Skip to content

Commit

Permalink
Merge pull request #18 from niklasmohrin/replace-winapi
Browse files Browse the repository at this point in the history
Migrate from `winapi` to official `windows` crate
  • Loading branch information
niklasmohrin authored Oct 24, 2024
2 parents 77d0604 + b26c182 commit 8a9ed67
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 38 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: obi1kenobi/cargo-semver-checks-action@v2
with:
verbose: true

rustfmt:
name: Check formatting
Expand Down
12 changes: 5 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "clircle"
version = "0.6.0"
version = "0.6.1"
authors = ["Niklas Mohrin <[email protected]>"]
license = "MIT OR Apache-2.0"
rust-version = "1.69"
Expand All @@ -24,12 +24,10 @@ serde_derive = { version = "1.0.117", optional = true }
cfg-if = "1.0.0"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["winnt", "winbase", "processenv", "handleapi", "ntdef", "fileapi", "std"] }
windows = { version = "0.56.0", features = ["Win32_Storage_FileSystem", "Win32_System_Console"] }

[dev-dependencies]
tempfile = "3.1.0"
tempfile = "3.4.0"

[target.'cfg(unix)'.dev-dependencies.nix]
version = "0.29"
default-features = false
features = ["term"]
[target.'cfg(unix)'.dev-dependencies]
nix = { version = "0.29", default-features = false, features = ["term"] }
58 changes: 27 additions & 31 deletions src/clircle_windows.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
use crate::{Clircle, Stdio};

use winapi::shared::ntdef::NULL;
use winapi::um::{
fileapi::{GetFileInformationByHandle, GetFileType, BY_HANDLE_FILE_INFORMATION},
handleapi::INVALID_HANDLE_VALUE,
processenv::GetStdHandle,
winbase::{FILE_TYPE_DISK, STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE},
use windows::Win32::{
Foundation::{CloseHandle, HANDLE, INVALID_HANDLE_VALUE},
Storage::FileSystem::{
GetFileInformationByHandle, GetFileType, BY_HANDLE_FILE_INFORMATION, FILE_TYPE_DISK,
},
System::Console::{GetStdHandle, STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE},
};

use std::convert::TryFrom;
use std::fs::File;
use std::mem::MaybeUninit;
use std::os::windows::io::{FromRawHandle, IntoRawHandle, RawHandle};
use std::os::windows::io::{FromRawHandle, IntoRawHandle};
use std::{cmp, hash, io, mem, ops};

/// Implementation of `Clircle` for Windows.
#[derive(Debug)]
pub(crate) struct Identifier {
volume_serial: u32,
file_index: u64,
handle: RawHandle,
handle: HANDLE,
owns_handle: bool,
}

impl Identifier {
unsafe fn try_from_raw_handle(handle: RawHandle, owns_handle: bool) -> Result<Self, io::Error> {
if handle == INVALID_HANDLE_VALUE || handle == NULL {
unsafe fn try_from_raw_handle(handle: HANDLE, owns_handle: bool) -> Result<Self, io::Error> {
if handle.is_invalid() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Tried to convert handle to Identifier that was invalid or null.",
Expand All @@ -42,24 +42,20 @@ impl Identifier {
let mut fi = MaybeUninit::<BY_HANDLE_FILE_INFORMATION>::uninit();
// SAFETY: This function is safe to call, if the handle is valid and a handle to a file.
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle
let success = GetFileInformationByHandle(handle, fi.as_mut_ptr());
if success == 0 {
Err(io::Error::last_os_error())
} else {
// SAFETY: If the return value of GetFileInformationByHandle is non-zero, the struct
// has successfully been initialized (see link above).
let fi = fi.assume_init();

Ok(Self {
volume_serial: fi.dwVolumeSerialNumber,
file_index: u64::from(fi.nFileIndexHigh) << 32 | u64::from(fi.nFileIndexLow),
handle,
owns_handle,
})
}
GetFileInformationByHandle(handle, fi.as_mut_ptr())?;

// SAFETY: GetFileInformationByHandle returned successfully.
let fi = fi.assume_init();

Ok(Self {
volume_serial: fi.dwVolumeSerialNumber,
file_index: u64::from(fi.nFileIndexHigh) << 32 | u64::from(fi.nFileIndexLow),
handle,
owns_handle,
})
}

unsafe fn take_handle(&mut self) -> Option<RawHandle> {
unsafe fn take_handle(&mut self) -> Option<HANDLE> {
if self.owns_handle {
self.owns_handle = false;
Some(mem::replace(&mut self.handle, INVALID_HANDLE_VALUE))
Expand All @@ -72,7 +68,7 @@ impl Identifier {
impl Clircle for Identifier {
#[must_use]
fn into_inner(mut self) -> Option<File> {
Some(unsafe { File::from_raw_handle(self.take_handle()?) })
Some(unsafe { File::from_raw_handle(self.take_handle()?.0 as _) })
}
}

Expand All @@ -88,8 +84,8 @@ impl TryFrom<Stdio> for Identifier {

// SAFETY: This method can safely be called with one of the above constants.
// https://docs.microsoft.com/en-us/windows/console/getstdhandle
let handle = unsafe { GetStdHandle(std_handle_id) };
if handle == INVALID_HANDLE_VALUE || handle == NULL {
let handle = unsafe { GetStdHandle(std_handle_id) }?;
if handle.is_invalid() {
return Err(io::Error::last_os_error());
}

Expand All @@ -100,15 +96,15 @@ impl TryFrom<File> for Identifier {
type Error = io::Error;

fn try_from(file: File) -> Result<Self, Self::Error> {
unsafe { Self::try_from_raw_handle(file.into_raw_handle(), true) }
unsafe { Self::try_from_raw_handle(HANDLE(file.into_raw_handle() as _), true) }
}
}

impl ops::Drop for Identifier {
fn drop(&mut self) {
unsafe {
if let Some(handle) = self.take_handle() {
drop(File::from_raw_handle(handle));
let _ = CloseHandle(handle);
}
}
}
Expand Down

0 comments on commit 8a9ed67

Please sign in to comment.