98 lines
2.4 KiB
Rust
98 lines
2.4 KiB
Rust
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::<c_char>();
|
|
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);
|
|
}
|