Rollup merge of #103637 - ChrisDenton:stdio-uwp, r=thomcc
Use stdio in UWP apps Fixes #103233 This has been supported since Windows 10.0.16299. See https://learn.microsoft.com/en-us/uwp/win32-and-com/win32-apis#apis-from-api-ms-win-core-console-l1-1-0dll
This commit is contained in:
commit
65d63caf8d
@ -56,6 +56,7 @@ pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
|
||||
pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES;
|
||||
pub type LPSTARTUPINFO = *mut STARTUPINFO;
|
||||
pub type LPVOID = *mut c_void;
|
||||
pub type LPCVOID = *const c_void;
|
||||
pub type LPWCH = *mut WCHAR;
|
||||
pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
|
||||
pub type LPWSADATA = *mut WSADATA;
|
||||
@ -773,6 +774,16 @@ pub struct timeval {
|
||||
pub tv_usec: c_long,
|
||||
}
|
||||
|
||||
#[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;
|
||||
|
||||
// Desktop specific functions & types
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(target_vendor = "uwp"))] {
|
||||
@ -801,17 +812,6 @@ if #[cfg(not(target_vendor = "uwp"))] {
|
||||
pub type PVECTORED_EXCEPTION_HANDLER =
|
||||
extern "system" fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;
|
||||
|
||||
#[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,
|
||||
@ -827,7 +827,6 @@ if #[cfg(not(target_vendor = "uwp"))] {
|
||||
}
|
||||
|
||||
pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
|
||||
pub type LPCVOID = *const c_void;
|
||||
|
||||
pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
|
||||
|
||||
@ -855,24 +854,6 @@ if #[cfg(not(target_vendor = "uwp"))] {
|
||||
|
||||
#[link(name = "kernel32")]
|
||||
extern "system" {
|
||||
// Functions forbidden when targeting UWP
|
||||
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 GetFileInformationByHandle(
|
||||
hFile: HANDLE,
|
||||
@ -914,6 +895,22 @@ if #[cfg(target_vendor = "uwp")] {
|
||||
extern "system" {
|
||||
pub fn GetCurrentProcessId() -> DWORD;
|
||||
|
||||
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 GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT;
|
||||
pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
|
||||
pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL;
|
||||
|
@ -29,6 +29,7 @@ pub mod path;
|
||||
pub mod pipe;
|
||||
pub mod process;
|
||||
pub mod rand;
|
||||
pub mod stdio;
|
||||
pub mod thread;
|
||||
pub mod thread_local_dtor;
|
||||
pub mod thread_local_key;
|
||||
@ -36,12 +37,9 @@ pub mod thread_parker;
|
||||
pub mod time;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(not(target_vendor = "uwp"))] {
|
||||
pub mod stdio;
|
||||
pub mod stack_overflow;
|
||||
} else {
|
||||
pub mod stdio_uwp;
|
||||
pub mod stack_overflow_uwp;
|
||||
pub use self::stdio_uwp as stdio;
|
||||
pub use self::stack_overflow_uwp as stack_overflow;
|
||||
}
|
||||
}
|
||||
|
@ -1,87 +0,0 @@
|
||||
#![unstable(issue = "none", feature = "windows_stdio")]
|
||||
|
||||
use crate::io;
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::os::windows::io::FromRawHandle;
|
||||
use crate::sys::c;
|
||||
use crate::sys::handle::Handle;
|
||||
|
||||
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)?;
|
||||
// SAFETY: The handle returned from `get_handle` must be valid and non-null.
|
||||
let handle = unsafe { Handle::from_raw_handle(handle) };
|
||||
ManuallyDrop::new(handle).write(data)
|
||||
}
|
||||
|
||||
impl Stdin {
|
||||
pub const fn new() -> Stdin {
|
||||
Stdin {}
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let handle = get_handle(c::STD_INPUT_HANDLE)?;
|
||||
// SAFETY: The handle returned from `get_handle` must be valid and non-null.
|
||||
let handle = unsafe { Handle::from_raw_handle(handle) };
|
||||
ManuallyDrop::new(handle).read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Stdout {
|
||||
pub const fn new() -> Stdout {
|
||||
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 const fn new() -> Stderr {
|
||||
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> {
|
||||
Some(Stderr::new())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user