mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 18:01:07 +00:00
[SHELL32] Commonize CCopyToMenu and CMoveToMenu (#5873)
Reduce code. And correctly do the filename check. CORE-18909
This commit is contained in:
parent
d21def4819
commit
a938d19714
|
@ -1,33 +1,29 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: shell32
|
* PROJECT: ReactOS shell32
|
||||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
* PURPOSE: MoveTo implementation
|
* PURPOSE: CopyTo and MoveTo implementation
|
||||||
* COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
* COPYRIGHT: Copyright 2020-2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
CMoveToMenu::CMoveToMenu() :
|
CCopyMoveToMenu::CCopyMoveToMenu() :
|
||||||
m_idCmdFirst(0),
|
m_idCmdFirst(0),
|
||||||
m_idCmdLast(0),
|
m_idCmdLast(0),
|
||||||
m_idCmdMoveTo(-1),
|
m_idCmdAction(-1),
|
||||||
m_fnOldWndProc(NULL),
|
m_fnOldWndProc(NULL),
|
||||||
m_bIgnoreTextBoxChange(FALSE)
|
m_bIgnoreTextBoxChange(FALSE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CMoveToMenu::~CMoveToMenu()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static LRESULT CALLBACK
|
static LRESULT CALLBACK
|
||||||
WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
WCHAR szPath[MAX_PATH];
|
WCHAR szPath[MAX_PATH];
|
||||||
CMoveToMenu *this_ =
|
CCopyMoveToMenu *this_ =
|
||||||
reinterpret_cast<CMoveToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
reinterpret_cast<CCopyMoveToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||||
|
|
||||||
switch (uMsg)
|
switch (uMsg)
|
||||||
{
|
{
|
||||||
|
@ -64,30 +60,30 @@ WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
return CallWindowProcW(this_->m_fnOldWndProc, hwnd, uMsg, wParam, 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)
|
BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
||||||
{
|
{
|
||||||
CMoveToMenu *this_ =
|
CCopyMoveToMenu *this_ =
|
||||||
reinterpret_cast<CMoveToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
reinterpret_cast<CCopyMoveToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||||
|
|
||||||
switch (uMsg)
|
switch (uMsg)
|
||||||
{
|
{
|
||||||
case BFFM_INITIALIZED:
|
case BFFM_INITIALIZED:
|
||||||
{
|
{
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, lpData);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, lpData);
|
||||||
this_ = reinterpret_cast<CMoveToMenu *>(lpData);
|
this_ = reinterpret_cast<CCopyMoveToMenu *>(lpData);
|
||||||
|
|
||||||
// Select initial directory
|
// Select initial directory
|
||||||
SendMessageW(hwnd, BFFM_SETSELECTION, FALSE,
|
SendMessageW(hwnd, BFFM_SETSELECTION, FALSE,
|
||||||
reinterpret_cast<LPARAM>(static_cast<LPCITEMIDLIST>(this_->m_pidlFolder)));
|
reinterpret_cast<LPARAM>(static_cast<LPCITEMIDLIST>(this_->m_pidlFolder)));
|
||||||
|
|
||||||
// Set caption
|
// Set caption
|
||||||
CString strCaption(MAKEINTRESOURCEW(IDS_MOVEITEMS));
|
CString strCaption(MAKEINTRESOURCEW(this_->GetCaptionStringID()));
|
||||||
SetWindowTextW(hwnd, strCaption);
|
SetWindowTextW(hwnd, strCaption);
|
||||||
|
|
||||||
// Set OK button text
|
// Set OK button text
|
||||||
CString strMove(MAKEINTRESOURCEW(IDS_MOVEBUTTON));
|
CString strCopyOrMove(MAKEINTRESOURCEW(this_->GetButtonStringID()));
|
||||||
SetDlgItemText(hwnd, IDOK, strMove);
|
SetDlgItemText(hwnd, IDOK, strCopyOrMove);
|
||||||
|
|
||||||
// Subclassing
|
// Subclassing
|
||||||
this_->m_fnOldWndProc =
|
this_->m_fnOldWndProc =
|
||||||
|
@ -125,7 +121,8 @@ BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CMoveToMenu::DoRealMove(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl)
|
HRESULT
|
||||||
|
CCopyMoveToMenu::DoRealFileOp(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl)
|
||||||
{
|
{
|
||||||
CDataObjectHIDA pCIDA(m_pDataObject);
|
CDataObjectHIDA pCIDA(m_pDataObject);
|
||||||
if (FAILED_UNEXPECTEDLY(pCIDA.hr()))
|
if (FAILED_UNEXPECTEDLY(pCIDA.hr()))
|
||||||
|
@ -175,10 +172,7 @@ HRESULT CMoveToMenu::DoRealMove(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHFILEOPSTRUCTW op = { lpici->hwnd };
|
SHFILEOPSTRUCTW op = { lpici->hwnd, GetFileOp(), strFiles, szPath };
|
||||||
op.wFunc = FO_MOVE;
|
|
||||||
op.pFrom = strFiles;
|
|
||||||
op.pTo = szPath;
|
|
||||||
op.fFlags = FOF_ALLOWUNDO;
|
op.fFlags = FOF_ALLOWUNDO;
|
||||||
int res = SHFileOperationW(&op);
|
int res = SHFileOperationW(&op);
|
||||||
if (res)
|
if (res)
|
||||||
|
@ -189,19 +183,18 @@ HRESULT CMoveToMenu::DoRealMove(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CStringW CMoveToMenu::DoGetFileTitle()
|
static HRESULT
|
||||||
|
DoGetFileTitle(CStringW& strTitle, IDataObject *pDataObject)
|
||||||
{
|
{
|
||||||
CStringW ret = L"(file)";
|
CDataObjectHIDA pCIDA(pDataObject);
|
||||||
|
|
||||||
CDataObjectHIDA pCIDA(m_pDataObject);
|
|
||||||
if (FAILED_UNEXPECTEDLY(pCIDA.hr()))
|
if (FAILED_UNEXPECTEDLY(pCIDA.hr()))
|
||||||
return ret;
|
return E_FAIL;
|
||||||
|
|
||||||
PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA);
|
PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA);
|
||||||
if (!pidlParent)
|
if (!pidlParent)
|
||||||
{
|
{
|
||||||
ERR("HIDA_GetPIDLFolder failed\n");
|
ERR("HIDA_GetPIDLFolder failed\n");
|
||||||
return ret;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
WCHAR szPath[MAX_PATH];
|
WCHAR szPath[MAX_PATH];
|
||||||
|
@ -209,28 +202,33 @@ CStringW CMoveToMenu::DoGetFileTitle()
|
||||||
if (!pidlRelative)
|
if (!pidlRelative)
|
||||||
{
|
{
|
||||||
ERR("HIDA_GetPIDLItem failed\n");
|
ERR("HIDA_GetPIDLItem failed\n");
|
||||||
return ret;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CComHeapPtr<ITEMIDLIST> pidlCombine(ILCombine(pidlParent, pidlRelative));
|
CComHeapPtr<ITEMIDLIST> pidlCombine(ILCombine(pidlParent, pidlRelative));
|
||||||
|
|
||||||
if (SHGetPathFromIDListW(pidlCombine, szPath))
|
if (!SHGetPathFromIDListW(pidlCombine, szPath))
|
||||||
ret = PathFindFileNameW(szPath);
|
{
|
||||||
else
|
|
||||||
ERR("Cannot get path\n");
|
ERR("Cannot get path\n");
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strTitle = PathFindFileNameW(szPath);
|
||||||
|
if (strTitle.IsEmpty())
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
if (pCIDA->cidl > 1)
|
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];
|
WCHAR wszPath[MAX_PATH];
|
||||||
HRESULT hr = E_FAIL;
|
HRESULT hr = E_FAIL;
|
||||||
|
|
||||||
TRACE("DoMoveToFolder(%p)\n", lpici);
|
TRACE("(%p)\n", lpici);
|
||||||
|
|
||||||
if (!SHGetPathFromIDListW(m_pidlFolder, wszPath))
|
if (!SHGetPathFromIDListW(m_pidlFolder, wszPath))
|
||||||
{
|
{
|
||||||
|
@ -238,9 +236,13 @@ HRESULT CMoveToMenu::DoMoveToFolder(LPCMINVOKECOMMANDINFO lpici)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CStringW strFileTitle = DoGetFileTitle();
|
CStringW strFileTitle;
|
||||||
|
hr = DoGetFileTitle(strFileTitle, m_pDataObject);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
CStringW strTitle;
|
CStringW strTitle;
|
||||||
strTitle.Format(IDS_MOVETOTITLE, static_cast<LPCWSTR>(strFileTitle));
|
strTitle.Format(GetActionTitleStringID(), static_cast<LPCWSTR>(strFileTitle));
|
||||||
|
|
||||||
BROWSEINFOW info = { lpici->hwnd };
|
BROWSEINFOW info = { lpici->hwnd };
|
||||||
info.pidlRoot = NULL;
|
info.pidlRoot = NULL;
|
||||||
|
@ -250,14 +252,67 @@ HRESULT CMoveToMenu::DoMoveToFolder(LPCMINVOKECOMMANDINFO lpici)
|
||||||
info.lParam = reinterpret_cast<LPARAM>(this);
|
info.lParam = reinterpret_cast<LPARAM>(this);
|
||||||
CComHeapPtr<ITEMIDLIST> pidl(SHBrowseForFolder(&info));
|
CComHeapPtr<ITEMIDLIST> pidl(SHBrowseForFolder(&info));
|
||||||
if (pidl)
|
if (pidl)
|
||||||
{
|
hr = DoRealFileOp(lpici, pidl);
|
||||||
hr = DoRealMove(lpici, pidl);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
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,
|
CMoveToMenu::QueryContextMenu(HMENU hMenu,
|
||||||
UINT indexMenu,
|
UINT indexMenu,
|
||||||
UINT idCmdFirst,
|
UINT idCmdFirst,
|
||||||
|
@ -309,7 +364,7 @@ CMoveToMenu::QueryContextMenu(HMENU hMenu,
|
||||||
mii.wID = m_idCmdLast;
|
mii.wID = m_idCmdLast;
|
||||||
if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
|
if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
|
||||||
{
|
{
|
||||||
m_idCmdMoveTo = m_idCmdLast++;
|
m_idCmdAction = m_idCmdLast++;
|
||||||
++indexMenu;
|
++indexMenu;
|
||||||
++Count;
|
++Count;
|
||||||
}
|
}
|
||||||
|
@ -317,36 +372,33 @@ CMoveToMenu::QueryContextMenu(HMENU hMenu,
|
||||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst + Count);
|
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst + Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI
|
STDMETHODIMP
|
||||||
CMoveToMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
|
CCopyMoveToMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
|
||||||
{
|
{
|
||||||
HRESULT hr = E_FAIL;
|
HRESULT hr = E_FAIL;
|
||||||
TRACE("CMoveToMenu::InvokeCommand(%p)\n", lpici);
|
TRACE("CCopyMoveToMenu::InvokeCommand(%p)\n", lpici);
|
||||||
|
|
||||||
if (IS_INTRESOURCE(lpici->lpVerb))
|
if (IS_INTRESOURCE(lpici->lpVerb))
|
||||||
{
|
{
|
||||||
if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdMoveTo)
|
if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdAction)
|
||||||
{
|
hr = DoAction(lpici);
|
||||||
hr = DoMoveToFolder(lpici);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (::lstrcmpiA(lpici->lpVerb, "moveto") == 0)
|
if (::lstrcmpiA(lpici->lpVerb, GetVerb()) == 0)
|
||||||
{
|
hr = DoAction(lpici);
|
||||||
hr = DoMoveToFolder(lpici);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI
|
STDMETHODIMP
|
||||||
CMoveToMenu::GetCommandString(UINT_PTR idCmd,
|
CCopyMoveToMenu::GetCommandString(
|
||||||
UINT uType,
|
UINT_PTR idCmd,
|
||||||
UINT *pwReserved,
|
UINT uType,
|
||||||
LPSTR pszName,
|
UINT *pwReserved,
|
||||||
UINT cchMax)
|
LPSTR pszName,
|
||||||
|
UINT cchMax)
|
||||||
{
|
{
|
||||||
FIXME("%p %lu %u %p %p %u\n", this,
|
FIXME("%p %lu %u %p %p %u\n", this,
|
||||||
idCmd, uType, pwReserved, pszName, cchMax);
|
idCmd, uType, pwReserved, pszName, cchMax);
|
||||||
|
@ -354,29 +406,30 @@ CMoveToMenu::GetCommandString(UINT_PTR idCmd,
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI
|
STDMETHODIMP
|
||||||
CMoveToMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
CCopyMoveToMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
TRACE("This %p uMsg %x\n", this, uMsg);
|
TRACE("This %p uMsg %x\n", this, uMsg);
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI
|
STDMETHODIMP
|
||||||
CMoveToMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder,
|
CCopyMoveToMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
|
||||||
IDataObject *pdtobj, HKEY hkeyProgID)
|
|
||||||
{
|
{
|
||||||
m_pidlFolder.Attach(ILClone(pidlFolder));
|
m_pidlFolder.Attach(ILClone(pidlFolder));
|
||||||
m_pDataObject = pdtobj;
|
m_pDataObject = pdtobj;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI CMoveToMenu::SetSite(IUnknown *pUnkSite)
|
STDMETHODIMP
|
||||||
|
CCopyMoveToMenu::SetSite(IUnknown *pUnkSite)
|
||||||
{
|
{
|
||||||
m_pSite = pUnkSite;
|
m_pSite = pUnkSite;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI CMoveToMenu::GetSite(REFIID riid, void **ppvSite)
|
STDMETHODIMP
|
||||||
|
CCopyMoveToMenu::GetSite(REFIID riid, void **ppvSite)
|
||||||
{
|
{
|
||||||
if (!m_pSite)
|
if (!m_pSite)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
111
dll/win32/shell32/CCopyMoveToMenu.h
Normal file
111
dll/win32/shell32/CCopyMoveToMenu.h
Normal file
|
@ -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<CComMultiThreadModelNoCS>,
|
||||||
|
public IContextMenu2,
|
||||||
|
public IObjectWithSite,
|
||||||
|
public IShellExtInit
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
UINT m_idCmdFirst, m_idCmdLast, m_idCmdAction;
|
||||||
|
CComPtr<IDataObject> m_pDataObject;
|
||||||
|
CComPtr<IUnknown> m_pSite;
|
||||||
|
|
||||||
|
HRESULT DoRealFileOp(LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidl);
|
||||||
|
HRESULT DoAction(LPCMINVOKECOMMANDINFO lpici);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CComHeapPtr<ITEMIDLIST> 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<CCopyToMenu, &CLSID_CopyToMenu>
|
||||||
|
, public CCopyMoveToMenu
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CComHeapPtr<ITEMIDLIST> 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<CMoveToMenu, &CLSID_MoveToMenu>
|
||||||
|
, 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"; }
|
||||||
|
};
|
|
@ -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<CCopyToMenu *>(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<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, BFFM_ENABLEOK, 0, FALSE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BFFM_SELCHANGED:
|
|
||||||
{
|
|
||||||
if (!this_)
|
|
||||||
break;
|
|
||||||
|
|
||||||
WCHAR szPath[MAX_PATH];
|
|
||||||
LPCITEMIDLIST pidl = reinterpret_cast<LPCITEMIDLIST>(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<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;
|
|
||||||
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<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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
|
@ -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<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;
|
|
||||||
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<CMoveToMenu, &CLSID_MoveToMenu>,
|
|
||||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
|
||||||
public IContextMenu2,
|
|
||||||
public IObjectWithSite,
|
|
||||||
public IShellExtInit
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
UINT m_idCmdFirst, m_idCmdLast, m_idCmdMoveTo;
|
|
||||||
CComPtr<IDataObject> m_pDataObject;
|
|
||||||
CComPtr<IUnknown> m_pSite;
|
|
||||||
|
|
||||||
HRESULT DoMoveToFolder(LPCMINVOKECOMMANDINFO lpici);
|
|
||||||
HRESULT DoRealMove(LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidl);
|
|
||||||
CStringW DoGetFileTitle();
|
|
||||||
|
|
||||||
public:
|
|
||||||
CComHeapPtr<ITEMIDLIST> 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()
|
|
||||||
};
|
|
|
@ -73,8 +73,7 @@ list(APPEND SOURCE
|
||||||
COpenWithMenu.cpp
|
COpenWithMenu.cpp
|
||||||
CNewMenu.cpp
|
CNewMenu.cpp
|
||||||
CSendToMenu.cpp
|
CSendToMenu.cpp
|
||||||
CCopyToMenu.cpp
|
CCopyMoveToMenu.cpp
|
||||||
CMoveToMenu.cpp
|
|
||||||
CShellDispatch.cpp
|
CShellDispatch.cpp
|
||||||
CFolder.cpp
|
CFolder.cpp
|
||||||
CFolderItems.cpp
|
CFolderItems.cpp
|
||||||
|
|
|
@ -95,7 +95,7 @@
|
||||||
#include "COpenWithMenu.h"
|
#include "COpenWithMenu.h"
|
||||||
#include "CNewMenu.h"
|
#include "CNewMenu.h"
|
||||||
#include "CSendToMenu.h"
|
#include "CSendToMenu.h"
|
||||||
#include "CCopyToMoveToMenu.h"
|
#include "CCopyMoveToMenu.h"
|
||||||
#include "dialogs/filedefext.h"
|
#include "dialogs/filedefext.h"
|
||||||
#include "dialogs/drvdefext.h"
|
#include "dialogs/drvdefext.h"
|
||||||
#include "CQueryAssociations.h"
|
#include "CQueryAssociations.h"
|
||||||
|
|
Loading…
Reference in a new issue