]> git.lizzy.rs Git - rust.git/commitdiff
std: win: Don't use console APIs on UWP
authorHugo Beauzée-Luyssen <hugo@beauzee.fr>
Mon, 27 May 2019 15:15:27 +0000 (17:15 +0200)
committerHugo Beauzée-Luyssen <hugo@beauzee.fr>
Thu, 25 Jul 2019 19:30:08 +0000 (21:30 +0200)
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/mod.rs
src/libstd/sys/windows/stdio_uwp.rs [new file with mode: 0644]

index 6b4d6d9e23b81718268a05ca0d6720cddee51b62..9d7f3a89d6fdcfd8797e142561917dc09984ca84 100644 (file)
@@ -35,7 +35,6 @@
 pub type LPBOOL = *mut BOOL;
 pub type LPBYTE = *mut BYTE;
 pub type LPCSTR = *const CHAR;
-pub type LPCVOID = *const c_void;
 pub type LPCWSTR = *const WCHAR;
 pub type LPDWORD = *mut DWORD;
 pub type LPHANDLE = *mut HANDLE;
@@ -609,16 +608,6 @@ pub enum EXCEPTION_DISPOSITION {
     ExceptionCollidedUnwind
 }
 
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct CONSOLE_READCONSOLE_CONTROL {
-    pub nLength: ULONG,
-    pub nInitialChars: ULONG,
-    pub dwCtrlWakeupMask: ULONG,
-    pub dwControlKeyState: ULONG,
-}
-pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
-
 #[repr(C)]
 #[derive(Copy)]
 pub struct fd_set {
@@ -642,6 +631,17 @@ pub struct timeval {
 // Functions forbidden when targeting UWP
 cfg_if::cfg_if! {
 if #[cfg(not(target_vendor = "uwp"))] {
+    #[repr(C)]
+    #[derive(Copy, Clone)]
+    pub struct CONSOLE_READCONSOLE_CONTROL {
+        pub nLength: ULONG,
+        pub nInitialChars: ULONG,
+        pub dwCtrlWakeupMask: ULONG,
+        pub dwControlKeyState: ULONG,
+    }
+
+    pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
+
     #[repr(C)]
     pub struct BY_HANDLE_FILE_INFORMATION {
         pub dwFileAttributes: DWORD,
@@ -657,6 +657,7 @@ pub struct BY_HANDLE_FILE_INFORMATION {
     }
 
     pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
+    pub type LPCVOID = *const c_void;
 
     pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
 
@@ -666,6 +667,20 @@ pub struct BY_HANDLE_FILE_INFORMATION {
         #[link_name = "SystemFunction036"]
         pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
 
+        pub fn ReadConsoleW(hConsoleInput: HANDLE,
+                            lpBuffer: LPVOID,
+                            nNumberOfCharsToRead: DWORD,
+                            lpNumberOfCharsRead: LPDWORD,
+                            pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL;
+
+        pub fn WriteConsoleW(hConsoleOutput: HANDLE,
+                             lpBuffer: LPCVOID,
+                             nNumberOfCharsToWrite: DWORD,
+                             lpNumberOfCharsWritten: LPDWORD,
+                             lpReserved: LPVOID) -> BOOL;
+
+        pub fn GetConsoleMode(hConsoleHandle: HANDLE,
+                              lpMode: LPDWORD) -> BOOL;
         // Allowed but unused by UWP
         pub fn OpenProcessToken(ProcessHandle: HANDLE,
                                 DesiredAccess: DWORD,
@@ -752,20 +767,6 @@ pub fn WSASocketW(af: c_int,
     pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
     pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
 
-    pub fn ReadConsoleW(hConsoleInput: HANDLE,
-                        lpBuffer: LPVOID,
-                        nNumberOfCharsToRead: DWORD,
-                        lpNumberOfCharsRead: LPDWORD,
-                        pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL;
-
-    pub fn WriteConsoleW(hConsoleOutput: HANDLE,
-                         lpBuffer: LPCVOID,
-                         nNumberOfCharsToWrite: DWORD,
-                         lpNumberOfCharsWritten: LPDWORD,
-                         lpReserved: LPVOID) -> BOOL;
-
-    pub fn GetConsoleMode(hConsoleHandle: HANDLE,
-                          lpMode: LPDWORD) -> BOOL;
     pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
     pub fn SetFileAttributesW(lpFileName: LPCWSTR,
                               dwFileAttributes: DWORD) -> BOOL;
index 36fb1fb5ff68d7086a397d037cc09c509c0e4f24..95465db089fab84989615c3ff94d1dba96c9f192 100644 (file)
 pub mod thread;
 pub mod thread_local;
 pub mod time;
-pub mod stdio;
+cfg_if::cfg_if! {
+    if #[cfg(not(target_vendor = "uwp"))] {
+        pub mod stdio;
+    } else {
+        pub mod stdio_uwp;
+        pub use self::stdio_uwp as stdio;
+    }
+}
 
 #[cfg(not(test))]
 pub fn init() {
diff --git a/src/libstd/sys/windows/stdio_uwp.rs b/src/libstd/sys/windows/stdio_uwp.rs
new file mode 100644 (file)
index 0000000..489d3df
--- /dev/null
@@ -0,0 +1,85 @@
+#![unstable(issue = "0", feature = "windows_stdio")]
+
+use crate::io;
+use crate::sys::c;
+use crate::sys::handle::Handle;
+use crate::mem::ManuallyDrop;
+
+pub struct Stdin {
+}
+pub struct Stdout;
+pub struct Stderr;
+
+const MAX_BUFFER_SIZE: usize = 8192;
+pub const STDIN_BUF_SIZE: usize = MAX_BUFFER_SIZE / 2 * 3;
+
+pub fn get_handle(handle_id: c::DWORD) -> io::Result<c::HANDLE> {
+    let handle = unsafe { c::GetStdHandle(handle_id) };
+    if handle == c::INVALID_HANDLE_VALUE {
+        Err(io::Error::last_os_error())
+    } else if handle.is_null() {
+        Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32))
+    } else {
+        Ok(handle)
+    }
+}
+
+fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
+    let handle = get_handle(handle_id)?;
+    let handle = Handle::new(handle);
+    ManuallyDrop::new(handle).write(data)
+}
+
+impl Stdin {
+    pub fn new() -> io::Result<Stdin> {
+        Ok(Stdin { })
+    }
+}
+
+impl io::Read for Stdin {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        let handle = get_handle(c::STD_INPUT_HANDLE)?;
+        let handle = Handle::new(handle);
+        ManuallyDrop::new(handle).read(buf)
+    }
+}
+
+impl Stdout {
+    pub fn new() -> io::Result<Stdout> {
+        Ok(Stdout)
+    }
+}
+
+impl io::Write for Stdout {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        write(c::STD_OUTPUT_HANDLE, buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl Stderr {
+    pub fn new() -> io::Result<Stderr> {
+        Ok(Stderr)
+    }
+}
+
+impl io::Write for Stderr {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        write(c::STD_ERROR_HANDLE, buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32)
+}
+
+pub fn panic_output() -> Option<impl io::Write> {
+    Stderr::new().ok()
+}