about summary refs log tree commit diff
path: root/library/std/src/sys/pal
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/pal')
-rw-r--r--library/std/src/sys/pal/windows/process.rs103
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>,
 }