xref: /reactos/dll/shellext/cabview/util.h (revision cc3672cb)
1 /*
2  * PROJECT:     ReactOS CabView Shell Extension
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Utility header file
5  * COPYRIGHT:   Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
6  */
7 
8 #pragma once
9 
10 template<class H> static int ErrorBox(H hWnd, int Error)
11 {
12     SHELL_ErrorBox(hWnd, Error);
13     return Error;
14 }
15 
16 template<class T> static inline bool IsPathSep(T c)
17 {
18     return c == '\\' || c == '/';
19 }
20 
21 inline bool IsEqual(const SHCOLUMNID &scid, REFGUID guid, UINT pid)
22 {
23     return scid.pid == pid && IsEqualGUID(scid.fmtid, guid);
24 }
25 
26 inline HRESULT InitVariantFromBuffer(const void *buffer, UINT cb, VARIANT *pv)
27 {
28     SAFEARRAY *pa = SafeArrayCreateVector(VT_UI1, 0, cb);
29     if (pa)
30     {
31         CopyMemory(pa->pvData, buffer, cb);
32         V_VT(pv) = VT_UI1 | VT_ARRAY;
33         V_UNION(pv, parray) = pa;
34         return S_OK;
35     }
36     V_VT(pv) = VT_EMPTY;
37     return E_OUTOFMEMORY;
38 }
39 
40 inline void FreeStrRet(STRRET &str)
41 {
42     if (str.uType == STRRET_WSTR)
43     {
44         SHFree(str.pOleStr);
45         str.uType = STRRET_CSTR;
46     }
47 }
48 
49 inline HRESULT StrTo(LPCWSTR str, UINT len, STRRET &sr)
50 {
51     LPWSTR data = (LPWSTR)SHAlloc(++len * sizeof(WCHAR));
52     if (!data)
53         return E_OUTOFMEMORY;
54     lstrcpynW(data, str, len);
55     sr.uType = STRRET_WSTR;
56     sr.pOleStr = data;
57     return S_OK;
58 }
59 
60 inline HRESULT StrTo(LPCWSTR str, STRRET &sr)
61 {
62     return StrTo(str, lstrlenW(str), sr);
63 }
64 
65 inline HRESULT StrTo(LPCWSTR str, UINT len, VARIANT &v)
66 {
67     BSTR data = SysAllocStringLen(str, len);
68     if (!data)
69         return E_OUTOFMEMORY;
70     V_VT(&v) = VT_BSTR;
71     V_BSTR(&v) = data;
72     return S_OK;
73 }
74 
75 inline HRESULT StrTo(LPCWSTR str, VARIANT &v)
76 {
77     return StrTo(str, lstrlenW(str), v);
78 }
79 
80 inline HRESULT StrRetToVariantBSTR(STRRET *psr, VARIANT &v)
81 {
82     HRESULT hr = StrRetToBSTR(psr, NULL, &V_BSTR(&v));
83     if (SUCCEEDED(hr))
84         V_VT(&v) = VT_BSTR;
85     return hr;
86 }
87 
88 inline HRESULT GetDetailsOf(IShellFolder2 &Folder, PCUITEMID_CHILD pidl, UINT Column, PWSTR &String)
89 {
90     SHELLDETAILS details;
91     HRESULT hr = Folder.GetDetailsOf(pidl, Column, &details);
92     if (SUCCEEDED(hr))
93         hr = StrRetToStrW(&details.str, pidl, &String);
94     return hr;
95 }
96 
97 inline HRESULT InsertMenuItem(QCMINFO &qcmi, UINT &Pos, UINT &TrackId, UINT Id, UINT ResId, int State = 0)
98 {
99     UINT flags = 0;
100     WCHAR string[MAX_PATH];
101     string[0] = UNICODE_NULL;
102     if ((Id += qcmi.idCmdFirst) > qcmi.idCmdLast)
103         return E_FAIL;
104     else if (ResId == (UINT)-1)
105         flags |= MF_SEPARATOR;
106     else if (!LoadStringW(_AtlBaseModule.GetResourceInstance(), ResId, string, _countof(string)))
107         return E_FAIL;
108 
109     MENUITEMINFOW mii;
110     mii.cbSize = FIELD_OFFSET(MENUITEMINFOW, hbmpItem); // USER32 version agnostic
111     mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_STATE;
112     mii.fType = flags;
113     mii.wID = Id;
114     mii.dwTypeData = string;
115     mii.cch = 0;
116     mii.fState = State;
117     if (!InsertMenuItemW(qcmi.hmenu, Pos, TRUE, &mii))
118         return E_FAIL;
119     Pos++;
120     TrackId = max(TrackId, Id);
121     return S_OK;
122 }
123 
124 inline SFGAOF MapFSToSFAttributes(UINT att)
125 {
126     return ((att & FILE_ATTRIBUTE_READONLY) ? SFGAO_READONLY : 0) |
127            ((att & FILE_ATTRIBUTE_HIDDEN) ? SFGAO_HIDDEN : 0) |
128            ((att & FILE_ATTRIBUTE_SYSTEM) ? SFGAO_SYSTEM : 0);
129 }
130 
131 inline bool IncludeInEnumIDList(SHCONTF contf, SFGAOF att)
132 {
133     const SHCONTF both = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
134     const SFGAOF superbits = SFGAO_HIDDEN | SFGAO_READONLY | SFGAO_SYSTEM;
135     const bool isfile = (att & (SFGAO_STREAM | SFGAO_FOLDER)) != SFGAO_FOLDER;
136     if ((contf & both) != both && !(contf & SHCONTF_STORAGE))
137     {
138         if (isfile && (contf & SHCONTF_FOLDERS))
139             return false;
140         if ((att & SFGAO_FOLDER) && (contf & SHCONTF_NONFOLDERS))
141             return false;
142     }
143     if ((att & SFGAO_HIDDEN) && !(contf & (SHCONTF_INCLUDEHIDDEN | SHCONTF_STORAGE)))
144         return false;
145     if ((att & superbits) > SFGAO_HIDDEN && !(contf & (SHCONTF_INCLUDESUPERHIDDEN | SHCONTF_STORAGE)))
146         return false;
147     return true;
148 }
149 
150 inline int MapPIDLToSystemImageListIndex(IShellFolder *pSF, PCUITEMID_CHILD pidl, UINT GilFlags = 0)
151 {
152     int normal, open;
153     BOOL qopen = GilFlags & GIL_OPENICON;
154     normal = SHMapPIDLToSystemImageListIndex(pSF, pidl, qopen ? &open : NULL);
155     return qopen && open != -1 ? open : normal;
156 }
157