shell32: SHSimpleIDListFromPath
Rolf Kalbermatter
rolf.kalbermatter at citeng.com
Sun May 4 15:29:57 CDT 2003
This is the first part of a patch to get SHChangeNotify working properly on
deleted and moved/renamed files. There needs to be another change in all
shlfldr_xx.c to actually make it work as desired.
As it is now with this patch SHSimpleIDListFromPath still does what it is
supposed to do for existing paths, which is already a lot more than the
function did until now and SHChangeNotify does work exactly as it did
already until now.
dlls\shell32\shlfsbind.h and dlls\shell32\shlfsbind.c are new files added
to the tree
Changelog
* dlls/shell32/changenotify.c
Make SHChangeNotify use SHSimpleIDListFromPath as it is supposed to do
* dlls/shell32/pidl.c
Fix SHSimpleIDListFromPath to create fully qualified ItemIDLists and
passing a bindcontext to IShellFolder_ParseDisplayName for conversion
of a path to an ItemIDList.
* dlls\shell32\shlfsbind.h
New header file for the FileSystemBindContext
* dlls\shell32\shlfsbind.c
New source file for the FileSystemBindContext
License: X11/LGPL
Rolf Kalbermatter
Index: dlls/shell32/changenotify.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/changenotify.c,v
retrieving revision 1.20
diff -u -r1.20 changenotify.c
--- dlls/shell32/changenotify.c 21 Jan 2003 19:36:24 -0000 1.20
+++ dlls/shell32/changenotify.c 4 May 2003 19:23:08 -0000
@@ -18,8 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "config.h"
+
#include <string.h>
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "winerror.h"
+#include "winbase.h"
+#include "winreg.h"
+
+#include "shlwapi.h"
#include "wine/debug.h"
#include "pidl.h"
#include "shell32_main.h"
@@ -212,24 +221,25 @@
{
LPITEMIDLIST Pidls[2];
LPNOTIFICATIONLIST ptr;
- DWORD dummy;
UINT typeFlag = uFlags & SHCNF_TYPE;
Pidls[0] = (LPITEMIDLIST)dwItem1;
Pidls[1] = (LPITEMIDLIST)dwItem2;
- TRACE("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId, uFlags, dwItem1, dwItem2);
+ TRACE("(0x%08lx,0x%08x,%p,%p)\n", wEventId, uFlags, dwItem1, dwItem2);
/* convert paths in IDLists*/
switch (typeFlag)
{
+ case SHCNF_IDLIST:
+ break;
case SHCNF_PATHA:
- if (dwItem1) SHILCreateFromPathA((LPCSTR)dwItem1, &Pidls[0], &dummy);
- if (dwItem2) SHILCreateFromPathA((LPCSTR)dwItem2, &Pidls[1], &dummy);
+ if (dwItem1) Pidls[0] = SHSimpleIDListFromPathA((LPCSTR)dwItem1);
+ if (dwItem2) Pidls[1] = SHSimpleIDListFromPathA((LPCSTR)dwItem2);
break;
case SHCNF_PATHW:
- if (dwItem1) SHILCreateFromPathW((LPCWSTR)dwItem1, &Pidls[0], &dummy);
- if (dwItem2) SHILCreateFromPathW((LPCWSTR)dwItem2, &Pidls[1], &dummy);
+ if (dwItem1) Pidls[0] = SHSimpleIDListFromPathW((LPCWSTR)dwItem1);
+ if (dwItem2) Pidls[1] = SHSimpleIDListFromPathW((LPCWSTR)dwItem2);
break;
case SHCNF_PRINTERA:
case SHCNF_PRINTERW:
@@ -255,8 +265,8 @@
LeaveCriticalSection(&SHELL32_ChangenotifyCS);
- /* if we allocated it, free it */
- if ((typeFlag == SHCNF_PATHA) || (typeFlag == SHCNF_PATHW))
+ /* if we allocated it, free it. The ANSI flag is also set in its Unicode sibling. */
+ if ((typeFlag & SHCNF_PATHA) /* || (typeFlag & SHCNF_PRINTERA) */ )
{
if (Pidls[0]) SHFree(Pidls[0]);
if (Pidls[1]) SHFree(Pidls[1]);
Index: dlls/shell32/pidl.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/pidl.c,v
retrieving revision 1.83
diff -u -r1.83 pidl.c
--- dlls/shell32/pidl.c 17 Apr 2003 02:18:33 -0000 1.83
+++ dlls/shell32/pidl.c 4 May 2003 19:25:30 -0000
@@ -39,6 +39,7 @@
#include "shlwapi.h"
#include "pidl.h"
+#include "shlfsbind.h"
#include "debughlp.h"
#include "wine/debug.h"
@@ -794,46 +795,115 @@
return ILCreateFromPathA (path);
}
/*************************************************************************
- * SHSimpleIDListFromPath [SHELL32.162]
+ * _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 non existing path still can work.
*/
-LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPCSTR lpszPath)
+HRESULT WINAPI _ILParsePathW(LPCWSTR path, LPWIN32_FIND_DATAW lpFindFile,
+ BOOL bBindCtx, LPITEMIDLIST *ppidl, LPDWORD prgfInOut)
{
- LPITEMIDLIST pidl=NULL;
- HANDLE hFile;
- WIN32_FIND_DATAA stffile;
+ LPSHELLFOLDER pSF = NULL;
+ LPBC pBC = NULL;
+ HRESULT ret;
- TRACE("path=%s\n", lpszPath);
+ TRACE("%s %p %ld %p %p %p 0x%lx\n", debugstr_w(path), lpFindFile, bBindCtx,
+ ppidl, ppidl ? *ppidl : NULL,
+ prgfInOut, prgfInOut ? *prgfInOut : 0);
- if (!lpszPath) return NULL;
+ ret = SHGetDesktopFolder(&pSF);
+ if (FAILED(ret))
+ {
+ return ret;
+ }
- hFile = FindFirstFileA(lpszPath, &stffile);
+ if (lpFindFile || bBindCtx)
+ ret = FSBindData_Constructor(lpFindFile, &pBC);
- if ( hFile != INVALID_HANDLE_VALUE )
+ if (SUCCEEDED(ret))
{
- if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- pidl = _ILCreateFolder (&stffile);
- }
- else
- {
- pidl = _ILCreateValue (&stffile);
- }
- FindClose (hFile);
+ ret = IShellFolder_ParseDisplayName(pSF, 0, pBC, (LPOLESTR)path, NULL, ppidl, prgfInOut);
+ IUnknown_Release(pBC);
}
+
+ if (pBC)
+ IBindCtx_Release(pBC);
+
+ 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]
+ *
+ * Creates a simple ItemIDList from a path and returns it. This function
+ * does not fail on non-existing paths.
+ *
+ * PARAMS
+ * path [I] path to parse and convert into an ItemIDList
+ *
+ * RETURNS
+ * the newly created simple ItemIDList
+ *
+ * NOTES
+ * Simple in the name does not mean a relative ItemIDList but rather a
+ * fully qualified list, where only the file name is filled in and the
+ * 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.
+ */
+LPITEMIDLIST WINAPI SHSimpleIDListFromPathA(LPCSTR path)
+{
+ LPITEMIDLIST pidl = NULL;
+ WCHAR wPath[MAX_PATH];
+
+ TRACE("%s\n", debugstr_a(path));
+
+ MultiByteToWideChar(CP_ACP, 0, path, -1, wPath, MAX_PATH);
+ _ILParsePathW(wPath, NULL, TRUE, &pidl, NULL);
return pidl;
}
-LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPCWSTR lpszPath)
+
+LPITEMIDLIST WINAPI SHSimpleIDListFromPathW(LPCWSTR path)
{
- char lpszTemp[MAX_PATH];
- TRACE("path=%s\n",debugstr_w(lpszPath));
+ LPITEMIDLIST pidl = NULL;
- if (!WideCharToMultiByte( CP_ACP, 0, lpszPath, -1, lpszTemp, sizeof(lpszTemp), NULL, NULL ))
- lpszTemp[sizeof(lpszTemp)-1] = 0;
+ TRACE("%s\n", debugstr_w(path));
- return SHSimpleIDListFromPathA (lpszTemp);
+ _ILParsePathW(path, NULL, TRUE, &pidl, NULL);
+ TRACE("%s %p\n", debugstr_w(path), pidl);
+ return pidl;
}
-LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW (LPCVOID lpszPath)
+LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW(LPCVOID lpszPath)
{
if ( SHELL_OsIsUnicode())
return SHSimpleIDListFromPathW (lpszPath);
--- /dev/nul Sun May 04 19:15:26 2003
+++ dlls/shell32/shlfsbind.h Sun May 04 20:08:32 2003
@@ -0,0 +1,64 @@
+/*
+ * File System Bind Data object to use as parameter for the bind context to
+ * IShellFolder_ParseDisplayName
+ *
+ * Copyright 2003 Rolf Kalbermatter
+ *
+ * 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
+ *
+ */
+
+/***********************************************************************
+* FSBindData declarations
+*/
+#ifndef __WINE_SHELL_FS_BINDDATA_H
+#define __WINE_SHELL_FS_BINDDATA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+typedef struct IFSBindData IFSBindData, *LPFSBINDDATA;
+
+#define INTERFACE IFSBindData
+#define IFSBindData_METHODS \
+ IUnknown_METHODS \
+ STDMETHOD(PutData)(THIS_ LPWIN32_FIND_DATAW lpFindFile) PURE; \
+ STDMETHOD(GetData)(THIS_ LPWIN32_FIND_DATAW lpFindFile) PURE;
+ICOM_DEFINE(IFSBindData,IUnknown)
+#undef INTERFACE
+
+DEFINE_GUID(IID_IFSBindData, 0x01E18D10,0x4D8B,0x11D2,0x85,0x5D,0x00,0x60,0x08,0x05,0x93,0x67);
+
+
+/*** IUnknown methods ***/
+#define IFSBindData_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IFSBindData_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IFSBindData_Release(p) (p)->lpVtbl->Release(p)
+/*** IFSBindData methods ***/
+#define IFSBindData_PutData(p,a) (p)->lpVtbl->PutData(p,a)
+#define IFSBindData_GetData(p,a) (p)->lpVtbl->GetData(p,a)
+
+HRESULT WINAPI FSBindData_Constructor(LPWIN32_FIND_DATAW lpFindFile, LPBC *ppV);
+
+HRESULT WINAPI FSBindData_QueryData(LPBC pbc, LPWIN32_FIND_DATAW lpFindFile);
+
+HRESULT WINAPI FSBindData_StoreData(LPBC pbc, LPWIN32_FIND_DATAW lpFindFile);
+
+#ifdef __cplusplus
+extern }
+#endif /* defined(__cplusplus) */
+
+#endif
--- /dev/nul Sun May 04 19:15:26 2003
+++ dlls/shell32/shlfsbind.c Sun May 04 19:19:00 2003
@@ -0,0 +1,203 @@
+/*
+ * File System Bind Data object to use as parameter for the bind context to
+ * IShellFolder_ParseDisplayName
+ *
+ * Copyright 2003 Rolf Kalbermatter
+ *
+ * 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
+ *
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "winbase.h"
+#include "shell32_main.h"
+#include "shlfsbind.h"
+
+#include "debughlp.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(pidl);
+
+/***********************************************************************
+ * FSBindData implementation
+ */
+typedef struct
+{
+ ICOM_VFIELD(IFSBindData);
+ DWORD ref;
+ LPWIN32_FIND_DATAW lpFindFile;
+} IFSBindDataImpl;
+
+static HRESULT WINAPI IFSBindData_fnQueryInterface(LPFSBINDDATA iface, REFIID riid, LPVOID* ppvObj);
+static ULONG WINAPI IFSBindData_fnAddRef(LPFSBINDDATA iface);
+static ULONG WINAPI IFSBindData_fnRelease(LPFSBINDDATA iface);
+static HRESULT WINAPI IFSBindData_fnPutData(LPFSBINDDATA iface, LPWIN32_FIND_DATAW lpFindFile);
+static HRESULT WINAPI IFSBindData_fnGetData(LPFSBINDDATA iface, LPWIN32_FIND_DATAW lpFindFile);
+
+static struct ICOM_VTABLE(IFSBindData) sbvt =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ IFSBindData_fnQueryInterface,
+ IFSBindData_fnAddRef,
+ IFSBindData_fnRelease,
+ IFSBindData_fnPutData,
+ IFSBindData_fnGetData,
+};
+
+static WCHAR lpFileSystemBindData[] = {'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d','D','a','t','a',0};
+
+HRESULT WINAPI FSBindData_Constructor(LPWIN32_FIND_DATAW lpFindFile, LPBC *ppV)
+{
+ IFSBindDataImpl *sb = (IFSBindDataImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IFSBindDataImpl));
+ HRESULT ret = E_OUTOFMEMORY;
+
+ *ppV = NULL;
+ if (!sb)
+ return ret;
+
+ sb->lpVtbl = &sbvt;
+ sb->ref = 1;
+ if (lpFindFile)
+ memcpy(sb->lpFindFile, lpFindFile, sizeof(LPWIN32_FIND_DATAW));
+ else
+ memset(sb->lpFindFile, 0, sizeof(LPWIN32_FIND_DATAW));
+
+ 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, lpFileSystemBindData, (LPUNKNOWN)sb);
+
+ IFSBindData_Release((LPFSBINDDATA)sb);
+ }
+ return ret;
+}
+
+HRESULT WINAPI FSBindData_QueryData(LPBC pbc, LPWIN32_FIND_DATAW lpFindFile)
+{
+ LPUNKNOWN pUnk;
+ LPFSBINDDATA pFSBindData = NULL;
+ HRESULT ret;
+
+ ret = IBindCtx_GetObjectParam(pbc, lpFileSystemBindData, &pUnk);
+ if (SUCCEEDED(ret))
+ {
+ ret = IUnknown_QueryInterface(pUnk, &IID_IFSBindData, &pFSBindData);
+ if (SUCCEEDED(ret))
+ {
+ ret = IFSBindData_GetData(pFSBindData, lpFindFile);
+ IFSBindData_Release(pFSBindData);
+ }
+ IUnknown_Release(pUnk);
+ }
+ return ret;
+}
+
+HRESULT WINAPI FSBindData_StoreData(LPBC pbc, LPWIN32_FIND_DATAW lpFindFile)
+{
+ LPUNKNOWN pUnk;
+ LPFSBINDDATA pFSBindData = NULL;
+ HRESULT ret;
+
+ ret = IBindCtx_GetObjectParam(pbc, lpFileSystemBindData, &pUnk);
+ if (SUCCEEDED(ret))
+ {
+ ret = IUnknown_QueryInterface(pUnk, &IID_IFSBindData, &pFSBindData);
+ if (SUCCEEDED(ret))
+ {
+ ret = IFSBindData_PutData(pFSBindData, lpFindFile);
+ IFSBindData_Release(pFSBindData);
+ }
+ IUnknown_Release(pUnk);
+ }
+ return ret;}
+
+HRESULT WINAPI IFSBindData_fnQueryInterface(LPFSBINDDATA iface, REFIID riid, LPVOID *ppV)
+{
+ ICOM_THIS(IFSBindDataImpl, 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_IFSBindData))
+ {
+ *ppV = (IFSBindData*)This;
+ }
+
+ if(*ppV)
+ {
+ IUnknown_AddRef((IUnknown*)(*ppV));
+ TRACE("-- Interface: (%p)->(%p)\n", ppV, *ppV);
+ return S_OK;
+ }
+ TRACE("-- Interface: E_NOINTERFACE\n");
+ return E_NOINTERFACE;
+}
+
+ULONG WINAPI IFSBindData_fnAddRef(LPFSBINDDATA iface)
+{
+ ICOM_THIS(IFSBindDataImpl, iface);
+ TRACE("(%p)\n", This);
+ return InterlockedIncrement(&This->ref);
+}
+
+ULONG WINAPI IFSBindData_fnRelease(LPFSBINDDATA iface)
+{
+ ICOM_THIS(IFSBindDataImpl, iface);
+ TRACE("(%p)\n", This);
+
+ if (!InterlockedDecrement(&This->ref))
+ {
+ TRACE(" destroying ISFBindPidl(%p)\n",This);
+ HeapFree(GetProcessHeap(), 0, This);
+ return 0;
+ }
+ return This->ref;
+}
+
+HRESULT WINAPI IFSBindData_fnPutData(LPFSBINDDATA iface, LPWIN32_FIND_DATAW lpFindFile)
+{
+ ICOM_THIS(IFSBindDataImpl, iface);
+ TRACE("(%p %p)\n", This, lpFindFile);
+
+ if (!lpFindFile)
+ memcpy(This->lpFindFile, lpFindFile, sizeof(LPWIN32_FIND_DATAW));
+ else
+ memset(This->lpFindFile, 0, sizeof(LPWIN32_FIND_DATAW));
+ return NOERROR;
+}
+
+HRESULT WINAPI IFSBindData_fnGetData(LPFSBINDDATA iface, LPWIN32_FIND_DATAW lpFindFile)
+{
+ ICOM_THIS(IFSBindDataImpl, iface);
+ TRACE("(%p %p)\n", This, lpFindFile);
+
+ if (!lpFindFile)
+ return E_INVALIDARG;
+
+ memcpy(lpFindFile, This->lpFindFile, sizeof(LPWIN32_FIND_DATAW));
+ return NOERROR;
+}
More information about the wine-patches
mailing list