shell32 patch 12
Martin Fuchs
martin-fuchs at gmx.net
Tue Jan 20 16:00:05 CST 2004
This patch is based on work of Ge van Geldorp <ge at gse.nl> and me.
Changelog:
reimplementation of SHGetPathFromIDListA/W() using the new helper
functions SHELL_GetPathFromIDListA/W(). The new implementation avoids to
use IShellFolder::GetDisplayNameOf(), so that it behaves like the following:
- return the absolute file system path, not relative to the dekstop
- return FALSE as error code if the path can not converted in a valid file system path
- don't return virtual CLSID paths
Note:
The two helper functions will we called from other places in following patches, so they
are declared in the header file.
Index: pidl.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/pidl.c,v
retrieving revision 1.96
diff -u -p -d -r1.96 pidl.c
--- pidl.c 18 Jan 2004 22:08:46 -0000 1.96
+++ pidl.c 20 Jan 2004 21:59:18 -0000
@@ -1213,6 +1213,59 @@ HRESULT WINAPI SHGetDataFromIDListW(LPSH
}
/*************************************************************************
+ * 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 && pstr<end) {
+ if (_ILIsSpecialFolder(pidl))
+ {hr = E_INVALIDARG; break;}
+
+ txt = _ILGetTextPointer(pidl);
+ if (!txt)
+ {hr = E_INVALIDARG; break;}
+
+ lstrcpynA(pstr, txt, end-pstr);
+
+ pidl = ILGetNext(pidl);
+ if (!pidl)
+ {hr = E_INVALIDARG; break;}
+
+ if (!pidl->mkid.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, S_OK);
+ return hr;
+}
+
+/*************************************************************************
* SHGetPathFromIDListA [SHELL32.@][NT 4.0: SHELL32.220]
*
* PARAMETERS
@@ -1230,61 +1283,86 @@ HRESULT WINAPI SHGetDataFromIDListW(LPSH
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;
+ 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);
- TRACE_(shell)("-- %s, 0x%08lx\n",pszPath, hr);
- return SUCCEEDED(hr);
+ if (SUCCEEDED(hr)) {
+ LPSTR txt;
+
+ while(pidl && pidl->mkid.cb && pstr<end) {
+ if (_ILIsSpecialFolder(pidl))
+ {hr = E_INVALIDARG; break;}
+
+ txt = _ILGetTextPointer(pidl);
+ if (!txt)
+ {hr = E_INVALIDARG; break;}
+
+ if (!MultiByteToWideChar(CP_ACP, 0, txt, -1, pstr, uOutSize))
+ {hr = E_OUTOFMEMORY; break;}
+
+ pidl = ILGetNext(pidl);
+ if (!pidl)
+ {hr = E_INVALIDARG; break;}
+
+ if (!pidl->mkid.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;
-
- 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);
- }
+ if (!pidl)
+ return FALSE;
- /* 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);
Index: pidl.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/pidl.h,v
retrieving revision 1.33
diff -u -p -d -r1.33 pidl.h
--- pidl.h 18 Jan 2004 22:08:46 -0000 1.33
+++ pidl.h 20 Jan 2004 21:59:18 -0000
@@ -210,4 +210,7 @@ LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEM
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
More information about the wine-patches
mailing list