#![cfg(windows)]
use std::ffi::CString;
use std::sync::OnceLock;
use windows_sys::Win32::Foundation::HMODULE;
use windows_sys::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryW};
pub(super) const WIN11_BUILD: u32 = 22000;
#[repr(C)]
struct RtlOsVersionInfoW {
dw_os_version_info_size: u32,
dw_major_version: u32,
dw_minor_version: u32,
dw_build_number: u32,
dw_platform_id: u32,
sz_csd_version: [u16; 128],
}
type RtlGetVersionFn = unsafe extern "system" fn(*mut RtlOsVersionInfoW) -> i32;
static BUILD_NUMBER: OnceLock<u32> = OnceLock::new();
pub(super) fn build_number() -> u32 {
*BUILD_NUMBER.get_or_init(|| unsafe {
let ntdll_name: Vec<u16> = "ntdll.dll\0".encode_utf16().collect();
let ntdll: HMODULE = LoadLibraryW(ntdll_name.as_ptr());
if ntdll.is_null() {
return 0;
}
let sym = CString::new("RtlGetVersion").expect("static literal contains no NUL");
let proc = GetProcAddress(ntdll, sym.as_ptr() as *const u8);
let Some(addr) = proc else {
return 0;
};
let rtl_get_version: RtlGetVersionFn = std::mem::transmute(addr);
let mut info: RtlOsVersionInfoW = std::mem::zeroed();
info.dw_os_version_info_size = std::mem::size_of::<RtlOsVersionInfoW>() as u32;
let status = rtl_get_version(&mut info);
if status != 0 {
return 0;
}
info.dw_build_number
})
}
pub(super) fn is_win11_or_newer() -> bool {
build_number() >= WIN11_BUILD
}