diff options
Diffstat (limited to 'library/std/src/sys/pal')
| -rw-r--r-- | library/std/src/sys/pal/windows/process.rs | 103 |
1 files changed, 13 insertions, 90 deletions
diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/pal/windows/process.rs index da0daacd1dd..2ca20a21dfe 100644 --- a/library/std/src/sys/pal/windows/process.rs +++ b/library/std/src/sys/pal/windows/process.rs @@ -10,10 +10,10 @@ use crate::collections::BTreeMap; use crate::env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use crate::ffi::{OsStr, OsString}; use crate::io::{self, Error, ErrorKind}; -use crate::mem::MaybeUninit; use crate::num::NonZero; use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle}; +use crate::os::windows::process::ProcThreadAttributeList; use crate::path::{Path, PathBuf}; use crate::sync::Mutex; use crate::sys::args::{self, Arg}; @@ -162,7 +162,6 @@ pub struct Command { stdout: Option<Stdio>, stderr: Option<Stdio>, force_quotes_enabled: bool, - proc_thread_attributes: BTreeMap<usize, ProcThreadAttributeValue>, } pub enum Stdio { @@ -194,7 +193,6 @@ impl Command { stdout: None, stderr: None, force_quotes_enabled: false, - proc_thread_attributes: Default::default(), } } @@ -248,21 +246,19 @@ impl Command { self.cwd.as_ref().map(Path::new) } - pub unsafe fn raw_attribute<T: Copy + Send + Sync + 'static>( + pub fn spawn( &mut self, - attribute: usize, - value: T, - ) { - self.proc_thread_attributes.insert(attribute, ProcThreadAttributeValue { - size: mem::size_of::<T>(), - data: Box::new(value), - }); + default: Stdio, + needs_stdin: bool, + ) -> io::Result<(Process, StdioPipes)> { + self.spawn_with_attributes(default, needs_stdin, None) } - pub fn spawn( + pub fn spawn_with_attributes( &mut self, default: Stdio, needs_stdin: bool, + proc_thread_attribute_list: Option<&ProcThreadAttributeList<'_>>, ) -> io::Result<(Process, StdioPipes)> { let maybe_env = self.env.capture_if_changed(); @@ -355,18 +351,18 @@ impl Command { let si_ptr: *mut c::STARTUPINFOW; - let mut proc_thread_attribute_list; let mut si_ex; - if !self.proc_thread_attributes.is_empty() { + if let Some(proc_thread_attribute_list) = proc_thread_attribute_list { si.cb = mem::size_of::<c::STARTUPINFOEXW>() as u32; flags |= c::EXTENDED_STARTUPINFO_PRESENT; - proc_thread_attribute_list = - make_proc_thread_attribute_list(&self.proc_thread_attributes)?; si_ex = c::STARTUPINFOEXW { StartupInfo: si, - lpAttributeList: proc_thread_attribute_list.0.as_mut_ptr() as _, + // SAFETY: Casting this `*const` pointer to a `*mut` pointer is "safe" + // here because windows does not internally mutate the attribute list. + // Ideally this should be reflected in the interface of the `windows-sys` crate. + lpAttributeList: proc_thread_attribute_list.as_ptr().cast::<c_void>().cast_mut(), }; si_ptr = (&raw mut si_ex) as _; } else { @@ -896,79 +892,6 @@ fn make_dirp(d: Option<&OsString>) -> io::Result<(*const u16, Vec<u16>)> { } } -struct ProcThreadAttributeList(Box<[MaybeUninit<u8>]>); - -impl Drop for ProcThreadAttributeList { - fn drop(&mut self) { - let lp_attribute_list = self.0.as_mut_ptr() as _; - unsafe { c::DeleteProcThreadAttributeList(lp_attribute_list) } - } -} - -/// Wrapper around the value data to be used as a Process Thread Attribute. -struct ProcThreadAttributeValue { - data: Box<dyn Send + Sync>, - size: usize, -} - -fn make_proc_thread_attribute_list( - attributes: &BTreeMap<usize, ProcThreadAttributeValue>, -) -> io::Result<ProcThreadAttributeList> { - // To initialize our ProcThreadAttributeList, we need to determine - // how many bytes to allocate for it. The Windows API simplifies this process - // by allowing us to call `InitializeProcThreadAttributeList` with - // a null pointer to retrieve the required size. - let mut required_size = 0; - let Ok(attribute_count) = attributes.len().try_into() else { - return Err(io::const_error!( - ErrorKind::InvalidInput, - "maximum number of ProcThreadAttributes exceeded", - )); - }; - unsafe { - c::InitializeProcThreadAttributeList( - ptr::null_mut(), - attribute_count, - 0, - &mut required_size, - ) - }; - - let mut proc_thread_attribute_list = - ProcThreadAttributeList(vec![MaybeUninit::uninit(); required_size].into_boxed_slice()); - - // Once we've allocated the necessary memory, it's safe to invoke - // `InitializeProcThreadAttributeList` to properly initialize the list. - cvt(unsafe { - c::InitializeProcThreadAttributeList( - proc_thread_attribute_list.0.as_mut_ptr() as *mut _, - attribute_count, - 0, - &mut required_size, - ) - })?; - - // # Add our attributes to the buffer. - // It's theoretically possible for the attribute count to exceed a u32 value. - // Therefore, we ensure that we don't add more attributes than the buffer was initialized for. - for (&attribute, value) in attributes.iter().take(attribute_count as usize) { - let value_ptr = (&raw const *value.data) as _; - cvt(unsafe { - c::UpdateProcThreadAttribute( - proc_thread_attribute_list.0.as_mut_ptr() as _, - 0, - attribute, - value_ptr, - value.size, - ptr::null_mut(), - ptr::null_mut(), - ) - })?; - } - - Ok(proc_thread_attribute_list) -} - pub struct CommandArgs<'a> { iter: crate::slice::Iter<'a, Arg>, } |
