[PATCH 5/7] shell32: Implement SHCreateShellItemFromIDLists.

David Hedberg david.hedberg at gmail.com
Wed Jul 30 13:43:24 CDT 2014


---
 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 <poppack.h>")
 
 #ifndef MAX_PATH
-- 
2.0.1




More information about the wine-patches mailing list