blob: b5d0933173cfc5156529225875fe355f8a8070cf [file] [log] [blame]
use std::ffi::OsString;
use std::mem;
use std::os::windows::ffi::OsStrExt;
use std::os::windows::ffi::OsStringExt;
use std::path::Path;
use windows_sys::Win32::UI::Shell::SHGetFileInfoW;
use windows_sys::Win32::UI::Shell::SHFILEINFOW;
use windows_sys::Win32::UI::Shell::SHGFI_DISPLAYNAME;
pub(crate) fn name(path: &Path) -> Option<OsString> {
let mut path: Vec<_> = path.as_os_str().encode_wide().collect();
if path.contains(&0) {
return None;
}
path.push(0);
let mut path_info = SHFILEINFOW {
hIcon: 0,
iIcon: 0,
dwAttributes: 0,
szDisplayName: [0; 260],
szTypeName: [0; 80],
};
let result = unsafe {
SHGetFileInfoW(
path.as_ptr(),
0,
&mut path_info,
mem::size_of_val(&path_info)
.try_into()
.expect("path information too large for WinAPI"),
SHGFI_DISPLAYNAME,
)
};
if result == 0 {
return None;
}
// The display name buffer has a fixed length, so it must be truncated at
// the first null character.
Some(OsString::from_wide(
path_info
.szDisplayName
.split(|&x| x == 0)
.next()
.expect("missing null byte in display name"),
))
}