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