]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/windows/handle.rs
Fix wrong argument in autoderef process
[rust.git] / src / libstd / 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_value() 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     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
96         let mut read = 0;
97         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
98         let res = unsafe {
99             let mut overlapped: c::OVERLAPPED = mem::zeroed();
100             overlapped.Offset = offset as u32;
101             overlapped.OffsetHigh = (offset >> 32) as u32;
102             cvt(c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, &mut overlapped))
103         };
104         match res {
105             Ok(_) => Ok(read as usize),
106             Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0),
107             Err(e) => Err(e),
108         }
109     }
110
111     pub unsafe fn read_overlapped(
112         &self,
113         buf: &mut [u8],
114         overlapped: *mut c::OVERLAPPED,
115     ) -> io::Result<Option<usize>> {
116         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
117         let mut amt = 0;
118         let res = cvt(c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped));
119         match res {
120             Ok(_) => Ok(Some(amt as usize)),
121             Err(e) => {
122                 if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
123                     Ok(None)
124                 } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
125                     Ok(Some(0))
126                 } else {
127                     Err(e)
128                 }
129             }
130         }
131     }
132
133     pub fn overlapped_result(
134         &self,
135         overlapped: *mut c::OVERLAPPED,
136         wait: bool,
137     ) -> io::Result<usize> {
138         unsafe {
139             let mut bytes = 0;
140             let wait = if wait { c::TRUE } else { c::FALSE };
141             let res = cvt(c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait));
142             match res {
143                 Ok(_) => Ok(bytes as usize),
144                 Err(e) => {
145                     if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32)
146                         || e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32)
147                     {
148                         Ok(0)
149                     } else {
150                         Err(e)
151                     }
152                 }
153             }
154         }
155     }
156
157     pub fn cancel_io(&self) -> io::Result<()> {
158         unsafe { cvt(c::CancelIo(self.raw())).map(drop) }
159     }
160
161     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
162         let mut amt = 0;
163         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
164         cvt(unsafe {
165             c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, ptr::null_mut())
166         })?;
167         Ok(amt as usize)
168     }
169
170     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
171         crate::io::default_write_vectored(|buf| self.write(buf), bufs)
172     }
173
174     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
175         let mut written = 0;
176         let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
177         unsafe {
178             let mut overlapped: c::OVERLAPPED = mem::zeroed();
179             overlapped.Offset = offset as u32;
180             overlapped.OffsetHigh = (offset >> 32) as u32;
181             cvt(c::WriteFile(
182                 self.0,
183                 buf.as_ptr() as c::LPVOID,
184                 len,
185                 &mut written,
186                 &mut overlapped,
187             ))?;
188         }
189         Ok(written as usize)
190     }
191
192     pub fn duplicate(
193         &self,
194         access: c::DWORD,
195         inherit: bool,
196         options: c::DWORD,
197     ) -> io::Result<Handle> {
198         let mut ret = 0 as c::HANDLE;
199         cvt(unsafe {
200             let cur_proc = c::GetCurrentProcess();
201             c::DuplicateHandle(
202                 cur_proc,
203                 self.0,
204                 cur_proc,
205                 &mut ret,
206                 access,
207                 inherit as c::BOOL,
208                 options,
209             )
210         })?;
211         Ok(Handle::new(ret))
212     }
213 }
214
215 impl<'a> Read for &'a RawHandle {
216     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
217         (**self).read(buf)
218     }
219
220     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
221         (**self).read_vectored(bufs)
222     }
223 }