Skip to main content

std\sys\pal\windows/
handle.rs

1#![unstable(issue = "none", feature = "windows_handle")]
2
3use core::ffi::c_void;
4use core::{cmp, mem, ptr};
5
6use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read};
7use crate::os::windows::io::{
8    AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
9};
10use crate::sys::{AsInner, FromInner, IntoInner, c, cvt};
11
12/// An owned container for `HANDLE` object, closing them on Drop.
13///
14/// All methods are inherited through a `Deref` impl to `RawHandle`
15#[derive(Debug)]
16pub struct Handle(OwnedHandle);
17
18impl Handle {
19    pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> {
20        unsafe {
21            let event =
22                c::CreateEventW(ptr::null_mut(), manual as c::BOOL, init as c::BOOL, ptr::null());
23            if event.is_null() {
24                Err(io::Error::last_os_error())
25            } else {
26                Ok(Handle::from_raw_handle(event))
27            }
28        }
29    }
30}
31
32impl AsInner<OwnedHandle> for Handle {
33    #[inline]
34    fn as_inner(&self) -> &OwnedHandle {
35        &self.0
36    }
37}
38
39impl IntoInner<OwnedHandle> for Handle {
40    fn into_inner(self) -> OwnedHandle {
41        self.0
42    }
43}
44
45impl FromInner<OwnedHandle> for Handle {
46    fn from_inner(file_desc: OwnedHandle) -> Self {
47        Self(file_desc)
48    }
49}
50
51impl AsHandle for Handle {
52    fn as_handle(&self) -> BorrowedHandle<'_> {
53        self.0.as_handle()
54    }
55}
56
57impl AsRawHandle for Handle {
58    fn as_raw_handle(&self) -> RawHandle {
59        self.0.as_raw_handle()
60    }
61}
62
63impl IntoRawHandle for Handle {
64    fn into_raw_handle(self) -> RawHandle {
65        self.0.into_raw_handle()
66    }
67}
68
69impl FromRawHandle for Handle {
70    unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
71        unsafe { Self(FromRawHandle::from_raw_handle(raw_handle)) }
72    }
73}
74
75impl Handle {
76    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
77        let res = unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), None) };
78
79        match res {
80            Ok(read) => Ok(read),
81
82            // The special treatment of BrokenPipe is to deal with Windows
83            // pipe semantics, which yields this error when *reading* from
84            // a pipe after the other end has closed; we interpret that as
85            // EOF on the pipe.
86            Err(ref e) if e.kind() == io::ErrorKind::BrokenPipe => Ok(0),
87
88            Err(e) => Err(e),
89        }
90    }
91
92    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
93        crate::io::default_read_vectored(|buf| self.read(buf), bufs)
94    }
95
96    #[inline]
97    pub fn is_read_vectored(&self) -> bool {
98        false
99    }
100
101    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
102        let res =
103            unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), Some(offset)) };
104
105        match res {
106            Ok(read) => Ok(read),
107            Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0),
108            Err(e) => Err(e),
109        }
110    }
111
112    pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
113        let res =
114            unsafe { self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), None) };
115
116        match res {
117            Ok(read) => {
118                // Safety: `read` bytes were written to the initialized portion of the buffer
119                unsafe {
120                    cursor.advance(read);
121                }
122                Ok(())
123            }
124
125            // The special treatment of BrokenPipe is to deal with Windows
126            // pipe semantics, which yields this error when *reading* from
127            // a pipe after the other end has closed; we interpret that as
128            // EOF on the pipe.
129            Err(ref e) if e.kind() == io::ErrorKind::BrokenPipe => Ok(()),
130
131            Err(e) => Err(e),
132        }
133    }
134
135    pub fn read_buf_at(&self, mut cursor: BorrowedCursor<'_>, offset: u64) -> io::Result<()> {
136        // SAFETY: `cursor.as_mut()` starts with `cursor.capacity()` writable bytes
137        let read = unsafe {
138            self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), Some(offset))
139        }?;
140
141        // SAFETY: `read` bytes were written to the initialized portion of the buffer
142        unsafe {
143            cursor.advance(read);
144        }
145        Ok(())
146    }
147
148    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
149        let mut me = self;
150
151        Read::read_to_end(&mut me, buf)
152    }
153
154    pub unsafe fn read_overlapped(
155        &self,
156        buf: &mut [mem::MaybeUninit<u8>],
157        overlapped: *mut c::OVERLAPPED,
158    ) -> io::Result<Option<usize>> {
159        // SAFETY: We have exclusive access to the buffer and it's up to the caller to
160        // ensure the OVERLAPPED pointer is valid for the lifetime of this function.
161        let (res, amt) = unsafe {
162            let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
163            let mut amt = 0;
164            let res = cvt(c::ReadFile(
165                self.as_raw_handle(),
166                buf.as_mut_ptr().cast::<u8>(),
167                len,
168                &mut amt,
169                overlapped,
170            ));
171            (res, amt)
172        };
173        match res {
174            Ok(_) => Ok(Some(amt as usize)),
175            Err(e) => {
176                if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
177                    Ok(None)
178                } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
179                    Ok(Some(0))
180                } else {
181                    Err(e)
182                }
183            }
184        }
185    }
186
187    pub fn overlapped_result(
188        &self,
189        overlapped: *mut c::OVERLAPPED,
190        wait: bool,
191    ) -> io::Result<usize> {
192        unsafe {
193            let mut bytes = 0;
194            let wait = if wait { c::TRUE } else { c::FALSE };
195            let res =
196                cvt(c::GetOverlappedResult(self.as_raw_handle(), overlapped, &mut bytes, wait));
197            match res {
198                Ok(_) => Ok(bytes as usize),
199                Err(e) => {
200                    if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32)
201                        || e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32)
202                    {
203                        Ok(0)
204                    } else {
205                        Err(e)
206                    }
207                }
208            }
209        }
210    }
211
212    pub fn cancel_io(&self) -> io::Result<()> {
213        unsafe { cvt(c::CancelIo(self.as_raw_handle())).map(drop) }
214    }
215
216    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
217        self.synchronous_write(buf, None)
218    }
219
220    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
221        crate::io::default_write_vectored(|buf| self.write(buf), bufs)
222    }
223
224    #[inline]
225    pub fn is_write_vectored(&self) -> bool {
226        false
227    }
228
229    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
230        self.synchronous_write(buf, Some(offset))
231    }
232
233    pub fn try_clone(&self) -> io::Result<Self> {
234        Ok(Self(self.0.try_clone()?))
235    }
236
237    pub fn duplicate(&self, access: u32, inherit: bool, options: u32) -> io::Result<Self> {
238        Ok(Self(self.0.as_handle().duplicate(access, inherit, options)?))
239    }
240
241    /// Performs a synchronous read.
242    ///
243    /// If the handle is opened for asynchronous I/O then this abort the process.
244    /// See #81357.
245    ///
246    /// If `offset` is `None` then the current file position is used.
247    unsafe fn synchronous_read(
248        &self,
249        buf: *mut mem::MaybeUninit<u8>,
250        len: usize,
251        offset: Option<u64>,
252    ) -> io::Result<usize> {
253        let mut io_status = c::IO_STATUS_BLOCK::PENDING;
254
255        // The length is clamped at u32::MAX.
256        let len = cmp::min(len, u32::MAX as usize) as u32;
257        // SAFETY: It's up to the caller to ensure `buf` is writeable up to
258        // the provided `len`.
259        let status = unsafe {
260            c::NtReadFile(
261                self.as_raw_handle(),
262                ptr::null_mut(),
263                None,
264                ptr::null_mut(),
265                &mut io_status,
266                buf.cast::<c_void>(),
267                len,
268                offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
269                ptr::null(),
270            )
271        };
272
273        let status = if status == c::STATUS_PENDING {
274            unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
275            io_status.status()
276        } else {
277            status
278        };
279        match status {
280            // If the operation has not completed then abort the process.
281            // Doing otherwise means that the buffer and stack may be written to
282            // after this function returns.
283            c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
284
285            // Return `Ok(0)` when there's nothing more to read.
286            c::STATUS_END_OF_FILE => Ok(0),
287
288            // Success!
289            status if c::nt_success(status) => Ok(io_status.Information),
290
291            status => {
292                let error = unsafe { c::RtlNtStatusToDosError(status) };
293                Err(io::Error::from_raw_os_error(error as _))
294            }
295        }
296    }
297
298    /// Performs a synchronous write.
299    ///
300    /// If the handle is opened for asynchronous I/O then this abort the process.
301    /// See #81357.
302    ///
303    /// If `offset` is `None` then the current file position is used.
304    fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> {
305        let mut io_status = c::IO_STATUS_BLOCK::PENDING;
306
307        // The length is clamped at u32::MAX.
308        let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
309        let status = unsafe {
310            c::NtWriteFile(
311                self.as_raw_handle(),
312                ptr::null_mut(),
313                None,
314                ptr::null_mut(),
315                &mut io_status,
316                buf.as_ptr().cast::<c_void>(),
317                len,
318                offset.as_ref().map(|n| ptr::from_ref(n).cast::<i64>()).unwrap_or(ptr::null()),
319                ptr::null(),
320            )
321        };
322        let status = if status == c::STATUS_PENDING {
323            unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
324            io_status.status()
325        } else {
326            status
327        };
328        match status {
329            // If the operation has not completed then abort the process.
330            // Doing otherwise means that the buffer may be read and the stack
331            // written to after this function returns.
332            c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
333
334            // Success!
335            status if c::nt_success(status) => Ok(io_status.Information),
336
337            status => {
338                let error = unsafe { c::RtlNtStatusToDosError(status) };
339                Err(io::Error::from_raw_os_error(error as _))
340            }
341        }
342    }
343}
344
345impl<'a> Read for &'a Handle {
346    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
347        (**self).read(buf)
348    }
349
350    fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
351        (**self).read_buf(buf)
352    }
353
354    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
355        (**self).read_vectored(bufs)
356    }
357
358    #[inline]
359    fn is_read_vectored(&self) -> bool {
360        (**self).is_read_vectored()
361    }
362}