Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

407
vendor/winapi-util/src/console.rs vendored Normal file
View File

@@ -0,0 +1,407 @@
use std::{io, mem};
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Console::{GetConsoleMode, SetConsoleMode};
use windows_sys::Win32::System::Console::{
GetConsoleScreenBufferInfo, SetConsoleTextAttribute,
CONSOLE_SCREEN_BUFFER_INFO, ENABLE_VIRTUAL_TERMINAL_PROCESSING,
FOREGROUND_BLUE, FOREGROUND_GREEN, FOREGROUND_INTENSITY, FOREGROUND_RED,
};
use crate::{AsHandleRef, HandleRef};
use FOREGROUND_BLUE as FG_BLUE;
use FOREGROUND_GREEN as FG_GREEN;
use FOREGROUND_INTENSITY as FG_INTENSITY;
use FOREGROUND_RED as FG_RED;
const FG_CYAN: u16 = FG_BLUE | FG_GREEN;
const FG_MAGENTA: u16 = FG_BLUE | FG_RED;
const FG_YELLOW: u16 = FG_GREEN | FG_RED;
const FG_WHITE: u16 = 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() as HANDLE, &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() as HANDLE, 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() as HANDLE, &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() as HANDLE, 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, 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 = 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) -> u16 {
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: u16) -> 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) -> u16 {
self.to_fg() << 4
}
fn from_bg(word: u16) -> Intense {
Intense::from_fg(word >> 4)
}
fn to_fg(&self) -> u16 {
match *self {
Intense::No => 0,
Intense::Yes => FG_INTENSITY,
}
}
fn from_fg(word: u16) -> 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) -> u16 {
self.to_fg() << 4
}
fn from_bg(word: u16) -> Color {
Color::from_fg(word >> 4)
}
fn to_fg(&self) -> u16 {
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: u16) -> 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,
}
}
}

166
vendor/winapi-util/src/file.rs vendored Normal file
View File

@@ -0,0 +1,166 @@
use std::{io, mem};
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::Foundation::{GetLastError, FILETIME, NO_ERROR};
use windows_sys::Win32::Storage::FileSystem::{
GetFileInformationByHandle, GetFileType, BY_HANDLE_FILE_INFORMATION,
FILE_ATTRIBUTE_HIDDEN,
};
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() as HANDLE, &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() as HANDLE);
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 & (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 == ::windows_sys::Win32::Storage::FileSystem::FILE_TYPE_CHAR
}
/// Returns true if this type represents a disk file.
pub fn is_disk(&self) -> bool {
self.0 == ::windows_sys::Win32::Storage::FileSystem::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 == ::windows_sys::Win32::Storage::FileSystem::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 == ::windows_sys::Win32::Storage::FileSystem::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)
}
}

