From 1f27eee3ed0356ddbaf659cb9bba262b97b65237 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sat, 2 Apr 2016 05:58:59 +0200 Subject: [PATCH] Added patches to fix multiple issues in shell32 context menu handling. --- patches/patchinstall.sh | 37 ++++ ...ing-of-files-when-using-a-context-me.patch | 30 ++++ ...et-return-value-correctly-in-DoPaste.patch | 26 +++ ...t-insert-paste-for-item-context-menu.patch | 165 ++++++++++++++++++ ...y-interpret-result-of-SHFileOperatio.patch | 35 ++++ ...ort-for-setting-getting-PREFERREDDRO.patch | 159 +++++++++++++++++ ...meter-to-ISFHelper-DeleteItems-to-al.patch | 152 ++++++++++++++++ ...ource-files-when-using-cut-in-the-co.patch | 113 ++++++++++++ ...e-cut-copy-paste-string-verbs-in-ite.patch | 30 ++++ patches/shell32-Context_Menu/definition | 3 + 10 files changed, 750 insertions(+) create mode 100644 patches/shell32-Context_Menu/0001-shell32-Fix-copying-of-files-when-using-a-context-me.patch create mode 100644 patches/shell32-Context_Menu/0002-shell32-Set-return-value-correctly-in-DoPaste.patch create mode 100644 patches/shell32-Context_Menu/0003-shell32-Implement-insert-paste-for-item-context-menu.patch create mode 100644 patches/shell32-Context_Menu/0004-shell32-Correctly-interpret-result-of-SHFileOperatio.patch create mode 100644 patches/shell32-Context_Menu/0005-shell32-Add-support-for-setting-getting-PREFERREDDRO.patch create mode 100644 patches/shell32-Context_Menu/0006-shell32-Add-parameter-to-ISFHelper-DeleteItems-to-al.patch create mode 100644 patches/shell32-Context_Menu/0007-shell32-Remove-source-files-when-using-cut-in-the-co.patch create mode 100644 patches/shell32-Context_Menu/0008-shell32-Recognize-cut-copy-paste-string-verbs-in-ite.patch create mode 100644 patches/shell32-Context_Menu/definition diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index f989ac21..af72c444 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -294,6 +294,7 @@ patch_enable_all () enable_setupapi_SetupPromptForDisk="$1" enable_sfc_SfcGetNextProtectedFile="$1" enable_shdocvw_ParseURLFromOutsideSource_Tests="$1" + enable_shell32_Context_Menu="$1" enable_shell32_Default_Path="$1" enable_shell32_File_Property_Dialog="$1" enable_shell32_FolderItems_Stub_Iface="$1" @@ -1059,6 +1060,9 @@ patch_enable () shdocvw-ParseURLFromOutsideSource_Tests) enable_shdocvw_ParseURLFromOutsideSource_Tests="$2" ;; + shell32-Context_Menu) + enable_shell32_Context_Menu="$2" + ;; shell32-Default_Path) enable_shell32_Default_Path="$2" ;; @@ -6181,6 +6185,39 @@ if test "$enable_shdocvw_ParseURLFromOutsideSource_Tests" -eq 1; then ) >> "$patchlist" fi +# Patchset shell32-Context_Menu +# | +# | This patchset fixes the following Wine bugs: +# | * [#34319] Add support for Paste in context menu +# | * [#34322] Fix implementation of Cut file operation +# | * [#34321] Fix Cut/Copy/Paste keyboard shortcuts in Total Commander +# | +# | Modified files: +# | * dlls/shell32/clipboard.c, dlls/shell32/dataobject.c, dlls/shell32/recyclebin.c, dlls/shell32/shell32.rc, +# | dlls/shell32/shell32_main.h, dlls/shell32/shellfolder.h, dlls/shell32/shfldr_fs.c, dlls/shell32/shfldr_unixfs.c, +# | dlls/shell32/shlview.c, dlls/shell32/shlview_cmenu.c +# | +if test "$enable_shell32_Context_Menu" -eq 1; then + patch_apply shell32-Context_Menu/0001-shell32-Fix-copying-of-files-when-using-a-context-me.patch + patch_apply shell32-Context_Menu/0002-shell32-Set-return-value-correctly-in-DoPaste.patch + patch_apply shell32-Context_Menu/0003-shell32-Implement-insert-paste-for-item-context-menu.patch + patch_apply shell32-Context_Menu/0004-shell32-Correctly-interpret-result-of-SHFileOperatio.patch + patch_apply shell32-Context_Menu/0005-shell32-Add-support-for-setting-getting-PREFERREDDRO.patch + patch_apply shell32-Context_Menu/0006-shell32-Add-parameter-to-ISFHelper-DeleteItems-to-al.patch + patch_apply shell32-Context_Menu/0007-shell32-Remove-source-files-when-using-cut-in-the-co.patch + patch_apply shell32-Context_Menu/0008-shell32-Recognize-cut-copy-paste-string-verbs-in-ite.patch + ( + echo '+ { "Michael Müller", "shell32: Fix copying of files when using a context menu.", 1 },'; + echo '+ { "Michael Müller", "shell32: Set return value correctly in DoPaste.", 1 },'; + echo '+ { "Michael Müller", "shell32: Implement insert/paste for item context menus.", 1 },'; + echo '+ { "Michael Müller", "shell32: Correctly interpret result of SHFileOperation in UNIXFS copy and delete.", 1 },'; + echo '+ { "Michael Müller", "shell32: Add support for setting/getting PREFERREDDROPEFFECT in IDataObject.", 1 },'; + echo '+ { "Michael Müller", "shell32: Add parameter to ISFHelper::DeleteItems to allow deleting files without confirmation.", 1 },'; + echo '+ { "Michael Müller", "shell32: Remove source files when using cut in the context menu.", 1 },'; + echo '+ { "Michael Müller", "shell32: Recognize cut/copy/paste string verbs in item menu context menu.", 1 },'; + ) >> "$patchlist" +fi + # Patchset shell32-Default_Path # | # | This patchset fixes the following Wine bugs: diff --git a/patches/shell32-Context_Menu/0001-shell32-Fix-copying-of-files-when-using-a-context-me.patch b/patches/shell32-Context_Menu/0001-shell32-Fix-copying-of-files-when-using-a-context-me.patch new file mode 100644 index 00000000..4878c4df --- /dev/null +++ b/patches/shell32-Context_Menu/0001-shell32-Fix-copying-of-files-when-using-a-context-me.patch @@ -0,0 +1,30 @@ +From 9175a389d86cc231e7e8158360402feb7c5b269e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sat, 2 Apr 2016 00:22:30 +0200 +Subject: shell32: Fix copying of files when using a context menu. + +--- + dlls/shell32/shlview_cmenu.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c +index 099f5bc..552b809 100644 +--- a/dlls/shell32/shlview_cmenu.c ++++ b/dlls/shell32/shlview_cmenu.c +@@ -739,6 +739,13 @@ static BOOL DoPaste(ContextMenu *This) + + apidl = _ILCopyCidaToaPidl(&pidl, lpcida); + ++ /* ++ * In case source is a file we need to remove the last component ++ * to obtain a IShellFolder of the parent. ++ */ ++ if (_ILIsValue(pidl)) ++ ILRemoveLastID(pidl); ++ + /* bind to the source shellfolder */ + SHGetDesktopFolder(&psfDesktop); + if(psfDesktop) +-- +2.7.1 + diff --git a/patches/shell32-Context_Menu/0002-shell32-Set-return-value-correctly-in-DoPaste.patch b/patches/shell32-Context_Menu/0002-shell32-Set-return-value-correctly-in-DoPaste.patch new file mode 100644 index 00000000..318635d5 --- /dev/null +++ b/patches/shell32-Context_Menu/0002-shell32-Set-return-value-correctly-in-DoPaste.patch @@ -0,0 +1,26 @@ +From 7f13fd37d55efe4cc20c4c3eb1c79d3c8ef0040d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sat, 2 Apr 2016 01:21:34 +0200 +Subject: shell32: Set return value correctly in DoPaste. + +--- + dlls/shell32/shlview_cmenu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c +index 552b809..7ce6cd9 100644 +--- a/dlls/shell32/shlview_cmenu.c ++++ b/dlls/shell32/shlview_cmenu.c +@@ -764,7 +764,8 @@ static BOOL DoPaste(ContextMenu *This) + /* do the copy/move */ + if (psfhlpdst && psfhlpsrc) + { +- ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); ++ if (SUCCEEDED(ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl))) ++ bSuccess = TRUE; + /* FIXME handle move + ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl); + */ +-- +2.7.1 + diff --git a/patches/shell32-Context_Menu/0003-shell32-Implement-insert-paste-for-item-context-menu.patch b/patches/shell32-Context_Menu/0003-shell32-Implement-insert-paste-for-item-context-menu.patch new file mode 100644 index 00000000..c6673377 --- /dev/null +++ b/patches/shell32-Context_Menu/0003-shell32-Implement-insert-paste-for-item-context-menu.patch @@ -0,0 +1,165 @@ +From f378913d8cb2e40abb4e24d4bfaf0cbe7ea8134a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sat, 2 Apr 2016 01:39:40 +0200 +Subject: shell32: Implement insert/paste for item context menus. + +--- + dlls/shell32/shell32.rc | 1 + + dlls/shell32/shlview_cmenu.c | 68 +++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 62 insertions(+), 7 deletions(-) + +diff --git a/dlls/shell32/shell32.rc b/dlls/shell32/shell32.rc +index bfba962..4f2015b 100644 +--- a/dlls/shell32/shell32.rc ++++ b/dlls/shell32/shell32.rc +@@ -99,6 +99,7 @@ BEGIN + MENUITEM SEPARATOR + MENUITEM "C&ut", FCIDM_SHVIEW_CUT + MENUITEM "&Copy", FCIDM_SHVIEW_COPY ++ MENUITEM "&Paste", FCIDM_SHVIEW_INSERT + MENUITEM SEPARATOR + MENUITEM "Create &Link", FCIDM_SHVIEW_CREATELINK + MENUITEM "&Delete", FCIDM_SHVIEW_DELETE +diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c +index 7ce6cd9..d972922 100644 +--- a/dlls/shell32/shlview_cmenu.c ++++ b/dlls/shell32/shlview_cmenu.c +@@ -59,6 +59,8 @@ typedef struct + BOOL desktop; + } ContextMenu; + ++static BOOL DoPaste(ContextMenu *This); ++ + static inline ContextMenu *impl_from_IContextMenu3(IContextMenu3 *iface) + { + return CONTAINING_RECORD(iface, ContextMenu, IContextMenu3_iface); +@@ -123,6 +125,30 @@ static ULONG WINAPI ContextMenu_Release(IContextMenu3 *iface) + return ref; + } + ++static BOOL CheckClipboard(void) ++{ ++ IDataObject *pda; ++ BOOL ret = FALSE; ++ ++ if (SUCCEEDED(OleGetClipboard(&pda))) ++ { ++ STGMEDIUM medium; ++ FORMATETC formatetc; ++ ++ /* Set the FORMATETC structure*/ ++ InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW), TYMED_HGLOBAL); ++ ++ /* Get the pidls from IDataObject */ ++ if (SUCCEEDED(IDataObject_GetData(pda, &formatetc, &medium))) ++ { ++ ReleaseStgMedium(&medium); ++ ret = TRUE; ++ } ++ IDataObject_Release(pda); ++ } ++ return ret; ++} ++ + static HRESULT WINAPI ItemMenu_QueryContextMenu( + IContextMenu3 *iface, + HMENU hmenu, +@@ -133,6 +159,7 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu( + { + ContextMenu *This = impl_from_IContextMenu3(iface); + INT uIDMax; ++ DWORD attr = SFGAO_CANRENAME; + + TRACE("(%p)->(%p %d 0x%x 0x%x 0x%x )\n", This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags); + +@@ -169,6 +196,9 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu( + + SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION); + ++ if (This->apidl && This->cidl == 1) ++ IShellFolder_GetAttributesOf(This->parent, 1, (LPCITEMIDLIST*)This->apidl, &attr); ++ + if(uFlags & ~CMF_CANRENAME) + RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME, MF_BYCOMMAND); + else +@@ -179,16 +209,14 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu( + if (!This->apidl || This->cidl > 1) + enable |= MFS_DISABLED; + else +- { +- DWORD attr = SFGAO_CANRENAME; +- +- IShellFolder_GetAttributesOf(This->parent, 1, (LPCITEMIDLIST*)This->apidl, &attr); + enable |= (attr & SFGAO_CANRENAME) ? MFS_ENABLED : MFS_DISABLED; +- } + + EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, enable); + } + ++ if ((attr & (SFGAO_FILESYSTEM|SFGAO_FOLDER)) != (SFGAO_FILESYSTEM|SFGAO_FOLDER) || !CheckClipboard()) ++ RemoveMenu(hmenu, FCIDM_SHVIEW_INSERT + idCmdFirst, MF_BYCOMMAND); ++ + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, uIDMax-idCmdFirst); + } + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); +@@ -447,6 +475,10 @@ static HRESULT WINAPI ItemMenu_InvokeCommand( + TRACE("Verb FCIDM_SHVIEW_CUT\n"); + DoCopyOrCut(This, lpcmi->hwnd, TRUE); + break; ++ case FCIDM_SHVIEW_INSERT: ++ TRACE("Verb FCIDM_SHVIEW_INSERT\n"); ++ DoPaste(This); ++ break; + case FCIDM_SHVIEW_PROPERTIES: + TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n"); + DoOpenProperties(This, lpcmi->hwnd); +@@ -510,6 +542,10 @@ static HRESULT WINAPI ItemMenu_GetCommandString( + strcpy(lpszName, "copy"); + hr = S_OK; + break; ++ case FCIDM_SHVIEW_INSERT: ++ strcpy(lpszName, "paste"); ++ hr = S_OK; ++ break; + case FCIDM_SHVIEW_CREATELINK: + strcpy(lpszName, "link"); + hr = S_OK; +@@ -550,6 +586,10 @@ static HRESULT WINAPI ItemMenu_GetCommandString( + MultiByteToWideChar(CP_ACP, 0, "copy", -1, (LPWSTR)lpszName, uMaxNameLen); + hr = S_OK; + break; ++ case FCIDM_SHVIEW_INSERT: ++ MultiByteToWideChar(CP_ACP, 0, "paste", -1, (LPWSTR)lpszName, uMaxNameLen); ++ hr = S_OK; ++ break; + case FCIDM_SHVIEW_CREATELINK: + MultiByteToWideChar(CP_ACP, 0, "link", -1, (LPWSTR)lpszName, uMaxNameLen); + hr = S_OK; +@@ -757,8 +797,22 @@ static BOOL DoPaste(ContextMenu *This) + if (psfFrom) + { + /* get source and destination shellfolder */ +- ISFHelper *psfhlpdst, *psfhlpsrc; +- IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst); ++ ISFHelper *psfhlpdst = NULL, *psfhlpsrc = NULL; ++ ++ /* when using an item context menu we first need to bind to the selected folder */ ++ if (This->apidl) ++ { ++ IShellFolder *folder; ++ ++ if (SUCCEEDED(IShellFolder_BindToObject(This->parent, This->apidl[0], NULL, &IID_IShellFolder, (LPVOID*)&folder))) ++ { ++ IShellFolder_QueryInterface(folder, &IID_ISFHelper, (void**)&psfhlpdst); ++ IShellFolder_Release(folder); ++ } ++ } ++ else ++ IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst); ++ + IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc); + + /* do the copy/move */ +-- +2.7.1 + diff --git a/patches/shell32-Context_Menu/0004-shell32-Correctly-interpret-result-of-SHFileOperatio.patch b/patches/shell32-Context_Menu/0004-shell32-Correctly-interpret-result-of-SHFileOperatio.patch new file mode 100644 index 00000000..08f9f011 --- /dev/null +++ b/patches/shell32-Context_Menu/0004-shell32-Correctly-interpret-result-of-SHFileOperatio.patch @@ -0,0 +1,35 @@ +From 540ec171b1ad3d84c2087f616151103e4a4593df Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sat, 2 Apr 2016 03:47:48 +0200 +Subject: shell32: Correctly interpret result of SHFileOperation in UNIXFS copy + and delete. + +--- + dlls/shell32/shfldr_unixfs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c +index be1ba81..17998f2 100644 +--- a/dlls/shell32/shfldr_unixfs.c ++++ b/dlls/shell32/shfldr_unixfs.c +@@ -847,7 +847,7 @@ static HRESULT UNIXFS_copy(LPCWSTR pwszDosSrc, LPCWSTR pwszDosDst) + op.pFrom = pwszSrc; + op.pTo = pwszDst; + op.fFlags = FOF_ALLOWUNDO; +- if (!SHFileOperationW(&op)) ++ if (SHFileOperationW(&op)) + { + WARN("SHFileOperationW failed\n"); + res = E_FAIL; +@@ -1981,7 +1981,7 @@ static HRESULT UNIXFS_delete_with_shfileop(UnixFolder *This, UINT cidl, const LP + op.wFunc = FO_DELETE; + op.pFrom = wszPathsList; + op.fFlags = FOF_ALLOWUNDO; +- if (!SHFileOperationW(&op)) ++ if (SHFileOperationW(&op)) + { + WARN("SHFileOperationW failed\n"); + ret = E_FAIL; +-- +2.7.1 + diff --git a/patches/shell32-Context_Menu/0005-shell32-Add-support-for-setting-getting-PREFERREDDRO.patch b/patches/shell32-Context_Menu/0005-shell32-Add-support-for-setting-getting-PREFERREDDRO.patch new file mode 100644 index 00000000..06b61ca8 --- /dev/null +++ b/patches/shell32-Context_Menu/0005-shell32-Add-support-for-setting-getting-PREFERREDDRO.patch @@ -0,0 +1,159 @@ +From 9540fdc5b1668e4b575ce00539454b8ac66457a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sat, 2 Apr 2016 04:15:02 +0200 +Subject: shell32: Add support for setting/getting PREFERREDDROPEFFECT in + IDataObject. + +--- + dlls/shell32/clipboard.c | 40 ++++++++++++++++++++++++++++++++++++++++ + dlls/shell32/dataobject.c | 24 +++++++++++++++++++++--- + dlls/shell32/shell32_main.h | 2 ++ + 3 files changed, 63 insertions(+), 3 deletions(-) + +diff --git a/dlls/shell32/clipboard.c b/dlls/shell32/clipboard.c +index 82df534..9c6f284 100644 +--- a/dlls/shell32/clipboard.c ++++ b/dlls/shell32/clipboard.c +@@ -38,6 +38,8 @@ + #include + #include + ++#define NONAMELESSUNION ++ + #include "windef.h" + #include "winbase.h" + #include "winreg.h" +@@ -214,3 +216,41 @@ HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) + + return hGlobal; + } ++ ++HGLOBAL RenderPREFERREDDROPEFFECT (DWORD value) ++{ ++ DWORD *pEffect; ++ HGLOBAL hGlobal; ++ ++ TRACE("(%d)\n", value); ++ ++ hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD)); ++ if(!hGlobal) return hGlobal; ++ ++ pEffect = GlobalLock(hGlobal); ++ if (pEffect) ++ { ++ *pEffect = value; ++ GlobalUnlock(hGlobal); ++ } ++ ++ return hGlobal; ++} ++ ++HRESULT GetPREFERREDDROPEFFECT (STGMEDIUM *pmedium, DWORD *value) ++{ ++ DWORD *pEffect; ++ BOOL result = E_OUTOFMEMORY; ++ ++ TRACE("(%p, %p)\n", pmedium, value); ++ ++ pEffect = GlobalLock(pmedium->u.hGlobal); ++ if (pEffect) ++ { ++ *value = *pEffect; ++ result = S_OK; ++ GlobalUnlock(pmedium->u.hGlobal); ++ } ++ ++ return result; ++} +diff --git a/dlls/shell32/dataobject.c b/dlls/shell32/dataobject.c +index cc7b63e..5a18a1a 100644 +--- a/dlls/shell32/dataobject.c ++++ b/dlls/shell32/dataobject.c +@@ -197,7 +197,7 @@ LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[]) + */ + + /* number of supported formats */ +-#define MAX_FORMATS 4 ++#define MAX_FORMATS 5 + + typedef struct + { +@@ -209,12 +209,13 @@ typedef struct + LPITEMIDLIST pidl; + LPITEMIDLIST * apidl; + UINT cidl; ++ DWORD dropEffect; + + FORMATETC pFormatEtc[MAX_FORMATS]; + UINT cfShellIDList; + UINT cfFileNameA; + UINT cfFileNameW; +- ++ UINT cfDropEffect; + } IDataObjectImpl; + + static inline IDataObjectImpl *impl_from_IDataObject(IDataObject *iface) +@@ -314,6 +315,10 @@ static HRESULT WINAPI IDataObject_fnGetData(IDataObject *iface, LPFORMATETC pfor + if (This->cidl < 1) return(E_UNEXPECTED); + pmedium->u.hGlobal = RenderFILENAMEW(This->pidl, This->apidl, This->cidl); + } ++ else if (pformatetcIn->cfFormat == This->cfDropEffect) ++ { ++ pmedium->u.hGlobal = RenderPREFERREDDROPEFFECT(This->dropEffect); ++ } + else + { + FIXME("-- expected clipformat not implemented\n"); +@@ -368,7 +373,17 @@ static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(IDataObject *iface, LP + static HRESULT WINAPI IDataObject_fnSetData(IDataObject *iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease) + { + IDataObjectImpl *This = impl_from_IDataObject(iface); +- FIXME("(%p)->()\n", This); ++ ++ FIXME("(%p)->(%p, %p, %u): semi-stub\n", This, pformatetc, pmedium, fRelease); ++ ++ if (pformatetc->cfFormat == This->cfDropEffect) ++ { ++ if (pmedium->tymed == TYMED_HGLOBAL) ++ return GetPREFERREDDROPEFFECT(pmedium, &This->dropEffect); ++ else ++ return DV_E_TYMED; ++ } ++ + return E_NOTIMPL; + } + +@@ -441,14 +456,17 @@ IDataObject* IDataObject_Constructor(HWND hwndOwner, + dto->pidl = ILClone(pMyPidl); + dto->apidl = _ILCopyaPidl(apidl, cidl); + dto->cidl = cidl; ++ dto->dropEffect = 0; + + dto->cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW); + dto->cfFileNameA = RegisterClipboardFormatA(CFSTR_FILENAMEA); + dto->cfFileNameW = RegisterClipboardFormatW(CFSTR_FILENAMEW); ++ dto->cfDropEffect = RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECTW); + InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL); + InitFormatEtc(dto->pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL); + InitFormatEtc(dto->pFormatEtc[2], dto->cfFileNameA, TYMED_HGLOBAL); + InitFormatEtc(dto->pFormatEtc[3], dto->cfFileNameW, TYMED_HGLOBAL); ++ InitFormatEtc(dto->pFormatEtc[4], dto->cfDropEffect, TYMED_HGLOBAL); + } + + TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl); +diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h +index 492f79f..29822b7 100644 +--- a/dlls/shell32/shell32_main.h ++++ b/dlls/shell32/shell32_main.h +@@ -130,6 +130,8 @@ HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) DECL + HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) DECLSPEC_HIDDEN; + HGLOBAL RenderFILENAMEA (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) DECLSPEC_HIDDEN; + HGLOBAL RenderFILENAMEW (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl) DECLSPEC_HIDDEN; ++HGLOBAL RenderPREFERREDDROPEFFECT (DWORD value); ++HRESULT GetPREFERREDDROPEFFECT (STGMEDIUM *pmedium, DWORD *value); + + /* Change Notification */ + void InitChangeNotifications(void) DECLSPEC_HIDDEN; +-- +2.7.1 + diff --git a/patches/shell32-Context_Menu/0006-shell32-Add-parameter-to-ISFHelper-DeleteItems-to-al.patch b/patches/shell32-Context_Menu/0006-shell32-Add-parameter-to-ISFHelper-DeleteItems-to-al.patch new file mode 100644 index 00000000..e565c8f1 --- /dev/null +++ b/patches/shell32-Context_Menu/0006-shell32-Add-parameter-to-ISFHelper-DeleteItems-to-al.patch @@ -0,0 +1,152 @@ +From 60a000e4b5c59b93db1ea24566ad4d7eeea9408b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sat, 2 Apr 2016 04:17:19 +0200 +Subject: shell32: Add parameter to ISFHelper::DeleteItems to allow deleting + files without confirmation. + +--- + dlls/shell32/recyclebin.c | 6 +++--- + dlls/shell32/shellfolder.h | 4 ++-- + dlls/shell32/shfldr_fs.c | 3 ++- + dlls/shell32/shfldr_unixfs.c | 7 ++++--- + dlls/shell32/shlview.c | 2 +- + dlls/shell32/shlview_cmenu.c | 2 +- + 6 files changed, 13 insertions(+), 11 deletions(-) + +diff --git a/dlls/shell32/recyclebin.c b/dlls/shell32/recyclebin.c +index 28098af..f890d97 100644 +--- a/dlls/shell32/recyclebin.c ++++ b/dlls/shell32/recyclebin.c +@@ -182,7 +182,7 @@ static void DoErase(RecycleBinMenu *This) + ISFHelper *helper; + IShellFolder2_QueryInterface(This->folder,&IID_ISFHelper,(void**)&helper); + if(helper) +- ISFHelper_DeleteItems(helper,This->cidl,(LPCITEMIDLIST*)This->apidl); ++ ISFHelper_DeleteItems(helper, This->cidl, (LPCITEMIDLIST *)This->apidl, TRUE); + } + + static void DoRestore(RecycleBinMenu *This) +@@ -824,10 +824,10 @@ static HRESULT erase_items(HWND parent,const LPCITEMIDLIST * apidl, UINT cidl, B + } + + static HRESULT WINAPI RecycleBin_DeleteItems(ISFHelper * iface, UINT cidl, +- LPCITEMIDLIST * apidl) ++ LPCITEMIDLIST * apidl, BOOL confirm) + { + TRACE("(%p,%u,%p)\n",iface,cidl,apidl); +- return erase_items(GetActiveWindow(),apidl,cidl,TRUE); ++ return erase_items(GetActiveWindow(), apidl, cidl, confirm); + } + + static HRESULT WINAPI RecycleBin_CopyItems(ISFHelper * iface, +diff --git a/dlls/shell32/shellfolder.h b/dlls/shell32/shellfolder.h +index 942e0e7..b8083a2 100644 +--- a/dlls/shell32/shellfolder.h ++++ b/dlls/shell32/shellfolder.h +@@ -48,7 +48,7 @@ DECLARE_INTERFACE_(ISFHelper,IUnknown) + /*** ISFHelper methods ***/ + STDMETHOD(GetUniqueName)(THIS_ LPWSTR lpName, UINT uLen) PURE; + STDMETHOD(AddFolder)(THIS_ HWND hwnd, LPCWSTR lpName, LPITEMIDLIST * ppidlOut) PURE; +- STDMETHOD(DeleteItems)(THIS_ UINT cidl, LPCITEMIDLIST * apidl) PURE; ++ STDMETHOD(DeleteItems)(THIS_ UINT cidl, LPCITEMIDLIST *apidl, BOOL confirm) PURE; + STDMETHOD(CopyItems)(THIS_ IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl) PURE; + }; + #undef INTERFACE +@@ -61,7 +61,7 @@ DECLARE_INTERFACE_(ISFHelper,IUnknown) + /*** ISFHelper methods ***/ + #define ISFHelper_GetUniqueName(p,a,b) (p)->lpVtbl->GetUniqueName(p,a,b) + #define ISFHelper_AddFolder(p,a,b,c) (p)->lpVtbl->AddFolder(p,a,b,c) +-#define ISFHelper_DeleteItems(p,a,b) (p)->lpVtbl->DeleteItems(p,a,b) ++#define ISFHelper_DeleteItems(p,a,b,c) (p)->lpVtbl->DeleteItems(p,a,b,c) + #define ISFHelper_CopyItems(p,a,b,c) (p)->lpVtbl->CopyItems(p,a,b,c) + #endif + +diff --git a/dlls/shell32/shfldr_fs.c b/dlls/shell32/shfldr_fs.c +index d8bcb4c..3d88fbd 100644 +--- a/dlls/shell32/shfldr_fs.c ++++ b/dlls/shell32/shfldr_fs.c +@@ -1230,7 +1230,7 @@ static WCHAR *build_paths_list(LPCWSTR wszBasePath, int cidl, const LPCITEMIDLIS + * deletes items in folder + */ + static HRESULT WINAPI +-ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl) ++ISFHelper_fnDeleteItems (ISFHelper *iface, UINT cidl, LPCITEMIDLIST *apidl, BOOL confirm) + { + IGenericSFImpl *This = impl_from_ISFHelper(iface); + UINT i; +@@ -1255,6 +1255,7 @@ ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl) + op.wFunc = FO_DELETE; + op.pFrom = wszPathsList; + op.fFlags = FOF_ALLOWUNDO; ++ if (!confirm) op.fFlags |= FOF_NOCONFIRMATION; + if (SHFileOperationW(&op)) + { + WARN("SHFileOperation failed\n"); +diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c +index 17998f2..d558efb 100644 +--- a/dlls/shell32/shfldr_unixfs.c ++++ b/dlls/shell32/shfldr_unixfs.c +@@ -1939,7 +1939,7 @@ static HRESULT WINAPI SFHelper_AddFolder(ISFHelper* iface, HWND hwnd, LPCWSTR pw + * be converted, S_FALSE is returned. In such situation DeleteItems will try to delete + * the files using syscalls + */ +-static HRESULT UNIXFS_delete_with_shfileop(UnixFolder *This, UINT cidl, const LPCITEMIDLIST *apidl) ++static HRESULT UNIXFS_delete_with_shfileop(UnixFolder *This, UINT cidl, const LPCITEMIDLIST *apidl, BOOL confirm) + { + char szAbsolute[FILENAME_MAX], *pszRelative; + LPWSTR wszPathsList, wszListPos; +@@ -1981,6 +1981,7 @@ static HRESULT UNIXFS_delete_with_shfileop(UnixFolder *This, UINT cidl, const LP + op.wFunc = FO_DELETE; + op.pFrom = wszPathsList; + op.fFlags = FOF_ALLOWUNDO; ++ if (!confirm) op.fFlags |= FOF_NOCONFIRMATION; + if (SHFileOperationW(&op)) + { + WARN("SHFileOperationW failed\n"); +@@ -2019,7 +2020,7 @@ static HRESULT UNIXFS_delete_with_syscalls(UnixFolder *This, UINT cidl, const LP + return S_OK; + } + +-static HRESULT WINAPI SFHelper_DeleteItems(ISFHelper* iface, UINT cidl, LPCITEMIDLIST* apidl) ++static HRESULT WINAPI SFHelper_DeleteItems(ISFHelper *iface, UINT cidl, LPCITEMIDLIST *apidl, BOOL confirm) + { + UnixFolder *This = impl_from_ISFHelper(iface); + char szAbsolute[FILENAME_MAX], *pszRelative; +@@ -2030,7 +2031,7 @@ static HRESULT WINAPI SFHelper_DeleteItems(ISFHelper* iface, UINT cidl, LPCITEMI + + TRACE("(%p)->(%d %p)\n", This, cidl, apidl); + +- hr = UNIXFS_delete_with_shfileop(This, cidl, apidl); ++ hr = UNIXFS_delete_with_shfileop(This, cidl, apidl, confirm); + if (hr == S_FALSE) + hr = UNIXFS_delete_with_syscalls(This, cidl, apidl); + +diff --git a/dlls/shell32/shlview.c b/dlls/shell32/shlview.c +index b763468..1770e6f 100644 +--- a/dlls/shell32/shlview.c ++++ b/dlls/shell32/shlview.c +@@ -1579,7 +1579,7 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn + } + + /* perform the item deletion */ +- ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems); ++ ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST *)pItems, TRUE); + ISFHelper_Release(psfhlp); + + /* free pidl array memory */ +diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c +index d972922..494d95b 100644 +--- a/dlls/shell32/shlview_cmenu.c ++++ b/dlls/shell32/shlview_cmenu.c +@@ -275,7 +275,7 @@ static void DoDelete(ContextMenu *This) + IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&helper); + if (helper) + { +- ISFHelper_DeleteItems(helper, This->cidl, (LPCITEMIDLIST*)This->apidl); ++ ISFHelper_DeleteItems(helper, This->cidl, (LPCITEMIDLIST *)This->apidl, TRUE); + ISFHelper_Release(helper); + } + } +-- +2.7.1 + diff --git a/patches/shell32-Context_Menu/0007-shell32-Remove-source-files-when-using-cut-in-the-co.patch b/patches/shell32-Context_Menu/0007-shell32-Remove-source-files-when-using-cut-in-the-co.patch new file mode 100644 index 00000000..0118e01e --- /dev/null +++ b/patches/shell32-Context_Menu/0007-shell32-Remove-source-files-when-using-cut-in-the-co.patch @@ -0,0 +1,113 @@ +From c6df9e2fd8f92597a728935e67a6ac6c3bc1223c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sat, 2 Apr 2016 04:22:07 +0200 +Subject: shell32: Remove source files when using cut in the context menu. + +--- + dlls/shell32/shlview_cmenu.c | 75 +++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 71 insertions(+), 4 deletions(-) + +diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c +index 494d95b..c32a4e8 100644 +--- a/dlls/shell32/shlview_cmenu.c ++++ b/dlls/shell32/shlview_cmenu.c +@@ -281,6 +281,64 @@ static void DoDelete(ContextMenu *This) + } + + /************************************************************************** ++ * SetDropEffect ++ * ++ * Set the drop effect in a IDataObject object ++ */ ++static void SetDropEffect(IDataObject *dataobject, DWORD value) ++{ ++ FORMATETC formatetc; ++ STGMEDIUM medium; ++ DWORD *effect; ++ ++ InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECTW), TYMED_HGLOBAL); ++ ++ medium.tymed = TYMED_HGLOBAL; ++ medium.pUnkForRelease = NULL; ++ medium.u.hGlobal = GlobalAlloc(GHND|GMEM_SHARE, sizeof(DWORD)); ++ if (!medium.u.hGlobal) return; ++ ++ effect = GlobalLock(medium.u.hGlobal); ++ if (!effect) ++ { ++ ReleaseStgMedium(&medium); ++ return; ++ } ++ *effect = value; ++ GlobalUnlock(effect); ++ ++ IDataObject_SetData(dataobject, &formatetc, &medium, FALSE); ++ ReleaseStgMedium(&medium); ++} ++ ++/************************************************************************** ++ * GetDropEffect ++ * ++ * Get the drop effect from a IDataObject object ++ */ ++static void GetDropEffect(IDataObject *dataobject, DWORD *value) ++{ ++ FORMATETC formatetc; ++ STGMEDIUM medium; ++ DWORD *effect; ++ ++ *value = DROPEFFECT_NONE; ++ ++ InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECTW), TYMED_HGLOBAL); ++ ++ if (SUCCEEDED(IDataObject_GetData(dataobject, &formatetc, &medium))) ++ { ++ effect = GlobalLock(medium.u.hGlobal); ++ if (effect) ++ { ++ *value = *effect; ++ GlobalUnlock(effect); ++ } ++ ReleaseStgMedium(&medium); ++ } ++} ++ ++/************************************************************************** + * DoCopyOrCut + * + * copies the currently selected items into the clipboard +@@ -293,6 +351,7 @@ static void DoCopyOrCut(ContextMenu *This, HWND hwnd, BOOL cut) + + if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->parent, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject, 0, (void**)&dataobject))) + { ++ SetDropEffect(dataobject, cut ? DROPEFFECT_MOVE : DROPEFFECT_COPY); + OleSetClipboard(dataobject); + IDataObject_Release(dataobject); + } +@@ -818,11 +877,19 @@ static BOOL DoPaste(ContextMenu *This) + /* do the copy/move */ + if (psfhlpdst && psfhlpsrc) + { ++ DWORD dropEffect; ++ GetDropEffect(pda, &dropEffect); ++ + if (SUCCEEDED(ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl))) +- bSuccess = TRUE; +- /* FIXME handle move +- ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl); +- */ ++ { ++ if (dropEffect == DROPEFFECT_MOVE) ++ { ++ if (SUCCEEDED(ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, (LPCITEMIDLIST*)apidl, FALSE))) ++ bSuccess = TRUE; ++ } ++ else ++ bSuccess = TRUE; ++ } + } + if(psfhlpdst) ISFHelper_Release(psfhlpdst); + if(psfhlpsrc) ISFHelper_Release(psfhlpsrc); +-- +2.7.1 + diff --git a/patches/shell32-Context_Menu/0008-shell32-Recognize-cut-copy-paste-string-verbs-in-ite.patch b/patches/shell32-Context_Menu/0008-shell32-Recognize-cut-copy-paste-string-verbs-in-ite.patch new file mode 100644 index 00000000..d07f3591 --- /dev/null +++ b/patches/shell32-Context_Menu/0008-shell32-Recognize-cut-copy-paste-string-verbs-in-ite.patch @@ -0,0 +1,30 @@ +From 47c24300c6530de5dfe32f352ef839e62ebbd520 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sat, 2 Apr 2016 04:41:56 +0200 +Subject: shell32: Recognize cut/copy/paste string verbs in item menu context + menu. + +--- + dlls/shell32/shlview_cmenu.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c +index c32a4e8..cfe88d5 100644 +--- a/dlls/shell32/shlview_cmenu.c ++++ b/dlls/shell32/shlview_cmenu.c +@@ -554,6 +554,12 @@ static HRESULT WINAPI ItemMenu_InvokeCommand( + DoDelete(This); + else if (strcmp(lpcmi->lpVerb,"properties")==0) + DoOpenProperties(This, lpcmi->hwnd); ++ else if (strcmp(lpcmi->lpVerb,"cut")==0) ++ DoCopyOrCut(This, lpcmi->hwnd, TRUE); ++ else if (strcmp(lpcmi->lpVerb,"copy")==0) ++ DoCopyOrCut(This, lpcmi->hwnd, FALSE); ++ else if (strcmp(lpcmi->lpVerb,"paste")==0) ++ DoPaste(This); + else { + FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi->lpVerb)); + return E_FAIL; +-- +2.7.1 + diff --git a/patches/shell32-Context_Menu/definition b/patches/shell32-Context_Menu/definition new file mode 100644 index 00000000..d177a78e --- /dev/null +++ b/patches/shell32-Context_Menu/definition @@ -0,0 +1,3 @@ +Fixes: [34319] Add support for Paste in context menu +Fixes: [34322] Fix implementation of Cut file operation +Fixes: [34321] Fix Cut/Copy/Paste keyboard shortcuts in Total Commander