diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-10-23 11:46:36 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-10-23 14:25:12 +0200 |
| commit | c641c388c24ddee0d8fcfe5031d36dbfe25b5746 (patch) | |
| tree | c9ed56a55e19425a2eb6f7e67a257f14e1a07c4d | |
| parent | d8157467bf48e81e91ee360033bd78e938ecec8c (diff) | |
| download | mullvadvpn-c641c388c24ddee0d8fcfe5031d36dbfe25b5746.tar.xz mullvadvpn-c641c388c24ddee0d8fcfe5031d36dbfe25b5746.zip | |
Convert Windows log sink input to UTF-8
| -rw-r--r-- | talpid-core/Cargo.toml | 2 | ||||
| -rw-r--r-- | talpid-core/src/logging/windows.rs | 45 |
2 files changed, 44 insertions, 3 deletions
diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index eafceb2854..7a38c982ab 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -72,7 +72,7 @@ tun = "0.5" [target.'cfg(windows)'.dependencies] widestring = "0.4" winreg = { version = "0.7", features = ["transactions"] } -winapi = { version = "0.3.6", features = ["handleapi", "ifdef", "libloaderapi", "netioapi", "synchapi", "winbase", "winuser"] } +winapi = { version = "0.3.6", features = ["handleapi", "ifdef", "libloaderapi", "netioapi", "stringapiset", "synchapi", "winbase", "winuser"] } socket2 = "0.3" pnet_packet = "0.26" diff --git a/talpid-core/src/logging/windows.rs b/talpid-core/src/logging/windows.rs index 97d6a47b0d..c853d3cd9d 100644 --- a/talpid-core/src/logging/windows.rs +++ b/talpid-core/src/logging/windows.rs @@ -1,5 +1,6 @@ use libc::{c_char, c_void}; -use std::ffi::CStr; +use std::{ffi::CStr, io, ptr}; +use winapi::um::{stringapiset::MultiByteToWideChar, winnls::CP_ACP}; /// Logging callback type. pub type LogSink = extern "system" fn(level: log::Level, msg: *const c_char, context: *mut c_void); @@ -17,7 +18,13 @@ pub extern "system" fn log_sink(level: log::Level, msg: *const c_char, context: unsafe { CStr::from_ptr(context as *const _).to_string_lossy() } }; - let managed_msg = unsafe { CStr::from_ptr(msg).to_string_lossy() }; + let mb_string = unsafe { CStr::from_ptr(msg) }; + + let managed_msg = match multibyte_to_wide(mb_string, CP_ACP) { + Ok(wide_str) => String::from_utf16_lossy(&wide_str), + // Best effort: + Err(_) => mb_string.to_string_lossy().into_owned(), + }; log::logger().log( &log::Record::builder() @@ -28,3 +35,37 @@ pub extern "system" fn log_sink(level: log::Level, msg: *const c_char, context: ); } } + +fn multibyte_to_wide(mb_string: &CStr, codepage: u32) -> Result<Vec<u16>, io::Error> { + if unsafe { *mb_string.as_ptr() } == 0 { + return Ok(vec![]); + } + + let wc_size = + unsafe { MultiByteToWideChar(codepage, 0, mb_string.as_ptr(), -1, ptr::null_mut(), 0) }; + + if wc_size == 0 { + return Err(io::Error::last_os_error()); + } + + let mut wc_buffer = Vec::with_capacity(wc_size as usize); + + let chars_written = unsafe { + MultiByteToWideChar( + codepage, + 0, + mb_string.as_ptr(), + -1, + wc_buffer.as_mut_ptr(), + wc_size, + ) + }; + + if chars_written == 0 { + return Err(io::Error::last_os_error()); + } + + unsafe { wc_buffer.set_len((chars_written - 1) as usize) }; + + Ok(wc_buffer) +} |
