aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/sys/windows/handle.rs
diff options
context:
space:
mode:
authorValentin <[email protected]>2018-06-15 18:57:24 +0200
committerFenrirWolf <[email protected]>2018-06-15 10:57:24 -0600
commitf2a90174bb36b9ad528e863ab34c02ebce002b02 (patch)
tree959e8d67883d3a89e179b3549b1f30d28e51a87c /ctr-std/src/sys/windows/handle.rs
parentMerge pull request #68 from linouxis9/master (diff)
downloadctru-rs-f2a90174bb36b9ad528e863ab34c02ebce002b02.tar.xz
ctru-rs-f2a90174bb36b9ad528e863ab34c02ebce002b02.zip
Update for latest nightly 2018-06-09 (#70)
* Update for latest nightly 2018-06-09 * We now have a proper horizon os and sys modules in libstd
Diffstat (limited to 'ctr-std/src/sys/windows/handle.rs')
-rw-r--r--ctr-std/src/sys/windows/handle.rs218
1 files changed, 218 insertions, 0 deletions
diff --git a/ctr-std/src/sys/windows/handle.rs b/ctr-std/src/sys/windows/handle.rs
new file mode 100644
index 0000000..3729d6d
--- /dev/null
+++ b/ctr-std/src/sys/windows/handle.rs
@@ -0,0 +1,218 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![unstable(issue = "0", feature = "windows_handle")]
+
+use cmp;
+use io::{ErrorKind, Read};
+use io;
+use mem;
+use ops::Deref;
+use ptr;
+use sys::c;
+use sys::cvt;
+
+/// An owned container for `HANDLE` object, closing them on Drop.
+///
+/// All methods are inherited through a `Deref` impl to `RawHandle`
+pub struct Handle(RawHandle);
+
+/// A wrapper type for `HANDLE` objects to give them proper Send/Sync inference
+/// as well as Rust-y methods.
+///
+/// This does **not** drop the handle when it goes out of scope, use `Handle`
+/// instead for that.
+#[derive(Copy, Clone)]
+pub struct RawHandle(c::HANDLE);
+
+unsafe impl Send for RawHandle {}
+unsafe impl Sync for RawHandle {}
+
+impl Handle {
+ pub fn new(handle: c::HANDLE) -> Handle {
+ Handle(RawHandle::new(handle))
+ }
+
+ pub fn new_event(manual: bool, init: bool) -> io::Result<Handle> {
+ unsafe {
+ let event = c::CreateEventW(ptr::null_mut(),
+ manual as c::BOOL,
+ init as c::BOOL,
+ ptr::null());
+ if event.is_null() {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(Handle::new(event))
+ }
+ }
+ }
+
+ pub fn into_raw(self) -> c::HANDLE {
+ let ret = self.raw();
+ mem::forget(self);
+ return ret;
+ }
+}
+
+impl Deref for Handle {
+ type Target = RawHandle;
+ fn deref(&self) -> &RawHandle { &self.0 }
+}
+
+impl Drop for Handle {
+ fn drop(&mut self) {
+ unsafe { let _ = c::CloseHandle(self.raw()); }
+ }
+}
+
+impl RawHandle {
+ pub fn new(handle: c::HANDLE) -> RawHandle {
+ RawHandle(handle)
+ }
+
+ pub fn raw(&self) -> c::HANDLE { self.0 }
+
+ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+ let mut read = 0;
+ let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+ let res = cvt(unsafe {
+ c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
+ len, &mut read, ptr::null_mut())
+ });
+
+ match res {
+ Ok(_) => Ok(read as usize),
+
+ // The special treatment of BrokenPipe is to deal with Windows
+ // pipe semantics, which yields this error when *reading* from
+ // a pipe after the other end has closed; we interpret that as
+ // EOF on the pipe.
+ Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(0),
+
+ Err(e) => Err(e)
+ }
+ }
+
+ pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
+ let mut read = 0;
+ let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+ let res = unsafe {
+ let mut overlapped: c::OVERLAPPED = mem::zeroed();
+ overlapped.Offset = offset as u32;
+ overlapped.OffsetHigh = (offset >> 32) as u32;
+ cvt(c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
+ len, &mut read, &mut overlapped))
+ };
+ match res {
+ Ok(_) => Ok(read as usize),
+ Err(ref e) if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) => Ok(0),
+ Err(e) => Err(e),
+ }
+ }
+
+ pub unsafe fn read_overlapped(&self,
+ buf: &mut [u8],
+ overlapped: *mut c::OVERLAPPED)
+ -> io::Result<Option<usize>> {
+ let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+ let mut amt = 0;
+ let res = cvt({
+ c::ReadFile(self.0, buf.as_ptr() as c::LPVOID,
+ len, &mut amt, overlapped)
+ });
+ match res {
+ Ok(_) => Ok(Some(amt as usize)),
+ Err(e) => {
+ if e.raw_os_error() == Some(c::ERROR_IO_PENDING as i32) {
+ Ok(None)
+ } else if e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
+ Ok(Some(0))
+ } else {
+ Err(e)
+ }
+ }
+ }
+ }
+
+ pub fn overlapped_result(&self,
+ overlapped: *mut c::OVERLAPPED,
+ wait: bool) -> io::Result<usize> {
+ unsafe {
+ let mut bytes = 0;
+ let wait = if wait {c::TRUE} else {c::FALSE};
+ let res = cvt({
+ c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait)
+ });
+ match res {
+ Ok(_) => Ok(bytes as usize),
+ Err(e) => {
+ if e.raw_os_error() == Some(c::ERROR_HANDLE_EOF as i32) ||
+ e.raw_os_error() == Some(c::ERROR_BROKEN_PIPE as i32) {
+ Ok(0)
+ } else {
+ Err(e)
+ }
+ }
+ }
+ }
+ }
+
+ pub fn cancel_io(&self) -> io::Result<()> {
+ unsafe {
+ cvt(c::CancelIo(self.raw())).map(|_| ())
+ }
+ }
+
+ pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+ let mut me = self;
+ (&mut me).read_to_end(buf)
+ }
+
+ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+ let mut amt = 0;
+ let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+ cvt(unsafe {
+ c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
+ len, &mut amt, ptr::null_mut())
+ })?;
+ Ok(amt as usize)
+ }
+
+ pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
+ let mut written = 0;
+ let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+ unsafe {
+ let mut overlapped: c::OVERLAPPED = mem::zeroed();
+ overlapped.Offset = offset as u32;
+ overlapped.OffsetHigh = (offset >> 32) as u32;
+ cvt(c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
+ len, &mut written, &mut overlapped))?;
+ }
+ Ok(written as usize)
+ }
+
+ pub fn duplicate(&self, access: c::DWORD, inherit: bool,
+ options: c::DWORD) -> io::Result<Handle> {
+ let mut ret = 0 as c::HANDLE;
+ cvt(unsafe {
+ let cur_proc = c::GetCurrentProcess();
+ c::DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret,
+ access, inherit as c::BOOL,
+ options)
+ })?;
+ Ok(Handle::new(ret))
+ }
+}
+
+impl<'a> Read for &'a RawHandle {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ (**self).read(buf)
+ }
+}