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