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
use std::ops::Deref;
use winapi::{
um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE},
um::winnt::HANDLE
};
/// Wraps a windows [HANDLE].
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Handle(RawHandle);
/// Wraps the actual [HANDLE] and drop if owned.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
struct RawHandle {
handle: HANDLE,
ownership: HandleOwnership,
}
// Synchronize the [Inner].
unsafe impl Send for RawHandle {}
unsafe impl Sync for RawHandle {}
/// Represents the ownership of a `HANDLE`.
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
enum HandleOwnership {
/// The handle is owned by the instance so should be close.
Owned,
/// The handle is used for others instances, so cannot be close.
Shared,
}
impl Drop for Handle {
fn drop(&mut self) {
if self.0.ownership == HandleOwnership::Owned {
assert!(unsafe { CloseHandle(**self) != 0 }, "Cannot close the handle")
}
}
}
impl Handle {
/// Creates a new shared `Handle` from the specified.
///
/// # Examples
///
/// Basic usages:
/// ```
/// use winapi::um::winbase::STD_INPUT_HANDLE;
/// use winapi::um::processenv::GetStdHandle;
/// use win32console::structs::handle::Handle;
///
/// let handle = Handle::new(unsafe { GetStdHandle(STD_INPUT_HANDLE) });
/// assert!(handle.is_valid());
/// ```
#[inline]
pub fn new(handle: HANDLE) -> Handle {
Handle(RawHandle { handle, ownership: HandleOwnership::Shared })
}
/// Creates a new `Handle` from the specified which will be close
/// when goes out of scope by calling [CloseHandle].
///
/// # Examples
///
/// Basic usages:
/// ```
/// use win32console::structs::handle::Handle;
/// use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
/// use winapi::um::handleapi::INVALID_HANDLE_VALUE;
/// use winapi::um::winnt::{GENERIC_READ, FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_WRITE};
/// use std::ptr::null_mut;
///
/// let file_name: Vec<u16> = "CONIN$\0".encode_utf16().collect();
/// let handle = Handle::new_owned(unsafe { CreateFileW(
/// file_name.as_ptr(),
/// GENERIC_READ | GENERIC_WRITE,
/// FILE_SHARE_READ | FILE_SHARE_WRITE,
/// null_mut(),
/// OPEN_EXISTING,
/// 0,
/// null_mut(),
/// ) });
/// assert_ne!(*handle, INVALID_HANDLE_VALUE);
/// ```
#[inline]
pub fn new_owned(handle: HANDLE) -> Handle {
Handle(RawHandle { handle, ownership: HandleOwnership::Owned })
}
/// Gets a reference to the underlying `HANDLE`.
///
/// # Examples
///
/// Basic usages:
/// ```
/// use win32console::structs::handle::Handle;
/// use winapi::um::processenv::GetStdHandle;
/// use winapi::um::winbase::STD_INPUT_HANDLE;
/// use winapi::um::winnt::HANDLE;
/// use winapi::um::handleapi::INVALID_HANDLE_VALUE;
///
/// let handle = Handle::new(unsafe { GetStdHandle(STD_INPUT_HANDLE) });
/// let raw_handle = handle.get_raw();
/// assert_ne!(raw_handle, INVALID_HANDLE_VALUE);
/// ```
#[inline]
pub fn get_raw(&self) -> HANDLE {
self.0.handle
}
/// Compare this handle to [INVALID_HANDLE_VALUE] to determines if the handle is valid.
///
/// # Examples:
///
/// Basic usages:
/// ```
/// use win32console::structs::handle::Handle;
/// use winapi::um::processenv::GetStdHandle;
/// use winapi::um::winbase::STD_INPUT_HANDLE;
/// use winapi::um::handleapi::INVALID_HANDLE_VALUE;
///
/// let handle = Handle::new(unsafe { GetStdHandle(STD_INPUT_HANDLE) });
/// assert!(handle.is_valid());
/// ```
pub fn is_valid(&self) -> bool {
if self.0.handle == INVALID_HANDLE_VALUE {
return false;
}
true
}
}
impl AsRef<Handle> for Handle{
#[inline]
fn as_ref(&self) -> &Handle {
self
}
}
impl Deref for Handle {
type Target = HANDLE;
/// Gets a reference to the underlying [HANDLE].
#[inline]
fn deref(&self) -> &Self::Target {
&self.0.handle
}
}