From 8da2ae937438b8d0995198f53cb51d6efa923b1d Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Mon, 31 Aug 2015 11:28:24 +0000 Subject: [PATCH] [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 --- .../win32/shell32/folders/CDesktopFolder.cpp | 14 ++- .../win32/shell32/folders/CDrivesFolder.cpp | 12 +-- .../dll/win32/shell32/folders/CFSFolder.cpp | 80 +++++++---------- reactos/dll/win32/shell32/shfldr.h | 3 +- reactos/dll/win32/shell32/shlfolder.cpp | 90 ++++++++----------- 5 files changed, 81 insertions(+), 118 deletions(-) diff --git a/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp b/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp index 5059ea6f2ef..f196873c417 100644 --- a/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp @@ -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)) { diff --git a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp index 39c8a5ed495..3f24376be94 100644 --- a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -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)) { diff --git a/reactos/dll/win32/shell32/folders/CFSFolder.cpp b/reactos/dll/win32/shell32/folders/CFSFolder.cpp index e1c5b4a9ffb..4ac9c50714c 100644 --- a/reactos/dll/win32/shell32/folders/CFSFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CFSFolder.cpp @@ -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; } /************************************************************************** diff --git a/reactos/dll/win32/shell32/shfldr.h b/reactos/dll/win32/shell32/shfldr.h index 7463753e6d6..88ea7c595bb 100644 --- a/reactos/dll/win32/shell32/shfldr.h +++ b/reactos/dll/win32/shell32/shfldr.h @@ -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); diff --git a/reactos/dll/win32/shell32/shlfolder.cpp b/reactos/dll/win32/shell32/shlfolder.cpp index f2ecbe7e35f..f764a45ee62 100644 --- a/reactos/dll/win32/shell32/shlfolder.cpp +++ b/reactos/dll/win32/shell32/shlfolder.cpp @@ -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 psfChild; + HRESULT hr = psf->BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild)); + if (SUCCEEDED (hr)) { - CComPtr 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))