[SHELL32] Rewrite CCopyAsPathMenu on top of IContextMenu

Also use the same registry key as Windows 10.
This commit is contained in:
Thamatip Chitpong 2024-04-09 10:50:48 +07:00
parent a706f6ba78
commit 7586fe5c1d
3 changed files with 89 additions and 31 deletions

View file

@ -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 <whindsaks@proton.me>
* Copyright 2024 Thamatip Chitpong <thamatip.chitpong@reactos.org>
*/
#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;
}

View file

@ -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 <whindsaks@proton.me>
* Copyright 2024 Thamatip Chitpong <thamatip.chitpong@reactos.org>
*/
#pragma once
@ -10,32 +11,33 @@
class CCopyAsPathMenu :
public CComCoClass<CCopyAsPathMenu, &CLSID_CopyAsPathMenu>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IDropTarget
public IContextMenu,
public IShellExtInit
{
private:
CComPtr<IDataObject> 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);
};

View file

@ -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}'
}
}
}