std: win: Don't use console APIs on UWP

This commit is contained in:
Hugo Beauzée-Luyssen 2019-05-27 17:15:27 +02:00
parent 4c05073d1d
commit 668f0d3495
3 changed files with 119 additions and 26 deletions

View 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;

View File

@ -37,7 +37,14 @@
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() {

View File

@ -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()
}