SHELL32: fix SHSimpleIDListFromPath to do the correct thing for non-existing pathes (RESEND)

Mike McCormack mike at codeweavers.com
Fri Feb 25 06:43:55 CST 2005


I haven't changed this patch, except to add test cases.  It depends upon 
the previous patch to make the tests pass.

Mike


ChangeLog:
* fix SHSimpleIDListFromPath to do the correct thing for non-existing pathes
* add simple test cases for IDLists
-------------- next part --------------
Index: dlls/shell32/pidl.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/pidl.c,v
retrieving revision 1.127
diff -u -p -r1.127 pidl.c
--- dlls/shell32/pidl.c	22 Feb 2005 14:50:35 -0000	1.127
+++ dlls/shell32/pidl.c	25 Feb 2005 12:35:44 -0000
@@ -963,71 +963,6 @@ LPITEMIDLIST WINAPI ILCreateFromPathAW (
     return ILCreateFromPathA (path);
 }
 
-/*************************************************************************
- * _ILParsePathW             [internal]
- *
- * Creates an ItemIDList from a path and returns it.
- *
- * PARAMS
- *  path         [I]   path to parse and convert into an ItemIDList
- *  lpFindFile   [I]   pointer to buffer to initialize the FileSystem
- *                     Bind Data object with
- *  bBindCtx     [I]   indicates to create a BindContext and assign a
- *                     FileSystem Bind Data object
- *  ppidl        [O]   the newly create ItemIDList
- *  prgfInOut    [I/O] requested attributes on input and actual
- *                     attributes on return
- *
- * RETURNS
- *  NO_ERROR on success or an OLE error code
- *
- * NOTES
- *  If either lpFindFile is non-NULL or bBindCtx is TRUE, this function
- *  creates a BindContext object and assigns a FileSystem Bind Data object
- *  to it, passing the BindContext to IShellFolder_ParseDisplayName. Each
- *  IShellFolder uses that FileSystem Bind Data object of the BindContext
- *  to pass data about the current path element to the next object. This
- *  is used to avoid having to verify the current path element on disk, so
- *  that creating an ItemIDList from a nonexistent path still can work.
- */
-static HRESULT WINAPI _ILParsePathW(LPCWSTR path, LPWIN32_FIND_DATAW lpFindFile,
-                             BOOL bBindCtx, LPITEMIDLIST *ppidl, LPDWORD prgfInOut)
-{
-    LPSHELLFOLDER pSF = NULL;
-    LPBC pBC = NULL;
-    HRESULT ret;
-
-    TRACE("%s %p %d (%p)->%p (%p)->0x%lx\n", debugstr_w(path), lpFindFile, bBindCtx,
-                                             ppidl, ppidl ? *ppidl : NULL,
-                                             prgfInOut, prgfInOut ? *prgfInOut : 0);
-
-    ret = SHGetDesktopFolder(&pSF);
-    if (FAILED(ret))
-        return ret;
-
-    if (lpFindFile || bBindCtx)
-        ret = IFileSystemBindData_Constructor(lpFindFile, &pBC);
-
-    if (SUCCEEDED(ret))
-    {
-        ret = IShellFolder_ParseDisplayName(pSF, 0, pBC, (LPOLESTR)path, NULL, ppidl, prgfInOut);
-    }
-
-    if (pBC)
-    {
-        IBindCtx_Release(pBC);
-        pBC = NULL;
-    }
-
-    IShellFolder_Release(pSF);
-
-    if (!SUCCEEDED(ret) && ppidl)
-        *ppidl = NULL;
-
-    TRACE("%s %p 0x%lx\n", debugstr_w(path), ppidl ? *ppidl : NULL, prgfInOut ? *prgfInOut : 0);
-
-    return ret;
-}
 
 /*************************************************************************
  * SHSimpleIDListFromPath    [SHELL32.162]
@@ -1047,8 +982,55 @@ static HRESULT WINAPI _ILParsePathW(LPCW
  *  directory flag for those ItemID elements this is known about, eg.
  *  it is not the last element in the ItemIDList or the actual directory
  *  exists on disk.
- *  exported by ordinal.
+ *  Exported by ordinal.
  */
