Skip to content

Commit

Permalink
Merge pull request stanislav-tkach#341 from poliorcetics/winapi-to-wi…
Browse files Browse the repository at this point in the history
…ndows-sys

deps: Move from winapi to windows-sys
  • Loading branch information
stanislav-tkach committed Mar 20, 2023
2 parents 755ae48 + 4e92fef commit 34c12c7
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 47 deletions.
10 changes: 9 additions & 1 deletion os_info/Cargo.toml
Expand Up @@ -21,7 +21,15 @@ log = "0.4.5"
serde = { version = "1", features = ["derive"], optional = true }

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.8", features = ["minwindef", "ntdef", "ntstatus", "sysinfoapi", "winnt", "winuser", "libloaderapi", "processthreadsapi", "winerror", "winreg"] }
windows-sys = { version = "0.45", features = [
"Win32_Foundation",
"Win32_System_Diagnostics_Debug",
"Win32_System_LibraryLoader",
"Win32_System_SystemInformation",
"Win32_UI_WindowsAndMessaging",
"Win32_System_Registry",
"Win32_System_SystemServices",
]}

[dev-dependencies]
pretty_assertions = "1"
Expand Down
79 changes: 33 additions & 46 deletions os_info/src/windows/winapi.rs
Expand Up @@ -12,32 +12,25 @@ use std::{
ptr,
};

