Reactos
at master 189 lines 5.3 kB view raw
1/* 2 * PROJECT: shell32 3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) 4 * PURPOSE: Utility functions 5 * COPYRIGHT: ReactOS Team 6 */ 7 8#pragma once 9 10#ifndef OPTIONAL_ 11 #ifdef __cplusplus 12 #define OPTIONAL_(arg) = arg 13 #else 14 #define OPTIONAL_(arg) 15 #endif 16#endif 17 18#ifdef __cplusplus 19static inline LPWSTR 20SHStrDupW(LPCWSTR Src) 21{ 22 LPWSTR Dup; 23 return SUCCEEDED(SHStrDupW(Src, &Dup)) ? Dup : NULL; 24} 25 26static inline UINT 27SHELL_ErrorBox(CMINVOKECOMMANDINFO &cmi, UINT Error) 28{ 29 if (cmi.fMask & CMIC_MASK_FLAG_NO_UI) 30 return Error ? Error : ERROR_INTERNAL_ERROR; 31 return SHELL_ErrorBox(cmi.hwnd, Error); 32} 33#endif 34 35static inline BOOL 36IsEqualPersistClassID(IPersist *pPersist, REFCLSID clsid) 37{ 38 CLSID temp; 39 return pPersist && SUCCEEDED(pPersist->GetClassID(&temp)) && IsEqualCLSID(clsid, temp); 40} 41 42static inline BOOL 43RegValueExists(HKEY hKey, LPCWSTR Name) 44{ 45 return RegQueryValueExW(hKey, Name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; 46} 47 48inline BOOL 49RegKeyExists(HKEY hKey, LPCWSTR Path) 50{ 51 BOOL ret = !RegOpenKeyExW(hKey, Path, 0, MAXIMUM_ALLOWED, &hKey); 52 if (ret) 53 RegCloseKey(hKey); 54 return ret; 55} 56 57inline UINT 58RegQueryDword(HKEY hKey, PCWSTR pszPath, PCWSTR pszName, DWORD *pnVal) 59{ 60 DWORD cb = sizeof(*pnVal); 61 return RegGetValueW(hKey, pszPath, pszName, RRF_RT_REG_DWORD, NULL, pnVal, &cb); 62} 63 64inline DWORD 65RegGetDword(HKEY hKey, PCWSTR pszPath, PCWSTR pszName, DWORD nDefVal) 66{ 67 DWORD nVal; 68 return RegQueryDword(hKey, pszPath, pszName, &nVal) == ERROR_SUCCESS ? nVal : nDefVal; 69} 70 71inline DWORD 72RegSetOrDelete(HKEY hKey, LPCWSTR Name, DWORD Type, LPCVOID Data, DWORD Size) 73{ 74 if (Data) 75 return RegSetValueExW(hKey, Name, 0, Type, (LPBYTE)Data, Size); 76 else 77 return RegDeleteValueW(hKey, Name); 78} 79 80static inline DWORD 81RegSetString(HKEY hKey, LPCWSTR Name, LPCWSTR Str, DWORD Type OPTIONAL_(REG_SZ)) 82{ 83 return RegSetValueExW(hKey, Name, 0, Type, (LPBYTE)Str, (lstrlenW(Str) + 1) * sizeof(WCHAR)); 84} 85 86typedef struct 87{ 88 LPCSTR Verb; 89 WORD CmdId; 90} CMVERBMAP; 91 92HRESULT 93SHELL_MapContextMenuVerbToCmdId(LPCMINVOKECOMMANDINFO pICI, const CMVERBMAP *pMap); 94HRESULT 95SHELL_GetCommandStringImpl(SIZE_T CmdId, UINT uFlags, LPSTR Buf, UINT cchBuf, const CMVERBMAP *pMap); 96 97// SHExtractIconsW is a forward, use this function instead inside shell32 98inline HICON 99SHELL32_SHExtractIcon(LPCWSTR File, int Index, int cx, int cy) 100{ 101 HICON hIco; 102 int r = PrivateExtractIconsW(File, Index, cx, cy, &hIco, NULL, 1, 0); 103 return r > 0 ? hIco : NULL; 104} 105 106HRESULT 107SHELL_CreateShell32DefaultExtractIcon(int IconIndex, REFIID riid, LPVOID *ppvOut); 108 109static inline HRESULT 110SHELL_CreateFallbackExtractIconForFolder(REFIID riid, LPVOID *ppvOut) 111{ 112 const int id = IDI_SHELL_FOLDER; 113 return SHELL_CreateShell32DefaultExtractIcon(id > 1 ? -id : 0, riid, ppvOut); 114} 115 116static inline HRESULT 117SHELL_CreateFallbackExtractIconForNoAssocFile(REFIID riid, LPVOID *ppvOut) 118{ 119 const int id = IDI_SHELL_DOCUMENT; 120 return SHELL_CreateShell32DefaultExtractIcon(id > 1 ? -id : 0, riid, ppvOut); 121} 122 123typedef HDSA HDCIA; // DynamicClassIdArray 124#define DCIA_Create() ( (HDCIA)DSA_Create(sizeof(CLSID), 4) ) 125#define DCIA_Destroy(hDCIA) DSA_Destroy((HDSA)(hDCIA)) 126#define DCIA_GetCount(hDCIA) DSA_GetItemCount((HDSA)(hDCIA)) 127#define DCIA_GetEntry(hDCIA, iItem) ( (const CLSID*)DSA_GetItemPtr((HDSA)(hDCIA), (iItem)) ) 128int DCIA_AddEntry(HDCIA hDCIA, REFCLSID rClsId); 129void DCIA_AddShellExSubkey(HDCIA hDCIA, HKEY hProgId, PCWSTR pszSubkey); 130 131#ifdef __cplusplus 132struct ClipboardViewerChain 133{ 134 HWND m_hWndNext = HWND_BOTTOM; 135 136 void Unhook(HWND hWnd) 137 { 138 if (m_hWndNext != HWND_BOTTOM) 139 ChangeClipboardChain(hWnd, m_hWndNext); 140 m_hWndNext = HWND_BOTTOM; 141 } 142 143 void Hook(HWND hWnd) 144 { 145 if (m_hWndNext == HWND_BOTTOM) 146 m_hWndNext = SetClipboardViewer(hWnd); 147 } 148 149 LRESULT HandleChangeCBChain(WPARAM wParam, LPARAM lParam) 150 { 151 if (m_hWndNext == (HWND)wParam) 152 return (LRESULT)(m_hWndNext = (HWND)lParam); 153 else if (m_hWndNext && m_hWndNext != HWND_BOTTOM) 154 return ::SendMessageW(m_hWndNext, WM_CHANGECBCHAIN, wParam, lParam); 155 return 0; 156 } 157 158 LRESULT HandleDrawClipboard(WPARAM wParam, LPARAM lParam) 159 { 160 if (m_hWndNext && m_hWndNext != HWND_BOTTOM) 161 return ::SendMessageW(m_hWndNext, WM_DRAWCLIPBOARD, wParam, lParam); 162 return 0; 163 } 164}; 165 166struct CCidaChildArrayHelper 167{ 168 // Note: This just creates an array pointing to the items and has the same lifetime as the CIDA. 169 // Use _ILCopyCidaToaPidl if you need the items to outlive the CIDA! 170 explicit CCidaChildArrayHelper(const CIDA *pCida) 171 { 172 m_hr = E_OUTOFMEMORY; 173 m_array = (PCUIDLIST_RELATIVE_ARRAY)SHAlloc(pCida->cidl * sizeof(LPITEMIDLIST)); 174 if (m_array) 175 { 176 m_hr = S_OK; 177 for (UINT i = 0; i < pCida->cidl; ++i) 178 *(LPITEMIDLIST*)(&m_array[i]) = (LPITEMIDLIST)HIDA_GetPIDLItem(pCida, i); 179 } 180 } 181 ~CCidaChildArrayHelper() { SHFree((LPITEMIDLIST*)m_array); } 182 183 HRESULT hr() const { return m_hr; } 184 PCUIDLIST_RELATIVE_ARRAY GetItems() const { return m_array; } 185 186 HRESULT m_hr; 187 PCUIDLIST_RELATIVE_ARRAY m_array; 188}; 189#endif // __cplusplus