use std::mem::MaybeUninit;
use windows_sys::Win32::Storage::FileSystem::{FILE_BASIC_INFO, GetFileInformationByHandleEx};
use win_shared_os_owned_handle::SharedHandle;
use crate::handle::SharedRaw;
use crate::outcome::{Outcome, perform_bool};
use crate::query::FileInformationClass;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct FileBasicInfo {
creation_time: i64,
last_access_time: i64,
last_write_time: i64,
change_time: i64,
file_attributes: u32,
}
impl FileBasicInfo {
#[must_use]
pub const fn new(
creation_time: i64,
last_access_time: i64,
last_write_time: i64,
change_time: i64,
file_attributes: u32,
) -> Self {
Self {
creation_time,
last_access_time,
last_write_time,
change_time,
file_attributes,
}
}
#[must_use]
pub const fn creation_time(&self) -> i64 {
self.creation_time
}
#[must_use]
pub const fn last_access_time(&self) -> i64 {
self.last_access_time
}
#[must_use]
pub const fn last_write_time(&self) -> i64 {
self.last_write_time
}
#[must_use]
pub const fn change_time(&self) -> i64 {
self.change_time
}
#[must_use]
pub const fn file_attributes(&self) -> u32 {
self.file_attributes
}
}
fn from_raw(info: &FILE_BASIC_INFO) -> FileBasicInfo {
FileBasicInfo::new(
info.CreationTime,
info.LastAccessTime,
info.LastWriteTime,
info.ChangeTime,
info.FileAttributes,
)
}
#[derive(Clone, Debug)]
#[must_use = "an unperformed request queries nothing"]
pub struct QueryFileBasicInfo {
handle: SharedHandle,
}
impl QueryFileBasicInfo {
pub fn new(handle: impl Into<SharedHandle>) -> Self {
Self {
handle: handle.into(),
}
}
pub fn handle(&self) -> &SharedHandle {
&self.handle
}
pub fn perform(&self) -> Outcome<FileBasicInfo> {
let mut information = MaybeUninit::<FILE_BASIC_INFO>::uninit();
let size = u32::try_from(size_of::<FILE_BASIC_INFO>())
.expect("this fixed, small struct's size always fits a u32");
perform_bool(|| {
unsafe {
GetFileInformationByHandleEx(
self.handle.raw(),
FileInformationClass::BASIC.as_raw(),
information.as_mut_ptr().cast(),
size,
)
}
})?;
Ok(from_raw(unsafe { information.assume_init_ref() }))
}
}
impl crate::request::Request for QueryFileBasicInfo {
type Error = crate::Win32Error;
type Output = FileBasicInfo;
fn perform(&self) -> Outcome<FileBasicInfo> {
Self::perform(self)
}
}
#[cfg(test)]
mod tests;