1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#![cfg(windows)]
use std::os::raw::{
c_ulong,
c_void,
c_ushort,
c_char
};
type DWORD = c_ulong;
const FORMAT_MESSAGE_ARGUMENT_ARRAY: DWORD = 0x00002000;
const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
extern "system" {
fn GetLastError() -> DWORD;
fn FormatMessageW(dwFlags: DWORD,
lpSource: *const c_void,
dwMessageId: DWORD,
dwLanguageId: DWORD,
lpBuffer: *mut c_ushort,
nSize: DWORD,
Arguments: *mut c_char) -> DWORD;
}
fn format_message_error(buff: &[u16]) -> String {
match unsafe {GetLastError()} {
122 => String::from_utf16_lossy(buff),
_ => "Unknown Error.".to_string()
}
}
fn format_message_ok(buff: &[u16]) -> String {
String::from_utf16_lossy(&buff[0..buff.len()-2])
}
pub fn format_error(errno: u32) -> String {
const BUF_SIZE: usize = 512;
const FMT_FLAGS: DWORD = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY;
let mut format_buff: [u16; BUF_SIZE] = [0; BUF_SIZE];
let num_chars: u32 = unsafe { FormatMessageW(FMT_FLAGS,
std::ptr::null(), errno,
0, format_buff.as_mut_ptr(),
BUF_SIZE as u32, std::ptr::null_mut()) };
if num_chars == 0 {
format_message_error(&format_buff)
} else {
format_message_ok(&format_buff[0..num_chars as usize])
}
}
use std::error::Error;
use std::fmt;
#[derive(Clone)]
pub struct WindowsError(u32);
impl WindowsError {
pub fn new(errno: u32) -> WindowsError {
WindowsError(errno)
}
pub fn from_last_err() -> WindowsError {
unsafe { WindowsError(GetLastError()) }
}
#[inline(always)]
pub fn errno(&self) -> u32 {
self.0
}
#[inline(always)]
pub fn errno_desc(&self) -> String {
format_error(self.0)
}
}
impl fmt::Debug for WindowsError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "WinAPI Error({})", self.errno())
}
}
impl fmt::Display for WindowsError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "WinAPI Error({})", self.errno())
}
}
impl Error for WindowsError {
fn description(&self) -> &str {
"WinAPI Error"
}
}
impl PartialEq for WindowsError {
fn eq(&self, right: &WindowsError) -> bool {
self.0 == right.0
}
fn ne(&self, right: &WindowsError) -> bool {
self.0 != right.0
}
}
macro_rules! impl_traits
{
($($t:ty), +) => {
$(
impl From<$t> for WindowsError {
fn from(num: $t) -> Self {
WindowsError(num as u32)
}
}
impl Into<$t> for WindowsError {
fn into(self) -> $t {
self.0 as $t
}
}
impl PartialEq<$t> for WindowsError {
fn eq(&self, right: &$t) -> bool {
self.0 == *right as u32
}
fn ne(&self, right: &$t) -> bool {
self.0 != *right as u32
}
}
)+
};
}
impl_traits!(u32, u16, u8, usize, i32, i16, i8, isize);