Module: wine Branch: master Commit: c4b38894cdd836d0da7766985e00af5f672276dd URL: https://gitlab.winehq.org/wine/wine/-/commit/c4b38894cdd836d0da7766985e00af5...
Author: Zebediah Figura zfigura@codeweavers.com Date: Sun Mar 3 20:54:15 2024 -0600
shell32: Reimplement pasting from CF_DROP directly.
Don't convert the source to PIDLs just to convert it back to paths.
---
dlls/shell32/shlview_cmenu.c | 64 ++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 23 deletions(-)
diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c index 6951bbd4216..aa89e14346e 100644 --- a/dlls/shell32/shlview_cmenu.c +++ b/dlls/shell32/shlview_cmenu.c @@ -366,7 +366,7 @@ static HRESULT get_data_format(IDataObject *data, UINT cf, STGMEDIUM *medium) return IDataObject_GetData(data, &format, medium); }
-static HRESULT do_paste(ContextMenu *menu) +static HRESULT do_paste(ContextMenu *menu, HWND hwnd) { IDataObject *data; HRESULT hr; @@ -404,31 +404,49 @@ static HRESULT do_paste(ContextMenu *menu) } else if (SUCCEEDED(get_data_format(data, CF_HDROP, &medium))) { - WCHAR path[MAX_PATH]; - ITEMIDLIST **pidls; - UINT count; + const DROPFILES *dropfiles = GlobalLock(medium.hGlobal); + IPersistFolder2 *dst_persist; + SHFILEOPSTRUCTW op = {0}; + WCHAR dst_path[MAX_PATH]; + ITEMIDLIST *dst_pidl; + int ret; + + if (FAILED(hr = IShellFolder_QueryInterface(menu->parent, &IID_IPersistFolder2, (void **)&dst_persist))) + { + WARN("Failed to get IPersistFolder2, hr %#lx.\n", hr); + IDataObject_Release(data); + return hr; + }
- count = DragQueryFileW(medium.hGlobal, -1, NULL, 0); - pidls = SHAlloc(count * sizeof(ITEMIDLIST*)); - if (pidls) + hr = IPersistFolder2_GetCurFolder(dst_persist, &dst_pidl); + IPersistFolder2_Release(dst_persist); + if (FAILED(hr)) { - for (unsigned int i = 0; i < count; i++) - { - DragQueryFileW(medium.hGlobal, i, path, ARRAY_SIZE(path)); - if (!(pidls[i] = ILCreateFromPathW(path))) - { - hr = E_FAIL; - break; - } - } - if (SUCCEEDED(hr)) - hr = paste_pidls(menu, pidls, count); - _ILFreeaPidl(pidls, count); + ERR("Failed to get dst folder pidl, hr %#lx.\n", hr); + IDataObject_Release(data); + return hr; } - else + + if (!SHGetPathFromIDListW(dst_pidl, dst_path)) { - hr = HRESULT_FROM_WIN32(GetLastError()); + ERR("Failed to get path, hr %#lx.\n", hr); + ILFree(dst_pidl); + IDataObject_Release(data); + return E_FAIL; } + + op.hwnd = hwnd; + op.wFunc = FO_COPY; + op.pFrom = (const WCHAR *)((const char *)dropfiles + dropfiles->pFiles); + op.pTo = dst_path; + op.fFlags = FOF_ALLOWUNDO; + if ((ret = SHFileOperationW(&op))) + { + WARN("Failed to copy, ret %d.\n", ret); + hr = E_FAIL; + } + + GlobalUnlock(medium.hGlobal); ReleaseStgMedium(&medium); } else @@ -1371,7 +1389,7 @@ static HRESULT WINAPI BackgroundMenu_InvokeCommand( } else if (!strcmp(lpcmi->lpVerb, "paste")) { - do_paste(This); + do_paste(This, lpcmi->hwnd); } else { @@ -1391,7 +1409,7 @@ static HRESULT WINAPI BackgroundMenu_InvokeCommand( break;
case FCIDM_SHVIEW_INSERT: - do_paste(This); + do_paste(This, lpcmi->hwnd); break;
case FCIDM_SHVIEW_PROPERTIES: