Called by IE11.
Signed-off-by: Mohamad Al-Jaf mohamadaljaf@gmail.com
v4: Don't reimplement SHBindToParent.
-- v12: shell32: Fix last parameter behavior in SHBindToFolderIDListParent(). shell32/tests: Test SHBindToParent() last parameter behavior. shell32/tests: Add SHBindToFolderIDListParent() tests. shell32: Implement SHBindToFolderIDListParent().
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Called by IE11.
Signed-off-by: Mohamad Al-Jaf mohamadaljaf@gmail.com --- dlls/shell32/pidl.c | 35 ++++++++++++++++++++++++----------- dlls/shell32/shell32.spec | 1 + include/shlobj.h | 3 +++ 3 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c index f9c91a79132..a95e4c5f295 100644 --- a/dlls/shell32/pidl.c +++ b/dlls/shell32/pidl.c @@ -1290,12 +1290,20 @@ BOOL WINAPI SHGetPathFromIDListEx(LPCITEMIDLIST pidl, WCHAR *path, DWORD path_si */ HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast) { - IShellFolder * psfDesktop; - HRESULT hr=E_FAIL; + return SHBindToFolderIDListParent(NULL, pidl, riid, ppv, ppidlLast); +} + +/************************************************************************* + * SHBindToFolderIDListParent [SHELL32.@] + */ +HRESULT WINAPI SHBindToFolderIDListParent(IShellFolder *psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast) +{ + IShellFolder *psfDesktop = NULL; + HRESULT hr;
- TRACE_(shell)("pidl=%p\n", pidl); + TRACE_(shell)("%p,%p,%s\n", psf, pidl, debugstr_guid(riid)); pdump(pidl); - + if (!pidl || !ppv) return E_INVALIDARG;
@@ -1303,29 +1311,34 @@ HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCI if (ppidlLast) *ppidlLast = NULL;
- hr = SHGetDesktopFolder(&psfDesktop); - if (FAILED(hr)) - return hr; + if (!psf) + { + hr = SHGetDesktopFolder(&psfDesktop); + if (FAILED(hr)) + return hr; + psf = psfDesktop; + }
if (_ILIsPidlSimple(pidl)) { /* we are on desktop level */ - hr = IShellFolder_QueryInterface(psfDesktop, riid, ppv); + hr = IShellFolder_QueryInterface(psf, riid, ppv); } else { LPITEMIDLIST pidlParent = ILClone(pidl); ILRemoveLastID(pidlParent); - hr = IShellFolder_BindToObject(psfDesktop, pidlParent, NULL, riid, ppv); + hr = IShellFolder_BindToObject(psf, pidlParent, NULL, riid, ppv); SHFree (pidlParent); }
- IShellFolder_Release(psfDesktop); + 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); + TRACE_(shell)("-- ppv=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr); return hr; }
diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec index 4a64b80ddd9..2c969869722 100644 --- a/dlls/shell32/shell32.spec +++ b/dlls/shell32/shell32.spec @@ -332,6 +332,7 @@ @ stdcall SHAddToRecentDocs (long ptr) @ stdcall SHAppBarMessage(long ptr) @ stdcall SHAssocEnumHandlers(wstr long ptr) +@ stdcall SHBindToFolderIDListParent(ptr ptr ptr ptr ptr) @ stdcall SHBindToObject(ptr ptr ptr ptr ptr) @ stdcall SHBindToParent(ptr ptr ptr ptr) @ stdcall SHBrowseForFolder(ptr) SHBrowseForFolderA diff --git a/include/shlobj.h b/include/shlobj.h index c7452cf5f0a..c00687e84d8 100644 --- a/include/shlobj.h +++ b/include/shlobj.h @@ -1748,6 +1748,9 @@ WINSHELLAPI HRESULT WINAPI SHGetFolderPathW(HWND hwnd, int nFolder, HANDLE hToke */ WINSHELLAPI HRESULT WINAPI SHGetDesktopFolder(IShellFolder * *);
+WINSHELLAPI HRESULT WINAPI SHBindToFolderIDListParent(IShellFolder *psf, LPCITEMIDLIST pidl, REFIID riid, + LPVOID *ppv, LPCITEMIDLIST *ppidlLast); + /**************************************************************************** * SHBindToParent API */
From: Dmitry Timoshkov dmitry@baikal.ru
--- dlls/shell32/tests/shlfolder.c | 53 ++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index dc0b6cb2ee2..0891b25dab4 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) { @@ -120,6 +121,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); @@ -5550,6 +5552,56 @@ static void test_SHOpenFolderAndSelectItems(void) ILFree(folder); }
+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); + todo_wine ok(pidl_last == NULL, "got %p\n", pidl_last); +} + START_TEST(shlfolder) { init_function_pointers(); @@ -5557,6 +5609,7 @@ START_TEST(shlfolder) CO_E_NOTINITIALIZED for malformed directory names */ OleInitialize(NULL);
+ test_SHBindToFolderIDListParent(); test_ParseDisplayName(); test_SHParseDisplayName(); test_BindToObject();
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/shell32/tests/shlfolder.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 0891b25dab4..5a5eb9fead8 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -775,9 +775,11 @@ static void test_GetDisplayName(void) ok (!lstrcmpiW(wszTestFile, wszTestFile2), "SHGetPathFromIDListW returns incorrect path!\n");
/* SHBindToParent fails, if called with a NULL PIDL. */ + pidlLast = (LPITEMIDLIST)0xdeadbeef; hr = SHBindToParent(NULL, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast); ok (hr == E_INVALIDARG || broken(hr == E_OUTOFMEMORY) /* XP */, "SHBindToParent(NULL) should fail! hr = %08lx\n", hr); + todo_wine ok(pidlLast == NULL, "got %p\n", pidlLast);
/* But it succeeds with an empty PIDL. */ hr = SHBindToParent(pidlEmpty, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast);
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/shell32/pidl.c | 7 ++++--- dlls/shell32/tests/shlfolder.c | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c index a95e4c5f295..c9ff5acbfc5 100644 --- a/dlls/shell32/pidl.c +++ b/dlls/shell32/pidl.c @@ -1304,12 +1304,13 @@ HRESULT WINAPI SHBindToFolderIDListParent(IShellFolder *psf, LPCITEMIDLIST pidl, TRACE_(shell)("%p,%p,%s\n", psf, pidl, debugstr_guid(riid)); pdump(pidl);
+ if (ppidlLast) + *ppidlLast = NULL; + if (!pidl || !ppv) return E_INVALIDARG; - + *ppv = NULL; - if (ppidlLast) - *ppidlLast = NULL;
if (!psf) { diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 5a5eb9fead8..be22e577c8b 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -779,7 +779,7 @@ static void test_GetDisplayName(void) hr = SHBindToParent(NULL, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast); ok (hr == E_INVALIDARG || broken(hr == E_OUTOFMEMORY) /* XP */, "SHBindToParent(NULL) should fail! hr = %08lx\n", hr); - todo_wine ok(pidlLast == NULL, "got %p\n", pidlLast); + ok(pidlLast == NULL, "got %p\n", pidlLast);
/* But it succeeds with an empty PIDL. */ hr = SHBindToParent(pidlEmpty, &IID_IShellFolder, (void **)&psfPersonal, &pidlLast); @@ -5601,7 +5601,7 @@ static void test_SHBindToFolderIDListParent(void) pidl_last = (LPITEMIDLIST)0xdeadbeef; hr = pSHBindToFolderIDListParent(NULL, NULL, &IID_IShellFolder, (void **)&psf, &pidl_last); ok(hr == E_INVALIDARG, "got %#lx\n", hr); - todo_wine ok(pidl_last == NULL, "got %p\n", pidl_last); + ok(pidl_last == NULL, "got %p\n", pidl_last); }
START_TEST(shlfolder)
On Wed Apr 26 05:01:43 2023 +0000, Mohamad Al-Jaf wrote:
changed this line in [version 12 of the diff](/wine/wine/-/merge_requests/566/diffs?diff_id=44067&start_sha=7aef319bf0b0defa757d37a8df41ead203af5d6a#42a26dabc5f3819d4cc0c6173510e859aee3f411_1751_1751)
Yeah, it was a bit long.
This merge request was approved by Huw Davies.