use std::io::Write;
use windows::core::PCWSTR;
use windows::Win32::System::Diagnostics::Debug::{IsDebuggerPresent, OutputDebugStringW};
#[derive(Debug)]
pub struct WinDbgWriter {
buffer: Vec<u8>,
utf16_buffer: Vec<u16>,
}
impl Default for WinDbgWriter {
fn default() -> Self {
Self {
buffer: Vec::with_capacity(8 * 1024),
utf16_buffer: Vec::with_capacity(8 * 1024),
}
}
}
impl Drop for WinDbgWriter {
fn drop(&mut self) {
let _ = self.flush();
}
}
impl Write for WinDbgWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
const LINE_FEED: u8 = b'\n';
for line in buf.split_inclusive(|c| c == &LINE_FEED) {
self.buffer.extend_from_slice(line);
if line.last() == Some(&LINE_FEED) {
self.flush()?;
}
}
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
if self.buffer.is_empty() {
return Ok(());
}
self.utf16_buffer.clear();
match std::str::from_utf8(&self.buffer) {
Ok(buffer_str) => self.utf16_buffer.extend(buffer_str.encode_utf16()),
Err(err) => self
.utf16_buffer
.extend(format!("ERROR: Invalid UTF-8 in input: {err}").encode_utf16()),
}
self.buffer.clear();
self.utf16_buffer.push(0);
unsafe { OutputDebugStringW(PCWSTR::from_raw(self.utf16_buffer.as_ptr())) };
Ok(())
}
}
pub fn attached() -> bool {
unsafe { IsDebuggerPresent().as_bool() }
}