From 1a1f75e59b4c18abdf6bc8790a4e54b53dff50df Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 6 Jan 2024 20:15:26 -0700 Subject: [PATCH] Windows implementation --- Cargo.toml | 4 +++- src/windows.rs | 46 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 783f46e..7e1598c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,9 @@ once_cell = "1.7.2" [target.'cfg(windows)'.dependencies] windows = { version = "0.44.0", features = [ "Win32_Foundation", + "Win32_Storage_EnhancedStorage", "Win32_System_Com_StructuredStorage", + "Win32_System_SystemServices", "Win32_UI_Shell_PropertiesSystem", ] } scopeguard = "1.2.0" @@ -61,4 +63,4 @@ pre-build = [ "cp /tmp/netbsd/usr/lib/libexecinfo.so /usr/local/x86_64-unknown-netbsd/lib", "rm base.tar.xz", "rm -rf /tmp/netbsd", -] \ No newline at end of file +] diff --git a/src/windows.rs b/src/windows.rs index e617647..dd56749 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -1,4 +1,4 @@ -use crate::{Error, TrashContext, TrashItem}; +use crate::{Error, TrashContext, TrashItem, TrashItemMetadata}; use std::{ borrow::Borrow, ffi::{c_void, OsStr, OsString}, @@ -7,7 +7,10 @@ use std::{ path::PathBuf, }; use windows::core::{Interface, GUID, PCWSTR, PWSTR}; -use windows::Win32::{Foundation::*, System::Com::*, UI::Shell::PropertiesSystem::*, UI::Shell::*}; +use windows::Win32::{ + Foundation::*, Storage::EnhancedStorage::*, System::Com::*, System::SystemServices::*, + UI::Shell::PropertiesSystem::*, UI::Shell::*, +}; /////////////////////////////////////////////////////////////////////////// // These don't have bindings in windows-rs for some reason @@ -70,7 +73,7 @@ impl TrashContext { } } - /// Removes all files and folder paths recursively. + /// Removes all files and folder paths recursively. pub(crate) fn delete_all_canonicalized(&self, full_paths: Vec) -> Result<(), Error> { let mut collection = Vec::new(); traverse_paths_recursively(full_paths, &mut collection)?; @@ -124,6 +127,43 @@ pub fn list() -> Result, Error> { } } +pub fn metadata(item: &TrashItem) -> Result { + ensure_com_initialized(); + unsafe { + let id_as_wide: Vec = item.id.encode_wide().chain(std::iter::once(0)).collect(); + let parsing_name = PCWSTR(id_as_wide.as_ptr()); + let item: IShellItem = SHCreateItemFromParsingName(parsing_name, None)?; + let is_dir = item.GetAttributes(SFGAO_FOLDER)? == SFGAO_FOLDER; + let size = if is_dir { + let pesi: IEnumShellItems = item.BindToHandler(None, &BHID_EnumItems)?; + let mut size = 0; + loop { + let mut fetched_count: u32 = 0; + let mut arr = [None]; + pesi.Next(&mut arr, Some(&mut fetched_count as *mut u32))?; + + if fetched_count == 0 { + break; + } + + match &arr[0] { + Some(_item) => { + size += 1; + } + None => { + break; + } + } + } + size + } else { + let item2: IShellItem2 = item.cast()?; + item2.GetUInt64(&PKEY_Size)? + }; + Ok(TrashItemMetadata { is_dir, size }) + } +} + pub fn purge_all(items: I) -> Result<(), Error> where I: IntoIterator,