1use std::{marker::PhantomData, mem, ops::Deref, os::raw::c_void};
5
6use derive_more::From;
7use windows::{
8 Win32::{
9 System::Com::{CLSCTX_ALL, CoCreateInstance, CoTaskMemFree},
10 UI::Shell::{Common::ITEMIDLIST, IPersistIDList, IShellItem, SHGetIDListFromObject},
11 },
12 core::{IUnknown, Interface, Param, Result},
13};
14
15use super::item::ShellItem;
16
17#[derive(Debug, Clone, From)]
18pub struct ChildID(pub *mut ITEMIDLIST);
19
20impl From<RelativeIDList> for ChildID {
21 fn from(value: RelativeIDList) -> Self {
22 let id = Self(value.0);
23 mem::forget(value);
24 id
25 }
26}
27
28impl ChildID {
29 pub fn to_ref(&self) -> ChildIDRef<'_> {
30 self.into()
31 }
32}
33
34impl Drop for ChildID {
35 fn drop(&mut self) {
36 unsafe { CoTaskMemFree(Some(self.0.cast())) }
37 }
38}
39
40#[derive(Debug, Clone, Copy)]
45pub struct ChildIDRef<'a>(pub *const ITEMIDLIST, PhantomData<&'a ()>);
46
47impl<'a> ChildIDRef<'a> {
48 pub unsafe fn from_raw(ptr: *const ITEMIDLIST) -> Self {
50 Self(ptr, PhantomData)
51 }
52}
53
54impl<'a> From<&'a ChildID> for ChildIDRef<'a> {
55 fn from(id: &'a ChildID) -> Self {
56 Self(id.0, PhantomData)
57 }
58}
59
60impl<'a> Deref for ChildIDRef<'a> {
61 type Target = ChildID;
62
63 fn deref(&self) -> &Self::Target {
64 unsafe { mem::transmute(self) }
65 }
66}
67
68#[derive(Debug, Clone, From)]
69pub struct RelativeIDList(pub *mut ITEMIDLIST);
70
71impl Drop for RelativeIDList {
72 fn drop(&mut self) {
73 unsafe { CoTaskMemFree(Some(self.0.cast())) }
74 }
75}
76
77#[derive(Debug, Clone, Copy)]
82pub struct RelativeIDListRef<'a>(pub *const ITEMIDLIST, PhantomData<&'a ()>);
83
84impl<'a> RelativeIDListRef<'a> {
85 pub unsafe fn from_raw(ptr: *const ITEMIDLIST) -> Self {
87 Self(ptr, PhantomData)
88 }
89}
90
91impl<'a> From<&'a RelativeIDList> for RelativeIDListRef<'a> {
92 fn from(id: &'a RelativeIDList) -> Self {
93 Self(id.0, PhantomData)
94 }
95}
96
97impl<'a> Deref for RelativeIDListRef<'a> {
98 type Target = RelativeIDList;
99
100 fn deref(&self) -> &Self::Target {
101 unsafe { mem::transmute(self) }
102 }
103}
104
105impl RelativeIDList {
106 pub fn into_child(self) -> ChildID {
112 self.into()
113 }
114
115 pub fn to_child_ref(&self) -> ChildIDRef<'_> {
120 ChildIDRef(self.0, PhantomData)
121 }
122}
123
124#[derive(Debug, Clone, From)]
125pub struct AbsoluteIDList(pub *mut ITEMIDLIST);
126
127impl AbsoluteIDList {
128 pub fn from_raw_void_ref<'a>(pidl: &'a *mut c_void) -> &'a Self {
129 unsafe { mem::transmute(pidl) }
130 }
131
132 pub fn from_object(unk: impl Param<IUnknown>) -> Result<Self> {
137 unsafe { SHGetIDListFromObject(unk) }.map(AbsoluteIDList)
138 }
139}
140
141impl Drop for AbsoluteIDList {
142 fn drop(&mut self) {
143 unsafe { CoTaskMemFree(Some(self.0.cast())) }
144 }
145}
146
147#[derive(Debug, Clone, Copy)]
152pub struct AbsoluteIDListRef<'a>(pub *const ITEMIDLIST, PhantomData<&'a ()>);
153
154impl<'a> AbsoluteIDListRef<'a> {
155 pub unsafe fn from_raw(ptr: *const ITEMIDLIST) -> Self {
157 Self(ptr, PhantomData)
158 }
159}
160
161impl<'a> From<&'a AbsoluteIDList> for AbsoluteIDListRef<'a> {
162 fn from(id: &'a AbsoluteIDList) -> Self {
163 Self(id.0, PhantomData)
164 }
165}
166
167impl<'a> Deref for AbsoluteIDListRef<'a> {
168 type Target = AbsoluteIDList;
169
170 fn deref(&self) -> &Self::Target {
171 unsafe { mem::transmute(self) }
172 }
173}
174
175pub trait PersistIDList {
177 fn new() -> Result<IPersistIDList>;
178
179 fn get_id_list(&self) -> Result<AbsoluteIDList>;
184
185 fn to_shell_item(&self) -> Result<IShellItem>;
186}
187
188impl PersistIDList for IPersistIDList {
189 fn new() -> Result<IPersistIDList> {
190 unsafe { CoCreateInstance(&IPersistIDList::IID, None, CLSCTX_ALL) }
191 }
192
193 fn get_id_list(&self) -> Result<AbsoluteIDList> {
194 unsafe { self.GetIDList() }.map(AbsoluteIDList)
195 }
196
197 fn to_shell_item(&self) -> Result<IShellItem> {
198 let id_list = self.get_id_list()?;
199 let item = IShellItem::from_id_list(&id_list)?;
200 Ok(item)
202 }
203}