Windows: Use WriteFile to write to a UTF-8 console
This commit is contained in:
parent
9bd5f3387d
commit
1e3ecd5e4d
3 changed files with 26 additions and 1 deletions
|
@ -2425,6 +2425,7 @@ Windows.Win32.System.Console.ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
|||
Windows.Win32.System.Console.ENABLE_WINDOW_INPUT
|
||||
Windows.Win32.System.Console.ENABLE_WRAP_AT_EOL_OUTPUT
|
||||
Windows.Win32.System.Console.GetConsoleMode
|
||||
Windows.Win32.System.Console.GetConsoleOutputCP
|
||||
Windows.Win32.System.Console.GetStdHandle
|
||||
Windows.Win32.System.Console.ReadConsoleW
|
||||
Windows.Win32.System.Console.STD_ERROR_HANDLE
|
||||
|
|
|
@ -34,6 +34,7 @@ windows_targets::link!("kernel32.dll" "system" fn FreeEnvironmentStringsW(penv :
|
|||
windows_targets::link!("kernel32.dll" "system" fn GetActiveProcessorCount(groupnumber : u16) -> u32);
|
||||
windows_targets::link!("kernel32.dll" "system" fn GetCommandLineW() -> PCWSTR);
|
||||
windows_targets::link!("kernel32.dll" "system" fn GetConsoleMode(hconsolehandle : HANDLE, lpmode : *mut CONSOLE_MODE) -> BOOL);
|
||||
windows_targets::link!("kernel32.dll" "system" fn GetConsoleOutputCP() -> u32);
|
||||
windows_targets::link!("kernel32.dll" "system" fn GetCurrentDirectoryW(nbufferlength : u32, lpbuffer : PWSTR) -> u32);
|
||||
windows_targets::link!("kernel32.dll" "system" fn GetCurrentProcess() -> HANDLE);
|
||||
windows_targets::link!("kernel32.dll" "system" fn GetCurrentProcessId() -> u32);
|
||||
|
@ -3317,6 +3318,7 @@ pub struct XSAVE_FORMAT {
|
|||
pub XmmRegisters: [M128A; 8],
|
||||
pub Reserved4: [u8; 224],
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "arm")]
|
||||
#[repr(C)]
|
||||
pub struct WSADATA {
|
||||
|
|
|
@ -84,21 +84,43 @@ fn is_console(handle: c::HANDLE) -> bool {
|
|||
unsafe { c::GetConsoleMode(handle, &mut mode) != 0 }
|
||||
}
|
||||
|
||||
/// Returns true if the attached console's code page is currently UTF-8.
|
||||
#[cfg(not(target_vendor = "win7"))]
|
||||
fn is_utf8_console() -> bool {
|
||||
unsafe { c::GetConsoleOutputCP() == c::CP_UTF8 }
|
||||
}
|
||||
|
||||
#[cfg(target_vendor = "win7")]
|
||||
fn is_utf8_console() -> bool {
|
||||
// Windows 7 has a fun "feature" where WriteFile on a console handle will return
|
||||
// the number of UTF-16 code units written and not the number of bytes from the input string.
|
||||
// So we always claim the console isn't UTF-8 to trigger the WriteConsole fallback code.
|
||||
false
|
||||
}
|
||||
|
||||
fn write(handle_id: u32, data: &[u8], incomplete_utf8: &mut IncompleteUtf8) -> io::Result<usize> {
|
||||
if data.is_empty() {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let handle = get_handle(handle_id)?;
|
||||
if !is_console(handle) {
|
||||
if !is_console(handle) || is_utf8_console() {
|
||||
unsafe {
|
||||
let handle = Handle::from_raw_handle(handle);
|
||||
let ret = handle.write(data);
|
||||
let _ = handle.into_raw_handle(); // Don't close the handle
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
write_console_utf16(data, incomplete_utf8, handle)
|
||||
}
|
||||
}
|
||||
|
||||
fn write_console_utf16(
|
||||
data: &[u8],
|
||||
incomplete_utf8: &mut IncompleteUtf8,
|
||||
handle: c::HANDLE,
|
||||
) -> io::Result<usize> {
|
||||
if incomplete_utf8.len > 0 {
|
||||
assert!(
|
||||
incomplete_utf8.len < 4,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue