From 5a9b8d69af87efa2d2cc72c4259032a3bfe657d4 Mon Sep 17 00:00:00 2001 From: "Alexis (Poliorcetics) Bourget" Date: Wed, 8 Mar 2023 17:57:08 +0100 Subject: [PATCH] deps: Move from `winapi` to `windows` `winapi` is in maintenance mode and the new blessed way to access Windows APIs are the `windows` and `windows-sys` crates. I was forced to use `windows` because `sysinfo` uses the COM APIs which are not present in `windows-sys`. --- Cargo.lock | 53 ++-- Cargo.toml | 71 +++--- src/common.rs | 2 +- src/lib.rs | 4 +- src/windows/component.rs | 331 +++++++++---------------- src/windows/cpu.rs | 190 ++++++++------- src/windows/disk.rs | 154 +++++------- src/windows/network.rs | 37 ++- src/windows/network_helper.rs | 41 ++-- src/windows/process.rs | 445 ++++++++++++++++------------------ src/windows/sid.rs | 85 ++++--- src/windows/system.rs | 75 +++--- src/windows/tools.rs | 6 +- src/windows/users.rs | 132 +++++----- src/windows/utils.rs | 76 +++--- 15 files changed, 770 insertions(+), 932 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 11518b786..4f39b4b77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -258,7 +258,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "winapi", + "windows", ] [[package]] @@ -296,6 +296,25 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -307,9 +326,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -322,42 +341,42 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index 02e39cab1..2dece03fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,43 +41,42 @@ serde = { version = "^1.0.152", optional = true } once_cell = "1.0" [target.'cfg(windows)'.dependencies] -# FIXME: remove std feature once https://github.com/retep998/winapi-rs/pull/1003 has been merged. -winapi = { version = "0.3.9", features = [ - "errhandlingapi", - "fileapi", - "handleapi", - "heapapi", - "ifdef", - "ioapiset", - "minwindef", - "pdh", - "psapi", - "synchapi", - "sysinfoapi", - "winbase", - "winerror", - "winioctl", - "winnt", - "oleauto", - "wbemcli", - "rpcdce", - "combaseapi", - "objidl", - "powerbase", - "netioapi", - "lmcons", - "lmaccess", - "lmapibuf", - "memoryapi", - "ntlsa", - "securitybaseapi", - "shellapi", - "std", - "iphlpapi", - "winsock2", - "sddl", -]} ntapi = "0.4" +windows = { version = "0.51", features = [ + "Wdk_System_SystemInformation", + "Wdk_System_SystemServices", + "Wdk_System_Threading", + "Win32_Foundation", + "Win32_NetworkManagement_IpHelper", + "Win32_NetworkManagement_NetManagement", + "Win32_NetworkManagement_Ndis", + "Win32_Networking_WinSock", + "Win32_Security", + "Win32_Security_Authentication_Identity", + "Win32_Security_Authorization", + "Win32_Storage_FileSystem", + "Win32_System_Com", + "Win32_System_Diagnostics_Debug", + "Win32_System_IO", + "Win32_System_Ioctl", + "Win32_System_LibraryLoader", + "Win32_System_Kernel", + "Win32_System_Memory", + "Win32_System_Ole", + "Win32_System_Performance", + "Win32_System_Power", + "Win32_System_ProcessStatus", + "Win32_System_Registry", + "Win32_System_RemoteDesktop", + "Win32_System_Rpc", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_Variant", + "Win32_System_WindowsProgramming", + "Win32_System_Wmi", + "Win32_UI_Shell", +]} [target.'cfg(not(any(target_os = "unknown", target_arch = "wasm32")))'.dependencies] libc = "^0.2.144" diff --git a/src/common.rs b/src/common.rs index fa19d5209..e55a0393e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1020,7 +1020,7 @@ pub fn get_current_pid() -> Result { } } else if #[cfg(windows)] { fn inner() -> Result { - use winapi::um::processthreadsapi::GetCurrentProcessId; + use windows::Win32::System::Threading::GetCurrentProcessId; unsafe { Ok(Pid(GetCurrentProcessId() as _)) } } diff --git a/src/lib.rs b/src/lib.rs index d30ecc72d..034a38601 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,8 +36,8 @@ cfg_if::cfg_if! { pub(crate) const MIN_USERS: usize = 1; } else if #[cfg(windows)] { mod windows; - use windows as sys; - use windows::network_helper; + use crate::windows as sys; + use crate::windows::network_helper; mod network; #[cfg(test)] diff --git a/src/windows/component.rs b/src/windows/component.rs index 2cd43b0f9..296d6266f 100644 --- a/src/windows/component.rs +++ b/src/windows/component.rs @@ -2,23 +2,19 @@ use crate::{ComponentExt, ComponentsExt}; -use std::ptr::null_mut; - -use winapi::shared::rpcdce::{ - RPC_C_AUTHN_LEVEL_CALL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, - RPC_C_IMP_LEVEL_IMPERSONATE, -}; -use winapi::shared::winerror::{FAILED, SUCCEEDED, S_FALSE, S_OK}; -use winapi::shared::wtypesbase::CLSCTX_INPROC_SERVER; -use winapi::um::combaseapi::{ +use windows::core::w; +use windows::Win32::Foundation::{SysAllocString, SysFreeString}; +use windows::Win32::Security::PSECURITY_DESCRIPTOR; +use windows::Win32::System::Com::{ CoCreateInstance, CoInitializeEx, CoInitializeSecurity, CoSetProxyBlanket, CoUninitialize, + CLSCTX_INPROC_SERVER, EOAC_NONE, RPC_C_AUTHN_LEVEL_CALL, RPC_C_AUTHN_LEVEL_DEFAULT, + RPC_C_IMP_LEVEL_IMPERSONATE, }; -use winapi::um::oaidl::VARIANT; -use winapi::um::objidl::EOAC_NONE; -use winapi::um::oleauto::{SysAllocString, SysFreeString, VariantClear}; -use winapi::um::wbemcli::{ - CLSID_WbemLocator, IEnumWbemClassObject, IID_IWbemLocator, IWbemClassObject, IWbemLocator, - IWbemServices, WBEM_FLAG_FORWARD_ONLY, WBEM_FLAG_NONSYSTEM_ONLY, WBEM_FLAG_RETURN_IMMEDIATELY, +use windows::Win32::System::Rpc::{RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE}; +use windows::Win32::System::Variant::{VariantClear, VARIANT}; +use windows::Win32::System::Wmi::{ + IEnumWbemClassObject, IWbemLocator, IWbemServices, WbemLocator, WBEM_FLAG_FORWARD_ONLY, + WBEM_FLAG_NONSYSTEM_ONLY, WBEM_FLAG_RETURN_IMMEDIATELY, WBEM_INFINITE, }; #[doc = include_str!("../../md_doc/component.md")] @@ -120,53 +116,16 @@ impl ComponentsExt for Components { } } -struct Instance(*mut IWbemLocator); - -impl Drop for Instance { - fn drop(&mut self) { - if !self.0.is_null() { - unsafe { - (*self.0).Release(); - } - } - } -} - -struct ServerConnection(*mut IWbemServices); - -impl Drop for ServerConnection { - fn drop(&mut self) { - if !self.0.is_null() { - unsafe { - (*self.0).Release(); - } - } - } -} - -struct Enumerator(*mut IEnumWbemClassObject); - -impl Drop for Enumerator { - fn drop(&mut self) { - if !self.0.is_null() { - unsafe { - (*self.0).Release(); - } - } - } -} - macro_rules! bstr { - ($($x:expr),*) => {{ - let x: &[u16] = &[$($x as u16),*, 0]; - SysAllocString(x.as_ptr()) - }} + ($x:literal) => {{ + SysAllocString(w!($x)) + }}; } struct Connection { - instance: Option, - server_connection: Option, - enumerator: Option, + instance: Option, + server_connection: Option, + enumerator: Option, initialized: bool, } @@ -177,157 +136,111 @@ unsafe impl Sync for Connection {} impl Connection { #[allow(clippy::unnecessary_wraps)] fn new() -> Option { - unsafe { - let val = CoInitializeEx(null_mut(), 0); - Some(Connection { - instance: None, - server_connection: None, - enumerator: None, - initialized: val == S_OK || val == S_FALSE, - }) - } + let val = unsafe { CoInitializeEx(None, Default::default()) }; + Some(Connection { + instance: None, + server_connection: None, + enumerator: None, + initialized: val.is_ok(), + }) } fn initialize_security(self) -> Option { unsafe { - if FAILED(CoInitializeSecurity( - null_mut(), + CoInitializeSecurity( + PSECURITY_DESCRIPTOR::default(), -1, - null_mut(), - null_mut(), + None, + None, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, - null_mut(), + None, EOAC_NONE, - null_mut(), - )) { - None - } else { - Some(self) - } + None, + ) } + .map_or(None, |_| Some(self)) } fn create_instance(mut self) -> Option { - let mut p_loc = null_mut(); - - unsafe { - if FAILED(CoCreateInstance( - &CLSID_WbemLocator as *const _, - null_mut(), - CLSCTX_INPROC_SERVER, - &IID_IWbemLocator as *const _, - &mut p_loc as *mut _ as *mut _, - )) { - None - } else { - self.instance = Some(Instance(p_loc)); - Some(self) - } - } + let instance = + unsafe { CoCreateInstance(&WbemLocator, None, CLSCTX_INPROC_SERVER) }.ok()?; + self.instance = Some(instance); + Some(self) } fn connect_server(mut self) -> Option { - let mut p_svc = null_mut(); - - if let Some(ref instance) = self.instance { - unsafe { - // "root\WMI" - let s = bstr!('r', 'o', 'o', 't', '\\', 'W', 'M', 'I'); - let res = (*instance.0).ConnectServer( - s, - null_mut(), - null_mut(), - null_mut(), - 0, - null_mut(), - null_mut(), - &mut p_svc as *mut _, - ); - SysFreeString(s); - if FAILED(res) { - return None; - } - } - } else { - return None; + let instance = self.instance.as_ref()?; + let svc = unsafe { + let s = bstr!("root\\WMI"); + let res = instance.ConnectServer( + &s, + &Default::default(), + &Default::default(), + &Default::default(), + 0, + &Default::default(), + None, + ); + SysFreeString(&s); + res } - self.server_connection = Some(ServerConnection(p_svc)); + .ok()?; + + self.server_connection = Some(svc); Some(self) } fn set_proxy_blanket(self) -> Option { - if let Some(ref server_connection) = self.server_connection { - unsafe { - if FAILED(CoSetProxyBlanket( - server_connection.0 as *mut _, - RPC_C_AUTHN_WINNT, - RPC_C_AUTHZ_NONE, - null_mut(), - RPC_C_AUTHN_LEVEL_CALL, - RPC_C_IMP_LEVEL_IMPERSONATE, - null_mut(), - EOAC_NONE, - )) { - return None; - } - } - } else { - return None; + unsafe { + CoSetProxyBlanket( + self.server_connection.as_ref()?, + RPC_C_AUTHN_WINNT, + RPC_C_AUTHZ_NONE, + None, + RPC_C_AUTHN_LEVEL_CALL, + RPC_C_IMP_LEVEL_IMPERSONATE, + None, + EOAC_NONE, + ) } + .ok()?; + Some(self) } fn exec_query(mut self) -> Option { - let mut p_enumerator = null_mut(); - - if let Some(ref server_connection) = self.server_connection { - unsafe { - // "WQL" - let s = bstr!('W', 'Q', 'L'); // query kind - // "SELECT * FROM MSAcpi_ThermalZoneTemperature" - let query = bstr!( - 'S', 'E', 'L', 'E', 'C', 'T', ' ', '*', ' ', 'F', 'R', 'O', 'M', ' ', 'M', 'S', - 'A', 'c', 'p', 'i', '_', 'T', 'h', 'e', 'r', 'm', 'a', 'l', 'Z', 'o', 'n', 'e', - 'T', 'e', 'm', 'p', 'e', 'r', 'a', 't', 'u', 'r', 'e' - ); - let hres = (*server_connection.0).ExecQuery( - s, - query, - (WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY) as _, - null_mut(), - &mut p_enumerator as *mut _, - ); - SysFreeString(s); - SysFreeString(query); - if FAILED(hres) { - return None; - } - } - } else { - return None; + let server_connection = self.server_connection.as_ref()?; + + let enumerator = unsafe { + let s = bstr!("WQL"); // query kind + let query = bstr!("SELECT * FROM MSAcpi_ThermalZoneTemperature"); + let hres = server_connection.ExecQuery( + &s, + &query, + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, + None, + ); + SysFreeString(&s); + SysFreeString(&query); + hres } - self.enumerator = Some(Enumerator(p_enumerator)); + .ok()?; + + self.enumerator = Some(enumerator); Some(self) } fn temperature(&mut self, get_critical: bool) -> Option<(f32, Option)> { - use winapi::um::wbemcli::WBEM_INFINITE; + let enumerator = self.enumerator.take()?; - let p_enum = match self.enumerator.take() { - Some(x) => x, - None => { - return None; - } - }; - let mut p_obj: *mut IWbemClassObject = null_mut(); let mut nb_returned = 0; + let mut obj = [None; 1]; unsafe { - (*p_enum.0).Next( - WBEM_INFINITE as _, // Time out - 1, // One object - &mut p_obj as *mut _, + let _r = enumerator.Next( + WBEM_INFINITE, // Time out + obj.as_mut_slice(), &mut nb_returned, ); @@ -335,46 +248,44 @@ impl Connection { return None; // not enough rights I suppose... } - (*p_obj).BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY as _); + let class_obj = match &mut obj { + [Some(co)] => co, + _ => return None, + }; + + let _r = class_obj.BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY.0); - let mut p_val = std::mem::MaybeUninit::::uninit(); - // "CurrentTemperature" - let temp = bstr!( - 'C', 'u', 'r', 'r', 'e', 'n', 't', 'T', 'e', 'm', 'p', 'e', 'r', 'a', 't', 'u', - 'r', 'e' - ); - let res = (*p_obj).Get(temp, 0, p_val.as_mut_ptr(), null_mut(), null_mut()); - let mut p_val = p_val.assume_init(); + let mut variant = std::mem::MaybeUninit::::uninit(); + // `Get` only initializes the variant if it succeeds, early returning is not a problem + // + // + class_obj + .Get( + w!("CurrentTemperature"), + 0, + variant.as_mut_ptr(), + None, + None, + ) + .ok()?; - SysFreeString(temp); - VariantClear(&mut p_val as *mut _ as *mut _); + let mut variant = variant.assume_init(); - let temp = if SUCCEEDED(res) { - // temperature is given in tenth of degrees Kelvin - (p_val.n1.decVal().Lo64 / 10) as f32 - 273.15 - } else { - (*p_obj).Release(); - return None; - }; + // temperature is given in tenth of degrees Kelvin + let temp = (variant.Anonymous.decVal.Anonymous2.Lo64 / 10) as f32 - 273.15; + let _r = VariantClear(&mut variant); let mut critical = None; if get_critical { - // "CriticalPoint" - let crit = bstr!( - 'C', 'r', 'i', 't', 'i', 'c', 'a', 'l', 'T', 'r', 'i', 'p', 'P', 'o', 'i', 'n', - 't' - ); - let res = (*p_obj).Get(crit, 0, &mut p_val, null_mut(), null_mut()); - - SysFreeString(crit); - VariantClear(&mut p_val as *mut _ as *mut _); - - if SUCCEEDED(res) { - // temperature is given in tenth of degrees Kelvin - critical = Some((p_val.n1.decVal().Lo64 / 10) as f32 - 273.15); - } + class_obj + .Get(w!("CriticalTripPoint"), 0, &mut variant, None, None) + .ok()?; + + // temperature is given in tenth of degrees Kelvin + critical = Some((variant.Anonymous.decVal.Anonymous2.Lo64 / 10) as f32 - 273.15); + let _r = VariantClear(&mut variant); } - (*p_obj).Release(); + Some((temp, critical)) } } @@ -387,9 +298,7 @@ impl Drop for Connection { self.server_connection.take(); self.instance.take(); if self.initialized { - unsafe { - CoUninitialize(); - } + unsafe { CoUninitialize() }; } } } diff --git a/src/windows/cpu.rs b/src/windows/cpu.rs index 3a998868e..48841759f 100644 --- a/src/windows/cpu.rs +++ b/src/windows/cpu.rs @@ -4,30 +4,31 @@ use crate::sys::tools::KeyHandler; use crate::{CpuExt, CpuRefreshKind, LoadAvg}; use std::collections::HashMap; +use std::ffi::c_void; use std::io::Error; use std::mem; use std::ops::DerefMut; -use std::ptr::null_mut; use std::sync::Mutex; -use ntapi::ntpoapi::PROCESSOR_POWER_INFORMATION; - -use winapi::shared::minwindef::FALSE; -use winapi::shared::winerror::{ERROR_INSUFFICIENT_BUFFER, ERROR_SUCCESS}; -use winapi::um::handleapi::CloseHandle; -use winapi::um::pdh::{ +use windows::core::{s, PCSTR, PCWSTR}; +use windows::Win32::Foundation::{ + CloseHandle, BOOLEAN, ERROR_INSUFFICIENT_BUFFER, ERROR_SUCCESS, FALSE, HANDLE, +}; +use windows::Win32::System::Performance::{ PdhAddEnglishCounterA, PdhAddEnglishCounterW, PdhCloseQuery, PdhCollectQueryData, PdhCollectQueryDataEx, PdhGetFormattedCounterValue, PdhOpenQueryA, PdhRemoveCounter, - PDH_FMT_COUNTERVALUE, PDH_FMT_DOUBLE, PDH_HCOUNTER, PDH_HQUERY, + PDH_FMT_COUNTERVALUE, PDH_FMT_DOUBLE, +}; +use windows::Win32::System::Power::{ + CallNtPowerInformation, ProcessorInformation, PROCESSOR_POWER_INFORMATION, }; -use winapi::um::powerbase::CallNtPowerInformation; -use winapi::um::synchapi::CreateEventA; -use winapi::um::sysinfoapi::GetLogicalProcessorInformationEx; -use winapi::um::sysinfoapi::SYSTEM_INFO; -use winapi::um::winbase::{RegisterWaitForSingleObject, INFINITE}; -use winapi::um::winnt::{ - ProcessorInformation, RelationAll, RelationProcessorCore, BOOLEAN, HANDLE, - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PVOID, WT_EXECUTEDEFAULT, +use windows::Win32::System::SystemInformation; +use windows::Win32::System::SystemInformation::{ + GetLogicalProcessorInformationEx, RelationAll, RelationProcessorCore, SYSTEM_INFO, + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, +}; +use windows::Win32::System::Threading::{ + CreateEventA, RegisterWaitForSingleObject, INFINITE, WT_EXECUTEDEFAULT, }; // This formula comes from Linux's include/linux/sched/loadavg.h @@ -54,22 +55,22 @@ pub(crate) fn get_load_average() -> LoadAvg { LoadAvg::default() } -unsafe extern "system" fn load_avg_callback(counter: PVOID, _: BOOLEAN) { +unsafe extern "system" fn load_avg_callback(counter: *mut c_void, _: BOOLEAN) { let mut display_value = mem::MaybeUninit::::uninit(); if PdhGetFormattedCounterValue( counter as _, PDH_FMT_DOUBLE, - null_mut(), + None, display_value.as_mut_ptr(), - ) != ERROR_SUCCESS as _ + ) != ERROR_SUCCESS.0 { return; } let display_value = display_value.assume_init(); if let Ok(mut avg) = LOAD_AVG.lock() { if let Some(avg) = avg.deref_mut() { - let current_load = display_value.u.doubleValue(); + let current_load = display_value.Anonymous.doubleValue; avg.one = avg.one * LOADAVG_FACTOR_1F + current_load * (1.0 - LOADAVG_FACTOR_1F); avg.five = avg.five * LOADAVG_FACTOR_5F + current_load * (1.0 - LOADAVG_FACTOR_5F); @@ -81,62 +82,61 @@ unsafe extern "system" fn load_avg_callback(counter: PVOID, _: BOOLEAN) { unsafe fn init_load_avg() -> Mutex> { // You can see the original implementation here: https://github.com/giampaolo/psutil - let mut query = null_mut(); + let mut query = 0; - if PdhOpenQueryA(null_mut(), 0, &mut query) != ERROR_SUCCESS as _ { + if PdhOpenQueryA(PCSTR::null(), 0, &mut query) != ERROR_SUCCESS.0 { sysinfo_debug!("init_load_avg: PdhOpenQueryA failed"); return Mutex::new(None); } - let mut counter: PDH_HCOUNTER = mem::zeroed(); - if PdhAddEnglishCounterA( - query, - b"\\System\\Cpu Queue Length\0".as_ptr() as _, - 0, - &mut counter, - ) != ERROR_SUCCESS as _ + let mut counter = 0; + if PdhAddEnglishCounterA(query, s!("\\System\\Cpu Queue Length"), 0, &mut counter) + != ERROR_SUCCESS.0 { PdhCloseQuery(query); sysinfo_debug!("init_load_avg: failed to get CPU queue length"); return Mutex::new(None); } - let event = CreateEventA(null_mut(), FALSE, FALSE, b"LoadUpdateEvent\0".as_ptr() as _); - if event.is_null() { - PdhCloseQuery(query); - sysinfo_debug!("init_load_avg: failed to create event `LoadUpdateEvent`"); - return Mutex::new(None); - } + let event = match CreateEventA(None, FALSE, FALSE, s!("LoadUpdateEvent")) { + Ok(ev) => ev, + Err(_) => { + PdhCloseQuery(query); + sysinfo_debug!("init_load_avg: failed to create event `LoadUpdateEvent`"); + return Mutex::new(None); + } + }; - if PdhCollectQueryDataEx(query, SAMPLING_INTERVAL as _, event) != ERROR_SUCCESS as _ { + if PdhCollectQueryDataEx(query, SAMPLING_INTERVAL as _, event) != ERROR_SUCCESS.0 { PdhCloseQuery(query); sysinfo_debug!("init_load_avg: PdhCollectQueryDataEx failed"); return Mutex::new(None); } - let mut wait_handle = null_mut(); + let mut wait_handle = HANDLE::default(); if RegisterWaitForSingleObject( &mut wait_handle, event, Some(load_avg_callback), - counter as _, + Some(counter as *const c_void), INFINITE, WT_EXECUTEDEFAULT, - ) == 0 + ) + .is_ok() { + Mutex::new(Some(LoadAvg::default())) + } else { PdhRemoveCounter(counter); PdhCloseQuery(query); sysinfo_debug!("init_load_avg: RegisterWaitForSingleObject failed"); Mutex::new(None) - } else { - Mutex::new(Some(LoadAvg::default())) } } struct InternalQuery { - query: PDH_HQUERY, + query: HANDLE, event: HANDLE, - data: HashMap, + data: HashMap, } unsafe impl Send for InternalQuery {} @@ -146,15 +146,15 @@ impl Drop for InternalQuery { fn drop(&mut self) { unsafe { for (_, counter) in self.data.iter() { - PdhRemoveCounter(*counter); + PdhRemoveCounter(counter.0); } - if !self.event.is_null() { - CloseHandle(self.event); + if !self.event.is_invalid() { + let _err = CloseHandle(self.event); } - if !self.query.is_null() { - PdhCloseQuery(self.query); + if !self.query.is_invalid() { + PdhCloseQuery(self.query.0); } } } @@ -166,12 +166,12 @@ pub(crate) struct Query { impl Query { pub fn new() -> Option { - let mut query = null_mut(); + let mut query = 0; unsafe { - if PdhOpenQueryA(null_mut(), 0, &mut query) == ERROR_SUCCESS as i32 { + if PdhOpenQueryA(PCSTR::null(), 0, &mut query) == ERROR_SUCCESS.0 { let q = InternalQuery { - query, - event: null_mut(), + query: HANDLE(query), + event: HANDLE::default(), data: HashMap::new(), }; Some(Query { internal: q }) @@ -187,18 +187,16 @@ impl Query { if let Some(counter) = self.internal.data.get(name) { unsafe { let mut display_value = mem::MaybeUninit::::uninit(); - let counter: PDH_HCOUNTER = *counter; - let ret = PdhGetFormattedCounterValue( - counter, + return if PdhGetFormattedCounterValue( + counter.0, PDH_FMT_DOUBLE, - null_mut(), + None, display_value.as_mut_ptr(), - ) as u32; - let display_value = display_value.assume_init(); - return if ret == ERROR_SUCCESS as _ { - let data = *display_value.u.doubleValue(); - Some(data as f32) + ) == ERROR_SUCCESS.0 + { + let display_value = display_value.assume_init(); + Some(display_value.Anonymous.doubleValue as f32) } else { sysinfo_debug!("Query::get: PdhGetFormattedCounterValue failed"); Some(0.) @@ -215,10 +213,15 @@ impl Query { return false; } unsafe { - let mut counter: PDH_HCOUNTER = std::mem::zeroed(); - let ret = PdhAddEnglishCounterW(self.internal.query, getter.as_ptr(), 0, &mut counter); - if ret == ERROR_SUCCESS as _ { - self.internal.data.insert(name.clone(), counter); + let mut counter = 0; + let ret = PdhAddEnglishCounterW( + self.internal.query.0, + PCWSTR::from_raw(getter.as_ptr()), + 0, + &mut counter, + ); + if ret == ERROR_SUCCESS.0 { + self.internal.data.insert(name.clone(), HANDLE(counter)); } else { sysinfo_debug!( "Query::add_english_counter: failed to add counter '{}': {:x}...", @@ -233,7 +236,7 @@ impl Query { pub fn refresh(&self) { unsafe { - if PdhCollectQueryData(self.internal.query) != ERROR_SUCCESS as _ { + if PdhCollectQueryData(self.internal.query.0) != ERROR_SUCCESS.0 { sysinfo_debug!("failed to refresh CPU data"); } } @@ -361,25 +364,24 @@ impl Cpu { } fn get_vendor_id_not_great(info: &SYSTEM_INFO) -> String { - use winapi::um::winnt; // https://docs.microsoft.com/fr-fr/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info unsafe { - match info.u.s().wProcessorArchitecture { - winnt::PROCESSOR_ARCHITECTURE_INTEL => "Intel x86", - winnt::PROCESSOR_ARCHITECTURE_MIPS => "MIPS", - winnt::PROCESSOR_ARCHITECTURE_ALPHA => "RISC Alpha", - winnt::PROCESSOR_ARCHITECTURE_PPC => "PPC", - winnt::PROCESSOR_ARCHITECTURE_SHX => "SHX", - winnt::PROCESSOR_ARCHITECTURE_ARM => "ARM", - winnt::PROCESSOR_ARCHITECTURE_IA64 => "Intel Itanium-based x64", - winnt::PROCESSOR_ARCHITECTURE_ALPHA64 => "RISC Alpha x64", - winnt::PROCESSOR_ARCHITECTURE_MSIL => "MSIL", - winnt::PROCESSOR_ARCHITECTURE_AMD64 => "(Intel or AMD) x64", - winnt::PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 => "Intel Itanium-based x86", - winnt::PROCESSOR_ARCHITECTURE_NEUTRAL => "unknown", - winnt::PROCESSOR_ARCHITECTURE_ARM64 => "ARM x64", - winnt::PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 => "ARM", - winnt::PROCESSOR_ARCHITECTURE_IA32_ON_ARM64 => "Intel Itanium-based x86", + match info.Anonymous.Anonymous.wProcessorArchitecture { + SystemInformation::PROCESSOR_ARCHITECTURE_INTEL => "Intel x86", + SystemInformation::PROCESSOR_ARCHITECTURE_MIPS => "MIPS", + SystemInformation::PROCESSOR_ARCHITECTURE_ALPHA => "RISC Alpha", + SystemInformation::PROCESSOR_ARCHITECTURE_PPC => "PPC", + SystemInformation::PROCESSOR_ARCHITECTURE_SHX => "SHX", + SystemInformation::PROCESSOR_ARCHITECTURE_ARM => "ARM", + SystemInformation::PROCESSOR_ARCHITECTURE_IA64 => "Intel Itanium-based x64", + SystemInformation::PROCESSOR_ARCHITECTURE_ALPHA64 => "RISC Alpha x64", + SystemInformation::PROCESSOR_ARCHITECTURE_MSIL => "MSIL", + SystemInformation::PROCESSOR_ARCHITECTURE_AMD64 => "(Intel or AMD) x64", + SystemInformation::PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 => "Intel Itanium-based x86", + SystemInformation::PROCESSOR_ARCHITECTURE_NEUTRAL => "unknown", + SystemInformation::PROCESSOR_ARCHITECTURE_ARM64 => "ARM x64", + SystemInformation::PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 => "ARM", + SystemInformation::PROCESSOR_ARCHITECTURE_IA32_ON_ARM64 => "Intel Itanium-based x86", _ => "unknown", } .to_owned() @@ -477,11 +479,12 @@ pub(crate) fn get_frequencies(nb_cpus: usize) -> Vec { unsafe { if CallNtPowerInformation( ProcessorInformation, - null_mut(), + None, 0, - infos.as_mut_ptr() as _, + Some(infos.as_mut_ptr() as _), size as _, - ) == 0 + ) + .is_ok() { infos.set_len(nb_cpus); // infos.Number @@ -504,21 +507,24 @@ pub(crate) fn get_physical_core_count() -> Option { let mut needed_size = 0; unsafe { - GetLogicalProcessorInformationEx(RelationAll, null_mut(), &mut needed_size); + let _err = GetLogicalProcessorInformationEx(RelationAll, None, &mut needed_size); let mut buf: Vec = Vec::with_capacity(needed_size as _); loop { if GetLogicalProcessorInformationEx( RelationAll, - buf.as_mut_ptr() as *mut _, + Some(buf.as_mut_ptr().cast()), &mut needed_size, - ) == FALSE + ) + .is_ok() { + break; + } else { let e = Error::last_os_error(); // For some reasons, the function might return a size not big enough... match e.raw_os_error() { - Some(value) if value == ERROR_INSUFFICIENT_BUFFER as _ => {} + Some(value) if value == ERROR_INSUFFICIENT_BUFFER.0 as i32 => {} _ => { sysinfo_debug!( "get_physical_core_count: GetLogicalCpuInformationEx failed" @@ -526,8 +532,6 @@ pub(crate) fn get_physical_core_count() -> Option { return None; } } - } else { - break; } let reserve = if needed_size as usize > buf.capacity() { needed_size as usize - buf.capacity() @@ -543,7 +547,7 @@ pub(crate) fn get_physical_core_count() -> Option { let raw_buf = buf.as_ptr(); let mut count = 0; while i < buf.len() { - let p = &*(raw_buf.add(i) as PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX); + let p = &*(raw_buf.add(i) as *const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX); i += p.Size as usize; if p.Relationship == RelationProcessorCore { // Only count the physical cores. diff --git a/src/windows/disk.rs b/src/windows/disk.rs index 65ae361b8..2213d095c 100644 --- a/src/windows/disk.rs +++ b/src/windows/disk.rs @@ -2,24 +2,22 @@ use crate::{DiskExt, DiskKind, Disks, DisksExt}; -use std::ffi::{OsStr, OsString}; +use std::ffi::{c_void, OsStr, OsString}; use std::mem::size_of; use std::path::Path; -use winapi::ctypes::c_void; -use winapi::shared::minwindef::{DWORD, MAX_PATH}; -use winapi::um::fileapi::{ +use windows::core::PCWSTR; +use windows::Win32::Foundation::{CloseHandle, HANDLE, MAX_PATH}; +use windows::Win32::Storage::FileSystem::{ CreateFileW, GetDiskFreeSpaceExW, GetDriveTypeW, GetLogicalDrives, GetVolumeInformationW, - OPEN_EXISTING, + FILE_ACCESS_RIGHTS, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING, }; -use winapi::um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE}; -use winapi::um::ioapiset::DeviceIoControl; -use winapi::um::winbase::{DRIVE_FIXED, DRIVE_REMOVABLE}; -use winapi::um::winioctl::{ - PropertyStandardQuery, StorageDeviceSeekPenaltyProperty, IOCTL_STORAGE_QUERY_PROPERTY, - STORAGE_PROPERTY_QUERY, +use windows::Win32::System::Ioctl::{ + PropertyStandardQuery, StorageDeviceSeekPenaltyProperty, DEVICE_SEEK_PENALTY_DESCRIPTOR, + IOCTL_STORAGE_QUERY_PROPERTY, STORAGE_PROPERTY_QUERY, }; -use winapi::um::winnt::{BOOLEAN, FILE_SHARE_READ, FILE_SHARE_WRITE, HANDLE, ULARGE_INTEGER}; +use windows::Win32::System::WindowsProgramming::{DRIVE_FIXED, DRIVE_REMOVABLE}; +use windows::Win32::System::IO::DeviceIoControl; #[doc = include_str!("../../md_doc/disk.md")] pub struct Disk { @@ -65,15 +63,10 @@ impl DiskExt for Disk { fn refresh(&mut self) -> bool { if self.total_space != 0 { unsafe { - let mut tmp: ULARGE_INTEGER = std::mem::zeroed(); - if GetDiskFreeSpaceExW( - self.mount_point.as_ptr(), - std::ptr::null_mut(), - std::ptr::null_mut(), - &mut tmp, - ) != 0 - { - self.available_space = *tmp.QuadPart(); + let mut tmp = 0; + let lpdirectoryname = PCWSTR::from_raw(self.mount_point.as_ptr()); + if GetDiskFreeSpaceExW(lpdirectoryname, None, None, Some(&mut tmp)).is_ok() { + self.available_space = tmp; return true; } } @@ -107,62 +100,47 @@ impl DisksExt for Disks { struct HandleWrapper(HANDLE); impl HandleWrapper { - unsafe fn new(drive_name: &[u16], open_rights: DWORD) -> Option { + unsafe fn new(drive_name: &[u16], open_rights: FILE_ACCESS_RIGHTS) -> Option { + let lpfilename = PCWSTR::from_raw(drive_name.as_ptr()); let handle = CreateFileW( - drive_name.as_ptr(), - open_rights, + lpfilename, + open_rights.0, FILE_SHARE_READ | FILE_SHARE_WRITE, - std::ptr::null_mut(), + None, OPEN_EXISTING, - 0, - std::ptr::null_mut(), - ); - if handle == INVALID_HANDLE_VALUE { - CloseHandle(handle); - None - } else { - Some(Self(handle)) - } + Default::default(), + HANDLE::default(), + ) + .ok()?; + Some(Self(handle)) } } impl Drop for HandleWrapper { fn drop(&mut self) { - unsafe { - CloseHandle(self.0); - } + let _err = unsafe { CloseHandle(self.0) }; } } unsafe fn get_drive_size(mount_point: &[u16]) -> Option<(u64, u64)> { - let mut total_size: ULARGE_INTEGER = std::mem::zeroed(); - let mut available_space: ULARGE_INTEGER = std::mem::zeroed(); + let mut total_size = 0; + let mut available_space = 0; + let lpdirectoryname = PCWSTR::from_raw(mount_point.as_ptr()); if GetDiskFreeSpaceExW( - mount_point.as_ptr(), - std::ptr::null_mut(), - &mut total_size, - &mut available_space, - ) != 0 + lpdirectoryname, + None, + Some(&mut total_size), + Some(&mut available_space), + ) + .is_ok() { - Some(( - *total_size.QuadPart() as _, - *available_space.QuadPart() as _, - )) + Some((total_size, available_space)) } else { None } } -// FIXME: To be removed once has been merged. -#[allow(non_snake_case)] -#[repr(C)] -struct DEVICE_SEEK_PENALTY_DESCRIPTOR { - Version: DWORD, - Size: DWORD, - IncursSeekPenalty: BOOLEAN, -} - -unsafe fn get_disks() -> Vec { +pub(crate) unsafe fn get_disks() -> Vec { let drives = GetLogicalDrives(); if drives == 0 { return Vec::new(); @@ -171,33 +149,33 @@ unsafe fn get_disks() -> Vec { #[cfg(feature = "multithread")] use rayon::iter::ParallelIterator; - crate::utils::into_iter(0..DWORD::BITS) + crate::utils::into_iter(0..u32::BITS) .filter_map(|x| { if (drives >> x) & 1 == 0 { return None; } let mount_point = [b'A' as u16 + x as u16, b':' as u16, b'\\' as u16, 0]; - let drive_type = GetDriveTypeW(mount_point.as_ptr()); + let raw_mount_point = PCWSTR::from_raw(mount_point.as_ptr()); + let drive_type = GetDriveTypeW(raw_mount_point); let is_removable = drive_type == DRIVE_REMOVABLE; if drive_type != DRIVE_FIXED && drive_type != DRIVE_REMOVABLE { return None; } - let mut name = [0u16; MAX_PATH + 1]; + let mut name = [0u16; MAX_PATH as usize + 1]; let mut file_system = [0u16; 32]; - if GetVolumeInformationW( - mount_point.as_ptr(), - name.as_mut_ptr(), - name.len() as DWORD, - std::ptr::null_mut(), - std::ptr::null_mut(), - std::ptr::null_mut(), - file_system.as_mut_ptr(), - file_system.len() as DWORD, - ) == 0 - { + let volume_info_res = GetVolumeInformationW( + raw_mount_point, + Some(&mut name), + None, + None, + None, + Some(&mut file_system), + ) + .is_ok(); + if !volume_info_res { return None; } let mut pos = 0; @@ -228,12 +206,12 @@ unsafe fn get_disks() -> Vec { b':' as u16, 0, ]; - let handle = HandleWrapper::new(&drive_name, 0)?; + let handle = HandleWrapper::new(&drive_name, Default::default())?; let (total_space, available_space) = get_drive_size(&mount_point)?; if total_space == 0 { return None; } - let mut spq_trim = STORAGE_PROPERTY_QUERY { + let spq_trim = STORAGE_PROPERTY_QUERY { PropertyId: StorageDeviceSeekPenaltyProperty, QueryType: PropertyStandardQuery, AdditionalParameters: [0], @@ -241,25 +219,27 @@ unsafe fn get_disks() -> Vec { let mut result: DEVICE_SEEK_PENALTY_DESCRIPTOR = std::mem::zeroed(); let mut dw_size = 0; - let type_ = if DeviceIoControl( + let device_io_control = DeviceIoControl( handle.0, IOCTL_STORAGE_QUERY_PROPERTY, - &mut spq_trim as *mut STORAGE_PROPERTY_QUERY as *mut c_void, - size_of::() as DWORD, - &mut result as *mut DEVICE_SEEK_PENALTY_DESCRIPTOR as *mut c_void, - size_of::() as DWORD, - &mut dw_size, - std::ptr::null_mut(), - ) == 0 - || dw_size != size_of::() as DWORD + Some(&spq_trim as *const STORAGE_PROPERTY_QUERY as *const c_void), + size_of::() as u32, + Some(&mut result as *mut DEVICE_SEEK_PENALTY_DESCRIPTOR as *mut c_void), + size_of::() as u32, + Some(&mut dw_size), + None, + ) + .is_ok(); + let type_ = if !device_io_control + || dw_size != size_of::() as u32 { DiskKind::Unknown(-1) } else { - let is_ssd = result.IncursSeekPenalty == 0; - if is_ssd { - DiskKind::SSD - } else { + let is_hdd = result.IncursSeekPenalty.as_bool(); + if is_hdd { DiskKind::HDD + } else { + DiskKind::SSD } }; Some(Disk { diff --git a/src/windows/network.rs b/src/windows/network.rs index 3998d7a80..aaed06546 100644 --- a/src/windows/network.rs +++ b/src/windows/network.rs @@ -6,11 +6,10 @@ use crate::{NetworkExt, Networks, NetworksExt, NetworksIter}; use std::collections::{hash_map, HashMap}; -use winapi::shared::ifdef::{MediaConnectStateDisconnected, NET_LUID}; -use winapi::shared::netioapi::{ - FreeMibTable, GetIfEntry2, GetIfTable2, MIB_IF_ROW2, PMIB_IF_TABLE2, +use windows::Win32::NetworkManagement::IpHelper::{ + FreeMibTable, GetIfEntry2, GetIfTable2, MIB_IF_ROW2, MIB_IF_TABLE2, }; -use winapi::shared::winerror::NO_ERROR; +use windows::Win32::NetworkManagement::Ndis::{MediaConnectStateDisconnected, NET_LUID_LH}; macro_rules! old_and_new { ($ty_:expr, $name:ident, $old:ident, $new_val:expr) => {{ @@ -32,10 +31,10 @@ impl NetworksExt for Networks { } fn refresh_list(&mut self) { - let mut table: PMIB_IF_TABLE2 = std::ptr::null_mut(); + let mut table: *mut MIB_IF_TABLE2 = std::ptr::null_mut(); unsafe { - if GetIfTable2(&mut table) != NO_ERROR { + if GetIfTable2(&mut table).is_err() { return; } @@ -59,16 +58,16 @@ impl NetworksExt for Networks { continue; } let id = vec![ - ptr.InterfaceGuid.Data2, - ptr.InterfaceGuid.Data3, - ptr.InterfaceGuid.Data4[0] as _, - ptr.InterfaceGuid.Data4[1] as _, - ptr.InterfaceGuid.Data4[2] as _, - ptr.InterfaceGuid.Data4[3] as _, - ptr.InterfaceGuid.Data4[4] as _, - ptr.InterfaceGuid.Data4[5] as _, - ptr.InterfaceGuid.Data4[6] as _, - ptr.InterfaceGuid.Data4[7] as _, + ptr.InterfaceGuid.data2, + ptr.InterfaceGuid.data3, + ptr.InterfaceGuid.data4[0] as _, + ptr.InterfaceGuid.data4[1] as _, + ptr.InterfaceGuid.data4[2] as _, + ptr.InterfaceGuid.data4[3] as _, + ptr.InterfaceGuid.data4[4] as _, + ptr.InterfaceGuid.data4[5] as _, + ptr.InterfaceGuid.data4[6] as _, + ptr.InterfaceGuid.data4[7] as _, ]; let entry = groups.entry(id.clone()).or_insert(0); *entry += 1; @@ -138,7 +137,7 @@ impl NetworksExt for Networks { } } } - FreeMibTable(table as _); + let _err = FreeMibTable(table as _); } // Remove interfaces which are gone. self.interfaces.retain(|_, d| d.updated); @@ -154,7 +153,7 @@ impl NetworksExt for Networks { for (_, interface) in self.interfaces.iter_mut() { entry.InterfaceLuid = interface.id; entry.InterfaceIndex = 0; // to prevent the function to pick this one as index - if GetIfEntry2(&mut entry) != NO_ERROR { + if GetIfEntry2(&mut entry).is_err() { continue; } old_and_new!(interface, current_out, old_out, entry.OutOctets); @@ -180,7 +179,7 @@ impl NetworksExt for Networks { #[doc = include_str!("../../md_doc/network_data.md")] pub struct NetworkData { - id: NET_LUID, + id: NET_LUID_LH, current_out: u64, old_out: u64, current_in: u64, diff --git a/src/windows/network_helper.rs b/src/windows/network_helper.rs index 4afe513ba..18752ecc3 100644 --- a/src/windows/network_helper.rs +++ b/src/windows/network_helper.rs @@ -1,33 +1,22 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::ffi::OsString; -use std::os::windows::prelude::OsStringExt; use std::ptr::null_mut; -use winapi::shared::winerror::{ERROR_BUFFER_OVERFLOW, ERROR_SUCCESS}; -use winapi::shared::ws2def::AF_UNSPEC; -use winapi::um::iphlpapi::GetAdaptersAddresses; -use winapi::um::iptypes::{ - GAA_FLAG_SKIP_ANYCAST, GAA_FLAG_SKIP_DNS_SERVER, GAA_FLAG_SKIP_MULTICAST, PIP_ADAPTER_ADDRESSES, +use windows::Win32::Foundation::{ERROR_BUFFER_OVERFLOW, ERROR_SUCCESS}; +use windows::Win32::NetworkManagement::IpHelper::{ + GetAdaptersAddresses, GAA_FLAG_SKIP_ANYCAST, GAA_FLAG_SKIP_DNS_SERVER, GAA_FLAG_SKIP_MULTICAST, + IP_ADAPTER_ADDRESSES_LH, }; +use windows::Win32::Networking::WinSock::AF_UNSPEC; use crate::common::MacAddr; -// Need a function to convert u16 pointer into String -// https://stackoverflow.com/a/48587463/8706476 -unsafe fn u16_ptr_to_string(ptr: *const u16) -> OsString { - let len = (0..).take_while(|&i| *ptr.offset(i) != 0).count(); - let slice = std::slice::from_raw_parts(ptr, len); - - OsString::from_wide(slice) -} - /// this iterator yields an interface name and address pub(crate) struct InterfaceAddressIterator { /// The first item in the linked list - buf: PIP_ADAPTER_ADDRESSES, + buf: *mut IP_ADAPTER_ADDRESSES_LH, /// The current adapter - adapter: PIP_ADAPTER_ADDRESSES, + adapter: *mut IP_ADAPTER_ADDRESSES_LH, } impl InterfaceAddressIterator { @@ -38,7 +27,7 @@ impl InterfaceAddressIterator { } } unsafe fn realloc(mut self, size: libc::size_t) -> Result { - let new_buf = libc::realloc(self.buf as _, size) as PIP_ADAPTER_ADDRESSES; + let new_buf = libc::realloc(self.buf as _, size) as *mut IP_ADAPTER_ADDRESSES_LH; if new_buf.is_null() { // insufficient memory available // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/malloc?view=msvc-170#return-value @@ -63,7 +52,7 @@ impl Iterator for InterfaceAddressIterator { let adapter = self.adapter; // Move to the next adapter self.adapter = (*adapter).Next; - if let Ok(interface_name) = u16_ptr_to_string((*adapter).FriendlyName).into_string() { + if let Ok(interface_name) = (*adapter).FriendlyName.to_string() { // take the first 6 bytes and return the MAC address instead let [mac @ .., _, _] = (*adapter).PhysicalAddress; Some((interface_name, MacAddr(mac))) @@ -88,7 +77,7 @@ pub(crate) fn get_interface_address() -> Result Result fmt::Result { @@ -73,17 +70,22 @@ fn get_process_handler(pid: Pid) -> Option { } let options = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ; - HandleWrapper::new(unsafe { OpenProcess(options, FALSE, pid.0 as DWORD) }) + HandleWrapper::new(unsafe { OpenProcess(options, false, pid.0 as u32).unwrap_or_default() }) .or_else(|| { - sysinfo_debug!("OpenProcess failed, error: {:?}", unsafe { GetLastError() }); + sysinfo_debug!( + "OpenProcess failed, error: {:?}", + io::Error::last_os_error() + ); HandleWrapper::new(unsafe { - OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid.0 as DWORD) + OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid.0 as u32) + .unwrap_or_default() }) }) .or_else(|| { - sysinfo_debug!("OpenProcess limited failed, error: {:?}", unsafe { - GetLastError() - }); + sysinfo_debug!( + "OpenProcess limited failed, error: {:?}", + io::Error::last_os_error() + ); None }) } @@ -95,8 +97,8 @@ unsafe fn get_process_user_id( struct HeapWrap(*mut T); impl HeapWrap { - unsafe fn new(size: DWORD) -> Option { - let ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size as _) as *mut T; + unsafe fn new(size: u32) -> Option { + let ptr = HeapAlloc(GetProcessHeap().ok()?, HEAP_ZERO_MEMORY, size as _) as *mut T; if ptr.is_null() { sysinfo_debug!("HeapAlloc failed"); None @@ -110,7 +112,9 @@ unsafe fn get_process_user_id( fn drop(&mut self) { if !self.0.is_null() { unsafe { - HeapFree(GetProcessHeap(), 0, self.0 as *mut _); + if let Ok(heap) = GetProcessHeap() { + let _err = HeapFree(heap, Default::default(), Some(self.0.cast())); + } } } } @@ -120,9 +124,9 @@ unsafe fn get_process_user_id( return None; } - let mut token = null_mut(); + let mut token = Default::default(); - if OpenProcessToken(**handle, TOKEN_QUERY, &mut token) == 0 { + if OpenProcessToken(**handle, TOKEN_QUERY, &mut token).is_err() { sysinfo_debug!("OpenProcessToken failed"); return None; } @@ -131,9 +135,8 @@ unsafe fn get_process_user_id( let mut size = 0; - if GetTokenInformation(*token, TokenUser, null_mut(), 0, &mut size) == 0 { - let err = GetLastError(); - if err != ERROR_INSUFFICIENT_BUFFER { + if let Err(err) = GetTokenInformation(*token, TokenUser, None, 0, &mut size) { + if err.code() != ERROR_INSUFFICIENT_BUFFER.to_hresult() { sysinfo_debug!("GetTokenInformation failed, error: {:?}", err); return None; } @@ -141,8 +144,11 @@ unsafe fn get_process_user_id( let ptu: HeapWrap = HeapWrap::new(size)?; - if GetTokenInformation(*token, TokenUser, ptu.0 as *mut _, size, &mut size) == 0 { - sysinfo_debug!("GetTokenInformation failed, error: {:?}", GetLastError()); + if let Err(_err) = GetTokenInformation(*token, TokenUser, Some(ptu.0.cast()), size, &mut size) { + sysinfo_debug!( + "GetTokenInformation failed (returned {_err:?}), error: {:?}", + io::Error::last_os_error() + ); return None; } @@ -153,7 +159,7 @@ struct HandleWrapper(HANDLE); impl HandleWrapper { fn new(handle: HANDLE) -> Option { - if handle.is_null() { + if handle.is_invalid() { None } else { Some(Self(handle)) @@ -171,9 +177,7 @@ impl Deref for HandleWrapper { impl Drop for HandleWrapper { fn drop(&mut self) { - unsafe { - CloseHandle(self.0); - } + let _err = unsafe { CloseHandle(self.0) }; } } @@ -225,12 +229,10 @@ impl CPUsageCalculationValues { } } static WINDOWS_8_1_OR_NEWER: Lazy = Lazy::new(|| unsafe { - let mut version_info: RTL_OSVERSIONINFOEXW = MaybeUninit::zeroed().assume_init(); + let mut version_info: OSVERSIONINFOEXW = MaybeUninit::zeroed().assume_init(); - version_info.dwOSVersionInfoSize = std::mem::size_of::() as u32; - if !NT_SUCCESS(RtlGetVersion( - &mut version_info as *mut RTL_OSVERSIONINFOEXW as *mut _, - )) { + version_info.dwOSVersionInfoSize = std::mem::size_of::() as u32; + if RtlGetVersion((&mut version_info as *mut OSVERSIONINFOEXW).cast()).is_err() { return true; } @@ -240,43 +242,14 @@ static WINDOWS_8_1_OR_NEWER: Lazy = Lazy::new(|| unsafe { }); #[cfg(feature = "debug")] -unsafe fn display_ntstatus_error(ntstatus: winapi::shared::ntdef::NTSTATUS) { - let mut buffer: LPVOID = null_mut(); - let x = &[ - 'N' as u16, 'T' as u16, 'D' as u16, 'L' as u16, 'L' as u16, '.' as u16, 'D' as u16, - 'L' as u16, 'L' as u16, 0, - ]; - let handler = winapi::um::libloaderapi::LoadLibraryW(x.as_ptr()); - - winapi::um::winbase::FormatMessageW( - winapi::um::winbase::FORMAT_MESSAGE_ALLOCATE_BUFFER - | winapi::um::winbase::FORMAT_MESSAGE_FROM_SYSTEM - | winapi::um::winbase::FORMAT_MESSAGE_FROM_HMODULE, - handler as _, - ntstatus as _, - winapi::shared::ntdef::MAKELANGID( - winapi::shared::ntdef::LANG_NEUTRAL, - winapi::shared::ntdef::SUBLANG_DEFAULT, - ) as _, - &mut buffer as *mut _ as *mut _, - 0, - null_mut(), +unsafe fn display_ntstatus_error(ntstatus: windows::core::HRESULT) { + let code = ntstatus.0; + let message = ntstatus.message(); + sysinfo_debug!( + "Couldn't get process infos: NtQuerySystemInformation returned {}: {}", + code, + message ); - let msg = buffer as *const u16; - for x in 0.. { - if *msg.offset(x) == 0 { - let slice = std::slice::from_raw_parts(msg as *const u16, x as usize); - let s = null_terminated_wchar_to_string(slice); - sysinfo_debug!( - "Couldn't get process infos: NtQuerySystemInformation returned {}: {}", - ntstatus, - s, - ); - break; - } - } - LocalFree(buffer); - winapi::um::libloaderapi::FreeLibrary(handler); } // Take a look at https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/query.htm @@ -284,54 +257,55 @@ unsafe fn display_ntstatus_error(ntstatus: winapi::shared::ntdef::NTSTATUS) { unsafe fn get_process_name(pid: Pid) -> Option { let mut info = SYSTEM_PROCESS_ID_INFORMATION { ProcessId: pid.0 as _, - ImageName: UNICODE_STRING { - Length: 0, - // `MaximumLength` MUST BE a power of 2. - MaximumLength: 1 << 7, // 128 - Buffer: null_mut(), - }, + ImageName: MaybeUninit::zeroed().assume_init(), }; + // `MaximumLength` MUST BE a power of 2: here 128 + info.ImageName.MaximumLength = 1 << 7; for i in 0.. { - info.ImageName.Buffer = LocalAlloc( + let local_alloc = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, info.ImageName.MaximumLength as _, - ) as *mut _; - if info.ImageName.Buffer.is_null() { - sysinfo_debug!("Couldn't get process infos: LocalAlloc failed"); - return None; + ); + match local_alloc { + Ok(buf) if !buf.0.is_null() => info.ImageName.Buffer = buf.0.cast(), + _ => { + sysinfo_debug!("Couldn't get process infos: LocalAlloc failed"); + return None; + } } - let ntstatus = NtQuerySystemInformation( - SystemProcessIdInformation, + match NtQuerySystemInformation( + SYSTEM_INFORMATION_CLASS(SystemProcessIdInformation as _), &mut info as *mut _ as *mut _, size_of::() as _, null_mut(), - ); - if ntstatus == STATUS_SUCCESS { - break; - } else if ntstatus == STATUS_INFO_LENGTH_MISMATCH { - if !info.ImageName.Buffer.is_null() { - LocalFree(info.ImageName.Buffer as *mut _); - } - if i > 2 { - // Too many iterations, we should have the correct length at this point normally, - // aborting name retrieval. - sysinfo_debug!( + ) { + Ok(()) => break, + Err(err) if err.code() == STATUS_INFO_LENGTH_MISMATCH.to_hresult() => { + if !info.ImageName.Buffer.is_null() { + let _err = LocalFree(HLOCAL(info.ImageName.Buffer.cast())); + } + if i > 2 { + // Too many iterations, we should have the correct length at this point normally, + // aborting name retrieval. + sysinfo_debug!( "NtQuerySystemInformation returned `STATUS_INFO_LENGTH_MISMATCH` too many times" ); - return None; - } - // New length has been set into `MaximumLength` so we just continue the loop. - } else { - if !info.ImageName.Buffer.is_null() { - LocalFree(info.ImageName.Buffer as *mut _); + return None; + } + // New length has been set into `MaximumLength` so we just continue the loop. } + Err(_err) => { + if !info.ImageName.Buffer.is_null() { + let _err = LocalFree(HLOCAL(info.ImageName.Buffer.cast())); + } - #[cfg(feature = "debug")] - { - display_ntstatus_error(ntstatus); + #[cfg(feature = "debug")] + { + display_ntstatus_error(_err.code()); + } + return None; } - return None; } } @@ -348,17 +322,16 @@ unsafe fn get_process_name(pid: Pid) -> Option { let name = Path::new(&os_str) .file_name() .map(|s| s.to_string_lossy().to_string()); - LocalFree(info.ImageName.Buffer as _); + let _err = LocalFree(HLOCAL(info.ImageName.Buffer.cast())); name } unsafe fn get_exe(process_handler: &HandleWrapper) -> PathBuf { - let mut exe_buf = [0u16; MAX_PATH + 1]; + let mut exe_buf = [0u16; MAX_PATH as usize + 1]; GetModuleFileNameExW( **process_handler, - std::ptr::null_mut(), - exe_buf.as_mut_ptr(), - MAX_PATH as DWORD + 1, + HINSTANCE::default(), + exe_buf.as_mut_slice(), ); PathBuf::from(null_terminated_wchar_to_string(&exe_buf)) @@ -374,12 +347,13 @@ impl Process { let process_handler = get_process_handler(pid)?; let mut info: MaybeUninit = MaybeUninit::uninit(); if NtQueryInformationProcess( - *process_handler, + process_handler.0, ProcessBasicInformation, - info.as_mut_ptr() as *mut _, + info.as_mut_ptr().cast(), size_of::() as _, null_mut(), - ) != 0 + ) + .is_err() { return None; } @@ -397,7 +371,7 @@ impl Process { } }; let (start_time, run_time) = get_start_and_run_time(*process_handler, now); - let parent = if info.InheritedFromUniqueProcessId as usize != 0 { + let parent = if info.InheritedFromUniqueProcessId != 0 { Some(Pid(info.InheritedFromUniqueProcessId as _)) } else { None @@ -536,7 +510,7 @@ impl ProcessExt for Process { super::system::convert_signal(signal)?; let mut kill = process::Command::new("taskkill.exe"); kill.arg("/PID").arg(self.pid.to_string()).arg("/F"); - kill.creation_flags(CREATE_NO_WINDOW); + kill.creation_flags(CREATE_NO_WINDOW.0); match kill.output() { Ok(o) => Some(o.status.success()), Err(_) => Some(false), @@ -642,10 +616,13 @@ impl ProcessExt for Process { fn session_id(&self) -> Option { unsafe { let mut out = 0; - if ProcessIdToSessionId(self.pid.as_u32(), &mut out) != 0 { + if ProcessIdToSessionId(self.pid.as_u32(), &mut out).is_ok() { return Some(Pid(out as _)); } - sysinfo_debug!("ProcessIdToSessionId failed, error: {:?}", GetLastError()); + sysinfo_debug!( + "ProcessIdToSessionId failed, error: {:?}", + io::Error::last_os_error() + ); None } } @@ -656,7 +633,7 @@ unsafe fn get_process_times(handle: HANDLE) -> u64 { let mut fstart: FILETIME = zeroed(); let mut x = zeroed(); - GetProcessTimes( + let _err = GetProcessTimes( handle, &mut fstart as *mut FILETIME, &mut x as *mut FILETIME, @@ -694,21 +671,26 @@ unsafe fn ph_query_process_variable_size( process_handle: &HandleWrapper, process_information_class: PROCESSINFOCLASS, ) -> Option> { - let mut return_length = MaybeUninit::::uninit(); + let mut return_length = MaybeUninit::::uninit(); let mut status = NtQueryInformationProcess( **process_handle, - process_information_class, + process_information_class as _, null_mut(), 0, return_length.as_mut_ptr() as *mut _, ); - if status != STATUS_BUFFER_OVERFLOW - && status != STATUS_BUFFER_TOO_SMALL - && status != STATUS_INFO_LENGTH_MISMATCH - { - return None; + if let Err(err) = status { + if ![ + STATUS_BUFFER_OVERFLOW.into(), + STATUS_BUFFER_TOO_SMALL.into(), + STATUS_INFO_LENGTH_MISMATCH.into(), + ] + .contains(&err.code()) + { + return None; + } } let mut return_length = return_length.assume_init(); @@ -716,12 +698,12 @@ unsafe fn ph_query_process_variable_size( let mut buffer: Vec = Vec::with_capacity(buf_len + 1); status = NtQueryInformationProcess( **process_handle, - process_information_class, + process_information_class as _, buffer.as_mut_ptr() as *mut _, return_length, &mut return_length as *mut _, ); - if !NT_SUCCESS(status) { + if status.is_err() { return None; } buffer.set_len(buf_len); @@ -729,10 +711,10 @@ unsafe fn ph_query_process_variable_size( Some(buffer) } -unsafe fn get_cmdline_from_buffer(buffer: *const u16) -> Vec { +unsafe fn get_cmdline_from_buffer(buffer: PCWSTR) -> Vec { // Get argc and argv from the command line let mut argc = MaybeUninit::::uninit(); - let argv_p = winapi::um::shellapi::CommandLineToArgvW(buffer, argc.as_mut_ptr()); + let argv_p = CommandLineToArgvW(buffer, argc.as_mut_ptr()); if argv_p.is_null() { return Vec::new(); } @@ -741,22 +723,23 @@ unsafe fn get_cmdline_from_buffer(buffer: *const u16) -> Vec { let mut res = Vec::new(); for arg in argv { - let len = libc::wcslen(*arg); - let str_slice = std::slice::from_raw_parts(*arg, len); - res.push(String::from_utf16_lossy(str_slice)); + res.push(String::from_utf16_lossy(arg.as_wide())); } - winapi::um::winbase::LocalFree(argv_p as *mut _); + let _err = LocalFree(HLOCAL(argv_p as _)); res } -unsafe fn get_region_size(handle: &HandleWrapper, ptr: LPVOID) -> Result { +unsafe fn get_region_size( + handle: &HandleWrapper, + ptr: *const c_void, +) -> Result { let mut meminfo = MaybeUninit::::uninit(); if VirtualQueryEx( **handle, - ptr, - meminfo.as_mut_ptr() as *mut _, + Some(ptr), + meminfo.as_mut_ptr().cast(), size_of::(), ) == 0 { @@ -768,7 +751,7 @@ unsafe fn get_region_size(handle: &HandleWrapper, ptr: LPVOID) -> Result Result, &'static str> { let mut buffer: Vec = Vec::with_capacity(size / 2 + 1); @@ -776,11 +759,12 @@ unsafe fn get_process_data( if ReadProcessMemory( **handle, - ptr as *mut _, - buffer.as_mut_ptr() as *mut _, + ptr, + buffer.as_mut_ptr().cast(), size, - &mut bytes_read, - ) == FALSE + Some(&mut bytes_read), + ) + .is_err() { return Err("Unable to read process data"); } @@ -818,7 +802,7 @@ macro_rules! impl_RtlUserProcessParameters { fn get_environ(&self, handle: &HandleWrapper) -> Result, &'static str> { let ptr = self.Environment; unsafe { - let size = get_region_size(handle, ptr as LPVOID)?; + let size = get_region_size(handle, ptr as _)?; get_process_data(handle, ptr as _, size as _) } } @@ -837,15 +821,16 @@ unsafe fn get_process_params( } // First check if target process is running in wow64 compatibility emulator - let mut pwow32info = MaybeUninit::::uninit(); - let result = NtQueryInformationProcess( + let mut pwow32info = MaybeUninit::<*const c_void>::uninit(); + if NtQueryInformationProcess( **handle, ProcessWow64Information, - pwow32info.as_mut_ptr() as *mut _, - size_of::() as u32, + pwow32info.as_mut_ptr().cast(), + size_of::<*const c_void>() as u32, null_mut(), - ); - if !NT_SUCCESS(result) { + ) + .is_err() + { return Err("Unable to check WOW64 information about the process"); } let pwow32info = pwow32info.assume_init(); @@ -854,14 +839,15 @@ unsafe fn get_process_params( // target is a 64 bit process let mut pbasicinfo = MaybeUninit::::uninit(); - let result = NtQueryInformationProcess( + if NtQueryInformationProcess( **handle, ProcessBasicInformation, - pbasicinfo.as_mut_ptr() as *mut _, + pbasicinfo.as_mut_ptr().cast(), size_of::() as u32, null_mut(), - ); - if !NT_SUCCESS(result) { + ) + .is_err() + { return Err("Unable to get basic process information"); } let pinfo = pbasicinfo.assume_init(); @@ -869,11 +855,12 @@ unsafe fn get_process_params( let mut peb = MaybeUninit::::uninit(); if ReadProcessMemory( **handle, - pinfo.PebBaseAddress as *mut _, - peb.as_mut_ptr() as *mut _, - size_of::() as SIZE_T, - null_mut(), - ) != TRUE + pinfo.PebBaseAddress.cast(), + peb.as_mut_ptr().cast(), + size_of::(), + None, + ) + .is_err() { return Err("Unable to read process PEB"); } @@ -883,11 +870,12 @@ unsafe fn get_process_params( let mut proc_params = MaybeUninit::::uninit(); if ReadProcessMemory( **handle, - peb.ProcessParameters as *mut PRTL_USER_PROCESS_PARAMETERS as *mut _, - proc_params.as_mut_ptr() as *mut _, - size_of::() as SIZE_T, - null_mut(), - ) != TRUE + peb.ProcessParameters.cast(), + proc_params.as_mut_ptr().cast(), + size_of::(), + None, + ) + .is_err() { return Err("Unable to read process parameters"); } @@ -905,10 +893,11 @@ unsafe fn get_process_params( if ReadProcessMemory( **handle, pwow32info, - peb32.as_mut_ptr() as *mut _, - size_of::() as SIZE_T, - null_mut(), - ) != TRUE + peb32.as_mut_ptr().cast(), + size_of::(), + None, + ) + .is_err() { return Err("Unable to read PEB32"); } @@ -917,11 +906,12 @@ unsafe fn get_process_params( let mut proc_params = MaybeUninit::::uninit(); if ReadProcessMemory( **handle, - peb32.ProcessParameters as *mut PRTL_USER_PROCESS_PARAMETERS32 as *mut _, - proc_params.as_mut_ptr() as *mut _, - size_of::() as SIZE_T, - null_mut(), - ) != TRUE + peb32.ProcessParameters as *mut _, + proc_params.as_mut_ptr().cast(), + size_of::(), + None, + ) + .is_err() { return Err("Unable to read 32 bit process parameters"); } @@ -957,7 +947,7 @@ fn get_cmd_line_old( handle: &HandleWrapper, ) -> Vec { match params.get_cmdline(handle) { - Ok(buffer) => unsafe { get_cmdline_from_buffer(buffer.as_ptr()) }, + Ok(buffer) => unsafe { get_cmdline_from_buffer(PCWSTR::from_raw(buffer.as_ptr())) }, Err(_e) => { sysinfo_debug!("get_cmd_line_old failed to get data: {}", _e); Vec::new() @@ -972,7 +962,7 @@ fn get_cmd_line_new(handle: &HandleWrapper) -> Vec { { let buffer = (*(buffer.as_ptr() as *const UNICODE_STRING)).Buffer; - get_cmdline_from_buffer(buffer) + get_cmdline_from_buffer(PCWSTR::from_raw(buffer.as_ptr())) } else { vec![] } @@ -1051,51 +1041,20 @@ pub(crate) fn compute_cpu_usage(p: &mut Process, nb_cpus: u64) { let mut fglobal_user_time: FILETIME = zeroed(); if let Some(handle) = p.get_handle() { - GetProcessTimes( - handle, - &mut ftime as *mut FILETIME, - &mut ftime as *mut FILETIME, - &mut fsys as *mut FILETIME, - &mut fuser as *mut FILETIME, - ); + let _err = GetProcessTimes(handle, &mut ftime, &mut ftime, &mut fsys, &mut fuser); } // FIXME: should these values be stored in one place to make use of // `MINIMUM_CPU_UPDATE_INTERVAL`? - GetSystemTimes( - &mut fglobal_idle_time as *mut FILETIME, - &mut fglobal_kernel_time as *mut FILETIME, - &mut fglobal_user_time as *mut FILETIME, + let _err = GetSystemTimes( + Some(&mut fglobal_idle_time), + Some(&mut fglobal_kernel_time), + Some(&mut fglobal_user_time), ); - let mut sys: ULARGE_INTEGER = std::mem::zeroed(); - memcpy( - &mut sys as *mut ULARGE_INTEGER as *mut c_void, - &mut fsys as *mut FILETIME as *mut c_void, - size_of::(), - ); - let mut user: ULARGE_INTEGER = std::mem::zeroed(); - memcpy( - &mut user as *mut ULARGE_INTEGER as *mut c_void, - &mut fuser as *mut FILETIME as *mut c_void, - size_of::(), - ); - let mut global_kernel_time: ULARGE_INTEGER = std::mem::zeroed(); - memcpy( - &mut global_kernel_time as *mut ULARGE_INTEGER as *mut c_void, - &mut fglobal_kernel_time as *mut FILETIME as *mut c_void, - size_of::(), - ); - let mut global_user_time: ULARGE_INTEGER = std::mem::zeroed(); - memcpy( - &mut global_user_time as *mut ULARGE_INTEGER as *mut c_void, - &mut fglobal_user_time as *mut FILETIME as *mut c_void, - size_of::(), - ); - - let sys = *sys.QuadPart(); - let user = *user.QuadPart(); - let global_kernel_time = *global_kernel_time.QuadPart(); - let global_user_time = *global_user_time.QuadPart(); + let sys = filetime_to_u64(fsys); + let user = filetime_to_u64(fuser); + let global_kernel_time = filetime_to_u64(fglobal_kernel_time); + let global_user_time = filetime_to_u64(fglobal_user_time); let delta_global_kernel_time = check_sub(global_kernel_time, p.cpu_calc_values.old_system_sys_cpu); @@ -1127,8 +1086,7 @@ pub(crate) fn update_disk_usage(p: &mut Process) { if let Some(handle) = p.get_handle() { unsafe { - let ret = GetProcessIoCounters(handle, counters.as_mut_ptr()); - if ret == 0 { + if GetProcessIoCounters(handle, counters.as_mut_ptr()).is_err() { sysinfo_debug!("GetProcessIoCounters call failed on process {}", p.pid()); } else { let counters = counters.assume_init(); @@ -1147,10 +1105,10 @@ pub(crate) fn update_memory(p: &mut Process) { let mut pmc: PROCESS_MEMORY_COUNTERS_EX = zeroed(); if GetProcessMemoryInfo( handle, - &mut pmc as *mut PROCESS_MEMORY_COUNTERS_EX as *mut c_void - as *mut PROCESS_MEMORY_COUNTERS, - size_of::() as DWORD, - ) != 0 + (&mut pmc as *mut PROCESS_MEMORY_COUNTERS_EX).cast(), + size_of::() as _, + ) + .is_ok() { p.memory = pmc.WorkingSetSize as _; p.virtual_memory = pmc.PrivateUsage as _; @@ -1158,3 +1116,8 @@ pub(crate) fn update_memory(p: &mut Process) { } } } + +#[inline(always)] +const fn filetime_to_u64(ft: FILETIME) -> u64 { + ((ft.dwHighDateTime as u64) << 32) + ft.dwLowDateTime as u64 +} diff --git a/src/windows/sid.rs b/src/windows/sid.rs index 44d94f2f5..5ed502912 100644 --- a/src/windows/sid.rs +++ b/src/windows/sid.rs @@ -2,17 +2,11 @@ use std::{fmt::Display, str::FromStr}; -use winapi::{ - shared::{ - sddl::{ConvertSidToStringSidW, ConvertStringSidToSidW}, - winerror::ERROR_INSUFFICIENT_BUFFER, - }, - um::{ - errhandlingapi::GetLastError, - securitybaseapi::{CopySid, GetLengthSid, IsValidSid}, - winbase::{LocalFree, LookupAccountSidW}, - winnt::{SidTypeUnknown, LPWSTR, PSID}, - }, +use windows::core::{PCWSTR, PWSTR}; +use windows::Win32::Foundation::{LocalFree, ERROR_INSUFFICIENT_BUFFER, HLOCAL, PSID}; +use windows::Win32::Security::Authorization::{ConvertSidToStringSidW, ConvertStringSidToSidW}; +use windows::Win32::Security::{ + CopySid, GetLengthSid, IsValidSid, LookupAccountSidW, SidTypeUnknown, }; use crate::sys::utils::to_str; @@ -26,11 +20,11 @@ pub struct Sid { impl Sid { /// Creates an `Sid` by making a copy of the given raw SID. pub(crate) unsafe fn from_psid(psid: PSID) -> Option { - if psid.is_null() { + if psid.is_invalid() { return None; } - if IsValidSid(psid) == 0 { + if !IsValidSid(psid).as_bool() { return None; } @@ -38,8 +32,8 @@ impl Sid { let mut sid = vec![0; length as usize]; - if CopySid(length, sid.as_mut_ptr() as *mut _, psid) == 0 { - sysinfo_debug!("CopySid failed: {:?}", GetLastError()); + if CopySid(length, PSID(sid.as_mut_ptr().cast()), psid).is_err() { + sysinfo_debug!("CopySid failed: {:?}", std::io::Error::last_os_error()); return None; } @@ -68,19 +62,18 @@ impl Sid { let mut domain_len = 0; let mut name_use = SidTypeUnknown; - if LookupAccountSidW( - std::ptr::null_mut(), - self.sid.as_ptr() as *mut _, - std::ptr::null_mut(), + let sid = PSID((self.sid.as_ptr() as *mut u8).cast()); + if let Err(err) = LookupAccountSidW( + PCWSTR::null(), + sid, + PWSTR::null(), &mut name_len, - std::ptr::null_mut(), + PWSTR::null(), &mut domain_len, &mut name_use, - ) == 0 - { - let error = GetLastError(); - if error != ERROR_INSUFFICIENT_BUFFER { - sysinfo_debug!("LookupAccountSidW failed: {:?}", error); + ) { + if err.code() != ERROR_INSUFFICIENT_BUFFER.to_hresult() { + sysinfo_debug!("LookupAccountSidW failed: {:?}", err); return None; } } @@ -92,20 +85,24 @@ impl Sid { domain_len = 0; if LookupAccountSidW( - std::ptr::null_mut(), - self.sid.as_ptr() as *mut _, - name.as_mut_ptr(), + PCWSTR::null(), + sid, + PWSTR::from_raw(name.as_mut_ptr()), &mut name_len, - std::ptr::null_mut(), + PWSTR::null(), &mut domain_len, &mut name_use, - ) == 0 + ) + .is_err() { - sysinfo_debug!("LookupAccountSidW failed: {:?}", GetLastError()); + sysinfo_debug!( + "LookupAccountSidW failed: {:?}", + std::io::Error::last_os_error() + ); return None; } - Some(to_str(name.as_mut_ptr())) + Some(to_str(PWSTR::from_raw(name.as_mut_ptr()))) } } } @@ -113,17 +110,18 @@ impl Sid { impl Display for Sid { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { unsafe fn convert_sid_to_string_sid(sid: PSID) -> Option { - let mut string_sid: LPWSTR = std::ptr::null_mut(); - if ConvertSidToStringSidW(sid, &mut string_sid) == 0 { - sysinfo_debug!("ConvertSidToStringSidW failed: {:?}", GetLastError()); + let mut string_sid = PWSTR::null(); + if let Err(_err) = ConvertSidToStringSidW(sid, &mut string_sid) { + sysinfo_debug!("ConvertSidToStringSidW failed: {:?}", _err); return None; } let result = to_str(string_sid); - LocalFree(string_sid as *mut _); + let _err = LocalFree(HLOCAL(string_sid.0 as _)); Some(result) } - let string_sid = unsafe { convert_sid_to_string_sid(self.sid.as_ptr() as *mut _) }; + let string_sid = + unsafe { convert_sid_to_string_sid(PSID((self.sid.as_ptr() as *mut u8).cast())) }; let string_sid = string_sid.ok_or(std::fmt::Error)?; write!(f, "{string_sid}") @@ -138,15 +136,14 @@ impl FromStr for Sid { let mut string_sid: Vec = s.encode_utf16().collect(); string_sid.push(0); - let mut psid: PSID = std::ptr::null_mut(); - if ConvertStringSidToSidW(string_sid.as_ptr(), &mut psid) == 0 { - return Err(format!( - "ConvertStringSidToSidW failed: {:?}", - GetLastError() - )); + let mut psid = PSID::default(); + if let Err(err) = + ConvertStringSidToSidW(PCWSTR::from_raw(string_sid.as_ptr()), &mut psid) + { + return Err(format!("ConvertStringSidToSidW failed: {:?}", err)); } let sid = Self::from_psid(psid); - LocalFree(psid as *mut _); + let _err = LocalFree(HLOCAL(psid.0 as _)); // Unwrapping because ConvertStringSidToSidW should've performed // all the necessary validations. If it returned an invalid SID, diff --git a/src/windows/system.rs b/src/windows/system.rs index b140eca25..4e68bf0b4 100644 --- a/src/windows/system.rs +++ b/src/windows/system.rs @@ -3,7 +3,6 @@ use crate::{ CpuRefreshKind, LoadAvg, Pid, ProcessExt, ProcessRefreshKind, RefreshKind, SystemExt, User, }; -use winapi::um::winreg::HKEY_LOCAL_MACHINE; use crate::sys::cpu::*; use crate::sys::process::{get_start_time, update_memory, Process}; @@ -19,20 +18,17 @@ use std::mem::{size_of, zeroed}; use std::ptr; use std::time::{Duration, SystemTime}; -use ntapi::ntexapi::{ - NtQuerySystemInformation, SystemProcessInformation, SYSTEM_PROCESS_INFORMATION, -}; -use winapi::ctypes::wchar_t; -use winapi::shared::minwindef::{FALSE, TRUE}; -use winapi::shared::ntstatus::{STATUS_INFO_LENGTH_MISMATCH, STATUS_SUCCESS}; -use winapi::um::minwinbase::STILL_ACTIVE; -use winapi::um::processthreadsapi::GetExitCodeProcess; -use winapi::um::psapi::{GetPerformanceInfo, PERFORMANCE_INFORMATION}; -use winapi::um::sysinfoapi::{ +use ntapi::ntexapi::SYSTEM_PROCESS_INFORMATION; +use windows::core::PWSTR; +use windows::Wdk::System::SystemInformation::{NtQuerySystemInformation, SystemProcessInformation}; +use windows::Win32::Foundation::{HANDLE, STATUS_INFO_LENGTH_MISMATCH, STILL_ACTIVE}; +use windows::Win32::System::ProcessStatus::{K32GetPerformanceInfo, PERFORMANCE_INFORMATION}; +use windows::Win32::System::Registry::HKEY_LOCAL_MACHINE; +use windows::Win32::System::SystemInformation::{ ComputerNamePhysicalDnsHostname, GetComputerNameExW, GetTickCount64, GlobalMemoryStatusEx, MEMORYSTATUSEX, }; -use winapi::um::winnt::HANDLE; +use windows::Win32::System::Threading::GetExitCodeProcess; declare_signals! { (), @@ -163,12 +159,12 @@ impl SystemExt for System { unsafe { let mut mem_info: MEMORYSTATUSEX = zeroed(); mem_info.dwLength = size_of::() as u32; - GlobalMemoryStatusEx(&mut mem_info); + let _err = GlobalMemoryStatusEx(&mut mem_info); self.mem_total = mem_info.ullTotalPhys as _; self.mem_available = mem_info.ullAvailPhys as _; let mut perf_info: PERFORMANCE_INFORMATION = zeroed(); - if GetPerformanceInfo(&mut perf_info, size_of::() as u32) - == TRUE + if K32GetPerformanceInfo(&mut perf_info, size_of::() as u32) + .as_bool() { let swap_total = perf_info.PageSize.saturating_mul( perf_info @@ -228,24 +224,26 @@ impl SystemExt for System { &mut cb_needed, ); - if ntstatus == STATUS_SUCCESS { - break; - } else if ntstatus == STATUS_INFO_LENGTH_MISMATCH { - // GetNewBufferSize - if cb_needed == 0 { - buffer_size *= 2; + match ntstatus { + Ok(()) => break, + Err(err) if err.code() == STATUS_INFO_LENGTH_MISMATCH.to_hresult() => { + // GetNewBufferSize + if cb_needed == 0 { + buffer_size *= 2; + continue; + } + // allocating a few more kilo bytes just in case there are some new process + // kicked in since new call to NtQuerySystemInformation + buffer_size = (cb_needed + (1024 * 10)) as usize; continue; } - // allocating a few more kilo bytes just in case there are some new process - // kicked in since new call to NtQuerySystemInformation - buffer_size = (cb_needed + (1024 * 10)) as usize; - continue; - } else { - sysinfo_debug!( - "Couldn't get process infos: NtQuerySystemInformation returned {}", - ntstatus - ); - return; + Err(_err) => { + sysinfo_debug!( + "Couldn't get process infos: NtQuerySystemInformation returned {}", + _err, + ); + return; + } } } } @@ -477,10 +475,8 @@ impl Default for System { pub(crate) fn is_proc_running(handle: HANDLE) -> bool { let mut exit_code = 0; - unsafe { - let ret = GetExitCodeProcess(handle, &mut exit_code); - !(ret == FALSE || exit_code != STILL_ACTIVE) - } + unsafe { GetExitCodeProcess(handle, &mut exit_code) }.is_ok() + && exit_code == STILL_ACTIVE.0 as u32 } /// If it returns `None`, it means that the PID owner changed and that the `Process` must be @@ -538,9 +534,9 @@ fn get_dns_hostname() -> Option { // setting the `lpBuffer` to null will return the buffer size // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getcomputernameexw unsafe { - GetComputerNameExW( + let _err = GetComputerNameExW( ComputerNamePhysicalDnsHostname, - std::ptr::null_mut(), + PWSTR::null(), &mut buffer_size, ); @@ -550,9 +546,10 @@ fn get_dns_hostname() -> Option { // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ne-sysinfoapi-computer_name_format if GetComputerNameExW( ComputerNamePhysicalDnsHostname, - buffer.as_mut_ptr() as *mut wchar_t, + PWSTR::from_raw(buffer.as_mut_ptr()), &mut buffer_size, - ) == TRUE + ) + .is_ok() { if let Some(pos) = buffer.iter().position(|c| *c == 0) { buffer.resize(pos, 0); diff --git a/src/windows/tools.rs b/src/windows/tools.rs index a0c334010..b41e0b607 100644 --- a/src/windows/tools.rs +++ b/src/windows/tools.rs @@ -3,9 +3,7 @@ use crate::sys::cpu::{self, Cpu, Query}; use crate::CpuRefreshKind; -use std::mem::zeroed; - -use winapi::um::sysinfoapi::{GetSystemInfo, SYSTEM_INFO}; +use windows::Win32::System::SystemInformation::{GetSystemInfo, SYSTEM_INFO}; pub(crate) struct KeyHandler { pub unique_id: String, @@ -19,7 +17,7 @@ impl KeyHandler { pub(crate) fn init_cpus(refresh_kind: CpuRefreshKind) -> (Vec, String, String) { unsafe { - let mut sys_info: SYSTEM_INFO = zeroed(); + let mut sys_info = SYSTEM_INFO::default(); GetSystemInfo(&mut sys_info); let (vendor_id, brand) = cpu::get_vendor_id_and_brand(&sys_info); let nb_cpus = sys_info.dwNumberOfProcessors as usize; diff --git a/src/windows/users.rs b/src/windows/users.rs index bb706eb77..498cd337f 100644 --- a/src/windows/users.rs +++ b/src/windows/users.rs @@ -8,56 +8,40 @@ use crate::{ }; use std::ptr::null_mut; -use winapi::shared::lmcons::{MAX_PREFERRED_LENGTH, NET_API_STATUS}; -use winapi::shared::minwindef::{DWORD, LPBYTE}; -use winapi::shared::ntstatus::STATUS_SUCCESS; -use winapi::shared::winerror::ERROR_MORE_DATA; -use winapi::um::lmaccess::{ - NetUserEnum, NetUserGetInfo, NetUserGetLocalGroups, LOCALGROUP_USERS_INFO_0, USER_INFO_23, +use windows::core::{w, PCWSTR}; +use windows::Win32::Foundation::{ERROR_MORE_DATA, LUID}; +use windows::Win32::NetworkManagement::NetManagement::{ + NERR_Success, NetApiBufferFree, NetUserEnum, NetUserGetInfo, NetUserGetLocalGroups, + FILTER_NORMAL_ACCOUNT, LG_INCLUDE_INDIRECT, LOCALGROUP_USERS_INFO_0, MAX_PREFERRED_LENGTH, + USER_INFO_0, USER_INFO_23, }; -use winapi::um::lmaccess::{FILTER_NORMAL_ACCOUNT, LG_INCLUDE_INDIRECT, USER_INFO_0}; -use winapi::um::lmapibuf::NetApiBufferFree; -use winapi::um::ntlsa::{ +use windows::Win32::Security::Authentication::Identity::{ LsaEnumerateLogonSessions, LsaFreeReturnBuffer, LsaGetLogonSessionData, - SECURITY_LOGON_SESSION_DATA, + SECURITY_LOGON_SESSION_DATA, SECURITY_LOGON_TYPE, }; -use winapi::um::winnt::{LPWSTR, LUID, WCHAR}; #[doc = include_str!("../../md_doc/user.md")] pub struct User { pub(crate) uid: Uid, pub(crate) gid: Gid, pub(crate) name: String, - c_user_name: Option>, + c_user_name: Option>, is_local: bool, } impl User { - fn new(uid: Uid, name: String, c_name: LPWSTR, is_local: bool) -> Self { - unsafe { - let c_user_name = if is_local && !c_name.is_null() { - let mut i = 0; - loop { - let c = *c_name.offset(i); - if c == 0 { - i += 1; // We increase by 1 because we need the '\0' at the end. - break; - } - i += 1; - } - Some(Vec::from(std::slice::from_raw_parts(c_name, i as _))) - } else { - // There is no local groups for a non-local user. - None - }; - - Self { - uid, - gid: Gid(0), - name, - c_user_name, - is_local, - } + fn new(uid: Uid, name: String, c_name: PCWSTR, is_local: bool) -> Self { + let c_user_name = if c_name.is_null() { + None + } else { + Some(unsafe { c_name.as_wide() }.into()) + }; + Self { + uid, + gid: Gid(0), + name, + c_user_name, + is_local, } } } @@ -76,27 +60,20 @@ impl UserExt for User { } fn groups(&self) -> Vec { - if self.is_local { - if let Some(c_user_name) = &self.c_user_name { - unsafe { return get_groups_for_user(c_user_name.as_ptr() as _) }; - } + if let (Some(c_user_name), true) = (&self.c_user_name, self.is_local) { + unsafe { get_groups_for_user(PCWSTR(c_user_name.as_ptr())) } + } else { + Vec::new() } - Vec::new() } } -// FIXME: Can be removed once merged in winapi. -#[allow(non_upper_case_globals)] -const NERR_Success: NET_API_STATUS = 0; - struct NetApiBuffer(*mut T); impl Drop for NetApiBuffer { fn drop(&mut self) { - unsafe { - if !self.0.is_null() { - NetApiBufferFree(self.0 as *mut _); - } + if !self.0.is_null() { + unsafe { NetApiBufferFree(Some(self.0.cast())) }; } } } @@ -113,10 +90,10 @@ impl NetApiBuffer { &mut self.0 } - pub unsafe fn inner_mut_as_bytes(&mut self) -> &mut LPBYTE { + pub unsafe fn inner_mut_as_bytes(&mut self) -> &mut *mut u8 { // https://doc.rust-lang.org/std/mem/fn.transmute.html // Turning an &mut T into an &mut U: - &mut *(self.inner_mut() as *mut *mut T as *mut LPBYTE) + &mut *(self.inner_mut() as *mut *mut T as *mut *mut u8) } } @@ -124,10 +101,8 @@ struct LsaBuffer(*mut T); impl Drop for LsaBuffer { fn drop(&mut self) { - unsafe { - if !self.0.is_null() { - LsaFreeReturnBuffer(self.0 as *mut _); - } + if !self.0.is_null() { + let _r = unsafe { LsaFreeReturnBuffer(self.0 as *mut _) }; } } } @@ -145,14 +120,14 @@ impl LsaBuffer { } } -unsafe fn get_groups_for_user(username: LPWSTR) -> Vec { +unsafe fn get_groups_for_user(username: PCWSTR) -> Vec { let mut buf: NetApiBuffer = Default::default(); let mut nb_entries = 0; let mut total_entries = 0; let mut groups; let status = NetUserGetLocalGroups( - [0u16].as_ptr(), + w!(""), username, 0, LG_INCLUDE_INDIRECT, @@ -182,22 +157,22 @@ unsafe fn get_groups_for_user(username: LPWSTR) -> Vec { pub unsafe fn get_users() -> Vec { let mut users = Vec::new(); - let mut resume_handle: DWORD = 0; + let mut resume_handle: u32 = 0; loop { let mut buffer: NetApiBuffer = Default::default(); let mut nb_read = 0; let mut total = 0; let status = NetUserEnum( - null_mut(), + PCWSTR::null(), 0, FILTER_NORMAL_ACCOUNT, buffer.inner_mut_as_bytes(), MAX_PREFERRED_LENGTH, &mut nb_read, &mut total, - &mut resume_handle, + Some(&mut resume_handle), ); - if status == NERR_Success || status == ERROR_MORE_DATA { + if status == NERR_Success || status == ERROR_MORE_DATA.0 { let entries = std::slice::from_raw_parts(buffer.0, nb_read as _); for entry in entries { if entry.usri0_name.is_null() { @@ -205,8 +180,12 @@ pub unsafe fn get_users() -> Vec { } let mut user: NetApiBuffer = Default::default(); - if NetUserGetInfo(null_mut(), entry.usri0_name, 23, user.inner_mut_as_bytes()) - == NERR_Success + if NetUserGetInfo( + PCWSTR::null(), + PCWSTR::from_raw(entry.usri0_name.as_ptr()), + 23, + user.inner_mut_as_bytes(), + ) == NERR_Success { if let Some(sid) = Sid::from_psid((*user.0).usri23_user_sid) { // Get the account name from the SID (because it's usually @@ -215,23 +194,28 @@ pub unsafe fn get_users() -> Vec { let name = sid .account_name() .unwrap_or_else(|| to_str(entry.usri0_name)); - users.push(User::new(Uid(sid), name, entry.usri0_name, true)) + users.push(User::new( + Uid(sid), + name, + PCWSTR(entry.usri0_name.0 as *const _), + true, + )) } } } } else { sysinfo_debug!( "NetUserEnum error: {}", - if status == winapi::shared::winerror::ERROR_ACCESS_DENIED { + if status == windows::Win32::Foundation::ERROR_ACCESS_DENIED.0 { "access denied" - } else if status == winapi::shared::winerror::ERROR_INVALID_LEVEL { + } else if status == windows::Win32::Foundation::ERROR_INVALID_LEVEL.0 { "invalid level" } else { "unknown error" } ); } - if status != ERROR_MORE_DATA { + if status != ERROR_MORE_DATA.0 { break; } } @@ -239,17 +223,15 @@ pub unsafe fn get_users() -> Vec { // First part done. Second part now! let mut nb_sessions = 0; let mut uids: LsaBuffer = Default::default(); - if LsaEnumerateLogonSessions(&mut nb_sessions, uids.inner_mut()) != STATUS_SUCCESS { + if LsaEnumerateLogonSessions(&mut nb_sessions, uids.inner_mut()).is_err() { sysinfo_debug!("LsaEnumerateLogonSessions failed"); } else { let entries = std::slice::from_raw_parts_mut(uids.0, nb_sessions as _); for entry in entries { let mut data: LsaBuffer = Default::default(); - if LsaGetLogonSessionData(entry, data.inner_mut()) == STATUS_SUCCESS - && !data.0.is_null() - { + if LsaGetLogonSessionData(entry, data.inner_mut()).is_ok() && !data.0.is_null() { let data = *data.0; - if data.LogonType == winapi::um::ntlsa::Network { + if data.LogonType == SECURITY_LOGON_TYPE::Network.0 as u32 { continue; } @@ -267,7 +249,7 @@ pub unsafe fn get_users() -> Vec { // if this fails. let name = sid.account_name().unwrap_or_else(|| { String::from_utf16(std::slice::from_raw_parts( - data.UserName.Buffer, + data.UserName.Buffer.as_ptr(), data.UserName.Length as usize / std::mem::size_of::(), )) .unwrap_or_else(|_err| { @@ -276,7 +258,7 @@ pub unsafe fn get_users() -> Vec { }) }); - users.push(User::new(Uid(sid), name, std::ptr::null_mut(), false)); + users.push(User::new(Uid(sid), name, PCWSTR::null(), false)); } } } diff --git a/src/windows/utils.rs b/src/windows/utils.rs index 699fe1217..25545b9aa 100644 --- a/src/windows/utils.rs +++ b/src/windows/utils.rs @@ -1,10 +1,10 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use winapi::shared::minwindef::FILETIME; -use winapi::shared::minwindef::{DWORD, HKEY}; -use winapi::shared::winerror; -use winapi::um::winnt::{KEY_READ, LPWSTR}; -use winapi::um::winreg::{RegCloseKey, RegOpenKeyExW, RegQueryValueExW}; +use windows::core::{PCWSTR, PWSTR}; +use windows::Win32::Foundation::{self, FILETIME}; +use windows::Win32::System::Registry::{ + RegCloseKey, RegOpenKeyExW, RegQueryValueExW, HKEY, KEY_READ, REG_NONE, +}; use std::ffi::OsStr; use std::os::windows::ffi::OsStrExt; @@ -23,21 +23,12 @@ pub(crate) fn get_now() -> u64 { .unwrap_or(0) } -pub(crate) unsafe fn to_str(p: LPWSTR) -> String { +pub(crate) unsafe fn to_str(p: PWSTR) -> String { if p.is_null() { return String::new(); } - let mut i = 0; - loop { - let c = *p.offset(i); - if c == 0 { - break; - } - i += 1; - } - let s = std::slice::from_raw_parts(p, i as _); - String::from_utf16(s).unwrap_or_else(|_e| { + p.to_string().unwrap_or_else(|_e| { sysinfo_debug!("Failed to convert to UTF-16 string: {}", _e); String::new() }) @@ -54,32 +45,43 @@ struct RegKey(HKEY); impl RegKey { unsafe fn open(hkey: HKEY, path: &[u16]) -> Option { - let mut new_hkey: HKEY = std::ptr::null_mut(); - if RegOpenKeyExW(hkey, path.as_ptr(), 0, KEY_READ, &mut new_hkey) != 0 { + let mut new_hkey = Default::default(); + if RegOpenKeyExW( + hkey, + PCWSTR::from_raw(path.as_ptr()), + 0, + KEY_READ, + &mut new_hkey, + ) + .is_err() + { return None; } Some(Self(new_hkey)) } - unsafe fn get_value(&self, field_name: &[u16], buf: &mut [u8], buf_len: &mut DWORD) -> DWORD { - let mut buf_type: DWORD = 0; + unsafe fn get_value( + &self, + field_name: &[u16], + buf: &mut [u8], + buf_len: &mut u32, + ) -> windows::core::Result<()> { + let mut buf_type = REG_NONE; RegQueryValueExW( self.0, - field_name.as_ptr(), - std::ptr::null_mut(), - &mut buf_type, - buf.as_mut_ptr() as _, - buf_len, - ) as DWORD + PCWSTR::from_raw(field_name.as_ptr()), + None, + Some(&mut buf_type), + Some(buf.as_mut_ptr()), + Some(buf_len), + ) } } impl Drop for RegKey { fn drop(&mut self) { - unsafe { - RegCloseKey(self.0); - } + let _err = unsafe { RegCloseKey(self.0) }; } } @@ -89,13 +91,13 @@ pub(crate) fn get_reg_string_value(hkey: HKEY, path: &str, field_name: &str) -> unsafe { let new_key = RegKey::open(hkey, &c_path)?; - let mut buf_len: DWORD = 2048; + let mut buf_len: u32 = 2048; let mut buf: Vec = Vec::with_capacity(buf_len as usize); loop { match new_key.get_value(&c_field_name, &mut buf, &mut buf_len) { - winerror::ERROR_SUCCESS => break, - winerror::ERROR_MORE_DATA => { + Ok(()) => break, + Err(err) if err.code() == Foundation::ERROR_MORE_DATA.to_hresult() => { buf.reserve(buf_len as _); } _ => return None, @@ -119,12 +121,12 @@ pub(crate) fn get_reg_value_u32(hkey: HKEY, path: &str, field_name: &str) -> Opt unsafe { let new_key = RegKey::open(hkey, &c_path)?; - let mut buf_len: DWORD = 4; + let mut buf_len: u32 = 4; let mut buf = [0u8; 4]; - match new_key.get_value(&c_field_name, &mut buf, &mut buf_len) { - winerror::ERROR_SUCCESS => Some(buf), - _ => None, - } + new_key + .get_value(&c_field_name, &mut buf, &mut buf_len) + .map(|_| buf) + .ok() } }