1
1
use crate :: {
2
2
windows:: {
3
3
pipe:: { self , ReadPipe , WritePipe } ,
4
+ util:: OwnedHandle ,
4
5
Cvt , Error , WindowsSandbox ,
5
6
} ,
6
7
InputSpecificationData , OutputSpecificationData ,
@@ -17,7 +18,7 @@ use winapi::{
17
18
shared:: { minwindef:: TRUE , winerror:: ERROR_INSUFFICIENT_BUFFER } ,
18
19
um:: {
19
20
errhandlingapi:: GetLastError ,
20
- handleapi:: { CloseHandle , INVALID_HANDLE_VALUE } ,
21
+ handleapi:: INVALID_HANDLE_VALUE ,
21
22
minwinbase:: SECURITY_ATTRIBUTES ,
22
23
processthreadsapi:: {
23
24
CreateProcessW , DeleteProcThreadAttributeList , GetCurrentProcess ,
@@ -34,46 +35,49 @@ use winapi::{
34
35
} ;
35
36
36
37
pub ( in crate :: windows) struct Stdio {
37
- pub stdin : HANDLE ,
38
- pub stdout : HANDLE ,
39
- pub stderr : HANDLE ,
38
+ pub stdin : Option < OwnedHandle > ,
39
+ pub stdout : Option < OwnedHandle > ,
40
+ pub stderr : Option < OwnedHandle > ,
40
41
}
41
42
42
43
impl Stdio {
43
44
fn make_input (
44
45
spec : crate :: InputSpecificationData ,
45
- ) -> Result < ( HANDLE , Option < WritePipe > ) , Error > {
46
+ ) -> Result < ( Option < OwnedHandle > , Option < WritePipe > ) , Error > {
46
47
match spec {
47
- InputSpecificationData :: Handle ( h) => Ok ( ( h as HANDLE , None ) ) ,
48
+ InputSpecificationData :: Handle ( h) => Ok ( ( Some ( OwnedHandle :: new ( h as HANDLE ) ) , None ) ) ,
48
49
InputSpecificationData :: Pipe => {
49
50
let ( reader, writer) = pipe:: make ( pipe:: InheritKind :: Allow ) ?;
50
- Ok ( ( reader. into_raw_handle ( ) , Some ( writer) ) )
51
+ Ok ( (
52
+ Some ( OwnedHandle :: new ( reader. into_raw_handle ( ) ) ) ,
53
+ Some ( writer) ,
54
+ ) )
51
55
}
52
- InputSpecificationData :: Empty => Ok ( ( open_empty_readable_file ( ) , None ) ) ,
53
- InputSpecificationData :: Null => Ok ( ( - 1_i32 as usize as HANDLE , None ) ) ,
56
+ InputSpecificationData :: Empty => Ok ( ( Some ( open_empty_readable_file ( ) ) , None ) ) ,
57
+ InputSpecificationData :: Null => Ok ( ( None , None ) ) ,
54
58
}
55
59
}
56
60
57
61
fn make_output (
58
62
spec : crate :: OutputSpecificationData ,
59
- ) -> Result < ( HANDLE , Option < ReadPipe > ) , Error > {
63
+ ) -> Result < ( Option < OwnedHandle > , Option < ReadPipe > ) , Error > {
60
64
match spec {
61
- OutputSpecificationData :: Handle ( h) => Ok ( ( h as HANDLE , None ) ) ,
65
+ OutputSpecificationData :: Handle ( h) => Ok ( ( Some ( OwnedHandle :: new ( h as HANDLE ) ) , None ) ) ,
62
66
OutputSpecificationData :: Pipe => {
63
67
let ( reader, writer) = pipe:: make ( pipe:: InheritKind :: Allow ) ?;
64
- Ok ( ( writer. into_raw_handle ( ) , Some ( reader) ) )
68
+ Ok ( (
69
+ Some ( OwnedHandle :: new ( writer. into_raw_handle ( ) ) ) ,
70
+ Some ( reader) ,
71
+ ) )
65
72
}
66
- OutputSpecificationData :: Null => Ok ( ( - 1_i32 as usize as HANDLE , None ) ) ,
73
+ OutputSpecificationData :: Null => Ok ( ( None , None ) ) ,
67
74
OutputSpecificationData :: Ignore => {
68
75
let file = std:: fs:: File :: create ( "C:\\ NUL" ) . map_err ( |io_err| Error :: Syscall {
69
76
errno : io_err. raw_os_error ( ) . unwrap_or ( -1 ) as u32 ,
70
77
} ) ?;
71
- let file = file. into_raw_handle ( ) ;
72
- let cloned_file = crate :: windows:: util:: duplicate_with_inheritance ( file) ?;
73
- unsafe {
74
- CloseHandle ( file) ;
75
- }
76
- Ok ( ( cloned_file, None ) )
78
+ let file = OwnedHandle :: new ( file. into_raw_handle ( ) ) ;
79
+ let cloned_file = file. try_clone_with_inheritance ( ) ?;
80
+ Ok ( ( Some ( cloned_file) , None ) )
77
81
}
78
82
OutputSpecificationData :: Buffer ( sz) => unsafe {
79
83
let sz = sz. unwrap_or ( usize:: max_value ( ) ) as u64 ;
@@ -88,8 +92,12 @@ impl Stdio {
88
92
if mmap. is_null ( ) {
89
93
Cvt :: nonzero ( 0 ) ?;
90
94
}
91
- let child_side = crate :: windows:: util:: duplicate_with_inheritance ( mmap) ?;
92
- Ok ( ( child_side, Some ( ReadPipe :: from_raw_handle ( mmap) ) ) )
95
+ let mmap = OwnedHandle :: new ( mmap) ;
96
+ let child_side = mmap. try_clone_with_inheritance ( ) ?;
97
+ Ok ( (
98
+ Some ( child_side) ,
99
+ Some ( ReadPipe :: from_raw_handle ( mmap. into_inner ( ) ) ) ,
100
+ ) )
93
101
} ,
94
102
}
95
103
}
@@ -117,14 +125,17 @@ impl Stdio {
117
125
}
118
126
}
119
127
120
- fn open_empty_readable_file ( ) -> HANDLE {
121
- static EMPTY_FILE_HANDLE : once_cell:: sync:: Lazy < usize > = once_cell:: sync:: Lazy :: new ( || {
122
- let ( reader, writer) =
123
- pipe:: make ( pipe:: InheritKind :: Allow ) . expect ( "failed to create a pipe" ) ;
124
- drop ( writer) ;
125
- reader. into_raw_handle ( ) as usize
126
- } ) ;
127
- * EMPTY_FILE_HANDLE as HANDLE
128
+ fn open_empty_readable_file ( ) -> OwnedHandle {
129
+ static EMPTY_FILE_HANDLE : once_cell:: sync:: Lazy < OwnedHandle > =
130
+ once_cell:: sync:: Lazy :: new ( || {
131
+ let ( reader, writer) =
132
+ pipe:: make ( pipe:: InheritKind :: Allow ) . expect ( "failed to create a pipe" ) ;
133
+ drop ( writer) ;
134
+ OwnedHandle :: new ( reader. into_raw_handle ( ) )
135
+ } ) ;
136
+ EMPTY_FILE_HANDLE
137
+ . try_clone ( )
138
+ . expect ( "failed to clone a handle" )
128
139
}
129
140
130
141
pub ( in crate :: windows) struct ChildParams {
@@ -211,9 +222,15 @@ pub(in crate::windows) fn spawn(
211
222
212
223
startup_info. StartupInfo . cb = size_of :: < STARTUPINFOEXW > ( ) as u32 ;
213
224
startup_info. StartupInfo . dwFlags = STARTF_USESTDHANDLES ;
214
- startup_info. StartupInfo . hStdInput = stdio. stdin ;
215
- startup_info. StartupInfo . hStdOutput = stdio. stdout ;
216
- startup_info. StartupInfo . hStdError = stdio. stderr ;
225
+
226
+ let cvt_handle = |h : Option < OwnedHandle > | {
227
+ h. map ( OwnedHandle :: into_inner)
228
+ . unwrap_or ( INVALID_HANDLE_VALUE )
229
+ } ;
230
+
231
+ startup_info. StartupInfo . hStdInput = cvt_handle ( stdio. stdin ) ;
232
+ startup_info. StartupInfo . hStdOutput = cvt_handle ( stdio. stdout ) ;
233
+ startup_info. StartupInfo . hStdError = cvt_handle ( stdio. stderr ) ;
217
234
startup_info
218
235
} ;
219
236
let creation_flags = CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT ;
0 commit comments