From 034e3978a9a72bbb51ce3a9097caa34ebabe124b Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Mon, 30 Mar 2026 17:43:43 +0200 Subject: [PATCH] Replace winapi with windows-sys winapi didn't have any update for 6 years --- .github/workflows/ci.yml | 2 +- Cargo.lock | 75 +++++++++++++++++++++++++++------ Cargo.toml | 11 ++++- src/platform/windows.rs | 46 ++++++++++++++++---- src/platform/windows_safe.rs | 81 +++++++++++++++++++++++------------- 5 files changed, 161 insertions(+), 54 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c09a31..2e900a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,7 +104,7 @@ jobs: echo "PWD='${PWD}'" # tooling info display echo "## tooling" - (gcc --version | head -1) || : + command -v gcc >/dev/null 2>&1 && (gcc --version | head -1) || true rustup -V 2>/dev/null rustup show active-toolchain cargo -V diff --git a/Cargo.lock b/Cargo.lock index 0a55c65..1f3eef9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,7 +29,7 @@ version = "2.1.0" dependencies = [ "libc", "regex", - "winapi", + "windows-sys", ] [[package]] @@ -62,23 +62,74 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-targets", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-targets" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows_aarch64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index a7dba81..bfc27de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,13 +13,20 @@ keywords = ["platform", "info", "system"] categories = ["os"] license = "MIT" -# spell-checker:ignore (crates) libc winapi (features) libloaderapi processthreadsapi sysinfoapi winbase winver +# spell-checker:ignore (crates) libc (features) libloaderapi processthreadsapi sysinfoapi winbase winver [target.'cfg(not(target_os = "windows"))'.dependencies] libc = "0.2.154" [target.'cfg(target_os = "windows")'.dependencies] -winapi = { version = "0.3.9", features = ["libloaderapi", "processthreadsapi", "sysinfoapi", "winbase", "winver"] } +windows-sys = { version = "0.59", features = [ + "Win32_Foundation", + "Win32_Storage_FileSystem", + "Win32_System_LibraryLoader", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", +] } [dev-dependencies] regex = "1.10.4" diff --git a/src/platform/windows.rs b/src/platform/windows.rs index ded87b6..bab889c 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -37,9 +37,36 @@ use std::fmt::{Debug, Formatter}; use std::io; use std::os::windows::ffi::OsStringExt; -use winapi::shared::minwindef::*; -use winapi::um::sysinfoapi::*; -use winapi::um::winnt::*; +use windows_sys::Win32::Foundation::FALSE; +use windows_sys::Win32::System::SystemInformation::{ + ComputerNamePhysicalDnsHostname, PROCESSOR_ARCHITECTURE_ALPHA, PROCESSOR_ARCHITECTURE_ALPHA64, + PROCESSOR_ARCHITECTURE_AMD64, PROCESSOR_ARCHITECTURE_ARM, PROCESSOR_ARCHITECTURE_ARM64, + PROCESSOR_ARCHITECTURE_IA64, PROCESSOR_ARCHITECTURE_INTEL, PROCESSOR_ARCHITECTURE_MIPS, + PROCESSOR_ARCHITECTURE_PPC, PROCESSOR_ARCHITECTURE_SHX, SYSTEM_INFO, VER_PRODUCT_TYPE, + VER_SUITENAME, +}; + +// Windows type aliases not exported by windows-sys +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +pub(crate) type BYTE = u8; +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +pub(crate) type WORD = u16; +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +pub(crate) type DWORD = u32; +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +pub(crate) type UINT = u32; + +// VER_* constants defined locally with types matching their usage context. +// windows-sys exports these as u32, but wProductType is u8 and VerSetConditionMask condition is u8. +const VER_EQUAL: BYTE = 1; +const VER_NT_WORKSTATION: BYTE = 1; +const VER_SUITE_WH_SERVER: DWORD = 32768; +#[cfg(test)] +const VER_NT_SERVER: BYTE = 3; +#[cfg(test)] +const VER_SUITE_PERSONAL: DWORD = 0x00000200; +#[cfg(test)] +const VER_SUITE_SMALLBUSINESS: DWORD = 0x00000001; use crate::{PlatformInfoAPI, PlatformInfoError, UNameAPI}; @@ -166,8 +193,9 @@ pub mod util { use std::ffi::OsStr; use std::os::windows::ffi::OsStrExt; - use winapi::um::winnt::*; - + /// WinOS wide character (`wchar_t` / `u16`) + #[allow(non_camel_case_types, clippy::upper_case_acronyms)] + pub type WCHAR = u16; /// WinOS wide-character string buffer ///
Note: `WCHAR` (aka `TCHAR`) == `wchar_t` == `u16` #[allow(clippy::upper_case_acronyms)] @@ -427,10 +455,10 @@ fn mmbr_from_file_version( ) -> Result { let info = WinOsFileVersionInfoQuery_root(&file_version_info)?; Ok(MmbrVersion { - major: DWORD::from(HIWORD(info.dwProductVersionMS)), - minor: DWORD::from(LOWORD(info.dwProductVersionMS)), - build: DWORD::from(HIWORD(info.dwProductVersionLS)), - release: DWORD::from(LOWORD(info.dwProductVersionLS)), + major: info.dwProductVersionMS >> 16, + minor: info.dwProductVersionMS & 0xffff, + build: info.dwProductVersionLS >> 16, + release: info.dwProductVersionLS & 0xffff, }) } diff --git a/src/platform/windows_safe.rs b/src/platform/windows_safe.rs index 4fc1319..e26d41f 100644 --- a/src/platform/windows_safe.rs +++ b/src/platform/windows_safe.rs @@ -15,16 +15,34 @@ use std::io; use std::mem::{self, MaybeUninit}; use std::ptr; -use winapi::shared::minwindef::*; -use winapi::shared::ntdef::NTSTATUS; -use winapi::shared::ntstatus::*; -use winapi::um::libloaderapi::*; -use winapi::um::processthreadsapi::GetCurrentProcess; -use winapi::um::sysinfoapi; -use winapi::um::sysinfoapi::*; -use winapi::um::winbase::*; -use winapi::um::winnt::*; -use winapi::um::winver::*; +use windows_sys::Win32::Foundation::{ + FreeLibrary, BOOL, FALSE, FARPROC, HANDLE, HMODULE, NTSTATUS, STATUS_SUCCESS, +}; +use windows_sys::Win32::Storage::FileSystem::{ + GetFileVersionInfoSizeW, GetFileVersionInfoW, VerQueryValueW, +}; +use windows_sys::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryW}; +use windows_sys::Win32::System::SystemInformation::{ + GetComputerNameExW, GetNativeSystemInfo, GetSystemDirectoryW, VerSetConditionMask, + VerifyVersionInfoW, COMPUTER_NAME_FORMAT, OSVERSIONINFOEXW, SYSTEM_INFO, +}; +use windows_sys::Win32::System::Threading::GetCurrentProcess; + +// Re-use shared type aliases from parent module +use super::{BYTE, DWORD, UINT, WORD}; + +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +type WCHAR = u16; +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +type LPVOID = *mut std::ffi::c_void; +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +type LPCVOID = *const std::ffi::c_void; +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +type ULONGLONG = u64; +#[allow(non_camel_case_types, clippy::upper_case_acronyms)] +type DWORDLONG = u64; +#[allow(non_camel_case_types)] +type RTL_OSVERSIONINFOEXW = OSVERSIONINFOEXW; use super::util::{to_c_string, to_c_wstring, CWSTR}; use super::{WinApiFileVersionInfo, WinApiSystemInfo}; @@ -68,7 +86,7 @@ impl WinApiSystemInfo { /// Returns `wProcessorArchitecture` extracted from the [`SYSTEM_INFO`](https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info) structure. ///
Refer to [`SYSTEM_INFO`](https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info) for more information. pub fn wProcessorArchitecture(&self) -> WORD { - unsafe { self.0.u.s().wProcessorArchitecture } + unsafe { self.0.Anonymous.Anonymous.wProcessorArchitecture } } } @@ -253,7 +271,7 @@ pub fn WinAPI_GetProcAddress>( // pub unsafe fn GetProcAddress(hModule: HMODULE, lpProcName: LPCSTR) -> FARPROC // ref: @@ let symbol_name_cs = to_c_string(symbol_name.as_ref()); - unsafe { GetProcAddress(module, symbol_name_cs.as_ptr()) } + unsafe { GetProcAddress(module, symbol_name_cs.as_ptr().cast()) } } // WinAPI_GetSystemDirectoryW @@ -412,7 +430,7 @@ pub fn WinAPI_VerSetConditionMask( // type_mask ~ mask indicating the member of version info whose comparison operator is being set // condition ~ comparison type // * returns ULONGLONG ~ updated condition_mask - unsafe { sysinfoapi::VerSetConditionMask(condition_mask, type_mask, condition) } + unsafe { VerSetConditionMask(condition_mask, type_mask, condition) } } // WinOsFileVersionInfoQuery_root @@ -474,16 +492,17 @@ pub fn KERNEL32_IsWow64Process(process: HANDLE) -> Result { let module_path = super::WinOsGetSystemDirectory()?.join(module_file); // let func = super::WinOsGetModuleProcAddress(module_path, procedure); // loads module "permanently" (for the life of current process) let module = WinAPI_LoadLibrary(module_path); - let func = WinAPI_GetProcAddress(module, symbol_name); - if func.is_null() { - return Err(Box::from(format!( - "Unable to find DLL procedure '{}' within '{}'", - symbol_name, module_file - ))); - } + let func = match WinAPI_GetProcAddress(module, symbol_name) { + Some(f) => f, + None => { + return Err(Box::from(format!( + "Unable to find DLL procedure '{}' within '{}'", + symbol_name, module_file + ))); + } + }; - let func: extern "system" fn(HANDLE, *mut BOOL) -> BOOL = - unsafe { mem::transmute(func as *const ()) }; + let func: extern "system" fn(HANDLE, *mut BOOL) -> BOOL = unsafe { mem::transmute(func) }; let mut is_wow64: BOOL = FALSE; let result: BOOL = func(process, &mut is_wow64); @@ -509,15 +528,17 @@ pub fn NTDLL_RtlGetVersion() -> Result { let module_path = super::WinOsGetSystemDirectory()?.join(module_file); // let func = super::WinOsGetModuleProcAddress(module_path, procedure); // loads module "permanently" (for the life of current process) let module = WinAPI_LoadLibrary(module_path); - let func = WinAPI_GetProcAddress(module, symbol_name); - if func.is_null() { - return Err(Box::from(format!( - "Unable to find DLL procedure '{}' within '{}'", - symbol_name, module_file - ))); - } + let func = match WinAPI_GetProcAddress(module, symbol_name) { + Some(f) => f, + None => { + return Err(Box::from(format!( + "Unable to find DLL procedure '{}' within '{}'", + symbol_name, module_file + ))); + } + }; let func: extern "system" fn(*mut RTL_OSVERSIONINFOEXW) -> NTSTATUS = - unsafe { mem::transmute(func as *const ()) }; + unsafe { mem::transmute(func) }; let mut os_version_info = match create_OSVERSIONINFOEXW() { Ok(value) => value,