1 #![unstable(issue = "none", feature = "windows_handle")]
7 use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, Read};
9 use crate::os::windows::io::{
10 AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
15 use crate::sys_common::{AsInner, FromInner, IntoInner};
17 /// An owned container for `HANDLE` object, closing them on Drop.
19 /// All methods are inherited through a `Deref` impl to `RawHandle`
20 pub struct Handle(OwnedHandle);
23 pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> {
26 c::CreateEventW(ptr::null_mut(), manual as c::BOOL, init as c::BOOL, ptr::null());
28 Err(io::Error::last_os_error())
30 Ok(Handle::from_raw_handle(event))
36 impl AsInner<OwnedHandle> for Handle {
37 fn as_inner(&self) -> &OwnedHandle {
42 impl IntoInner<OwnedHandle> for Handle {
43 fn into_inner(self) -> OwnedHandle {
48 impl FromInner<OwnedHandle> for Handle {
49 fn from_inner(file_desc: OwnedHandle) -> Self {
54 impl AsHandle for Handle {
55 fn as_handle(&self) -> BorrowedHandle<'_> {
60 impl AsRawHandle for Handle {
61 fn as_raw_handle(&self) -> RawHandle {
62 self.0.as_raw_handle()
66 impl IntoRawHandle for Handle {
67 fn into_raw_handle(self) -> RawHandle {
68 self.0.into_raw_handle()
72 impl FromRawHandle for Handle {
73 unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
74 Self(FromRawHandle::from_raw_handle(raw_handle))
79 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
80 let res = unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), None) };
83 Ok(read) => Ok(read as usize),
85 // The special treatment of BrokenPipe is to deal with Windows
86 // pipe semantics, which yields this error when *reading* from
87 // a pipe after the other end has closed; we interpret that as
89 Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0),
95 pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
96 crate::io::default_read_vectored(|buf| self.read(buf), bufs)
100 pub fn is_read_vectored(&self) -> bool {
104 pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
106 unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), Some(offset)) };
109 Ok(read) => Ok(read as usize),
110 Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0),
115 pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
117 unsafe { self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), None) };
121 // Safety: `read` bytes were written to the initialized portion of the buffer
123 cursor.advance(read as usize);
128 // The special treatment of BrokenPipe is to deal with Windows
129 // pipe semantics, which yields this error when *reading* from
130 // a pipe after the other end has closed; we interpret that as
132 Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(()),
138 pub unsafe fn read_overlapped(
141 overlapped: *mut c::OVERLAPPED,
142 ) -> io::Result<Option<usize>> {
143 let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
145 let res = cvt(c::ReadFile(
147 buf.as_ptr() as c::LPVOID,
153 Ok(_) => Ok(Some(amt as usize)),
155 if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
157 } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
166 pub fn overlapped_result(
168 overlapped: *mut c::OVERLAPPED,
170 ) -> io::Result<usize> {
173 let wait = if wait { c::TRUE } else { c::FALSE };
175 cvt(c::GetOverlappedResult(self.as_raw_handle(), overlapped, &mut bytes, wait));
177 Ok(_) => Ok(bytes as usize),
179 if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32)
180 || e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32)
191 pub fn cancel_io(&self) -> io::Result<()> {
192 unsafe { cvt(c::CancelIo(self.as_raw_handle())).map(drop) }
195 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
196 self.synchronous_write(&buf, None)
199 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
200 crate::io::default_write_vectored(|buf| self.write(buf), bufs)
204 pub fn is_write_vectored(&self) -> bool {
208 pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
209 self.synchronous_write(&buf, Some(offset))
212 pub fn try_clone(&self) -> io::Result<Self> {
213 Ok(Self(self.0.try_clone()?))
221 ) -> io::Result<Self> {
222 Ok(Self(self.0.as_handle().duplicate(access, inherit, options)?))
225 /// Performs a synchronous read.
227 /// If the handle is opened for asynchronous I/O then this abort the process.
230 /// If `offset` is `None` then the current file position is used.
231 unsafe fn synchronous_read(
233 buf: *mut mem::MaybeUninit<u8>,
236 ) -> io::Result<usize> {
237 let mut io_status = c::IO_STATUS_BLOCK::default();
239 // The length is clamped at u32::MAX.
240 let len = cmp::min(len, c::DWORD::MAX as usize) as c::DWORD;
241 let status = c::NtReadFile(
249 offset.map(|n| n as _).as_ref(),
253 let status = if status == c::STATUS_PENDING {
254 c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE);
260 // If the operation has not completed then abort the process.
261 // Doing otherwise means that the buffer and stack may be written to
262 // after this function returns.
263 c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
265 // Return `Ok(0)` when there's nothing more to read.
266 c::STATUS_END_OF_FILE => Ok(0),
269 status if c::nt_success(status) => Ok(io_status.Information),
272 let error = c::RtlNtStatusToDosError(status);
273 Err(io::Error::from_raw_os_error(error as _))
278 /// Performs a synchronous write.
280 /// If the handle is opened for asynchronous I/O then this abort the process.
283 /// If `offset` is `None` then the current file position is used.
284 fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> {
285 let mut io_status = c::IO_STATUS_BLOCK::default();
287 // The length is clamped at u32::MAX.
288 let len = cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD;
289 let status = unsafe {
298 offset.map(|n| n as _).as_ref(),
302 let status = if status == c::STATUS_PENDING {
303 unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
309 // If the operation has not completed then abort the process.
310 // Doing otherwise means that the buffer may be read and the stack
311 // written to after this function returns.
312 c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
315 status if c::nt_success(status) => Ok(io_status.Information),
318 let error = unsafe { c::RtlNtStatusToDosError(status) };
319 Err(io::Error::from_raw_os_error(error as _))
325 impl<'a> Read for &'a Handle {
326 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
330 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
331 (**self).read_vectored(bufs)