+LPITEMIDLIST WINAPI SHSimpleIDListFromPathW(LPCWSTR path)
+{
+    static const WCHAR szfsbc[] = { 
+        'F','i','l','e',' ','S','y','s','t','e','m',' ',
+        'B','i','n','d',' ','D','a','t','a',0 };
+    IFileSystemBindData *pfsbd = NULL;
+    LPITEMIDLIST pidl = NULL;
+    LPSHELLFOLDER psf = NULL;
+    LPBC pbc = NULL;
+    HRESULT r;
+
+    TRACE("%s\n", debugstr_w(path));
+
+    r = SHGetDesktopFolder(&psf);
+    if (FAILED(r))
+        goto end;
+
+    r = CreateBindCtx(0, &pbc);
+    if (FAILED(r))
+        goto end;
+    
+    pfsbd = IFileSystemBindData_Constructor();
+    if (!pfsbd)
+        goto end;
+
+    r = IBindCtx_RegisterObjectParam(pbc, (LPOLESTR) szfsbc, (IUnknown*) pfsbd);
+    if (FAILED(r))
+        goto end;
+
+    r = IShellFolder_ParseDisplayName( psf, 0, pbc, (LPOLESTR)path,
+                                       NULL, &pidl, NULL );
+
+end:
+    if (pfsbd)
+        IFileSystemBindData_Release(pfsbd);
+
+    if (pbc)
+        IBindCtx_Release(pbc);
+
+    if (psf)
+        IShellFolder_Release(psf);
+
+    TRACE("%s -> %p\n", debugstr_w(path), pidl);
+
+    return pidl;
+}
+
 LPITEMIDLIST WINAPI SHSimpleIDListFromPathA(LPCSTR lpszPath)
 {
     LPITEMIDLIST pidl = NULL;
@@ -1064,21 +1046,8 @@ LPITEMIDLIST WINAPI SHSimpleIDListFromPa
         MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, wPath, len);
     }
 
-    _ILParsePathW(wPath, NULL, TRUE, &pidl, NULL);
-
+    pidl = SHSimpleIDListFromPathW(wPath);
     HeapFree(GetProcessHeap(), 0, wPath);
-    TRACE("%s %p\n", debugstr_a(lpszPath), pidl);
-    return pidl;
-}
-
-LPITEMIDLIST WINAPI SHSimpleIDListFromPathW(LPCWSTR lpszPath)
-{
-    LPITEMIDLIST pidl = NULL;
-
-    TRACE("%s\n", debugstr_w(lpszPath));
-
-    _ILParsePathW(lpszPath, NULL, TRUE, &pidl, NULL);
-    TRACE("%s %p\n", debugstr_w(lpszPath), pidl);
     return pidl;
 }
 
Index: dlls/shell32/shell32_main.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.h,v
retrieving revision 1.92
diff -u -p -r1.92 shell32_main.h
--- dlls/shell32/shell32_main.h	21 Oct 2004 19:59:46 -0000	1.92
+++ dlls/shell32/shell32_main.h	25 Feb 2005 12:35:44 -0000
@@ -90,7 +90,7 @@ HRESULT WINAPI IShellLink_ConstructFromF
 HRESULT WINAPI ISF_Desktop_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
 HRESULT WINAPI ISF_MyComputer_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
 HRESULT WINAPI IDropTargetHelper_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
-HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC *ppV);
+extern IFileSystemBindData* IFileSystemBindData_Constructor(void);
 HRESULT WINAPI IControlPanel_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
 HRESULT WINAPI CPanel_GetIconLocationA(LPITEMIDLIST pidl, LPSTR szIconFile, UINT cchMax, int* piIndex);
 HRESULT WINAPI CPanel_GetIconLocationW(LPITEMIDLIST pidl, LPWSTR szIconFile, UINT cchMax, int* piIndex);
Index: dlls/shell32/shlfsbind.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlfsbind.c,v
retrieving revision 1.13
diff -u -p -r1.13 shlfsbind.c
--- dlls/shell32/shlfsbind.c	23 Feb 2005 15:41:39 -0000	1.13
+++ dlls/shell32/shlfsbind.c	25 Feb 2005 12:35:44 -0000
@@ -47,129 +47,24 @@ typedef struct
     WIN32_FIND_DATAW findFile;
 } IFileSystemBindDataImpl;
 
