shell32: Implement SHGetItemFromDataObject.

This commit is contained in:
David Hedberg 2010-07-22 20:17:05 +02:00 committed by Alexandre Julliard
parent 222d2142ef
commit c8c2bc8b4b
4 changed files with 227 additions and 0 deletions

View File

@ -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)

View File

@ -437,3 +437,101 @@ 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;
}

View File

@ -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();
}

View File

@ -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