From: David Hedberg Subject: [PATCH 5/7] shell32: Implement SHCreateShellItemFromIDLists. Message-Id: <1406745806-17144-5-git-send-email-david.hedberg@gmail.com> Date: Wed, 30 Jul 2014 20:43:24 +0200 --- dlls/shell32/shell32.spec | 1 + dlls/shell32/shellitem.c | 45 ++++++++++ dlls/shell32/tests/shlfolder.c | 181 +++++++++++++++++++++++++++++++++++++++++ include/shobjidl.idl | 1 + include/shtypes.idl | 1 + 5 files changed, 229 insertions(+) diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec index d73dcbb..a85b45d 100644 --- a/dlls/shell32/shell32.spec +++ b/dlls/shell32/shell32.spec @@ -345,6 +345,7 @@ @ stdcall SHCreateShellItemArray(ptr ptr long ptr ptr) @ stdcall SHCreateShellItemArrayFromDataObject(ptr ptr ptr) @ stdcall SHCreateShellItemArrayFromShellItem(ptr ptr ptr) +@ stdcall SHCreateShellItemArrayFromIDLists(long ptr ptr) @ stdcall SHEmptyRecycleBinA(long str long) @ stdcall SHEmptyRecycleBinW(long wstr long) @ stdcall SHExtractIconsW(wstr long long long ptr ptr long long) user32.PrivateExtractIconsW diff --git a/dlls/shell32/shellitem.c b/dlls/shell32/shellitem.c index 06b0783..707a4c2 100644 --- a/dlls/shell32/shellitem.c +++ b/dlls/shell32/shellitem.c @@ -1092,3 +1092,48 @@ HRESULT WINAPI SHCreateShellItemArrayFromDataObject(IDataObject *pdo, REFIID rii return ret; } + +HRESULT WINAPI SHCreateShellItemArrayFromIDLists(UINT cidl, + PCIDLIST_ABSOLUTE_ARRAY pidl_array, + IShellItemArray **psia) +{ + IShellItemArrayImpl *This; + IShellItem **array; + HRESULT ret; + UINT i; + TRACE("%d, %p, %p\n", cidl, pidl_array, psia); + + *psia = NULL; + + if(cidl == 0) + return E_INVALIDARG; + + array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellItem*)); + if(!array) + return E_OUTOFMEMORY; + + for(i = 0; i < cidl; i++) + { + ret = SHCreateShellItem(NULL, NULL, pidl_array[i], &array[i]); + if(FAILED(ret)) + break; + } + + if(SUCCEEDED(ret)) + { + ret = IShellItemArray_Constructor(NULL, &IID_IShellItemArray, (void**)psia); + if(SUCCEEDED(ret)) + { + This = impl_from_IShellItemArray(*psia); + This->array = array; + This->item_count = cidl; + return S_OK; + } + } + + for(i = 0; i < cidl; i++) + if(array[i]) IShellItem_Release(array[i]); + HeapFree(GetProcessHeap(), 0, array); + *psia = NULL; + return ret; +} diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index acb3517..38d265a 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -60,6 +60,7 @@ static HRESULT (WINAPI *pSHCreateItemFromIDList)(PCIDLIST_ABSOLUTE pidl, REFIID 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 HRESULT (WINAPI *pSHCreateShellItemArrayFromIDLists)(UINT, PCIDLIST_ABSOLUTE*, IShellItemArray**); static HRESULT (WINAPI *pSHCreateShellItemArrayFromDataObject)(IDataObject*, REFIID, void **); static HRESULT (WINAPI *pSHCreateShellItemArrayFromShellItem)(IShellItem*, REFIID, void **); static LPITEMIDLIST (WINAPI *pILCombine)(LPCITEMIDLIST,LPCITEMIDLIST); @@ -116,6 +117,7 @@ static void init_function_pointers(void) MAKEFUNC(SHCreateItemFromParsingName); MAKEFUNC(SHCreateShellItem); MAKEFUNC(SHCreateShellItemArray); + MAKEFUNC(SHCreateShellItemArrayFromIDLists); MAKEFUNC(SHCreateShellItemArrayFromDataObject); MAKEFUNC(SHCreateShellItemArrayFromShellItem); MAKEFUNC(SHGetFolderPathA); @@ -3542,6 +3544,185 @@ static void test_SHCreateShellItemArray(void) else skip("No SHCreateShellItemArrayFromDataObject.\n"); + if(pSHCreateShellItemArrayFromIDLists) + { + WCHAR test1W[] = {'t','e','s','t','1','.','t','x','t',0}; + WCHAR test1pathW[MAX_PATH]; + LPITEMIDLIST pidltest1; + LPCITEMIDLIST pidl_array[2]; + + if(0) + { + /* Crashes */ + hr = pSHCreateShellItemArrayFromIDLists(0, NULL, NULL); + } + + psia = (void*)0xdeadbeef; + hr = pSHCreateShellItemArrayFromIDLists(0, NULL, &psia); + ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); + ok(psia == NULL, "Got %p\n", psia); + + psia = (void*)0xdeadbeef; + hr = pSHCreateShellItemArrayFromIDLists(0, pidl_array, &psia); + ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr); + ok(psia == NULL, "Got %p\n", psia); + + psia = (void*)0xdeadbeef; + pidl_array[0] = NULL; + hr = pSHCreateShellItemArrayFromIDLists(1, pidl_array, &psia); + todo_wine ok(hr == E_OUTOFMEMORY, "Got 0x%08x\n", hr); + ok(psia == NULL, "Got %p\n", psia); + + psia = (void*)0xdeadbeef; + pidl_array[0] = pidl_testdir; + pidl_array[1] = NULL; + hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia); + todo_wine ok(hr == S_OK || broken(hr == E_INVALIDARG) /* Vista */, "Got 0x%08x\n", hr); + todo_wine ok(psia != NULL || broken(psia == NULL) /* Vista */, "Got %p\n", psia); + if(SUCCEEDED(hr)) + { + IShellItem *psi; + UINT count = 0; + + hr = IShellItemArray_GetCount(psia, &count); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(count == 2, "Got %d\n", count); + + hr = IShellItemArray_GetItemAt(psia, 0, &psi); + ok(hr == S_OK, "Got 0x%08x\n", hr); + if(SUCCEEDED(hr)) + { + LPWSTR path; + hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path)); + if(SUCCEEDED(hr)) + CoTaskMemFree(path); + + IShellItem_Release(psi); + } + + hr = IShellItemArray_GetItemAt(psia, 1, &psi); + ok(hr == S_OK, "Got 0x%08x\n", hr); + if(SUCCEEDED(hr)) + { + LPWSTR path; + WCHAR desktoppath[MAX_PATH]; + BOOL result; + + result = pSHGetSpecialFolderPathW(NULL, desktoppath, CSIDL_DESKTOPDIRECTORY, FALSE); + ok(result, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError()); + + hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(!lstrcmpW(path, desktoppath), "Got %s\n", wine_dbgstr_w(path)); + if(SUCCEEDED(hr)) + CoTaskMemFree(path); + + IShellItem_Release(psi); + } + + + IShellItemArray_Release(psia); + } + + + /* Single pidl */ + psia = (void*)0xdeadbeef; + pidl_array[0] = pidl_testdir; + hr = pSHCreateShellItemArrayFromIDLists(1, pidl_array, &psia); + ok(hr == S_OK, "Got 0x%08x\n", hr); + if(SUCCEEDED(hr)) + { + IShellItem *psi; + UINT count = 0; + + hr = IShellItemArray_GetCount(psia, &count); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(count == 1, "Got %d\n", count); + + hr = IShellItemArray_GetItemAt(psia, 0, &psi); + ok(hr == S_OK, "Got 0x%08x\n", hr); + if(SUCCEEDED(hr)) + { + LPWSTR path; + hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path)); + if(SUCCEEDED(hr)) + CoTaskMemFree(path); + + IShellItem_Release(psi); + } + + IShellItemArray_Release(psia); + } + + + lstrcpyW(test1pathW, cTestDirW); + myPathAddBackslashW(test1pathW); + lstrcatW(test1pathW, test1W); + + SHGetDesktopFolder(&pdesktopsf); + + hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, test1pathW, NULL, &pidltest1, NULL); + ok(hr == S_OK, "Got 0x%08x\n", hr); + if(SUCCEEDED(hr)) + { + psia = (void*)0xdeadbeef; + pidl_array[0] = pidl_testdir; + pidl_array[1] = pidltest1; + hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia); + ok(hr == S_OK, "Got 0x%08x\n", hr); + if(SUCCEEDED(hr)) + { + IShellItem *psi; + UINT count = 0; + + hr = IShellItemArray_GetCount(psia, &count); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(count == 2, "Got %d\n", count); + + hr = IShellItemArray_GetItemAt(psia, 0, &psi); + ok(hr == S_OK, "Got 0x%08x\n", hr); + if(SUCCEEDED(hr)) + { + LPWSTR path; + hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path)); + if(SUCCEEDED(hr)) + CoTaskMemFree(path); + + IShellItem_Release(psi); + } + + hr = IShellItemArray_GetItemAt(psia, 1, &psi); + ok(hr == S_OK, "Got 0x%08x\n", hr); + if(SUCCEEDED(hr)) + { + LPWSTR path; + hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path); + ok(hr == S_OK, "Got 0x%08x\n", hr); + ok(!lstrcmpW(path, test1pathW), "Got %s\n", wine_dbgstr_w(path)); + if(SUCCEEDED(hr)) + CoTaskMemFree(path); + + IShellItem_Release(psi); + } + + + IShellItemArray_Release(psia); + } + + pILFree(pidltest1); + } + + IShellFolder_Release(pdesktopsf); + } + else + skip("No SHCreateShellItemArrayFromIDLists.\n"); + IShellFolder_Release(psf); pILFree(pidl_testdir); Cleanup(); diff --git a/include/shobjidl.idl b/include/shobjidl.idl index ae42c2e..627a6df 100644 --- a/include/shobjidl.idl +++ b/include/shobjidl.idl @@ -589,6 +589,7 @@ cpp_quote("HRESULT WINAPI SHGetIDListFromObject(IUnknown *punk, PIDLIST_ABSOLUTE 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);") cpp_quote("HRESULT WINAPI SHCreateShellItemArrayFromShellItem(IShellItem *psi, REFIID riid, void **ppv);") +cpp_quote("HRESULT WINAPI SHCreateShellItemArrayFromIDLists(UINT cidl, PCIDLIST_ABSOLUTE_ARRAY pidl_array, IShellItemArray **psia);") cpp_quote("HRESULT WINAPI SHCreateShellItemArrayFromDataObject(IDataObject *pdo, REFIID riid, void **ppv);") /***************************************************************************** diff --git a/include/shtypes.idl b/include/shtypes.idl index a8ee131..3d54c80 100644 --- a/include/shtypes.idl +++ b/include/shtypes.idl @@ -41,6 +41,7 @@ typedef LPCITEMIDLIST *PCUITEMID_CHILD_ARRAY; typedef LPCITEMIDLIST PCUIDLIST_RELATIVE; typedef LPITEMIDLIST PIDLIST_ABSOLUTE; typedef LPCITEMIDLIST PCIDLIST_ABSOLUTE; +typedef LPCITEMIDLIST *PCIDLIST_ABSOLUTE_ARRAY; cpp_quote("#include ") #ifndef MAX_PATH -- 2.0.1