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.
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.
11 #![unstable(issue = "0", feature = "windows_handle")]
14 use io::{ErrorKind, Read};
21 use sys_common::io::read_to_end_uninitialized;
24 /// An owned container for `HANDLE` object, closing them on Drop.
26 /// All methods are inherited through a `Deref` impl to `RawHandle`
27 pub struct Handle(RawHandle);
29 /// A wrapper type for `HANDLE` objects to give them proper Send/Sync inference
30 /// as well as Rust-y methods.
32 /// This does **not** drop the handle when it goes out of scope, use `Handle`
34 #[derive(Copy, Clone)]
35 pub struct RawHandle(c::HANDLE);
37 unsafe impl Send for RawHandle {}
38 unsafe impl Sync for RawHandle {}
41 pub fn new(handle: c::HANDLE) -> Handle {
42 Handle(RawHandle::new(handle))
45 pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> {
47 let event = c::CreateEventW(ptr::null_mut(),
52 Err(io::Error::last_os_error())
54 Ok(Handle::new(event))
59 pub fn into_raw(self) -> c::HANDLE {
66 impl Deref for Handle {
67 type Target = RawHandle;
68 fn deref(&self) -> &RawHandle { &self.0 }
71 impl Drop for Handle {
73 unsafe { let _ = c::CloseHandle(self.raw()); }
78 pub fn new(handle: c::HANDLE) -> RawHandle {
82 pub fn raw(&self) -> c::HANDLE { self.0 }
84 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
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;
89 let res = cvt(unsafe {
90 c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
91 len, &mut read, ptr::null_mut())
95 Ok(_) => Ok(read as usize),
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
101 Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0),
107 pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
109 let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
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))
118 Ok(_) => Ok(read as usize),
119 Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0),
124 pub unsafe fn read_overlapped(&self,
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;
131 c::ReadFile(self.0, buf.as_ptr() as c::LPVOID,
132 len, &mut amt, overlapped)
135 Ok(_) => Ok(Some(amt as usize)),
137 if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
139 } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
148 pub fn overlapped_result(&self,
149 overlapped: *mut c::OVERLAPPED,
150 wait: bool) -> io::Result<usize> {
153 let wait = if wait {c::TRUE} else {c::FALSE};
155 c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait)
158 Ok(_) => Ok(bytes as usize),
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) {
171 pub fn cancel_io(&self) -> io::Result<()> {
173 cvt(c::CancelIo(self.raw())).map(|_| ())
177 pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
179 (&mut me).read_to_end(buf)
182 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
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;
188 c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
189 len, &mut amt, ptr::null_mut())
194 pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
196 let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
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))?;
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;
211 let cur_proc = c::GetCurrentProcess();
212 c::DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret,
213 access, inherit as c::BOOL,
220 impl<'a> Read for &'a RawHandle {
221 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
225 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
226 unsafe { read_to_end_uninitialized(self, buf) }