1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
use crate::c_wide_string::CWideStr;
use crate::c_wide_string::CWideString;
use skylight::HResult;
use std::convert::TryInto;
use winapi::shared::minwindef::MAX_PATH;
use winapi::um::fileapi::GetFullPathNameW;
pub fn get_full_path_name(input_path: &CWideStr) -> Result<(CWideString, Option<usize>), HResult> {
let mut path = Vec::with_capacity(MAX_PATH);
let mut file_part = std::ptr::null_mut();
let mut size = MAX_PATH as u32;
loop {
size = unsafe {
GetFullPathNameW(input_path.as_ptr(), size, path.as_mut_ptr(), &mut file_part)
};
if size == 0 {
return Err(HResult::get_last_error());
}
let size_usize: usize = size.try_into().expect("path len cannot fit in a usize");
if size_usize < MAX_PATH {
unsafe {
path.set_len(size_usize + 1);
}
let filename_offset = if !file_part.is_null() {
let diff = file_part as usize - path.as_ptr() as usize;
Some(diff / 2)
} else {
None
};
let ret = CWideString::from_vec_with_nul(path).expect("path contained interior NULs");
return Ok((ret, filename_offset));
}
path.reserve(size_usize);
}
}