| 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"), |
| )) |
| } |