[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
This commit is contained in:
Giannis Adamopoulos 2015-08-31 23:44:02 +00:00
parent 5d50aaffdd
commit bb8a6e700c
5 changed files with 79 additions and 45 deletions

View file

@ -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 );
}
/**************************************************************************

View file

@ -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);
}
/**************************************************************************

View file

@ -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);
}
/**************************************************************************

View file

@ -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);

View file

@ -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<IShellFolder> pShellFolder;
@ -163,8 +163,7 @@ static HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot,
CComPtr<IPersistFolder> ppf;
CComPtr<IPersistFolder3> 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<IShellFolder> 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<IPersistFolder> 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<IShellFolder> psf;
hr = pFolder->QueryInterface(IID_PPV_ARG(IShellFolder, &psf));
if (FAILED(hr))