35
vendor/winapi-util/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,35 @@
/*!
This crate provides a smattering of safe routines for parts of windows-sys. The
primary purpose of this crate is to serve as a dumping ground for various
utility functions that make interactions with windows-sys 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)]
/// Safe routines for querying various Windows specific properties.
pub mod sysinfo;
#[cfg(windows)]
mod win;

161
vendor/winapi-util/src/sysinfo.rs vendored Normal file
View File

@@ -0,0 +1,161 @@
use std::{ffi::OsString, io};
use windows_sys::Win32::System::SystemInformation::{
GetComputerNameExW, COMPUTER_NAME_FORMAT,
};
/// The type of name to be retrieved by [`get_computer_name`].
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub enum ComputerNameKind {
/// The name of the DNS domain assigned to the local computer. If the local
/// computer is a node in a cluster, lpBuffer receives the DNS domain name
/// of the cluster virtual server.
DnsDomain,
/// The fully qualified DNS name that uniquely identifies the local
/// computer. This name is a combination of the DNS host name and the DNS
/// domain name, using the form HostName.DomainName. If the local computer
/// is a node in a cluster, lpBuffer receives the fully qualified DNS name
/// of the cluster virtual server.
DnsFullyQualified,
/// The DNS host name of the local computer. If the local computer is a
/// node in a cluster, lpBuffer receives the DNS host name of the cluster
/// virtual server.
DnsHostname,
/// The NetBIOS name of the local computer. If the local computer is a node
/// in a cluster, lpBuffer receives the NetBIOS name of the cluster virtual
/// server.
NetBios,
/// The name of the DNS domain assigned to the local computer. If the local
/// computer is a node in a cluster, lpBuffer receives the DNS domain name
/// of the local computer, not the name of the cluster virtual server.
PhysicalDnsDomain,
/// The fully qualified DNS name that uniquely identifies the computer. If
/// the local computer is a node in a cluster, lpBuffer receives the fully
/// qualified DNS name of the local computer, not the name of the cluster
/// virtual server.
///
/// The fully qualified DNS name is a combination of the DNS host name and
/// the DNS domain name, using the form HostName.DomainName.
PhysicalDnsFullyQualified,
/// The DNS host name of the local computer. If the local computer is a
/// node in a cluster, lpBuffer receives the DNS host name of the local
/// computer, not the name of the cluster virtual server.
PhysicalDnsHostname,
/// The NetBIOS name of the local computer. If the local computer is a node
/// in a cluster, lpBuffer receives the NetBIOS name of the local computer,
/// not the name of the cluster virtual server.
PhysicalNetBios,
}
impl ComputerNameKind {
fn to_format(&self) -> COMPUTER_NAME_FORMAT {
use self::ComputerNameKind::*;
use windows_sys::Win32::System::SystemInformation;
match *self {
DnsDomain => SystemInformation::ComputerNameDnsDomain,
DnsFullyQualified => {
SystemInformation::ComputerNameDnsFullyQualified
}
DnsHostname => SystemInformation::ComputerNameDnsHostname,
NetBios => SystemInformation::ComputerNameNetBIOS,
PhysicalDnsDomain => {
SystemInformation::ComputerNamePhysicalDnsDomain
}
PhysicalDnsFullyQualified => {
SystemInformation::ComputerNamePhysicalDnsFullyQualified
}
PhysicalDnsHostname => {
SystemInformation::ComputerNamePhysicalDnsHostname
}
PhysicalNetBios => SystemInformation::ComputerNamePhysicalNetBIOS,
}
}
}
/// Retrieves a NetBIOS or DNS name associated with the local computer.
///
/// The names are established at system startup, when the system reads them
/// from the registry.
///
/// This corresponds to calling [`GetComputerNameExW`].
///
/// [`GetComputerNameExW`]: https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getcomputernameexw
pub fn get_computer_name(kind: ComputerNameKind) -> io::Result<OsString> {
use std::os::windows::ffi::OsStringExt;
let format = kind.to_format();
let mut len1 = 0;
// SAFETY: As documented, we call this with a null pointer which will in
// turn cause this routine to write the required buffer size fo `len1`.
// Also, we explicitly ignore the return value since we expect this call to
// fail given that the destination buffer is too small by design.
let _ =
unsafe { GetComputerNameExW(format, std::ptr::null_mut(), &mut len1) };
let len = match usize::try_from(len1) {
Ok(len) => len,
Err(_) => {
return Err(io::Error::new(
io::ErrorKind::Other,
"GetComputerNameExW buffer length overflowed usize",
))
}
};
let mut buf = vec![0; len];
let mut len2 = len1;
// SAFETY: We pass a valid pointer to an appropriately sized Vec<u16>.
let rc =
unsafe { GetComputerNameExW(format, buf.as_mut_ptr(), &mut len2) };
if rc == 0 {
return Err(io::Error::last_os_error());
}
// Apparently, the subsequent call writes the number of characters written
// to the buffer to `len2` but not including the NUL terminator. Notice
// that in the first call above, the length written to `len1` *does*
// include the NUL terminator. Therefore, we expect `len1` to be at least
// one greater than `len2`. If not, then something weird has happened and
// we report an error.
if len1 <= len2 {
let msg = format!(
"GetComputerNameExW buffer length mismatch, \
expected length strictly less than {} \
but got {}",
len1, len2,
);
return Err(io::Error::new(io::ErrorKind::Other, msg));
}
let len = usize::try_from(len2).expect("len1 fits implies len2 fits");
Ok(OsString::from_wide(&buf[..len]))
}
#[cfg(test)]
mod tests {
use super::*;
// This test doesn't really check anything other than that we can
// successfully query all kinds of computer names. We just print them out
// since there aren't really any properties about the names that we can
// assert.
//
// We specifically run this test in CI with --nocapture so that we can see
// the output.
#[test]
fn itworks() {
let kinds = [
ComputerNameKind::DnsDomain,
ComputerNameKind::DnsFullyQualified,
ComputerNameKind::DnsHostname,
ComputerNameKind::NetBios,
ComputerNameKind::PhysicalDnsDomain,
ComputerNameKind::PhysicalDnsFullyQualified,
ComputerNameKind::PhysicalDnsHostname,
ComputerNameKind::PhysicalNetBios,
];
for kind in kinds {
let result = get_computer_name(kind);
let name = result.unwrap();
println!("{kind:?}: {name:?}");
}
}
}

246
vendor/winapi-util/src/win.rs vendored Normal file
View File

@@ -0,0 +1,246 @@
use std::{
fs::File,
io,
os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle},
path::Path,
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 windows_sys::Win32::Storage::FileSystem::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()) }
}
}