shell32: Initial implementation of IShellItemArray with SHCreateShellItemArray.

This commit is contained in:
David Hedberg 2010-07-26 11:54:03 +02:00 committed by Alexandre Julliard
parent dcb2ebee78
commit 090824feb5
4 changed files with 370 additions and 1 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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();

View File

@ -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