Damjan Jovanovic : shell32: Fix pasting from the shellview context menu.

Alexandre Julliard julliard at winehq.org
Mon May 3 16:37:05 CDT 2021


Module: wine
Branch: master
Commit: 19379007e517a7e55857e1841cca0bea505d19d6
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=19379007e517a7e55857e1841cca0bea505d19d6

Author: Damjan Jovanovic <damjan.jov at 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 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at 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;
 




More information about the wine-cvs mailing list