stdio_override/
windows.rs1use std::fs::File;
2use std::io;
3use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
4use std::ptr;
5
6use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE};
7use winapi::um::handleapi::{CloseHandle, DuplicateHandle, GetHandleInformation, INVALID_HANDLE_VALUE};
8use winapi::um::processenv::{GetStdHandle, SetStdHandle};
9use winapi::um::processthreadsapi::GetCurrentProcess;
10use winapi::um::winbase::HANDLE_FLAG_INHERIT;
11use winapi::um::winbase::{STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
12use winapi::um::winnt::DUPLICATE_SAME_ACCESS;
13
14pub(crate) use std::os::windows::io::{AsRawHandle as AsRaw, IntoRawHandle as IntoRaw, RawHandle as Raw};
15
16pub(crate) fn as_raw(io: &impl AsRawHandle) -> RawHandle {
17 io.as_raw_handle()
18}
19pub(crate) fn into_raw(io: impl IntoRawHandle) -> RawHandle {
20 io.into_raw_handle()
21}
22
23pub(crate) fn override_stdin(io: RawHandle, owned: bool) -> io::Result<File> {
24 override_stdio(STD_INPUT_HANDLE, io, owned)
25}
26pub(crate) fn override_stdout(io: RawHandle, owned: bool) -> io::Result<File> {
27 override_stdio(STD_OUTPUT_HANDLE, io, owned)
28}
29pub(crate) fn override_stderr(io: RawHandle, owned: bool) -> io::Result<File> {
30 override_stdio(STD_ERROR_HANDLE, io, owned)
31}
32
33pub(crate) fn reset_stdin(old: RawHandle) -> io::Result<()> {
34 reset_stdio(STD_INPUT_HANDLE, old)
35}
36pub(crate) fn reset_stdout(old: RawHandle) -> io::Result<()> {
37 reset_stdio(STD_OUTPUT_HANDLE, old)
38}
39pub(crate) fn reset_stderr(old: RawHandle) -> io::Result<()> {
40 reset_stdio(STD_ERROR_HANDLE, old)
41}
42
43fn override_stdio(stdio: DWORD, other: RawHandle, owned: bool) -> io::Result<File> {
44 let original = handle_res(unsafe { GetStdHandle(stdio) })?;
45
46 let other = if owned {
47 other
48 } else {
49 let process = unsafe { GetCurrentProcess() };
53
54 let mut handle_information = 0;
55 io_res(unsafe { GetHandleInformation(other, &mut handle_information as *mut DWORD) })?;
56 let inherit_handle = if handle_information & HANDLE_FLAG_INHERIT == HANDLE_FLAG_INHERIT { TRUE } else { FALSE };
57
58 let mut target = ptr::null_mut();
59 io_res(unsafe {
60 DuplicateHandle(
61 process,
62 other,
63 process,
64 &mut target as *mut RawHandle,
65 0, inherit_handle,
67 DUPLICATE_SAME_ACCESS,
68 )
69 })?;
70
71 target
72 };
73
74 io_res(unsafe { SetStdHandle(stdio, other) })?;
75
76 Ok(unsafe { File::from_raw_handle(original) })
77}
78fn reset_stdio(stdio: DWORD, other: RawHandle) -> io::Result<()> {
79 let current = handle_res(unsafe { GetStdHandle(stdio) })?;
80
81 io_res(unsafe { SetStdHandle(stdio, other) })?;
82
83 io_res(unsafe { CloseHandle(current) })?;
84
85 Ok(())
86}
87
88fn io_res(res: BOOL) -> io::Result<()> {
89 if res == 0 {
90 Err(io::Error::last_os_error())
91 } else {
92 Ok(())
93 }
94}
95
96fn handle_res(res: RawHandle) -> io::Result<RawHandle> {
97 if res == INVALID_HANDLE_VALUE {
98 Err(io::Error::last_os_error())
99 } else {
100 Ok(res)
101 }
102}
103
104impl AsRawHandle for crate::StdinOverride {
105 fn as_raw_handle(&self) -> RawHandle {
106 self.original.as_raw_handle()
107 }
108}
109impl AsRawHandle for crate::StdoutOverride {
110 fn as_raw_handle(&self) -> RawHandle {
111 self.original.as_raw_handle()
112 }
113}
114impl AsRawHandle for crate::StderrOverride {
115 fn as_raw_handle(&self) -> RawHandle {
116 self.original.as_raw_handle()
117 }
118}