Skip to content

Commit a713a03

Browse files
committed
std: win: Don't use SetHandleInformation on UWP
Attempt to create sockets with the WSA_FLAG_NO_HANDLE_INHERIT flag, and handle the potential error gracefully (as the flag isn't support on Windows 7 before SP1)
1 parent 9407ed7 commit a713a03

File tree

4 files changed

+61
-19
lines changed

4 files changed

+61
-19
lines changed

src/libstd/sys/windows/c.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ impl Clone for WIN32_FIND_DATAW {
121121
}
122122

123123
pub const WSA_FLAG_OVERLAPPED: DWORD = 0x01;
124+
pub const WSA_FLAG_NO_HANDLE_INHERIT: DWORD = 0x80;
124125

125126
pub const WSADESCRIPTION_LEN: usize = 256;
126127
pub const WSASYS_STATUS_LEN: usize = 128;
@@ -130,6 +131,7 @@ pub const INVALID_SOCKET: SOCKET = !0;
130131
pub const WSAEACCES: c_int = 10013;
131132
pub const WSAEINVAL: c_int = 10022;
132133
pub const WSAEWOULDBLOCK: c_int = 10035;
134+
pub const WSAEPROTOTYPE: c_int = 10041;
133135
pub const WSAEADDRINUSE: c_int = 10048;
134136
pub const WSAEADDRNOTAVAIL: c_int = 10049;
135137
pub const WSAECONNABORTED: c_int = 10053;
@@ -157,8 +159,6 @@ pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
157159
pub const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
158160
pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
159161

160-
pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
161-
162162
pub const PROGRESS_CONTINUE: DWORD = 0;
163163

164164
pub const ERROR_FILE_NOT_FOUND: DWORD = 2;
@@ -658,9 +658,15 @@ pub struct timeval {
658658
// Functions forbidden when targeting UWP
659659
cfg_if::cfg_if! {
660660
if #[cfg(not(target_vendor = "uwp"))] {
661+
pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
662+
661663
extern "system" {
662664
#[link_name = "SystemFunction036"]
663665
pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
666+
667+
pub fn SetHandleInformation(hObject: HANDLE,
668+
dwMask: DWORD,
669+
dwFlags: DWORD) -> BOOL;
664670
}
665671
}
666672
}
@@ -772,9 +778,6 @@ extern "system" {
772778
pub fn GetUserProfileDirectoryW(hToken: HANDLE,
773779
lpProfileDir: LPWSTR,
774780
lpcchSize: *mut DWORD) -> BOOL;
775-
pub fn SetHandleInformation(hObject: HANDLE,
776-
dwMask: DWORD,
777-
dwFlags: DWORD) -> BOOL;
778781
pub fn CopyFileExW(lpExistingFileName: LPCWSTR,
779782
lpNewFileName: LPCWSTR,
780783
lpProgressRoutine: LPPROGRESS_ROUTINE,

src/libstd/sys/windows/net.rs

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,26 @@ impl Socket {
9797
};
9898
let socket = unsafe {
9999
match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0,
100-
c::WSA_FLAG_OVERLAPPED) {
101-
c::INVALID_SOCKET => Err(last_error()),
100+
c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
101+
c::INVALID_SOCKET => {
102+
match c::WSAGetLastError() {
103+
c::WSAEPROTOTYPE => {
104+
match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0,
105+
c::WSA_FLAG_OVERLAPPED) {
106+
c::INVALID_SOCKET => Err(last_error()),
107+
n => {
108+
let s = Socket(n);
109+
s.set_no_inherit()?;
110+
Ok(s)
111+
},
112+
}
113+
},
114+
n => Err(io::Error::from_raw_os_error(n)),
115+
}
116+
},
102117
n => Ok(Socket(n)),
103118
}
104119
}?;
105-
socket.set_no_inherit()?;
106120
Ok(socket)
107121
}
108122

@@ -168,7 +182,6 @@ impl Socket {
168182
n => Ok(Socket(n)),
169183
}
170184
}?;
171-
socket.set_no_inherit()?;
172185
Ok(socket)
173186
}
174187

