[PATCH 5/5] shell32: Implement SHCreateShellItemArrayFromDataObject.

David Hedberg david.hedberg at gmail.com
Sun Jul 25 12:08:18 CDT 2010


---
 dlls/shell32/shell32.spec      |    1 +
 dlls/shell32/shellitemarray.c  |   52 ++++++++++++++++++++++++
 dlls/shell32/tests/shlfolder.c |   87 ++++++++++++++++++++++++++++++++++++++++
 include/shobjidl.idl           |    1 +
 4 files changed, 141 insertions(+), 0 deletions(-)

diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec
index 41cfde3..da8944a 100644
--- a/dlls/shell32/shell32.spec
+++ b/dlls/shell32/shell32.spec
@@ -335,6 +335,7 @@
 @ stub SHCreateProcessAsUserW
 @ stdcall SHCreateShellItem(ptr ptr ptr ptr)
 @ stdcall SHCreateShellItemArray(ptr ptr long ptr ptr)
+@ stdcall SHCreateShellItemArrayFromDataObject(ptr ptr ptr)
 @ stdcall SHCreateShellItemArrayFromShellItem(ptr ptr ptr)
 @ stdcall SHEmptyRecycleBinA(long str long)
 @ stdcall SHEmptyRecycleBinW(long wstr long)
diff --git a/dlls/shell32/shellitemarray.c b/dlls/shell32/shellitemarray.c
index f690eaf..1ac6e69 100644
--- a/dlls/shell32/shellitemarray.c
+++ b/dlls/shell32/shellitemarray.c
@@ -298,3 +298,55 @@ HRESULT WINAPI SHCreateShellItemArrayFromShellItem(IShellItem *psi, REFIID riid,
 
     return ret;
 }
+
+HRESULT WINAPI SHCreateShellItemArrayFromDataObject(IDataObject *pdo, REFIID riid, void **ppv)
+{
+    IShellItemArray *psia;
+    FORMATETC fmt;
+    STGMEDIUM medium;
+    HRESULT ret;
+
+    TRACE("%p, %s, %p\n", pdo, shdebugstr_guid(riid), ppv);
+
+    if(!pdo)
+        return E_INVALIDARG;
+
+    *ppv = NULL;
+
+    fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
+    fmt.ptd = NULL;
+    fmt.dwAspect = DVASPECT_CONTENT;
+    fmt.lindex = -1;
+    fmt.tymed = TYMED_HGLOBAL;
+
+    ret = IDataObject_GetData(pdo, &fmt, &medium);
+    if(SUCCEEDED(ret))
+    {
+        LPIDA pida = GlobalLock(medium.u.hGlobal);
+        LPCITEMIDLIST parent_pidl;
+        LPCITEMIDLIST *children;
+        UINT i;
+        TRACE("Converting %d objects.\n", pida->cidl);
+
+        parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
+
+        children = HeapAlloc(GetProcessHeap(), 0, sizeof(LPCITEMIDLIST)*pida->cidl);
+        for(i = 0; i < pida->cidl; i++)
+            children[i] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i+1]);
+
+        ret = SHCreateShellItemArray(parent_pidl, NULL, pida->cidl, children, (IShellItemArray**)&psia);
+
+        HeapFree(GetProcessHeap(), 0, children);
+
+        GlobalUnlock(medium.u.hGlobal);
+        GlobalFree(medium.u.hGlobal);
+    }
+
+    if(SUCCEEDED(ret))
+    {
+        ret = IShellItemArray_QueryInterface(psia, riid, ppv);
+        IShellItemArray_Release(psia);
+    }
+
+    return ret;
+}
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index b8c5da6..c2305c8 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -59,6 +59,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 *pSHCreateShellItemArrayFromDataObject)(IDataObject*, REFIID, void **);
 static HRESULT (WINAPI *pSHCreateShellItemArrayFromShellItem)(IShellItem*, REFIID, void **);
 static LPITEMIDLIST (WINAPI *pILCombine)(LPCITEMIDLIST,LPCITEMIDLIST);
 static HRESULT (WINAPI *pSHParseDisplayName)(LPCWSTR,IBindCtx*,LPITEMIDLIST*,SFGAOF,SFGAOF*);
@@ -82,6 +83,7 @@ static void init_function_pointers(void)
     MAKEFUNC(SHCreateItemFromParsingName);
     MAKEFUNC(SHCreateShellItem);
     MAKEFUNC(SHCreateShellItemArray);
+    MAKEFUNC(SHCreateShellItemArrayFromDataObject);
     MAKEFUNC(SHCreateShellItemArrayFromShellItem);
     MAKEFUNC(SHGetFolderPathA);
     MAKEFUNC(SHGetFolderPathAndSubDirA);
@@ -3112,6 +3114,91 @@ static void test_SHCreateShellItemArray(void)
     else
         skip("No SHCreateShellItemArrayFromShellItem.\n");
 
+    if(pSHCreateShellItemArrayFromDataObject)
+    {
+        IShellView *psv;
+
+        if(0)
+        {
+            /* Crashes under Windows 7 */
+            hr = pSHCreateShellItemArrayFromDataObject(NULL, &IID_IShellItemArray, NULL);
+        }
+        hr = pSHCreateShellItemArrayFromDataObject(NULL, &IID_IShellItemArray, (void**)&psia);
+        ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr);
+
+        hr = IShellFolder_CreateViewObject(psf, NULL, &IID_IShellView, (void**)&psv);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        if(SUCCEEDED(hr))
+        {
+            IEnumIDList *peidl;
+            IDataObject *pdo;
+            SHCONTF enum_flags;
+
+            enum_flags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN;
+            hr = IShellFolder_EnumObjects(psf, NULL, enum_flags, &peidl);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            if(SUCCEEDED(hr))
+            {
+                LPITEMIDLIST apidl[5];
+                UINT count, i;
+
+                for(count = 0; count < 5; count++)
+                    if(IEnumIDList_Next(peidl, 1, &apidl[count], NULL) != S_OK)
+                        break;
+                ok(count == 5, "Got %d\n", count);
+
+                if(count)
+                {
+                    hr = IShellFolder_GetUIObjectOf(psf, NULL, count, (LPCITEMIDLIST*)apidl,
+                                                    &IID_IDataObject, NULL, (void**)&pdo);
+                    ok(hr == S_OK, "Got 0x%08x\n", hr);
+                    if(SUCCEEDED(hr))
+                    {
+                        hr = pSHCreateShellItemArrayFromDataObject(pdo, &IID_IShellItemArray,
+                                                                   (void**)&psia);
+                        ok(hr == S_OK, "Got 0x%08x\n", hr);
+                        if(SUCCEEDED(hr))
+                        {
+                            UINT count_sia, i;
+                            hr = IShellItemArray_GetCount(psia, &count_sia);
+                            ok(count_sia == count, "Counts differ (%d, %d)\n", count, count_sia);
+                            for(i = 0; i < count_sia; i++)
+                            {
+                                LPITEMIDLIST pidl_abs = ILCombine(pidl_testdir, apidl[i]);
+                                IShellItem *psi;
+                                hr = IShellItemArray_GetItemAt(psia, i, &psi);
+                                ok(hr == S_OK, "Got 0x%08x\n", hr);
+                                if(SUCCEEDED(hr))
+                                {
+                                    LPITEMIDLIST pidl;
+                                    hr = pSHGetIDListFromObject((IUnknown*)psi, &pidl);
+                                    ok(hr == S_OK, "Got 0x%08x\n", hr);
+                                    ok(pidl != NULL, "pidl as NULL.\n");
+                                    ok(ILIsEqual(pidl, pidl_abs), "pidls differ.\n");
+                                    pILFree(pidl);
+                                    IShellItem_Release(psi);
+                                }
+                                pILFree(pidl_abs);
+                            }
+
+                            IShellItemArray_Release(psia);
+                        }
+
+                        IDataObject_Release(pdo);
+                    }
+                    for(i = 0; i < count; i++)
+                        pILFree(apidl[i]);
+                }
+                else
+                    skip("No files found - skipping test.\n");
+
+                IEnumIDList_Release(peidl);
+            }
+            IShellView_Release(psv);
+        }
+    }
+    else
+        skip("No SHCreateShellItemArrayFromDataObject.\n");
 
     IShellFolder_Release(psf);
     pILFree(pidl_testdir);
diff --git a/include/shobjidl.idl b/include/shobjidl.idl
index f4defe0..82d8aaf 100644
--- a/include/shobjidl.idl
+++ b/include/shobjidl.idl
@@ -519,6 +519,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 SHCreateShellItemArrayFromDataObject(IDataObject *pdo, REFIID riid, void **ppv);")
 
 /*****************************************************************************
  * IShellItemFilter interface
-- 
1.7.1.1




More information about the wine-patches mailing list