summaryrefslogtreecommitdiffstats
path: root/third_party/rust/winapi-util/src/win.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/winapi-util/src/win.rs')
-rw-r--r--third_party/rust/winapi-util/src/win.rs246
1 files changed, 246 insertions, 0 deletions
diff --git a/third_party/rust/winapi-util/src/win.rs b/third_party/rust/winapi-util/src/win.rs
new file mode 100644
index 0000000000..9c77c0da62
--- /dev/null
+++ b/third_party/rust/winapi-util/src/win.rs
@@ -0,0 +1,246 @@
+use std::fs::File;
+use std::io;
+use std::os::windows::io::{
+ AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle,
+};
+use std::path::Path;
+use std::process;
+
+/// A handle represents an owned and valid Windows handle to a file-like
+/// object.
+///
+/// When an owned handle is dropped, then the underlying raw handle is closed.
+/// To get a borrowed handle, use `HandleRef`.
+#[derive(Debug)]
+pub struct Handle(File);
+
+impl AsRawHandle for Handle {
+ fn as_raw_handle(&self) -> RawHandle {
+ self.0.as_raw_handle()
+ }
+}
+
+impl FromRawHandle for Handle {
+ unsafe fn from_raw_handle(handle: RawHandle) -> Handle {
+ Handle(File::from_raw_handle(handle))
+ }
+}
+
+impl IntoRawHandle for Handle {
+ fn into_raw_handle(self) -> RawHandle {
+ self.0.into_raw_handle()
+ }
+}
+
+impl Handle {
+ /// Create an owned handle to the given file.
+ ///
+ /// When the returned handle is dropped, the file is closed.
+ ///
+ /// Note that if the given file represents a handle to a directory, then
+ /// it is generally required that it have been opened with the
+ /// [`FILE_FLAG_BACKUP_SEMANTICS`] flag in order to use it in various
+ /// calls such as `information` or `typ`. To have this done automatically
+ /// for you, use the `from_path_any` constructor.
+ ///
+ /// [`FILE_FLAG_BACKUP_SEMANTICS`]: https://docs.microsoft.com/en-us/windows/desktop/api/FileAPI/nf-fileapi-createfilea
+ pub fn from_file(file: File) -> Handle {
+ Handle(file)
+ }
+
+ /// Open a file to the given file path, and return an owned handle to that
+ /// file.
+ ///
+ /// When the returned handle is dropped, the file is closed.
+ ///
+ /// If there was a problem opening the file, then the corresponding error
+ /// is returned.
+ pub fn from_path<P: AsRef<Path>>(path: P) -> io::Result<Handle> {
+ Ok(Handle::from_file(File::open(path)?))
+ }
+
+ /// Like `from_path`, but supports opening directory handles as well.
+ ///
+ /// If you use `from_path` on a directory, then subsequent queries using
+ /// that handle will fail.
+ pub fn from_path_any<P: AsRef<Path>>(path: P) -> io::Result<Handle> {
+ use std::fs::OpenOptions;
+ use std::os::windows::fs::OpenOptionsExt;
+ use winapi::um::winbase::FILE_FLAG_BACKUP_SEMANTICS;
+
+ let file = OpenOptions::new()
+ .read(true)
+ .custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
+ .open(path)?;
+ Ok(Handle::from_file(file))
+ }
+
+ /// Return this handle as a standard `File` reference.
+ pub fn as_file(&self) -> &File {
+ &self.0
+ }
+
+ /// Return this handle as a standard `File` mutable reference.
+ pub fn as_file_mut(&mut self) -> &mut File {
+ &mut self.0
+ }
+}
+
+/// Represents a borrowed and valid Windows handle to a file-like object, such
+/// as stdin/stdout/stderr or an actual file.
+///
+/// When a borrowed handle is dropped, then the underlying raw handle is
+/// **not** closed. To get an owned handle, use `Handle`.
+#[derive(Debug)]
+pub struct HandleRef(HandleRefInner);
+
+/// The representation of a HandleRef, on which we define a custom Drop impl
+/// that avoids closing the underlying raw handle.
+#[derive(Debug)]
+struct HandleRefInner(Option<File>);
+
+impl Drop for HandleRefInner {
+ fn drop(&mut self) {
+ self.0.take().unwrap().into_raw_handle();
+ }
+}
+
+impl AsRawHandle for HandleRef {
+ fn as_raw_handle(&self) -> RawHandle {
+ self.as_file().as_raw_handle()
+ }
+}
+
+impl Clone for HandleRef {
+ fn clone(&self) -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
+ }
+}
+
+impl HandleRef {
+ /// Create a borrowed handle to stdin.
+ ///
+ /// When the returned handle is dropped, stdin is not closed.
+ pub fn stdin() -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(io::stdin().as_raw_handle()) }
+ }
+
+ /// Create a handle to stdout.
+ ///
+ /// When the returned handle is dropped, stdout is not closed.
+ pub fn stdout() -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(io::stdout().as_raw_handle()) }
+ }
+
+ /// Create a handle to stderr.
+ ///
+ /// When the returned handle is dropped, stderr is not closed.
+ pub fn stderr() -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(io::stderr().as_raw_handle()) }
+ }
+
+ /// Create a borrowed handle to the given file.
+ ///
+ /// When the returned handle is dropped, the file is not closed.
+ pub fn from_file(file: &File) -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(file.as_raw_handle()) }
+ }
+
+ /// Create a borrowed handle from the given raw handle.
+ ///
+ /// Note that unlike the `FromRawHandle` trait, this constructor does
+ /// **not** consume ownership of the given handle. That is, when the
+ /// borrowed handle created by this constructor is dropped, the underlying
+ /// handle will not be closed.
+ ///
+ /// # Safety
+ ///
+ /// This is unsafe because there is no guarantee that the given raw handle
+ /// is a valid handle. The caller must ensure this is true before invoking
+ /// this constructor.
+ pub unsafe fn from_raw_handle(handle: RawHandle) -> HandleRef {
+ HandleRef(HandleRefInner(Some(File::from_raw_handle(handle))))
+ }
+
+ /// Return this handle as a standard `File` reference.
+ pub fn as_file(&self) -> &File {
+ (self.0).0.as_ref().unwrap()
+ }
+
+ /// Return this handle as a standard `File` mutable reference.
+ pub fn as_file_mut(&mut self) -> &mut File {
+ (self.0).0.as_mut().unwrap()
+ }
+}
+
+/// Construct borrowed and valid Windows handles from file-like objects.
+pub trait AsHandleRef {
+ /// A borrowed handle that wraps the raw handle of the `Self` object.
+ fn as_handle_ref(&self) -> HandleRef;
+
+ /// A convenience routine for extracting a `HandleRef` from `Self`, and
+ /// then extracting a raw handle from the `HandleRef`.
+ fn as_raw(&self) -> RawHandle {
+ self.as_handle_ref().as_raw_handle()
+ }
+}
+
+impl<'a, T: AsHandleRef> AsHandleRef for &'a T {
+ fn as_handle_ref(&self) -> HandleRef {
+ (**self).as_handle_ref()
+ }
+}
+
+impl AsHandleRef for Handle {
+ fn as_handle_ref(&self) -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
+ }
+}
+
+impl AsHandleRef for HandleRef {
+ fn as_handle_ref(&self) -> HandleRef {
+ self.clone()
+ }
+}
+
+impl AsHandleRef for File {
+ fn as_handle_ref(&self) -> HandleRef {
+ HandleRef::from_file(self)
+ }
+}
+
+impl AsHandleRef for io::Stdin {
+ fn as_handle_ref(&self) -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
+ }
+}
+
+impl AsHandleRef for io::Stdout {
+ fn as_handle_ref(&self) -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
+ }
+}
+
+impl AsHandleRef for io::Stderr {
+ fn as_handle_ref(&self) -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
+ }
+}
+
+impl AsHandleRef for process::ChildStdin {
+ fn as_handle_ref(&self) -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
+ }
+}
+
+impl AsHandleRef for process::ChildStdout {
+ fn as_handle_ref(&self) -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
+ }
+}
+
+impl AsHandleRef for process::ChildStderr {
+ fn as_handle_ref(&self) -> HandleRef {
+ unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
+ }
+}