shell32: Initial implementation of IShellItemArray with SHCreateShellItemArray.
This commit is contained in:
parent
dcb2ebee78
commit
090824feb5
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue