https://git.reactos.org/?p=reactos.git;a=commitdiff;h=85fdcdf2ccd6b569eeaa8e771a98ab47a6de687c

commit 85fdcdf2ccd6b569eeaa8e771a98ab47a6de687c
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sun Aug 16 08:04:07 2020 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sun Aug 16 08:04:07 2020 +0900

    [SHELL32] Implement Copy To Folder (retrial) (#3044)
    
    - Add context menu item "Copy to &folder..." and implement the action.
    - Implement the "Copy to &folder..." menu item of "Edit" menu of Explorer.
    CORE-11132
---
 dll/win32/shell32/CCopyToMenu.cpp         | 374 ++++++++++++++++++++++++++++++
 dll/win32/shell32/CCopyToMenu.h           |  58 +++++
 dll/win32/shell32/CDefView.cpp            |  21 ++
 dll/win32/shell32/CDefaultContextMenu.cpp |  35 ++-
 dll/win32/shell32/CMakeLists.txt          |   1 +
 dll/win32/shell32/lang/bg-BG.rc           |   4 +
 dll/win32/shell32/lang/ca-ES.rc           |   4 +
 dll/win32/shell32/lang/cs-CZ.rc           |   4 +
 dll/win32/shell32/lang/da-DK.rc           |   4 +
 dll/win32/shell32/lang/de-DE.rc           |   4 +
 dll/win32/shell32/lang/el-GR.rc           |   4 +
 dll/win32/shell32/lang/en-GB.rc           |   4 +
 dll/win32/shell32/lang/en-US.rc           |   4 +
 dll/win32/shell32/lang/es-ES.rc           |   4 +
 dll/win32/shell32/lang/et-EE.rc           |   4 +
 dll/win32/shell32/lang/fi-FI.rc           |   4 +
 dll/win32/shell32/lang/fr-FR.rc           |   4 +
 dll/win32/shell32/lang/he-IL.rc           |   4 +
 dll/win32/shell32/lang/hi-IN.rc           |   4 +
 dll/win32/shell32/lang/hu-HU.rc           |   4 +
 dll/win32/shell32/lang/id-ID.rc           |   4 +
 dll/win32/shell32/lang/it-IT.rc           |   4 +
 dll/win32/shell32/lang/ja-JP.rc           |   4 +
 dll/win32/shell32/lang/ko-KR.rc           |   4 +
 dll/win32/shell32/lang/nl-NL.rc           |   4 +
 dll/win32/shell32/lang/no-NO.rc           |   4 +
 dll/win32/shell32/lang/pl-PL.rc           |   4 +
 dll/win32/shell32/lang/pt-BR.rc           |   4 +
 dll/win32/shell32/lang/pt-PT.rc           |   4 +
 dll/win32/shell32/lang/ro-RO.rc           |   4 +
 dll/win32/shell32/lang/ru-RU.rc           |   4 +
 dll/win32/shell32/lang/sk-SK.rc           |   4 +
 dll/win32/shell32/lang/sl-SI.rc           |   4 +
 dll/win32/shell32/lang/sq-AL.rc           |   4 +
 dll/win32/shell32/lang/sv-SE.rc           |   4 +
 dll/win32/shell32/lang/tr-TR.rc           |   4 +
 dll/win32/shell32/lang/uk-UA.rc           |   4 +
 dll/win32/shell32/lang/zh-CN.rc           |   4 +
 dll/win32/shell32/lang/zh-TW.rc           |   4 +
 dll/win32/shell32/precomp.h               |   1 +
 dll/win32/shell32/res/rgs/copytomenu.rgs  |  26 +++
 dll/win32/shell32/rgs_res.rc              |   1 +
 dll/win32/shell32/shell32.cpp             |   1 +
 dll/win32/shell32/shresdef.h              |   6 +
 44 files changed, 659 insertions(+), 1 deletion(-)

diff --git a/dll/win32/shell32/CCopyToMenu.cpp 
b/dll/win32/shell32/CCopyToMenu.cpp
new file mode 100644
index 00000000000..bc1325bb86d
--- /dev/null
+++ b/dll/win32/shell32/CCopyToMenu.cpp
@@ -0,0 +1,374 @@
+/*
+ * 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 
([email protected])
+ */
+
+#include "precomp.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+static HRESULT
+_GetCidlFromDataObject(IDataObject *pDataObject, CIDA** ppcida)
+{
+    static CLIPFORMAT s_cfHIDA = 0;
+    if (s_cfHIDA == 0)
+    {
+        s_cfHIDA = 
static_cast<CLIPFORMAT>(RegisterClipboardFormatW(CFSTR_SHELLIDLIST));
+    }
+
+    FORMATETC fmt = { s_cfHIDA, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+    STGMEDIUM medium;
+
+    HRESULT hr = pDataObject->GetData(&fmt, &medium);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    LPVOID lpSrc = GlobalLock(medium.hGlobal);
+    SIZE_T cbSize = GlobalSize(medium.hGlobal);
+
+    *ppcida = reinterpret_cast<CIDA *>(::CoTaskMemAlloc(cbSize));
+    if (*ppcida)
+    {
+        memcpy(*ppcida, lpSrc, cbSize);
+        hr = S_OK;
+    }
+    else
+    {
+        ERR("Out of memory\n");
+        hr = E_FAIL;
+    }
+    ReleaseStgMedium(&medium);
+    return hr;
+}
+
+CCopyToMenu::CCopyToMenu() :
+    m_idCmdFirst(0),
+    m_idCmdLast(0),
+    m_idCmdCopyTo(-1)
+{
+}
+
+CCopyToMenu::~CCopyToMenu()
+{
+}
+
+#define WM_ENABLEOK (WM_USER + 0x2000)
+
+static LRESULT CALLBACK
+WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    CCopyToMenu *this_ =
+        reinterpret_cast<CCopyToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
+
+    switch (uMsg)
+    {
+        case WM_ENABLEOK:
+            SendMessageW(hwnd, BFFM_ENABLEOK, 0, (BOOL)lParam);
+            return 0;
+    }
+    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<CCopyToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
+
+    switch (uMsg)
+    {
+        case BFFM_INITIALIZED:
+        {
+            SetWindowLongPtr(hwnd, GWLP_USERDATA, lpData);
+            this_ = reinterpret_cast<CCopyToMenu *>(lpData);
+
+            // Select initial directory
+            SendMessageW(hwnd, BFFM_SETSELECTION, FALSE,
+                
reinterpret_cast<LPARAM>(static_cast<LPCITEMIDLIST>(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<WNDPROC>(
+                    SetWindowLongPtr(hwnd, GWLP_WNDPROC, 
reinterpret_cast<LONG_PTR>(WindowProc)));
+
+            // Disable OK
+            PostMessageW(hwnd, WM_ENABLEOK, 0, FALSE);
+            break;
+        }
+        case BFFM_SELCHANGED:
+        {
+            WCHAR szPath[MAX_PATH];
+            LPCITEMIDLIST pidl = reinterpret_cast<LPCITEMIDLIST>(lParam);
+
+            szPath[0] = 0;
+            SHGetPathFromIDListW(pidl, szPath);
+
+            if (ILIsEqual(pidl, this_->m_pidlFolder))
+                PostMessageW(hwnd, WM_ENABLEOK, 0, FALSE);
+            else if (PathFileExistsW(szPath) || _ILIsDesktop(pidl))
+                PostMessageW(hwnd, WM_ENABLEOK, 0, TRUE);
+            else
+                PostMessageW(hwnd, WM_ENABLEOK, 0, FALSE);
+            break;
+        }
+    }
+
+    return FALSE;
+}
+
+HRESULT CCopyToMenu::DoRealCopy(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST 
pidl)
+{
+    CComHeapPtr<CIDA> pCIDA;
+    HRESULT hr = _GetCidlFromDataObject(m_pDataObject, &pCIDA);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return 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<ITEMIDLIST> 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;
+    return ((SHFileOperation(&op) == 0) ? S_OK : E_FAIL);
+}
+
+CStringW CCopyToMenu::DoGetFileTitle()
+{
+    CStringW ret = L"(file)";
+
+    CComHeapPtr<CIDA> pCIDA;
+    HRESULT hr = _GetCidlFromDataObject(m_pDataObject, &pCIDA);
+    if (FAILED_UNEXPECTEDLY(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<ITEMIDLIST> 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<LPCWSTR>(strFileTitle));
+
+    BROWSEINFOW info = { lpici->hwnd };
+    info.pidlRoot = NULL;
+    info.lpszTitle = strTitle;
+    info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
+    info.lpfn = BrowseCallbackProc;
+    info.lParam = reinterpret_cast<LPARAM>(this);
+    CComHeapPtr<ITEMIDLIST> 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);
+
+    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, Count);
+}
+
+HRESULT WINAPI
+CCopyToMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
+{
+    HRESULT hr = E_FAIL;
+    TRACE("CCopyToMenu::InvokeCommand(%p)\n", lpici);
+
+    if (HIWORD(lpici->lpVerb) == 0)
+    {
+        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/CCopyToMenu.h b/dll/win32/shell32/CCopyToMenu.h
new file mode 100644
index 00000000000..a56cba111de
--- /dev/null
+++ b/dll/win32/shell32/CCopyToMenu.h
@@ -0,0 +1,58 @@
+/*
+ * 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 
([email protected])
+ */
+#pragma once
+
+class CCopyToMenu :
+    public CComCoClass<CCopyToMenu, &CLSID_CopyToMenu>,
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public IContextMenu2,
+    public IObjectWithSite,
+    public IShellExtInit
+{
+protected:
+    UINT m_idCmdFirst, m_idCmdLast, m_idCmdCopyTo;
+    CComPtr<IDataObject> m_pDataObject;
+    CComPtr<IUnknown> m_pSite;
+
+    HRESULT DoCopyToFolder(LPCMINVOKECOMMANDINFO lpici);
+    HRESULT DoRealCopy(LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidl);
+    CStringW DoGetFileTitle();
+
+public:
+    CComHeapPtr<ITEMIDLIST> m_pidlFolder;
+    WNDPROC m_fnOldWndProc;
+
+    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()
+};
diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp
index cb5dd140eb1..a42d4d495cb 100644
--- a/dll/win32/shell32/CDefView.cpp
+++ b/dll/win32/shell32/CDefView.cpp
@@ -1822,6 +1822,7 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, 
LPARAM lParam, BOOL &bHand
         case FCIDM_SHVIEW_COPY:
         case FCIDM_SHVIEW_RENAME:
         case FCIDM_SHVIEW_PROPERTIES:
+        case FCIDM_SHVIEW_COPYTO:
             return OnExplorerCommand(dwCmdID, TRUE);
 
         case FCIDM_SHVIEW_INSERT:
@@ -2295,6 +2296,26 @@ LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM 
wParam, LPARAM lParam, BOOL
 
     HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW);
 
+    if (GetSelections() == 0)
+    {
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_CUT, MF_GRAYED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPY, MF_GRAYED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, MF_GRAYED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPYTO, MF_GRAYED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_MOVETO, MF_GRAYED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_DELETE, MF_GRAYED);
+    }
+    else
+    {
+        // FIXME: Check copyable
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_CUT, MF_ENABLED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPY, MF_ENABLED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, MF_ENABLED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPYTO, MF_ENABLED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_MOVETO, MF_ENABLED);
+        ::EnableMenuItem(hmenu, FCIDM_SHVIEW_DELETE, MF_ENABLED);
+    }
+
     /* Lets try to find out what the hell wParam is */
     if (hmenu == GetSubMenu(m_hMenu, nPos))
         menuItemId = ReallyGetMenuItemID(m_hMenu, nPos);
diff --git a/dll/win32/shell32/CDefaultContextMenu.cpp 
b/dll/win32/shell32/CDefaultContextMenu.cpp
index d36d042c70c..a717078f70b 100644
--- a/dll/win32/shell32/CDefaultContextMenu.cpp
+++ b/dll/win32/shell32/CDefaultContextMenu.cpp
@@ -48,9 +48,9 @@ struct _StaticInvokeCommandMap_
     { "delete", FCIDM_SHVIEW_DELETE},
     { "properties", FCIDM_SHVIEW_PROPERTIES},
     { "rename", FCIDM_SHVIEW_RENAME},
+    { "copyto", FCIDM_SHVIEW_COPYTO },
 };
 
-
 class CDefaultContextMenu :
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
     public IContextMenu3,
@@ -95,6 +95,7 @@ class CDefaultContextMenu :
         HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi);
         HRESULT DoProperties(LPCMINVOKECOMMANDINFO lpcmi);
         HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFO lpici);