-static HRESULT WINAPI IFileSystemBindData_fnQueryInterface(IFileSystemBindData *, REFIID, LPVOID*);
-static ULONG WINAPI IFileSystemBindData_fnAddRef(IFileSystemBindData *);
-static ULONG WINAPI IFileSystemBindData_fnRelease(IFileSystemBindData *);
-static HRESULT WINAPI IFileSystemBindData_fnGetFindData(IFileSystemBindData *, WIN32_FIND_DATAW *);
-static HRESULT WINAPI IFileSystemBindData_fnSetFindData(IFileSystemBindData *, const WIN32_FIND_DATAW *);
-
-static struct IFileSystemBindDataVtbl sbvt =
-{
-    IFileSystemBindData_fnQueryInterface,
-    IFileSystemBindData_fnAddRef,
-    IFileSystemBindData_fnRelease,
-    IFileSystemBindData_fnSetFindData,
-    IFileSystemBindData_fnGetFindData,
-};
-
-static const WCHAR wFileSystemBindData[] = {
-    'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d','D','a','t','a',0};
-
-HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC *ppV)
-{
-    IFileSystemBindDataImpl *sb;
-    HRESULT ret = E_OUTOFMEMORY;
-
-    TRACE("%p, %p\n", pfd, ppV);
-
-    if (!ppV)
-       return E_INVALIDARG;
-
-    *ppV = NULL;
-
-    sb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IFileSystemBindDataImpl));
-    if (!sb)
-        return ret;
-
-    sb->lpVtbl = &sbvt;
-    sb->ref = 1;
-    IFileSystemBindData_fnSetFindData((IFileSystemBindData*)sb, pfd);
-
-    ret = CreateBindCtx(0, ppV);
-    if (SUCCEEDED(ret))
-    {
-        BIND_OPTS bindOpts;
-
-        bindOpts.cbStruct = sizeof(BIND_OPTS);
-        bindOpts.grfFlags = 0;
-        bindOpts.grfMode = STGM_CREATE;
-        bindOpts.dwTickCountDeadline = 0;
-        IBindCtx_SetBindOptions(*ppV, &bindOpts);
-        IBindCtx_RegisterObjectParam(*ppV, (LPOLESTR)wFileSystemBindData, (LPUNKNOWN)sb);
-
-        IFileSystemBindData_Release((IFileSystemBindData*)sb);
-    }
-    else
-        HeapFree(GetProcessHeap(), 0, sb);
-    return ret;
-}
-
-HRESULT WINAPI FileSystemBindData_GetFindData(LPBC pbc, WIN32_FIND_DATAW *pfd)
-{
-    LPUNKNOWN pUnk;
-    IFileSystemBindData *pfsbd = NULL;
-    HRESULT ret;
-
-    TRACE("%p, %p\n", pbc, pfd);
-
-    if (!pfd)
-        return E_INVALIDARG;
-
-    ret = IBindCtx_GetObjectParam(pbc, (LPOLESTR)wFileSystemBindData, &pUnk);
-    if (SUCCEEDED(ret))
-    {
-        ret = IUnknown_QueryInterface(pUnk, &IID_IFileSystemBindData, (LPVOID *)&pfsbd);
-        if (SUCCEEDED(ret))
-        {
-            ret = IFileSystemBindData_GetFindData(pfsbd, pfd);
-            IFileSystemBindData_Release(pfsbd);
-        }
-        IUnknown_Release(pUnk);
-    }
-    return ret;
-}
-
-HRESULT WINAPI FileSystemBindData_SetFindData(LPBC pbc, const WIN32_FIND_DATAW *pfd)
-{
-    LPUNKNOWN pUnk;
-    IFileSystemBindData *pfsbd = NULL;
-    HRESULT ret;
-    
-    TRACE("%p, %p\n", pbc, pfd);
-
-    ret = IBindCtx_GetObjectParam(pbc, (LPOLESTR)wFileSystemBindData, &pUnk);
-    if (SUCCEEDED(ret))
-    {
-        ret = IUnknown_QueryInterface(pUnk, &IID_IFileSystemBindData, (LPVOID *)&pfsbd);
-        if (SUCCEEDED(ret))
-        {
-            ret = IFileSystemBindData_SetFindData(pfsbd, pfd);
-            IFileSystemBindData_Release(pfsbd);
-        }
-        IUnknown_Release(pUnk);
-    }
-    return ret;
-}
-
 static HRESULT WINAPI IFileSystemBindData_fnQueryInterface(
                 IFileSystemBindData *iface, REFIID riid, LPVOID *ppV)
 {
     IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface;
+
     TRACE("(%p)->(\n\tIID:\t%s, %p)\n", This, debugstr_guid(riid), ppV);
 
     *ppV = NULL;
 
-    if (IsEqualIID(riid, &IID_IUnknown))
-        *ppV = This;
-    else if (IsEqualIID(riid, &IID_IFileSystemBindData))
-        *ppV = (IFileSystemBindData*)This;
-
-    if (*ppV)
+    if (IsEqualIID(riid, &IID_IUnknown) ||
+        IsEqualIID(riid, &IID_IFileSystemBindData))
     {
-        IUnknown_AddRef((IUnknown*)(*ppV));
-        TRACE("-- Interface: (%p)->(%p)\n", ppV, *ppV);
+        *ppV = This;
+        IUnknown_AddRef((IUnknown*)This);
+        TRACE("-- Interface: (%p)->(%p)\n", ppV, This);
         return S_OK;
     }
+
     TRACE("-- Interface: E_NOINTERFACE\n");
     return E_NOINTERFACE;
 }
