winbrew_windows\system/
version.rs1use winreg::{RegKey, enums::HKEY_LOCAL_MACHINE};
2
3const WINDOWS_CURRENT_VERSION_KEY: &str = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
4const CURRENT_MAJOR_VERSION_NUMBER: &str = "CurrentMajorVersionNumber";
5const CURRENT_MINOR_VERSION_NUMBER: &str = "CurrentMinorVersionNumber";
6const CURRENT_VERSION: &str = "CurrentVersion";
7const CURRENT_BUILD_NUMBER: &str = "CurrentBuildNumber";
8const CURRENT_BUILD: &str = "CurrentBuild";
9const UBR: &str = "UBR";
10
11pub fn windows_version_string() -> Option<String> {
13 let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
14 let Ok(current_version_key) = hklm.open_subkey(WINDOWS_CURRENT_VERSION_KEY) else {
15 return None;
16 };
17
18 let major = current_version_key
19 .get_value::<u32, _>(CURRENT_MAJOR_VERSION_NUMBER)
20 .ok();
21 let minor = current_version_key
22 .get_value::<u32, _>(CURRENT_MINOR_VERSION_NUMBER)
23 .ok();
24 let prefix = match (major, minor) {
25 (Some(major), Some(minor)) => format!("{major}.{minor}"),
26 _ => current_version_key
27 .get_value::<String, _>(CURRENT_VERSION)
28 .ok()?
29 .trim()
30 .to_string(),
31 };
32
33 let build = current_version_key
34 .get_value::<String, _>(CURRENT_BUILD_NUMBER)
35 .ok()
36 .or_else(|| {
37 current_version_key
38 .get_value::<String, _>(CURRENT_BUILD)
39 .ok()
40 })?;
41
42 let ubr = current_version_key.get_value::<u32, _>(UBR).ok();
43
44 format_windows_version(&prefix, &build, ubr)
45}
46
47fn format_windows_version(prefix: &str, build: &str, ubr: Option<u32>) -> Option<String> {
48 let prefix = prefix.trim();
49 let build = build.trim();
50
51 if prefix.is_empty() || build.is_empty() {
52 return None;
53 }
54
55 let mut version = format!("{prefix}.{build}");
56 if let Some(ubr) = ubr {
57 version.push('.');
58 version.push_str(&ubr.to_string());
59 }
60
61 Some(version)
62}
63
64#[cfg(test)]
65mod tests {
66 use super::format_windows_version;
67
68 #[test]
69 fn formats_windows_version_strings() {
70 assert_eq!(
71 format_windows_version("10.0", "26200", Some(8246)),
72 Some("10.0.26200.8246".to_string())
73 );
74 assert_eq!(
75 format_windows_version("6.3", "9600", None),
76 Some("6.3.9600".to_string())
77 );
78 assert_eq!(format_windows_version("", "9600", Some(1)), None);
79 assert_eq!(format_windows_version("10.0", "", Some(1)), None);
80 }
81}