Auto merge of #106610 - euclio:windows-rs, r=ChrisDenton
migrate compiler, bootstrap and compiletest to windows-rs This PR migrates the compiler, bootstrap, and compiletest to use [windows-rs](https://github.com/microsoft/windows-rs) instead of winapi-rs. windows-rs is the bindings crate provided by Microsoft, and is actively maintained compared to winapi-rs. Not all ecosystem crates have migrated over yet, so there will be a period of time where both crates are used. windows-rs also provides some nice ergonomics over winapi-rs to convert return values to `Result`s (which found a case where we forgot to check the return value of `CreateFileW`).
This commit is contained in:
commit
44f5180584
53
Cargo.lock
53
Cargo.lock
@ -898,7 +898,7 @@ dependencies = [
|
||||
"tracing-subscriber",
|
||||
"unified-diff",
|
||||
"walkdir",
|
||||
"winapi",
|
||||
"windows 0.46.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2273,7 +2273,7 @@ dependencies = [
|
||||
"dirs",
|
||||
"gix-path",
|
||||
"libc",
|
||||
"windows",
|
||||
"windows 0.43.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4529,7 +4529,7 @@ dependencies = [
|
||||
"tempfile",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
"winapi",
|
||||
"windows 0.46.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4588,7 +4588,7 @@ dependencies = [
|
||||
"rustc_ty_utils",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
"winapi",
|
||||
"windows 0.46.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4636,7 +4636,7 @@ dependencies = [
|
||||
"termize",
|
||||
"tracing",
|
||||
"unicode-width",
|
||||
"winapi",
|
||||
"windows 0.46.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5277,7 +5277,7 @@ dependencies = [
|
||||
"smallvec",
|
||||
"termize",
|
||||
"tracing",
|
||||
"winapi",
|
||||
"windows 0.46.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6908,6 +6908,15 @@ dependencies = [
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
@ -6934,9 +6943,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.1"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
@ -6949,45 +6958,45 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.1"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.1"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.1"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.1"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.1"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.1"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.1"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
|
@ -36,8 +36,15 @@ elsa = "1.8"
|
||||
[dependencies.parking_lot]
|
||||
version = "0.11"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["fileapi", "psapi", "winerror"] }
|
||||
[target.'cfg(windows)'.dependencies.windows]
|
||||
version = "0.46.0"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_System_IO",
|
||||
"Win32_System_ProcessStatus",
|
||||
"Win32_System_Threading",
|
||||
]
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
memmap2 = "0.2.1"
|
||||
|
@ -4,9 +4,6 @@
|
||||
//! green/native threading. This is just a bare-bones enough solution for
|
||||
//! librustdoc, it is not production quality at all.
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(nonstandard_style)]
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_os = "linux")] {
|
||||
mod linux;
|
||||
@ -16,7 +13,7 @@
|
||||
use unix as imp;
|
||||
} else if #[cfg(windows)] {
|
||||
mod windows;
|
||||
use windows as imp;
|
||||
use self::windows as imp;
|
||||
} else {
|
||||
mod unsupported;
|
||||
use unsupported as imp;
|
||||
|
@ -1,13 +1,16 @@
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::os::windows::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
use winapi::shared::winerror::ERROR_INVALID_FUNCTION;
|
||||
use winapi::um::fileapi::LockFileEx;
|
||||
use winapi::um::minwinbase::{LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, OVERLAPPED};
|
||||
use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
|
||||
use windows::{
|
||||
Win32::Foundation::{ERROR_INVALID_FUNCTION, HANDLE},
|
||||
Win32::Storage::FileSystem::{
|
||||
LockFileEx, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, LOCKFILE_EXCLUSIVE_LOCK,
|
||||
LOCKFILE_FAIL_IMMEDIATELY, LOCK_FILE_FLAGS,
|
||||
},
|
||||
Win32::System::IO::OVERLAPPED,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lock {
|
||||
@ -25,7 +28,7 @@ pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lo
|
||||
let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
|
||||
let mut open_options = OpenOptions::new();
|
||||
open_options.read(true).share_mode(share_mode);
|
||||
open_options.read(true).share_mode(share_mode.0);
|
||||
|
||||
if create {
|
||||
open_options.create(true).write(true);
|
||||
@ -43,33 +46,42 @@ pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lo
|
||||
}
|
||||
};
|
||||
|
||||
let ret = unsafe {
|
||||
let mut overlapped: OVERLAPPED = mem::zeroed();
|
||||
|
||||
let mut dwFlags = 0;
|
||||
if !wait {
|
||||
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
|
||||
}
|
||||
|
||||
if exclusive {
|
||||
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
||||
}
|
||||
|
||||
debug!("attempting to acquire lock on lock file `{}`", p.display());
|
||||
LockFileEx(file.as_raw_handle(), dwFlags, 0, 0xFFFF_FFFF, 0xFFFF_FFFF, &mut overlapped)
|
||||
};
|
||||
if ret == 0 {
|
||||
let err = io::Error::last_os_error();
|
||||
debug!("failed acquiring file lock: {}", err);
|
||||
Err(err)
|
||||
} else {
|
||||
debug!("successfully acquired lock");
|
||||
Ok(Lock { _file: file })
|
||||
let mut flags = LOCK_FILE_FLAGS::default();
|
||||
if !wait {
|
||||
flags |= LOCKFILE_FAIL_IMMEDIATELY;
|
||||
}
|
||||
|
||||
if exclusive {
|
||||
flags |= LOCKFILE_EXCLUSIVE_LOCK;
|
||||
}
|
||||
|
||||
let mut overlapped = OVERLAPPED::default();
|
||||
|
||||
debug!("attempting to acquire lock on lock file `{}`", p.display());
|
||||
|
||||
unsafe {
|
||||
LockFileEx(
|
||||
HANDLE(file.as_raw_handle() as isize),
|
||||
flags,
|
||||
0,
|
||||
u32::MAX,
|
||||
u32::MAX,
|
||||
&mut overlapped,
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
.map_err(|e| {
|
||||
let err = io::Error::from_raw_os_error(e.code().0);
|
||||
debug!("failed acquiring file lock: {}", err);
|
||||
err
|
||||
})?;
|
||||
|
||||
debug!("successfully acquired lock");
|
||||
Ok(Lock { _file: file })
|
||||
}
|
||||
|
||||
pub fn error_unsupported(err: &io::Error) -> bool {
|
||||
err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
|
||||
err.raw_os_error() == Some(ERROR_INVALID_FUNCTION.0 as i32)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -796,21 +796,26 @@ fn get_thread_id() -> u32 {
|
||||
cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
pub fn get_resident_set_size() -> Option<usize> {
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::processthreadsapi::GetCurrentProcess;
|
||||
use winapi::um::psapi::{GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS};
|
||||
use std::mem;
|
||||
|
||||
let mut pmc = MaybeUninit::<PROCESS_MEMORY_COUNTERS>::uninit();
|
||||
match unsafe {
|
||||
GetProcessMemoryInfo(GetCurrentProcess(), pmc.as_mut_ptr(), mem::size_of_val(&pmc) as DWORD)
|
||||
} {
|
||||
0 => None,
|
||||
_ => {
|
||||
let pmc = unsafe { pmc.assume_init() };
|
||||
Some(pmc.WorkingSetSize as usize)
|
||||
}
|
||||
use windows::{
|
||||
Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
|
||||
Win32::System::Threading::GetCurrentProcess,
|
||||
};
|
||||
|
||||
let mut pmc = PROCESS_MEMORY_COUNTERS::default();
|
||||
let pmc_size = mem::size_of_val(&pmc);
|
||||
unsafe {
|
||||
K32GetProcessMemoryInfo(
|
||||
GetCurrentProcess(),
|
||||
&mut pmc,
|
||||
pmc_size as u32,
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
.ok()?;
|
||||
|
||||
Some(pmc.WorkingSetSize)
|
||||
}
|
||||
} else if #[cfg(target_os = "macos")] {
|
||||
pub fn get_resident_set_size() -> Option<usize> {
|
||||
|
@ -54,8 +54,11 @@ rustc_hir_analysis = { path = "../rustc_hir_analysis" }
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
|
||||
[target.'cfg(windows)'.dependencies.windows]
|
||||
version = "0.46.0"
|
||||
features = [
|
||||
"Win32_System_Diagnostics_Debug",
|
||||
]
|
||||
|
||||
[features]
|
||||
llvm = ['rustc_interface/llvm']
|
||||
|
@ -1246,11 +1246,9 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||
interface::try_print_query_stack(&handler, num_frames);
|
||||
|
||||
#[cfg(windows)]
|
||||
unsafe {
|
||||
if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
|
||||
// Trigger a debugger if we crashed during bootstrap
|
||||
winapi::um::debugapi::DebugBreak();
|
||||
}
|
||||
if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
|
||||
// Trigger a debugger if we crashed during bootstrap
|
||||
unsafe { windows::Win32::System::Diagnostics::Debug::DebugBreak() };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,14 @@ termize = "0.1.1"
|
||||
serde = { version = "1.0.125", features = [ "derive" ] }
|
||||
serde_json = "1.0.59"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = [ "handleapi", "synchapi", "winbase" ] }
|
||||
[target.'cfg(windows)'.dependencies.windows]
|
||||
version = "0.46.0"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Security",
|
||||
"Win32_System_Threading",
|
||||
"Win32_System_WindowsProgramming",
|
||||
]
|
||||
|
||||
[features]
|
||||
rustc_use_parallel_compiler = ['rustc_error_messages/rustc_use_parallel_compiler']
|
||||
|
@ -16,10 +16,12 @@ pub fn acquire_global_lock(name: &str) -> Box<dyn Any> {
|
||||
use std::ffi::CString;
|
||||
use std::io;
|
||||
|
||||
use winapi::shared::ntdef::HANDLE;
|
||||
use winapi::um::handleapi::CloseHandle;
|
||||
use winapi::um::synchapi::{CreateMutexA, ReleaseMutex, WaitForSingleObject};
|
||||
use winapi::um::winbase::{INFINITE, WAIT_ABANDONED, WAIT_OBJECT_0};
|
||||
use windows::{
|
||||
core::PCSTR,
|
||||
Win32::Foundation::{CloseHandle, HANDLE, WAIT_ABANDONED, WAIT_OBJECT_0},
|
||||
Win32::System::Threading::{CreateMutexA, ReleaseMutex, WaitForSingleObject},
|
||||
Win32::System::WindowsProgramming::INFINITE,
|
||||
};
|
||||
|
||||
struct Handle(HANDLE);
|
||||
|
||||
@ -42,49 +44,38 @@ fn drop(&mut self) {
|
||||
}
|
||||
|
||||
let cname = CString::new(name).unwrap();
|
||||
unsafe {
|
||||
// Create a named mutex, with no security attributes and also not
|
||||
// acquired when we create it.
|
||||
//
|
||||
// This will silently create one if it doesn't already exist, or it'll
|
||||
// open up a handle to one if it already exists.
|
||||
let mutex = CreateMutexA(std::ptr::null_mut(), 0, cname.as_ptr());
|
||||
if mutex.is_null() {
|
||||
panic!(
|
||||
"failed to create global mutex named `{}`: {}",
|
||||
name,
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
let mutex = Handle(mutex);
|
||||
// Create a named mutex, with no security attributes and also not
|
||||
// acquired when we create it.
|
||||
//
|
||||
// This will silently create one if it doesn't already exist, or it'll
|
||||
// open up a handle to one if it already exists.
|
||||
let mutex = unsafe { CreateMutexA(None, false, PCSTR::from_raw(cname.as_ptr().cast())) }
|
||||
.unwrap_or_else(|_| panic!("failed to create global mutex named `{}`", name));
|
||||
let mutex = Handle(mutex);
|
||||
|
||||
// Acquire the lock through `WaitForSingleObject`.
|
||||
//
|
||||
// A return value of `WAIT_OBJECT_0` means we successfully acquired it.
|
||||
//
|
||||
// A return value of `WAIT_ABANDONED` means that the previous holder of
|
||||
// the thread exited without calling `ReleaseMutex`. This can happen,
|
||||
// for example, when the compiler crashes or is interrupted via ctrl-c
|
||||
// or the like. In this case, however, we are still transferred
|
||||
// ownership of the lock so we continue.
|
||||
//
|
||||
// If an error happens.. well... that's surprising!
|
||||
match WaitForSingleObject(mutex.0, INFINITE) {
|
||||
WAIT_OBJECT_0 | WAIT_ABANDONED => {}
|
||||
code => {
|
||||
panic!(
|
||||
"WaitForSingleObject failed on global mutex named \
|
||||
`{}`: {} (ret={:x})",
|
||||
name,
|
||||
io::Error::last_os_error(),
|
||||
code
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Return a guard which will call `ReleaseMutex` when dropped.
|
||||
Box::new(Guard(mutex))
|
||||
// Acquire the lock through `WaitForSingleObject`.
|
||||
//
|
||||
// A return value of `WAIT_OBJECT_0` means we successfully acquired it.
|
||||
//
|
||||
// A return value of `WAIT_ABANDONED` means that the previous holder of
|
||||
// the thread exited without calling `ReleaseMutex`. This can happen,
|
||||
// for example, when the compiler crashes or is interrupted via ctrl-c
|
||||
// or the like. In this case, however, we are still transferred
|
||||
// ownership of the lock so we continue.
|
||||
//
|
||||
// If an error happens.. well... that's surprising!
|
||||
match unsafe { WaitForSingleObject(mutex.0, INFINITE) } {
|
||||
WAIT_OBJECT_0 | WAIT_ABANDONED => (),
|
||||
err => panic!(
|
||||
"WaitForSingleObject failed on global mutex named `{}`: {} (ret={:x})",
|
||||
name,
|
||||
io::Error::last_os_error(),
|
||||
err.0
|
||||
),
|
||||
}
|
||||
|
||||
// Return a guard which will call `ReleaseMutex` when dropped.
|
||||
Box::new(Guard(mutex))
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
|
@ -24,5 +24,9 @@ termize = "0.1.1"
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["libloaderapi"] }
|
||||
[target.'cfg(windows)'.dependencies.windows]
|
||||
version = "0.46.0"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_System_LibraryLoader",
|
||||
]
|
||||
|
@ -87,35 +87,38 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::os::windows::prelude::*;
|
||||
use std::ptr;
|
||||
|
||||
use winapi::um::libloaderapi::{
|
||||
GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
use windows::{
|
||||
core::PCWSTR,
|
||||
Win32::Foundation::HINSTANCE,
|
||||
Win32::System::LibraryLoader::{
|
||||
GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
},
|
||||
};
|
||||
|
||||
let mut module = HINSTANCE::default();
|
||||
unsafe {
|
||||
let mut module = ptr::null_mut();
|
||||
let r = GetModuleHandleExW(
|
||||
GetModuleHandleExW(
|
||||
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
current_dll_path as usize as *mut _,
|
||||
PCWSTR(current_dll_path as *mut u16),
|
||||
&mut module,
|
||||
);
|
||||
if r == 0 {
|
||||
return Err(format!("GetModuleHandleExW failed: {}", io::Error::last_os_error()));
|
||||
}
|
||||
let mut space = Vec::with_capacity(1024);
|
||||
let r = GetModuleFileNameW(module, space.as_mut_ptr(), space.capacity() as u32);
|
||||
if r == 0 {
|
||||
return Err(format!("GetModuleFileNameW failed: {}", io::Error::last_os_error()));
|
||||
}
|
||||
let r = r as usize;
|
||||
if r >= space.capacity() {
|
||||
return Err(format!("our buffer was too small? {}", io::Error::last_os_error()));
|
||||
}
|
||||
space.set_len(r);
|
||||
let os = OsString::from_wide(&space);
|
||||
Ok(PathBuf::from(os))
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let mut filename = vec![0; 1024];
|
||||
let n = unsafe { GetModuleFileNameW(module, &mut filename) } as usize;
|
||||
if n == 0 {
|
||||
return Err(format!("GetModuleFileNameW failed: {}", io::Error::last_os_error()));
|
||||
}
|
||||
if n >= filename.capacity() {
|
||||
return Err(format!("our buffer was too small? {}", io::Error::last_os_error()));
|
||||
}
|
||||
|
||||
filename.truncate(n);
|
||||
|
||||
Ok(OsString::from_wide(&filename).into())
|
||||
}
|
||||
|
||||
pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
|
||||
|
@ -57,7 +57,7 @@ dependencies = [
|
||||
"tar",
|
||||
"toml",
|
||||
"walkdir",
|
||||
"winapi",
|
||||
"windows",
|
||||
"xz2",
|
||||
]
|
||||
|
||||
@ -720,6 +720,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
@ -736,46 +745,61 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.0"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.0"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
|
@ -59,18 +59,20 @@ sysinfo = { version = "0.26.0", optional = true }
|
||||
[target.'cfg(not(target_os = "solaris"))'.dependencies]
|
||||
fd-lock = "3.0.8"
|
||||
|
||||
[target.'cfg(windows)'.dependencies.winapi]
|
||||
version = "0.3"
|
||||
[target.'cfg(windows)'.dependencies.windows]
|
||||
version = "0.46.0"
|
||||
features = [
|
||||
"fileapi",
|
||||
"ioapiset",
|
||||
"jobapi2",
|
||||
"handleapi",
|
||||
"winioctl",
|
||||
"psapi",
|
||||
"impl-default",
|
||||
"timezoneapi",
|
||||
"winbase",
|
||||
"Win32_Foundation",
|
||||
"Win32_Security",
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_System_Diagnostics_Debug",
|
||||
"Win32_System_IO",
|
||||
"Win32_System_Ioctl",
|
||||
"Win32_System_JobObjects",
|
||||
"Win32_System_ProcessStatus",
|
||||
"Win32_System_SystemServices",
|
||||
"Win32_System_Threading",
|
||||
"Win32_System_Time",
|
||||
]
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -281,41 +281,49 @@ fn format_rusage_data(_child: Child) -> Option<String> {
|
||||
#[cfg(windows)]
|
||||
fn format_rusage_data(child: Child) -> Option<String> {
|
||||
use std::os::windows::io::AsRawHandle;
|
||||
use winapi::um::{processthreadsapi, psapi, timezoneapi};
|
||||
let handle = child.as_raw_handle();
|
||||
macro_rules! try_bool {
|
||||
($e:expr) => {
|
||||
if $e != 1 {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
use windows::{
|
||||
Win32::Foundation::HANDLE,
|
||||
Win32::System::ProcessStatus::{
|
||||
K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS, PROCESS_MEMORY_COUNTERS_EX,
|
||||
},
|
||||
Win32::System::Threading::GetProcessTimes,
|
||||
Win32::System::Time::FileTimeToSystemTime,
|
||||
};
|
||||
|
||||
let handle = HANDLE(child.as_raw_handle() as isize);
|
||||
|
||||
let mut user_filetime = Default::default();
|
||||
let mut user_time = Default::default();
|
||||
let mut kernel_filetime = Default::default();
|
||||
let mut kernel_time = Default::default();
|
||||
let mut memory_counters = psapi::PROCESS_MEMORY_COUNTERS::default();
|
||||
let mut memory_counters = PROCESS_MEMORY_COUNTERS::default();
|
||||
|
||||
unsafe {
|
||||
try_bool!(processthreadsapi::GetProcessTimes(
|
||||
GetProcessTimes(
|
||||
handle,
|
||||
&mut Default::default(),
|
||||
&mut Default::default(),
|
||||
&mut kernel_filetime,
|
||||
&mut user_filetime,
|
||||
));
|
||||
try_bool!(timezoneapi::FileTimeToSystemTime(&user_filetime, &mut user_time));
|
||||
try_bool!(timezoneapi::FileTimeToSystemTime(&kernel_filetime, &mut kernel_time));
|
||||
|
||||
// Unlike on Linux with RUSAGE_CHILDREN, this will only return memory information for the process
|
||||
// with the given handle and none of that process's children.
|
||||
try_bool!(psapi::GetProcessMemoryInfo(
|
||||
handle as _,
|
||||
&mut memory_counters as *mut _ as _,
|
||||
std::mem::size_of::<psapi::PROCESS_MEMORY_COUNTERS_EX>() as u32,
|
||||
));
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
.ok()?;
|
||||
unsafe { FileTimeToSystemTime(&user_filetime, &mut user_time) }.ok().ok()?;
|
||||
unsafe { FileTimeToSystemTime(&kernel_filetime, &mut kernel_time) }.ok().ok()?;
|
||||
|
||||
// Unlike on Linux with RUSAGE_CHILDREN, this will only return memory information for the process
|
||||
// with the given handle and none of that process's children.
|
||||
unsafe {
|
||||
K32GetProcessMemoryInfo(
|
||||
handle,
|
||||
&mut memory_counters,
|
||||
std::mem::size_of::<PROCESS_MEMORY_COUNTERS_EX>() as u32,
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
.ok()?;
|
||||
|
||||
// Guide on interpreting these numbers:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/psapi/process-memory-usage-information
|
||||
|
@ -1303,6 +1303,14 @@ pub fn cargo(
|
||||
}
|
||||
};
|
||||
|
||||
// By default, windows-rs depends on a native library that doesn't get copied into the
|
||||
// sysroot. Passing this cfg enables raw-dylib support instead, which makes the native
|
||||
// library unnecessary. This can be removed when windows-rs enables raw-dylib
|
||||
// unconditionally.
|
||||
if let Mode::Rustc | Mode::ToolRustc = mode {
|
||||
rustflags.arg("--cfg=windows_raw_dylib");
|
||||
}
|
||||
|
||||
if use_new_symbol_mangling {
|
||||
rustflags.arg("-Csymbol-mangling-version=v0");
|
||||
} else {
|
||||
|
@ -27,52 +27,54 @@
|
||||
//! Note that this module has a #[cfg(windows)] above it as none of this logic
|
||||
//! is required on Unix.
|
||||
|
||||
#![allow(nonstandard_style, dead_code)]
|
||||
|
||||
use crate::Build;
|
||||
use std::env;
|
||||
use std::ffi::c_void;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use winapi::shared::minwindef::{DWORD, FALSE, LPVOID};
|
||||
use winapi::um::errhandlingapi::SetErrorMode;
|
||||
use winapi::um::handleapi::{CloseHandle, DuplicateHandle};
|
||||
use winapi::um::jobapi2::{AssignProcessToJobObject, CreateJobObjectW, SetInformationJobObject};
|
||||
use winapi::um::processthreadsapi::{GetCurrentProcess, OpenProcess};
|
||||
use winapi::um::winbase::{BELOW_NORMAL_PRIORITY_CLASS, SEM_NOGPFAULTERRORBOX};
|
||||
use winapi::um::winnt::{
|
||||
JobObjectExtendedLimitInformation, DUPLICATE_SAME_ACCESS, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS, PROCESS_DUP_HANDLE,
|
||||
use windows::{
|
||||
core::PCWSTR,
|
||||
Win32::Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE},
|
||||
Win32::System::Diagnostics::Debug::{SetErrorMode, SEM_NOGPFAULTERRORBOX, THREAD_ERROR_MODE},
|
||||
Win32::System::JobObjects::{
|
||||
AssignProcessToJobObject, CreateJobObjectW, JobObjectExtendedLimitInformation,
|
||||
SetInformationJobObject, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS,
|
||||
},
|
||||
Win32::System::Threading::{
|
||||
GetCurrentProcess, OpenProcess, BELOW_NORMAL_PRIORITY_CLASS, PROCESS_DUP_HANDLE,
|
||||
},
|
||||
};
|
||||
|
||||
pub unsafe fn setup(build: &mut Build) {
|
||||
// Enable the Windows Error Reporting dialog which msys disables,
|
||||
// so we can JIT debug rustc
|
||||
let mode = SetErrorMode(0);
|
||||
let mode = SetErrorMode(THREAD_ERROR_MODE::default());
|
||||
let mode = THREAD_ERROR_MODE(mode);
|
||||
SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX);
|
||||
|
||||
// Create a new job object for us to use
|
||||
let job = CreateJobObjectW(ptr::null_mut(), ptr::null());
|
||||
assert!(!job.is_null(), "{}", io::Error::last_os_error());
|
||||
let job = CreateJobObjectW(None, PCWSTR::null()).unwrap();
|
||||
|
||||
// Indicate that when all handles to the job object are gone that all
|
||||
// process in the object should be killed. Note that this includes our
|
||||
// entire process tree by default because we've added ourselves and our
|
||||
// children will reside in the job by default.
|
||||
let mut info = mem::zeroed::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>();
|
||||
let mut info = JOBOBJECT_EXTENDED_LIMIT_INFORMATION::default();
|
||||
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||
if build.config.low_priority {
|
||||
info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
|
||||
info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
|
||||
info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS.0;
|
||||
}
|
||||
let r = SetInformationJobObject(
|
||||
job,
|
||||
JobObjectExtendedLimitInformation,
|
||||
&mut info as *mut _ as LPVOID,
|
||||
mem::size_of_val(&info) as DWORD,
|
||||
);
|
||||
assert!(r != 0, "{}", io::Error::last_os_error());
|
||||
&info as *const _ as *const c_void,
|
||||
mem::size_of_val(&info) as u32,
|
||||
)
|
||||
.ok();
|
||||
assert!(r.is_ok(), "{}", io::Error::last_os_error());
|
||||
|
||||
// Assign our process to this job object. Note that if this fails, one very
|
||||
// likely reason is that we are ourselves already in a job object! This can
|
||||
@ -83,8 +85,8 @@ pub unsafe fn setup(build: &mut Build) {
|
||||
// Also note that nested jobs (why this might fail) are supported in recent
|
||||
// versions of Windows, but the version of Windows that our bots are running
|
||||
// at least don't support nested job objects.
|
||||
let r = AssignProcessToJobObject(job, GetCurrentProcess());
|
||||
if r == 0 {
|
||||
let r = AssignProcessToJobObject(job, GetCurrentProcess()).ok();
|
||||
if r.is_err() {
|
||||
CloseHandle(job);
|
||||
return;
|
||||
}
|
||||
@ -102,31 +104,32 @@ pub unsafe fn setup(build: &mut Build) {
|
||||
Err(..) => return,
|
||||
};
|
||||
|
||||
let parent = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid.parse().unwrap());
|
||||
let parent = match OpenProcess(PROCESS_DUP_HANDLE, false, pid.parse().unwrap()).ok() {
|
||||
Some(parent) => parent,
|
||||
_ => {
|
||||
// If we get a null parent pointer here, it is possible that either
|
||||
// we have an invalid pid or the parent process has been closed.
|
||||
// Since the first case rarely happens
|
||||
// (only when wrongly setting the environmental variable),
|
||||
// it might be better to improve the experience of the second case
|
||||
// when users have interrupted the parent process and we haven't finish
|
||||
// duplicating the handle yet. We just need close the job object if that occurs.
|
||||
CloseHandle(job);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// If we get a null parent pointer here, it is possible that either
|
||||
// we have got an invalid pid or the parent process has been closed.
|
||||
// Since the first case rarely happens
|
||||
// (only when wrongly setting the environmental variable),
|
||||
// so it might be better to improve the experience of the second case
|
||||
// when users have interrupted the parent process and we don't finish
|
||||
// duplicating the handle yet.
|
||||
// We just need close the job object if that occurs.
|
||||
if parent.is_null() {
|
||||
CloseHandle(job);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut parent_handle = ptr::null_mut();
|
||||
let mut parent_handle = HANDLE::default();
|
||||
let r = DuplicateHandle(
|
||||
GetCurrentProcess(),
|
||||
job,
|
||||
parent,
|
||||
&mut parent_handle,
|
||||
0,
|
||||
FALSE,
|
||||
false,
|
||||
DUPLICATE_SAME_ACCESS,
|
||||
);
|
||||
)
|
||||
.ok();
|
||||
|
||||
// If this failed, well at least we tried! An example of DuplicateHandle
|
||||
// failing in the past has been when the wrong python2 package spawned this
|
||||
@ -134,7 +137,7 @@ pub unsafe fn setup(build: &mut Build) {
|
||||
// `mingw-w64-x86_64-python2`. Not sure why it failed, but the "failure
|
||||
// mode" here is that we only clean everything up when the build system
|
||||
// dies, not when the python parent does, so not too bad.
|
||||
if r != 0 {
|
||||
if r.is_err() {
|
||||
CloseHandle(job);
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +144,9 @@ pub unsafe fn setup(_build: &mut crate::Build) {}
|
||||
// FIXME: Used by filetime, but we should not be triggering on external dependencies.
|
||||
(Some(Mode::Rustc), "emulate_second_only_system", None),
|
||||
(Some(Mode::ToolRustc), "emulate_second_only_system", None),
|
||||
// Needed to avoid the need to copy windows.lib into the sysroot.
|
||||
(Some(Mode::Rustc), "windows_raw_dylib", None),
|
||||
(Some(Mode::ToolRustc), "windows_raw_dylib", None),
|
||||
];
|
||||
|
||||
/// A structure representing a Rust compiler.
|
||||
|
@ -155,29 +155,30 @@ fn symlink_dir_inner(src: &Path, dest: &Path) -> io::Result<()> {
|
||||
fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
|
||||
use std::ffi::OsStr;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::ptr;
|
||||
|
||||
use winapi::shared::minwindef::{DWORD, WORD};
|
||||
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
|
||||
use winapi::um::handleapi::CloseHandle;
|
||||
use winapi::um::ioapiset::DeviceIoControl;
|
||||
use winapi::um::winbase::{FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT};
|
||||
use winapi::um::winioctl::FSCTL_SET_REPARSE_POINT;
|
||||
use winapi::um::winnt::{
|
||||
FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_WRITE,
|
||||
IO_REPARSE_TAG_MOUNT_POINT, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, WCHAR,
|
||||
use windows::{
|
||||
core::PCWSTR,
|
||||
Win32::Foundation::{CloseHandle, HANDLE},
|
||||
Win32::Storage::FileSystem::{
|
||||
CreateFileW, FILE_ACCESS_FLAGS, FILE_FLAG_BACKUP_SEMANTICS,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE,
|
||||
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, OPEN_EXISTING,
|
||||
},
|
||||
Win32::System::Ioctl::FSCTL_SET_REPARSE_POINT,
|
||||
Win32::System::SystemServices::{GENERIC_WRITE, IO_REPARSE_TAG_MOUNT_POINT},
|
||||
Win32::System::IO::DeviceIoControl,
|
||||
};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[repr(C)]
|
||||
struct REPARSE_MOUNTPOINT_DATA_BUFFER {
|
||||
ReparseTag: DWORD,
|
||||
ReparseDataLength: DWORD,
|
||||
Reserved: WORD,
|
||||
ReparseTargetLength: WORD,
|
||||
ReparseTargetMaximumLength: WORD,
|
||||
Reserved1: WORD,
|
||||
ReparseTarget: WCHAR,
|
||||
ReparseTag: u32,
|
||||
ReparseDataLength: u32,
|
||||
Reserved: u16,
|
||||
ReparseTargetLength: u16,
|
||||
ReparseTargetMaximumLength: u16,
|
||||
Reserved1: u16,
|
||||
ReparseTarget: u16,
|
||||
}
|
||||
|
||||
fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
|
||||
@ -193,17 +194,20 @@ fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
|
||||
|
||||
let path = to_u16s(junction)?;
|
||||
|
||||
unsafe {
|
||||
let h = CreateFileW(
|
||||
path.as_ptr(),
|
||||
GENERIC_WRITE,
|
||||
let h = unsafe {
|
||||
CreateFileW(
|
||||
PCWSTR(path.as_ptr()),
|
||||
FILE_ACCESS_FLAGS(GENERIC_WRITE),
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
|
||||
ptr::null_mut(),
|
||||
);
|
||||
HANDLE::default(),
|
||||
)
|
||||
}
|
||||
.map_err(|_| io::Error::last_os_error())?;
|
||||
|
||||
unsafe {
|
||||
#[repr(C, align(8))]
|
||||
struct Align8<T>(T);
|
||||
let mut data = Align8([0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]);
|
||||
@ -219,27 +223,29 @@ fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
|
||||
}
|
||||
*buf.offset(i) = 0;
|
||||
i += 1;
|
||||
|
||||
(*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||
(*db).ReparseTargetMaximumLength = (i * 2) as WORD;
|
||||
(*db).ReparseTargetLength = ((i - 1) * 2) as WORD;
|
||||
(*db).ReparseDataLength = (*db).ReparseTargetLength as DWORD + 12;
|
||||
(*db).ReparseTargetMaximumLength = (i * 2) as u16;
|
||||
(*db).ReparseTargetLength = ((i - 1) * 2) as u16;
|
||||
(*db).ReparseDataLength = ((*db).ReparseTargetLength + 12) as u32;
|
||||
|
||||
let mut ret = 0;
|
||||
let res = DeviceIoControl(
|
||||
h as *mut _,
|
||||
let mut ret = 0u32;
|
||||
DeviceIoControl(
|
||||
h,
|
||||
FSCTL_SET_REPARSE_POINT,
|
||||
db.cast(),
|
||||
Some(db.cast()),
|
||||
(*db).ReparseDataLength + 8,
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
0,
|
||||
&mut ret,
|
||||
ptr::null_mut(),
|
||||
);
|
||||
|
||||
let out = if res == 0 { Err(io::Error::last_os_error()) } else { Ok(()) };
|
||||
CloseHandle(h);
|
||||
out
|
||||
Some(&mut ret),
|
||||
None,
|
||||
)
|
||||
.ok()
|
||||
.map_err(|_| io::Error::last_os_error())?;
|
||||
}
|
||||
|
||||
unsafe { CloseHandle(h) };
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,4 +26,10 @@ libc = "0.2"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
miow = "0.5"
|
||||
winapi = { version = "0.3", features = ["winerror"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies.windows]
|
||||
version = "0.46.0"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_System_Diagnostics_Debug",
|
||||
]
|
||||
|
@ -232,7 +232,7 @@ mod imp {
|
||||
use miow::iocp::{CompletionPort, CompletionStatus};
|
||||
use miow::pipe::NamedPipe;
|
||||
use miow::Overlapped;
|
||||
use winapi::shared::winerror::ERROR_BROKEN_PIPE;
|
||||
use windows::Win32::Foundation::ERROR_BROKEN_PIPE;
|
||||
|
||||
struct Pipe<'a> {
|
||||
dst: &'a mut Vec<u8>,
|
||||
@ -295,7 +295,7 @@ unsafe fn read(&mut self) -> io::Result<()> {
|
||||
match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => {
|
||||
if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
|
||||
if e.raw_os_error() == Some(ERROR_BROKEN_PIPE.0 as i32) {
|
||||
self.done = true;
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -49,8 +49,10 @@
|
||||
#[cfg(windows)]
|
||||
fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
use std::sync::Mutex;
|
||||
use winapi::um::errhandlingapi::SetErrorMode;
|
||||
use winapi::um::winbase::SEM_NOGPFAULTERRORBOX;
|
||||
|
||||
use windows::Win32::System::Diagnostics::Debug::{
|
||||
SetErrorMode, SEM_NOGPFAULTERRORBOX, THREAD_ERROR_MODE,
|
||||
};
|
||||
|
||||
static LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
@ -62,6 +64,7 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
// termination by design. This mode is inherited by all child processes.
|
||||
unsafe {
|
||||
let old_mode = SetErrorMode(SEM_NOGPFAULTERRORBOX); // read inherited flags
|
||||
let old_mode = THREAD_ERROR_MODE(old_mode);
|
||||
SetErrorMode(old_mode | SEM_NOGPFAULTERRORBOX);
|
||||
let r = f();
|
||||
SetErrorMode(old_mode);
|
||||
|
@ -260,6 +260,7 @@
|
||||
"valuable",
|
||||
"version_check",
|
||||
"wasi",
|
||||
"windows",
|
||||
"winapi",
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-util",
|
||||
|
Loading…
Reference in New Issue
Block a user