summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2020-10-23 11:46:36 +0200
committerDavid Lönnhager <david.l@mullvad.net>2020-10-23 14:25:12 +0200
commitc641c388c24ddee0d8fcfe5031d36dbfe25b5746 (patch)
treec9ed56a55e19425a2eb6f7e67a257f14e1a07c4d
parentd8157467bf48e81e91ee360033bd78e938ecec8c (diff)
downloadmullvadvpn-c641c388c24ddee0d8fcfe5031d36dbfe25b5746.tar.xz
mullvadvpn-c641c388c24ddee0d8fcfe5031d36dbfe25b5746.zip
Convert Windows log sink input to UTF-8
-rw-r--r--talpid-core/Cargo.toml2
-rw-r--r--talpid-core/src/logging/windows.rs45
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)
+}