https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a3e6ae2e8a82a94b0d9984463621c20c5b4dab26
commit a3e6ae2e8a82a94b0d9984463621c20c5b4dab26 Author: Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com> AuthorDate: Fri Aug 25 07:57:22 2023 +0900 Commit: GitHub <nore...@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; }