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#[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 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 unsafe {
120 cursor.advance(read);
121 }
122 Ok(())
123 }
124
125 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 let read = unsafe {
138 self.synchronous_read(cursor.as_mut().as_mut_ptr(), cursor.capacity(), Some(offset))
139 }?;
140
141 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 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 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 let len = cmp::min(len, u32::MAX as usize) as u32;
257 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 c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
284
285 c::STATUS_END_OF_FILE => Ok(0),
287
288 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 fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> {
305 let mut io_status = c::IO_STATUS_BLOCK::PENDING;
306
307 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 c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
333
334 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}