From bb8a6e700ce862004d8c29a2ac0fe3132f883d43 Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Mon, 31 Aug 2015 23:44:02 +0000 Subject: [PATCH] [SHELL32] - Rename SHELL32_BindToChild to SHELL32_BindToFS. Do not let it be used for guid items any more. Split SHELL32_GetCLSIDForDirectoryout of it and call it only when needed. - Fix callers to use SHELL32_BindToGuidItem for guid items. - Fix a bug in CFSFolder which marked folder items as files when a binding context was used. svn path=/trunk/; revision=68885 --- .../win32/shell32/folders/CDesktopFolder.cpp | 5 +- .../win32/shell32/folders/CDrivesFolder.cpp | 2 +- .../dll/win32/shell32/folders/CFSFolder.cpp | 9 +- reactos/dll/win32/shell32/shfldr.h | 2 +- reactos/dll/win32/shell32/shlfolder.cpp | 106 +++++++++++------- 5 files changed, 79 insertions(+), 45 deletions(-) diff --git a/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp b/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp index 4708b0b15aa..570f77c34be 100644 --- a/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp @@ -446,7 +446,10 @@ HRESULT WINAPI CDesktopFolder::BindToObject( TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut); - return SHELL32_BindToChild( pidlRoot, sPathTarget, pidl, riid, ppvOut ); + if (_ILIsSpecialFolder(pidl)) + return SHELL32_BindToGuidItem(pidlRoot, pidl, pbcReserved, riid, ppvOut); + + return SHELL32_BindToFS( pidlRoot, sPathTarget, pidl, riid, ppvOut ); } /************************************************************************** diff --git a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp index 3f24376be94..3ed7a73872c 100644 --- a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -272,7 +272,7 @@ HRESULT WINAPI CDrivesFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcRese if (_ILIsSpecialFolder(pidl)) return SHELL32_BindToGuidItem(pidlRoot, pidl, pbcReserved, riid, ppvOut); - return SHELL32_BindToChild(pidlRoot, NULL, pidl, riid, ppvOut); + return SHELL32_BindToFS(pidlRoot, NULL, pidl, riid, ppvOut); } /************************************************************************** diff --git a/reactos/dll/win32/shell32/folders/CFSFolder.cpp b/reactos/dll/win32/shell32/folders/CFSFolder.cpp index 4ac9c50714c..72587c832c7 100644 --- a/reactos/dll/win32/shell32/folders/CFSFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CFSFolder.cpp @@ -207,6 +207,13 @@ HRESULT WINAPI CFSFolder::ParseDisplayName(HWND hwndOwner, pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, szElement); if (pidlTemp != NULL) { + /* We are creating an id list without ensuring that the items exist. + If we have a remaining path, this must be a folder. + We have to do it now because it is set as a file by default */ + if (szNext) + { + pidlTemp->mkid.abID[0] = PT_FOLDER; + } hr = S_OK; } else @@ -280,7 +287,7 @@ HRESULT WINAPI CFSFolder::BindToObject( TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl, pbc, shdebugstr_guid(&riid), ppvOut); - return SHELL32_BindToChild(pidlRoot, sPathTarget, pidl, riid, ppvOut); + return SHELL32_BindToFS(pidlRoot, sPathTarget, pidl, riid, ppvOut); } /************************************************************************** diff --git a/reactos/dll/win32/shell32/shfldr.h b/reactos/dll/win32/shell32/shfldr.h index 88ea7c595bb..841963dc514 100644 --- a/reactos/dll/win32/shell32/shfldr.h +++ b/reactos/dll/win32/shell32/shfldr.h @@ -41,7 +41,7 @@ HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes); HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet); -HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, +HRESULT SHELL32_BindToFS (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut); HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); diff --git a/reactos/dll/win32/shell32/shlfolder.cpp b/reactos/dll/win32/shell32/shlfolder.cpp index f764a45ee62..94c5c5334f3 100644 --- a/reactos/dll/win32/shell32/shlfolder.cpp +++ b/reactos/dll/win32/shell32/shlfolder.cpp @@ -149,7 +149,7 @@ HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, * In this case the absolute path is built from pidlChild (eg. C:) */ static HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, - LPCITEMIDLIST pidlChild, REFCLSID clsid, LPVOID * ppvOut) + LPCITEMIDLIST pidlChild, REFCLSID clsid, IShellFolder** ppsfOut) { HRESULT hr; CComPtr pShellFolder; @@ -163,8 +163,7 @@ static HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, CComPtr ppf; CComPtr ppf3; - if ((_ILIsFolder(pidlChild) || _ILIsDrive(pidlChild)) && - SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3)))) + if (SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3)))) { PERSIST_FOLDER_TARGET_INFO ppfti; @@ -198,15 +197,35 @@ static HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, ILFree (pidlAbsolute); } - *ppvOut = pShellFolder.Detach(); + *ppsfOut = pShellFolder.Detach(); - TRACE ("-- (%p) ret=0x%08x\n", *ppvOut, hr); + TRACE ("-- (%p) ret=0x%08x\n", *ppsfOut, hr); return hr; } +void SHELL32_GetCLSIDForDirectory(LPCWSTR pathRoot, LPCITEMIDLIST pidl, CLSID* pclsidFolder) +{ + static const WCHAR wszDotShellClassInfo[] = { + '.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0 }; + static const WCHAR wszCLSID[] = {'C','L','S','I','D',0}; + WCHAR wszCLSIDValue[CHARS_IN_GUID], wszFolderPath[MAX_PATH], *pwszPathTail = wszFolderPath; + + /* see if folder CLSID should be overridden by desktop.ini file */ + if (pathRoot) { + lstrcpynW(wszFolderPath, pathRoot, MAX_PATH); + pwszPathTail = PathAddBackslashW(wszFolderPath); + } + + _ILSimpleGetTextW(pidl,pwszPathTail,MAX_PATH - (int)(pwszPathTail - wszFolderPath)); + + if (SHELL32_GetCustomFolderAttributeFromPath (wszFolderPath, + wszDotShellClassInfo, wszCLSID, wszCLSIDValue, CHARS_IN_GUID)) + CLSIDFromString (wszCLSIDValue, pclsidFolder); +} + /*********************************************************************** - * SHELL32_BindToChild [Internal] + * SHELL32_BindToFS [Internal] * * Common code for IShellFolder_BindToObject. * @@ -222,49 +241,40 @@ static HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, * This function makes special assumptions on the shell namespace, which * means you probably can't use it for your IShellFolder implementation. */ -HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, +HRESULT SHELL32_BindToFS (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut) { - static const WCHAR wszDotShellClassInfo[] = { - '.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0 }; - - GUID const *clsid; CComPtr pSF; HRESULT hr; - LPITEMIDLIST pidlChild; + LPCITEMIDLIST pidlChild; if (!pidlRoot || !ppvOut || !pidlComplete || !pidlComplete->mkid.cb) return E_INVALIDARG; + if (_ILIsValue(pidlComplete)) + { + ERR("Binding to file is unimplemented\n"); + return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + } + if (!_ILIsFolder(pidlComplete) && !_ILIsDrive(pidlComplete)) + { + ERR("Got an unknown type of pidl!\n"); + return E_FAIL; + } + *ppvOut = NULL; - pidlChild = ILCloneFirst (pidlComplete); + pidlChild = (_ILIsPidlSimple (pidlComplete)) ? pidlComplete : ILCloneFirst (pidlComplete); - if ((clsid = _ILGetGUIDPointer (pidlChild))) { - /* virtual folder */ - hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, *clsid, (LPVOID *)&pSF); - } else { - /* file system folder */ - CLSID clsidFolder = CLSID_ShellFSFolder; - static const WCHAR wszCLSID[] = {'C','L','S','I','D',0}; - WCHAR wszCLSIDValue[CHARS_IN_GUID], wszFolderPath[MAX_PATH], *pwszPathTail = wszFolderPath; + CLSID clsidFolder = CLSID_ShellFSFolder; + DWORD attributes = _ILGetFileAttributes(ILFindLastID(pidlChild), NULL, 0); + if ((attributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)) != 0) + SHELL32_GetCLSIDForDirectory(pathRoot, pidlChild, &clsidFolder); - /* see if folder CLSID should be overridden by desktop.ini file */ - if (pathRoot) { - lstrcpynW(wszFolderPath, pathRoot, MAX_PATH); - pwszPathTail = PathAddBackslashW(wszFolderPath); - } + hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, clsidFolder, &pSF); - _ILSimpleGetTextW(pidlChild,pwszPathTail,MAX_PATH - (int)(pwszPathTail - wszFolderPath)); - - if (SHELL32_GetCustomFolderAttributeFromPath (wszFolderPath, - wszDotShellClassInfo, wszCLSID, wszCLSIDValue, CHARS_IN_GUID)) - CLSIDFromString (wszCLSIDValue, &clsidFolder); - - hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, - clsidFolder, (LPVOID *)&pSF); - } - ILFree (pidlChild); + if (pidlChild != pidlComplete) + ILFree ((LPITEMIDLIST)pidlChild); if (SUCCEEDED (hr)) { if (_ILIsPidlSimple (pidlComplete)) { @@ -290,27 +300,41 @@ HRESULT SHELL32_BindToGuidItem(LPCITEMIDLIST pidlRoot, CComPtr pFolder; HRESULT hr; + if (!pidlRoot || !ppvOut || !pidl || !pidl->mkid.cb) + return E_INVALIDARG; + + *ppvOut = NULL; + GUID *pGUID = _ILGetGUIDPointer(pidl); if (!pGUID) { ERR("SHELL32_BindToGuidItem called for non guid item!\n"); - return E_FAIL; + return E_INVALIDARG; } hr = SHCoCreateInstance(NULL, pGUID, NULL, IID_PPV_ARG(IPersistFolder, &pFolder)); if (FAILED(hr)) return hr; - hr = pFolder->Initialize(ILCombine(pidlRoot, pidl)); - if (FAILED(hr)) - return hr; - if (_ILIsPidlSimple (pidl)) { + hr = pFolder->Initialize(ILCombine(pidlRoot, pidl)); + if (FAILED(hr)) + return hr; + return pFolder->QueryInterface(riid, ppvOut); } else { + LPITEMIDLIST pidlChild = ILCloneFirst (pidl); + if (!pidlChild) + return E_OUTOFMEMORY; + + hr = pFolder->Initialize(ILCombine(pidlRoot, pidlChild)); + ILFree(pidlChild); + if (FAILED(hr)) + return hr; + CComPtr psf; hr = pFolder->QueryInterface(IID_PPV_ARG(IShellFolder, &psf)); if (FAILED(hr))