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
#![cfg(windows)]
use std::{
io::{
self,
ErrorKind,
},
};
use winapi::{
ctypes::c_void,
shared::{
minwindef::HGLOBAL,
winerror::HRESULT,
},
um::{
winbase::{
GlobalUnlock,
GlobalLock,
},
},
};
pub mod clipboard;
pub mod com;
pub mod keyboard;
pub mod process;
pub mod ui;
pub(crate) trait WinErrCheckable: Sized + Copy {
fn if_null_get_last_error(self) -> io::Result<Self> {
if self.is_null() {
Err(io::Error::last_os_error())
} else {
Ok(self)
}
}
fn if_null_to_error(self, error_gen: impl Fn() -> io::Error) -> io::Result<Self> {
if self.is_null() {
Err(error_gen())
} else {
Ok(self)
}
}
fn if_null_panic(self) -> Self {
if self.is_null() {
panic!()
} else {
self
}
}
fn is_null(self) -> bool;
}
impl WinErrCheckable for *mut c_void {
fn is_null(self) -> bool {
self.is_null()
}
}
impl WinErrCheckable for u32 {
fn is_null(self) -> bool {
self == 0
}
}
impl WinErrCheckable for i32 {
fn is_null(self) -> bool {
self == 0
}
}
pub(crate) fn custom_hresult_err<T>(err_text: &str, hresult: HRESULT) -> io::Result<T> {
Err(io::Error::new(
ErrorKind::Other,
format!("{}. Code: {}", err_text, hresult),
))
}
pub(crate) struct GlobalLockedData<'ptr> {
handle: HGLOBAL,
ptr: &'ptr mut c_void,
}
impl GlobalLockedData<'_> {
pub(crate) fn lock(handle: *mut c_void) -> io::Result<Self> {
unsafe {
GlobalLock(handle)
.if_null_get_last_error()
.map(|ptr| GlobalLockedData {
handle,
ptr: ptr.as_mut().expect("Unexpected null from GlobalLock"),
})
}
}
#[inline(always)]
pub(crate) fn ptr(&mut self) -> *mut c_void {
self.ptr
}
}
impl Drop for GlobalLockedData<'_> {
fn drop(&mut self) {
unsafe {
GlobalUnlock(self.handle);
}
}
}