]>
Commit | Line | Data |
---|---|---|
54a0048b SL |
1 | #![unstable(issue = "0", feature = "windows_handle")] |
2 | ||
532ac7d7 | 3 | use crate::cmp; |
60c5eb7d | 4 | use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read}; |
532ac7d7 XL |
5 | use crate::mem; |
6 | use crate::ops::Deref; | |
7 | use crate::ptr; | |
8 | use crate::sys::c; | |
9 | use crate::sys::cvt; | |
85aaf69f | 10 | |
62682a34 SL |
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); | |
85aaf69f | 15 | |
62682a34 SL |
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)] | |
92a42be0 | 22 | pub struct RawHandle(c::HANDLE); |
62682a34 SL |
23 | |
24 | unsafe impl Send for RawHandle {} | |
25 | unsafe impl Sync for RawHandle {} | |
85aaf69f SL |
26 | |
27 | impl Handle { | |
92a42be0 | 28 | pub fn new(handle: c::HANDLE) -> Handle { |
62682a34 | 29 | Handle(RawHandle::new(handle)) |
85aaf69f SL |
30 | } |
31 | ||
54a0048b SL |
32 | pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> { |
33 | unsafe { | |
60c5eb7d XL |
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)) } | |
54a0048b SL |
37 | } |
38 | } | |
39 | ||
92a42be0 | 40 | pub fn into_raw(self) -> c::HANDLE { |
62682a34 | 41 | let ret = self.raw(); |
bd371182 | 42 | mem::forget(self); |
e74abb32 | 43 | ret |
c34b1796 | 44 | } |
62682a34 SL |
45 | } |
46 | ||
47 | impl Deref for Handle { | |
48 | type Target = RawHandle; | |
60c5eb7d XL |
49 | fn deref(&self) -> &RawHandle { |
50 | &self.0 | |
51 | } | |
62682a34 SL |
52 | } |
53 | ||
54 | impl Drop for Handle { | |
55 | fn drop(&mut self) { | |
60c5eb7d XL |
56 | unsafe { |
57 | let _ = c::CloseHandle(self.raw()); | |
58 | } | |
62682a34 SL |
59 | } |
60 | } | |
61 | ||
62 | impl RawHandle { | |
92a42be0 | 63 | pub fn new(handle: c::HANDLE) -> RawHandle { |
62682a34 SL |
64 | RawHandle(handle) |
65 | } | |
66 | ||
60c5eb7d XL |
67 | pub fn raw(&self) -> c::HANDLE { |
68 | self.0 | |
69 | } | |
c34b1796 | 70 | |
85aaf69f | 71 | pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { |
9346a6ac | 72 | let mut read = 0; |
32a655c1 | 73 | let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; |
9346a6ac | 74 | let res = cvt(unsafe { |
60c5eb7d | 75 | c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, ptr::null_mut()) |
9346a6ac AL |
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 | ||
60c5eb7d | 87 | Err(e) => Err(e), |
9346a6ac | 88 | } |
85aaf69f SL |
89 | } |
90 | ||
48663c56 XL |
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 | ||
c30ab7b3 SL |
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; | |
60c5eb7d | 102 | cvt(c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, &mut overlapped)) |
c30ab7b3 SL |
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 | ||
60c5eb7d XL |
111 | pub unsafe fn read_overlapped( |
112 | &self, | |
113 | buf: &mut [u8], | |
114 | overlapped: *mut c::OVERLAPPED, | |
115 | ) -> io::Result<Option<usize>> { | |
54a0048b SL |
116 | let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; |
117 | let mut amt = 0; | |
60c5eb7d XL |
118 | let res = |
119 | cvt({ c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped) }); | |
54a0048b SL |
120 | match res { |
121 | Ok(_) => Ok(Some(amt as usize)), | |
122 | Err(e) => { | |
123 | if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) { | |
124 | Ok(None) | |
125 | } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) { | |
126 | Ok(Some(0)) | |
127 | } else { | |
128 | Err(e) | |
129 | } | |
130 | } | |
131 | } | |
132 | } | |
133 | ||
60c5eb7d XL |
134 | pub fn overlapped_result( |
135 | &self, | |
136 | overlapped: *mut c::OVERLAPPED, | |
137 | wait: bool, | |
138 | ) -> io::Result<usize> { | |
54a0048b SL |
139 | unsafe { |
140 | let mut bytes = 0; | |
60c5eb7d XL |
141 | let wait = if wait { c::TRUE } else { c::FALSE }; |
142 | let res = cvt({ c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait) }); | |
54a0048b SL |
143 | match res { |
144 | Ok(_) => Ok(bytes as usize), | |
145 | Err(e) => { | |
60c5eb7d XL |
146 | if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) |
147 | || e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) | |
148 | { | |
54a0048b SL |
149 | Ok(0) |
150 | } else { | |
151 | Err(e) | |
152 | } | |
153 | } | |
154 | } | |
155 | } | |
156 | } | |
157 | ||
158 | pub fn cancel_io(&self) -> io::Result<()> { | |
60c5eb7d | 159 | unsafe { cvt(c::CancelIo(self.raw())).map(|_| ()) } |
54a0048b SL |
160 | } |
161 | ||
85aaf69f | 162 | pub fn write(&self, buf: &[u8]) -> io::Result<usize> { |
9346a6ac | 163 | let mut amt = 0; |
32a655c1 | 164 | let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; |
54a0048b | 165 | cvt(unsafe { |
60c5eb7d | 166 | c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, ptr::null_mut()) |
54a0048b | 167 | })?; |
9346a6ac | 168 | Ok(amt as usize) |
85aaf69f | 169 | } |
bd371182 | 170 | |
48663c56 XL |
171 | pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
172 | crate::io::default_write_vectored(|buf| self.write(buf), bufs) | |
173 | } | |
174 | ||
c30ab7b3 SL |
175 | pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { |
176 | let mut written = 0; | |
177 | let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; | |
178 | unsafe { | |
179 | let mut overlapped: c::OVERLAPPED = mem::zeroed(); | |
180 | overlapped.Offset = offset as u32; | |
181 | overlapped.OffsetHigh = (offset >> 32) as u32; | |
60c5eb7d XL |
182 | cvt(c::WriteFile( |
183 | self.0, | |
184 | buf.as_ptr() as c::LPVOID, | |
185 | len, | |
186 | &mut written, | |
187 | &mut overlapped, | |
188 | ))?; | |
c30ab7b3 SL |
189 | } |
190 | Ok(written as usize) | |
191 | } | |
192 | ||
60c5eb7d XL |
193 | pub fn duplicate( |
194 | &self, | |
195 | access: c::DWORD, | |
196 | inherit: bool, | |
197 | options: c::DWORD, | |
198 | ) -> io::Result<Handle> { | |
92a42be0 | 199 | let mut ret = 0 as c::HANDLE; |
54a0048b | 200 | cvt(unsafe { |
92a42be0 | 201 | let cur_proc = c::GetCurrentProcess(); |
60c5eb7d XL |
202 | c::DuplicateHandle( |
203 | cur_proc, | |
204 | self.0, | |
205 | cur_proc, | |
206 | &mut ret, | |
207 | access, | |
208 | inherit as c::BOOL, | |
209 | options, | |
210 | ) | |
54a0048b | 211 | })?; |
bd371182 AL |
212 | Ok(Handle::new(ret)) |
213 | } | |
85aaf69f | 214 | } |
54a0048b SL |
215 | |
216 | impl<'a> Read for &'a RawHandle { | |
217 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
218 | (**self).read(buf) | |
219 | } | |
48663c56 XL |
220 | |
221 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { | |
222 | (**self).read_vectored(bufs) | |
223 | } | |
54a0048b | 224 | } |