#![doc = include_str!("../readme.md")]
#![cfg(windows)]
#![cfg_attr(not(test), no_std)]
mod bindings;
use bindings::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct OsVersion {
pub major: u32,
pub minor: u32,
pub pack: u32,
pub build: u32,
}
impl OsVersion {
pub const fn new(major: u32, minor: u32, pack: u32, build: u32) -> Self {
Self {
major,
minor,
pack,
build,
}
}
#[cfg(not(test))]
pub fn current() -> Self {
let mut info = OSVERSIONINFOEXW::new();
unsafe {
RtlGetVersion(&mut info as *mut _ as *mut _);
}
OsVersion {
major: info.dwMajorVersion,
minor: info.dwMinorVersion,
pack: info.wServicePackMajor as u32,
build: info.dwBuildNumber,
}
}
#[cfg(test)]
fn current() -> Self {
test::test_current()
}
}
pub fn is_server() -> bool {
let mut info = OSVERSIONINFOEXW::new();
unsafe {
RtlGetVersion(&mut info as *mut _ as *mut _);
}
info.wProductType as u32 != VER_NT_WORKSTATION
}
impl OSVERSIONINFOEXW {
fn new() -> Self {
Self {
dwOSVersionInfoSize: core::mem::size_of::<Self>() as u32,
..Default::default()
}
}
}
#[cfg(test)]
mod test {
use super::OsVersion;
use std::sync::RwLock;
static TEST_CURRENT: RwLock<OsVersion> = RwLock::new(OsVersion::new(0, 0, 0, 0));
pub fn test_current() -> OsVersion {
*TEST_CURRENT.read().unwrap()
}
fn set_current(version: OsVersion) {
*TEST_CURRENT.write().unwrap() = version;
}
#[test]
fn test() {
assert_eq!(OsVersion::current(), OsVersion::new(0, 0, 0, 0));
set_current(OsVersion::new(1, 2, 3, 4));
assert_eq!(OsVersion::current(), OsVersion::new(1, 2, 3, 4));
set_current(OsVersion::new(10, 0, 0, 0));
assert!(OsVersion::current() >= OsVersion::new(9, 0, 0, 0));
assert!(OsVersion::current() >= OsVersion::new(10, 0, 0, 0));
assert!(!(OsVersion::current() >= OsVersion::new(11, 0, 0, 0)));
set_current(OsVersion::new(10, 100, 0, 0));
assert!(OsVersion::current() >= OsVersion::new(10, 99, 0, 0));
assert!(OsVersion::current() >= OsVersion::new(10, 100, 0, 0));
assert!(!(OsVersion::current() >= OsVersion::new(10, 101, 0, 0)));
set_current(OsVersion::new(10, 100, 1000, 0));
assert!(OsVersion::current() >= OsVersion::new(10, 100, 999, 0));
assert!(OsVersion::current() >= OsVersion::new(10, 100, 1000, 0));
assert!(!(OsVersion::current() >= OsVersion::new(10, 100, 1001, 0)));
set_current(OsVersion::new(10, 100, 1_000, 10_000));
assert!(OsVersion::current() >= OsVersion::new(10, 100, 1_000, 9_999));
assert!(OsVersion::current() >= OsVersion::new(10, 100, 1_000, 10_000));
assert!(!(OsVersion::current() >= OsVersion::new(10, 100, 1_000, 10_001)));
}
}