[PATCH v2] shell32: Implement SHBindToFolderIDListParent.

Dmitry Timoshkov dmitry at baikal.ru
Thu Jun 9 10:56:59 CDT 2022


Based on SHBindToParent and SHBindToObject implementations.

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/shell32/pidl.c            | 46 +++++++++++++++++++++++++++++
 dlls/shell32/shell32.spec      |  1 +
 dlls/shell32/tests/shlfolder.c | 53 ++++++++++++++++++++++++++++++++++
 3 files changed, 100 insertions(+)

diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c
index f9c91a79132..8d42f58acc7 100644
--- a/dlls/shell32/pidl.c
+++ b/dlls/shell32/pidl.c
@@ -1364,6 +1364,52 @@ HRESULT WINAPI SHBindToObject(IShellFolder *psf, LPCITEMIDLIST pidl, IBindCtx *p
 }
 
 
+HRESULT WINAPI SHBindToFolderIDListParent(IShellFolder *psf, LPCITEMIDLIST pidl,
+    REFIID riid, void **ppv, LPCITEMIDLIST *ppidlLast)
+{
+    IShellFolder *psfDesktop = NULL;
+    HRESULT hr;
+
+    TRACE_(shell)("%p,%p,%s,%p,%p\n", psf, pidl, debugstr_guid(riid), ppv, ppidlLast);
+    pdump(pidl);
+
+    *ppv = NULL;
+    if (ppidlLast)
+        *ppidlLast = NULL;
+
+    if (!pidl)
+        return E_INVALIDARG;
+
+    if (!psf)
+    {
+        hr = SHGetDesktopFolder(&psfDesktop);
+        if (FAILED(hr))
+            return hr;
+        psf = psfDesktop;
+    }
+
+    if (_ILIsPidlSimple(pidl))
+        /* we are on desktop level */
+        hr = IShellFolder_QueryInterface(psf, riid, ppv);
+    else
+    {
+        LPITEMIDLIST pidlParent = ILClone(pidl);
+        ILRemoveLastID(pidlParent);
+        hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv);
+        SHFree(pidlParent);
+    }
+
+    if (psfDesktop)
+        IShellFolder_Release(psfDesktop);
+
+    if (SUCCEEDED(hr) && ppidlLast)
+        *ppidlLast = ILFindLastID(pidl);
+
+    TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, ppidlLast ? *ppidlLast : NULL, hr);
+    return hr;
+}
+
+
 /*************************************************************************
  * SHParseDisplayName             [SHELL32.@]
  */
diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec
index f8bf8f246e8..5b812774e1f 100644
--- a/dlls/shell32/shell32.spec
+++ b/dlls/shell32/shell32.spec
@@ -334,6 +334,7 @@
 @ stdcall SHAssocEnumHandlers(wstr long ptr)
 @ stdcall SHBindToObject(ptr ptr ptr ptr ptr)
 @ stdcall SHBindToParent(ptr ptr ptr ptr)
+@ stdcall SHBindToFolderIDListParent(ptr ptr ptr ptr ptr)
 @ stdcall SHBrowseForFolder(ptr) SHBrowseForFolderA
 @ stdcall SHBrowseForFolderA(ptr)
 @ stdcall SHBrowseForFolderW(ptr)
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index da606a9e707..1c482c06407 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -60,6 +60,7 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
 static HRESULT (WINAPI *pSHCreateDefaultContextMenu)(const DEFCONTEXTMENU*,REFIID,void**);
 static BOOL (WINAPI *pSHGetPathFromIDListEx)(PCIDLIST_ABSOLUTE,WCHAR*,DWORD,GPFIDL_FLAGS);
 static HRESULT (WINAPI *pSHGetSetFolderCustomSettings)(LPSHFOLDERCUSTOMSETTINGS,PCWSTR,DWORD);
+static HRESULT (WINAPI *pSHBindToFolderIDListParent)(IShellFolder*,LPCITEMIDLIST,REFIID,void **,LPCITEMIDLIST*);
 
 static WCHAR *make_wstr(const char *str)
 {
@@ -89,6 +90,7 @@ static void init_function_pointers(void)
     hmod = GetModuleHandleA("shell32.dll");
 
 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hmod, #f))
+    MAKEFUNC(SHBindToFolderIDListParent);
     MAKEFUNC(SHCreateItemFromIDList);
     MAKEFUNC(SHCreateItemFromParsingName);
     MAKEFUNC(SHCreateItemFromRelativeName);
@@ -5410,6 +5412,56 @@ static void test_SHGetSetFolderCustomSettings(void)
     RemoveDirectoryW(pathW);
 }
 
+static void test_SHBindToFolderIDListParent(void)
+{
+    IShellFolder *psf_desktop;
+    LPITEMIDLIST pidl;
+    HRESULT hr;
+    WCHAR path[MAX_PATH];
+    SHITEMID empty_item = { 0, { 0 } };
+    LPITEMIDLIST pidl_empty = (LPITEMIDLIST)&empty_item;
+    LPCITEMIDLIST pidl_last;
+    IShellFolder *psf;
+
+    if (!pSHBindToFolderIDListParent)
+    {
+        win_skip("SHBindToFolderIDListParent not available\n");
+        return;
+    }
+
+    GetTempPathW(ARRAY_SIZE(path), path);
+    SHGetDesktopFolder(&psf_desktop);
+
+    hr = IShellFolder_ParseDisplayName(psf_desktop, NULL, NULL, path, NULL, &pidl, 0);
+    ok(hr == S_OK, "got %#lx\n", hr);
+
+    pidl_last = NULL;
+    hr = pSHBindToFolderIDListParent(psf_desktop, pidl, &IID_IShellFolder, (void **)&psf, &pidl_last);
+    ok(hr == S_OK, "got %#lx\n", hr);
+    ok(pidl_last != NULL, "got %p\n", pidl_last);
+    IShellFolder_Release(psf);
+
+    hr = pSHBindToFolderIDListParent(NULL, pidl_empty, &IID_IShellFolder, (void **)&psf, &pidl_last);
+    ok(hr == S_OK, "got %#lx\n", hr);
+    ok(pidl_last == pidl_empty, "got %p\n", pidl_last);
+    IShellFolder_Release(psf);
+
+    hr = pSHBindToFolderIDListParent(NULL, pidl, &IID_IShellFolder, (void **)&psf, NULL);
+    ok(hr == S_OK, "got %#lx\n", hr);
+    IShellFolder_Release(psf);
+
+    if (0) /* crashes under Windows */
+        hr = pSHBindToFolderIDListParent(NULL, pidl, &IID_IShellFolder, NULL, NULL);
+
+    ILFree(pidl);
+    IShellFolder_Release(psf_desktop);
+
+    pidl_last = (LPITEMIDLIST)0xdeadbeef;
+    hr = pSHBindToFolderIDListParent(NULL, NULL, &IID_IShellFolder, (void **)&psf, &pidl_last);
+    ok(hr == E_INVALIDARG, "got %#lx\n", hr);
+    ok(pidl_last == NULL, "got %p\n", pidl_last);
+}
+
 START_TEST(shlfolder)
 {
     init_function_pointers();
@@ -5417,6 +5469,7 @@ START_TEST(shlfolder)
        CO_E_NOTINITIALIZED for malformed directory names */
     OleInitialize(NULL);
 
+    test_SHBindToFolderIDListParent();
     test_ParseDisplayName();
     test_SHParseDisplayName();
     test_BindToObject();
-- 
2.36.1




More information about the wine-devel mailing list