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_buf_at(&self, mut cursor: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
140 let read = unsafe {
142 self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), Some(offset))
143 }?;
144
145 unsafe {
147 cursor.advance_unchecked(read);
148 }
149 Ok(())
150 }
151
152 pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
153 let mut me = self;
154
155 Read::read_to_end(&mut me, buf)
156 }
157
158 pub unsafe fn read_overlapped(
159 &self,
160 buf: &mut [mem::MaybeUninit<u8>],
161 overlapped: *mut c::OVERLAPPED,
162 ) -> io::Result<Option<usize>> {
163 let (res, amt) = unsafe {
166 let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
167 let mut amt = 0;
168 let res = cvt(c::ReadFile(
169 self.as_raw_handle(),
170 buf.as_mut_ptr().cast::<u8>(),
171 len,
172 &mut amt,
173 overlapped,
174 ));
175 (res, amt)
176 };
177 match res {
178 Ok(_) => Ok(Some(amt as usize)),
179 Err(e) => {
180 if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
181 Ok(None)
182 } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
183 Ok(Some(0))
184 } else {
185 Err(e)
186 }
187 }
188 }
189 }
190
191 pub fn overlapped_result(
192 &self,
193 overlapped: *mut c::OVERLAPPED,
194 wait: bool,
195 ) -> io::Result<usize> {
196 unsafe {
197 let mut bytes = 0;
198 let wait = if wait { c::TRUE } else { c::FALSE };
199 let res =
200 cvt(c::GetOverlappedResult(self.as_raw_handle(), overlapped, &mut bytes, wait));
201 match res {
202 Ok(_) => Ok(bytes as usize),
203 Err(e) => {
204 if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32)
205 || e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32)
206 {
207 Ok(0)
208 } else {
209 Err(e)
210 }
211 }
212 }
213 }
214 }
215
216 pub fn cancel_io(&self) -> io::Result<()> {
217 unsafe { cvt(c::CancelIo(self.as_raw_handle())).map(drop) }
218 }
219
220 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
221 self.synchronous_write(buf, None)
222 }
223
224 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
225 crate::io::default_write_vectored(|buf| self.write(buf), bufs)
226 }
227
228 #[inline]
229 pub fn is_write_vectored(&self) -> bool {
230 false
231 }
232
233 pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
234 self.synchronous_write(buf, Some(offset))
235 }
236
237 pub fn try_clone(&self) -> io::Result<Self> {
238 Ok(Self(self.0.try_clone()?))
239 }
240
241 pub fn duplicate(&self, access: u32, inherit: bool, options: u32) -> io::Result<Self> {
242 Ok(Self(self.0.as_handle().duplicate(access, inherit, options)?))
243 }
244
245 unsafe fn synchronous_read(
252 &self,
253 buf: *mut mem::MaybeUninit<u8>,
254 len: usize,
255 offset: Option<u64>,
256 ) -> io::Result<usize> {
257 let mut io_status = c::IO_STATUS_BLOCK::PENDING;
258
259 let len = cmp::min(len, u32::MAX as usize) as u32;
261 let status = unsafe {
264 c::NtReadFile(
265 self.as_raw_handle(),
266 ptr::null_mut(),
267 None,
268 ptr::null_mut(),
269 &mut io_status,
270 buf.cast::<c_void>(),
271 len,
272 offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
273 ptr::null(),
274 )
275 };
276
277 let status = if status == c::STATUS_PENDING {
278 unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
279 io_status.status()
280 } else {
281 status
282 };
283 match status {
284 c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
288
289 c::STATUS_END_OF_FILE => Ok(0),
291
292 status if c::nt_success(status) => Ok(io_status.Information),
294
295 status => {
296 let error = unsafe { c::RtlNtStatusToDosError(status) };
297 Err(io::Error::from_raw_os_error(error as _))
298 }
299 }
300 }
301
302 fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> {
309 let mut io_status = c::IO_STATUS_BLOCK::PENDING;
310
311 let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
313 let status = unsafe {
314 c::NtWriteFile(
315 self.as_raw_handle(),
316 ptr::null_mut(),
317 None,
318 ptr::null_mut(),
319 &mut io_status,
320 buf.as_ptr().cast::<c_void>(),
321 len,
322 offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
323 ptr::null(),
324 )
325 };
326 let status = if status == c::STATUS_PENDING {
327 unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
328 io_status.status()
329 } else {
330 status
331 };
332 match status {
333 c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
337
338 status if c::nt_success(status) => Ok(io_status.Information),
340
341 status => {
342 let error = unsafe { c::RtlNtStatusToDosError(status) };
343 Err(io::Error::from_raw_os_error(error as _))
344 }
345 }
346 }
347}
348
349impl<'a> Read for &'a Handle {
350 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
351 (**self).read(buf)
352 }
353
354 fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
355 (**self).read_buf(buf)
356 }
357
358 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
359 (**self).read_vectored(bufs)
360 }
361
362 #[inline]
363 fn is_read_vectored(&self) -> bool {
364 (**self).is_read_vectored()
365 }
366}