Damjan Jovanovic : shell32: Support the CF_HDROP format too when pasting from the context menu.
Alexandre Julliard
julliard at winehq.org
Wed May 26 15:46:27 CDT 2021
Module: wine
Branch: master
Commit: 91b0340170a60f7229cb9419ccb6b6f7d9adc692
URL: https://source.winehq.org/git/wine.git/?a=commit;h=91b0340170a60f7229cb9419ccb6b6f7d9adc692
Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date: Tue May 25 07:53:28 2021 +0200
shell32: Support the CF_HDROP format too when pasting from the context menu.
Signed-off-by: Damjan Jovanovic <damjan.jov at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/shell32/shlview_cmenu.c | 95 +++++++++++++++++++++++++++++++++++++++++-
dlls/shell32/tests/shlfolder.c | 10 +++++
2 files changed, 104 insertions(+), 1 deletion(-)
diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c
index 3d79f82a92e..dd03c64e654 100644
--- a/dlls/shell32/shlview_cmenu.c
+++ b/dlls/shell32/shlview_cmenu.c
@@ -1134,10 +1134,59 @@ static void DoNewFolder(ContextMenu *This, IShellView *view)
}
}
+static HRESULT paste_pidls(ContextMenu *This, ITEMIDLIST **pidls, UINT count)
+{
+ IShellFolder *psfDesktop;
+ UINT i;
+ HRESULT hr = S_OK;
+
+ /* bind to the source shellfolder */
+ hr = SHGetDesktopFolder(&psfDesktop);
+ if (FAILED(hr))
+ return hr;
+
+ for (i = 0; SUCCEEDED(hr) && i < count; i++) {
+ ITEMIDLIST *pidl_dir = NULL;
+ ITEMIDLIST *pidl_item;
+ IShellFolder *psfFrom = NULL;
+
+ pidl_dir = ILClone(pidls[i]);
+ ILRemoveLastID(pidl_dir);
+ pidl_item = ILFindLastID(pidls[i]);
+ hr = IShellFolder_BindToObject(psfDesktop, pidl_dir, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom);
+
+ if (psfFrom)
+ {
+ /* get source and destination shellfolder */
+ ISFHelper *psfhlpdst, *psfhlpsrc;
+ hr = IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst);
+ if (SUCCEEDED(hr))
+ hr = IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc);
+
+ /* do the copy/move */
+ if (psfhlpdst && psfhlpsrc)
+ {
+ hr = ISFHelper_CopyItems(psfhlpdst, psfFrom, 1, (LPCITEMIDLIST*)&pidl_item);
+ /* FIXME handle move
+ ISFHelper_DeleteItems(psfhlpsrc, 1, &pidl_item);
+ */
+ }
+ if(psfhlpdst) ISFHelper_Release(psfhlpdst);
+ if(psfhlpsrc) ISFHelper_Release(psfhlpsrc);
+ IShellFolder_Release(psfFrom);
+ }
+ SHFree(pidl_dir);
+ }
+
+ IShellFolder_Release(psfDesktop);
+ return hr;
+}
+
static BOOL DoPaste(ContextMenu *This)
{
BOOL bSuccess = TRUE;
IDataObject * pda;
+ HRESULT hr;
TRACE("\n");
@@ -1145,6 +1194,7 @@ static BOOL DoPaste(ContextMenu *This)
{
STGMEDIUM medium;
FORMATETC formatetc;
+ HRESULT format_hr;
TRACE("pda=%p\n", pda);
@@ -1152,7 +1202,8 @@ static BOOL DoPaste(ContextMenu *This)
InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW), TYMED_HGLOBAL);
/* Get the pidls from IDataObject */
- if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium)))
+ format_hr = IDataObject_GetData(pda,&formatetc,&medium);
+ if(SUCCEEDED(format_hr))
{
LPITEMIDLIST * apidl;
LPITEMIDLIST pidl;
@@ -1215,6 +1266,48 @@ static BOOL DoPaste(ContextMenu *This)
}
else
bSuccess = FALSE;
+
+ if(FAILED(format_hr))
+ {
+ InitFormatEtc(formatetc, CF_HDROP, TYMED_HGLOBAL);
+ format_hr = IDataObject_GetData(pda,&formatetc,&medium);
+ if(SUCCEEDED(format_hr))
+ {
+ WCHAR path[MAX_PATH];
+ UINT i, count;
+ ITEMIDLIST **pidls;
+
+ TRACE("CF_HDROP=%p\n", medium.u.hGlobal);
+ count = DragQueryFileW(medium.u.hGlobal, -1, NULL, 0);
+ pidls = SHAlloc(count*sizeof(ITEMIDLIST**));
+ if (pidls)
+ {
+ for (i = 0; i < count; i++)
+ {
+ DragQueryFileW(medium.u.hGlobal, i, path, ARRAY_SIZE(path));
+ if ((pidls[i] = ILCreateFromPathW(path)) == NULL)
+ {
+ hr = E_FAIL;
+ break;
+ }
+ }
+ if (SUCCEEDED(hr))
+ hr = paste_pidls(This, pidls, count);
+ _ILFreeaPidl(pidls, count);
+ }
+ else
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ ReleaseStgMedium(&medium);
+ bSuccess = SUCCEEDED(hr);
+ }
+ }
+
+ if (FAILED(format_hr))
+ {
+ ERR("there are no supported and retrievable clipboard formats\n");
+ bSuccess = FALSE;
+ }
+
IDataObject_Release(pda);
}
else
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index 8e92a0896b5..29fcd0b7754 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -4387,7 +4387,17 @@ static void test_contextmenu(IContextMenu *menu, BOOL background)
{
trace("Got ID %d, verb %s, string %s.\n", mii.wID, debugstr_a(buf), debugstr_a(mii.dwTypeData));
if (!strcmp(buf, "copy"))
+ {
+ CMINVOKECOMMANDINFO cmi;
ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_COPY, "wrong menu wID %d\n", mii.wID);
+ memset(&cmi, 0, sizeof(CMINVOKECOMMANDINFO));
+ cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
+ cmi.lpVerb = "copy";
+ hr = IContextMenu_InvokeCommand(menu, &cmi);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(IsClipboardFormatAvailable(RegisterClipboardFormatA(CFSTR_SHELLIDLISTA)), "CFSTR_SHELLIDLISTA not available\n");
+ ok(IsClipboardFormatAvailable(CF_HDROP), "CF_HDROP not available\n");
+ }
else if (!strcmp(buf, "paste"))
ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_INSERT, "wrong menu wID %d\n", mii.wID);
else if (!strcmp(buf, "properties"))
More information about the wine-cvs
mailing list