shell32: Support the CF_HDROP format too when pasting from the context menu.

Signed-off-by: Damjan Jovanovic <damjan.jov@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Damjan Jovanovic 2021-05-25 07:53:28 +02:00 committed by Alexandre Julliard
parent 401de24b89
commit 91b0340170
2 changed files with 104 additions and 1 deletions

View File

@ -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

View File

@ -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"))