]> git.proxmox.com Git - rustc.git/blob - src/vendor/os_pipe/src/windows.rs
New upstream version 1.25.0+dfsg1
[rustc.git] / src / vendor / os_pipe / src / windows.rs
1 extern crate winapi;
2 extern crate kernel32;
3
4 use std::fs::File;
5 use std::io;
6 use std::os::windows::prelude::*;
7 use std::process::Stdio;
8 use std::ptr;
9
10 use PipeReader;
11 use PipeWriter;
12 use IntoStdio;
13
14 pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
15 let mut read_pipe: winapi::HANDLE = ptr::null_mut();
16 let mut write_pipe: winapi::HANDLE = ptr::null_mut();
17
18 let ret = unsafe {
19 // TODO: These pipes do not support IOCP. We might want to emulate anonymous pipes with
20 // CreateNamedPipe, as Rust's stdlib does.
21 kernel32::CreatePipe(&mut read_pipe as winapi::PHANDLE,
22 &mut write_pipe as winapi::PHANDLE,
23 ptr::null_mut(),
24 0)
25 };
26
27 if ret == 0 {
28 Err(io::Error::last_os_error())
29 } else {
30 unsafe {
31 Ok((PipeReader::from_raw_handle(read_pipe), PipeWriter::from_raw_handle(write_pipe)))
32 }
33 }
34 }
35
36 pub fn parent_stdin() -> io::Result<Stdio> {
37 dup_std_handle(winapi::STD_INPUT_HANDLE)
38 }
39
40 pub fn parent_stdout() -> io::Result<Stdio> {
41 dup_std_handle(winapi::STD_OUTPUT_HANDLE)
42 }
43
44 pub fn parent_stderr() -> io::Result<Stdio> {
45 dup_std_handle(winapi::STD_ERROR_HANDLE)
46 }
47
48 // adapted from src/libstd/sys/windows/stdio.rs
49 fn dup_std_handle(which: winapi::DWORD) -> io::Result<Stdio> {
50 let handle = unsafe { kernel32::GetStdHandle(which) };
51 if handle == winapi::INVALID_HANDLE_VALUE {
52 return Err(io::Error::last_os_error());
53 }
54 if handle.is_null() {
55 return Err(io::Error::new(io::ErrorKind::Other,
56 "no stdio handle available for this process"));
57 }
58 // This handle is *not* a dup. It's just a copy of the global stdin/stdout/stderr handle, and
59 // we need to dup it ourselves. The simplest way to do that is File::try_clone(), but we need
60 // to make sure that the file is never dropped.
61 let temp_file = unsafe { File::from_raw_handle(handle) };
62 let dup_result = temp_file.try_clone(); // No short-circuit here!
63 temp_file.into_raw_handle(); // Prevent closing handle on drop().
64 dup_result.map(File::into_stdio)
65 }
66
67 impl<T: IntoRawHandle> IntoStdio for T {
68 fn into_stdio(self) -> Stdio {
69 let handle = self.into_raw_handle();
70 unsafe { Stdio::from_raw_handle(handle) }
71 }
72 }
73
74 impl IntoRawHandle for PipeReader {
75 fn into_raw_handle(self) -> RawHandle {
76 self.0.into_raw_handle()
77 }
78 }
79
80 impl AsRawHandle for PipeReader {
81 fn as_raw_handle(&self) -> RawHandle {
82 self.0.as_raw_handle()
83 }
84 }
85
86 impl FromRawHandle for PipeReader {
87 unsafe fn from_raw_handle(handle: RawHandle) -> PipeReader {
88 PipeReader(File::from_raw_handle(handle))
89 }
90 }
91
92 impl IntoRawHandle for PipeWriter {
93 fn into_raw_handle(self) -> RawHandle {
94 self.0.into_raw_handle()
95 }
96 }
97
98 impl AsRawHandle for PipeWriter {
99 fn as_raw_handle(&self) -> RawHandle {
100 self.0.as_raw_handle()
101 }
102 }
103
104 impl FromRawHandle for PipeWriter {
105 unsafe fn from_raw_handle(handle: RawHandle) -> PipeWriter {
106 PipeWriter(File::from_raw_handle(handle))
107 }
108 }