shell32: Fix pasting from the shellview context menu.

Pasting from the shellview context menu is completely broken,
as the desktop folder's BindToObject() always fails since the CIDA
parent folder PIDL is an empty PIDL. The desktop shell folder
doesn't support the ISFHelper interface either. Rather bind to
each item's immediate parent, and copy each item individually.
Also try get error handling to work a little better.

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-03 03:13:28 +02:00 committed by Alexandre Julliard
parent 566454b9dc
commit 19379007e5
1 changed files with 43 additions and 24 deletions

View File

@ -1136,7 +1136,7 @@ static void DoNewFolder(ContextMenu *This, IShellView *view)
static BOOL DoPaste(ContextMenu *This) static BOOL DoPaste(ContextMenu *This)
{ {
BOOL bSuccess = FALSE; BOOL bSuccess = TRUE;
IDataObject * pda; IDataObject * pda;
TRACE("\n"); TRACE("\n");
@ -1157,38 +1157,53 @@ static BOOL DoPaste(ContextMenu *This)
LPITEMIDLIST * apidl; LPITEMIDLIST * apidl;
LPITEMIDLIST pidl; LPITEMIDLIST pidl;
IShellFolder *psfFrom = NULL, *psfDesktop; IShellFolder *psfFrom = NULL, *psfDesktop;
int i;
LPIDA lpcida = GlobalLock(medium.u.hGlobal); LPIDA lpcida = GlobalLock(medium.u.hGlobal);
TRACE("cida=%p\n", lpcida); TRACE("cida=%p\n", lpcida);
apidl = _ILCopyCidaToaPidl(&pidl, lpcida); apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
/* bind to the source shellfolder */ for (i = 0; bSuccess && i < lpcida->cidl; i++) {
SHGetDesktopFolder(&psfDesktop); ITEMIDLIST *apidl_dir = NULL;
if(psfDesktop) ITEMIDLIST *apidl_item;
{
IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom);
IShellFolder_Release(psfDesktop);
}
if (psfFrom) psfFrom = NULL;
{ /* bind to the source shellfolder */
/* get source and destination shellfolder */ SHGetDesktopFolder(&psfDesktop);
ISFHelper *psfhlpdst, *psfhlpsrc; if(psfDesktop)
IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst);
IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc);
/* do the copy/move */
if (psfhlpdst && psfhlpsrc)
{ {
ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); apidl_dir = ILClone(apidl[i]);
/* FIXME handle move ILRemoveLastID(apidl_dir);
ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl); apidl_item = ILFindLastID(apidl[i]);
*/ IShellFolder_BindToObject(psfDesktop, apidl_dir, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom);
IShellFolder_Release(psfDesktop);
} }
if(psfhlpdst) ISFHelper_Release(psfhlpdst);
if(psfhlpsrc) ISFHelper_Release(psfhlpsrc); if (psfFrom)
IShellFolder_Release(psfFrom); {
/* get source and destination shellfolder */
ISFHelper *psfhlpdst, *psfhlpsrc;
IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst);
IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc);
/* do the copy/move */
if (psfhlpdst && psfhlpsrc)
{
HRESULT hr = ISFHelper_CopyItems(psfhlpdst, psfFrom, 1, (LPCITEMIDLIST*)&apidl_item);
if (FAILED(hr))
bSuccess = FALSE;
/* FIXME handle move
ISFHelper_DeleteItems(psfhlpsrc, 1, &apidl_item);
*/
}
if(psfhlpdst) ISFHelper_Release(psfhlpdst);
if(psfhlpsrc) ISFHelper_Release(psfhlpsrc);
IShellFolder_Release(psfFrom);
}
else
bSuccess = FALSE;
SHFree(apidl_dir);
} }
_ILFreeaPidl(apidl, lpcida->cidl); _ILFreeaPidl(apidl, lpcida->cidl);
@ -1197,8 +1212,12 @@ static BOOL DoPaste(ContextMenu *This)
/* release the medium*/ /* release the medium*/
ReleaseStgMedium(&medium); ReleaseStgMedium(&medium);
} }
else
bSuccess = FALSE;
IDataObject_Release(pda); IDataObject_Release(pda);
} }
else
bSuccess = FALSE;
#if 0 #if 0
HGLOBAL hMem; HGLOBAL hMem;