[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)
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);
}
@ -677,7 +681,7 @@ HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFl
else
HCR_GetClassNameW(CLSID_ShellDesktop, pszPath, MAX_PATH);
}
else if (_ILIsPidlSimple (pidl))
else
{
int cLen = 0;
@ -710,12 +714,6 @@ HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFl
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))
{

View file

@ -483,6 +483,11 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla
if (!strRet)
return E_INVALIDARG;
if (!_ILIsPidlSimple (pidl))
{
return SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, strRet);
}
pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
if (!pszPath)
return E_OUTOFMEMORY;
@ -496,7 +501,7 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla
pszPath[1] = ':';
SHELL32_GUIDToStringW(CLSID_MyComputer, &pszPath[2]);
}
else if (_ILIsPidlSimple(pidl))
else
{
if (_ILIsSpecialFolder(pidl))
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;
}
}
else
{
/* Complex pidl. Let the child folder do the work */
hr = SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, pszPath, MAX_PATH);
}
if (SUCCEEDED(hr))
{

View file

@ -591,67 +591,47 @@ void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags)
HRESULT WINAPI CFSFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl,
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)
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)
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) &&
(GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
{
if (sPathTarget)
lstrcpynW(pszPath, sPathTarget, MAX_PATH);
}
else
hr = E_INVALIDARG; /* pidl has to contain exactly one non null SHITEMID */
lstrcpynW(pszPath, sPathTarget, MAX_PATH);
PathAddBackslashW(pszPath);
len = wcslen(pszPath);
}
else if (_ILIsPidlSimple(pidl))
{
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);
_ILSimpleGetTextW(pidl, pszPath + len, MAX_PATH + 1 - len);
if (!_ILIsFolder(pidl)) SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
if (SUCCEEDED(hr)) {
/* Win9x always returns ANSI strings, NT always returns Unicode strings */
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);
strRet->uType = STRRET_WSTR;
strRet->pOleStr = pszPath;
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);
HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut,
LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes);
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPWSTR szOut,
DWORD dwOutLen);
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet);
HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
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.
*/
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf,
LPCITEMIDLIST pidl, DWORD dwFlags, LPWSTR szOut, DWORD dwOutLen)
LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
{
LPITEMIDLIST pidlFirst;
HRESULT hr = E_INVALIDARG;
LPITEMIDLIST pidlFirst = ILCloneFirst(pidl);
if (!pidlFirst)
return E_OUTOFMEMORY;
TRACE ("(%p)->(pidl=%p 0x%08x %p 0x%08x)\n", psf, pidl, dwFlags, szOut, dwOutLen);
pdump (pidl);
pidlFirst = ILCloneFirst(pidl);
if (pidlFirst)
CComPtr<IShellFolder> psfChild;
HRESULT hr = psf->BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild));
if (SUCCEEDED (hr))
{
CComPtr<IShellFolder> psfChild;
hr = psf->BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild));
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));
hr = psfChild->GetDisplayNameOf(ILGetNext (pidl), dwFlags, strRet);
}
ILFree (pidlFirst);
return hr;
}
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);
if (!strRet)
return E_INVALIDARG;
LPWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
if (!pszPath)
return E_OUTOFMEMORY;
if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
/* First of all check if we need to query the name from the child item */
if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING &&
GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL)
{
int bWantsForParsing;
@ -408,32 +388,38 @@ HRESULT SHELL32_GetDisplayNameOfGUIDItem(IShellFolder2* psf, LPCWSTR pszFolderPa
}
}
if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
bWantsForParsing)
if (bWantsForParsing)
{
/*
* we need the filesystem path to the destination folder.
* Only the folder itself can know it
*/
hr = SHELL32_GetDisplayNameOfChild (psf, pidl, dwFlags,
pszPath,
MAX_PATH);
* we need the filesystem path to the destination folder.
* Only the folder itself can know it
*/
return SHELL32_GetDisplayNameOfChild (psf, pidl, dwFlags, strRet);
}
else
{
wcscpy(pszPath, pszFolderPath);
PWCHAR pItemName = &pszPath[wcslen(pszPath)];
}
/* parsing name like ::{...} */
pItemName[0] = ':';
pItemName[1] = ':';
SHELL32_GUIDToStringW (*clsid, &pItemName[2]);
}
/* Allocate the buffer for the result */
LPWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
if (!pszPath)
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
{
/* user friendly name */
HCR_GetClassNameW (*clsid, pszPath, MAX_PATH);
if (!HCR_GetClassNameW (*clsid, pszPath, MAX_PATH))
hr = E_FAIL;
}
if (SUCCEEDED(hr))