use winapi::{
shared::{
minwindef::{DWORD, FARPROC, LPBYTE},
ntdef::{LPCSTR, NTSTATUS},
ntstatus::STATUS_SUCCESS,
winerror::ERROR_SUCCESS,
},
um::{
libloaderapi::{GetModuleHandleA, GetProcAddress},
sysinfoapi::{GetSystemInfo, SYSTEM_INFO},
winnt::{
KEY_READ, PROCESSOR_ARCHITECTURE_AMD64, REG_SZ, VER_NT_WORKSTATION,
VER_SUITE_WH_SERVER, WCHAR,
},
winreg::{RegOpenKeyExW, RegQueryValueExW, HKEY_LOCAL_MACHINE, LSTATUS},
winuser::{GetSystemMetrics, SM_SERVERR2},
use windows_sys::Win32::{
Foundation::{ERROR_SUCCESS, FARPROC, NTSTATUS, STATUS_SUCCESS},
System::{
Diagnostics::Debug::PROCESSOR_ARCHITECTURE_AMD64,
LibraryLoader::{GetModuleHandleA, GetProcAddress},
Registry::{RegOpenKeyExW, RegQueryValueExW, HKEY_LOCAL_MACHINE, KEY_READ, REG_SZ},
SystemInformation::{GetSystemInfo, SYSTEM_INFO},
SystemServices::{VER_NT_WORKSTATION, VER_SUITE_WH_SERVER},
},
UI::WindowsAndMessaging::{GetSystemMetrics, SM_SERVERR2},
};

use crate::{Bitness, Info, Type, Version};

#[cfg(target_arch = "x86")]
type OSVERSIONINFOEX = winapi::um::winnt::OSVERSIONINFOEXA;
type OSVERSIONINFOEX = windows_sys::Win32::System::SystemInformation::OSVERSIONINFOEXA;

#[cfg(not(target_arch = "x86"))]
type OSVERSIONINFOEX = winapi::um::winnt::OSVERSIONINFOEXW;
type OSVERSIONINFOEX = windows_sys::Win32::System::SystemInformation::OSVERSIONINFOEXW;

pub fn get() -> Info {
let (version, edition) = version();
Expand Down Expand Up @@ -72,13 +65,8 @@ fn bitness() -> Bitness {

#[cfg(target_pointer_width = "32")]
fn bitness() -> Bitness {
use winapi::{
shared::{
minwindef::{BOOL, FALSE, PBOOL},
ntdef::HANDLE,
},
um::processthreadsapi::GetCurrentProcess,
};
use windows_sys::Win32::Foundation::{BOOL, FALSE, HANDLE};
use windows_sys::Win32::System::Threading::GetCurrentProcess;

// IsWow64Process is not available on all supported versions of Windows. Use GetModuleHandle to
// get a handle to the DLL that contains the function and GetProcAddress to get a pointer to the
Expand All @@ -88,7 +76,7 @@ fn bitness() -> Bitness {
Some(val) => val,
};

type IsWow64 = unsafe extern "system" fn(HANDLE, PBOOL) -> BOOL;
type IsWow64 = unsafe extern "system" fn(HANDLE, *mut BOOL) -> BOOL;
let is_wow_64: IsWow64 = unsafe { mem::transmute(is_wow_64) };

let mut result = FALSE;
Expand Down Expand Up @@ -116,7 +104,7 @@ fn version_info() -> Option<OSVERSIONINFOEX> {
let rtl_get_version: RtlGetVersion = unsafe { mem::transmute(rtl_get_version) };

let mut info: OSVERSIONINFOEX = unsafe { mem::zeroed() };
info.dwOSVersionInfoSize = mem::size_of::<OSVERSIONINFOEX>() as DWORD;
info.dwOSVersionInfoSize = mem::size_of::<OSVERSIONINFOEX>() as u32;

if unsafe { rtl_get_version(&mut info) } == STATUS_SUCCESS {
Some(info)
Expand All @@ -126,13 +114,11 @@ fn version_info() -> Option<OSVERSIONINFOEX> {
}

fn product_name(info: &OSVERSIONINFOEX) -> Option<String> {
const REG_SUCCESS: LSTATUS = ERROR_SUCCESS as LSTATUS;

let sub_key = to_wide("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
let mut key = ptr::null_mut();
let mut key = Default::default();
if unsafe { RegOpenKeyExW(HKEY_LOCAL_MACHINE, sub_key.as_ptr(), 0, KEY_READ, &mut key) }
!= REG_SUCCESS
|| key.is_null()
!= ERROR_SUCCESS
|| key == 0
{
log::error!("RegOpenKeyExW(HKEY_LOCAL_MACHINE, ...) failed");
return None;
Expand All @@ -146,8 +132,8 @@ fn product_name(info: &OSVERSIONINFOEX) -> Option<String> {
} else {
"ProductName"
});
let mut data_type: DWORD = 0;
let mut data_size: DWORD = 0;
let mut data_type = 0;
let mut data_size = 0;
if unsafe {
RegQueryValueExW(
key,
Expand All @@ -157,7 +143,7 @@ fn product_name(info: &OSVERSIONINFOEX) -> Option<String> {
ptr::null_mut(),
&mut data_size,
)
} != REG_SUCCESS
} != ERROR_SUCCESS
|| data_type != REG_SZ
|| data_size == 0
|| data_size % 2 != 0
Expand All @@ -174,10 +160,10 @@ fn product_name(info: &OSVERSIONINFOEX) -> Option<String> {
name.as_ptr(),
ptr::null_mut(),
ptr::null_mut(),
data.as_mut_ptr() as LPBYTE,
data.as_mut_ptr().cast(),
&mut data_size,
)
} != REG_SUCCESS
} != ERROR_SUCCESS
|| data_size as usize != data.len() * 2
{
return None;
Expand All @@ -203,7 +189,7 @@ fn product_name(info: &OSVERSIONINFOEX) -> Option<String> {
}
}

fn to_wide(value: &str) -> Vec<WCHAR> {
fn to_wide(value: &str) -> Vec<u16> {
OsStr::new(value).encode_wide().chain(Some(0)).collect()
}

Expand All @@ -213,7 +199,7 @@ fn edition(version_info: &OSVERSIONINFOEX) -> Option<String> {
match (
version_info.dwMajorVersion,
version_info.dwMinorVersion,
version_info.wProductType,
version_info.wProductType as u32,
) {
// Windows 10.
(10, 0, VER_NT_WORKSTATION) => {
Expand All @@ -240,12 +226,13 @@ fn edition(version_info: &OSVERSIONINFOEX) -> Option<String> {
let mut info: SYSTEM_INFO = unsafe { mem::zeroed() };
unsafe { GetSystemInfo(&mut info) };

if Into::<DWORD>::into(version_info.wSuiteMask) & VER_SUITE_WH_SERVER
if Into::<u32>::into(version_info.wSuiteMask) & VER_SUITE_WH_SERVER
== VER_SUITE_WH_SERVER
{
Some("Windows Home Server")
} else if version_info.wProductType == VER_NT_WORKSTATION
&& unsafe { info.u.s().wProcessorArchitecture } == PROCESSOR_ARCHITECTURE_AMD64
} else if version_info.wProductType == VER_NT_WORKSTATION as u8
&& unsafe { info.Anonymous.Anonymous.wProcessorArchitecture }
== PROCESSOR_ARCHITECTURE_AMD64
{
Some("Windows XP Professional x64 Edition")
} else {
Expand All @@ -267,16 +254,16 @@ fn get_proc_address(module: &[u8], proc: &[u8]) -> Option<FARPROC> {
"Procedure name should be zero-terminated"
);

let handle = unsafe { GetModuleHandleA(module.as_ptr() as LPCSTR) };
if handle.is_null() {
let handle = unsafe { GetModuleHandleA(module.as_ptr()) };
if handle == 0 {
log::error!(
"GetModuleHandleA({}) failed",
String::from_utf8_lossy(module)
);
return None;
}

unsafe { Some(GetProcAddress(handle, proc.as_ptr() as LPCSTR)) }
unsafe { Some(GetProcAddress(handle, proc.as_ptr())) }
}

#[cfg(test)]
Expand Down Expand Up @@ -321,7 +308,7 @@ mod tests {
for &(major, minor, product_type, expected_edition) in &test_data {
info.dwMajorVersion = major;
info.dwMinorVersion = minor;
info.wProductType = product_type;
info.wProductType = product_type as u8;

let edition = edition(&info).unwrap();
assert_eq!(edition, expected_edition);
Expand Down

0 comments on commit 34c12c7

Please sign in to comment.