diff options
| author | Elahn Ientile <github@elahn.com.au> | 2016-12-10 09:46:47 +1000 |
|---|---|---|
| committer | Elahn Ientile <github@elahn.com.au> | 2016-12-10 09:46:47 +1000 |
| commit | f9bca00469f4e6826c79638a5058c838ab4c1925 (patch) | |
| tree | de621eeec786f494d602bdbbdafcafbf0ae3a8bb /src/libstd/sys/windows/stdio.rs | |
| parent | e9aa73d2bf3c94bc4ff32afeb2b20f28c677dafa (diff) | |
| download | rust-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.rs | 24 |
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 |
