SHGetPathFromIDList problem

Ge van Geldorp gvg at reactos.com
Fri Aug 12 10:19:25 CDT 2005


Since this patch: http://www.winehq.org/hypermail/wine-cvs/2005/06/0338.html
SHGetPathFromIDList() seems broken. The problem is that files stored in the
Desktop directory don't get the path to the Desktop directory prepended.
I've tried to fix it in the attached patch and added a testcase, but the shell
COM interfaces easily confuse me, so perhaps someone with a better understanding
of this stuff should look it over before I submit it to wine-patches.

Ge van Geldorp.

Index: dlls/shell32/pidl.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/pidl.c,v
retrieving revision 1.133
diff -u -r1.133 pidl.c
--- dlls/shell32/pidl.c	8 Jul 2005 14:18:32 -0000	1.133
+++ dlls/shell32/pidl.c	12 Aug 2005 15:04:05 -0000
@@ -1242,6 +1242,7 @@
 BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
 {
     HRESULT hr;
+    BOOL result;
     LPCITEMIDLIST pidlLast;
     LPSHELLFOLDER psfFolder;
     DWORD dwAttributes;
@@ -1258,13 +1259,34 @@
 
     dwAttributes = SFGAO_FILESYSTEM;
     hr = IShellFolder_GetAttributesOf(psfFolder, 1, &pidlLast, &dwAttributes);
-    if (FAILED(hr) || !(dwAttributes & SFGAO_FILESYSTEM)) return FALSE;
+    if (FAILED(hr) || !(dwAttributes & SFGAO_FILESYSTEM)) {
+        IShellFolder_Release(psfFolder);
+        ILFree((LPITEMIDLIST) pidlLast);
+        return FALSE;
+    }
                 
     hr = IShellFolder_GetDisplayNameOf(psfFolder, pidlLast, SHGDN_FORPARSING, &strret);
-    if (FAILED(hr)) return FALSE;
-
-    hr = StrRetToBufW(&strret, pidlLast, pszPath, MAX_PATH);
     IShellFolder_Release(psfFolder);
+    if (FAILED(hr)) {
+        ILFree((LPITEMIDLIST) pidlLast);
+        return FALSE;
+    }
+
+    /* Check for a PIDL rooted at desktop level */
+    if (_ILIsValue(pidl) || _ILIsFolder(pidl)) {
+        result = SHGetSpecialFolderPathW(NULL, pszPath, CSIDL_DESKTOPDIRECTORY, FALSE);
+        if (! result) {
+            ILFree((LPITEMIDLIST) pidlLast);
+            return FALSE;
+        }
+        PathAddBackslashW(pszPath);
+    } else {
+        pszPath[0] = '\0';
+    }
+
+    hr = StrRetToBufW(&strret, pidlLast, pszPath + lstrlenW(pszPath),
+                      MAX_PATH - lstrlenW(pszPath));
+    ILFree((LPITEMIDLIST) pidlLast);
 
     TRACE_(shell)("-- %s, 0x%08lx\n",debugstr_w(pszPath), hr);
     return SUCCEEDED(hr);
Index: dlls/shell32/tests/shlfolder.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/tests/shlfolder.c,v
retrieving revision 1.29
diff -u -r1.29 shlfolder.c
--- dlls/shell32/tests/shlfolder.c	12 Aug 2005 10:33:37 -0000	1.29
+++ dlls/shell32/tests/shlfolder.c	12 Aug 2005 15:04:06 -0000
@@ -584,6 +584,11 @@
     WCHAR wszMyComputer[] = { 
         ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
         'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
+    WCHAR wszFileName[MAX_PATH];
+    LPITEMIDLIST pidlTestFile;
+    HANDLE hTestFile;
+    static WCHAR wszTestFile[] = {
+        'w','i','n','e','t','e','s','t','.','f','o','o',0 };
 
     if(!pSHGetSpecialFolderPathW) return;
 
@@ -604,15 +609,52 @@
 
     hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyComputer, NULL, &pidlMyComputer, NULL);
     ok (SUCCEEDED(hr), "Desktop's ParseDisplayName failed to parse MyComputer's CLSID! hr = %08lx\n", hr);
-    IShellFolder_Release(psfDesktop);
-    if (FAILED(hr)) return;
+    if (FAILED(hr)) {
+        IShellFolder_Release(psfDesktop);
+        return;
+    }
 
     SetLastError(0xdeadbeef);
     result = SHGetPathFromIDListW(pidlMyComputer, wszPath);
     ok (!result, "SHGetPathFromIDList succeeded where it shouldn't!\n");
     ok (GetLastError()==0xdeadbeef, "SHGetPathFromIDList shouldn't set last error! Last error: %08lx\n", GetLastError());
+    if (result) {
+        IShellFolder_Release(psfDesktop);
+        return;
+    }
 
     IMalloc_Free(ppM, pidlMyComputer);
+
+    result = pSHGetSpecialFolderPathW(NULL, wszFileName, CSIDL_DESKTOPDIRECTORY, FALSE);
+    ok(result, "SHGetSpecialFolderPathW failed! Last error: %08lx\n", GetLastError());
+    if (!result) {
+        IShellFolder_Release(psfDesktop);
+        return;
+    }
+    PathAddBackslashW(wszFileName);
+    lstrcatW(wszFileName, wszTestFile);
+    hTestFile = CreateFileW(wszFileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
+    ok(hTestFile != INVALID_HANDLE_VALUE, "CreateFileW failed! Last error: %08lx\n", GetLastError());
+    if (hTestFile == INVALID_HANDLE_VALUE) {
+        IShellFolder_Release(psfDesktop);
+        return;
+    }
+    CloseHandle(hTestFile);
+
+    hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszTestFile, NULL, &pidlTestFile, NULL);
+    ok (SUCCEEDED(hr), "Desktop's ParseDisplayName failed to parse filename hr = %08lx\n", hr);
+    IShellFolder_Release(psfDesktop);
+    DeleteFileW(wszFileName);
+    if (FAILED(hr)) {
+        IMalloc_Free(ppM, pidlTestFile);
+        return;
+    }
+
+    result = SHGetPathFromIDListW(pidlTestFile, wszPath);
+    ok(result, "SHGetPathFromIDListW failed! Last error: %08lx\n", GetLastError());
+    IMalloc_Free(ppM, pidlTestFile);
+    if (!result) return;
+    ok(0 == lstrcmpW(wszFileName, wszPath), "SHGetPathFromIDListW returned incorrect path for file placed on desktop\n");
 }
 
 static void test_EnumObjects_and_CompareIDs(void)



More information about the wine-devel mailing list