]>
Commit | Line | Data |
---|---|---|
85aaf69f SL |
1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
54a0048b SL |
11 | #![unstable(issue = "0", feature = "windows_handle")] |
12 | ||
7453a54e | 13 | use cmp; |
54a0048b | 14 | use io::{ErrorKind, Read}; |
c34b1796 | 15 | use io; |
c34b1796 | 16 | use mem; |
62682a34 | 17 | use ops::Deref; |
85aaf69f | 18 | use ptr; |
92a42be0 | 19 | use sys::c; |
85aaf69f | 20 | use sys::cvt; |
54a0048b | 21 | use sys_common::io::read_to_end_uninitialized; |
7453a54e | 22 | use u32; |
85aaf69f | 23 | |
62682a34 SL |
24 | /// An owned container for `HANDLE` object, closing them on Drop. |
25 | /// | |
26 | /// All methods are inherited through a `Deref` impl to `RawHandle` | |
27 | pub struct Handle(RawHandle); | |
85aaf69f | 28 | |
62682a34 SL |
29 | /// A wrapper type for `HANDLE` objects to give them proper Send/Sync inference |
30 | /// as well as Rust-y methods. | |
31 | /// | |
32 | /// This does **not** drop the handle when it goes out of scope, use `Handle` | |
33 | /// instead for that. | |
34 | #[derive(Copy, Clone)] | |
92a42be0 | 35 | pub struct RawHandle(c::HANDLE); |
62682a34 SL |
36 | |
37 | unsafe impl Send for RawHandle {} | |
38 | unsafe impl Sync for RawHandle {} | |
85aaf69f SL |
39 | |
40 | impl Handle { | |
92a42be0 | 41 | pub fn new(handle: c::HANDLE) -> Handle { |
62682a34 | 42 | Handle(RawHandle::new(handle)) |
85aaf69f SL |
43 | } |
44 | ||
54a0048b SL |
45 | pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> { |
46 | unsafe { | |
5bcae85e | 47 | let event = c::CreateEventW(ptr::null_mut(), |
54a0048b SL |
48 | manual as c::BOOL, |
49 | init as c::BOOL, | |
5bcae85e | 50 | ptr::null()); |
54a0048b SL |
51 | if event.is_null() { |
52 | Err(io::Error::last_os_error()) | |
53 | } else { | |
54 | Ok(Handle::new(event)) | |
55 | } | |
56 | } | |
57 | } | |
58 | ||
92a42be0 | 59 | pub fn into_raw(self) -> c::HANDLE { |
62682a34 | 60 | let ret = self.raw(); |
bd371182 | 61 | mem::forget(self); |
c34b1796 AL |
62 | return ret; |
63 | } | |
62682a34 SL |
64 | } |
65 | ||
66 | impl Deref for Handle { | |
67 | type Target = RawHandle; | |
68 | fn deref(&self) -> &RawHandle { &self.0 } | |
69 | } | |
70 | ||
71 | impl Drop for Handle { | |
72 | fn drop(&mut self) { | |
92a42be0 | 73 | unsafe { let _ = c::CloseHandle(self.raw()); } |
62682a34 SL |
74 | } |
75 | } | |
76 | ||
77 | impl RawHandle { | |
92a42be0 | 78 | pub fn new(handle: c::HANDLE) -> RawHandle { |
62682a34 SL |
79 | RawHandle(handle) |
80 | } | |
81 | ||
92a42be0 | 82 | pub fn raw(&self) -> c::HANDLE { self.0 } |
c34b1796 | 83 | |
85aaf69f | 84 | pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { |
9346a6ac | 85 | let mut read = 0; |
7453a54e SL |
86 | // ReadFile takes a DWORD (u32) for the length so it only supports |
87 | // reading u32::MAX bytes at a time. | |
88 | let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD; | |
9346a6ac | 89 | let res = cvt(unsafe { |
7453a54e SL |
90 | c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, |
91 | len, &mut read, ptr::null_mut()) | |
9346a6ac AL |
92 | }); |
93 | ||
94 | match res { | |
95 | Ok(_) => Ok(read as usize), | |
96 | ||
97 | // The special treatment of BrokenPipe is to deal with Windows | |
98 | // pipe semantics, which yields this error when *reading* from | |
99 | // a pipe after the other end has closed; we interpret that as | |
100 | // EOF on the pipe. | |
101 | Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0), | |
102 | ||
103 | Err(e) => Err(e) | |
104 | } | |
85aaf69f SL |
105 | } |
106 | ||
c30ab7b3 SL |
107 | pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { |
108 | let mut read = 0; | |
109 | let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; | |
110 | let res = unsafe { | |
111 | let mut overlapped: c::OVERLAPPED = mem::zeroed(); | |
112 | overlapped.Offset = offset as u32; | |
113 | overlapped.OffsetHigh = (offset >> 32) as u32; | |
114 | cvt(c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, | |
115 | len, &mut read, &mut overlapped)) | |
116 | }; | |
117 | match res { | |
118 | Ok(_) => Ok(read as usize), | |
119 | Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0), | |
120 | Err(e) => Err(e), | |
121 | } | |
122 | } | |
123 | ||
54a0048b SL |
124 | pub unsafe fn read_overlapped(&self, |
125 | buf: &mut [u8], | |
126 | overlapped: *mut c::OVERLAPPED) | |
127 | -> io::Result<Option<usize>> { | |
128 | let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; | |
129 | let mut amt = 0; | |
130 | let res = cvt({ | |
131 | c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, | |
132 | len, &mut amt, overlapped) | |
133 | }); | |
134 | match res { | |
135 | Ok(_) => Ok(Some(amt as usize)), | |
136 | Err(e) => { | |
137 | if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) { | |
138 | Ok(None) | |
139 | } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) { | |
140 | Ok(Some(0)) | |
141 | } else { | |
142 | Err(e) | |
143 | } | |
144 | } | |
145 | } | |
146 | } | |
147 | ||
148 | pub fn overlapped_result(&self, | |
149 | overlapped: *mut c::OVERLAPPED, | |
150 | wait: bool) -> io::Result<usize> { | |
151 | unsafe { | |
152 | let mut bytes = 0; | |
153 | let wait = if wait {c::TRUE} else {c::FALSE}; | |
154 | let res = cvt({ | |
155 | c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait) | |
156 | }); | |
157 | match res { | |
158 | Ok(_) => Ok(bytes as usize), | |
159 | Err(e) => { | |
160 | if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) || | |
161 | e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) { | |
162 | Ok(0) | |
163 | } else { | |
164 | Err(e) | |
165 | } | |
166 | } | |
167 | } | |
168 | } | |
169 | } | |
170 | ||
171 | pub fn cancel_io(&self) -> io::Result<()> { | |
172 | unsafe { | |
173 | cvt(c::CancelIo(self.raw())).map(|_| ()) | |
174 | } | |
175 | } | |
176 | ||
177 | pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { | |
178 | let mut me = self; | |
179 | (&mut me).read_to_end(buf) | |
180 | } | |
181 | ||
85aaf69f | 182 | pub fn write(&self, buf: &[u8]) -> io::Result<usize> { |
9346a6ac | 183 | let mut amt = 0; |
7453a54e SL |
184 | // WriteFile takes a DWORD (u32) for the length so it only supports |
185 | // writing u32::MAX bytes at a time. | |
186 | let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD; | |
54a0048b | 187 | cvt(unsafe { |
92a42be0 | 188 | c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, |
7453a54e | 189 | len, &mut amt, ptr::null_mut()) |
54a0048b | 190 | })?; |
9346a6ac | 191 | Ok(amt as usize) |
85aaf69f | 192 | } |
bd371182 | 193 | |
c30ab7b3 SL |
194 | pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { |
195 | let mut written = 0; | |
196 | let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; | |
197 | unsafe { | |
198 | let mut overlapped: c::OVERLAPPED = mem::zeroed(); | |
199 | overlapped.Offset = offset as u32; | |
200 | overlapped.OffsetHigh = (offset >> 32) as u32; | |
201 | cvt(c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, | |
202 | len, &mut written, &mut overlapped))?; | |
203 | } | |
204 | Ok(written as usize) | |
205 | } | |
206 | ||
92a42be0 SL |
207 | pub fn duplicate(&self, access: c::DWORD, inherit: bool, |
208 | options: c::DWORD) -> io::Result<Handle> { | |
209 | let mut ret = 0 as c::HANDLE; | |
54a0048b | 210 | cvt(unsafe { |
92a42be0 SL |
211 | let cur_proc = c::GetCurrentProcess(); |
212 | c::DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret, | |
213 | access, inherit as c::BOOL, | |
bd371182 | 214 | options) |
54a0048b | 215 | })?; |
bd371182 AL |
216 | Ok(Handle::new(ret)) |
217 | } | |
85aaf69f | 218 | } |
54a0048b SL |
219 | |
220 | impl<'a> Read for &'a RawHandle { | |
221 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
222 | (**self).read(buf) | |
223 | } | |
224 | ||
225 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { | |
226 | unsafe { read_to_end_uninitialized(self, buf) } | |
227 | } | |
228 | } |