#![allow(non_camel_case_types, non_snake_case)]
use crate::co;
use crate::decl::*;
use crate::guard::*;
use crate::kernel::privs::*;
use crate::version::ffi;
handle! { HVERSIONINFO;
}
impl HVERSIONINFO {
#[must_use]
pub fn GetFileVersionInfo(file_name: &str) -> SysResult<VersionInfoGuard> {
let block_sz = Self::GetFileVersionInfoSize(file_name)?;
let mut hglobal =
HGLOBAL::GlobalAlloc(co::GMEM::FIXED | co::GMEM::ZEROINIT, block_sz as _)?;
let hglobal_ptr = hglobal.leak();
BoolRet(unsafe {
ffi::GetFileVersionInfoW(
WString::from_str(file_name).as_ptr(),
0,
block_sz,
hglobal_ptr.ptr(),
)
})
.to_sysresult()
.map(|_| unsafe {
VersionInfoGuard::new(
HVERSIONINFO::from_ptr(hglobal_ptr.ptr()), )
})
}
#[must_use]
pub fn GetFileVersionInfoSize(file_name: &str) -> SysResult<u32> {
let mut dw_handle = 0u32;
match unsafe {
ffi::GetFileVersionInfoSizeW(WString::from_str(file_name).as_ptr(), &mut dw_handle)
} {
0 => Err(GetLastError()),
sz => Ok(sz),
}
}
#[must_use]
pub fn langs_and_cps(&self) -> SysResult<&[(LANGID, co::CP)]> {
unsafe {
self.VerQueryValue::<(LANGID, co::CP)>("\\VarFileInfo\\Translation")
.map(|(pblocks, sz)| {
std::slice::from_raw_parts(
pblocks,
sz as usize / std::mem::size_of::<(LANGID, co::CP)>(),
)
})
}
}
#[must_use]
pub unsafe fn VerQueryValue<T>(&self, sub_block: &str) -> SysResult<(*const T, u32)> {
let mut lp_lp_buffer = std::ptr::null();
let mut pu_len = 0;
BoolRet(unsafe {
ffi::VerQueryValueW(
self.ptr(),
WString::from_str(sub_block).as_ptr(),
pvoid(&mut lp_lp_buffer),
&mut pu_len,
)
})
.to_sysresult()
.map(|_| (lp_lp_buffer as *const T, pu_len))
}
#[must_use]
pub fn str_val(&self, lang_and_cp: (LANGID, co::CP), name: &str) -> SysResult<String> {
unsafe {
self.VerQueryValue::<u16>(&format!(
"\\StringFileInfo\\{:04x}{:04x}\\{}",
u16::from(lang_and_cp.0),
u16::from(lang_and_cp.1),
name
))
.map(|(pstr, len)| {
WString::from_wchars_slice(std::slice::from_raw_parts(pstr, len as _)).to_string()
})
}
}
#[must_use]
pub fn version_info(&self) -> SysResult<&VS_FIXEDFILEINFO> {
unsafe {
self.VerQueryValue::<VS_FIXEDFILEINFO>("\\")
.map(|(p, _)| &*p)
}
}
}