about summary refs log tree commit diff
path: root/src/libstd/sys/windows/stdio.rs
diff options
context:
space:
mode:
authorElahn Ientile <github@elahn.com.au>2016-12-10 09:46:47 +1000
committerElahn Ientile <github@elahn.com.au>2016-12-10 09:46:47 +1000
commitf9bca00469f4e6826c79638a5058c838ab4c1925 (patch)
treede621eeec786f494d602bdbbdafcafbf0ae3a8bb /src/libstd/sys/windows/stdio.rs
parente9aa73d2bf3c94bc4ff32afeb2b20f28c677dafa (diff)
downloadrust-f9bca00469f4e6826c79638a5058c838ab4c1925.tar.gz
rust-f9bca00469f4e6826c79638a5058c838ab4c1925.zip
Ctrl-Z returns from Stdin.read() when reading from the console on
Windows.
Fixes #19914.
Fixes read(), read_to_string(), read_to_end(), etc.
Diffstat (limited to 'src/libstd/sys/windows/stdio.rs')
-rw-r--r--src/libstd/sys/windows/stdio.rs24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index 72788776ded..e4335b9d0bb 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -111,19 +111,27 @@ impl Stdin {
         if utf8.position() as usize == utf8.get_ref().len() {
             let mut utf16 = vec![0u16; 0x1000];
             let mut num = 0;
+            let mut input_control = readconsole_input_control(CTRL_Z_MASK);
             cvt(unsafe {
                 c::ReadConsoleW(handle,
                                 utf16.as_mut_ptr() as c::LPVOID,
                                 utf16.len() as u32,
                                 &mut num,
-                                ptr::null_mut())
+                                &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL)
             })?;
             utf16.truncate(num as usize);
             // FIXME: what to do about this data that has already been read?
-            let data = match String::from_utf16(&utf16) {
+            let mut data = match String::from_utf16(&utf16) {
                 Ok(utf8) => utf8.into_bytes(),
                 Err(..) => return Err(invalid_encoding()),
             };
+            if let Output::Console(_) = self.handle {
+                if let Some(&last_byte) = data.last() {
+                    if last_byte == CTRL_Z {
+                        data.pop();
+                    }
+                }
+            }
             *utf8 = Cursor::new(data);
         }
 
@@ -206,6 +214,18 @@ fn invalid_encoding() -> io::Error {
     io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
 }
 
+fn readconsole_input_control(wakeup_mask: c::ULONG) -> c::CONSOLE_READCONSOLE_CONTROL {
+    c::CONSOLE_READCONSOLE_CONTROL {
+        nLength: ::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG,
+        nInitialChars: 0,
+        dwCtrlWakeupMask: wakeup_mask,
+        dwControlKeyState: 0,
+    }
+}
+
+const CTRL_Z: u8 = 0x1A;
+const CTRL_Z_MASK: c::ULONG = 0x4000000; //1 << 0x1A
+
 pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32;
 // The default buffer capacity is 64k, but apparently windows
 // doesn't like 64k reads on stdin. See #13304 for details, but the