stdio_utils/sys/
windows.rs

1use std::io::{Error, Result};
2pub(crate) use std::os::windows::io::{
3    AsHandle as AsFd, BorrowedHandle as BorrowedFd, OwnedHandle as OwnedFd,
4};
5use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
6
7use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
8use windows_sys::Win32::System::Console::*;
9
10use crate::{AsFdExt as _, Guard, Stdio};
11
12pub(crate) const DEV_NULL: &str = "nul";
13
14impl Stdio {
15    fn id(&self) -> STD_HANDLE {
16        match self {
17            Stdio::Stdin => STD_INPUT_HANDLE,
18            Stdio::Stdout => STD_OUTPUT_HANDLE,
19            Stdio::Stderr => STD_ERROR_HANDLE,
20        }
21    }
22
23    fn as_raw_handle(&self) -> Result<RawHandle> {
24        let handle = unsafe { GetStdHandle(self.id()) };
25        if handle == INVALID_HANDLE_VALUE {
26            return Err(Error::last_os_error());
27        }
28        Ok(handle)
29    }
30
31    unsafe fn set_raw_handle(&self, handle: RawHandle) -> Result<()> {
32        if SetStdHandle(self.id(), handle) == 0 {
33            return Err(Error::last_os_error());
34        }
35        Ok(())
36    }
37}
38
39impl AsFd for Guard {
40    fn as_handle(&self) -> BorrowedFd<'_> {
41        self.backup.as_ref().unwrap().borrow_file()
42    }
43}
44
45pub(crate) fn borrow_fd(file: &(impl AsFd + ?Sized)) -> BorrowedFd<'_> {
46    file.as_handle()
47}
48
49pub(crate) unsafe fn override_stdio(file: impl AsFd, stdio: Stdio) -> Result<OwnedFd> {
50    let original = stdio.as_raw_handle()?;
51    let file = file.duplicate_file()?;
52    stdio.set_raw_handle(file.as_handle().as_raw_handle())?;
53    let _ = file.into_raw_handle(); // drop ownership of the handle, it's managed the stdio now
54    Ok(OwnedFd::from_raw_handle(original))
55}