mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 16:43:04 +00:00
181 lines
4.8 KiB
C
181 lines
4.8 KiB
C
/*
|
|
* PROJECT: shell32
|
|
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
|
|
* PURPOSE: Utility functions
|
|
* COPYRIGHT: ReactOS Team
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#ifndef OPTIONAL_
|
|
#ifdef __cplusplus
|
|
#define OPTIONAL_(arg) = arg
|
|
#else
|
|
#define OPTIONAL_(arg)
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
static inline LPWSTR
|
|
SHStrDupW(LPCWSTR Src)
|
|
{
|
|
LPWSTR Dup;
|
|
return SUCCEEDED(SHStrDupW(Src, &Dup)) ? Dup : NULL;
|
|
}
|
|
|
|
static inline UINT
|
|
SHELL_ErrorBox(CMINVOKECOMMANDINFO &cmi, UINT Error)
|
|
{
|
|
if (cmi.fMask & CMIC_MASK_FLAG_NO_UI)
|
|
return Error ? Error : ERROR_INTERNAL_ERROR;
|
|
return SHELL_ErrorBox(cmi.hwnd, Error);
|
|
}
|
|
#endif
|
|
|
|
static inline BOOL
|
|
IsEqualPersistClassID(IPersist *pPersist, REFCLSID clsid)
|
|
{
|
|
CLSID temp;
|
|
return pPersist && SUCCEEDED(pPersist->GetClassID(&temp)) && IsEqualCLSID(clsid, temp);
|
|
}
|
|
|
|
static inline BOOL
|
|
RegValueExists(HKEY hKey, LPCWSTR Name)
|
|
{
|
|
return RegQueryValueExW(hKey, Name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS;
|
|
}
|
|
|
|
inline BOOL
|
|
RegKeyExists(HKEY hKey, LPCWSTR Path)
|
|
{
|
|
BOOL ret = !RegOpenKeyExW(hKey, Path, 0, MAXIMUM_ALLOWED, &hKey);
|
|
if (ret)
|
|
RegCloseKey(hKey);
|
|
return ret;
|
|
}
|
|
|
|
inline UINT
|
|
RegQueryDword(HKEY hKey, PCWSTR pszPath, PCWSTR pszName, DWORD *pnVal)
|
|
{
|
|
DWORD cb = sizeof(*pnVal);
|
|
return RegGetValueW(hKey, pszPath, pszName, RRF_RT_REG_DWORD, NULL, pnVal, &cb);
|
|
}
|
|
|
|
inline DWORD
|
|
RegGetDword(HKEY hKey, PCWSTR pszPath, PCWSTR pszName, DWORD nDefVal)
|
|
{
|
|
DWORD nVal;
|
|
return RegQueryDword(hKey, pszPath, pszName, &nVal) == ERROR_SUCCESS ? nVal : nDefVal;
|
|
}
|
|
|
|
inline DWORD
|
|
RegSetOrDelete(HKEY hKey, LPCWSTR Name, DWORD Type, LPCVOID Data, DWORD Size)
|
|
{
|
|
if (Data)
|
|
return RegSetValueExW(hKey, Name, 0, Type, (LPBYTE)Data, Size);
|
|
else
|
|
return RegDeleteValueW(hKey, Name);
|
|
}
|
|
|
|
static inline DWORD
|
|
RegSetString(HKEY hKey, LPCWSTR Name, LPCWSTR Str, DWORD Type OPTIONAL_(REG_SZ))
|
|
{
|
|
return RegSetValueExW(hKey, Name, 0, Type, (LPBYTE)Str, (lstrlenW(Str) + 1) * sizeof(WCHAR));
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
LPCSTR Verb;
|
|
WORD CmdId;
|
|
} CMVERBMAP;
|
|
|
|
HRESULT
|
|
SHELL_MapContextMenuVerbToCmdId(LPCMINVOKECOMMANDINFO pICI, const CMVERBMAP *pMap);
|
|
HRESULT
|
|
SHELL_GetCommandStringImpl(SIZE_T CmdId, UINT uFlags, LPSTR Buf, UINT cchBuf, const CMVERBMAP *pMap);
|
|
|
|
// SHExtractIconsW is a forward, use this function instead inside shell32
|
|
inline HICON
|
|
SHELL32_SHExtractIcon(LPCWSTR File, int Index, int cx, int cy)
|
|
{
|
|
HICON hIco;
|
|
int r = PrivateExtractIconsW(File, Index, cx, cy, &hIco, NULL, 1, 0);
|
|
return r > 0 ? hIco : NULL;
|
|
}
|
|
|
|
HRESULT
|
|
SHELL_CreateShell32DefaultExtractIcon(int IconIndex, REFIID riid, LPVOID *ppvOut);
|
|
|
|
static inline HRESULT
|
|
SHELL_CreateFallbackExtractIconForFolder(REFIID riid, LPVOID *ppvOut)
|
|
{
|
|
const int id = IDI_SHELL_FOLDER;
|
|
return SHELL_CreateShell32DefaultExtractIcon(id > 1 ? -id : 0, riid, ppvOut);
|
|
}
|
|
|
|
static inline HRESULT
|
|
SHELL_CreateFallbackExtractIconForNoAssocFile(REFIID riid, LPVOID *ppvOut)
|
|
{
|
|
const int id = IDI_SHELL_DOCUMENT;
|
|
return SHELL_CreateShell32DefaultExtractIcon(id > 1 ? -id : 0, riid, ppvOut);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
struct ClipboardViewerChain
|
|
{
|
|
HWND m_hWndNext = HWND_BOTTOM;
|
|
|
|
void Unhook(HWND hWnd)
|
|
{
|
|
if (m_hWndNext != HWND_BOTTOM)
|
|
ChangeClipboardChain(hWnd, m_hWndNext);
|
|
m_hWndNext = HWND_BOTTOM;
|
|
}
|
|
|
|
void Hook(HWND hWnd)
|
|
{
|
|
if (m_hWndNext == HWND_BOTTOM)
|
|
m_hWndNext = SetClipboardViewer(hWnd);
|
|
}
|
|
|
|
LRESULT HandleChangeCBChain(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (m_hWndNext == (HWND)wParam)
|
|
return (LRESULT)(m_hWndNext = (HWND)lParam);
|
|
else if (m_hWndNext && m_hWndNext != HWND_BOTTOM)
|
|
return ::SendMessageW(m_hWndNext, WM_CHANGECBCHAIN, wParam, lParam);
|
|
return 0;
|
|
}
|
|
|
|
LRESULT HandleDrawClipboard(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (m_hWndNext && m_hWndNext != HWND_BOTTOM)
|
|
return ::SendMessageW(m_hWndNext, WM_DRAWCLIPBOARD, wParam, lParam);
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
struct CCidaChildArrayHelper
|
|
{
|
|
// Note: This just creates an array pointing to the items and has the same lifetime as the CIDA.
|
|
// Use _ILCopyCidaToaPidl if you need the items to outlive the CIDA!
|
|
explicit CCidaChildArrayHelper(const CIDA *pCida)
|
|
{
|
|
m_hr = E_OUTOFMEMORY;
|
|
m_array = (PCUIDLIST_RELATIVE_ARRAY)SHAlloc(pCida->cidl * sizeof(LPITEMIDLIST));
|
|
if (m_array)
|
|
{
|
|
m_hr = S_OK;
|
|
for (UINT i = 0; i < pCida->cidl; ++i)
|
|
*(LPITEMIDLIST*)(&m_array[i]) = (LPITEMIDLIST)HIDA_GetPIDLItem(pCida, i);
|
|
}
|
|
}
|
|
~CCidaChildArrayHelper() { SHFree((LPITEMIDLIST*)m_array); }
|
|
|
|
HRESULT hr() const { return m_hr; }
|
|
PCUIDLIST_RELATIVE_ARRAY GetItems() const { return m_array; }
|
|
|
|
HRESULT m_hr;
|
|
PCUIDLIST_RELATIVE_ARRAY m_array;
|
|
};
|
|
#endif // __cplusplus
|