1#![unstable(issue = "none", feature = "windows_handle")]
2
3#[cfg(test)]
4mod tests;
5
6use core::ffi::c_void;
7use core::{cmp, mem, ptr};
8
9use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, Read};
10use crate::os::windows::io::{
11 AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
12};
13use crate::sys::{c, cvt};
14use crate::sys_common::{AsInner, FromInner, IntoInner};
15
16#[derive(Debug)]
20pub struct Handle(OwnedHandle);
21
22impl Handle {
23 pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> {
24 unsafe {
25 let event =
26 c::CreateEventW(ptr::null_mut(), manual as c::BOOL, init as c::BOOL, ptr::null());
27 if event.is_null() {
28 Err(io::Error::last_os_error())
29 } else {
30 Ok(Handle::from_raw_handle(event))
31 }
32 }
33 }
34}
35
36impl AsInner<OwnedHandle> for Handle {
37 #[inline]
38 fn as_inner(&self) -> &OwnedHandle {
39 &self.0
40 }
41}
42
43impl IntoInner<OwnedHandle> for Handle {
44 fn into_inner(self) -> OwnedHandle {
45 self.0
46 }
47}
48
49impl FromInner<OwnedHandle> for Handle {
50 fn from_inner(file_desc: OwnedHandle) -> Self {
51 Self(file_desc)
52 }
53}
54
55impl AsHandle for Handle {
56 fn as_handle(&self) -> BorrowedHandle<'_> {
57 self.0.as_handle()
58 }
59}
60
61impl AsRawHandle for Handle {
62 fn as_raw_handle(&self) -> RawHandle {
63 self.0.as_raw_handle()
64 }
65}
66
67impl IntoRawHandle for Handle {
68 fn into_raw_handle(self) -> RawHandle {
69 self.0.into_raw_handle()
70 }
71}
72
73impl FromRawHandle for Handle {
74 unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
75 unsafe { Self(FromRawHandle::from_raw_handle(raw_handle)) }
76 }
77}
78
79impl Handle {
80 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
81 let res = unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), None) };
82
83 match res {
84 Ok(read) => Ok(read),
85
86 Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0),
91
92 Err(e) => Err(e),
93 }
94 }
95
96 pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
97 crate::io::default_read_vectored(|buf| self.read(buf), bufs)
98 }
99
100 #[inline]
101 pub fn is_read_vectored(&self) -> bool {
102 false
103 }
104
105 pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
106 let res =
107 unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), Some(offset)) };
108
109 match res {
110 Ok(read) => Ok(read),
111 Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0),
112 Err(e) => Err(e),
113 }
114 }
115
116 pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
117 let res =
118 unsafe { self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), None) };
119
120 match res {
121 Ok(read) => {
122 unsafe {
124 cursor.advance_unchecked(read);
125 }
126 Ok(())
127 }
128
129 Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(()),
134
135 Err(e) => Err(e),
136 }
137 }
138
139 pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
140 let mut me = self;
141
142 Read::read_to_end(&mut me, buf)
143 }
144
145 pub unsafe fn read_overlapped(
146 &self,
147 buf: &mut [mem::MaybeUninit<u8>],
148 overlapped: *mut c::OVERLAPPED,
149 ) -> io::Result<Option<usize>> {
150 let (res, amt) = unsafe {
153 let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
154 let mut amt = 0;
155 let res = cvt(c::ReadFile(
156 self.as_raw_handle(),
157 buf.as_mut_ptr().cast::<u8>(),
158 len,
159 &mut amt,
160 overlapped,
161 ));
162 (res, amt)
163 };
164 match res {
165 Ok(_) => Ok(Some(amt as usize)),
166 Err(e) => {
167 if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
168 Ok(None)
169 } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
170 Ok(Some(0))
171 } else {
172 Err(e)
173 }
174 }
175 }
176 }
177
178 pub fn overlapped_result(
179 &self,
180 overlapped: *mut c::OVERLAPPED,
181 wait: bool,
182 ) -> io::Result<usize> {
183 unsafe {
184 let mut bytes = 0;
185 let wait = if wait { c::TRUE } else { c::FALSE };
186 let res =
187 cvt(c::GetOverlappedResult(self.as_raw_handle(), overlapped, &mut bytes, wait));
188 match res {
189 Ok(_) => Ok(bytes as usize),
190 Err(e) => {
191 if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32)
192 || e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32)
193 {
194 Ok(0)
195 } else {
196 Err(e)
197 }
198 }
199 }
200 }
201 }
202
203 pub fn cancel_io(&self) -> io::Result<()> {
204 unsafe { cvt(c::CancelIo(self.as_raw_handle())).map(drop) }
205 }
206
207 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
208 self.synchronous_write(buf, None)
209 }
210
211 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
212 crate::io::default_write_vectored(|buf| self.write(buf), bufs)
213 }
214
215 #[inline]
216 pub fn is_write_vectored(&self) -> bool {
217 false
218 }
219
220 pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
221 self.synchronous_write(buf, Some(offset))
222 }
223
224 pub fn try_clone(&self) -> io::Result<Self> {
225 Ok(Self(self.0.try_clone()?))
226 }
227
228 pub fn duplicate(&self, access: u32, inherit: bool, options: u32) -> io::Result<Self> {
229 Ok(Self(self.0.as_handle().duplicate(access, inherit, options)?))
230 }
231
232 unsafe fn synchronous_read(
239 &self,
240 buf: *mut mem::MaybeUninit<u8>,
241 len: usize,
242 offset: Option<u64>,
243 ) -> io::Result<usize> {
244 let mut io_status = c::IO_STATUS_BLOCK::PENDING;
245
246 let len = cmp::min(len, u32::MAX as usize) as u32;
248 let status = unsafe {
251 c::NtReadFile(
252 self.as_raw_handle(),
253 ptr::null_mut(),
254 None,
255 ptr::null_mut(),
256 &mut io_status,
257 buf.cast::<c_void>(),
258 len,
259 offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
260 ptr::null(),
261 )
262 };
263
264 let status = if status == c::STATUS_PENDING {
265 unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
266 io_status.status()
267 } else {
268 status
269 };
270 match status {
271 c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
275
276 c::STATUS_END_OF_FILE => Ok(0),
278
279 status if c::nt_success(status) => Ok(io_status.Information),
281
282 status => {
283 let error = unsafe { c::RtlNtStatusToDosError(status) };
284 Err(io::Error::from_raw_os_error(error as _))
285 }
286 }
287 }
288
289 fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> {
296 let mut io_status = c::IO_STATUS_BLOCK::PENDING;
297
298 let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
300 let status = unsafe {
301 c::NtWriteFile(
302 self.as_raw_handle(),
303 ptr::null_mut(),
304 None,
305 ptr::null_mut(),
306 &mut io_status,
307 buf.as_ptr().cast::<c_void>(),
308 len,
309 offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
310 ptr::null(),
311 )
312 };
313 let status = if status == c::STATUS_PENDING {
314 unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
315 io_status.status()
316 } else {
317 status
318 };
319 match status {
320 c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
324
325 status if c::nt_success(status) => Ok(io_status.Information),
327
328 status => {
329 let error = unsafe { c::RtlNtStatusToDosError(status) };
330 Err(io::Error::from_raw_os_error(error as _))
331 }
332 }
333 }
334}
335
336impl<'a> Read for &'a Handle {
337 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
338 (**self).read(buf)
339 }
340
341 fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
342 (**self).read_buf(buf)
343 }
344
345 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
346 (**self).read_vectored(bufs)
347 }
348
349 #[inline]
350 fn is_read_vectored(&self) -> bool {
351 (**self).is_read_vectored()
352 }
353}