From aa43d0162743b880f59343a1226f2938d45f7d6b Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 21 Jan 2004 23:50:26 +0000 Subject: [PATCH] Authors: Martin Fuchs , Ge van Geldorp Reimplementation of SHGetPathFromIDListA/W() using the new helper functions SHELL_GetPathFromIDListA/W(). The new implementation avoids using IShellFolder::GetDisplayNameOf(), so that it - returns the absolute file system path, not relative to the dekstop - returns FALSE as error code if the path can not converted in a valid file system path - doesn't return virtual CLSID paths --- dlls/shell32/pidl.c | 148 +++++++++++++++++++++++++++++++++----------- dlls/shell32/pidl.h | 3 + 2 files changed, 116 insertions(+), 35 deletions(-) diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c index 3179fd33d08..d03d3a3d70c 100644 --- a/dlls/shell32/pidl.c +++ b/dlls/shell32/pidl.c @@ -1274,6 +1274,59 @@ HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int n return E_INVALIDARG; } +/************************************************************************* + * SHELL_GetPathFromIDListA + */ +HRESULT SHELL_GetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize) +{ + LPSTR pstr = pszPath; + LPSTR end = pszPath + uOutSize; + HRESULT hr = S_OK; + + /* One case is a PIDL rooted at desktop level */ + if (_ILIsValue(pidl) || _ILIsFolder(pidl)) { + hr = SHGetSpecialFolderPathA(0, pstr, CSIDL_DESKTOP, FALSE); + + if (SUCCEEDED(hr)) + pstr = PathAddBackslashA(pstr); + } + /* The only other valid case is a item ID list beginning at "My Computer" */ + else if (_ILIsMyComputer(pidl)) + pidl = ILGetNext(pidl); + + if (SUCCEEDED(hr)) { + LPSTR txt; + + while(pidl && pidl->mkid.cb && pstrmkid.cb) { + /* We are at the end and successfully converted the complete PIDL. */ + break; + } + + pstr = PathAddBackslashA(pstr); + if (!pstr) + {hr = E_INVALIDARG; break;} + } + } else + hr = E_INVALIDARG; + + TRACE_(shell)("-- %s, 0x%08lx\n", pszPath, hr); + return hr; +} + /************************************************************************* * SHGetPathFromIDListA [SHELL32.@][NT 4.0: SHELL32.220] * @@ -1292,61 +1345,86 @@ HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int n BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath) { HRESULT hr; - STRRET str; - LPSHELLFOLDER shellfolder; TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath); pdump(pidl); if (!pidl) - return FALSE; + return FALSE; - hr = SHGetDesktopFolder(&shellfolder); - if (SUCCEEDED (hr)) { - hr = IShellFolder_GetDisplayNameOf(shellfolder, pidl, SHGDN_FORPARSING, &str); - if(SUCCEEDED(hr)) { - StrRetToStrNA (pszPath, MAX_PATH, &str, pidl); - } - IShellFolder_Release(shellfolder); - } + hr = SHELL_GetPathFromIDListA(pidl, pszPath, MAX_PATH); - /* don't allow to return displaynames of the form "::{guid}" */ - if (pszPath[0]==':' && pszPath[1]==':') { - *pszPath = '\0'; - return FALSE; - } - - TRACE_(shell)("-- %s, 0x%08lx\n",pszPath, hr); return SUCCEEDED(hr); } + +/************************************************************************* + * SHELL_GetPathFromIDListW + */ +HRESULT SHELL_GetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize) +{ + LPWSTR pstr = pszPath; + LPWSTR end = pszPath + uOutSize; + HRESULT hr = S_OK; + + /* One case is a PIDL rooted at desktop level */ + if (_ILIsValue(pidl) || _ILIsFolder(pidl)) { + hr = SHGetSpecialFolderPathW(0, pstr, CSIDL_DESKTOP, FALSE); + + if (SUCCEEDED(hr)) + pstr = PathAddBackslashW(pstr); + } + /* The only other valid case is a item ID list beginning at "My Computer" */ + else if (_ILIsMyComputer(pidl)) + pidl = ILGetNext(pidl); + + if (SUCCEEDED(hr)) { + LPSTR txt; + + while(pidl && pidl->mkid.cb && pstrmkid.cb) { + /* We are at the end and successfully converted the complete PIDL. */ + break; + } + + pstr = PathAddBackslashW(pstr); + if (!pstr) + {hr = E_INVALIDARG; break;} + } + } else + hr = E_INVALIDARG; + + TRACE_(shell)("-- %s, 0x%08lx\n", debugstr_w(pszPath), hr); + return hr; +} + /************************************************************************* * SHGetPathFromIDListW [SHELL32.@] */ BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath) { HRESULT hr; - STRRET str; - LPSHELLFOLDER shellfolder; TRACE_(shell)("(pidl=%p,%p)\n", pidl, debugstr_w(pszPath)); pdump(pidl); - if (!pidl) return FALSE; + if (!pidl) + return FALSE; - hr = SHGetDesktopFolder(&shellfolder); - if (SUCCEEDED(hr)) { - hr = IShellFolder_GetDisplayNameOf(shellfolder, pidl, SHGDN_FORPARSING, &str); - if (SUCCEEDED(hr)) { - StrRetToStrNW(pszPath, MAX_PATH, &str, pidl); - } - IShellFolder_Release(shellfolder); - } - - /* don't allow to return displaynames of the form "::{guid}" */ - if (pszPath[0]==':' && pszPath[1]==':') { - *pszPath = '\0'; - return FALSE; - } + hr = SHELL_GetPathFromIDListW(pidl, pszPath, MAX_PATH); TRACE_(shell)("-- %s, 0x%08lx\n",debugstr_w(pszPath), hr); return SUCCEEDED(hr); diff --git a/dlls/shell32/pidl.h b/dlls/shell32/pidl.h index 2d6f0e2da74..bf8f33e5a04 100644 --- a/dlls/shell32/pidl.h +++ b/dlls/shell32/pidl.h @@ -210,4 +210,7 @@ LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida); BOOL WINAPI ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type); BOOL WINAPI ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type); +HRESULT SHELL_GetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize); +HRESULT SHELL_GetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize); + #endif