Skip to content

Instantly share code, notes, and snippets.

@sagacity
Last active June 26, 2025 09:52
Show Gist options
  • Save sagacity/0f37823cdd1af412722d3c47ee62276d to your computer and use it in GitHub Desktop.
Save sagacity/0f37823cdd1af412722d3c47ee62276d to your computer and use it in GitHub Desktop.
Capture OutputDebugString in Windows and emits the result to either the log (if enabled) or via println
use std::ffi::c_void;
use std::slice;
use log::{info, log_enabled, Level};
use windows::core::s;
use windows::Win32::Foundation::{FALSE, HANDLE, INVALID_HANDLE_VALUE};
use windows::Win32::System::Diagnostics::Debug::IsDebuggerPresent;
use windows::Win32::System::Memory::{CreateFileMappingA, MapViewOfFile, FILE_MAP_READ, PAGE_READWRITE, SECTION_MAP_READ};
use windows::Win32::System::Threading::{CreateEventA, CreateEventW, CreateThread, SetEvent, WaitForSingleObject, INFINITE, THREAD_CREATE_RUN_IMMEDIATELY, THREAD_CREATION_FLAGS, GetCurrentProcessId};
#[repr(C)]
struct OdsBuffer {
process_id: u32,
data: [u8; 4092],
}
unsafe extern "system" fn ods_proc(args: *mut c_void) -> u32 {
let file = CreateFileMappingA(INVALID_HANDLE_VALUE, None, PAGE_READWRITE, 0, size_of::<OdsBuffer>() as u32, s!("DBWIN_BUFFER")).unwrap();
let ods_buffer = MapViewOfFile(file, FILE_MAP_READ, 0, 0, 0);
let ods_buffer = ods_buffer.Value as *const OdsBuffer;
let ods_buffer_ready = CreateEventA(None, false, false, s!("DBWIN_BUFFER_READY")).unwrap();
let ods_data_ready = CreateEventA(None, false, false, s!("DBWIN_DATA_READY")).unwrap();
loop {
SetEvent(ods_buffer_ready).unwrap();
let wait = WaitForSingleObject(ods_data_ready, INFINITE);
let mut length: usize = 0;
while length < 4092 && (*ods_buffer).data[length] != 0 {
length += 1;
}
if length != 0 && (*ods_buffer).process_id == GetCurrentProcessId() {
let data: &[u8] = slice::from_raw_parts(&(*ods_buffer).data[0], length);
let str = std::str::from_utf8(data).unwrap().trim();
if log_enabled!(Level::Info) {
info!("{}", str);
} else {
println!("{}", str);
}
}
}
}
pub fn ods_capture() {
unsafe {
let thread = CreateThread(None, 0, Some(ods_proc), None, THREAD_CREATE_RUN_IMMEDIATELY, None).unwrap();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment