[PATCH 4/6] shell32: Implement SHGetItemFromDataObject. (resend)
David Hedberg
david.hedberg at gmail.com
Thu Jul 22 13:17:05 CDT 2010
---
dlls/shell32/shell32.spec | 1 +
dlls/shell32/shellitem.c | 99 +++++++++++++++++++++++++++++++++
dlls/shell32/tests/shlfolder.c | 117 ++++++++++++++++++++++++++++++++++++++++
include/shobjidl.idl | 11 ++++
4 files changed, 228 insertions(+), 0 deletions(-)
diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec
index cc7744d..88f1f5d 100644
--- a/dlls/shell32/shell32.spec
+++ b/dlls/shell32/shell32.spec
@@ -360,6 +360,7 @@
@ stdcall SHGetIconOverlayIndexA(str long)
@ stdcall SHGetIconOverlayIndexW(wstr long)
@ stdcall SHGetInstanceExplorer(long)
+@ stdcall SHGetItemFromDataObject(ptr long ptr ptr)
@ stdcall SHGetLocalizedName(wstr ptr long ptr)
@ stdcall SHGetMalloc(ptr)
@ stdcall SHGetNameFromIDList(ptr long ptr)
diff --git a/dlls/shell32/shellitem.c b/dlls/shell32/shellitem.c
index 84a195f..523bdb9 100644
--- a/dlls/shell32/shellitem.c
+++ b/dlls/shell32/shellitem.c
@@ -437,3 +437,102 @@ HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void
return ret;
}
+
+HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj,
+ DATAOBJ_GET_ITEM_FLAGS dwFlags, REFIID riid, void **ppv)
+{
+ FORMATETC fmt;
+ STGMEDIUM medium;
+ HRESULT ret;
+
+ TRACE("%p, %x, %s, %p\n", pdtobj, dwFlags, debugstr_guid(riid), ppv);
+
+ if(!pdtobj)
+ return E_INVALIDARG;
+
+ fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
+ fmt.ptd = NULL;
+ fmt.dwAspect = DVASPECT_CONTENT;
+ fmt.lindex = -1;
+ fmt.tymed = TYMED_HGLOBAL;
+
+ ret = IDataObject_GetData(pdtobj, &fmt, &medium);
+ if(SUCCEEDED(ret))
+ {
+ LPIDA pida = GlobalLock(medium.u.hGlobal);
+
+ if((pida->cidl > 1 && !(dwFlags & DOGIF_ONLY_IF_ONE)) ||
+ pida->cidl == 1)
+ {
+ LPITEMIDLIST pidl;
+
+ /* Get the first pidl (parent + child1) */
+ pidl = ILCombine((LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]),
+ (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]));
+
+ ret = SHCreateItemFromIDList(pidl, riid, ppv);
+ ILFree(pidl);
+ }
+ else
+ {
+ ret = E_FAIL;
+ }
+
+ GlobalUnlock(medium.u.hGlobal);
+ GlobalFree(medium.u.hGlobal);
+ }
+
+ if(FAILED(ret) && !(dwFlags & DOGIF_NO_HDROP))
+ {
+ TRACE("Attempting to fall back on CF_HDROP.\n");
+
+ fmt.cfFormat = CF_HDROP;
+ fmt.ptd = NULL;
+ fmt.dwAspect = DVASPECT_CONTENT;
+ fmt.lindex = -1;
+ fmt.tymed = TYMED_HGLOBAL;
+
+ ret = IDataObject_GetData(pdtobj, &fmt, &medium);
+ if(SUCCEEDED(ret))
+ {
+ DROPFILES *df = GlobalLock(medium.u.hGlobal);
+ LPBYTE files = (LPBYTE)df + df->pFiles;
+ BOOL multiple_files = FALSE;
+
+ ret = E_FAIL;
+ if(!df->fWide)
+ {
+ WCHAR filename[MAX_PATH];
+ PCSTR first_file = (PCSTR)files;
+ if(*(files + lstrlenA(first_file) + 1) != 0)
+ multiple_files = TRUE;
+
+ if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
+ {
+ MultiByteToWideChar(CP_ACP, 0, first_file, -1, filename, MAX_PATH);
+ ret = SHCreateItemFromParsingName(filename, NULL, riid, ppv);
+ }
+ }
+ else
+ {
+ PCWSTR first_file = (PCWSTR)files;
+ if(*((PCWSTR)files + lstrlenW(first_file) + 1) != 0)
+ multiple_files = TRUE;
+
+ if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
+ ret = SHCreateItemFromParsingName(first_file, NULL, riid, ppv);
+ }
+
+ GlobalUnlock(medium.u.hGlobal);
+ GlobalFree(medium.u.hGlobal);
+ }
+ }
+
+ if(FAILED(ret) && !(dwFlags & DOGIF_NO_URL))
+ {
+ FIXME("Failed to create item, should try CF_URL.\n");
+ }
+
+ return ret;
+}
+
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index 7eda991..485cefd 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -60,6 +60,7 @@ static LPITEMIDLIST (WINAPI *pILCombine)(LPCITEMIDLIST,LPCITEMIDLIST);
static HRESULT (WINAPI *pSHParseDisplayName)(LPCWSTR,IBindCtx*,LPITEMIDLIST*,SFGAOF,SFGAOF*);
static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPathAW)(LPCVOID);
static HRESULT (WINAPI *pSHGetNameFromIDList)(PCIDLIST_ABSOLUTE,SIGDN,PWSTR*);
+static HRESULT (WINAPI *pSHGetItemFromDataObject)(IDataObject*,DATAOBJ_GET_ITEM_FLAGS,REFIID,void**);
static void init_function_pointers(void)
{
@@ -82,6 +83,7 @@ static void init_function_pointers(void)
MAKEFUNC(SHGetSpecialFolderLocation);
MAKEFUNC(SHParseDisplayName);
MAKEFUNC(SHGetNameFromIDList);
+ MAKEFUNC(SHGetItemFromDataObject);
#undef MAKEFUNC
#define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
@@ -2293,6 +2295,120 @@ static void test_SHGetNameFromIDList(void)
pILFree(pidl);
}
+static void test_SHGetItemFromDataObject(void)
+{
+ IShellFolder *psfdesktop;
+ IShellItem *psi;
+ IShellView *psv;
+ HRESULT hres;
+
+ if(!pSHGetItemFromDataObject)
+ {
+ win_skip("No SHGetItemFromDataObject.\n");
+ return;
+ }
+
+ if(0)
+ {
+ /* Crashes under win7 */
+ hres = pSHGetItemFromDataObject(NULL, 0, &IID_IShellItem, NULL);
+ }
+
+ hres = pSHGetItemFromDataObject(NULL, 0, &IID_IShellItem, (void**)&psv);
+ ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
+
+ SHGetDesktopFolder(&psfdesktop);
+
+ hres = IShellFolder_CreateViewObject(psfdesktop, NULL, &IID_IShellView, (void**)&psv);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ IEnumIDList *peidl;
+ IDataObject *pdo;
+ SHCONTF enum_flags;
+
+ enum_flags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN;
+ hres = IShellFolder_EnumObjects(psfdesktop, NULL, enum_flags, &peidl);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ LPITEMIDLIST apidl[5];
+ UINT count = 0, i;
+
+ for(count = 0; count < 5; count++)
+ if(IEnumIDList_Next(peidl, 1, &apidl[count], NULL) != S_OK)
+ break;
+
+ if(count)
+ {
+ hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, 1, (LPCITEMIDLIST*)apidl,
+ &IID_IDataObject, NULL, (void**)&pdo);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_DEFAULT, &IID_IShellItem, (void**)&psi);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_TRAVERSE_LINK, &IID_IShellItem, (void**)&psi);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_HDROP, &IID_IShellItem, (void**)&psi);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_URL, &IID_IShellItem, (void**)&psi);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_ONLY_IF_ONE, &IID_IShellItem, (void**)&psi);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+
+ IDataObject_Release(pdo);
+ }
+ }
+ else
+ skip("No file(s) found - skipping single-file test.\n");
+
+ if(count > 1)
+ {
+ hres = IShellFolder_GetUIObjectOf(psfdesktop, NULL, count, (LPCITEMIDLIST*)apidl,
+ &IID_IDataObject, NULL, (void**)&pdo);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_DEFAULT, &IID_IShellItem, (void**)&psi);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_TRAVERSE_LINK, &IID_IShellItem, (void**)&psi);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_HDROP, &IID_IShellItem, (void**)&psi);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_NO_URL, &IID_IShellItem, (void**)&psi);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+ hres = pSHGetItemFromDataObject(pdo, DOGIF_ONLY_IF_ONE, &IID_IShellItem, (void**)&psi);
+ ok(hres == E_FAIL, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres)) IShellItem_Release(psi);
+
+ IDataObject_Release(pdo);
+ }
+ }
+ else
+ skip("zero or one file found - skipping multi-file test.\n");
+
+ for(i = 0; i < count; i++)
+ pILFree(apidl[i]);
+
+ IEnumIDList_Release(peidl);
+ }
+
+ IShellView_Release(psv);
+ }
+
+ IShellFolder_Release(psfdesktop);
+}
+
static void test_SHParseDisplayName(void)
{
LPITEMIDLIST pidl1, pidl2;
@@ -2799,6 +2915,7 @@ START_TEST(shlfolder)
test_SHSimpleIDListFromPath();
test_ParseDisplayNamePBC();
test_SHGetNameFromIDList();
+ test_SHGetItemFromDataObject();
OleUninitialize();
}
diff --git a/include/shobjidl.idl b/include/shobjidl.idl
index d79c932..feee7ff 100644
--- a/include/shobjidl.idl
+++ b/include/shobjidl.idl
@@ -494,9 +494,20 @@ interface IShellItemArray : IUnknown
}
+typedef [v1_enum] enum DATAOBJ_GET_ITEM_FLAGS
+{
+ DOGIF_DEFAULT = 0x0,
+ DOGIF_TRAVERSE_LINK = 0x1,
+ DOGIF_NO_HDROP = 0x2,
+ DOGIF_NO_URL = 0x4,
+ DOGIF_ONLY_IF_ONE = 0x8
+} DATAOBJ_GET_ITEM_FLAGS;
+cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(DATAOBJ_GET_ITEM_FLAGS)")
+
cpp_quote("HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWSTR *ppszName);")
cpp_quote("HRESULT WINAPI SHCreateItemFromParsingName(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);")
cpp_quote("HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv);")
+cpp_quote("HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj, DATAOBJ_GET_ITEM_FLAGS dwFlags, REFIID riid, void **ppv);")
/*****************************************************************************
* IShellItemFilter interface
--
1.7.1.1
More information about the wine-patches
mailing list