[PATCH 5/6] shell32: Implement SHGetIDListFromObject. (resend)
David Hedberg
david.hedberg at gmail.com
Thu Jul 22 13:17:06 CDT 2010
---
dlls/shell32/pidl.c | 75 ++++++++++++++
dlls/shell32/shell32.spec | 1 +
dlls/shell32/tests/shlfolder.c | 219 ++++++++++++++++++++++++++++++++++++++++
include/shobjidl.idl | 1 +
4 files changed, 296 insertions(+), 0 deletions(-)
diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c
index 9ec0dd4..a596ebf 100644
--- a/dlls/shell32/pidl.c
+++ b/dlls/shell32/pidl.c
@@ -1405,6 +1405,81 @@ HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWST
IShellFolder_Release(psfparent);
}
+ return ret;
+}
+
+/*************************************************************************
+ * SHGetIDListFromObject [SHELL32.@]
+ */
+HRESULT WINAPI SHGetIDListFromObject(IUnknown *punk, PIDLIST_ABSOLUTE *ppidl)
+{
+ IPersistIDList *ppersidl;
+ IPersistFolder2 *ppf2;
+ IDataObject *pdo;
+ IFolderView *pfv;
+ HRESULT ret;
+
+ if(!punk)
+ return E_NOINTERFACE;
+
+ *ppidl = NULL;
+
+ /* Try IPersistIDList */
+ ret = IUnknown_QueryInterface(punk, &IID_IPersistIDList, (void**)&ppersidl);
+ if(SUCCEEDED(ret))
+ {
+ TRACE("IPersistIDList (%p)\n", ppersidl);
+ ret = IPersistIDList_GetIDList(ppersidl, ppidl);
+ IPersistIDList_Release(ppersidl);
+ if(SUCCEEDED(ret))
+ return ret;
+ }
+
+ /* Try IPersistFolder2 */
+ ret = IUnknown_QueryInterface(punk, &IID_IPersistFolder2, (void**)&ppf2);
+ if(SUCCEEDED(ret))
+ {
+ TRACE("IPersistFolder2 (%p)\n", ppf2);
+ ret = IPersistFolder2_GetCurFolder(ppf2, ppidl);
+ IPersistFolder2_Release(ppf2);
+ if(SUCCEEDED(ret))
+ return ret;
+ }
+
+ /* Try IDataObject */
+ ret = IUnknown_QueryInterface(punk, &IID_IDataObject, (void**)&pdo);
+ if(SUCCEEDED(ret))
+ {
+ IShellItem *psi;
+ TRACE("IDataObject (%p)\n", pdo);
+ ret = SHGetItemFromDataObject(pdo, DOGIF_ONLY_IF_ONE,
+ &IID_IShellItem, (void**)&psi);
+ if(SUCCEEDED(ret))
+ {
+ ret = SHGetIDListFromObject((IUnknown*)psi, ppidl);
+ IShellItem_Release(psi);
+ }
+ IDataObject_Release(pdo);
+
+ if(SUCCEEDED(ret))
+ return ret;
+ }
+
+ /* Try IFolderView */
+ ret = IUnknown_QueryInterface(punk, &IID_IFolderView, (void**)&pfv);
+ if(SUCCEEDED(ret))
+ {
+ IShellFolder *psf;
+ TRACE("IFolderView (%p)\n", pfv);
+ ret = IFolderView_GetFolder(pfv, &IID_IShellFolder, (void**)&psf);
+ if(SUCCEEDED(ret))
+ {
+ /* We might be able to get IPersistFolder2 from a shellfolder. */
+ ret = SHGetIDListFromObject((IUnknown*)psf, ppidl);
+ }
+ IFolderView_Release(pfv);
+ return ret;
+ }
return ret;
}
diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec
index 88f1f5d..c11f20e 100644
--- a/dlls/shell32/shell32.spec
+++ b/dlls/shell32/shell32.spec
@@ -359,6 +359,7 @@
@ stub SHGetFreeDiskSpace
@ stdcall SHGetIconOverlayIndexA(str long)
@ stdcall SHGetIconOverlayIndexW(wstr long)
+@ stdcall SHGetIDListFromObject(ptr ptr)
@ stdcall SHGetInstanceExplorer(long)
@ stdcall SHGetItemFromDataObject(ptr long ptr ptr)
@ stdcall SHGetLocalizedName(wstr ptr long ptr)
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index 485cefd..cf7150e 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -39,6 +39,8 @@
#include "wine/test.h"
+#include <initguid.h>
+DEFINE_GUID(IID_IParentAndItem, 0xB3A4B685, 0xB685, 0x4805, 0x99,0xD9, 0x5D,0xEA,0xD2,0x87,0x32,0x36);
static IMalloc *ppM;
@@ -61,6 +63,7 @@ static HRESULT (WINAPI *pSHParseDisplayName)(LPCWSTR,IBindCtx*,LPITEMIDLIST*,SFG
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 HRESULT (WINAPI *pSHGetIDListFromObject)(IUnknown*, PIDLIST_ABSOLUTE*);
static void init_function_pointers(void)
{
@@ -84,6 +87,7 @@ static void init_function_pointers(void)
MAKEFUNC(SHParseDisplayName);
MAKEFUNC(SHGetNameFromIDList);
MAKEFUNC(SHGetItemFromDataObject);
+ MAKEFUNC(SHGetIDListFromObject);
#undef MAKEFUNC
#define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
@@ -2390,6 +2394,219 @@ static void test_SHGetItemFromDataObject(void)
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);
+}
+
+/**************************************************************/
+/* IUnknown implementation for counting QueryInterface calls. */
+typedef struct {
+ const IUnknownVtbl *lpVtbl;
+ struct if_count {
+ REFIID id;
+ LONG count;
+ } *ifaces;
+ LONG unknown;
+} IUnknownImpl;
+
+static HRESULT WINAPI unk_fnQueryInterface(IUnknown *iunk, REFIID riid, void** punk)
+{
+ IUnknownImpl *This = (IUnknownImpl*)iunk;
+ UINT i, found;
+ for(i = found = 0; This->ifaces[i].id != NULL; i++)
+ {
+ if(IsEqualIID(This->ifaces[i].id, riid))
+ {
+ This->ifaces[i].count++;
+ found = 1;
+ break;
+ }
+ }
+ if(!found)
+ This->unknown++;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI unk_fnAddRef(IUnknown *iunk)
+{
+ return 2;
+}
+
+static ULONG WINAPI unk_fnRelease(IUnknown *iunk)
+{
+ return 1;
+}
+
+const IUnknownVtbl vt_IUnknown = {
+ unk_fnQueryInterface,
+ unk_fnAddRef,
+ unk_fnRelease
+};
+
+static void test_SHGetIDListFromObject(void)
+{
+ IUnknownImpl *punkimpl;
+ IShellFolder *psfdesktop;
+ IShellView *psv;
+ LPITEMIDLIST pidl, pidl_desktop;
+ HRESULT hres;
+ UINT i;
+ struct if_count ifaces[] =
+ { {&IID_IPersistIDList, 0},
+ {&IID_IPersistFolder2, 0},
+ {&IID_IDataObject, 0},
+ {&IID_IParentAndItem, 0},
+ {&IID_IFolderView, 0},
+ {NULL, 0} };
+
+ if(!pSHGetIDListFromObject)
+ {
+ win_skip("SHGetIDListFromObject missing.\n");
+ return;
+ }
+
+ ok(pSHGetSpecialFolderLocation != NULL, "SHGetSpecialFolderLocation missing.\n");
+
+ if(0)
+ {
+ /* Crashes native */
+ pSHGetIDListFromObject(NULL, NULL);
+ pSHGetIDListFromObject((void*)0xDEADBEEF, NULL);
+ }
+
+ hres = pSHGetIDListFromObject(NULL, &pidl);
+ ok(hres == E_NOINTERFACE, "Got %x\n", hres);
+
+ punkimpl = HeapAlloc(GetProcessHeap(), 0, sizeof(IUnknownImpl));
+ punkimpl->lpVtbl = &vt_IUnknown;
+ punkimpl->ifaces = ifaces;
+ punkimpl->unknown = 0;
+
+ hres = pSHGetIDListFromObject((IUnknown*)punkimpl, &pidl);
+ ok(hres == E_NOINTERFACE, "Got %x\n", hres);
+ ok(ifaces[0].count, "interface not requested.\n");
+ ok(ifaces[1].count, "interface not requested.\n");
+ ok(ifaces[2].count, "interface not requested.\n");
+ todo_wine
+ ok(ifaces[3].count || broken(!ifaces[3].count /*vista*/),
+ "interface not requested.\n");
+ ok(ifaces[4].count || broken(!ifaces[4].count /*vista*/),
+ "interface not requested.\n");
+
+ ok(!punkimpl->unknown, "Got %d unknown.\n", punkimpl->unknown);
+ HeapFree(GetProcessHeap(), 0, punkimpl);
+
+ pidl_desktop = NULL;
+ pSHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl_desktop);
+ ok(pidl_desktop != NULL, "Failed to get desktop pidl.\n");
+
+ SHGetDesktopFolder(&psfdesktop);
+
+ /* Test IShellItem */
+ if(pSHCreateShellItem)
+ {
+ IShellItem *shellitem;
+ hres = pSHCreateShellItem(NULL, NULL, pidl_desktop, &shellitem);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ hres = pSHGetIDListFromObject((IUnknown*)shellitem, &pidl);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ ok(ILIsEqual(pidl_desktop, pidl), "pidl not equal.\n");
+ pILFree(pidl);
+ }
+ IShellItem_Release(shellitem);
+ }
+ }
+ else
+ skip("no SHCreateShellItem.\n");
+
+ /* Test IShellFolder */
+ hres = pSHGetIDListFromObject((IUnknown*)psfdesktop, &pidl);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ ok(ILIsEqual(pidl_desktop, pidl), "pidl not equal.\n");
+ pILFree(pidl);
+ }
+
+ 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;
+
+ /* Test IFolderView */
+ hres = pSHGetIDListFromObject((IUnknown*)psv, &pidl);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ if(SUCCEEDED(hres))
+ {
+ ok(ILIsEqual(pidl_desktop, pidl), "pidl not equal.\n");
+ pILFree(pidl);
+ }
+
+ /* Test IDataObject */
+ 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;
+ 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))
+ {
+ pidl = (void*)0xDEADBEEF;
+ hres = pSHGetIDListFromObject((IUnknown*)pdo, &pidl);
+ ok(hres == S_OK, "got 0x%08x\n", hres);
+ ok(pidl != NULL, "pidl is NULL.\n");
+ ok(ILIsEqual(pidl, apidl[0]), "pidl not equal.\n");
+ pILFree(pidl);
+
+ IDataObject_Release(pdo);
+ }
+ }
+ else
+ skip("No files 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))
+ {
+ pidl = (void*)0xDEADBEEF;
+ hres = pSHGetIDListFromObject((IUnknown*)pdo, &pidl);
+ ok(hres == E_NOINTERFACE || hres == E_FAIL /*Vista*/,
+ "got 0x%08x\n", hres);
+ ok(pidl == NULL, "pidl is not NULL.\n");
IDataObject_Release(pdo);
}
@@ -2407,6 +2624,7 @@ static void test_SHGetItemFromDataObject(void)
}
IShellFolder_Release(psfdesktop);
+ pILFree(pidl_desktop);
}
static void test_SHParseDisplayName(void)
@@ -2916,6 +3134,7 @@ START_TEST(shlfolder)
test_ParseDisplayNamePBC();
test_SHGetNameFromIDList();
test_SHGetItemFromDataObject();
+ test_SHGetIDListFromObject();
OleUninitialize();
}
diff --git a/include/shobjidl.idl b/include/shobjidl.idl
index feee7ff..19dcd28 100644
--- a/include/shobjidl.idl
+++ b/include/shobjidl.idl
@@ -508,6 +508,7 @@ cpp_quote("HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigd
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);")
+cpp_quote("HRESULT WINAPI SHGetIDListFromObject(IUnknown *punk, PIDLIST_ABSOLUTE *ppidl);")
/*****************************************************************************
* IShellItemFilter interface
--
1.7.1.1
More information about the wine-patches
mailing list