https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a3e6ae2e8a82a94b0d998…
commit a3e6ae2e8a82a94b0d9984463621c20c5b4dab26
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Fri Aug 25 07:57:22 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Fri Aug 25 07:57:22 2023 +0900
[SHLWAPI] Implement SHGetViewStatePropertyBag Part 2 (#5610)
CORE-9283
---
dll/win32/shlwapi/propbag.cpp | 321 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 299 insertions(+), 22 deletions(-)
diff --git a/dll/win32/shlwapi/propbag.cpp b/dll/win32/shlwapi/propbag.cpp
index 3a937019a51..9faa250cd07 100644
--- a/dll/win32/shlwapi/propbag.cpp
+++ b/dll/win32/shlwapi/propbag.cpp
@@ -130,7 +130,7 @@ protected:
ATL::CSimpleMap<ATL::CStringW, ATL::CComVariant, CPropMapEqual> m_PropMap;
public:
- CMemPropertyBag(DWORD dwFlags) : CBasePropertyBag(dwFlags) { }
+ CMemPropertyBag(DWORD dwMode) : CBasePropertyBag(dwMode) { }
STDMETHODIMP Read(_In_z_ LPCWSTR pszPropName, _Inout_ VARIANT *pvari,
_Inout_opt_ IErrorLog *pErrorLog) override;
@@ -1007,7 +1007,7 @@ protected:
IStream* _NewStreamFromOld(IStream *pOldStream);
public:
- CDesktopUpgradePropertyBag() : CBasePropertyBag(0) { }
+ CDesktopUpgradePropertyBag() : CBasePropertyBag(STGM_READ) { }
STDMETHODIMP Read(
_In_z_ LPCWSTR pszPropName,
@@ -1174,7 +1174,7 @@ CDesktopUpgradePropertyBag::Read(
}
/**************************************************************************
- * SHGetDesktopUpgradePropertyBag (Not exported; used in CViewStatePropertyBag)
+ * SHGetDesktopUpgradePropertyBag (Internal)
*
* Creates or gets a property bag object for desktop upgrade
*
@@ -1223,11 +1223,13 @@ protected:
HKEY _GetHKey(DWORD dwVspbFlags);
+ HRESULT _GetMRUSlot(LPCITEMIDLIST pidl, DWORD dwMode, HKEY hKey, UINT *pSlot);
+
HRESULT _GetRegKey(
LPCITEMIDLIST pidl,
LPCWSTR pszBagName,
DWORD dwFlags,
- char unknown,
+ DWORD dwMode,
HKEY hKey,
LPWSTR pszDest,
INT cchDest);
@@ -1238,14 +1240,28 @@ protected:
DWORD dwVspbFlags,
DWORD dwMode,
REFIID riid,
- void **ppvObj);
+ IPropertyBag **pppb);
+
+ HRESULT _FindNearestInheritBag(REFIID riid, IPropertyBag **pppb);
void _ResetTryAgainFlag();
+ BOOL _EnsureReadBag(DWORD dwMode, REFIID riid);
+ BOOL _EnsurePidlBag(DWORD dwMode, REFIID riid);
+ BOOL _EnsureInheritBag(DWORD dwMode, REFIID riid);
+ BOOL _EnsureUpgradeBag(DWORD dwMode, REFIID riid);
+ BOOL _EnsureUserDefaultsBag(DWORD dwMode, REFIID riid);
+ BOOL _EnsureFolderDefaultsBag(DWORD dwMode, REFIID riid);
+ BOOL _EnsureGlobalDefaultsBag(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);
+
public:
- CViewStatePropertyBag() : CBasePropertyBag(0)
- {
- }
+ CViewStatePropertyBag() : CBasePropertyBag(STGM_READ) { }
~CViewStatePropertyBag() override
{
@@ -1396,17 +1412,63 @@ HKEY CViewStatePropertyBag::_GetHKey(DWORD dwVspbFlags)
return SHGetShellKey(SHKEY_Key_ShellNoRoam | SHKEY_Root_HKCU, NULL, TRUE);
}
-HRESULT CViewStatePropertyBag::_GetRegKey(
+HRESULT
+CViewStatePropertyBag::_GetMRUSlot(LPCITEMIDLIST pidl, DWORD dwMode, HKEY hKey, UINT
*pSlot)
+{
+ FIXME("Stub\n");
+ return E_NOTIMPL;
+}
+
+HRESULT
+CViewStatePropertyBag::_GetRegKey(
LPCITEMIDLIST pidl,
LPCWSTR pszBagName,
DWORD dwFlags,
- char unknown,
+ DWORD dwMode,
HKEY hKey,
LPWSTR pszDest,
INT cchDest)
{
- FIXME("Stub\n");
- return E_NOTIMPL;
+ HRESULT hr = S_OK;
+ UINT nSlot;
+
+ if (dwFlags & (SHGVSPB_INHERIT | SHGVSPB_PERFOLDER))
+ {
+ hr = _GetMRUSlot(pidl, dwMode, hKey, &nSlot);
+ if (SUCCEEDED(hr))
+ {
+ if (dwFlags & SHGVSPB_INHERIT)
+ wnsprintfW(pszDest, cchDest, L"Bags\\%d\\%s\\Inherit", nSlot,
pszBagName);
+ else
+ wnsprintfW(pszDest, cchDest, L"Bags\\%d\\%s", nSlot,
pszBagName);
+ }
+ }
+ else
+ {
+ wnsprintfW(pszDest, cchDest, L"Bags\\AllFolders\\%s", pszBagName);
+ }
+
+ return hr;
+}
+
+static HRESULT BindCtx_CreateWithMode(DWORD dwMode, IBindCtx **ppbc)
+{
+ HRESULT hr = ::CreateBindCtx(0, ppbc);
+ if (FAILED(hr))
+ return hr;
+
+ IBindCtx *pbc = *ppbc;
+
+ BIND_OPTS opts = { sizeof(opts) };
+ opts.grfMode = dwMode;
+ hr = pbc->SetBindOptions(&opts);
+ if (FAILED(hr))
+ {
+ pbc->Release();
+ *ppbc = NULL;
+ }
+
+ return hr;
}
HRESULT
@@ -1416,20 +1478,235 @@ CViewStatePropertyBag::_CreateBag(
DWORD dwVspbFlags,
DWORD dwMode,
REFIID riid,
- void **ppvObj)
+ IPropertyBag **pppb)
+{
+ HRESULT hr;
+ HKEY hKey;
+ CComPtr<IBindCtx> pBC;
+ CComPtr<IShellFolder> psf;
+ WCHAR szBuff[64];
+
+ if ((dwMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) != STGM_READ)
+ dwMode |= STGM_CREATE;
+
+ if ((dwVspbFlags & SHGVSPB_ALLUSERS) && (dwVspbFlags &
SHGVSPB_PERFOLDER))
+ {
+ hr = BindCtx_CreateWithMode(dwMode, &pBC);
+ if (SUCCEEDED(hr))
+ {
+ hr = SHGetDesktopFolder(&psf);
+ if (SUCCEEDED(hr))
+ {
+ hr = psf->BindToObject(m_pidl, pBC, riid, (void **)pppb);
+ if (SUCCEEDED(hr) && !*pppb)
+ hr = E_FAIL;
+ }
+ }
+ }
+ else
+ {
+ hKey = _GetHKey(dwVspbFlags);
+ if (!hKey)
+ return E_FAIL;
+
+ hr = _GetRegKey(pidl, pszPath, dwVspbFlags, dwMode, hKey, szBuff,
_countof(szBuff));
+ if (SUCCEEDED(hr))
+ hr = SHCreatePropertyBagOnRegKey(hKey, szBuff, dwMode, riid, (void**)pppb);
+
+ ::RegCloseKey(hKey);
+ }
+
+ return hr;
+}
+
+HRESULT
+CViewStatePropertyBag::_FindNearestInheritBag(REFIID riid, IPropertyBag **pppb)
{
FIXME("Stub\n");
return E_NOTIMPL;
}
+BOOL CViewStatePropertyBag::_EnsureReadBag(DWORD dwMode, REFIID riid)
+{
+ if (!m_pReadBag && !m_bReadBag)
+ {
+ m_bReadBag = TRUE;
+ _CreateBag(m_pidl, m_pszPath, m_dwVspbFlags, dwMode, riid, &m_pReadBag);
+ }
+ return (m_pReadBag != NULL);
+}
+
+BOOL CViewStatePropertyBag::_EnsurePidlBag(DWORD dwMode, REFIID riid)
+{
+ if (!m_pPidlBag && !m_bPidlBag && _CanAccessPidlBag())
+ {
+ m_bPidlBag = TRUE;
+ _CreateBag(m_pidl, m_pszPath, SHGVSPB_FOLDER, dwMode, riid, &m_pPidlBag);
+ }
+ return (m_pPidlBag != NULL);
+}
+
+BOOL CViewStatePropertyBag::_EnsureInheritBag(DWORD dwMode, REFIID riid)
+{
+ if (!m_pInheritBag && !m_bInheritBag && _CanAccessInheritBag())
+ {
+ m_bInheritBag = TRUE;
+ _FindNearestInheritBag(riid, &m_pInheritBag);
+ }
+ return (m_pInheritBag != NULL);
+}
+
+BOOL CViewStatePropertyBag::_EnsureUpgradeBag(DWORD dwMode, REFIID riid)
+{
+ if (!m_pUpgradeBag && !m_bUpgradeBag && _CanAccessUpgradeBag())
+ {
+ m_bUpgradeBag = TRUE;
+ SHGetDesktopUpgradePropertyBag(riid, (void**)&m_pUpgradeBag);
+ }
+ return (m_pUpgradeBag != NULL);
+}
+
+BOOL CViewStatePropertyBag::_EnsureUserDefaultsBag(DWORD dwMode, REFIID riid)
+{
+ if (!m_pUserDefaultsBag && !m_bUserDefaultsBag &&
_CanAccessUserDefaultsBag())
+ {
+ m_bUserDefaultsBag = TRUE;
+ _CreateBag(NULL, m_pszPath, SHGVSPB_USERDEFAULTS, dwMode, riid,
&m_pUserDefaultsBag);
+ }
+ return (m_pUserDefaultsBag != NULL);
+}
+
+BOOL CViewStatePropertyBag::_EnsureFolderDefaultsBag(DWORD dwMode, REFIID riid)
+{
+ if (!m_pFolderDefaultsBag && !m_bFolderDefaultsBag &&
_CanAccessFolderDefaultsBag())
+ {
+ m_bFolderDefaultsBag = TRUE;
+ if (_IsSystemFolder())
+ {
+ _CreateBag(m_pidl, m_pszPath, SHGVSPB_PERFOLDER | SHGVSPB_ALLUSERS,
+ dwMode, riid, &m_pFolderDefaultsBag);
+ }
+ }
+ return (m_pFolderDefaultsBag != NULL);
+}
+
+BOOL CViewStatePropertyBag::_EnsureGlobalDefaultsBag(DWORD dwMode, REFIID riid)
+{
+ if (!m_pGlobalDefaultsBag && !m_bGlobalDefaultsBag &&
_CanAccessGlobalDefaultsBag())
+ {
+ m_bGlobalDefaultsBag = TRUE;
+ _CreateBag(NULL, m_pszPath, SHGVSPB_GLOBALDEAFAULTS, dwMode, riid,
&m_pGlobalDefaultsBag);
+ }
+ return (m_pGlobalDefaultsBag != NULL);
+}
+
+HRESULT
+CViewStatePropertyBag::_ReadPidlBag(
+ LPCWSTR pszPropName,
+ VARIANT *pvari,
+ IErrorLog *pErrorLog)
+{
+ if (!_EnsurePidlBag(STGM_READ, IID_IPropertyBag))
+ return E_FAIL;
+
+ return m_pPidlBag->Read(pszPropName, pvari, pErrorLog);
+}
+
+HRESULT
+CViewStatePropertyBag::_ReadInheritBag(
+ LPCWSTR pszPropName,
+ VARIANT *pvari,
+ IErrorLog *pErrorLog)
+{
+ if (!_EnsureInheritBag(STGM_READ, IID_IPropertyBag))
+ return E_FAIL;
+
+ return m_pInheritBag->Read(pszPropName, pvari, pErrorLog);
+}
+
+HRESULT
+CViewStatePropertyBag::_ReadUpgradeBag(
+ LPCWSTR pszPropName,
+ VARIANT *pvari,
+ IErrorLog *pErrorLog)
+{
+ if (!_EnsureUpgradeBag(STGM_READ, IID_IPropertyBag))
+ return E_FAIL;
+
+ return m_pUpgradeBag->Read(pszPropName, pvari, pErrorLog);
+}
+
+HRESULT
+CViewStatePropertyBag::_ReadUserDefaultsBag(
+ LPCWSTR pszPropName,
+ VARIANT *pvari,
+ IErrorLog *pErrorLog)
+{
+ if (!_EnsureUserDefaultsBag(STGM_READ, IID_IPropertyBag))
+ return E_FAIL;
+
+ return m_pUserDefaultsBag->Read(pszPropName, pvari, pErrorLog);
+}
+
+HRESULT
+CViewStatePropertyBag::_ReadFolderDefaultsBag(
+ LPCWSTR pszPropName,
+ VARIANT *pvari,
+ IErrorLog *pErrorLog)
+{
+ if (!_EnsureFolderDefaultsBag(STGM_READ, IID_IPropertyBag))
+ return E_FAIL;
+
+ return m_pFolderDefaultsBag->Read(pszPropName, pvari, pErrorLog);
+}
+
+HRESULT
+CViewStatePropertyBag::_ReadGlobalDefaultsBag(
+ LPCWSTR pszPropName,
+ VARIANT *pvari,
+ IErrorLog *pErrorLog)
+{
+ if (!_EnsureGlobalDefaultsBag(STGM_READ, IID_IPropertyBag))
+ return E_FAIL;
+
+ return m_pGlobalDefaultsBag->Read(pszPropName, pvari, pErrorLog);
+}
+
STDMETHODIMP
CViewStatePropertyBag::Read(
_In_z_ LPCWSTR pszPropName,
_Inout_ VARIANT *pvari,
_Inout_opt_ IErrorLog *pErrorLog)
{
- FIXME("Stub\n");
- return E_NOTIMPL;
+ if ((m_dwVspbFlags & SHGVSPB_NOAUTODEFAULTS) || (m_dwVspbFlags &
SHGVSPB_INHERIT))
+ {
+ if (!_EnsureReadBag(STGM_READ, IID_IPropertyBag))
+ return E_FAIL;
+
+ return m_pReadBag->Read(pszPropName, pvari, pErrorLog);
+ }
+
+ HRESULT hr = _ReadPidlBag(pszPropName, pvari, pErrorLog);
+ if (SUCCEEDED(hr))
+ return hr;
+
+ hr = _ReadInheritBag(pszPropName, pvari, pErrorLog);
+ if (SUCCEEDED(hr))
+ return hr;
+
+ hr = _ReadUpgradeBag(pszPropName, pvari, pErrorLog);
+ if (SUCCEEDED(hr))
+ return hr;
+
+ hr = _ReadUserDefaultsBag(pszPropName, pvari, pErrorLog);
+ if (SUCCEEDED(hr))
+ return hr;
+
+ hr = _ReadFolderDefaultsBag(pszPropName, pvari, pErrorLog);
+ if (SUCCEEDED(hr))
+ return hr;
+
+ return _ReadGlobalDefaultsBag(pszPropName, pvari, pErrorLog);
}
static BOOL SHIsRemovableDrive(LPCITEMIDLIST pidl)
@@ -1508,17 +1785,17 @@ SHGetViewStatePropertyBag(
CComPtr<CViewStatePropertyBag> pBag(new CViewStatePropertyBag());
hr = pBag->Init(pidl, bag_name, flags);
- if (SUCCEEDED(hr))
- {
- g_pCachedBag.Attach(pBag);
-
- hr = g_pCachedBag->QueryInterface(riid, ppv);
- }
- else
+ if (FAILED(hr))
{
ERR("0x%08X\n", hr);
+ ::LeaveCriticalSection(&g_csBagCacheLock);
+ return hr;
}
+ g_pCachedBag.Attach(pBag);
+
+ hr = g_pCachedBag->QueryInterface(riid, ppv);
+
::LeaveCriticalSection(&g_csBagCacheLock);
return hr;
}