+        HRESULT DoCopyToFolder(LPCMINVOKECOMMANDINFO lpici);
         HRESULT InvokeShellExt(LPCMINVOKECOMMANDINFO lpcmi);
         HRESULT InvokeRegVerb(LPCMINVOKECOMMANDINFO lpcmi);
         DWORD BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, 
PStaticShellEntry pEntry);
@@ -893,6 +894,35 @@ CDefaultContextMenu::DoProperties(
     return S_OK;
 }
 
+HRESULT
+CDefaultContextMenu::DoCopyToFolder(LPCMINVOKECOMMANDINFO lpici)
+{
+    HRESULT hr = E_FAIL;
+    if (!m_pDataObj)
+    {
+        ERR("m_pDataObj is NULL\n");
+        return hr;
+    }
+
+    CComPtr<IContextMenu> pContextMenu;
+    hr = SHCoCreateInstance(NULL, &CLSID_CopyToMenu, NULL, 
IID_PPV_ARG(IContextMenu, &pContextMenu));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    CComPtr<IShellExtInit> pInit;
+    hr = pContextMenu->QueryInterface(IID_PPV_ARG(IShellExtInit, &pInit));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    hr = pInit->Initialize(m_pidlFolder, m_pDataObj, NULL);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    lpici->lpVerb = "copyto";
+
+    return pContextMenu->InvokeCommand(lpici);
+}
+
 // This code is taken from CNewMenu and should be shared between the 2 classes
 HRESULT
 CDefaultContextMenu::DoCreateNewFolder(
@@ -1248,6 +1278,9 @@ CDefaultContextMenu::InvokeCommand(
     case FCIDM_SHVIEW_NEWFOLDER:
         Result = DoCreateNewFolder(&LocalInvokeInfo);
         break;
+    case FCIDM_SHVIEW_COPYTO:
+        Result = DoCopyToFolder(&LocalInvokeInfo);
+        break;
     default:
         Result = E_INVALIDARG;
         ERR("Unhandled Verb %xl\n", LOWORD(LocalInvokeInfo.lpVerb));
diff --git a/dll/win32/shell32/CMakeLists.txt b/dll/win32/shell32/CMakeLists.txt
index e0a84c9fe8e..aa51a47fe43 100644
--- a/dll/win32/shell32/CMakeLists.txt
+++ b/dll/win32/shell32/CMakeLists.txt
@@ -83,6 +83,7 @@ list(APPEND SOURCE
     COpenWithMenu.cpp
     CNewMenu.cpp
     CSendToMenu.cpp
+    CCopyToMenu.cpp
     CShellDispatch.cpp
     CFolder.cpp
     CFolderItems.cpp
diff --git a/dll/win32/shell32/lang/bg-BG.rc b/dll/win32/shell32/lang/bg-BG.rc
index 9c1a859495c..56ca1049511 100644
--- a/dll/win32/shell32/lang/bg-BG.rc
+++ b/dll/win32/shell32/lang/bg-BG.rc
@@ -999,4 +999,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/ca-ES.rc b/dll/win32/shell32/lang/ca-ES.rc
index 13595784d31..8e920649408 100644
--- a/dll/win32/shell32/lang/ca-ES.rc
+++ b/dll/win32/shell32/lang/ca-ES.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/cs-CZ.rc b/dll/win32/shell32/lang/cs-CZ.rc
index 5e41d728b22..4c86a7c5869 100644
--- a/dll/win32/shell32/lang/cs-CZ.rc
+++ b/dll/win32/shell32/lang/cs-CZ.rc
@@ -1004,4 +1004,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/da-DK.rc b/dll/win32/shell32/lang/da-DK.rc
index 48abdf760b3..6bf29e180b5 100644
--- a/dll/win32/shell32/lang/da-DK.rc
+++ b/dll/win32/shell32/lang/da-DK.rc
@@ -1004,4 +1004,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/de-DE.rc b/dll/win32/shell32/lang/de-DE.rc
index 0fdce04259d..cc4b49246a7 100644
--- a/dll/win32/shell32/lang/de-DE.rc
+++ b/dll/win32/shell32/lang/de-DE.rc
@@ -999,4 +999,8 @@ BEGIN
     IDS_NO_ICONS "Die Datei '%s' enthält keine Symbole.\n\nWählen Sie ein 
Symbol aus der Liste oder wählen Sie eine andere Datei."
     IDS_FILE_NOT_FOUND "Die Datei '%s' wurde nicht gefunden."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/el-GR.rc b/dll/win32/shell32/lang/el-GR.rc
index cc9c8c15ba4..fd2bb3cfc42 100644
--- a/dll/win32/shell32/lang/el-GR.rc
+++ b/dll/win32/shell32/lang/el-GR.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/en-GB.rc b/dll/win32/shell32/lang/en-GB.rc
index 2fa65e383ed..4d1f9e55495 100644
--- a/dll/win32/shell32/lang/en-GB.rc
+++ b/dll/win32/shell32/lang/en-GB.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/en-US.rc b/dll/win32/shell32/lang/en-US.rc
index 0af80340d2c..21f06a42d42 100644
--- a/dll/win32/shell32/lang/en-US.rc
+++ b/dll/win32/shell32/lang/en-US.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/es-ES.rc b/dll/win32/shell32/lang/es-ES.rc
index 8b2afe4f73c..bdf04fd74a4 100644
--- a/dll/win32/shell32/lang/es-ES.rc
+++ b/dll/win32/shell32/lang/es-ES.rc
@@ -1007,4 +1007,8 @@ BEGIN
     IDS_NO_ICONS "El archivo '%s' no contiene íconos.\n\nEscoja un ícono de la 
lista o seleccione otro archivo."
     IDS_FILE_NOT_FOUND "El archivo '%s' no pudo ser encontrado."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/et-EE.rc b/dll/win32/shell32/lang/et-EE.rc
index 9f9703ca32a..8585ad68b08 100644
--- a/dll/win32/shell32/lang/et-EE.rc
+++ b/dll/win32/shell32/lang/et-EE.rc
@@ -1005,4 +1005,8 @@ BEGIN
     IDS_NO_ICONS "Fail '%s' ei sisalda ühtegi ikooni.\n\nVali ikoon 
nimekirjast või määra teine fail."
     IDS_FILE_NOT_FOUND "Faili '%s' ei leitud."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/fi-FI.rc b/dll/win32/shell32/lang/fi-FI.rc
index 9b112922152..80356afb3d5 100644
--- a/dll/win32/shell32/lang/fi-FI.rc
+++ b/dll/win32/shell32/lang/fi-FI.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/fr-FR.rc b/dll/win32/shell32/lang/fr-FR.rc
index fc780633ed9..019fed4cc69 100644
--- a/dll/win32/shell32/lang/fr-FR.rc
+++ b/dll/win32/shell32/lang/fr-FR.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "Le fichier '%s' ne contient pas d'icônes.\n\nVeuillez 
choisir une icône dans la liste ou sélectionner un fichier différent."
     IDS_FILE_NOT_FOUND "Le fichier '%s' ne peut être trouvé."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/he-IL.rc b/dll/win32/shell32/lang/he-IL.rc
index 51e94334e7f..8d469bf407e 100644
--- a/dll/win32/shell32/lang/he-IL.rc
+++ b/dll/win32/shell32/lang/he-IL.rc
@@ -1000,4 +1000,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "לא ניתן למצוא את הקובץ '%s'."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/hi-IN.rc b/dll/win32/shell32/lang/hi-IN.rc
index 101d5b5c136..59be1fd3cbf 100644
--- a/dll/win32/shell32/lang/hi-IN.rc
+++ b/dll/win32/shell32/lang/hi-IN.rc
@@ -993,4 +993,8 @@ BEGIN
     IDS_NO_ICONS "फ़ाइल '%s' में कोई आइकन नहीं है।\n\nसूची से एक आइकन चुनें या 
एक अलग फ़ाइल निर्दिष्ट करें।"
     IDS_FILE_NOT_FOUND "फ़ाइल '%s' नहीं मिली।"
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/hu-HU.rc b/dll/win32/shell32/lang/hu-HU.rc
index 1b3a743f11e..90f964dbd7c 100644
--- a/dll/win32/shell32/lang/hu-HU.rc
+++ b/dll/win32/shell32/lang/hu-HU.rc
@@ -997,4 +997,8 @@ BEGIN
     IDS_NO_ICONS "A fájl ('%s') nem tartalmaz ikonokat.\n\nVálasszon egy ikont 
a listából, vagy adjon meg egy másik fájlt."
     IDS_FILE_NOT_FOUND "A fájl ('%s') nem található."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/id-ID.rc b/dll/win32/shell32/lang/id-ID.rc
index 90c22133c2b..09571a9f2a6 100644
--- a/dll/win32/shell32/lang/id-ID.rc
+++ b/dll/win32/shell32/lang/id-ID.rc
@@ -994,4 +994,8 @@ BEGIN
     IDS_NO_ICONS "Berkas '%s' tidak berisi ikon.\n\nPilih ikon dari daftar 
atau pilih berkas yang berbeda."
     IDS_FILE_NOT_FOUND "Berkas '%s' tidak ditemukan."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/it-IT.rc b/dll/win32/shell32/lang/it-IT.rc
index b1bf68e20d7..ed3dac4bfc8 100644
--- a/dll/win32/shell32/lang/it-IT.rc
+++ b/dll/win32/shell32/lang/it-IT.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/ja-JP.rc b/dll/win32/shell32/lang/ja-JP.rc
index d385640dfdd..3593c981ce7 100644
--- a/dll/win32/shell32/lang/ja-JP.rc
+++ b/dll/win32/shell32/lang/ja-JP.rc
@@ -995,4 +995,8 @@ BEGIN
     IDS_NO_ICONS "ファイル '%s' にはアイコン 
データがありません。.\n\nリストからアイコンを選ぶか、別のファイルを指定して下さい。"
     IDS_FILE_NOT_FOUND "ファイル '%s' は見つかりませんでした。"
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/ko-KR.rc b/dll/win32/shell32/lang/ko-KR.rc
index 6fed522e97d..3c46406aab7 100644
--- a/dll/win32/shell32/lang/ko-KR.rc
+++ b/dll/win32/shell32/lang/ko-KR.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/nl-NL.rc b/dll/win32/shell32/lang/nl-NL.rc
index 14181b2cc6a..26b311387a5 100644
--- a/dll/win32/shell32/lang/nl-NL.rc
+++ b/dll/win32/shell32/lang/nl-NL.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/no-NO.rc b/dll/win32/shell32/lang/no-NO.rc
index 502648fef4e..1831921be23 100644
--- a/dll/win32/shell32/lang/no-NO.rc
+++ b/dll/win32/shell32/lang/no-NO.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/pl-PL.rc b/dll/win32/shell32/lang/pl-PL.rc
index 1b5de4427d8..b125105cb29 100644
--- a/dll/win32/shell32/lang/pl-PL.rc
+++ b/dll/win32/shell32/lang/pl-PL.rc
@@ -1004,4 +1004,8 @@ BEGIN
     IDS_NO_ICONS "Plik '%s' nie zawiera ikon.\n\nWybierz ikonę z listy lub 
określ inny plik."
     IDS_FILE_NOT_FOUND "Nie odnaleziono pliku '%s'."
     IDS_LINK_INVALID "Element '%s', do którego odwołuje się ten skrót, został 
zmieniony lub przeniesiony i dlatego skrót ten nie będzie działał poprawnie."
+    IDS_COPYTOMENU "Copy To &Folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/pt-BR.rc b/dll/win32/shell32/lang/pt-BR.rc
index 0bca68bc3f4..9610e4e0fb6 100644
--- a/dll/win32/shell32/lang/pt-BR.rc
+++ b/dll/win32/shell32/lang/pt-BR.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/pt-PT.rc b/dll/win32/shell32/lang/pt-PT.rc
index 1325c971be2..f64de677bc9 100644
--- a/dll/win32/shell32/lang/pt-PT.rc
+++ b/dll/win32/shell32/lang/pt-PT.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "O arquivo '%s' não contém ícones.\n\nEscolha um ícone da 
lista ou especifique um arquivo diferente."
     IDS_FILE_NOT_FOUND "O arquivo '%s' não foi encontrado."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/ro-RO.rc b/dll/win32/shell32/lang/ro-RO.rc
index 1cbf12ba8aa..b4f0e6059aa 100644
--- a/dll/win32/shell32/lang/ro-RO.rc
+++ b/dll/win32/shell32/lang/ro-RO.rc
@@ -1000,4 +1000,8 @@ BEGIN
     IDS_NO_ICONS "Fișierul „%s” nu conține pictograme.\n\nAlegeți o pictogramă 
din listă sau specificați un alt fișier."
     IDS_FILE_NOT_FOUND "Fișierul „%s” nu a fost găsit."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/ru-RU.rc b/dll/win32/shell32/lang/ru-RU.rc
index 52e20a39d8e..a12ecfe9d2b 100644
--- a/dll/win32/shell32/lang/ru-RU.rc
+++ b/dll/win32/shell32/lang/ru-RU.rc
@@ -1005,4 +1005,8 @@ BEGIN
     IDS_NO_ICONS "Файл '%s' не содержит значков.\n\nВыберите значок из списка 
или укажите другой файл."
     IDS_FILE_NOT_FOUND "Файл '%s' не найден."
     IDS_LINK_INVALID "Элемент '%s', на который ссылается этот ярлык, был 
изменён или перемещён, поэтому ярлык не будет работать правильно."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/sk-SK.rc b/dll/win32/shell32/lang/sk-SK.rc
index 5fb69feaf1e..93e87e85cad 100644
--- a/dll/win32/shell32/lang/sk-SK.rc
+++ b/dll/win32/shell32/lang/sk-SK.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/sl-SI.rc b/dll/win32/shell32/lang/sl-SI.rc
index a8daae20a67..eca49866975 100644
--- a/dll/win32/shell32/lang/sl-SI.rc
+++ b/dll/win32/shell32/lang/sl-SI.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/sq-AL.rc b/dll/win32/shell32/lang/sq-AL.rc
index 36362694a9e..fa69346d878 100644
--- a/dll/win32/shell32/lang/sq-AL.rc
+++ b/dll/win32/shell32/lang/sq-AL.rc
@@ -1002,4 +1002,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/sv-SE.rc b/dll/win32/shell32/lang/sv-SE.rc
index 0eaf3eae9c9..a81f73f5c6a 100644
--- a/dll/win32/shell32/lang/sv-SE.rc
+++ b/dll/win32/shell32/lang/sv-SE.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/tr-TR.rc b/dll/win32/shell32/lang/tr-TR.rc
index c4fda54ac1e..519103301b3 100644
--- a/dll/win32/shell32/lang/tr-TR.rc
+++ b/dll/win32/shell32/lang/tr-TR.rc
@@ -1000,4 +1000,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/uk-UA.rc b/dll/win32/shell32/lang/uk-UA.rc
index 85b0ea6ee96..62d8787ec23 100644
--- a/dll/win32/shell32/lang/uk-UA.rc
+++ b/dll/win32/shell32/lang/uk-UA.rc
@@ -998,4 +998,8 @@ BEGIN
     IDS_NO_ICONS "Файл '%s' не містить значків.\n\nВиберіть значок зі списку 
або відкрийте інший файл."
     IDS_FILE_NOT_FOUND "Файд '%s' не знайдено."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/zh-CN.rc b/dll/win32/shell32/lang/zh-CN.rc
index 70d68078cc4..a07f3cfdaf6 100644
--- a/dll/win32/shell32/lang/zh-CN.rc
+++ b/dll/win32/shell32/lang/zh-CN.rc
@@ -1008,4 +1008,8 @@ BEGIN
     IDS_NO_ICONS "文件 '%s' 不包含图标\n\n从列表中选择一个图标或指定其他文件。"
     IDS_FILE_NOT_FOUND "无法找到文件 '%s'。"
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/lang/zh-TW.rc b/dll/win32/shell32/lang/zh-TW.rc
index 9f01928299a..c634e81d2f4 100644
--- a/dll/win32/shell32/lang/zh-TW.rc
+++ b/dll/win32/shell32/lang/zh-TW.rc
@@ -1009,4 +1009,8 @@ BEGIN
     IDS_NO_ICONS "The file '%s' contains no icons.\n\nChoose an icon from the 
list or specify a different file."
     IDS_FILE_NOT_FOUND "The file '%s' was not found."
     IDS_LINK_INVALID "The item '%s' that this shortcut refers to has been 
changed or moved, so this shortcut will no longer work properly."
+    IDS_COPYTOMENU "Copy to &folder..."
+    IDS_COPYTOTITLE "Select the place where you want to copy '%s'. Then click 
the Copy button."
+    IDS_COPYITEMS "Copy Items"
+    IDS_COPYBUTTON "Copy"
 END
diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h
index da9155f0bff..2703b42e817 100644
--- a/dll/win32/shell32/precomp.h
+++ b/dll/win32/shell32/precomp.h
@@ -81,6 +81,7 @@
 #include "COpenWithMenu.h"
 #include "CNewMenu.h"
 #include "CSendToMenu.h"
+#include "CCopyToMenu.h"
 #include "dialogs/filedefext.h"
 #include "dialogs/drvdefext.h"
 #include "CQueryAssociations.h"
diff --git a/dll/win32/shell32/res/rgs/copytomenu.rgs 
b/dll/win32/shell32/res/rgs/copytomenu.rgs
new file mode 100644
index 00000000000..8f2726c811c
--- /dev/null
+++ b/dll/win32/shell32/res/rgs/copytomenu.rgs
@@ -0,0 +1,26 @@
+HKCR
+{
+       NoRemove CLSID
+       {
+               ForceRemove {C2FBB630-2971-11D1-A18C-00C04FD75D13} = s 'ReactOS 
CopyTo Object Service'
+               {
+                       val flags = d '1'
+                       InprocServer32 = s '%MODULE%'
+                       {
+                               val ThreadingModel = s 'Apartment'
+                       }
+               }
+       }
+       NoRemove AllFilesystemObjects
+       {
+               NoRemove shellex
+               {
+                       NoRemove ContextMenuHandlers
+                       {
+                               ForceRemove CopyTo = s 
'{C2FBB630-2971-11D1-A18C-00C04FD75D13}'
+                               {
+                               }
+                       }
+               }
+       }
+}
diff --git a/dll/win32/shell32/rgs_res.rc b/dll/win32/shell32/rgs_res.rc
index d46053ddd99..9435241aaaa 100644
--- a/dll/win32/shell32/rgs_res.rc
+++ b/dll/win32/shell32/rgs_res.rc
@@ -30,3 +30,4 @@ IDR_USERNOTIFICATION REGISTRY "res/rgs/usernotification.rgs"
 IDR_SHELL REGISTRY "res/rgs/shell.rgs"
 IDR_ACTIVEDESKTOP REGISTRY "res/rgs/activedesktop.rgs"
 IDR_SENDTOMENU REGISTRY "res/rgs/sendtomenu.rgs"
+IDR_COPYTOMENU REGISTRY "res/rgs/copytomenu.rgs"
diff --git a/dll/win32/shell32/shell32.cpp b/dll/win32/shell32/shell32.cpp
index c244477cf6b..527cbd29342 100644
--- a/dll/win32/shell32/shell32.cpp
+++ b/dll/win32/shell32/shell32.cpp
@@ -290,6 +290,7 @@ BEGIN_OBJECT_MAP(ObjectMap)
     OBJECT_ENTRY(CLSID_OpenWithMenu, COpenWithMenu)
     OBJECT_ENTRY(CLSID_NewMenu, CNewMenu)
     OBJECT_ENTRY(CLSID_SendToMenu, CSendToMenu)
+    OBJECT_ENTRY(CLSID_CopyToMenu, CCopyToMenu)
     OBJECT_ENTRY(CLSID_StartMenu, CStartMenuDummy)
     OBJECT_ENTRY(CLSID_MenuBandSite, CMenuSite)
     OBJECT_ENTRY(CLSID_MenuBand, CMenuBand)
diff --git a/dll/win32/shell32/shresdef.h b/dll/win32/shell32/shresdef.h
index 2152134eefc..81f22f97530 100644
--- a/dll/win32/shell32/shresdef.h
+++ b/dll/win32/shell32/shresdef.h
@@ -297,6 +297,10 @@
 #define IDS_NO_ICONS                                30529
 #define IDS_FILE_NOT_FOUND                          30530
 #define IDS_LINK_INVALID                            30531
+#define IDS_COPYTOMENU                              30532
+#define IDS_COPYTOTITLE                             30533
+#define IDS_COPYITEMS                               30534
+#define IDS_COPYBUTTON                              30535
 
 /* Dialogs */
 
@@ -796,6 +800,7 @@
 #define IDM_DELETE (FCIDM_SHVIEW_DELETE - 0x7000)
 #define IDM_RENAME (FCIDM_SHVIEW_RENAME - 0x7000)
 #define IDM_PROPERTIES (FCIDM_SHVIEW_PROPERTIES - 0x7000)
+#define IDM_COPYTO (FCIDM_SHVIEW_COPYTO - 0x7000)
 
 #define IDM_DRAGFILE 0xce
 #define IDM_COPYHERE 0x7
@@ -836,3 +841,4 @@
 #define IDR_SHELL               156
 #define IDR_ACTIVEDESKTOP       157
 #define IDR_SENDTOMENU          158
+#define IDR_COPYTOMENU          159

Reply via email to