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