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)
This commit is contained in:
parent
9407ed759f
commit
a713a0399a
4 changed files with 61 additions and 19 deletions
|
@ -121,6 +121,7 @@ impl Clone for WIN32_FIND_DATAW {
|
|||
}
|
||||
|
||||
pub const WSA_FLAG_OVERLAPPED: DWORD = 0x01;
|
||||
pub const WSA_FLAG_NO_HANDLE_INHERIT: DWORD = 0x80;
|
||||
|
||||
pub const WSADESCRIPTION_LEN: usize = 256;
|
||||
pub const WSASYS_STATUS_LEN: usize = 128;
|
||||
|
@ -130,6 +131,7 @@ pub const INVALID_SOCKET: SOCKET = !0;
|
|||
pub const WSAEACCES: c_int = 10013;
|
||||
pub const WSAEINVAL: c_int = 10022;
|
||||
pub const WSAEWOULDBLOCK: c_int = 10035;
|
||||
pub const WSAEPROTOTYPE: c_int = 10041;
|
||||
pub const WSAEADDRINUSE: c_int = 10048;
|
||||
pub const WSAEADDRNOTAVAIL: c_int = 10049;
|
||||
pub const WSAECONNABORTED: c_int = 10053;
|
||||
|
@ -157,8 +159,6 @@ pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
|
|||
pub const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
|
||||
pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
|
||||
|
||||
pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
|
||||
|
||||
pub const PROGRESS_CONTINUE: DWORD = 0;
|
||||
|
||||
pub const ERROR_FILE_NOT_FOUND: DWORD = 2;
|
||||
|
@ -658,9 +658,15 @@ pub struct timeval {
|
|||
// Functions forbidden when targeting UWP
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(target_vendor = "uwp"))] {
|
||||
pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
|
||||
|
||||
extern "system" {
|
||||
#[link_name = "SystemFunction036"]
|
||||
pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
|
||||
|
||||
pub fn SetHandleInformation(hObject: HANDLE,
|
||||
dwMask: DWORD,
|
||||
dwFlags: DWORD) -> BOOL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -772,9 +778,6 @@ extern "system" {
|
|||
pub fn GetUserProfileDirectoryW(hToken: HANDLE,
|
||||
lpProfileDir: LPWSTR,
|
||||
lpcchSize: *mut DWORD) -> BOOL;
|
||||
pub fn SetHandleInformation(hObject: HANDLE,
|
||||
dwMask: DWORD,
|
||||
dwFlags: DWORD) -> BOOL;
|
||||
pub fn CopyFileExW(lpExistingFileName: LPCWSTR,
|
||||
lpNewFileName: LPCWSTR,
|
||||
lpProgressRoutine: LPPROGRESS_ROUTINE,
|
||||
|
|
|
@ -97,12 +97,26 @@ impl Socket {
|
|||
};
|
||||
let socket = unsafe {
|
||||
match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0,
|
||||
c::WSA_FLAG_OVERLAPPED) {
|
||||
c::INVALID_SOCKET => Err(last_error()),
|
||||
c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
|
||||
c::INVALID_SOCKET => {
|
||||
match c::WSAGetLastError() {
|
||||
c::WSAEPROTOTYPE => {
|
||||
match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0,
|
||||
c::WSA_FLAG_OVERLAPPED) {
|
||||
c::INVALID_SOCKET => Err(last_error()),
|
||||
n => {
|
||||
let s = Socket(n);
|
||||
s.set_no_inherit()?;
|
||||
Ok(s)
|
||||
},
|
||||
}
|
||||
},
|
||||
n => Err(io::Error::from_raw_os_error(n)),
|
||||
}
|
||||
},
|
||||
n => Ok(Socket(n)),
|
||||
}
|
||||
}?;
|
||||
socket.set_no_inherit()?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
|
@ -168,7 +182,6 @@ impl Socket {
|
|||
n => Ok(Socket(n)),
|
||||
}
|
||||
}?;
|
||||
socket.set_no_inherit()?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
|
@ -178,16 +191,34 @@ impl Socket {
|
|||
cvt(c::WSADuplicateSocketW(self.0,
|
||||
c::GetCurrentProcessId(),
|
||||
&mut info))?;
|
||||
|
||||
match c::WSASocketW(info.iAddressFamily,
|
||||
info.iSocketType,
|
||||
info.iProtocol,
|
||||
&mut info, 0,
|
||||
c::WSA_FLAG_OVERLAPPED) {
|
||||
c::INVALID_SOCKET => Err(last_error()),
|
||||
c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) {
|
||||
c::INVALID_SOCKET => {
|
||||
match c::WSAGetLastError() {
|
||||
c::WSAEPROTOTYPE => {
|
||||
match c::WSASocketW(info.iAddressFamily,
|
||||
info.iSocketType,
|
||||
info.iProtocol,
|
||||
&mut info, 0,
|
||||
c::WSA_FLAG_OVERLAPPED) {
|
||||
c::INVALID_SOCKET => Err(last_error()),
|
||||
n => {
|
||||
let s = Socket(n);
|
||||
s.set_no_inherit()?;
|
||||
Ok(s)
|
||||
},
|
||||
}
|
||||
},
|
||||
n => Err(io::Error::from_raw_os_error(n)),
|
||||
}
|
||||
},
|
||||
n => Ok(Socket(n)),
|
||||
}
|
||||
}?;
|
||||
socket.set_no_inherit()?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
|
@ -312,6 +343,7 @@ impl Socket {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_vendor = "uwp"))]
|
||||
fn set_no_inherit(&self) -> io::Result<()> {
|
||||
sys::cvt(unsafe {
|
||||
c::SetHandleInformation(self.0 as c::HANDLE,
|
||||
|
@ -319,6 +351,11 @@ impl Socket {
|
|||
}).map(|_| ())
|
||||
}
|
||||
|
||||
#[cfg(target_vendor = "uwp")]
|
||||
fn set_no_inherit(&self) -> io::Result<()> {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "Unavailable on UWP"))
|
||||
}
|
||||
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
let how = match how {
|
||||
Shutdown::Write => c::SD_SEND,
|
||||
|
|
|
@ -45,7 +45,7 @@ pub struct Pipes {
|
|||
/// mode. This means that technically speaking it should only ever be used
|
||||
/// with `OVERLAPPED` instances, but also works out ok if it's only ever used
|
||||
/// once at a time (which we do indeed guarantee).
|
||||
pub fn anon_pipe(ours_readable: bool) -> io::Result<Pipes> {
|
||||
pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result<Pipes> {
|
||||
// Note that we specifically do *not* use `CreatePipe` here because
|
||||
// unfortunately the anonymous pipes returned do not support overlapped
|
||||
// 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> {
|
|||
opts.write(ours_readable);
|
||||
opts.read(!ours_readable);
|
||||
opts.share_mode(0);
|
||||
let size = mem::size_of::<c::SECURITY_ATTRIBUTES>();
|
||||
let mut sa = c::SECURITY_ATTRIBUTES {
|
||||
nLength: size as c::DWORD,
|
||||
lpSecurityDescriptor: ptr::null_mut(),
|
||||
bInheritHandle: their_handle_inheritable as i32,
|
||||
};
|
||||
opts.security_attributes(&mut sa);
|
||||
let theirs = File::open(Path::new(&name), &opts)?;
|
||||
let theirs = AnonPipe { inner: theirs.into_handle() };
|
||||
|
||||
|
|
|
@ -267,13 +267,8 @@ impl Stdio {
|
|||
|
||||
Stdio::MakePipe => {
|
||||
let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
|
||||
let pipes = pipe::anon_pipe(ours_readable)?;
|
||||
let pipes = pipe::anon_pipe(ours_readable, true)?;
|
||||
*pipe = Some(pipes.ours);
|
||||
cvt(unsafe {
|
||||
c::SetHandleInformation(pipes.theirs.handle().raw(),
|
||||
c::HANDLE_FLAG_INHERIT,
|
||||
c::HANDLE_FLAG_INHERIT)
|
||||
})?;
|
||||
Ok(pipes.theirs.into_handle())
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue