ib_shell_item/prop/
system.rs1use std::ptr;
2
3use widestring::U16CStr;
4use windows::{
5 Win32::{
6 Foundation::PROPERTYKEY,
7 System::Com::StructuredStorage::PROPVARIANT,
8 UI::Shell::PropertiesSystem::{PROPDESC_FORMAT_FLAGS, PSGetPropertySystem},
9 },
10 core::{Interface, PWSTR, Result},
11};
12
13pub use windows::Win32::UI::Shell::PropertiesSystem::IPropertySystem;
14
15use crate::init;
16
17pub trait PropertySystem {
21 fn new_init() -> Result<IPropertySystem>;
23
24 fn new() -> Result<IPropertySystem>;
26
27 fn format_for_display<'b>(
37 &self,
38 key: &PROPERTYKEY,
39 propvar: &PROPVARIANT,
40 pdff: PROPDESC_FORMAT_FLAGS,
41 buffer: &'b mut [u16],
42 ) -> Result<&'b mut U16CStr>;
43
44 fn format_for_display_alloc(
65 &self,
66 key: &PROPERTYKEY,
67 propvar: &PROPVARIANT,
68 pdff: PROPDESC_FORMAT_FLAGS,
69 ) -> Result<PWSTR>;
70}
71
72impl PropertySystem for IPropertySystem {
73 fn new_init() -> Result<IPropertySystem> {
74 _ = init();
75 Self::new()
76 }
77
78 fn new() -> Result<IPropertySystem> {
79 let mut pv = ptr::null_mut();
80 unsafe { PSGetPropertySystem(&IPropertySystem::IID, &mut pv)? };
81 Ok(unsafe { IPropertySystem::from_raw(pv) })
82 }
83
84 fn format_for_display<'b>(
85 &self,
86 key: &PROPERTYKEY,
87 propvar: &PROPVARIANT,
88 pdff: PROPDESC_FORMAT_FLAGS,
89 buffer: &'b mut [u16],
90 ) -> Result<&'b mut U16CStr> {
91 unsafe { self.FormatForDisplay(key, propvar, pdff, buffer) }?;
92 Ok(U16CStr::from_slice_truncate_mut(buffer).unwrap())
93 }
94
95 fn format_for_display_alloc(
96 &self,
97 key: &PROPERTYKEY,
98 propvar: &PROPVARIANT,
99 pdff: PROPDESC_FORMAT_FLAGS,
100 ) -> Result<PWSTR> {
101 unsafe { self.FormatForDisplayAlloc(key, propvar, pdff) }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 use windows::Win32::Storage::EnhancedStorage::PKEY_Size;
110
111 #[test]
112 fn format_for_display() {
113 let prop_system = IPropertySystem::new_init().expect("Failed to create IPropertySystem");
114 let key = PKEY_Size;
115 let propvar = PROPVARIANT::from(1024_i64);
116 let pdff = PROPDESC_FORMAT_FLAGS::default();
117
118 let mut buffer: [u16; 256] = [0; 256];
120
121 let display_value = prop_system
122 .format_for_display(&key, &propvar, pdff, &mut buffer)
123 .expect("Failed to format for display");
124 assert_eq!(display_value, widestring::u16cstr!("1.00 KB"));
125 }
126
127 #[test]
128 fn format_for_display_alloc_with_pkey_size() {
129 let prop_system = IPropertySystem::new_init().expect("Failed to create IPropertySystem");
130
131 let key = PKEY_Size;
133
134 let propvar = PROPVARIANT::from(1024_i64);
136
137 let pdff = PROPDESC_FORMAT_FLAGS::default();
139
140 let result = prop_system
141 .format_for_display_alloc(&key, &propvar, pdff)
142 .expect("Failed to format for display");
143
144 let display_value: String =
146 unsafe { result.to_string() }.expect("Failed to convert PWSTR to String");
147
148 assert!(!display_value.is_empty());
150 eprintln!("Formatted size value: {display_value}");
154
155 assert_eq!(display_value, "1.00 KB");
157 }
158
159 #[test]
160 fn format_for_display_alloc_with_various_sizes() {
161 let prop_system = IPropertySystem::new_init().expect("Failed to create IPropertySystem");
162
163 let key = PKEY_Size;
164
165 let test_cases = [
166 (1024_i64, "1.00 KB"),
167 (1024 * 1024, "1.00 MB"),
168 (1024 * 1024 * 1024, "1.00 GB"),
169 ];
170
171 for (size, expected) in test_cases {
172 let propvar = PROPVARIANT::from(size);
173 let result = prop_system
174 .format_for_display_alloc(&key, &propvar, PROPDESC_FORMAT_FLAGS::default())
175 .expect("Failed to format for display");
176
177 let display_value: String =
178 unsafe { result.to_string() }.expect("Failed to convert PWSTR");
179 assert_eq!(
180 display_value, expected,
181 "Size {size} should format to '{expected}'"
182 );
183 }
184 }
185}