Module: wine Branch: master Commit: 19379007e517a7e55857e1841cca0bea505d19d6 URL: https://source.winehq.org/git/wine.git/?a=commit;h=19379007e517a7e55857e1841...
Author: Damjan Jovanovic damjan.jov@gmail.com Date: Mon May 3 03:13:28 2021 +0200
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
---
dlls/shell32/shlview_cmenu.c | 65 ++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 23 deletions(-)
diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c index bd58a448d17..67f5ac80d84 100644 --- a/dlls/shell32/shlview_cmenu.c +++ b/dlls/shell32/shlview_cmenu.c @@ -1136,7 +1136,7 @@ static void DoNewFolder(ContextMenu *This, IShellView *view)
static BOOL DoPaste(ContextMenu *This) { - BOOL bSuccess = FALSE; + BOOL bSuccess = TRUE; IDataObject * pda;
TRACE("\n"); @@ -1157,38 +1157,53 @@ static BOOL DoPaste(ContextMenu *This) LPITEMIDLIST * apidl; LPITEMIDLIST pidl; IShellFolder *psfFrom = NULL, *psfDesktop; + int i;
LPIDA lpcida = GlobalLock(medium.u.hGlobal); TRACE("cida=%p\n", lpcida);
apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
- /* bind to the source shellfolder */ - SHGetDesktopFolder(&psfDesktop); - if(psfDesktop) - { - IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom); - IShellFolder_Release(psfDesktop); - } + for (i = 0; bSuccess && i < lpcida->cidl; i++) { + ITEMIDLIST *apidl_dir = NULL; + ITEMIDLIST *apidl_item;
- if (psfFrom) - { - /* get source and destination shellfolder */ - ISFHelper *psfhlpdst, *psfhlpsrc; - IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst); - IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc); + psfFrom = NULL; + /* bind to the source shellfolder */ + SHGetDesktopFolder(&psfDesktop); + if(psfDesktop) + { + apidl_dir = ILClone(apidl[i]); + ILRemoveLastID(apidl_dir); + apidl_item = ILFindLastID(apidl[i]); + IShellFolder_BindToObject(psfDesktop, apidl_dir, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom); + IShellFolder_Release(psfDesktop); + }
- /* do the copy/move */ - if (psfhlpdst && psfhlpsrc) + if (psfFrom) { - ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); - /* FIXME handle move - ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl); - */ + /* 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); } - if(psfhlpdst) ISFHelper_Release(psfhlpdst); - if(psfhlpsrc) ISFHelper_Release(psfhlpsrc); - IShellFolder_Release(psfFrom); + else + bSuccess = FALSE; + SHFree(apidl_dir); }
_ILFreeaPidl(apidl, lpcida->cidl); @@ -1197,8 +1212,12 @@ static BOOL DoPaste(ContextMenu *This) /* release the medium*/ ReleaseStgMedium(&medium); } + else + bSuccess = FALSE; IDataObject_Release(pda); } + else + bSuccess = FALSE; #if 0 HGLOBAL hMem;