use std::ffi::{CStr, CString, c_char}; use std::ptr; use std::ptr::null_mut; use std::slice::from_raw_parts_mut; use windows::Win32::Foundation::{HLOCAL, LocalFree, WIN32_ERROR}; use windows::Win32::Networking::WinSock::WSA_ERROR; use windows::Win32::System::Diagnostics::Debug::{ FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS, FormatMessageA, }; use windows::core::{HRESULT, PSTR}; trait ErrCode { fn to_dword(&self) -> u32; } impl ErrCode for WSA_ERROR { fn to_dword(&self) -> u32 { return i32::to_dword(&self.0) } } impl ErrCode for u32 { fn to_dword(&self) -> u32 { return *self; } } impl ErrCode for i32 { fn to_dword(&self) -> u32 { return 0u32 .checked_add_signed(*self) .unwrap_or_else(|| panic!("Cast i32 -> u32 overflow")); } } impl ErrCode for HRESULT { fn to_dword(&self) -> u32 { return i32::to_dword(&self.0) } } impl ErrCode for WIN32_ERROR { fn to_dword(&self) -> u32 { return self.0 } } pub(super) fn throw_from_windows_err_code(code: impl ErrCode) -> ! { panic!( "Windows error [{:X}]: {}", code.to_dword(), format_windows_err_code(code) ) } pub(super) fn format_windows_err_code_result(code: impl ErrCode) -> Result<(), String> { return Result::Err(format_windows_err_code(code)); } pub(super) fn format_windows_err_code(code: impl ErrCode) -> String { unsafe { let mut msg = null_mut::(); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, None, code.to_dword(), 1 << 10, PSTR(ptr::from_mut(&mut msg).cast()), 0, None, ); let mut trim_size = CStr::from_ptr(msg).count_bytes(); let msg = from_raw_parts_mut(msg, trim_size + 1); while trim_size > 0 { trim_size -= 1; match msg[trim_size] { 0x0A | 0x0D => msg[trim_size] = 0x00, _ => break, } } let msg_owned = CStr::from_ptr(msg.as_ptr()).to_str().unwrap().to_owned(); LocalFree(Some(HLOCAL(msg.as_mut_ptr().cast()))); return msg_owned; } } #[test] fn _test_works() { format_windows_err_code(0u32); }