mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[SHLWAPI][SDK] Implement SHGetViewStatePropertyBag Part 3 (#5615)
Follow-up to #5610. - Add _EnsureWriteBag, _PruneMRUTree, _GetMRUSize and _GetMRUSlots helper functions. - Add code into _GetMRUSlot, _FindNearestInheritBag, and Write. - Add CLSID_MruPidlList and IID_IMruPidlList definitions into <shlguid_undoc.h>. - Add IMruPidlList interface into <shlobj_undoc.h>. CORE-9283
This commit is contained in:
parent
ff63d06406
commit
29fbe60abe
3 changed files with 178 additions and 23 deletions
|
@ -9,6 +9,8 @@
|
|||
#include "precomp.h"
|
||||
#include <shlwapi.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
#include <shlobj_undoc.h>
|
||||
#include <shlguid_undoc.h>
|
||||
#include <atlstr.h> // for CStringW
|
||||
#include <atlsimpcoll.h> // for CSimpleMap
|
||||
#include <atlcomcli.h> // for CComVariant
|
||||
|
@ -17,6 +19,11 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
#define MODE_CAN_READ(dwMode) \
|
||||
(((dwMode) & (STGM_READ | STGM_WRITE | STGM_READWRITE)) != STGM_WRITE)
|
||||
#define MODE_CAN_WRITE(dwMode) \
|
||||
(((dwMode) & (STGM_READ | STGM_WRITE | STGM_READWRITE)) != STGM_READ)
|
||||
|
||||
class CBasePropertyBag
|
||||
: public IPropertyBag
|
||||
#if (_WIN32_WINNT < _WIN32_WINNT_VISTA)
|
||||
|
@ -39,6 +46,9 @@ public:
|
|||
// IUnknown interface
|
||||
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
|
||||
{
|
||||
if (!ppvObject)
|
||||
return E_POINTER;
|
||||
|
||||
#if (_WIN32_WINNT < _WIN32_WINNT_VISTA)
|
||||
if (::IsEqualGUID(riid, IID_IPropertyBag2))
|
||||
{
|
||||
|
@ -54,8 +64,8 @@ public:
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
ERR("%p: %s: E_NOTIMPL\n", this, debugstr_guid(&riid));
|
||||
return E_NOTIMPL;
|
||||
ERR("%p: %s: E_NOINTERFACE\n", this, debugstr_guid(&riid));
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
STDMETHODIMP_(ULONG) AddRef() override
|
||||
{
|
||||
|
@ -153,7 +163,7 @@ CMemPropertyBag::Read(
|
|||
::VariantInit(pvari);
|
||||
|
||||
#if (_WIN32_WINNT < _WIN32_WINNT_VISTA)
|
||||
if ((m_dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_WRITE)
|
||||
if (!MODE_CAN_READ(m_dwMode))
|
||||
{
|
||||
ERR("%p: 0x%X\n", this, m_dwMode);
|
||||
return E_ACCESSDENIED;
|
||||
|
@ -198,7 +208,7 @@ CMemPropertyBag::Write(
|
|||
TRACE("%p: %s %p\n", this, debugstr_w(pszPropName), pvari);
|
||||
|
||||
#if (_WIN32_WINNT < _WIN32_WINNT_VISTA)
|
||||
if ((m_dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_READ)
|
||||
if (!MODE_CAN_WRITE(m_dwMode))
|
||||
{
|
||||
ERR("%p: 0x%X\n", this, m_dwMode);
|
||||
return E_ACCESSDENIED;
|
||||
|
@ -288,9 +298,9 @@ public:
|
|||
HRESULT CRegPropertyBag::Init(HKEY hKey, LPCWSTR lpSubKey)
|
||||
{
|
||||
REGSAM nAccess = 0;
|
||||
if ((m_dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) != STGM_WRITE)
|
||||
if (MODE_CAN_READ(m_dwMode))
|
||||
nAccess |= KEY_READ;
|
||||
if ((m_dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) != STGM_READ)
|
||||
if (MODE_CAN_WRITE(m_dwMode))
|
||||
nAccess |= KEY_WRITE;
|
||||
|
||||
LONG error;
|
||||
|
@ -409,7 +419,7 @@ CRegPropertyBag::Read(
|
|||
|
||||
TRACE("%p: %s %p %p\n", this, debugstr_w(pszPropName), pvari, pErrorLog);
|
||||
|
||||
if ((m_dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_WRITE)
|
||||
if (!MODE_CAN_READ(m_dwMode))
|
||||
{
|
||||
ERR("%p: 0x%X\n", this, m_dwMode);
|
||||
::VariantInit(pvari);
|
||||
|
@ -479,7 +489,7 @@ CRegPropertyBag::Write(_In_z_ LPCWSTR pszPropName, _In_ VARIANT *pvari)
|
|||
{
|
||||
TRACE("%p: %s %p\n", this, debugstr_w(pszPropName), pvari);
|
||||
|
||||
if ((m_dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_READ)
|
||||
if (!MODE_CAN_WRITE(m_dwMode))
|
||||
{
|
||||
ERR("%p: 0x%X\n", this, m_dwMode);
|
||||
return E_ACCESSDENIED;
|
||||
|
@ -856,7 +866,7 @@ CIniPropertyBag::Read(
|
|||
|
||||
::VariantInit(pvari);
|
||||
|
||||
if ((m_dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_WRITE)
|
||||
if (!MODE_CAN_READ(m_dwMode))
|
||||
{
|
||||
ERR("%p: 0x%X\n", this, m_dwMode);
|
||||
return E_ACCESSDENIED;
|
||||
|
@ -890,7 +900,7 @@ CIniPropertyBag::Write(_In_z_ LPCWSTR pszPropName, _In_ VARIANT *pvari)
|
|||
{
|
||||
TRACE("%p: %s %p\n", this, debugstr_w(pszPropName), pvari);
|
||||
|
||||
if ((m_dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_READ)
|
||||
if (!MODE_CAN_WRITE(m_dwMode))
|
||||
{
|
||||
ERR("%p: 0x%X\n", this, m_dwMode);
|
||||
return E_ACCESSDENIED;
|
||||
|
@ -1017,6 +1027,7 @@ public:
|
|||
|
||||
STDMETHODIMP Write(_In_z_ LPCWSTR pszPropName, _In_ VARIANT *pvari) override
|
||||
{
|
||||
ERR("%p: %s: Read-only\n", this, debugstr_w(pszPropName));
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
};
|
||||
|
@ -1224,6 +1235,16 @@ protected:
|
|||
|
||||
HKEY _GetHKey(DWORD dwVspbFlags);
|
||||
|
||||
UINT _GetMRUSize(HKEY hKey);
|
||||
|
||||
HRESULT _GetMRUSlots(
|
||||
LPCITEMIDLIST pidl,
|
||||
DWORD dwMode,
|
||||
HKEY hKey,
|
||||
UINT *puSlots,
|
||||
UINT cSlots,
|
||||
UINT *pcSlots);
|
||||
|
||||
HRESULT _GetMRUSlot(LPCITEMIDLIST pidl, DWORD dwMode, HKEY hKey, UINT *pSlot);
|
||||
|
||||
HRESULT _GetRegKey(
|
||||
|
@ -1254,12 +1275,14 @@ protected:
|
|||
BOOL _EnsureUserDefaultsBag(DWORD dwMode, REFIID riid);
|
||||
BOOL _EnsureFolderDefaultsBag(DWORD dwMode, REFIID riid);
|
||||
BOOL _EnsureGlobalDefaultsBag(DWORD dwMode, REFIID riid);
|
||||
BOOL _EnsureWriteBag(DWORD dwMode, REFIID riid);
|
||||
HRESULT _ReadPidlBag(LPCWSTR pszPropName, VARIANT *pvari, IErrorLog *pErrorLog);
|
||||
HRESULT _ReadInheritBag(LPCWSTR pszPropName, VARIANT *pvari, IErrorLog *pErrorLog);
|
||||
HRESULT _ReadUpgradeBag(LPCWSTR pszPropName, VARIANT *pvari, IErrorLog *pErrorLog);
|
||||
HRESULT _ReadUserDefaultsBag(LPCWSTR pszPropName, VARIANT *pvari, IErrorLog *pErrorLog);
|
||||
HRESULT _ReadFolderDefaultsBag(LPCWSTR pszPropName, VARIANT *pvari, IErrorLog *pErrorLog);
|
||||
HRESULT _ReadGlobalDefaultsBag(LPCWSTR pszPropName, VARIANT *pvari, IErrorLog *pErrorLog);
|
||||
void _PruneMRUTree();
|
||||
|
||||
public:
|
||||
CViewStatePropertyBag() : CBasePropertyBag(STGM_READ) { }
|
||||
|
@ -1278,11 +1301,7 @@ public:
|
|||
_Inout_ VARIANT *pvari,
|
||||
_Inout_opt_ IErrorLog *pErrorLog) override;
|
||||
|
||||
STDMETHODIMP Write(_In_z_ LPCWSTR pszPropName, _In_ VARIANT *pvari) override
|
||||
{
|
||||
ERR("%p: %s: Read-only\n", this, debugstr_w(pszPropName));
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
STDMETHODIMP Write(_In_z_ LPCWSTR pszPropName, _In_ VARIANT *pvari) override;
|
||||
};
|
||||
|
||||
// CViewStatePropertyBag is cached
|
||||
|
@ -1413,11 +1432,50 @@ HKEY CViewStatePropertyBag::_GetHKey(DWORD dwVspbFlags)
|
|||
return SHGetShellKey(SHKEY_Key_ShellNoRoam | SHKEY_Root_HKCU, NULL, TRUE);
|
||||
}
|
||||
|
||||
UINT CViewStatePropertyBag::_GetMRUSize(HKEY hKey)
|
||||
{
|
||||
DWORD dwValue, cbValue = sizeof(dwValue);
|
||||
|
||||
if (SHGetValueW(hKey, NULL, L"BagMRU Size", NULL, &dwValue, &cbValue) != ERROR_SUCCESS)
|
||||
return 400; // The default size of the MRU (most recently used) list
|
||||
|
||||
return (UINT)dwValue;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CViewStatePropertyBag::_GetMRUSlots(
|
||||
LPCITEMIDLIST pidl,
|
||||
DWORD dwMode,
|
||||
HKEY hKey,
|
||||
UINT *puSlots,
|
||||
UINT cSlots,
|
||||
UINT *pcSlots)
|
||||
{
|
||||
CComPtr<IMruPidlList> pMruList;
|
||||
HRESULT hr = ::CoCreateInstance(CLSID_MruPidlList, NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_IMruPidlList, (void**)&pMruList);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
UINT cMRUSize = _GetMRUSize(hKey);
|
||||
hr = pMruList->InitList(cMRUSize, hKey, L"BagMRU");
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = pMruList->QueryPidl(pidl, cSlots, puSlots, pcSlots);
|
||||
if (hr == S_OK && MODE_CAN_WRITE(dwMode))
|
||||
hr = pMruList->UsePidl(pidl, puSlots);
|
||||
else if (cSlots == 1)
|
||||
hr = E_FAIL;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CViewStatePropertyBag::_GetMRUSlot(LPCITEMIDLIST pidl, DWORD dwMode, HKEY hKey, UINT *pSlot)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
UINT cSlots;
|
||||
return _GetMRUSlots(pidl, dwMode, hKey, pSlot, 1, &cSlots);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
@ -1439,14 +1497,14 @@ CViewStatePropertyBag::_GetRegKey(
|
|||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (dwFlags & SHGVSPB_INHERIT)
|
||||
wnsprintfW(pszDest, cchDest, L"Bags\\%d\\%s\\Inherit", nSlot, pszBagName);
|
||||
StringCchPrintfW(pszDest, cchDest, L"Bags\\%d\\%s\\Inherit", nSlot, pszBagName);
|
||||
else
|
||||
wnsprintfW(pszDest, cchDest, L"Bags\\%d\\%s", nSlot, pszBagName);
|
||||
StringCchPrintfW(pszDest, cchDest, L"Bags\\%d\\%s", nSlot, pszBagName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wnsprintfW(pszDest, cchDest, L"Bags\\AllFolders\\%s", pszBagName);
|
||||
StringCchPrintfW(pszDest, cchDest, L"Bags\\AllFolders\\%s", pszBagName);
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
@ -1487,7 +1545,7 @@ CViewStatePropertyBag::_CreateBag(
|
|||
CComPtr<IShellFolder> psf;
|
||||
WCHAR szBuff[64];
|
||||
|
||||
if ((dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) != STGM_READ)
|
||||
if (MODE_CAN_WRITE(dwMode))
|
||||
dwMode |= STGM_CREATE;
|
||||
|
||||
if ((dwVspbFlags & SHGVSPB_ALLUSERS) && (dwVspbFlags & SHGVSPB_PERFOLDER))
|
||||
|
@ -1523,8 +1581,32 @@ CViewStatePropertyBag::_CreateBag(
|
|||
HRESULT
|
||||
CViewStatePropertyBag::_FindNearestInheritBag(REFIID riid, IPropertyBag **pppb)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return E_NOTIMPL;
|
||||
*pppb = NULL;
|
||||
|
||||
HKEY hKey = _GetHKey(SHGVSPB_INHERIT);
|
||||
if (!hKey)
|
||||
return E_FAIL;
|
||||
|
||||
UINT cSlots, anSlots[64];
|
||||
if (FAILED(_GetMRUSlots(m_pidl, 0, hKey, anSlots, _countof(anSlots), &cSlots)) || !cSlots)
|
||||
{
|
||||
::RegCloseKey(hKey);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT hr = E_FAIL;
|
||||
WCHAR szBuff[64];
|
||||
for (UINT iSlot = 0; iSlot < cSlots; ++iSlot)
|
||||
{
|
||||
StringCchPrintfW(szBuff, _countof(szBuff), L"Bags\\%d\\%s\\Inherit", anSlots[iSlot],
|
||||
m_pszPath);
|
||||
hr = SHCreatePropertyBagOnRegKey(hKey, szBuff, STGM_READ, riid, (void**)pppb);
|
||||
if (SUCCEEDED(hr))
|
||||
break;
|
||||
}
|
||||
|
||||
::RegCloseKey(hKey);
|
||||
return hr;
|
||||
}
|
||||
|
||||
BOOL CViewStatePropertyBag::_EnsureReadBag(DWORD dwMode, REFIID riid)
|
||||
|
@ -1710,6 +1792,49 @@ CViewStatePropertyBag::Read(
|
|||
return _ReadGlobalDefaultsBag(pszPropName, pvari, pErrorLog);
|
||||
}
|
||||
|
||||
void CViewStatePropertyBag::_PruneMRUTree()
|
||||
{
|
||||
HKEY hKey = _GetHKey(SHGVSPB_INHERIT);
|
||||
if (!hKey)
|
||||
return;
|
||||
|
||||
CComPtr<IMruPidlList> pMruList;
|
||||
HRESULT hr = ::CoCreateInstance(CLSID_MruPidlList, NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_IMruPidlList, (void**)&pMruList);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pMruList->InitList(200, hKey, L"BagMRU");
|
||||
if (SUCCEEDED(hr))
|
||||
pMruList->PruneKids(m_pidl);
|
||||
}
|
||||
|
||||
::RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
BOOL CViewStatePropertyBag::_EnsureWriteBag(DWORD dwMode, REFIID riid)
|
||||
{
|
||||
if (!m_pWriteBag && !m_bWriteBag)
|
||||
{
|
||||
m_bWriteBag = TRUE;
|
||||
_CreateBag(m_pidl, m_pszPath, m_dwVspbFlags, dwMode, riid, &m_pWriteBag);
|
||||
if (m_pWriteBag)
|
||||
{
|
||||
_ResetTryAgainFlag();
|
||||
if (m_dwVspbFlags & SHGVSPB_INHERIT)
|
||||
_PruneMRUTree();
|
||||
}
|
||||
}
|
||||
return (m_pWriteBag != NULL);
|
||||
}
|
||||
|
||||
STDMETHODIMP CViewStatePropertyBag::Write(_In_z_ LPCWSTR pszPropName, _In_ VARIANT *pvari)
|
||||
{
|
||||
if (!_EnsureWriteBag(STGM_WRITE, IID_IPropertyBag))
|
||||
return E_FAIL;
|
||||
|
||||
return m_pWriteBag->Write(pszPropName, pvari);
|
||||
}
|
||||
|
||||
static BOOL SHIsRemovableDrive(LPCITEMIDLIST pidl)
|
||||
{
|
||||
STRRET strret;
|
||||
|
|
|
@ -142,6 +142,8 @@ DEFINE_GUID(CLSID_SharedTaskScheduler, 0x603D3801, 0xBD81, 0x11d0, 0xA3, 0xA
|
|||
DEFINE_GUID(CLSID_SendToMenu, 0x7BA4C740, 0x9E81, 0x11CF, 0x99, 0xD3, 0x00, 0xAA, 0x00, 0x4A, 0xE8, 0x37);
|
||||
DEFINE_GUID(CLSID_CopyToMenu, 0xC2FBB630, 0x2971, 0x11D1, 0xA1, 0x8C, 0x00, 0xC0, 0x4F, 0xD7, 0x5D, 0x13);
|
||||
DEFINE_GUID(CLSID_MoveToMenu, 0xC2FBB631, 0x2971, 0x11D1, 0xA1, 0x8C, 0x00, 0xC0, 0x4F, 0xD7, 0x5D, 0x13);
|
||||
DEFINE_GUID(CLSID_MruPidlList, 0x42AEDC87, 0x2188, 0x41FD, 0xB9, 0xA3, 0x0C, 0x96, 0x6F, 0xEA, 0xBE, 0xC1);
|
||||
DEFINE_GUID(IID_IMruPidlList, 0x47851649, 0xA2EF, 0x4E67, 0xBA, 0xEC, 0xC6, 0xA1, 0x53, 0xAC, 0x72, 0xEC);
|
||||
|
||||
/* The following list of interfaces was taken from here: http://www.geoffchappell.com/studies/windows/shell/shell32/interfaces/index.htm */
|
||||
DEFINE_GUID(IID_IAggregateFilterCondition, 0x86228AA3, 0xA736, 0x4733, 0xBD, 0x8A, 0x10, 0xA8, 0x3C, 0x69, 0xBF, 0x84);
|
||||
|
|
|
@ -678,6 +678,34 @@ DECLARE_INTERFACE_(IShellBrowserService, IUnknown)
|
|||
#define IShellBrowserService_GetPropertyBag(T,a,b,c) (T)->lpVtbl->GetPropertyBag(T,a,b,c)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* IMruPidlList interface
|
||||
*/
|
||||
#define INTERFACE IMruPidlList
|
||||
DECLARE_INTERFACE_(IMruPidlList, IUnknown)
|
||||
{
|
||||
/*** IUnknown ***/
|
||||
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
|
||||
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
||||
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
||||
/*** IMruPidlList ***/
|
||||
STDMETHOD(InitList)(THIS_ UINT, HKEY, LPCWSTR) PURE;
|
||||
STDMETHOD(UsePidl)(THIS_ LPCITEMIDLIST, UINT*) PURE;
|
||||
STDMETHOD(QueryPidl)(THIS_ LPCITEMIDLIST, UINT, UINT*, UINT*) PURE;
|
||||
STDMETHOD(PruneKids)(THIS_ LPCITEMIDLIST) PURE;
|
||||
};
|
||||
#undef INTERFACE
|
||||
|
||||
#ifdef COBJMACROS
|
||||
#define IMruPidlList_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b)
|
||||
#define IMruPidlList_AddRef(T) (T)->lpVtbl->AddRef(T)
|
||||
#define IMruPidlList_Release(T) (T)->lpVtbl->Release(T)
|
||||
#define IMruPidlList_InitList(T,a,b,c) (T)->lpVtbl->InitList(T,a,b,c)
|
||||
#define IMruPidlList_UsePidl(T,a,b) (T)->lpVtbl->UsePidl(T,a,b)
|
||||
#define IMruPidlList_QueryPidl(T,a,b,c,d) (T)->lpVtbl->QueryPidl(T,a,b,c,d)
|
||||
#define IMruPidlList_PruneKids(T,a) (T)->lpVtbl->PruneKids(T,a)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* ITrayPriv interface
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue