]> git.proxmox.com Git - rustc.git/blame - src/libstd/sys/windows/handle.rs
New upstream version 1.13.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
54a0048b
SL
107 pub unsafe fn read_overlapped(&self,
108 buf: &mut [u8],
109 overlapped: *mut c::OVERLAPPED)
110 -> io::Result<Option<usize>> {
111 let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
112 let mut amt = 0;
113 let res = cvt({
114 c::ReadFile(self.0, buf.as_ptr() as c::LPVOID,
115 len, &mut amt, overlapped)
116 });
117 match res {
118 Ok(_) => Ok(Some(amt as usize)),
119 Err(e) => {
120 if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
121 Ok(None)
122 } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
123 Ok(Some(0))
124 } else {
125 Err(e)
126 }
127 }
128 }
129 }
130
131 pub fn overlapped_result(&self,
132 overlapped: *mut c::OVERLAPPED,
133 wait: bool) -> io::Result<usize> {
134 unsafe {
135 let mut bytes = 0;
136 let wait = if wait {c::TRUE} else {c::FALSE};
137 let res = cvt({
138 c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait)
139 });
140 match res {
141 Ok(_) => Ok(bytes as usize),
142 Err(e) => {
143 if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) ||
144 e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
145 Ok(0)
146 } else {
147 Err(e)
148 }
149 }
150 }
151 }
152 }
153
154 pub fn cancel_io(&self) -> io::Result<()> {
155 unsafe {
156 cvt(c::CancelIo(self.raw())).map(|_| ())
157 }
158 }
159
160 pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
161 let mut me = self;
162 (&mut me).read_to_end(buf)
163 }
164
85aaf69f 165 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
9346a6ac 166 let mut amt = 0;
7453a54e
SL
167 // WriteFile takes a DWORD (u32) for the length so it only supports
168 // writing u32::MAX bytes at a time.
169 let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
54a0048b 170 cvt(unsafe {
92a42be0 171 c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
7453a54e 172 len, &mut amt, ptr::null_mut())
54a0048b 173 })?;
9346a6ac 174 Ok(amt as usize)
85aaf69f 175 }
bd371182 176
92a42be0
SL
177 pub fn duplicate(&self, access: c::DWORD, inherit: bool,
178 options: c::DWORD) -> io::Result<Handle> {
179 let mut ret = 0 as c::HANDLE;
54a0048b 180 cvt(unsafe {
92a42be0
SL
181 let cur_proc = c::GetCurrentProcess();
182 c::DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret,
183 access, inherit as c::BOOL,
bd371182 184 options)
54a0048b 185 })?;
bd371182
AL
186 Ok(Handle::new(ret))
187 }
85aaf69f 188}
54a0048b
SL
189
190impl<'a> Read for &'a RawHandle {
191 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
192 (**self).read(buf)
193 }
194
195 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
196 unsafe { read_to_end_uninitialized(self, buf) }
197 }
198}