@@ -178,16 +191,34 @@ impl Socket {
178191
cvt(c::WSADuplicateSocketW(self.0,
179192
c::GetCurrentProcessId(),
180193
&mut info))?;
194+
181195
match c::WSASocketW(info.iAddressFamily,
182196
info.iSocketType,
183197
info.iProtocol,
184198
&mut info, 0,
185-
c::WSA_FLAG_OVERLAPPED) {
186-
c::INVALID_SOCKET => Err(last_error()),
199+
c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
200+
c::INVALID_SOCKET => {
201+
match c::WSAGetLastError() {
202+
c::WSAEPROTOTYPE => {
203+
match c::WSASocketW(info.iAddressFamily,
204+
info.iSocketType,
205+
info.iProtocol,
206+
&mut info, 0,
207+
c::WSA_FLAG_OVERLAPPED) {
208+
c::INVALID_SOCKET => Err(last_error()),
209+
n => {
210+
let s = Socket(n);
211+
s.set_no_inherit()?;
212+
Ok(s)
213+
},
214+
}
215+
},
216+
n => Err(io::Error::from_raw_os_error(n)),
217+
}
218+
},
187219
n => Ok(Socket(n)),
188220
}
189221
}?;
190-
socket.set_no_inherit()?;
191222
Ok(socket)
192223
}
193224

@@ -312,13 +343,19 @@ impl Socket {
312343
}
313344
}
314345

346+
#[cfg(not(target_vendor = "uwp"))]
315347
fn set_no_inherit(&self) -> io::Result<()> {
316348
sys::cvt(unsafe {
317349
c::SetHandleInformation(self.0 as c::HANDLE,
318350
c::HANDLE_FLAG_INHERIT, 0)
319351
}).map(|_| ())
320352
}
321353

354+
#[cfg(target_vendor = "uwp")]
355+
fn set_no_inherit(&self) -> io::Result<()> {
356+
Err(io::Error::new(io::ErrorKind::Other, "Unavailable on UWP"))
357+
}
358+
322359
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
323360
let how = match how {
324361
Shutdown::Write => c::SD_SEND,

src/libstd/sys/windows/pipe.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub struct Pipes {
4545
/// mode. This means that technically speaking it should only ever be used
4646
/// with `OVERLAPPED` instances, but also works out ok if it's only ever used
4747
/// once at a time (which we do indeed guarantee).
48-
pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> {
48+
pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result<Pipes> {
4949
// Note that we specifically do *not* use `CreatePipe` here because
5050
// unfortunately the anonymous pipes returned do not support overlapped
5151
// operations. Instead, we create a "hopefully unique" name and create a
@@ -137,6 +137,13 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> {
137137
opts.write(ours_readable);
138138
opts.read(!ours_readable);
139139
opts.share_mode(0);
140+
let size = mem::size_of::<c::SECURITY_ATTRIBUTES>();
141+
let mut sa = c::SECURITY_ATTRIBUTES {
142+
nLength: size as c::DWORD,
143+
lpSecurityDescriptor: ptr::null_mut(),
144+
bInheritHandle: their_handle_inheritable as i32,
145+
};
146+
opts.security_attributes(&mut sa);
140147
let theirs = File::open(Path::new(&name), &opts)?;
141148
let theirs = AnonPipe { inner: theirs.into_handle() };
142149

src/libstd/sys/windows/process.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,13 +267,8 @@ impl Stdio {
267267

268268
Stdio::MakePipe => {
269269
let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
270-
let pipes = pipe::anon_pipe(ours_readable)?;
270+
let pipes = pipe::anon_pipe(ours_readable, true)?;
271271
*pipe = Some(pipes.ours);
272-
cvt(unsafe {
273-
c::SetHandleInformation(pipes.theirs.handle().raw(),
274-
c::HANDLE_FLAG_INHERIT,
275-
c::HANDLE_FLAG_INHERIT)
276-
})?;
277272
Ok(pipes.theirs.into_handle())
278273
}
279274

0 commit comments

Comments
 (0)