std\sys\pal\windows/
handle.rs

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/// An owned container for `HANDLE` object, closing them on Drop.
17///
18/// All methods are inherited through a `Deref` impl to `RawHandle`
19#[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            // The special treatment of BrokenPipe is to deal with Windows
87            // pipe semantics, which yields this error when *reading* from
88            // a pipe after the other end has closed; we interpret that as
89            // EOF on the pipe.
90            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                // Safety: `read` bytes were written to the initialized portion of the buffer
123                unsafe {
124                    cursor.advance_unchecked(read);
125                }
126                Ok(())
127            }
128
129            // The special treatment of BrokenPipe is to deal with Windows
130            // pipe semantics, which yields this error when *reading* from
131            // a pipe after the other end has closed; we interpret that as
132            // EOF on the pipe.
133            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        // SAFETY: `cursor.as_mut()` starts with `cursor.capacity()` writable bytes
141        let read = unsafe {
142            self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), Some(offset))
143        }?;
144
145        // SAFETY: `read` bytes were written to the initialized portion of the buffer
146        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        // SAFETY: We have exclusive access to the buffer and it's up to the caller to
164        // ensure the OVERLAPPED pointer is valid for the lifetime of this function.
165        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    /// Performs a synchronous read.
246    ///
247    /// If the handle is opened for asynchronous I/O then this abort the process.
248    /// See #81357.
249    ///
250    /// If `offset` is `None` then the current file position is used.
251    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        // The length is clamped at u32::MAX.
260        let len = cmp::min(len, u32::MAX as usize) as u32;
261        // SAFETY: It's up to the caller to ensure `buf` is writeable up to
262        // the provided `len`.
263        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            // If the operation has not completed then abort the process.
285            // Doing otherwise means that the buffer and stack may be written to
286            // after this function returns.
287            c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
288
289            // Return `Ok(0)` when there's nothing more to read.
290            c::STATUS_END_OF_FILE => Ok(0),
291
292            // Success!
293            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    /// Performs a synchronous write.
303    ///
304    /// If the handle is opened for asynchronous I/O then this abort the process.
305    /// See #81357.
306    ///
307    /// If `offset` is `None` then the current file position is used.
308    fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> {
309        let mut io_status = c::IO_STATUS_BLOCK::PENDING;
310
311        // The length is clamped at u32::MAX.
312        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            // If the operation has not completed then abort the process.
334            // Doing otherwise means that the buffer may be read and the stack
335            // written to after this function returns.
336            c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
337
338            // Success!
339            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}