networks-2.rs/network/windows/src/errors.rs

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);
}