1pub fn get_file_version(file_name: &str) -> Option<(u32, u32, u32, u32)> {
12 use winapi::um::winver::{GetFileVersionInfoSizeW, GetFileVersionInfoW, VerQueryValueW};
13
14 #[allow(non_snake_case)]
15 #[repr(C)]
16 struct VS_FIXEDFILEINFO {
17 pub dwSignature: u32,
18 pub dwStrucVersion: u32,
19 pub dwFileVersionMS: u32,
20 pub dwFileVersionLS: u32,
21 pub dwProductVersionMS: u32,
22 pub dwProductVersionLS: u32,
23 pub dwFileFlagsMask: u32,
24 pub dwFileFlags: u32,
25 pub dwFileOS: i32,
26 pub dwFileType: i32,
27 pub dwFileSubtype: i32,
28 pub dwFileDateMS: u32,
29 pub dwFileDateLS: u32,
30 }
31
32 unsafe {
33 let filename = to_wide(file_name);
34
35 let mut handle = 0;
36 let size = GetFileVersionInfoSizeW(filename.as_ptr(), &mut handle);
37
38 if size == 0 {
39 return None;
40 }
41
42 let mut buf = vec![0u8; size as usize];
43 let pbuf = buf.as_mut_ptr() as *mut _;
44
45 if GetFileVersionInfoW(filename.as_ptr(), 0, size, pbuf) == 0 {
46 return None;
47 }
48
49 let mut pinfo: winapi::um::winnt::PVOID = std::ptr::null_mut();
50 let mut length = 0;
51
52 let path: Vec<u16> = to_wide("\\");
53
54 if VerQueryValueW(pbuf, path.as_ptr(), &mut pinfo, &mut length) == 0 {
55 return None;
56 }
57
58 let info = &*(pinfo as *const VS_FIXEDFILEINFO);
59
60 let v1 = info.dwFileVersionMS >> 16 & 0xFFFF;
61 let v2 = info.dwFileVersionMS >> 0 & 0xFFFF;
62 let v3 = info.dwFileVersionLS >> 16 & 0xFFFF;
63 let v4 = info.dwFileVersionLS >> 0 & 0xFFFF;
64 return Some((v1, v2, v3, v4));
65 }
66}
67
68fn to_wide(s: &str) -> Vec<u16> {
69 use std::{ffi::OsStr, iter::once, os::windows::prelude::OsStrExt};
70
71 OsStr::new(s).encode_wide().chain(once(0)).collect()
72}