about summary refs log tree commit diff
path: root/library/std/src/process/tests.rs
diff options
context:
space:
mode:
authorMichael van Straten <michael@vanstraten.de>2023-08-25 16:19:16 +0200
committerMichael van Straten <michael@vanstraten.de>2023-08-25 16:30:34 +0200
commitedefa8b105cd4a35b689e85187689f4fb4085ede (patch)
treecdfe88612e167bf4bd4e8cd225e73f4c8a5171b0 /library/std/src/process/tests.rs
parentd7e751006cb3691d1384b74196a9cb45447acfa8 (diff)
downloadrust-edefa8b105cd4a35b689e85187689f4fb4085ede.tar.gz
rust-edefa8b105cd4a35b689e85187689f4fb4085ede.zip
Added option to set ProcThreadAttributes for Windows processes
This implements the ability to add arbitrary attributes to a command on Windows targets using a new `raw_attribute` method on the [`CommandExt`](https://doc.rust-lang.org/stable/std/os/windows/process/trait.CommandExt.html) trait. Setting these attributes provides extended configuration options for Windows processes.

Co-authored-by: Tyler Ruckinger <t.ruckinger@gmail.com>
Diffstat (limited to 'library/std/src/process/tests.rs')
-rw-r--r--library/std/src/process/tests.rs85
1 files changed, 85 insertions, 0 deletions
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 366b591466c..00636237288 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -434,6 +434,91 @@ fn test_creation_flags() {
     assert!(events > 0);
 }
 
+/// Tests proc thread attributes by spawning a process with a custom parent process,
+/// then comparing the parent process ID with the expected parent process ID.
+#[test]
+#[cfg(windows)]
+fn test_proc_thread_attributes() {
+    use crate::mem;
+    use crate::os::windows::io::AsRawHandle;
+    use crate::os::windows::process::CommandExt;
+    use crate::sys::c::{CloseHandle, BOOL, HANDLE};
+    use crate::sys::cvt;
+
+    #[repr(C)]
+    #[allow(non_snake_case)]
+    struct PROCESSENTRY32W {
+        dwSize: u32,
+        cntUsage: u32,
+        th32ProcessID: u32,
+        th32DefaultHeapID: usize,
+        th32ModuleID: u32,
+        cntThreads: u32,
+        th32ParentProcessID: u32,
+        pcPriClassBase: i32,
+        dwFlags: u32,
+        szExeFile: [u16; 260],
+    }
+
+    extern "system" {
+        fn CreateToolhelp32Snapshot(dwflags: u32, th32processid: u32) -> HANDLE;
+        fn Process32First(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL;
+        fn Process32Next(hsnapshot: HANDLE, lppe: *mut PROCESSENTRY32W) -> BOOL;
+    }
+
+    const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000;
+    const TH32CS_SNAPPROCESS: u32 = 0x00000002;
+
+    struct ProcessDropGuard(crate::process::Child);
+
+    impl Drop for ProcessDropGuard {
+        fn drop(&mut self) {
+            let _ = self.0.kill();
+        }
+    }
+
+    let parent = ProcessDropGuard(Command::new("cmd").spawn().unwrap());
+
+    let mut child_cmd = Command::new("cmd");
+
+    unsafe {
+        child_cmd
+            .raw_attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parent.0.as_raw_handle() as isize);
+    }
+
+    let child = ProcessDropGuard(child_cmd.spawn().unwrap());
+
+    let h_snapshot = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) };
+
+    let mut process_entry = PROCESSENTRY32W {
+        dwSize: mem::size_of::<PROCESSENTRY32W>() as u32,
+        cntUsage: 0,
+        th32ProcessID: 0,
+        th32DefaultHeapID: 0,
+        th32ModuleID: 0,
+        cntThreads: 0,
+        th32ParentProcessID: 0,
+        pcPriClassBase: 0,
+        dwFlags: 0,
+        szExeFile: [0; 260],
+    };
+
+    unsafe { cvt(Process32First(h_snapshot, &mut process_entry as *mut _)) }.unwrap();
+
+    loop {
+        if child.0.id() == process_entry.th32ProcessID {
+            break;
+        }
+        unsafe { cvt(Process32Next(h_snapshot, &mut process_entry as *mut _)) }.unwrap();
+    }
+
+    unsafe { cvt(CloseHandle(h_snapshot)) }.unwrap();
+
+    assert_eq!(parent.0.id(), process_entry.th32ParentProcessID);
+
+    drop(child)
+}
+
 #[test]
 fn test_command_implements_send_sync() {
     fn take_send_sync_type<T: Send + Sync>(_: T) {}