]> git.proxmox.com Git - rustc.git/blob - src/libstd/sys/windows/handle.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / libstd / sys / windows / handle.rs
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
11 #![unstable(issue = "0", feature = "windows_handle")]
12
13 use prelude::v1::*;
14
15 use cmp;
16 use io::{ErrorKind, Read};
17 use io;
18 use mem;
19 use ops::Deref;
20 use ptr;
21 use sys::c;
22 use sys::cvt;
23 use sys_common::io::read_to_end_uninitialized;
24 use u32;
25
26 /// An owned container for `HANDLE` object, closing them on Drop.
27 ///
28 /// All methods are inherited through a `Deref` impl to `RawHandle`
29 pub struct Handle(RawHandle);
30
31 /// A wrapper type for `HANDLE` objects to give them proper Send/Sync inference
32 /// as well as Rust-y methods.
33 ///
34 /// This does **not** drop the handle when it goes out of scope, use `Handle`
35 /// instead for that.
36 #[derive(Copy, Clone)]
37 pub struct RawHandle(c::HANDLE);
38
39 unsafe impl Send for RawHandle {}
40 unsafe impl Sync for RawHandle {}
41
42 impl Handle {
43 pub fn new(handle: c::HANDLE) -> Handle {
44 Handle(RawHandle::new(handle))
45 }
46
47 pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> {
48 unsafe {
49 let event = c::CreateEventW(0 as *mut _,
50 manual as c::BOOL,
51 init as c::BOOL,
52 0 as *const _);
53 if event.is_null() {
54 Err(io::Error::last_os_error())
55 } else {
56 Ok(Handle::new(event))
57 }
58 }
59 }
60
61 pub fn into_raw(self) -> c::HANDLE {
62 let ret = self.raw();
63 mem::forget(self);
64 return ret;
65 }
66 }
67
68 impl Deref for Handle {
69 type Target = RawHandle;
70 fn deref(&self) -> &RawHandle { &self.0 }
71 }
72
73 impl Drop for Handle {
74 fn drop(&mut self) {
75 unsafe { let _ = c::CloseHandle(self.raw()); }
76 }
77 }
78
79 impl RawHandle {
80 pub fn new(handle: c::HANDLE) -> RawHandle {
81 RawHandle(handle)
82 }
83
84 pub fn raw(&self) -> c::HANDLE { self.0 }
85
86 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
87 let mut read = 0;
88 // ReadFile takes a DWORD (u32) for the length so it only supports
89 // reading u32::MAX bytes at a time.
90 let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
91 let res = cvt(unsafe {
92 c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
93 len, &mut read, ptr::null_mut())
94 });
95
96 match res {
97 Ok(_) => Ok(read as usize),
98
99 // The special treatment of BrokenPipe is to deal with Windows
100 // pipe semantics, which yields this error when *reading* from
101 // a pipe after the other end has closed; we interpret that as
102 // EOF on the pipe.
103 Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0),
104
105 Err(e) => Err(e)
106 }
107 }
108
109 pub unsafe fn read_overlapped(&self,
110 buf: &mut [u8],
111 overlapped: *mut c::OVERLAPPED)
112 -> io::Result<Option<usize>> {
113 let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
114 let mut amt = 0;
115 let res = cvt({
116 c::ReadFile(self.0, buf.as_ptr() as c::LPVOID,
117 len, &mut amt, overlapped)
118 });
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(&self,
134 overlapped: *mut c::OVERLAPPED,
135 wait: bool) -> io::Result<usize> {
136 unsafe {
137 let mut bytes = 0;
138 let wait = if wait {c::TRUE} else {c::FALSE};
139 let res = cvt({
140 c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait)
141 });
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 Ok(0)
148 } else {
149 Err(e)
150 }
151 }
152 }
153 }
154 }
155
156 pub fn cancel_io(&self) -> io::Result<()> {
157 unsafe {
158 cvt(c::CancelIo(self.raw())).map(|_| ())
159 }
160 }
161
162 pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
163 let mut me = self;
164 (&mut me).read_to_end(buf)
165 }
166
167 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
168 let mut amt = 0;
169 // WriteFile takes a DWORD (u32) for the length so it only supports
170 // writing u32::MAX bytes at a time.
171 let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
172 cvt(unsafe {
173 c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
174 len, &mut amt, ptr::null_mut())
175 })?;
176 Ok(amt as usize)
177 }
178
179 pub fn duplicate(&self, access: c::DWORD, inherit: bool,
180 options: c::DWORD) -> io::Result<Handle> {
181 let mut ret = 0 as c::HANDLE;
182 cvt(unsafe {
183 let cur_proc = c::GetCurrentProcess();
184 c::DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret,
185 access, inherit as c::BOOL,
186 options)
187 })?;
188 Ok(Handle::new(ret))
189 }
190 }
191
192 impl<'a> Read for &'a RawHandle {
193 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
194 (**self).read(buf)
195 }
196
197 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
198 unsafe { read_to_end_uninitialized(self, buf) }
199 }
200 }