use windows::{
Win32::{
Foundation::PROPERTYKEY,
Storage::EnhancedStorage::{
PKEY_ItemPathDisplay, PKEY_ParsingName, PKEY_ParsingPath, PKEY_Size,
},
System::Com::StructuredStorage::PROPVARIANT,
UI::Shell::{IShellItem2, PropertiesSystem::GETPROPERTYSTOREFLAGS},
},
core::{PCWSTR, Result},
};
pub use windows::Win32::UI::Shell::PropertiesSystem::IPropertyStore;
use crate::item2::ShellItem2;
pub trait PropertyStore {
fn from_path_w(path: PCWSTR, flags: GETPROPERTYSTOREFLAGS) -> Result<IPropertyStore>;
fn get_value(&self, key: &PROPERTYKEY) -> Result<PROPVARIANT>;
fn get_size(&self) -> Result<PROPVARIANT>;
fn get_size_u64(&self) -> Result<u64>;
fn get_parsing_path(&self) -> Result<PROPVARIANT>;
fn get_parsing_name(&self) -> Result<PROPVARIANT>;
fn get_item_path_display(&self) -> Result<PROPVARIANT>;
}
impl PropertyStore for IPropertyStore {
fn from_path_w(path: PCWSTR, flags: GETPROPERTYSTOREFLAGS) -> Result<IPropertyStore> {
IShellItem2::from_path_w(path)?.get_property_store(flags)
}
fn get_value(&self, key: &PROPERTYKEY) -> Result<PROPVARIANT> {
unsafe { self.GetValue(key) }
}
fn get_size(&self) -> Result<PROPVARIANT> {
self.get_value(&PKEY_Size)
}
fn get_size_u64(&self) -> Result<u64> {
(&self.get_size()?).try_into()
}
fn get_parsing_path(&self) -> Result<PROPVARIANT> {
self.get_value(&PKEY_ParsingPath)
}
fn get_parsing_name(&self) -> Result<PROPVARIANT> {
self.get_value(&PKEY_ParsingName)
}
fn get_item_path_display(&self) -> Result<PROPVARIANT> {
self.get_value(&PKEY_ItemPathDisplay)
}
}
#[cfg(test)]
mod tests {
use std::assert_matches;
use windows::{
Win32::Storage::EnhancedStorage::{
PKEY_ImageParsingName, PKEY_ItemUrl, PKEY_Link_TargetParsingPath,
},
core::w,
};
use super::*;
use crate::{id_list::AbsoluteIDList, init};
#[test]
fn get_value() {
_ = init();
let prop_store =
IPropertyStore::from_path_w(w!(r"C:\Windows\explorer.exe"), Default::default())
.expect("Failed to create property store from path");
let size: u64 = prop_store.get_size_u64().unwrap();
dbg!(size);
assert!(size > 0);
let name = prop_store.get_parsing_name().unwrap().to_string();
assert_eq!(name, "explorer.exe");
let name = prop_store
.get_value(&PKEY_ImageParsingName)
.unwrap()
.to_string();
assert_eq!(name, "");
let path = prop_store.get_parsing_path().unwrap().to_string();
assert_eq!(path, r"C:\Windows\explorer.exe");
let path = prop_store.get_item_path_display().unwrap().to_string();
assert_eq!(path, r"C:\Windows\explorer.exe");
let url = prop_store.get_value(&PKEY_ItemUrl).unwrap().to_string();
assert_eq!(url, "");
let path = prop_store
.get_value(&PKEY_Link_TargetParsingPath)
.unwrap()
.to_string();
assert_eq!(path, "");
}
#[test]
fn get_parsing_path() {
_ = init();
let prop_store = IPropertyStore::from_path_w(
w!(r"C:\Users\Public\Documents\desktop.ini"),
Default::default(),
)
.unwrap();
let path = prop_store.get_parsing_path().unwrap().to_string();
assert_eq!(path, r"C:\Users\Public\Documents\desktop.ini");
let path = prop_store.get_item_path_display().unwrap().to_string();
assert_eq!(path, r"C:\Users\Public\Public Documents\desktop.ini");
assert_matches!(AbsoluteIDList::from_object(&prop_store), Err(_));
}
}