@@ -223,4 +118,29 @@ static HRESULT WINAPI IFileSystemBindDat
     else
         memset(&This->findFile, 0, sizeof(WIN32_FIND_DATAW));
     return NOERROR;
+}
+
+static struct IFileSystemBindDataVtbl sbvt =
+{
+    IFileSystemBindData_fnQueryInterface,
+    IFileSystemBindData_fnAddRef,
+    IFileSystemBindData_fnRelease,
+    IFileSystemBindData_fnSetFindData,
+    IFileSystemBindData_fnGetFindData,
+};
+
+IFileSystemBindData* IFileSystemBindData_Constructor(void)
+{
+    IFileSystemBindDataImpl *sb;
+
+    TRACE("\n");
+
+    sb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IFileSystemBindDataImpl));
+    if (!sb)
+        return NULL;
+
+    sb->lpVtbl = &sbvt;
+    sb->ref = 1;
+
+    return (IFileSystemBindData*) sb;
 }
Index: dlls/shell32/tests/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/shell32/tests/Makefile.in,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile.in
--- dlls/shell32/tests/Makefile.in	22 Oct 2004 19:52:33 -0000	1.6
+++ dlls/shell32/tests/Makefile.in	25 Feb 2005 12:35:44 -0000
@@ -8,6 +8,7 @@ EXTRALIBS = -luuid
 
 CTESTS = \
 	generated.c \
+	pidl.c \
 	shelllink.c \
 	shellpath.c \
 	shlfileop.c \
