Skip to main content

ib_shell_item/
item.rs

1use widestring::U16CString;
2use windows::{
3    Win32::{
4        System::Com::CoTaskMemFree,
5        UI::Shell::{
6            Common::ITEMIDLIST, SHCreateItemFromIDList, SIGDN, SIGDN_DESKTOPABSOLUTEEDITING,
7            SIGDN_DESKTOPABSOLUTEPARSING, SIGDN_FILESYSPATH, SIGDN_NORMALDISPLAY,
8            SIGDN_PARENTRELATIVE, SIGDN_PARENTRELATIVEEDITING, SIGDN_PARENTRELATIVEFORADDRESSBAR,
9            SIGDN_PARENTRELATIVEFORUI, SIGDN_PARENTRELATIVEPARSING, SIGDN_URL,
10        },
11    },
12    core::Result,
13};
14
15pub use windows::Win32::UI::Shell::IShellItem;
16
17/// Requests the form of an item's display name to retrieve through [`IShellItem::GetDisplayName`] and [`SHGetNameFromIDList`].
18///
19/// [SIGDN (shobjidl_core.h) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/ne-shobjidl_core-sigdn)
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21#[repr(i32)]
22pub enum ShellItemDisplayName {
23    /// 0x00000000. Returns the display name relative to the parent folder.
24    ///
25    /// In UI this name is generally ideal for display to the user.
26    NormalDisplay = SIGDN_NORMALDISPLAY.0,
27
28    /// 0x80018001. Returns the parsing name relative to the parent folder.
29    ///
30    /// This name is not suitable for use in UI.
31    ParentRelativeParsing = SIGDN_PARENTRELATIVEPARSING.0,
32
33    /// 0x80028000. Returns the parsing name relative to the desktop.
34    ///
35    /// This name is not suitable for use in UI.
36    DesktopAbsoluteParsing = SIGDN_DESKTOPABSOLUTEPARSING.0,
37
38    /// 0x80031001. Returns the editing name relative to the parent folder.
39    ///
40    /// In UI this name is suitable for display to the user.
41    ParentRelativeEditing = SIGDN_PARENTRELATIVEEDITING.0,
42
43    /// 0x8004c000. Returns the editing name relative to the desktop.
44    ///
45    /// In UI this name is suitable for display to the user.
46    DesktopAbsoluteEditing = SIGDN_DESKTOPABSOLUTEEDITING.0,
47
48    /// 0x80058000. Returns the item's file system path, if it has one.
49    ///
50    /// Only items that report [`SFGAO_FILESYSTEM`] have a file system path. When an item does not have a file system path, a call to [`IShellItem::GetDisplayName`] on that item will fail.
51    ///
52    /// In UI this name is suitable for display to the user in some cases, but note that it might not be specified for all items.
53    ///
54    /// e.g. `C:\Users\Ib`
55    FileSystemPath = SIGDN_FILESYSPATH.0,
56
57    /// 0x80068000. Returns the item's URL, if it has one.
58    ///
59    /// Some items do not have a URL, and in those cases a call to [`IShellItem::GetDisplayName`] will fail.
60    ///
61    /// This name is suitable for display to the user in some cases, but note that it might not be specified for all items.
62    Url = SIGDN_URL.0,
63
64    /// 0x8007c001. Returns the path relative to the parent folder in a friendly format as displayed in an address bar.
65    ///
66    /// This name is suitable for display to the user.
67    ParentRelativeForAddressBar = SIGDN_PARENTRELATIVEFORADDRESSBAR.0,
68
69    /// 0x80080001. Returns the path relative to the parent folder.
70    ParentRelative = SIGDN_PARENTRELATIVE.0,
71
72    /// 0x80094001. Introduced in Windows 8. Returns the path relative to the parent folder for UI purposes.
73    ParentRelativeForUI = SIGDN_PARENTRELATIVEFORUI.0,
74}
75
76/// [IShellItem (shobjidl_core.h) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ishellitem)
77pub trait ShellItem {
78    #[doc(alias = "from_pidl")]
79    fn from_id_list(id_list: *const ITEMIDLIST) -> Result<IShellItem>;
80
81    /// [IShellItem::GetDisplayName (shobjidl_core.h) - Win32 apps | Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitem-getdisplayname)
82    fn get_display_name(&self, name: ShellItemDisplayName) -> Result<U16CString>;
83}
84
85impl ShellItem for IShellItem {
86    /// Ref: https://github.com/Hau-Hau/restart-explorer/blob/230ed6dd78ac656a86e07310c3afc62f03057a36/src/infrastructure/windows_os/persist_id_list.rs
87    fn from_id_list(id_list: *const ITEMIDLIST) -> Result<IShellItem> {
88        unsafe { SHCreateItemFromIDList::<IShellItem>(id_list) }
89    }
90
91    /// Ref: https://github.com/Hau-Hau/restart-explorer/blob/230ed6dd78ac656a86e07310c3afc62f03057a36/src/infrastructure/windows_os/shell_item.rs
92    fn get_display_name(&self, name: ShellItemDisplayName) -> Result<U16CString> {
93        let name = unsafe { self.GetDisplayName(SIGDN(name as i32)) }?;
94        let name_u16 = unsafe { U16CString::from_ptr_str(name.0) };
95        unsafe { CoTaskMemFree(Some(name.0 as _)) };
96        Ok(name_u16)
97    }
98}