]> git.proxmox.com Git - rustc.git/blame - src/libstd/sys/windows/handle.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / libstd / sys / windows / handle.rs
CommitLineData
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 13use cmp;
54a0048b 14use io::{ErrorKind, Read};
c34b1796 15use io;
c34b1796 16use mem;
62682a34 17use ops::Deref;
85aaf69f 18use ptr;
92a42be0 19use sys::c;
85aaf69f 20use sys::cvt;
54a0048b 21use sys_common::io::read_to_end_uninitialized;
7453a54e 22use 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`
27pub 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 35pub struct RawHandle(c::HANDLE);
62682a34
SL
36
37unsafe impl Send for RawHandle {}
38unsafe impl Sync for RawHandle {}
85aaf69f
SL
39
40impl 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
66impl Deref for Handle {
67 type Target = RawHandle;
68 fn deref(&self) -> &RawHandle { &self.0 }
69}
70
71impl Drop for Handle {
72 fn drop(&mut self) {
92a42be0 73 unsafe { let _ = c::CloseHandle(self.raw()); }
62682a34
SL
74 }
75}
76
77impl 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
220impl<'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}