From a938d19714f9ab659c8d9c2250f2cafc5db8f637 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Sat, 4 Nov 2023 21:56:15 +0900 Subject: [PATCH] [SHELL32] Commonize CCopyToMenu and CMoveToMenu (#5873) Reduce code. And correctly do the filename check. CORE-18909 --- .../{CMoveToMenu.cpp => CCopyMoveToMenu.cpp} | 189 +++++---- dll/win32/shell32/CCopyMoveToMenu.h | 111 +++++ dll/win32/shell32/CCopyToMenu.cpp | 381 ------------------ dll/win32/shell32/CCopyToMoveToMenu.h | 112 ----- dll/win32/shell32/CMakeLists.txt | 3 +- dll/win32/shell32/precomp.h | 2 +- 6 files changed, 234 insertions(+), 564 deletions(-) rename dll/win32/shell32/{CMoveToMenu.cpp => CCopyMoveToMenu.cpp} (66%) create mode 100644 dll/win32/shell32/CCopyMoveToMenu.h delete mode 100644 dll/win32/shell32/CCopyToMenu.cpp delete mode 100644 dll/win32/shell32/CCopyToMoveToMenu.h diff --git a/dll/win32/shell32/CMoveToMenu.cpp b/dll/win32/shell32/CCopyMoveToMenu.cpp similarity index 66% rename from dll/win32/shell32/CMoveToMenu.cpp rename to dll/win32/shell32/CCopyMoveToMenu.cpp index a2d35f1ade1..859b05eb5b7 100644 --- a/dll/win32/shell32/CMoveToMenu.cpp +++ b/dll/win32/shell32/CCopyMoveToMenu.cpp @@ -1,33 +1,29 @@ /* - * PROJECT: shell32 + * PROJECT: ReactOS shell32 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) - * PURPOSE: MoveTo implementation - * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + * PURPOSE: CopyTo and MoveTo implementation + * COPYRIGHT: Copyright 2020-2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) */ #include "precomp.h" WINE_DEFAULT_DEBUG_CHANNEL(shell); -CMoveToMenu::CMoveToMenu() : +CCopyMoveToMenu::CCopyMoveToMenu() : m_idCmdFirst(0), m_idCmdLast(0), - m_idCmdMoveTo(-1), + m_idCmdAction(-1), m_fnOldWndProc(NULL), m_bIgnoreTextBoxChange(FALSE) { } -CMoveToMenu::~CMoveToMenu() -{ -} - static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { WCHAR szPath[MAX_PATH]; - CMoveToMenu *this_ = - reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + CCopyMoveToMenu *this_ = + reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); switch (uMsg) { @@ -64,30 +60,30 @@ WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return CallWindowProcW(this_->m_fnOldWndProc, hwnd, uMsg, wParam, lParam); } -static int CALLBACK +static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) { - CMoveToMenu *this_ = - reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + CCopyMoveToMenu *this_ = + reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); switch (uMsg) { case BFFM_INITIALIZED: { SetWindowLongPtr(hwnd, GWLP_USERDATA, lpData); - this_ = reinterpret_cast(lpData); + this_ = reinterpret_cast(lpData); // Select initial directory SendMessageW(hwnd, BFFM_SETSELECTION, FALSE, reinterpret_cast(static_cast(this_->m_pidlFolder))); // Set caption - CString strCaption(MAKEINTRESOURCEW(IDS_MOVEITEMS)); + CString strCaption(MAKEINTRESOURCEW(this_->GetCaptionStringID())); SetWindowTextW(hwnd, strCaption); // Set OK button text - CString strMove(MAKEINTRESOURCEW(IDS_MOVEBUTTON)); - SetDlgItemText(hwnd, IDOK, strMove); + CString strCopyOrMove(MAKEINTRESOURCEW(this_->GetButtonStringID())); + SetDlgItemText(hwnd, IDOK, strCopyOrMove); // Subclassing this_->m_fnOldWndProc = @@ -125,7 +121,8 @@ BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) return FALSE; } -HRESULT CMoveToMenu::DoRealMove(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl) +HRESULT +CCopyMoveToMenu::DoRealFileOp(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl) { CDataObjectHIDA pCIDA(m_pDataObject); if (FAILED_UNEXPECTEDLY(pCIDA.hr())) @@ -175,10 +172,7 @@ HRESULT CMoveToMenu::DoRealMove(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl) return E_FAIL; } - SHFILEOPSTRUCTW op = { lpici->hwnd }; - op.wFunc = FO_MOVE; - op.pFrom = strFiles; - op.pTo = szPath; + SHFILEOPSTRUCTW op = { lpici->hwnd, GetFileOp(), strFiles, szPath }; op.fFlags = FOF_ALLOWUNDO; int res = SHFileOperationW(&op); if (res) @@ -189,19 +183,18 @@ HRESULT CMoveToMenu::DoRealMove(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl) return S_OK; } -CStringW CMoveToMenu::DoGetFileTitle() +static HRESULT +DoGetFileTitle(CStringW& strTitle, IDataObject *pDataObject) { - CStringW ret = L"(file)"; - - CDataObjectHIDA pCIDA(m_pDataObject); + CDataObjectHIDA pCIDA(pDataObject); if (FAILED_UNEXPECTEDLY(pCIDA.hr())) - return ret; + return E_FAIL; PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA); if (!pidlParent) { ERR("HIDA_GetPIDLFolder failed\n"); - return ret; + return E_FAIL; } WCHAR szPath[MAX_PATH]; @@ -209,28 +202,33 @@ CStringW CMoveToMenu::DoGetFileTitle() if (!pidlRelative) { ERR("HIDA_GetPIDLItem failed\n"); - return ret; + return E_FAIL; } CComHeapPtr pidlCombine(ILCombine(pidlParent, pidlRelative)); - if (SHGetPathFromIDListW(pidlCombine, szPath)) - ret = PathFindFileNameW(szPath); - else + if (!SHGetPathFromIDListW(pidlCombine, szPath)) + { ERR("Cannot get path\n"); + return E_FAIL; + } + + strTitle = PathFindFileNameW(szPath); + if (strTitle.IsEmpty()) + return E_FAIL; if (pCIDA->cidl > 1) - ret += L" ..."; + strTitle += L" ..."; - return ret; + return S_OK; } -HRESULT CMoveToMenu::DoMoveToFolder(LPCMINVOKECOMMANDINFO lpici) +HRESULT CCopyMoveToMenu::DoAction(LPCMINVOKECOMMANDINFO lpici) { WCHAR wszPath[MAX_PATH]; HRESULT hr = E_FAIL; - TRACE("DoMoveToFolder(%p)\n", lpici); + TRACE("(%p)\n", lpici); if (!SHGetPathFromIDListW(m_pidlFolder, wszPath)) { @@ -238,9 +236,13 @@ HRESULT CMoveToMenu::DoMoveToFolder(LPCMINVOKECOMMANDINFO lpici) return hr; } - CStringW strFileTitle = DoGetFileTitle(); + CStringW strFileTitle; + hr = DoGetFileTitle(strFileTitle, m_pDataObject); + if (FAILED(hr)) + return hr; + CStringW strTitle; - strTitle.Format(IDS_MOVETOTITLE, static_cast(strFileTitle)); + strTitle.Format(GetActionTitleStringID(), static_cast(strFileTitle)); BROWSEINFOW info = { lpici->hwnd }; info.pidlRoot = NULL; @@ -250,14 +252,67 @@ HRESULT CMoveToMenu::DoMoveToFolder(LPCMINVOKECOMMANDINFO lpici) info.lParam = reinterpret_cast(this); CComHeapPtr pidl(SHBrowseForFolder(&info)); if (pidl) - { - hr = DoRealMove(lpici, pidl); - } + hr = DoRealFileOp(lpici, pidl); return hr; } -HRESULT WINAPI +STDMETHODIMP +CCopyToMenu::QueryContextMenu(HMENU hMenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags) +{ + MENUITEMINFOW mii; + UINT Count = 0; + + TRACE("CCopyToMenu::QueryContextMenu(%p, %u, %u, %u, %u)\n", + hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); + + if (uFlags & (CMF_NOVERBS | CMF_VERBSONLY)) + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst); + + m_idCmdFirst = m_idCmdLast = idCmdFirst; + + // insert separator if necessary + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_TYPE; + if (GetMenuItemInfoW(hMenu, indexMenu - 1, TRUE, &mii) && + mii.fType != MFT_SEPARATOR) + { + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_TYPE; + mii.fType = MFT_SEPARATOR; + if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii)) + { + ++indexMenu; + ++Count; + } + } + + // insert "Copy to folder..." + CStringW strText(MAKEINTRESOURCEW(IDS_COPYTOMENU)); + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = strText.GetBuffer(); + mii.cch = wcslen(mii.dwTypeData); + mii.wID = m_idCmdLast; + if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii)) + { + m_idCmdAction = m_idCmdLast++; + ++indexMenu; + ++Count; + } + + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst + Count); +} + +STDMETHODIMP CMoveToMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, @@ -309,7 +364,7 @@ CMoveToMenu::QueryContextMenu(HMENU hMenu, mii.wID = m_idCmdLast; if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii)) { - m_idCmdMoveTo = m_idCmdLast++; + m_idCmdAction = m_idCmdLast++; ++indexMenu; ++Count; } @@ -317,36 +372,33 @@ CMoveToMenu::QueryContextMenu(HMENU hMenu, return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst + Count); } -HRESULT WINAPI -CMoveToMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) +STDMETHODIMP +CCopyMoveToMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) { HRESULT hr = E_FAIL; - TRACE("CMoveToMenu::InvokeCommand(%p)\n", lpici); + TRACE("CCopyMoveToMenu::InvokeCommand(%p)\n", lpici); if (IS_INTRESOURCE(lpici->lpVerb)) { - if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdMoveTo) - { - hr = DoMoveToFolder(lpici); - } + if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdAction) + hr = DoAction(lpici); } else { - if (::lstrcmpiA(lpici->lpVerb, "moveto") == 0) - { - hr = DoMoveToFolder(lpici); - } + if (::lstrcmpiA(lpici->lpVerb, GetVerb()) == 0) + hr = DoAction(lpici); } return hr; } -HRESULT WINAPI -CMoveToMenu::GetCommandString(UINT_PTR idCmd, - UINT uType, - UINT *pwReserved, - LPSTR pszName, - UINT cchMax) +STDMETHODIMP +CCopyMoveToMenu::GetCommandString( + UINT_PTR idCmd, + UINT uType, + UINT *pwReserved, + LPSTR pszName, + UINT cchMax) { FIXME("%p %lu %u %p %p %u\n", this, idCmd, uType, pwReserved, pszName, cchMax); @@ -354,29 +406,30 @@ CMoveToMenu::GetCommandString(UINT_PTR idCmd, return E_NOTIMPL; } -HRESULT WINAPI -CMoveToMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) +STDMETHODIMP +CCopyMoveToMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) { TRACE("This %p uMsg %x\n", this, uMsg); return E_NOTIMPL; } -HRESULT WINAPI -CMoveToMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, - IDataObject *pdtobj, HKEY hkeyProgID) +STDMETHODIMP +CCopyMoveToMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID) { m_pidlFolder.Attach(ILClone(pidlFolder)); m_pDataObject = pdtobj; return S_OK; } -HRESULT WINAPI CMoveToMenu::SetSite(IUnknown *pUnkSite) +STDMETHODIMP +CCopyMoveToMenu::SetSite(IUnknown *pUnkSite) { m_pSite = pUnkSite; return S_OK; } -HRESULT WINAPI CMoveToMenu::GetSite(REFIID riid, void **ppvSite) +STDMETHODIMP +CCopyMoveToMenu::GetSite(REFIID riid, void **ppvSite) { if (!m_pSite) return E_FAIL; diff --git a/dll/win32/shell32/CCopyMoveToMenu.h b/dll/win32/shell32/CCopyMoveToMenu.h new file mode 100644 index 00000000000..3b9de7ad91a --- /dev/null +++ b/dll/win32/shell32/CCopyMoveToMenu.h @@ -0,0 +1,111 @@ +/* + * PROJECT: ReactOS shell32 + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: CopyTo and MoveTo implementation + * COPYRIGHT: Copyright 2020-2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + */ +#pragma once + +class CCopyMoveToMenu : + public CComObjectRootEx, + public IContextMenu2, + public IObjectWithSite, + public IShellExtInit +{ +protected: + UINT m_idCmdFirst, m_idCmdLast, m_idCmdAction; + CComPtr m_pDataObject; + CComPtr m_pSite; + + HRESULT DoRealFileOp(LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidl); + HRESULT DoAction(LPCMINVOKECOMMANDINFO lpici); + +public: + CComHeapPtr m_pidlFolder; + WNDPROC m_fnOldWndProc; + BOOL m_bIgnoreTextBoxChange; + + CCopyMoveToMenu(); + + virtual UINT GetCaptionStringID() const = 0; + virtual UINT GetButtonStringID() const = 0; + virtual UINT GetActionTitleStringID() const = 0; + virtual UINT GetFileOp() const = 0; + virtual LPCSTR GetVerb() const = 0; + + // IContextMenu + STDMETHODIMP GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen) override; + STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) override; + + // IContextMenu2 + STDMETHODIMP HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) override; + + // IShellExtInit + STDMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID) override; + + // IObjectWithSite + STDMETHODIMP SetSite(IUnknown *pUnkSite) override; + STDMETHODIMP GetSite(REFIID riid, void **ppvSite) override; +}; + +class CCopyToMenu + : public CComCoClass + , public CCopyMoveToMenu +{ +public: + CComHeapPtr m_pidlFolder; + WNDPROC m_fnOldWndProc; + BOOL m_bIgnoreTextBoxChange; + + CCopyToMenu() { } + + // IContextMenu + STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) override; + + DECLARE_REGISTRY_RESOURCEID(IDR_COPYTOMENU) + DECLARE_NOT_AGGREGATABLE(CCopyToMenu) + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CCopyToMenu) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) + COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) + COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) + END_COM_MAP() + + UINT GetCaptionStringID() const override { return IDS_COPYITEMS; } + UINT GetButtonStringID() const override { return IDS_COPYBUTTON; } + UINT GetActionTitleStringID() const override { return IDS_COPYTOTITLE; } + UINT GetFileOp() const override { return FO_COPY; } + LPCSTR GetVerb() const override { return "copyto"; } +}; + +class CMoveToMenu + : public CComCoClass + , public CCopyMoveToMenu +{ +public: + CMoveToMenu() { } + + // IContextMenu + STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) override; + + DECLARE_REGISTRY_RESOURCEID(IDR_MOVETOMENU) + DECLARE_NOT_AGGREGATABLE(CMoveToMenu) + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CMoveToMenu) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) + COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) + COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) + END_COM_MAP() + + UINT GetCaptionStringID() const override { return IDS_MOVEITEMS; } + UINT GetButtonStringID() const override { return IDS_MOVEBUTTON; } + UINT GetActionTitleStringID() const override { return IDS_MOVETOTITLE; } + UINT GetFileOp() const override { return FO_MOVE; } + LPCSTR GetVerb() const override { return "moveto"; } +}; diff --git a/dll/win32/shell32/CCopyToMenu.cpp b/dll/win32/shell32/CCopyToMenu.cpp deleted file mode 100644 index d3da9d1f5a8..00000000000 --- a/dll/win32/shell32/CCopyToMenu.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - * PROJECT: shell32 - * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) - * PURPOSE: CopyTo implementation - * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) - */ - -#include "precomp.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - - -CCopyToMenu::CCopyToMenu() : - m_idCmdFirst(0), - m_idCmdLast(0), - m_idCmdCopyTo(-1), - m_fnOldWndProc(NULL), - m_bIgnoreTextBoxChange(FALSE) -{ -} - -CCopyToMenu::~CCopyToMenu() -{ -} - -static LRESULT CALLBACK -WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - WCHAR szPath[MAX_PATH]; - CCopyToMenu *this_ = - reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); - - switch (uMsg) - { - case WM_COMMAND: - { - switch (LOWORD(wParam)) - { - case IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT: - { - if (HIWORD(wParam) == EN_CHANGE) - { - if (!this_->m_bIgnoreTextBoxChange) - { - // get the text - GetDlgItemTextW(hwnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT, szPath, _countof(szPath)); - StrTrimW(szPath, L" \t"); - - // update OK button - BOOL bValid = !PathIsRelative(szPath) && PathIsDirectoryW(szPath); - SendMessageW(hwnd, BFFM_ENABLEOK, 0, bValid); - - return 0; - } - - // reset flag - this_->m_bIgnoreTextBoxChange = FALSE; - } - break; - } - } - break; - } - } - return CallWindowProcW(this_->m_fnOldWndProc, hwnd, uMsg, wParam, lParam); -} - -static int CALLBACK -BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) -{ - CCopyToMenu *this_ = - reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); - - switch (uMsg) - { - case BFFM_INITIALIZED: - { - SetWindowLongPtr(hwnd, GWLP_USERDATA, lpData); - this_ = reinterpret_cast(lpData); - - // Select initial directory - SendMessageW(hwnd, BFFM_SETSELECTION, FALSE, - reinterpret_cast(static_cast(this_->m_pidlFolder))); - - // Set caption - CString strCaption(MAKEINTRESOURCEW(IDS_COPYITEMS)); - SetWindowTextW(hwnd, strCaption); - - // Set OK button text - CString strCopy(MAKEINTRESOURCEW(IDS_COPYBUTTON)); - SetDlgItemText(hwnd, IDOK, strCopy); - - // Subclassing - this_->m_fnOldWndProc = - reinterpret_cast( - SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast(WindowProc))); - - // Disable OK - PostMessageW(hwnd, BFFM_ENABLEOK, 0, FALSE); - break; - } - case BFFM_SELCHANGED: - { - if (!this_) - break; - - WCHAR szPath[MAX_PATH]; - LPCITEMIDLIST pidl = reinterpret_cast(lParam); - - szPath[0] = 0; - SHGetPathFromIDListW(pidl, szPath); - - if (ILIsEqual(pidl, this_->m_pidlFolder)) - PostMessageW(hwnd, BFFM_ENABLEOK, 0, FALSE); - else if (PathFileExistsW(szPath) || _ILIsDesktop(pidl)) - PostMessageW(hwnd, BFFM_ENABLEOK, 0, TRUE); - else - PostMessageW(hwnd, BFFM_ENABLEOK, 0, FALSE); - - // the text box will be updated later soon, ignore it - this_->m_bIgnoreTextBoxChange = TRUE; - break; - } - } - - return FALSE; -} - -HRESULT CCopyToMenu::DoRealCopy(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl) -{ - CDataObjectHIDA pCIDA(m_pDataObject); - if (FAILED_UNEXPECTEDLY(pCIDA.hr())) - return pCIDA.hr(); - - PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA); - if (!pidlParent) - { - ERR("HIDA_GetPIDLFolder failed\n"); - return E_FAIL; - } - - CStringW strFiles; - WCHAR szPath[MAX_PATH]; - for (UINT n = 0; n < pCIDA->cidl; ++n) - { - PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(pCIDA, n); - if (!pidlRelative) - continue; - - CComHeapPtr pidlCombine(ILCombine(pidlParent, pidlRelative)); - if (!pidl) - return E_FAIL; - - SHGetPathFromIDListW(pidlCombine, szPath); - - if (n > 0) - strFiles += L'|'; - strFiles += szPath; - } - - strFiles += L'|'; // double null-terminated - strFiles.Replace(L'|', L'\0'); - - if (_ILIsDesktop(pidl)) - SHGetSpecialFolderPathW(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE); - else - SHGetPathFromIDListW(pidl, szPath); - INT cchPath = lstrlenW(szPath); - if (cchPath + 1 < MAX_PATH) - { - szPath[cchPath + 1] = 0; // double null-terminated - } - else - { - ERR("Too long path\n"); - return E_FAIL; - } - - SHFILEOPSTRUCTW op = { lpici->hwnd }; - op.wFunc = FO_COPY; - op.pFrom = strFiles; - op.pTo = szPath; - op.fFlags = FOF_ALLOWUNDO; - int res = SHFileOperationW(&op); - if (res) - { - ERR("SHFileOperationW failed with 0x%x\n", res); - return E_FAIL; - } - return S_OK; -} - -CStringW CCopyToMenu::DoGetFileTitle() -{ - CStringW ret = L"(file)"; - - CDataObjectHIDA pCIDA(m_pDataObject); - if (FAILED_UNEXPECTEDLY(pCIDA.hr())) - return ret; - - PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA); - if (!pidlParent) - { - ERR("HIDA_GetPIDLFolder failed\n"); - return ret; - } - - WCHAR szPath[MAX_PATH]; - PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(pCIDA, 0); - if (!pidlRelative) - { - ERR("HIDA_GetPIDLItem failed\n"); - return ret; - } - - CComHeapPtr pidlCombine(ILCombine(pidlParent, pidlRelative)); - - if (SHGetPathFromIDListW(pidlCombine, szPath)) - ret = PathFindFileNameW(szPath); - else - ERR("Cannot get path\n"); - - if (pCIDA->cidl > 1) - ret += L" ..."; - - return ret; -} - -HRESULT CCopyToMenu::DoCopyToFolder(LPCMINVOKECOMMANDINFO lpici) -{ - WCHAR wszPath[MAX_PATH]; - HRESULT hr = E_FAIL; - - TRACE("DoCopyToFolder(%p)\n", lpici); - - if (!SHGetPathFromIDListW(m_pidlFolder, wszPath)) - { - ERR("SHGetPathFromIDListW failed\n"); - return hr; - } - - CStringW strFileTitle = DoGetFileTitle(); - CStringW strTitle; - strTitle.Format(IDS_COPYTOTITLE, static_cast(strFileTitle)); - - BROWSEINFOW info = { lpici->hwnd }; - info.pidlRoot = NULL; - info.lpszTitle = strTitle; - info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI; - info.lpfn = BrowseCallbackProc; - info.lParam = reinterpret_cast(this); - CComHeapPtr pidl(SHBrowseForFolder(&info)); - if (pidl) - { - hr = DoRealCopy(lpici, pidl); - } - - return hr; -} - -HRESULT WINAPI -CCopyToMenu::QueryContextMenu(HMENU hMenu, - UINT indexMenu, - UINT idCmdFirst, - UINT idCmdLast, - UINT uFlags) -{ - MENUITEMINFOW mii; - UINT Count = 0; - - TRACE("CCopyToMenu::QueryContextMenu(%p, %u, %u, %u, %u)\n", - hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); - - if (uFlags & (CMF_NOVERBS | CMF_VERBSONLY)) - return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst); - - m_idCmdFirst = m_idCmdLast = idCmdFirst; - - // insert separator if necessary - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE; - if (GetMenuItemInfoW(hMenu, indexMenu - 1, TRUE, &mii) && - mii.fType != MFT_SEPARATOR) - { - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE; - mii.fType = MFT_SEPARATOR; - if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii)) - { - ++indexMenu; - ++Count; - } - } - - // insert "Copy to folder..." - CStringW strText(MAKEINTRESOURCEW(IDS_COPYTOMENU)); - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_ID | MIIM_TYPE; - mii.fType = MFT_STRING; - mii.dwTypeData = strText.GetBuffer(); - mii.cch = wcslen(mii.dwTypeData); - mii.wID = m_idCmdLast; - if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii)) - { - m_idCmdCopyTo = m_idCmdLast++; - ++indexMenu; - ++Count; - } - - return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst + Count); -} - -HRESULT WINAPI -CCopyToMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) -{ - HRESULT hr = E_FAIL; - TRACE("CCopyToMenu::InvokeCommand(%p)\n", lpici); - - if (IS_INTRESOURCE(lpici->lpVerb)) - { - if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdCopyTo) - { - hr = DoCopyToFolder(lpici); - } - } - else - { - if (::lstrcmpiA(lpici->lpVerb, "copyto") == 0) - { - hr = DoCopyToFolder(lpici); - } - } - - return hr; -} - -HRESULT WINAPI -CCopyToMenu::GetCommandString(UINT_PTR idCmd, - UINT uType, - UINT *pwReserved, - LPSTR pszName, - UINT cchMax) -{ - FIXME("%p %lu %u %p %p %u\n", this, - idCmd, uType, pwReserved, pszName, cchMax); - - return E_NOTIMPL; -} - -HRESULT WINAPI -CCopyToMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TRACE("This %p uMsg %x\n", this, uMsg); - return E_NOTIMPL; -} - -HRESULT WINAPI -CCopyToMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, - IDataObject *pdtobj, HKEY hkeyProgID) -{ - m_pidlFolder.Attach(ILClone(pidlFolder)); - m_pDataObject = pdtobj; - return S_OK; -} - -HRESULT WINAPI CCopyToMenu::SetSite(IUnknown *pUnkSite) -{ - m_pSite = pUnkSite; - return S_OK; -} - -HRESULT WINAPI CCopyToMenu::GetSite(REFIID riid, void **ppvSite) -{ - if (!m_pSite) - return E_FAIL; - - return m_pSite->QueryInterface(riid, ppvSite); -} diff --git a/dll/win32/shell32/CCopyToMoveToMenu.h b/dll/win32/shell32/CCopyToMoveToMenu.h deleted file mode 100644 index 01ee85d30c7..00000000000 --- a/dll/win32/shell32/CCopyToMoveToMenu.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * PROJECT: shell32 - * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) - * PURPOSE: CopyTo and MoveTo implementation - * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) - */ -#pragma once - - -class CCopyToMenu : - public CComCoClass, - public CComObjectRootEx, - public IContextMenu2, - public IObjectWithSite, - public IShellExtInit -{ -protected: - UINT m_idCmdFirst, m_idCmdLast, m_idCmdCopyTo; - CComPtr m_pDataObject; - CComPtr m_pSite; - - HRESULT DoCopyToFolder(LPCMINVOKECOMMANDINFO lpici); - HRESULT DoRealCopy(LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidl); - CStringW DoGetFileTitle(); - -public: - CComHeapPtr m_pidlFolder; - WNDPROC m_fnOldWndProc; - BOOL m_bIgnoreTextBoxChange; - - CCopyToMenu(); - ~CCopyToMenu(); - - // IContextMenu - virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); - virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi); - virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen); - - // IContextMenu2 - virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam); - - // IShellExtInit - virtual HRESULT WINAPI Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID); - - // IObjectWithSite - virtual HRESULT WINAPI SetSite(IUnknown *pUnkSite); - virtual HRESULT WINAPI GetSite(REFIID riid, void **ppvSite); - - DECLARE_REGISTRY_RESOURCEID(IDR_COPYTOMENU) - DECLARE_NOT_AGGREGATABLE(CCopyToMenu) - - DECLARE_PROTECT_FINAL_CONSTRUCT() - - BEGIN_COM_MAP(CCopyToMenu) - COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2) - COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) - COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) - COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) - END_COM_MAP() -}; - -class CMoveToMenu : - public CComCoClass, - public CComObjectRootEx, - public IContextMenu2, - public IObjectWithSite, - public IShellExtInit -{ -protected: - UINT m_idCmdFirst, m_idCmdLast, m_idCmdMoveTo; - CComPtr m_pDataObject; - CComPtr m_pSite; - - HRESULT DoMoveToFolder(LPCMINVOKECOMMANDINFO lpici); - HRESULT DoRealMove(LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidl); - CStringW DoGetFileTitle(); - -public: - CComHeapPtr m_pidlFolder; - WNDPROC m_fnOldWndProc; - BOOL m_bIgnoreTextBoxChange; - - CMoveToMenu(); - ~CMoveToMenu(); - - // IContextMenu - virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); - virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi); - virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen); - - // IContextMenu2 - virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam); - - // IShellExtInit - virtual HRESULT WINAPI Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID); - - // IObjectWithSite - virtual HRESULT WINAPI SetSite(IUnknown *pUnkSite); - virtual HRESULT WINAPI GetSite(REFIID riid, void **ppvSite); - - DECLARE_REGISTRY_RESOURCEID(IDR_MOVETOMENU) - DECLARE_NOT_AGGREGATABLE(CMoveToMenu) - - DECLARE_PROTECT_FINAL_CONSTRUCT() - - BEGIN_COM_MAP(CMoveToMenu) - COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2) - COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) - COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) - COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) - END_COM_MAP() -}; diff --git a/dll/win32/shell32/CMakeLists.txt b/dll/win32/shell32/CMakeLists.txt index 5f972807c8b..264b116f5a2 100644 --- a/dll/win32/shell32/CMakeLists.txt +++ b/dll/win32/shell32/CMakeLists.txt @@ -73,8 +73,7 @@ list(APPEND SOURCE COpenWithMenu.cpp CNewMenu.cpp CSendToMenu.cpp - CCopyToMenu.cpp - CMoveToMenu.cpp + CCopyMoveToMenu.cpp CShellDispatch.cpp CFolder.cpp CFolderItems.cpp diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h index 9b422353e6c..393693885ac 100644 --- a/dll/win32/shell32/precomp.h +++ b/dll/win32/shell32/precomp.h @@ -95,7 +95,7 @@ #include "COpenWithMenu.h" #include "CNewMenu.h" #include "CSendToMenu.h" -#include "CCopyToMoveToMenu.h" +#include "CCopyMoveToMenu.h" #include "dialogs/filedefext.h" #include "dialogs/drvdefext.h" #include "CQueryAssociations.h"