diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2021-01-28 21:42:16 +0000 |
|---|---|---|
| committer | Emīls Piņķis <emils@mullvad.net> | 2021-01-29 14:22:01 +0000 |
| commit | 067f9bc6c599d774a5807a940ca896f9c5866912 (patch) | |
| tree | 2e062f270a30a880c7a1702e8310c86a49f6a7e1 | |
| parent | 77e2bd23662edbc5cff2c4c747fe75e80c726299 (diff) | |
| download | mullvadvpn-067f9bc6c599d774a5807a940ca896f9c5866912.tar.xz mullvadvpn-067f9bc6c599d774a5807a940ca896f9c5866912.zip | |
Change version info on Windows
| -rw-r--r-- | Cargo.lock | 2 | ||||
| -rw-r--r-- | talpid-platform-metadata/Cargo.toml | 3 | ||||
| -rw-r--r-- | talpid-platform-metadata/src/lib.rs | 3 | ||||
| -rw-r--r-- | talpid-platform-metadata/src/windows.rs | 122 |
4 files changed, 91 insertions, 39 deletions
diff --git a/Cargo.lock b/Cargo.lock index 5745394850..a15f06b68e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2609,6 +2609,8 @@ version = "0.1.0" dependencies = [ "rs-release", "talpid-dbus", + "utf16_lit", + "winapi 0.3.9", ] [[package]] diff --git a/talpid-platform-metadata/Cargo.toml b/talpid-platform-metadata/Cargo.toml index d922adf865..d75ae1c3f1 100644 --- a/talpid-platform-metadata/Cargo.toml +++ b/talpid-platform-metadata/Cargo.toml @@ -11,3 +11,6 @@ publish = false [target.'cfg(target_os = "linux")'.dependencies] rs-release = "0.1.7" talpid-dbus = { path = "../talpid-dbus" } + +[target.'cfg(target_os = "windows")'.dependencies] +winapi = { version = "0.3.6", features = ["winbase"] } diff --git a/talpid-platform-metadata/src/lib.rs b/talpid-platform-metadata/src/lib.rs index f4ba78eaeb..5fd43e62d4 100644 --- a/talpid-platform-metadata/src/lib.rs +++ b/talpid-platform-metadata/src/lib.rs @@ -15,3 +15,6 @@ mod imp; mod imp; pub use self::imp::{extra_metadata, short_version, version}; + +#[cfg(target_os = "windows")] +pub use self::imp::WindowsVersion; diff --git a/talpid-platform-metadata/src/windows.rs b/talpid-platform-metadata/src/windows.rs index 41faf0099b..0222f63221 100644 --- a/talpid-platform-metadata/src/windows.rs +++ b/talpid-platform-metadata/src/windows.rs @@ -1,54 +1,98 @@ -use std::collections::HashMap; - -mod command; -use command::command_stdout_lossy; +use std::{ + ffi::OsString, + io, iter, + mem::{self, MaybeUninit}, + os::windows::ffi::OsStrExt, + ptr, +}; +use winapi::um::{ + libloaderapi::{GetModuleHandleW, GetProcAddress}, + winnt::RTL_OSVERSIONINFOW, +}; pub fn version() -> String { - let system_info = system_info(); - let os_name = system_info.get("OS Name"); - let os_version = system_info.get("OS Version"); - let version = os_name.map(parse_version).unwrap_or(String::from("N/A")); - let full_version = os_version - .map(parse_full_version) - .unwrap_or(String::from("N/A")); - format!("Windows {} ({})", version, full_version) + let (major, minor, build) = WindowsVersion::new() + .map(|version_info| { + ( + version_info.major_version().to_string(), + version_info.minor_version().to_string(), + version_info.build_number().to_string(), + ) + }) + .unwrap_or_else(|_| ("N/A".to_string(), "N/A".to_string(), "N/A".to_string())); + + format!("Windows {}.{} Build {}", major, minor, build) } pub fn short_version() -> String { - let system_info = system_info(); - let os_name = system_info.get("OS Name"); - let version = os_name.map(parse_version).unwrap_or(String::from("N/A")); - format!("Windows {}", version) + let version_string = WindowsVersion::new() + .map(|version| version.major_version().to_string()) + .unwrap_or("N/A".into()); + format!("Windows {}", version_string) } -fn system_info() -> HashMap<String, String> { - let system_info = - command_stdout_lossy("systeminfo", &["/FO", "LIST"]).unwrap_or_else(String::new); +pub fn extra_metadata() -> impl Iterator<Item = (String, String)> { + std::iter::empty() +} - let mut info_map = HashMap::new(); - system_info.lines().for_each(|line| { - let mut split = line.split(":"); - if let Some(key) = split.next() { - if let Some(value) = split.next() { - info_map.insert(key.to_owned(), value.to_owned()); - } - } - }); - info_map +pub struct WindowsVersion { + inner: RTL_OSVERSIONINFOW, } -fn parse_version(os_name: &String) -> String { - os_name - .trim() - .trim_start_matches("Microsoft Windows ") - .to_owned() -} +impl WindowsVersion { + pub fn new() -> Result<WindowsVersion, io::Error> { + let module_name: Vec<u16> = OsString::from("ntdll") + .as_os_str() + .encode_wide() + .chain(iter::once(0u16)) + .collect(); + + + let ntdll = unsafe { GetModuleHandleW(module_name.as_ptr()) }; + if ntdll == ptr::null_mut() { + return Err(io::Error::last_os_error()); + } -fn parse_full_version(os_version: &String) -> String { - os_version.trim().to_owned() + let function_address = + unsafe { GetProcAddress(ntdll, b"RtlGetVersion\0" as *const _ as *const i8) }; + if function_address == ptr::null_mut() { + return Err(io::Error::last_os_error()); + } + + let rtl_get_version: extern "stdcall" fn(*mut RTL_OSVERSIONINFOW) = + unsafe { *(&function_address as *const _ as *const _) }; + + let mut version_info: MaybeUninit<RTL_OSVERSIONINFOW> = mem::MaybeUninit::zeroed(); + unsafe { + (*version_info.as_mut_ptr()).dwOSVersionInfoSize = + mem::size_of_val(&version_info) as u32; + rtl_get_version(version_info.as_mut_ptr()); + + Ok(WindowsVersion { + inner: version_info.assume_init(), + }) + } + } + + pub fn major_version(&self) -> u32 { + self.inner.dwMajorVersion + } + + pub fn minor_version(&self) -> u32 { + self.inner.dwMinorVersion + } + + pub fn build_number(&self) -> u32 { + self.inner.dwBuildNumber + } } -pub fn extra_metadata() -> impl Iterator<Item = (String, String)> { - std::iter::empty() +#[cfg(test)] +mod test { + use super::*; + #[test] + fn test_windows_version() { + WindowsVersion::new().unwrap(); + } } |
