blob: 7ac1f8122f781ce5e2a5a5bf04cbb12caa219851 [file] [log] [blame]
use crate::io;
use crate::sys::c;
use crate::path::PathBuf;
use crate::fs::{OpenOptions, File};
use crate::sys::ext::fs::OpenOptionsExt;
use crate::sys::handle::Handle;
use libc::c_char;
use super::super::{fill_utf16_buf, os2path, to_u16s, wide_char_to_multi_byte};
fn query_full_process_image_name() -> io::Result<PathBuf> {
unsafe {
let process_handle = Handle::new(c::OpenProcess(c::PROCESS_QUERY_INFORMATION,
c::FALSE,
c::GetCurrentProcessId()));
fill_utf16_buf(|buf, mut sz| {
if c::QueryFullProcessImageNameW(process_handle.raw(), 0, buf, &mut sz) == 0 {
0
} else {
sz
}
}, os2path)
}
}
fn lock_and_get_executable_filename() -> io::Result<(PathBuf, File)> {
// We query the current image name, open the file without FILE_SHARE_DELETE so it
// can't be moved and then get the current image name again. If the names are the
// same than we have successfully locked the file
let image_name1 = query_full_process_image_name()?;
let file = OpenOptions::new()
.read(true)
.share_mode(c::FILE_SHARE_READ | c::FILE_SHARE_WRITE)
.open(&image_name1)?;
let image_name2 = query_full_process_image_name()?;
if image_name1 != image_name2 {
return Err(io::Error::new(io::ErrorKind::Other,
"executable moved while trying to lock it"));
}
Ok((image_name1, file))
}
// Get the executable filename for libbacktrace
// This returns the path in the ANSI code page and a File which should remain open
// for as long as the path should remain valid
pub fn get_executable_filename() -> io::Result<(Vec<c_char>, File)> {
let (executable, file) = lock_and_get_executable_filename()?;
let u16_executable = to_u16s(executable.into_os_string())?;
Ok((wide_char_to_multi_byte(c::CP_ACP, c::WC_NO_BEST_FIT_CHARS,
&u16_executable, true)?, file))
}