--- /dev/null	2005-02-25 01:31:53.000000000 +0900
+++ dlls/shell32/tests/pidl.c	2005-02-25 21:32:58.000000000 +0900
@@ -0,0 +1,201 @@
+/*
+ * Unit tests for ID Lists
+ *
+ * Copyright 2005 Mike McCormack
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define COBJMACROS
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "windef.h"
+#include "winbase.h"
+#include "shlguid.h"
+#include "shlobj.h"
+#include "shobjidl.h"
+#include "shlwapi.h"
+#include "wine/test.h"
+
+struct fsbd_impl
+{
+    IFileSystemBindDataVtbl *vtbl;
+    int ref;
+    WIN32_FIND_DATAW fd;
+};
+
+ULONG WINAPI fsbd_AddRef(IFileSystemBindData *iface)
+{
+    struct fsbd_impl *This = (struct fsbd_impl*)iface;
+    return This->ref++;
+}
+
+ULONG WINAPI fsbd_Release(IFileSystemBindData *iface)
+{
+    struct fsbd_impl *This = (struct fsbd_impl*)iface;
+    LONG ref;
+
+    ref = --This->ref;
+    if(!ref)
+        HeapFree(GetProcessHeap(), 0, This);
+    return ref;
+}
+
+HRESULT WINAPI fsbd_QueryInterface(IFileSystemBindData *iface, REFIID iid, LPVOID *out)
+{
+    struct fsbd_impl *This = (struct fsbd_impl*)iface;
+
+    if(IsEqualGUID(iid, &IID_IUnknown)||
+        IsEqualGUID(iid, &IID_IFileSystemBindData))
+    {
+        This->ref++;
+        *out = iface;
+        return S_OK;
+    }
+    return E_NOINTERFACE;
+}
+
+HRESULT WINAPI fsbd_SetFindData(IFileSystemBindData *iface, const WIN32_FIND_DATAW *pfd)
+{
+    struct fsbd_impl *This = (struct fsbd_impl*)iface;
+    memcpy(&This->fd, pfd, sizeof *pfd);
+    return S_OK;
+}
+
+HRESULT WINAPI fsbd_GetFindData(IFileSystemBindData *iface, WIN32_FIND_DATAW *pfd)
+{
+    struct fsbd_impl *This = (struct fsbd_impl*)iface;
+    memcpy(pfd, &This->fd, sizeof *pfd);
+    return S_OK;
+}
+
+IFileSystemBindDataVtbl fsbd_vtbl = {
+    fsbd_QueryInterface,
+    fsbd_AddRef,
+    fsbd_Release,
+    fsbd_SetFindData,
+    fsbd_GetFindData,
+};
+
+static IFileSystemBindData *create_fsbd()
+{
+    struct fsbd_impl *fsbd;
+
+    fsbd = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *fsbd);
+    fsbd->ref = 1;
+    fsbd->vtbl = &fsbd_vtbl;
+
+    return (IFileSystemBindData*)fsbd;
+}
+
+void test_pidl(void)
+{
+    WCHAR exe[] = { 'd','u','h','.','e','x','e',0 };
+    WCHAR drive[] = { 'c',':','\\',0 };
+    LPITEMIDLIST pidl;
+    HMODULE hShell32;
+    typedef LPITEMIDLIST (WINAPI *fnILCreateFromPathW)(LPCWSTR);
+    fnILCreateFromPathW pILCreateFromPathW = NULL;
+    typedef HRESULT (WINAPI *fnSHILCreateFromPath)(LPCWSTR,LPITEMIDLIST*,DWORD*);
+    fnSHILCreateFromPath pSHILCreateFromPath = NULL;
+    typedef LPITEMIDLIST (WINAPI *fnSHSimpleIDListFromPath)(LPCWSTR);
+    fnSHSimpleIDListFromPath pSHSimpleIDListFromPath = NULL;
+    LPSHELLFOLDER psf;
+    HRESULT r;
+    DWORD x = 0;
+
+    hShell32 = LoadLibrary("shell32");
+    if (!hShell32)
+        return;
+
+    pILCreateFromPathW = (fnILCreateFromPathW) GetProcAddress(hShell32,(LPSTR)190);
+    pSHILCreateFromPath = (fnSHILCreateFromPath) GetProcAddress(hShell32, (LPSTR)28);
+    pSHSimpleIDListFromPath = (fnSHSimpleIDListFromPath) GetProcAddress(hShell32, (LPSTR)162);
+
+    if(!pILCreateFromPathW)
+        return;
+    if(!pSHILCreateFromPath)
+        return;
+    if(!pSHSimpleIDListFromPath)
+        return;
+
+    pidl = pILCreateFromPathW(exe);
+    ok(pidl == NULL, "created pidl for non-existing path\n");
+
+    pidl = NULL;
+    r = pSHILCreateFromPath(exe, &pidl, NULL);
+    ok(pidl == NULL, "created pidl for non-existing path\n");
+    ok(r == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "didn't fail\n");
+
+    pidl = NULL;
+    r = pSHILCreateFromPath(exe, &pidl, &x);
+    ok(pidl == NULL, "created pidl for non-existing path\n");
+    ok(r == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "didn't fail\n");
+
+    pidl = pSHSimpleIDListFromPath(exe);
+    ok(pidl != NULL, "failed to create pidl from non-existing path\n");
+    /* FIXME: free the pidl */
+
+    pidl = pSHSimpleIDListFromPath(drive);
+    ok(pidl != NULL, "failed to create pidl for drive\n");
+    /* FIXME: free the pidl */
+
+    psf = NULL;
+    r = SHGetDesktopFolder( &psf );
+    ok( r == S_OK, "failed to get desktop folder\n");
+    if( r == S_OK )
+    {
+        IBindCtx *pbc = NULL;
+
+        pidl = NULL;
+        r = IShellFolder_ParseDisplayName(psf, 0, NULL, exe, NULL, &pidl, NULL);
+        ok( r == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "ParseDisplayName return code wrong\n");
+
+        r = CreateBindCtx(0, &pbc);
+        ok( r == S_OK, "failed to create bind context\n");
+        if( r == S_OK )
+        {
+            WCHAR szfsbc[] = { 'F','i','l','e',' ','S','y','s','t','e','m',' ',
+                'B','i','n','d',' ','D','a','t','a',0 };
+            IFileSystemBindData *pfsbc;
+
+            pfsbc = NULL;
+            r = IBindCtx_RegisterObjectParam(pbc, szfsbc, (IUnknown*) pfsbc);
+            ok( r == E_INVALIDARG, "registered null bind context param\n");
+
+            pfsbc = create_fsbd();
+            r = IBindCtx_RegisterObjectParam(pbc, szfsbc, (IUnknown*) pfsbc);
+            ok( r == S_OK, "failed to register file system bind context\n");
+            IUnknown_Release( (IUnknown*) pfsbc);
+
+            pidl = NULL;
+            r = IShellFolder_ParseDisplayName(psf, 0, pbc, exe, NULL, &pidl, NULL);
+            ok( r == S_OK, "failed to parse display name\n");
+            ok( pidl != NULL, "failed to create pidl\n");
+            /* FIXME: free the pidl */
+
+            IBindCtx_Release(pbc);
+        }
+        IShellFolder_Release( psf );
+    }
+
+    FreeLibrary(hShell32);
+}
+
+START_TEST(pidl)
+{
+    test_pidl();
+}


More information about the wine-patches mailing list