about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHugo Beauzée-Luyssen <hugo@beauzee.fr>2019-05-27 16:51:29 +0200
committerHugo Beauzée-Luyssen <hugo@beauzee.fr>2019-07-25 21:30:08 +0200
commita713a0399a6e63de1c8009a390ae964ff03f4067 (patch)
tree9154a6d4ac29ade41d40fca9933f67332431ed7d
parent9407ed759fd31fca3c32c1bc3b3e2f26313c462f (diff)
downloadrust-a713a0399a6e63de1c8009a390ae964ff03f4067.tar.gz
rust-a713a0399a6e63de1c8009a390ae964ff03f4067.zip
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)
-rw-r--r--src/libstd/sys/windows/c.rs13
-rw-r--r--src/libstd/sys/windows/net.rs51
-rw-r--r--src/libstd/sys/windows/pipe.rs9
-rw-r--r--src/libstd/sys/windows/process.rs7
4 files changed, 61 insertions, 19 deletions
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 9738c9daf7c..2cec96e0016 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -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,
diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs
index 7dd1af5441b..32f4011fb32 100644
--- a/src/libstd/sys/windows/net.rs
+++ b/src/libstd/sys/windows/net.rs
@@ -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,
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index c77f30dfc71..041d5385eb6 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -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() };
 
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index e39b7ae8890..05e0ca67064 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -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())
             }