From 7586fe5c1d25a5524ec7ddc46ab6e2547f2c01ed Mon Sep 17 00:00:00 2001 From: Thamatip Chitpong Date: Tue, 9 Apr 2024 10:50:48 +0700 Subject: [PATCH] [SHELL32] Rewrite CCopyAsPathMenu on top of IContextMenu Also use the same registry key as Windows 10. --- dll/win32/shell32/CCopyAsPathMenu.cpp | 71 ++++++++++++++++++-- dll/win32/shell32/CCopyAsPathMenu.h | 40 +++++------ dll/win32/shell32/res/rgs/copyaspathmenu.rgs | 9 +-- 3 files changed, 89 insertions(+), 31 deletions(-) diff --git a/dll/win32/shell32/CCopyAsPathMenu.cpp b/dll/win32/shell32/CCopyAsPathMenu.cpp index 55bac2f4909..1c78776a8c8 100644 --- a/dll/win32/shell32/CCopyAsPathMenu.cpp +++ b/dll/win32/shell32/CCopyAsPathMenu.cpp @@ -3,12 +3,23 @@ * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Copy as Path Menu implementation * COPYRIGHT: Copyright 2024 Whindmar Saksit + * Copyright 2024 Thamatip Chitpong */ #include "precomp.h" WINE_DEFAULT_DEBUG_CHANNEL(shell); +#define IDC_COPYASPATH 0 + +CCopyAsPathMenu::CCopyAsPathMenu() +{ +} + +CCopyAsPathMenu::~CCopyAsPathMenu() +{ +} + static DWORD SetClipboard(UINT cf, const void* data, SIZE_T size) { @@ -59,8 +70,8 @@ AppendToPathList(CStringW &paths, LPCWSTR path, DWORD index) paths += L'\"'; } -STDMETHODIMP -CCopyAsPathMenu::Drop(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect) +HRESULT +CCopyAsPathMenu::DoCopyAsPath(IDataObject *pdto) { CStringW paths; DWORD i, count; @@ -144,9 +155,57 @@ CCopyAsPathMenu::Drop(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *p hr = HRESULT_FROM_WIN32(err); } - if (SUCCEEDED(hr)) - *pdwEffect &= DROPEFFECT_COPY; - else - *pdwEffect &= DROPEFFECT_NONE; return hr; } + +STDMETHODIMP +CCopyAsPathMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) +{ + MENUITEMINFOW mii; + + TRACE("CCopyAsPathMenu::QueryContextMenu(%p %p %u %u %u %u)\n", this, + hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); + + if ((uFlags & CMF_NOVERBS) || !(uFlags & CMF_EXTENDEDVERBS)) + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst); + + // Insert "Copy as path" + CStringW strText(MAKEINTRESOURCEW(IDS_COPYASPATHMENU)); + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.wID = idCmdFirst + IDC_COPYASPATH; + mii.dwTypeData = strText.GetBuffer(); + if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii)) + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, mii.wID - idCmdFirst + 1); + + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst); +} + +STDMETHODIMP +CCopyAsPathMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) +{ + TRACE("CCopyAsPathMenu::InvokeCommand(%p %p)\n", this, lpcmi); + + if (IS_INTRESOURCE(lpcmi->lpVerb) && LOWORD(lpcmi->lpVerb) == IDC_COPYASPATH) + return DoCopyAsPath(m_pDataObject); + + return E_FAIL; +} + +STDMETHODIMP +CCopyAsPathMenu::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen) +{ + FIXME("CCopyAsPathMenu::GetCommandString(%p %lu %u %p %p %u)\n", this, + idCommand, uFlags, lpReserved, lpszName, uMaxNameLen); + + return E_NOTIMPL; +} + +STDMETHODIMP +CCopyAsPathMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID) +{ + m_pDataObject = pdtobj; + return S_OK; +} diff --git a/dll/win32/shell32/CCopyAsPathMenu.h b/dll/win32/shell32/CCopyAsPathMenu.h index f11efd20a90..a72af085f19 100644 --- a/dll/win32/shell32/CCopyAsPathMenu.h +++ b/dll/win32/shell32/CCopyAsPathMenu.h @@ -3,6 +3,7 @@ * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Copy as Path Menu implementation * COPYRIGHT: Copyright 2024 Whindmar Saksit + * Copyright 2024 Thamatip Chitpong */ #pragma once @@ -10,32 +11,33 @@ class CCopyAsPathMenu : public CComCoClass, public CComObjectRootEx, - public IDropTarget + public IContextMenu, + public IShellExtInit { +private: + CComPtr m_pDataObject; + + HRESULT DoCopyAsPath(IDataObject *pdto); + public: + CCopyAsPathMenu(); + ~CCopyAsPathMenu(); + + // IContextMenu + STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) override; + STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) override; + STDMETHODIMP GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen) override; + + // IShellExtInit + STDMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID) override; + DECLARE_REGISTRY_RESOURCEID(IDR_COPYASPATHMENU) DECLARE_NOT_AGGREGATABLE(CCopyAsPathMenu) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CCopyAsPathMenu) - COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) + COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) END_COM_MAP() - - // IDropTarget - STDMETHODIMP DragEnter(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect) - { - *pdwEffect &= DROPEFFECT_COPY; - return S_OK; - } - STDMETHODIMP DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect) - { - *pdwEffect &= DROPEFFECT_COPY; - return S_OK; - } - STDMETHODIMP DragLeave() - { - return S_OK; - } - STDMETHODIMP Drop(IDataObject *pdto, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect); }; diff --git a/dll/win32/shell32/res/rgs/copyaspathmenu.rgs b/dll/win32/shell32/res/rgs/copyaspathmenu.rgs index a1961e240c1..0aff18720ce 100644 --- a/dll/win32/shell32/res/rgs/copyaspathmenu.rgs +++ b/dll/win32/shell32/res/rgs/copyaspathmenu.rgs @@ -12,15 +12,12 @@ HKCR } NoRemove AllFilesystemObjects { - NoRemove shell + NoRemove shellex { - ForceRemove copyaspath + NoRemove ContextMenuHandlers { - val MUIVerb = s '@%MODULE%,-30328' - val Extended = s '' - DropTarget + ForceRemove CopyAsPathMenu = s '{F3D06E7C-1E45-4A26-847E-F9FCDEE59BE0}' { - val CLSID = s '{F3D06E7C-1E45-4A26-847E-F9FCDEE59BE0}' } } }