[SHELL32]

- Make SHELL32_GetDisplayNameOfChild return the result via a STRRET. Fix all callers accordingly.
- Avoid any heap allocations if a shell folder needs to forward the GetDisplayNameOf call to a child.

svn path=/trunk/; revision=68877
This commit is contained in:
Giannis Adamopoulos 2015-08-31 11:28:24 +00:00
parent 8828db039a
commit 8da2ae9374
5 changed files with 81 additions and 118 deletions

View file

@ -660,7 +660,11 @@ HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFl
if (!strRet) if (!strRet)
return E_INVALIDARG; return E_INVALIDARG;
if (!_ILIsDesktop(pidl) && _ILIsPidlSimple(pidl) && _ILIsSpecialFolder(pidl)) if (!_ILIsPidlSimple (pidl))
{
return SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, strRet);
}
else if (!_ILIsDesktop(pidl) && ILIsSpecialFolder(pidl))
{ {
return SHELL32_GetDisplayNameOfGUIDItem(this, L"", pidl, dwFlags, strRet); return SHELL32_GetDisplayNameOfGUIDItem(this, L"", pidl, dwFlags, strRet);
} }
@ -677,7 +681,7 @@ HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFl
else else
HCR_GetClassNameW(CLSID_ShellDesktop, pszPath, MAX_PATH); HCR_GetClassNameW(CLSID_ShellDesktop, pszPath, MAX_PATH);
} }
else if (_ILIsPidlSimple (pidl)) else
{ {
int cLen = 0; int cLen = 0;
@ -710,12 +714,6 @@ HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFl
SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags); SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
} }
} }
else
{
/* a complex pidl, let the subfolder do the work */
hr = SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags,
pszPath, MAX_PATH);
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {

View file

@ -483,6 +483,11 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla
if (!strRet) if (!strRet)
return E_INVALIDARG; return E_INVALIDARG;
if (!_ILIsPidlSimple (pidl))
{
return SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, strRet);
}
pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR)); pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
if (!pszPath) if (!pszPath)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@ -496,7 +501,7 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla
pszPath[1] = ':'; pszPath[1] = ':';
SHELL32_GUIDToStringW(CLSID_MyComputer, &pszPath[2]); SHELL32_GUIDToStringW(CLSID_MyComputer, &pszPath[2]);
} }
else if (_ILIsPidlSimple(pidl)) else
{ {
if (_ILIsSpecialFolder(pidl)) if (_ILIsSpecialFolder(pidl))
return SHELL32_GetDisplayNameOfGUIDItem(this, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", pidl, dwFlags, strRet); return SHELL32_GetDisplayNameOfGUIDItem(this, L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", pidl, dwFlags, strRet);
@ -557,11 +562,6 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla
return E_INVALIDARG; return E_INVALIDARG;
} }
} }
else
{
/* Complex pidl. Let the child folder do the work */
hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, pszPath, MAX_PATH);
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {

View file

@ -591,67 +591,47 @@ void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags)
HRESULT WINAPI CFSFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, HRESULT WINAPI CFSFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl,
DWORD dwFlags, LPSTRRET strRet) DWORD dwFlags, LPSTRRET strRet)
{ {
LPWSTR pszPath;
HRESULT hr = S_OK;
int len = 0;
TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
pdump(pidl);
if (!pidl || !strRet) if (!pidl || !strRet)
return E_INVALIDARG; return E_INVALIDARG;
pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR)); /* If it is a complex pidl, let the child handle it */
if (!_ILIsPidlSimple (pidl)) /* complex pidl */
{
return SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, strRet);
}
else if (!pidl->mkid.cb) /* empty pidl */
{
/* If it is an empty pidl return only the path of the folder */
if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
(GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) &&
sPathTarget)
{
return SHSetStrRet(strRet, sPathTarget);
}
return E_INVALIDARG;
}
int len = 0;
LPWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
if (!pszPath) if (!pszPath)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (_ILIsDesktop(pidl)) /* empty pidl */ if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
(GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) &&
sPathTarget)
{ {
if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) && lstrcpynW(pszPath, sPathTarget, MAX_PATH);
(GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER)) PathAddBackslashW(pszPath);
{ len = wcslen(pszPath);
if (sPathTarget)
lstrcpynW(pszPath, sPathTarget, MAX_PATH);
}
else
hr = E_INVALIDARG; /* pidl has to contain exactly one non null SHITEMID */
} }
else if (_ILIsPidlSimple(pidl)) _ILSimpleGetTextW(pidl, pszPath + len, MAX_PATH + 1 - len);
{ if (!_ILIsFolder(pidl)) SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
(GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) &&
sPathTarget)
{
lstrcpynW(pszPath, sPathTarget, MAX_PATH);
PathAddBackslashW(pszPath);
len = wcslen(pszPath);
}
_ILSimpleGetTextW(pidl, pszPath + len, MAX_PATH + 1 - len);
if (!_ILIsFolder(pidl)) SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
} else
hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, pszPath, MAX_PATH);
if (SUCCEEDED(hr)) { strRet->uType = STRRET_WSTR;
/* Win9x always returns ANSI strings, NT always returns Unicode strings */ strRet->pOleStr = pszPath;
if (GetVersion() & 0x80000000)
{
strRet->uType = STRRET_CSTR;
if (!WideCharToMultiByte(CP_ACP, 0, pszPath, -1, strRet->cStr, MAX_PATH,
NULL, NULL))
strRet->cStr[0] = '\0';
CoTaskMemFree(pszPath);
}
else
{
strRet->uType = STRRET_WSTR;
strRet->pOleStr = pszPath;
}
} else
CoTaskMemFree(pszPath);
TRACE ("-- (%p)->(%s)\n", this, strRet->uType == STRRET_CSTR ? strRet->cStr : debugstr_w(strRet->pOleStr)); TRACE ("-- (%p)->(%s)\n", this, strRet->uType == STRRET_CSTR ? strRet->cStr : debugstr_w(strRet->pOleStr));
return hr; return S_OK;
} }
/************************************************************************** /**************************************************************************

View file

@ -39,8 +39,7 @@ typedef struct {
LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut); LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut);
HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut, HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut,
LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes); LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes);
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPWSTR szOut, HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet);
DWORD dwOutLen);
HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut); LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut);

View file

@ -335,54 +335,34 @@ HRESULT SHELL32_BindToGuidItem(LPCITEMIDLIST pidlRoot,
* virtual folders with the registry key WantsFORPARSING set. * virtual folders with the registry key WantsFORPARSING set.
*/ */
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf,
LPCITEMIDLIST pidl, DWORD dwFlags, LPWSTR szOut, DWORD dwOutLen) LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
{ {
LPITEMIDLIST pidlFirst; LPITEMIDLIST pidlFirst = ILCloneFirst(pidl);
HRESULT hr = E_INVALIDARG; if (!pidlFirst)
return E_OUTOFMEMORY;
TRACE ("(%p)->(pidl=%p 0x%08x %p 0x%08x)\n", psf, pidl, dwFlags, szOut, dwOutLen); CComPtr<IShellFolder> psfChild;
pdump (pidl); HRESULT hr = psf->BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild));
if (SUCCEEDED (hr))
pidlFirst = ILCloneFirst(pidl);
if (pidlFirst)
{ {
CComPtr<IShellFolder> psfChild; hr = psfChild->GetDisplayNameOf(ILGetNext (pidl), dwFlags, strRet);
}
hr = psf->BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild)); ILFree (pidlFirst);
if (SUCCEEDED (hr))
{
STRRET strTemp;
LPITEMIDLIST pidlNext = ILGetNext (pidl);
hr = psfChild->GetDisplayNameOf(pidlNext, dwFlags, &strTemp);
if (SUCCEEDED (hr))
{
if(!StrRetToStrNW (szOut, dwOutLen, &strTemp, pidlNext))
hr = E_FAIL;
}
}
ILFree (pidlFirst);
} else
hr = E_OUTOFMEMORY;
TRACE ("-- ret=0x%08x %s\n", hr, debugstr_w(szOut));
return hr; return hr;
} }
HRESULT SHELL32_GetDisplayNameOfGUIDItem(IShellFolder2* psf, LPCWSTR pszFolderPath, PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet) HRESULT SHELL32_GetDisplayNameOfGUIDItem(IShellFolder2* psf, LPCWSTR pszFolderPath, PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
{ {
HRESULT hr = S_OK; HRESULT hr;
GUID const *clsid = _ILGetGUIDPointer (pidl); GUID const *clsid = _ILGetGUIDPointer (pidl);
if (!strRet) if (!strRet)
return E_INVALIDARG; return E_INVALIDARG;
LPWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR)); /* First of all check if we need to query the name from the child item */
if (!pszPath) if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING &&
return E_OUTOFMEMORY; GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL)
if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
{ {
int bWantsForParsing; int bWantsForParsing;
@ -408,32 +388,38 @@ HRESULT SHELL32_GetDisplayNameOfGUIDItem(IShellFolder2* psf, LPCWSTR pszFolderPa
} }
} }
if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && if (bWantsForParsing)
bWantsForParsing)
{ {
/* /*
* we need the filesystem path to the destination folder. * we need the filesystem path to the destination folder.
* Only the folder itself can know it * Only the folder itself can know it
*/ */
hr = SHELL32_GetDisplayNameOfChild (psf, pidl, dwFlags, return SHELL32_GetDisplayNameOfChild (psf, pidl, dwFlags, strRet);
pszPath,
MAX_PATH);
} }
else }
{
wcscpy(pszPath, pszFolderPath);
PWCHAR pItemName = &pszPath[wcslen(pszPath)];
/* parsing name like ::{...} */ /* Allocate the buffer for the result */
pItemName[0] = ':'; LPWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
pItemName[1] = ':'; if (!pszPath)
SHELL32_GUIDToStringW (*clsid, &pItemName[2]); return E_OUTOFMEMORY;
}
hr = S_OK;
if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
{
wcscpy(pszPath, pszFolderPath);
PWCHAR pItemName = &pszPath[wcslen(pszPath)];
/* parsing name like ::{...} */
pItemName[0] = ':';
pItemName[1] = ':';
SHELL32_GUIDToStringW (*clsid, &pItemName[2]);
} }
else else
{ {
/* user friendly name */ /* user friendly name */
HCR_GetClassNameW (*clsid, pszPath, MAX_PATH); if (!HCR_GetClassNameW (*clsid, pszPath, MAX_PATH))
hr = E_FAIL;
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))