shell32: Implement SHGetItemFromDataObject.
This commit is contained in:
parent
222d2142ef
commit
c8c2bc8b4b
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue