summaryrefslogtreecommitdiffstats
path: root/third_party/rust/winapi-util
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
commit0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch)
treea31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /third_party/rust/winapi-util
parentInitial commit. (diff)
downloadfirefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz
firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/winapi-util')
-rw-r--r--third_party/rust/winapi-util/.cargo-checksum.json1
-rw-r--r--third_party/rust/winapi-util/COPYING3
-rw-r--r--third_party/rust/winapi-util/Cargo.toml30
-rw-r--r--third_party/rust/winapi-util/LICENSE-MIT21
-rw-r--r--third_party/rust/winapi-util/README.md58
-rw-r--r--third_party/rust/winapi-util/UNLICENSE24
-rw-r--r--third_party/rust/winapi-util/rustfmt.toml2
-rw-r--r--third_party/rust/winapi-util/src/console.rs402
-rw-r--r--third_party/rust/winapi-util/src/file.rs168
-rw-r--r--third_party/rust/winapi-util/src/lib.rs32
-rw-r--r--third_party/rust/winapi-util/src/win.rs246
11 files changed, 987 insertions, 0 deletions
diff --git a/third_party/rust/winapi-util/.cargo-checksum.json b/third_party/rust/winapi-util/.cargo-checksum.json
new file mode 100644
index 0000000000..deb1761563
--- /dev/null
+++ b/third_party/rust/winapi-util/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"8d5e3ed912b57104e1448a8437c840a5d5b9842e5cbb371429f9e879cb45fc56","LICENSE-MIT":"cb3c929a05e6cbc9de9ab06a4c57eeb60ca8c724bef6c138c87d3a577e27aa14","README.md":"b97062c8af7a615725a19394c8d26a19460a1840979196f0c119a1c1432d15f1","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/console.rs":"41d3d1d7501e9e4f8836d642bf8a848b690112fb707b040cabe7f8f1f0e4a692","src/file.rs":"5e2b5f60de7f8a2eeeafe165701eb0e442a0bafbf6df6e2e0d92fdccafd7a8bf","src/lib.rs":"36aba07c7bd526e341382b6471212ccfef8030f27b73a607f2539b307ccff8d1","src/win.rs":"146b65eae8fe2fe3c567609d7d7be0a983f607fc9d3fcdb5cd7ca6f2cc7bde33"},"package":"70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"} \ No newline at end of file
diff --git a/third_party/rust/winapi-util/COPYING b/third_party/rust/winapi-util/COPYING
new file mode 100644
index 0000000000..bb9c20a094
--- /dev/null
+++ b/third_party/rust/winapi-util/COPYING
@@ -0,0 +1,3 @@
+This project is dual-licensed under the Unlicense and MIT licenses.
+
+You may use this code under the terms of either license.
diff --git a/third_party/rust/winapi-util/Cargo.toml b/third_party/rust/winapi-util/Cargo.toml
new file mode 100644
index 0000000000..fe6933cffb
--- /dev/null
+++ b/third_party/rust/winapi-util/Cargo.toml
@@ -0,0 +1,30 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "winapi-util"
+version = "0.1.5"
+authors = ["Andrew Gallant <jamslam@gmail.com>"]
+description = "A dumping ground for high level safe wrappers over winapi."
+homepage = "https://github.com/BurntSushi/winapi-util"
+documentation = "https://docs.rs/winapi-util"
+readme = "README.md"
+keywords = ["windows", "winapi", "util", "win"]
+categories = ["os::windows-apis", "external-ffi-bindings"]
+license = "Unlicense/MIT"
+repository = "https://github.com/BurntSushi/winapi-util"
+[package.metadata.docs.rs]
+targets = ["x86_64-pc-windows-msvc"]
+[target."cfg(windows)".dependencies.winapi]
+version = "0.3"
+features = ["std", "consoleapi", "errhandlingapi", "fileapi", "minwindef", "processenv", "winbase", "wincon", "winerror", "winnt"]
diff --git a/third_party/rust/winapi-util/LICENSE-MIT b/third_party/rust/winapi-util/LICENSE-MIT
new file mode 100644
index 0000000000..3303149e52
--- /dev/null
+++ b/third_party/rust/winapi-util/LICENSE-MIT
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Andrew Gallant
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/third_party/rust/winapi-util/README.md b/third_party/rust/winapi-util/README.md
new file mode 100644
index 0000000000..79e47301fc
--- /dev/null
+++ b/third_party/rust/winapi-util/README.md
@@ -0,0 +1,58 @@
+winapi-util
+===========
+This crate provides a smattering of safe wrappers around various parts of the
+[winapi](https://crates.io/crates/winapi) crate.
+
+[![Build status](https://github.com/BurntSushi/winapi-util/workflows/ci/badge.svg)](https://github.com/BurntSushi/winapi-util/actions)
+[![](http://meritbadge.herokuapp.com/winapi-util)](https://crates.io/crates/winapi-util)
+
+Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
+
+
+### Documentation
+
+https://docs.rs/winapi-util
+
+
+### Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+winapi-util = "0.1"
+```
+
+
+### Notes
+
+This crate was born out of frustration with having to write lots of little
+ffi utility bindings in a variety of crates in order to get Windows support.
+Eventually, I started needing to copy & paste a lot of those utility routines.
+Since they are utility routines, they often don't make sense to expose directly
+in the crate in which they are defined. Instead of continuing this process,
+I decided to make a crate instead.
+
+Normally, I'm not a huge fan of "utility" crates like this that don't have a
+well defined scope, but this is primarily a practical endeavor to make it
+easier to isolate Windows specific ffi code.
+
+While I don't have a long term vision for this crate, I will welcome additional
+PRs that add more high level routines/types on an as-needed basis.
+
+**WARNING:** I am not a Windows developer, so extra review to make sure I've
+got things right is most appreciated.
+
+
+### Minimum Rust version policy
+
+This crate's minimum supported `rustc` version is `1.34.0`.
+
+The current policy is that the minimum Rust version required to use this crate
+can be increased in non-breaking version updates. For example, if `crate 1.0`
+requires Rust 1.20.0, then `crate 1.0.z` for all values of `z` will also
+require Rust 1.20.0 or newer. However, `crate 1.y` for `y > 0` may require a
+newer minimum version of Rust.
+
+In general, this crate will be conservative with respect to the minimum
+supported version of Rust.
diff --git a/third_party/rust/winapi-util/UNLICENSE b/third_party/rust/winapi-util/UNLICENSE
new file mode 100644
index 0000000000..68a49daad8
--- /dev/null
+++ b/third_party/rust/winapi-util/UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/third_party/rust/winapi-util/rustfmt.toml b/third_party/rust/winapi-util/rustfmt.toml
new file mode 100644
index 0000000000..aa37a218b9
--- /dev/null
+++ b/third_party/rust/winapi-util/rustfmt.toml
@@ -0,0 +1,2 @@
+max_width = 79
+use_small_heuristics = "max"
diff --git a/third_party/rust/winapi-util/src/console.rs b/third_party/rust/winapi-util/src/console.rs
new file mode 100644
index 0000000000..233d5c9694
--- /dev/null
+++ b/third_party/rust/winapi-util/src/console.rs
@@ -0,0 +1,402 @@
+use std::io;
+use std::mem;
+
+use winapi::shared::minwindef::WORD;
+use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
+use winapi::um::wincon::{
+ self, GetConsoleScreenBufferInfo, SetConsoleTextAttribute,
+ CONSOLE_SCREEN_BUFFER_INFO, FOREGROUND_BLUE as FG_BLUE,
+ FOREGROUND_GREEN as FG_GREEN, FOREGROUND_INTENSITY as FG_INTENSITY,
+ FOREGROUND_RED as FG_RED,
+};
+
+use crate::{AsHandleRef, HandleRef};
+
+const FG_CYAN: WORD = FG_BLUE | FG_GREEN;
+const FG_MAGENTA: WORD = FG_BLUE | FG_RED;
+const FG_YELLOW: WORD = FG_GREEN | FG_RED;
+const FG_WHITE: WORD = FG_BLUE | FG_GREEN | FG_RED;
+
+/// Query the given handle for information about the console's screen buffer.
+///
+/// The given handle should represent a console. Otherwise, an error is
+/// returned.
+///
+/// This corresponds to calling [`GetConsoleScreenBufferInfo`].
+///
+/// [`GetConsoleScreenBufferInfo`]: https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo
+pub fn screen_buffer_info<H: AsHandleRef>(
+ h: H,
+) -> io::Result<ScreenBufferInfo> {
+ unsafe {
+ let mut info: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
+ let rc = GetConsoleScreenBufferInfo(h.as_raw(), &mut info);
+ if rc == 0 {
+ return Err(io::Error::last_os_error());
+ }
+ Ok(ScreenBufferInfo(info))
+ }
+}
+
+/// Set the text attributes of the console represented by the given handle.
+///
+/// This corresponds to calling [`SetConsoleTextAttribute`].
+///
+/// [`SetConsoleTextAttribute`]: https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute
+pub fn set_text_attributes<H: AsHandleRef>(
+ h: H,
+ attributes: u16,
+) -> io::Result<()> {
+ if unsafe { SetConsoleTextAttribute(h.as_raw(), attributes) } == 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+/// Query the mode of the console represented by the given handle.
+///
+/// This corresponds to calling [`GetConsoleMode`], which describes the return
+/// value.
+///
+/// [`GetConsoleMode`]: https://docs.microsoft.com/en-us/windows/console/getconsolemode
+pub fn mode<H: AsHandleRef>(h: H) -> io::Result<u32> {
+ let mut mode = 0;
+ if unsafe { GetConsoleMode(h.as_raw(), &mut mode) } == 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(mode)
+ }
+}
+
+/// Set the mode of the console represented by the given handle.
+///
+/// This corresponds to calling [`SetConsoleMode`], which describes the format
+/// of the mode parameter.
+///
+/// [`SetConsoleMode`]: https://docs.microsoft.com/en-us/windows/console/setconsolemode
+pub fn set_mode<H: AsHandleRef>(h: H, mode: u32) -> io::Result<()> {
+ if unsafe { SetConsoleMode(h.as_raw(), mode) } == 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(())
+ }
+}
+
+/// Represents console screen buffer information such as size, cursor position
+/// and styling attributes.
+///
+/// This wraps a [`CONSOLE_SCREEN_BUFFER_INFO`].
+///
+/// [`CONSOLE_SCREEN_BUFFER_INFO`]: https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str
+#[derive(Clone)]
+pub struct ScreenBufferInfo(CONSOLE_SCREEN_BUFFER_INFO);
+
+impl ScreenBufferInfo {
+ /// Returns the size of the console screen buffer, in character columns and
+ /// rows.
+ ///
+ /// This corresponds to `dwSize`.
+ pub fn size(&self) -> (i16, i16) {
+ (self.0.dwSize.X, self.0.dwSize.Y)
+ }
+
+ /// Returns the position of the cursor in terms of column and row
+ /// coordinates of the console screen buffer.
+ ///
+ /// This corresponds to `dwCursorPosition`.
+ pub fn cursor_position(&self) -> (i16, i16) {
+ (self.0.dwCursorPosition.X, self.0.dwCursorPosition.Y)
+ }
+
+ /// Returns the character attributes associated with this console.
+ ///
+ /// This corresponds to `wAttributes`.
+ ///
+ /// See [`char info`] for more details.
+ ///
+ /// [`char info`]: https://docs.microsoft.com/en-us/windows/console/char-info-str
+ pub fn attributes(&self) -> u16 {
+ self.0.wAttributes
+ }
+
+ /// Returns the maximum size of the console window, in character columns
+ /// and rows, given the current screen buffer size and font and the screen
+ /// size.
+ pub fn max_window_size(&self) -> (i16, i16) {
+ (self.0.dwMaximumWindowSize.X, self.0.dwMaximumWindowSize.Y)
+ }
+
+ /// Returns the console screen buffer coordinates of the upper-left and
+ /// lower-right corners of the display window.
+ ///
+ /// This corresponds to `srWindow`.
+ pub fn window_rect(&self) -> SmallRect {
+ SmallRect {
+ left: self.0.srWindow.Left,
+ top: self.0.srWindow.Top,
+ right: self.0.srWindow.Right,
+ bottom: self.0.srWindow.Bottom,
+ }
+ }
+}
+
+/// Defines the coordinates of the upper left and lower right corners of a rectangle.
+///
+/// This corresponds to [`SMALL_RECT`].
+///
+/// [`SMALL_RECT`]: https://docs.microsoft.com/en-us/windows/console/small-rect-str
+pub struct SmallRect {
+ pub left: i16,
+ pub top: i16,
+ pub right: i16,
+ pub bottom: i16,
+}
+
+/// A Windows console.
+///
+/// This represents a very limited set of functionality available to a Windows
+/// console. In particular, it can only change text attributes such as color
+/// and intensity. This may grow over time. If you need more routines, please
+/// file an issue and/or PR.
+///
+/// There is no way to "write" to this console. Simply write to
+/// stdout or stderr instead, while interleaving instructions to the console
+/// to change text attributes.
+///
+/// A common pitfall when using a console is to forget to flush writes to
+/// stdout before setting new text attributes.
+///
+/// # Example
+/// ```no_run
+/// # #[cfg(windows)]
+/// # {
+/// use winapi_util::console::{Console, Color, Intense};
+///
+/// let mut con = Console::stdout().unwrap();
+/// con.fg(Intense::Yes, Color::Cyan).unwrap();
+/// println!("This text will be intense cyan.");
+/// con.reset().unwrap();
+/// println!("This text will be normal.");
+/// # }
+/// ```
+#[derive(Debug)]
+pub struct Console {
+ kind: HandleKind,
+ start_attr: TextAttributes,
+ cur_attr: TextAttributes,
+}
+
+#[derive(Clone, Copy, Debug)]
+enum HandleKind {
+ Stdout,
+ Stderr,
+}
+
+impl HandleKind {
+ fn handle(&self) -> HandleRef {
+ match *self {
+ HandleKind::Stdout => HandleRef::stdout(),
+ HandleKind::Stderr => HandleRef::stderr(),
+ }
+ }
+}
+
+impl Console {
+ /// Get a console for a standard I/O stream.
+ fn create_for_stream(kind: HandleKind) -> io::Result<Console> {
+ let h = kind.handle();
+ let info = screen_buffer_info(&h)?;
+ let attr = TextAttributes::from_word(info.attributes());
+ Ok(Console { kind: kind, start_attr: attr, cur_attr: attr })
+ }
+
+ /// Create a new Console to stdout.
+ ///
+ /// If there was a problem creating the console, then an error is returned.
+ pub fn stdout() -> io::Result<Console> {
+ Self::create_for_stream(HandleKind::Stdout)
+ }
+
+ /// Create a new Console to stderr.
+ ///
+ /// If there was a problem creating the console, then an error is returned.
+ pub fn stderr() -> io::Result<Console> {
+ Self::create_for_stream(HandleKind::Stderr)
+ }
+
+ /// Applies the current text attributes.
+ fn set(&mut self) -> io::Result<()> {
+ set_text_attributes(self.kind.handle(), self.cur_attr.to_word())
+ }
+
+ /// Apply the given intensity and color attributes to the console
+ /// foreground.
+ ///
+ /// If there was a problem setting attributes on the console, then an error
+ /// is returned.
+ pub fn fg(&mut self, intense: Intense, color: Color) -> io::Result<()> {
+ self.cur_attr.fg_color = color;
+ self.cur_attr.fg_intense = intense;
+ self.set()
+ }
+
+ /// Apply the given intensity and color attributes to the console
+ /// background.
+ ///
+ /// If there was a problem setting attributes on the console, then an error
+ /// is returned.
+ pub fn bg(&mut self, intense: Intense, color: Color) -> io::Result<()> {
+ self.cur_attr.bg_color = color;
+ self.cur_attr.bg_intense = intense;
+ self.set()
+ }
+
+ /// Reset the console text attributes to their original settings.
+ ///
+ /// The original settings correspond to the text attributes on the console
+ /// when this `Console` value was created.
+ ///
+ /// If there was a problem setting attributes on the console, then an error
+ /// is returned.
+ pub fn reset(&mut self) -> io::Result<()> {
+ self.cur_attr = self.start_attr;
+ self.set()
+ }
+
+ /// Toggle virtual terminal processing.
+ ///
+ /// This method attempts to toggle virtual terminal processing for this
+ /// console. If there was a problem toggling it, then an error returned.
+ /// On success, the caller may assume that toggling it was successful.
+ ///
+ /// When virtual terminal processing is enabled, characters emitted to the
+ /// console are parsed for VT100 and similar control character sequences
+ /// that control color and other similar operations.
+ pub fn set_virtual_terminal_processing(
+ &mut self,
+ yes: bool,
+ ) -> io::Result<()> {
+ let vt = wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+
+ let handle = self.kind.handle();
+ let old_mode = mode(&handle)?;
+ let new_mode = if yes { old_mode | vt } else { old_mode & !vt };
+ if old_mode == new_mode {
+ return Ok(());
+ }
+ set_mode(&handle, new_mode)
+ }
+}
+
+/// A representation of text attributes for the Windows console.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+struct TextAttributes {
+ fg_color: Color,
+ fg_intense: Intense,
+ bg_color: Color,
+ bg_intense: Intense,
+}
+
+impl TextAttributes {
+ fn to_word(&self) -> WORD {
+ let mut w = 0;
+ w |= self.fg_color.to_fg();
+ w |= self.fg_intense.to_fg();
+ w |= self.bg_color.to_bg();
+ w |= self.bg_intense.to_bg();
+ w
+ }
+
+ fn from_word(word: WORD) -> TextAttributes {
+ TextAttributes {
+ fg_color: Color::from_fg(word),
+ fg_intense: Intense::from_fg(word),
+ bg_color: Color::from_bg(word),
+ bg_intense: Intense::from_bg(word),
+ }
+ }
+}
+
+/// Whether to use intense colors or not.
+#[allow(missing_docs)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum Intense {
+ Yes,
+ No,
+}
+
+impl Intense {
+ fn to_bg(&self) -> WORD {
+ self.to_fg() << 4
+ }
+
+ fn from_bg(word: WORD) -> Intense {
+ Intense::from_fg(word >> 4)
+ }
+
+ fn to_fg(&self) -> WORD {
+ match *self {
+ Intense::No => 0,
+ Intense::Yes => FG_INTENSITY,
+ }
+ }
+
+ fn from_fg(word: WORD) -> Intense {
+ if word & FG_INTENSITY > 0 {
+ Intense::Yes
+ } else {
+ Intense::No
+ }
+ }
+}
+
+/// The set of available colors for use with a Windows console.
+#[allow(missing_docs)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum Color {
+ Black,
+ Blue,
+ Green,
+ Red,
+ Cyan,
+ Magenta,
+ Yellow,
+ White,
+}
+
+impl Color {
+ fn to_bg(&self) -> WORD {
+ self.to_fg() << 4
+ }
+
+ fn from_bg(word: WORD) -> Color {
+ Color::from_fg(word >> 4)
+ }
+
+ fn to_fg(&self) -> WORD {
+ match *self {
+ Color::Black => 0,
+ Color::Blue => FG_BLUE,
+ Color::Green => FG_GREEN,
+ Color::Red => FG_RED,
+ Color::Cyan => FG_CYAN,
+ Color::Magenta => FG_MAGENTA,
+ Color::Yellow => FG_YELLOW,
+ Color::White => FG_WHITE,
+ }
+ }
+
+ fn from_fg(word: WORD) -> Color {
+ match word & 0b111 {
+ FG_BLUE => Color::Blue,
+ FG_GREEN => Color::Green,
+ FG_RED => Color::Red,
+ FG_CYAN => Color::Cyan,
+ FG_MAGENTA => Color::Magenta,
+ FG_YELLOW => Color::Yellow,
+ FG_WHITE => Color::White,
+ _ => Color::Black,
+ }
+ }
+}
diff --git a/third_party/rust/winapi-util/src/file.rs b/third_party/rust/winapi-util/src/file.rs
new file mode 100644
index 0000000000..56a1e4105f
--- /dev/null
+++ b/third_party/rust/winapi-util/src/file.rs
@@ -0,0 +1,168 @@
+use std::io;
+use std::mem;
+
+use winapi::shared::minwindef::FILETIME;
+use winapi::shared::winerror::NO_ERROR;
+use winapi::um::errhandlingapi::GetLastError;
+use winapi::um::fileapi::{
+ GetFileInformationByHandle, GetFileType, BY_HANDLE_FILE_INFORMATION,
+};
+use winapi::um::winnt;
+
+use crate::AsHandleRef;
+
+/// Return various pieces of information about a file.
+///
+/// This includes information such as a file's size, unique identifier and
+/// time related fields.
+///
+/// This corresponds to calling [`GetFileInformationByHandle`].
+///
+/// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle
+pub fn information<H: AsHandleRef>(h: H) -> io::Result<Information> {
+ unsafe {
+ let mut info: BY_HANDLE_FILE_INFORMATION = mem::zeroed();
+ let rc = GetFileInformationByHandle(h.as_raw(), &mut info);
+ if rc == 0 {
+ return Err(io::Error::last_os_error());
+ };
+ Ok(Information(info))
+ }
+}
+
+/// Returns the file type of the given handle.
+///
+/// If there was a problem querying the file type, then an error is returned.
+///
+/// This corresponds to calling [`GetFileType`].
+///
+/// [`GetFileType`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletype
+pub fn typ<H: AsHandleRef>(h: H) -> io::Result<Type> {
+ unsafe {
+ let rc = GetFileType(h.as_raw());
+ if rc == 0 && GetLastError() != NO_ERROR {
+ return Err(io::Error::last_os_error());
+ }
+ Ok(Type(rc))
+ }
+}
+
+/// Returns true if and only if the given file attributes contain the
+/// `FILE_ATTRIBUTE_HIDDEN` attribute.
+pub fn is_hidden(file_attributes: u64) -> bool {
+ file_attributes & (winnt::FILE_ATTRIBUTE_HIDDEN as u64) > 0
+}
+
+/// Represents file information such as creation time, file size, etc.
+///
+/// This wraps a [`BY_HANDLE_FILE_INFORMATION`].
+///
+/// [`BY_HANDLE_FILE_INFORMATION`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information
+#[derive(Clone)]
+pub struct Information(BY_HANDLE_FILE_INFORMATION);
+
+impl Information {
+ /// Returns file attributes.
+ ///
+ /// This corresponds to `dwFileAttributes`.
+ pub fn file_attributes(&self) -> u64 {
+ self.0.dwFileAttributes as u64
+ }
+
+ /// Returns true if and only if this file information has the
+ /// `FILE_ATTRIBUTE_HIDDEN` attribute.
+ pub fn is_hidden(&self) -> bool {
+ is_hidden(self.file_attributes())
+ }
+
+ /// Return the creation time, if one exists.
+ ///
+ /// This corresponds to `ftCreationTime`.
+ pub fn creation_time(&self) -> Option<u64> {
+ filetime_to_u64(self.0.ftCreationTime)
+ }
+
+ /// Return the last access time, if one exists.
+ ///
+ /// This corresponds to `ftLastAccessTime`.
+ pub fn last_access_time(&self) -> Option<u64> {
+ filetime_to_u64(self.0.ftLastAccessTime)
+ }
+
+ /// Return the last write time, if one exists.
+ ///
+ /// This corresponds to `ftLastWriteTime`.
+ pub fn last_write_time(&self) -> Option<u64> {
+ filetime_to_u64(self.0.ftLastWriteTime)
+ }
+
+ /// Return the serial number of the volume that the file is on.
+ ///
+ /// This corresponds to `dwVolumeSerialNumber`.
+ pub fn volume_serial_number(&self) -> u64 {
+ self.0.dwVolumeSerialNumber as u64
+ }
+
+ /// Return the file size, in bytes.
+ ///
+ /// This corresponds to `nFileSizeHigh` and `nFileSizeLow`.
+ pub fn file_size(&self) -> u64 {
+ ((self.0.nFileSizeHigh as u64) << 32) | (self.0.nFileSizeLow as u64)
+ }
+
+ /// Return the number of links to this file.
+ ///
+ /// This corresponds to `nNumberOfLinks`.
+ pub fn number_of_links(&self) -> u64 {
+ self.0.nNumberOfLinks as u64
+ }
+
+ /// Return the index of this file. The index of a file is a purpotedly
+ /// unique identifier for a file within a particular volume.
+ pub fn file_index(&self) -> u64 {
+ ((self.0.nFileIndexHigh as u64) << 32) | (self.0.nFileIndexLow as u64)
+ }
+}
+
+/// Represents a Windows file type.
+///
+/// This wraps the result of [`GetFileType`].
+///
+/// [`GetFileType`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletype
+#[derive(Clone)]
+pub struct Type(u32);
+
+impl Type {
+ /// Returns true if this type represents a character file, which is
+ /// typically an LPT device or a console.
+ pub fn is_char(&self) -> bool {
+ self.0 == ::winapi::um::winbase::FILE_TYPE_CHAR
+ }
+
+ /// Returns true if this type represents a disk file.
+ pub fn is_disk(&self) -> bool {
+ self.0 == ::winapi::um::winbase::FILE_TYPE_DISK
+ }
+
+ /// Returns true if this type represents a sock, named pipe or an
+ /// anonymous pipe.
+ pub fn is_pipe(&self) -> bool {
+ self.0 == ::winapi::um::winbase::FILE_TYPE_PIPE
+ }
+
+ /// Returns true if this type is not known.
+ ///
+ /// Note that this never corresponds to a failure.
+ pub fn is_unknown(&self) -> bool {
+ self.0 == ::winapi::um::winbase::FILE_TYPE_UNKNOWN
+ }
+}
+
+fn filetime_to_u64(t: FILETIME) -> Option<u64> {
+ let v = ((t.dwHighDateTime as u64) << 32) | (t.dwLowDateTime as u64);
+ if v == 0 {
+ None
+ } else {
+ Some(v)
+ }
+}
diff --git a/third_party/rust/winapi-util/src/lib.rs b/third_party/rust/winapi-util/src/lib.rs
new file mode 100644
index 0000000000..0bb259dbae
--- /dev/null
+++ b/third_party/rust/winapi-util/src/lib.rs
@@ -0,0 +1,32 @@
+/*!
+This crate provides a smattering of safe routines for parts of winapi. The
+primary purpose of this crate is to serve as a dumping ground for various
+utility functions that make interactions with winapi safe. This permits the
+centralization of `unsafe` when dealing with Windows APIs, and thus makes it
+easier to audit.
+
+A key abstraction in this crate is the combination of the
+[`Handle`](struct.Handle.html)
+and
+[`HandleRef`](struct.HandleRef.html)
+types. Both represent a valid Windows handle to an I/O-like object, where
+`Handle` is owned (the resource is closed when the handle is dropped) and
+`HandleRef` is borrowed (the resource is not closed when the handle is
+dropped). Many of the routines in this crate work on handles and accept
+anything that can be safely converted into a `HandleRef`. This includes
+standard library types such as `File`, `Stdin`, `Stdout` and `Stderr`.
+
+Note that this crate is completely empty on non-Windows platforms.
+*/
+
+#[cfg(windows)]
+pub use win::*;
+
+/// Safe routines for dealing with the Windows console.
+#[cfg(windows)]
+pub mod console;
+/// Safe routines for dealing with files and handles on Windows.
+#[cfg(windows)]
+pub mod file;
+#[cfg(windows)]
+mod win;
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()) }
+ }
+}