]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/windows/handle.rs
Merge commit '05677b6bd6c938ed760835d9b1f6514992654ae3' into sync_cg_clif-2021-08-06
[rust.git] / library / std / src / sys / windows / handle.rs
1 #![unstable(issue = "none", feature = "windows_handle")]
2
3 use crate::cmp;
4 use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read};
5 use crate::mem;
6 use crate::ops::Deref;
7 use crate::ptr;
8 use crate::sys::c;
9 use crate::sys::cvt;
10
11 /// An owned container for `HANDLE` object, closing them on Drop.
12 ///
13 /// All methods are inherited through a `Deref` impl to `RawHandle`
14 pub struct Handle(RawHandle);
15
16 /// A wrapper type for `HANDLE` objects to give them proper Send/Sync inference
17 /// as well as Rust-y methods.
18 ///
19 /// This does **not** drop the handle when it goes out of scope, use `Handle`
20 /// instead for that.
21 #[derive(Copy, Clone)]
22 pub struct RawHandle(c::HANDLE);
23
24 unsafe impl Send for RawHandle {}
25 unsafe impl Sync for RawHandle {}
26
27 impl Handle {
28     pub fn new(handle: c::HANDLE) -> Handle {
29         Handle(RawHandle::new(handle))
30     }
31
32     pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> {
33         unsafe {
34             let event =
35                 c::CreateEventW(ptr::null_mut(), manual as c::BOOL, init as c::BOOL, ptr::null());
36             if event.is_null() { Err(io::Error::last_os_error()) } else { Ok(Handle::new(event)) }
37         }
38     }
39
40     pub fn into_raw(self) -> c::HANDLE {
41         let ret = self.raw();
42         mem::forget(self);
43         ret
44     }
45 }
46
47 impl Deref for Handle {
48     type Target = RawHandle;
49     fn deref(&self) -> &RawHandle {
50         &self.0
51     }
52 }
53
54 impl Drop for Handle {
55     fn drop(&mut self) {
56         unsafe {
57             let _ = c::CloseHandle(self.raw());
58         }
59     }
60 }
61
62 impl RawHandle {
63     pub fn new(handle: c::HANDLE) -> RawHandle {
64         RawHandle(handle)
65     }
66
67     pub fn raw(&self) -> c::HANDLE {
68         self.0
69     }
70
71     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
72         let mut read = 0;
73         let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
74         let res = cvt(unsafe {
75             c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, ptr::null_mut())
76         });
77
78         match res {
79             Ok(_) => Ok(read as usize),
80
81             // The special treatment of BrokenPipe is to deal with Windows
82             // pipe semantics, which yields this error when *reading* from
83             // a pipe after the other end has closed; we interpret that as
84             // EOF on the pipe.
85             Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0),
86
87             Err(e) => Err(e),
88         }
89     }
90
91     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
92         crate::io::default_read_vectored(|buf| self.read(buf), bufs)
93     }
94
95     #[inline]
96     pub fn is_read_vectored(&self) -> bool {
97         false
98     }
99
100     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
101         let mut read = 0;
102         let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
103         let res = unsafe {
104             let mut overlapped: c::OVERLAPPED = mem::zeroed();
105             overlapped.Offset = offset as u32;
106             overlapped.OffsetHigh = (offset >> 32) as u32;
107             cvt(c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, &mut overlapped))
108         };
109         match res {
110             Ok(_) => Ok(read as usize),
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 unsafe fn read_overlapped(
117         &self,
118         buf: &mut [u8],
119         overlapped: *mut c::OVERLAPPED,
120     ) -> io::Result<Option<usize>> {
121         let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
122         let mut amt = 0;
123         let res = cvt(c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped));
124         match res {
125             Ok(_) => Ok(Some(amt as usize)),
126             Err(e) => {
127                 if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
128                     Ok(None)
129                 } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
130                     Ok(Some(0))
131                 } else {
132                     Err(e)
133                 }
134             }
135         }
136     }
137
138     pub fn overlapped_result(
139         &self,
140         overlapped: *mut c::OVERLAPPED,
141         wait: bool,
142     ) -> io::Result<usize> {
143         unsafe {
144             let mut bytes = 0;
145             let wait = if wait { c::TRUE } else { c::FALSE };
146             let res = cvt(c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait));
147             match res {
148                 Ok(_) => Ok(bytes as usize),
149                 Err(e) => {
150                     if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32)
151                         || e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32)
152                     {
153                         Ok(0)
154                     } else {
155                         Err(e)
156                     }
157                 }
158             }
159         }
160     }
161
162     pub fn cancel_io(&self) -> io::Result<()> {
163         unsafe { cvt(c::CancelIo(self.raw())).map(drop) }
164     }
165
166     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
167         let mut amt = 0;
168         let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
169         cvt(unsafe {
170             c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, ptr::null_mut())
171         })?;
172         Ok(amt as usize)
173     }
174
175     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
176         crate::io::default_write_vectored(|buf| self.write(buf), bufs)
177     }
178
179     #[inline]
180     pub fn is_write_vectored(&self) -> bool {
181         false
182     }
183
184     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
185         let mut written = 0;
186         let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
187         unsafe {
188             let mut overlapped: c::OVERLAPPED = mem::zeroed();
189             overlapped.Offset = offset as u32;
190             overlapped.OffsetHigh = (offset >> 32) as u32;
191             cvt(c::WriteFile(
192                 self.0,
193                 buf.as_ptr() as c::LPVOID,
194                 len,
195                 &mut written,
196                 &mut overlapped,
197             ))?;
198         }
199         Ok(written as usize)
200     }
201
202     pub fn duplicate(
203         &self,
204         access: c::DWORD,
205         inherit: bool,
206         options: c::DWORD,
207     ) -> io::Result<Handle> {
208         let mut ret = 0 as c::HANDLE;
209         cvt(unsafe {
210             let cur_proc = c::GetCurrentProcess();
211             c::DuplicateHandle(
212                 cur_proc,
213                 self.0,
214                 cur_proc,
215                 &mut ret,
216                 access,
217                 inherit as c::BOOL,
218                 options,
219             )
220         })?;
221         Ok(Handle::new(ret))
222     }
223 }
224
225 impl<'a> Read for &'a RawHandle {
226     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
227         (**self).read(buf)
228     }
229
230     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
231         (**self).read_vectored(bufs)
232     }
233 }