[PATCH 3/5] shell32: Initial implementation of IShellItemArray with SHCreateShellItemArray. (try 2)
David Hedberg
david.hedberg at gmail.com
Mon Jul 26 04:54:03 CDT 2010
Moved it to into shellitem.c.
---
dlls/shell32/shell32.spec | 1 +
dlls/shell32/shellitem.c | 237 +++++++++++++++++++++++++++++++++++++++-
dlls/shell32/tests/shlfolder.c | 132 ++++++++++++++++++++++
include/shobjidl.idl | 1 +
4 files changed, 370 insertions(+), 1 deletions(-)
diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec
index ed61f0b..426e841 100644
--- a/dlls/shell32/shell32.spec
+++ b/dlls/shell32/shell32.spec
@@ -334,6 +334,7 @@
@ stdcall SHCreateItemFromParsingName(wstr ptr ptr ptr)
@ stub SHCreateProcessAsUserW
@ stdcall SHCreateShellItem(ptr ptr ptr ptr)
+@ stdcall SHCreateShellItemArray(ptr ptr long ptr ptr)
@ stdcall SHEmptyRecycleBinA(long str long)
@ stdcall SHEmptyRecycleBinW(long wstr long)
@ stub SHExtractIconsW
diff --git a/dlls/shell32/shellitem.c b/dlls/shell32/shellitem.c
index bbd85e6..8dd6239 100644
--- a/dlls/shell32/shellitem.c
+++ b/dlls/shell32/shellitem.c
@@ -1,5 +1,5 @@
/*
- * IShellItem implementation
+ * IShellItem and IShellItemArray implementations
*
* Copyright 2008 Vincent Povirk for CodeWeavers
*
@@ -592,3 +592,238 @@ HRESULT WINAPI SHGetItemFromObject(IUnknown *punk, REFIID riid, void **ppv)
return ret;
}
+
+/*************************************************************************
+ * IShellItemArray implementation
+ */
+typedef struct {
+ const IShellItemArrayVtbl *lpVtbl;
+ LONG ref;
+
+ IShellItem **array;
+ DWORD item_count;
+} IShellItemArrayImpl;
+
+static HRESULT WINAPI IShellItemArray_fnQueryInterface(IShellItemArray *iface,
+ REFIID riid,
+ void **ppvObject)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
+
+ *ppvObject = NULL;
+ if(IsEqualIID(riid, &IID_IShellItemArray) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *ppvObject = This;
+ }
+
+ if(*ppvObject)
+ {
+ IUnknown_AddRef((IUnknown*)*ppvObject);
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI IShellItemArray_fnAddRef(IShellItemArray *iface)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ LONG ref = InterlockedIncrement(&This->ref);
+ TRACE("%p - ref %d\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI IShellItemArray_fnRelease(IShellItemArray *iface)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ LONG ref = InterlockedDecrement(&This->ref);
+ TRACE("%p - ref %d\n", This, ref);
+
+ if(!ref)
+ {
+ UINT i;
+ TRACE("Freeing.\n");
+
+ for(i = 0; i < This->item_count; i++)
+ IShellItem_Release(This->array[i]);
+
+ HeapFree(GetProcessHeap(), 0, This->array);
+ HeapFree(GetProcessHeap(), 0, This);
+ return 0;
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI IShellItemArray_fnBindToHandler(IShellItemArray *iface,
+ IBindCtx *pbc,
+ REFGUID bhid,
+ REFIID riid,
+ void **ppvOut)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ FIXME("Stub: %p (%p, %s, %s, %p)\n",
+ This, pbc, shdebugstr_guid(bhid), shdebugstr_guid(riid), ppvOut);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IShellItemArray_fnGetPropertyStore(IShellItemArray *iface,
+ GETPROPERTYSTOREFLAGS flags,
+ REFIID riid,
+ void **ppv)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ FIXME("Stub: %p (%x, %s, %p)\n", This, flags, shdebugstr_guid(riid), ppv);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IShellItemArray_fnGetPropertyDescriptionList(IShellItemArray *iface,
+ REFPROPERTYKEY keyType,
+ REFIID riid,
+ void **ppv)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ FIXME("Stub: %p (%p, %s, %p)\n",
+ This, keyType, shdebugstr_guid(riid), ppv);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IShellItemArray_fnGetAttributes(IShellItemArray *iface,
+ SIATTRIBFLAGS AttribFlags,
+ SFGAOF sfgaoMask,
+ SFGAOF *psfgaoAttribs)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ FIXME("Stub: %p (%x, %x, %p)\n", This, AttribFlags, sfgaoMask, psfgaoAttribs);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IShellItemArray_fnGetCount(IShellItemArray *iface,
+ DWORD *pdwNumItems)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ TRACE("%p (%p)\n", This, pdwNumItems);
+
+ *pdwNumItems = This->item_count;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI IShellItemArray_fnGetItemAt(IShellItemArray *iface,
+ DWORD dwIndex,
+ IShellItem **ppsi)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ TRACE("%p (%x, %p)\n", This, dwIndex, ppsi);
+
+ /* zero indexed */
+ if(dwIndex + 1 > This->item_count)
+ return E_FAIL;
+
+ *ppsi = This->array[dwIndex];
+ IShellItem_AddRef(*ppsi);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI IShellItemArray_fnEnumItems(IShellItemArray *iface,
+ IEnumShellItems **ppenumShellItems)
+{
+ IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
+ FIXME("Stub: %p (%p)\n", This, ppenumShellItems);
+
+ return E_NOTIMPL;
+}
+
+static const IShellItemArrayVtbl vt_IShellItemArray = {
+ IShellItemArray_fnQueryInterface,
+ IShellItemArray_fnAddRef,
+ IShellItemArray_fnRelease,
+ IShellItemArray_fnBindToHandler,
+ IShellItemArray_fnGetPropertyStore,
+ IShellItemArray_fnGetPropertyDescriptionList,
+ IShellItemArray_fnGetAttributes,
+ IShellItemArray_fnGetCount,
+ IShellItemArray_fnGetItemAt,
+ IShellItemArray_fnEnumItems
+};
+
+static HRESULT WINAPI IShellItemArray_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
+{
+ IShellItemArrayImpl *This;
+ HRESULT ret;
+
+ TRACE("(%p, %s, %p)\n",pUnkOuter, debugstr_guid(riid), ppv);
+
+ if(pUnkOuter)
+ return CLASS_E_NOAGGREGATION;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(IShellItemArrayImpl));
+ if(!This)
+ return E_OUTOFMEMORY;
+
+ This->ref = 1;
+ This->lpVtbl = &vt_IShellItemArray;
+
+ ret = IShellItemArray_QueryInterface((IShellItemArray*)This, riid, ppv);
+ IShellItemArray_Release((IShellItemArray*)This);
+
+ return ret;
+}
+
+HRESULT WINAPI SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent,
+ IShellFolder *psf,
+ UINT cidl,
+ PCUITEMID_CHILD_ARRAY ppidl,
+ IShellItemArray **ppsiItemArray)
+{
+ IShellItemArrayImpl *This;
+ IShellItem **array;
+ HRESULT ret = E_FAIL;
+ UINT i;
+
+ TRACE("%p, %p, %d, %p, %p\n", pidlParent, psf, cidl, ppidl, ppsiItemArray);
+
+ if(!pidlParent && !psf)
+ return E_POINTER;
+
+ if(!ppidl)
+ return E_INVALIDARG;
+
+ array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cidl*sizeof(IShellItem*));
+ if(!array)
+ return E_OUTOFMEMORY;
+
+ for(i = 0; i < cidl; i++)
+ {
+ ret = SHCreateShellItem(pidlParent, psf, ppidl[i], &array[i]);
+ if(FAILED(ret)) break;
+ }
+
+ if(SUCCEEDED(ret))
+ {
+ ret = IShellItemArray_Constructor(NULL, &IID_IShellItemArray, (void**)&This);
+ if(SUCCEEDED(ret))
+ {
+ This->array = array;
+ This->item_count = cidl;
+ *ppsiItemArray = (IShellItemArray*)This;
+
+ return ret;
+ }
+ }
+
+ /* Something failed, clean up. */
+ for(i = 0; i < cidl; i++)
+ if(array[i]) IShellItem_Release(array[i]);
+ HeapFree(GetProcessHeap(), 0, array);
+ *ppsiItemArray = NULL;
+ return ret;
+}
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index 2781b23..491327e 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -58,6 +58,7 @@ static BOOL (WINAPI *pILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST);
static HRESULT (WINAPI *pSHCreateItemFromIDList)(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv);
static HRESULT (WINAPI *pSHCreateItemFromParsingName)(PCWSTR,IBindCtx*,REFIID,void**);
static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**);
+static HRESULT (WINAPI *pSHCreateShellItemArray)(LPCITEMIDLIST,IShellFolder*,UINT,LPCITEMIDLIST*,IShellItemArray**);
static LPITEMIDLIST (WINAPI *pILCombine)(LPCITEMIDLIST,LPCITEMIDLIST);
static HRESULT (WINAPI *pSHParseDisplayName)(LPCWSTR,IBindCtx*,LPITEMIDLIST*,SFGAOF,SFGAOF*);
static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPathAW)(LPCVOID);
@@ -79,6 +80,7 @@ static void init_function_pointers(void)
MAKEFUNC(SHCreateItemFromIDList);
MAKEFUNC(SHCreateItemFromParsingName);
MAKEFUNC(SHCreateShellItem);
+ MAKEFUNC(SHCreateShellItemArray);
MAKEFUNC(SHGetFolderPathA);
MAKEFUNC(SHGetFolderPathAndSubDirA);
MAKEFUNC(SHGetPathFromIDListW);
@@ -2930,6 +2932,135 @@ static void test_SHGetItemFromObject(void)
IShellFolder_Release(psfdesktop);
}
+static void test_SHCreateShellItemArray(void)
+{
+ IShellFolder *pdesktopsf, *psf;
+ IShellItemArray *psia;
+ IEnumIDList *peidl;
+ HRESULT hr;
+ WCHAR cTestDirW[MAX_PATH];
+ LPITEMIDLIST pidl_testdir, pidl;
+ static const WCHAR testdirW[] = {'t','e','s','t','d','i','r',0};
+
+ if(!pSHCreateShellItemArray) {
+ skip("No pSHCreateShellItemArray!\n");
+ return;
+ }
+
+ ok(pSHGetSpecialFolderLocation != NULL, "SHGetSpecialFolderLocation missing.\n");
+
+ if(0)
+ {
+ /* Crashes under native */
+ pSHCreateShellItemArray(NULL, NULL, 0, NULL, NULL);
+ pSHCreateShellItemArray(NULL, NULL, 1, NULL, NULL);
+ pSHCreateShellItemArray(NULL, pdesktopsf, 0, NULL, NULL);
+ pSHCreateShellItemArray(pidl, NULL, 0, NULL, NULL);
+ }
+
+ hr = pSHCreateShellItemArray(NULL, NULL, 0, NULL, &psia);
+ ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+ SHGetDesktopFolder(&pdesktopsf);
+ hr = pSHCreateShellItemArray(NULL, pdesktopsf, 0, NULL, &psia);
+ ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+ hr = pSHCreateShellItemArray(NULL, pdesktopsf, 1, NULL, &psia);
+ ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+ pSHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
+ hr = pSHCreateShellItemArray(pidl, NULL, 0, NULL, &psia);
+ ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+ pILFree(pidl);
+
+ GetCurrentDirectoryW(MAX_PATH, cTestDirW);
+ myPathAddBackslashW(cTestDirW);
+ lstrcatW(cTestDirW, testdirW);
+
+ CreateFilesFolders();
+
+ hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, cTestDirW, NULL, &pidl_testdir, 0);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ if(SUCCEEDED(hr))
+ {
+ hr = IShellFolder_BindToObject(pdesktopsf, pidl_testdir, NULL, (REFIID)&IID_IShellFolder,
+ (void**)&psf);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+ }
+ IShellFolder_Release(pdesktopsf);
+
+ if(FAILED(hr))
+ {
+ skip("Failed to set up environment for SHCreateShellItemArray tests.\n");
+ pILFree(pidl_testdir);
+ Cleanup();
+ return;
+ }
+
+ hr = IShellFolder_EnumObjects(psf, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &peidl);
+ ok(hr == S_OK, "Got %08x\n", hr);
+ if(SUCCEEDED(hr))
+ {
+ LPITEMIDLIST apidl[5];
+ UINT done, numitems, i;
+
+ for(done = 0; done < 5; done++)
+ if(IEnumIDList_Next(peidl, 1, &apidl[done], NULL) != S_OK)
+ break;
+ ok(done == 5, "Got %d pidls\n", done);
+ IEnumIDList_Release(peidl);
+
+ /* Create a ShellItemArray */
+ hr = pSHCreateShellItemArray(NULL, psf, done, (LPCITEMIDLIST*)apidl, &psia);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+ if(SUCCEEDED(hr))
+ {
+ IShellItem *psi;
+
+ if(0)
+ {
+ /* Crashes in Windows 7 */
+ hr = IShellItemArray_GetCount(psia, NULL);
+ }
+
+ IShellItemArray_GetCount(psia, &numitems);
+ ok(numitems == done, "Got %d, expected %d\n", numitems, done);
+
+ hr = IShellItemArray_GetItemAt(psia, numitems, &psi);
+ ok(hr == E_FAIL, "Got 0x%08x\n", hr);
+
+ /* Compare all the items */
+ for(i = 0; i < numitems; i++)
+ {
+ LPITEMIDLIST pidl_abs;
+ pidl_abs = ILCombine(pidl_testdir, apidl[i]);
+
+ hr = IShellItemArray_GetItemAt(psia, i, &psi);
+ ok(hr == S_OK, "(%d) Failed with 0x%08x\n", i, hr);
+ if(SUCCEEDED(hr))
+ {
+ hr = pSHGetIDListFromObject((IUnknown*)psi, &pidl);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+ if(SUCCEEDED(hr))
+ {
+ ok(ILIsEqual(pidl_abs, pidl), "Pidl not equal.\n");
+ pILFree(pidl);
+ }
+ IShellItem_Release(psi);
+ }
+ pILFree(pidl_abs);
+ }
+ for(i = 0; i < done; i++)
+ pILFree(apidl[i]);
+ IShellItemArray_Release(psia);
+ }
+ }
+
+ IShellFolder_Release(psf);
+ pILFree(pidl_testdir);
+ Cleanup();
+}
+
static void test_SHParseDisplayName(void)
{
LPITEMIDLIST pidl1, pidl2;
@@ -3431,6 +3562,7 @@ START_TEST(shlfolder)
test_SHGetFolderPathAndSubDirA();
test_LocalizedNames();
test_SHCreateShellItem();
+ test_SHCreateShellItemArray();
test_desktop_IPersist();
test_GetUIObject();
test_SHSimpleIDListFromPath();
diff --git a/include/shobjidl.idl b/include/shobjidl.idl
index 6bd6b07..d982cc1 100644
--- a/include/shobjidl.idl
+++ b/include/shobjidl.idl
@@ -517,6 +517,7 @@ cpp_quote("HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID
cpp_quote("HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj, DATAOBJ_GET_ITEM_FLAGS dwFlags, REFIID riid, void **ppv);")
cpp_quote("HRESULT WINAPI SHGetIDListFromObject(IUnknown *punk, PIDLIST_ABSOLUTE *ppidl);")
cpp_quote("HRESULT WINAPI SHGetItemFromObject(IUnknown *punk, REFIID riid, void **ppv);")
+cpp_quote("HRESULT WINAPI SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent, IShellFolder* psf, UINT cidl, PCUITEMID_CHILD_ARRAY ppidl, IShellItemArray **ppsiItemArray);")
/*****************************************************************************
* IShellItemFilter interface
--
1.7.1.1
More information about the wine-patches
mailing list