mirror of
https://github.com/reactos/reactos.git
synced 2025-08-11 14:15:35 +00:00
[SHELL32][BROWSEUI] CopyMoveToMenu must initialize without a PIDL folder (#7047)
- IShellExtInit cannot rely on a folder PIDL being present - Use common QueryContextMenu function for both menu items - Allow copy to the same folder - Disable toolbar buttons when the selection is not valid - Minor DefView cache enhancement and bugfixes
This commit is contained in:
parent
df5affedce
commit
d24675b63d
6 changed files with 128 additions and 145 deletions
|
@ -1362,6 +1362,13 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::GetBitmapSize(long *paramC)
|
||||||
HRESULT STDMETHODCALLTYPE CInternetToolbar::SendToolbarMsg(const GUID *pguidCmdGroup, UINT uMsg,
|
HRESULT STDMETHODCALLTYPE CInternetToolbar::SendToolbarMsg(const GUID *pguidCmdGroup, UINT uMsg,
|
||||||
WPARAM wParam, LPARAM lParam, LRESULT *result)
|
WPARAM wParam, LPARAM lParam, LRESULT *result)
|
||||||
{
|
{
|
||||||
|
if (fToolbarWindow)
|
||||||
|
{
|
||||||
|
LRESULT res = ::SendMessageW(fToolbarWindow, uMsg, wParam, lParam);
|
||||||
|
if (result)
|
||||||
|
*result = res;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,9 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
|
enum { IDC_ACTION = 0 };
|
||||||
|
|
||||||
CCopyMoveToMenu::CCopyMoveToMenu() :
|
CCopyMoveToMenu::CCopyMoveToMenu() :
|
||||||
m_idCmdFirst(0),
|
|
||||||
m_idCmdLast(0),
|
|
||||||
m_idCmdAction(-1),
|
|
||||||
m_fnOldWndProc(NULL),
|
m_fnOldWndProc(NULL),
|
||||||
m_bIgnoreTextBoxChange(FALSE)
|
m_bIgnoreTextBoxChange(FALSE)
|
||||||
{
|
{
|
||||||
|
@ -106,7 +105,7 @@ BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
||||||
SHGetPathFromIDListW(pidl, szPath);
|
SHGetPathFromIDListW(pidl, szPath);
|
||||||
|
|
||||||
if (ILIsEqual(pidl, this_->m_pidlFolder))
|
if (ILIsEqual(pidl, this_->m_pidlFolder))
|
||||||
PostMessageW(hwnd, BFFM_ENABLEOK, 0, FALSE);
|
PostMessageW(hwnd, BFFM_ENABLEOK, 0, this_->GetFileOp() == FO_COPY);
|
||||||
else if (PathFileExistsW(szPath) || _ILIsDesktop(pidl))
|
else if (PathFileExistsW(szPath) || _ILIsDesktop(pidl))
|
||||||
PostMessageW(hwnd, BFFM_ENABLEOK, 0, TRUE);
|
PostMessageW(hwnd, BFFM_ENABLEOK, 0, TRUE);
|
||||||
else
|
else
|
||||||
|
@ -122,32 +121,18 @@ BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
CCopyMoveToMenu::DoRealFileOp(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl)
|
CCopyMoveToMenu::DoRealFileOp(const CIDA *pCIDA, LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidlDestination)
|
||||||
{
|
{
|
||||||
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;
|
CStringW strFiles;
|
||||||
WCHAR szPath[MAX_PATH];
|
WCHAR szPath[MAX_PATH];
|
||||||
for (UINT n = 0; n < pCIDA->cidl; ++n)
|
for (UINT n = 0; n < pCIDA->cidl; ++n)
|
||||||
{
|
{
|
||||||
PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(pCIDA, n);
|
CComHeapPtr<ITEMIDLIST> pidlCombine(SHELL_CIDA_ILCloneFull(pCIDA, n));
|
||||||
if (!pidlRelative)
|
if (!pidlCombine)
|
||||||
continue;
|
|
||||||
|
|
||||||
CComHeapPtr<ITEMIDLIST> pidlCombine(ILCombine(pidlParent, pidlRelative));
|
|
||||||
if (!pidl)
|
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
SHGetPathFromIDListW(pidlCombine, szPath);
|
if (!SHGetPathFromIDListW(pidlCombine, szPath))
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
strFiles += L'|';
|
strFiles += L'|';
|
||||||
|
@ -157,10 +142,10 @@ CCopyMoveToMenu::DoRealFileOp(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl)
|
||||||
strFiles += L'|'; // double null-terminated
|
strFiles += L'|'; // double null-terminated
|
||||||
strFiles.Replace(L'|', L'\0');
|
strFiles.Replace(L'|', L'\0');
|
||||||
|
|
||||||
if (_ILIsDesktop(pidl))
|
if (_ILIsDesktop(pidlDestination))
|
||||||
SHGetSpecialFolderPathW(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE);
|
SHGetSpecialFolderPathW(lpici->hwnd, szPath, CSIDL_DESKTOPDIRECTORY, TRUE);
|
||||||
else
|
else
|
||||||
SHGetPathFromIDListW(pidl, szPath);
|
SHGetPathFromIDListW(pidlDestination, szPath);
|
||||||
INT cchPath = lstrlenW(szPath);
|
INT cchPath = lstrlenW(szPath);
|
||||||
if (cchPath + 1 < MAX_PATH)
|
if (cchPath + 1 < MAX_PATH)
|
||||||
{
|
{
|
||||||
|
@ -184,60 +169,44 @@ CCopyMoveToMenu::DoRealFileOp(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl)
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT
|
static HRESULT
|
||||||
DoGetFileTitle(CStringW& strTitle, IDataObject *pDataObject)
|
DoGetFileTitle(const CIDA *pCIDA, CStringW& strTitle)
|
||||||
{
|
{
|
||||||
CDataObjectHIDA pCIDA(pDataObject);
|
CComHeapPtr<ITEMIDLIST> pidlCombine(SHELL_CIDA_ILCloneFull(pCIDA, 0));
|
||||||
if (FAILED_UNEXPECTEDLY(pCIDA.hr()))
|
if (!pidlCombine)
|
||||||
return E_FAIL;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA);
|
|
||||||
if (!pidlParent)
|
|
||||||
{
|
|
||||||
ERR("HIDA_GetPIDLFolder failed\n");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
WCHAR szPath[MAX_PATH];
|
WCHAR szPath[MAX_PATH];
|
||||||
PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(pCIDA, 0);
|
HRESULT hr = SHGetNameAndFlagsW(pidlCombine, SHGDN_INFOLDER, szPath, _countof(szPath), NULL);
|
||||||
if (!pidlRelative)
|
strTitle = SUCCEEDED(hr) ? szPath : L"";
|
||||||
{
|
|
||||||
ERR("HIDA_GetPIDLItem failed\n");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CComHeapPtr<ITEMIDLIST> pidlCombine(ILCombine(pidlParent, pidlRelative));
|
|
||||||
|
|
||||||
if (!SHGetPathFromIDListW(pidlCombine, szPath))
|
|
||||||
{
|
|
||||||
ERR("Cannot get path\n");
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
strTitle = PathFindFileNameW(szPath);
|
|
||||||
if (strTitle.IsEmpty())
|
if (strTitle.IsEmpty())
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if (pCIDA->cidl > 1)
|
if (pCIDA->cidl > 1)
|
||||||
strTitle += L" ...";
|
strTitle += L" ...";
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CCopyMoveToMenu::DoAction(LPCMINVOKECOMMANDINFO lpici)
|
HRESULT CCopyMoveToMenu::DoAction(LPCMINVOKECOMMANDINFO lpici)
|
||||||
{
|
{
|
||||||
WCHAR wszPath[MAX_PATH];
|
WCHAR wszPath[MAX_PATH];
|
||||||
HRESULT hr = E_FAIL;
|
|
||||||
|
|
||||||
TRACE("(%p)\n", lpici);
|
TRACE("(%p)\n", lpici);
|
||||||
|
|
||||||
|
CDataObjectHIDA pCIDA(m_pDataObject);
|
||||||
|
HRESULT hr = pCIDA.hr();
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
{
|
||||||
|
ERR("Failed to get CIDA, %#x\n", hr);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SHGetPathFromIDListW(m_pidlFolder, wszPath))
|
if (!SHGetPathFromIDListW(m_pidlFolder, wszPath))
|
||||||
{
|
{
|
||||||
ERR("SHGetPathFromIDListW failed\n");
|
ERR("SHGetPathFromIDListW failed\n");
|
||||||
return hr;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CStringW strFileTitle;
|
CStringW strFileTitle;
|
||||||
hr = DoGetFileTitle(strFileTitle, m_pDataObject);
|
hr = DoGetFileTitle(pCIDA, strFileTitle);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
@ -252,7 +221,7 @@ HRESULT CCopyMoveToMenu::DoAction(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 = DoRealFileOp(pCIDA, lpici, pidl);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
@ -279,52 +248,9 @@ CCopyToMenu::QueryContextMenu(HMENU hMenu,
|
||||||
UINT idCmdLast,
|
UINT idCmdLast,
|
||||||
UINT uFlags)
|
UINT uFlags)
|
||||||
{
|
{
|
||||||
MENUITEMINFOW mii;
|
|
||||||
UINT Count = 0;
|
|
||||||
|
|
||||||
TRACE("CCopyToMenu::QueryContextMenu(%p, %u, %u, %u, %u)\n",
|
TRACE("CCopyToMenu::QueryContextMenu(%p, %u, %u, %u, %u)\n",
|
||||||
hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
|
hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
|
||||||
|
return QueryContextMenuImpl(TRUE, 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 (GetPreviousMenuItemInfo(hMenu, indexMenu, &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
|
STDMETHODIMP
|
||||||
|
@ -334,57 +260,56 @@ CMoveToMenu::QueryContextMenu(HMENU hMenu,
|
||||||
UINT idCmdLast,
|
UINT idCmdLast,
|
||||||
UINT uFlags)
|
UINT uFlags)
|
||||||
{
|
{
|
||||||
MENUITEMINFOW mii;
|
|
||||||
UINT Count = 0;
|
|
||||||
|
|
||||||
TRACE("CMoveToMenu::QueryContextMenu(%p, %u, %u, %u, %u)\n",
|
TRACE("CMoveToMenu::QueryContextMenu(%p, %u, %u, %u, %u)\n",
|
||||||
hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
|
hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
|
||||||
|
return QueryContextMenuImpl(FALSE, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP
|
||||||
|
CCopyMoveToMenu::QueryContextMenuImpl(BOOL IsCopyOp, HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
|
||||||
|
{
|
||||||
if (uFlags & (CMF_NOVERBS | CMF_VERBSONLY))
|
if (uFlags & (CMF_NOVERBS | CMF_VERBSONLY))
|
||||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst);
|
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
|
||||||
|
|
||||||
m_idCmdFirst = m_idCmdLast = idCmdFirst;
|
UINT idHighest = 0;
|
||||||
|
CStringW strCopyTo(MAKEINTRESOURCEW(IDS_COPYTOMENU)), strMoveTo;
|
||||||
|
LPWSTR itemText = strCopyTo.GetBuffer();
|
||||||
|
if (!IsCopyOp)
|
||||||
|
{
|
||||||
|
strMoveTo.LoadString(IDS_MOVETOMENU);
|
||||||
|
itemText = strMoveTo.GetBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
// insert separator if necessary
|
// Insert separator if necessary
|
||||||
CStringW strCopyTo(MAKEINTRESOURCEW(IDS_COPYTOMENU));
|
|
||||||
WCHAR szBuff[128];
|
WCHAR szBuff[128];
|
||||||
ZeroMemory(&mii, sizeof(mii));
|
MENUITEMINFOW mii = { sizeof(mii), MIIM_TYPE };
|
||||||
mii.cbSize = sizeof(mii);
|
|
||||||
mii.fMask = MIIM_TYPE;
|
|
||||||
mii.dwTypeData = szBuff;
|
mii.dwTypeData = szBuff;
|
||||||
mii.cch = _countof(szBuff);
|
mii.cch = _countof(szBuff);
|
||||||
if (GetPreviousMenuItemInfo(hMenu, indexMenu, &mii) &&
|
if (GetPreviousMenuItemInfo(hMenu, indexMenu, &mii) &&
|
||||||
mii.fType != MFT_SEPARATOR &&
|
mii.fType != MFT_SEPARATOR &&
|
||||||
!(mii.fType == MFT_STRING && CStringW(szBuff) == strCopyTo))
|
(IsCopyOp || !(mii.fType == MFT_STRING && !wcscmp(szBuff, strCopyTo.GetBuffer()))))
|
||||||
{
|
{
|
||||||
ZeroMemory(&mii, sizeof(mii));
|
|
||||||
mii.cbSize = sizeof(mii);
|
|
||||||
mii.fMask = MIIM_TYPE;
|
mii.fMask = MIIM_TYPE;
|
||||||
mii.fType = MFT_SEPARATOR;
|
mii.fType = MFT_SEPARATOR;
|
||||||
|
mii.dwTypeData = NULL;
|
||||||
|
mii.cch = 0;
|
||||||
if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
|
if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
|
||||||
{
|
{
|
||||||
++indexMenu;
|
++indexMenu;
|
||||||
++Count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert "Move to folder..."
|
// Insert the menu item
|
||||||
CStringW strText(MAKEINTRESOURCEW(IDS_MOVETOMENU));
|
|
||||||
ZeroMemory(&mii, sizeof(mii));
|
|
||||||
mii.cbSize = sizeof(mii);
|
|
||||||
mii.fMask = MIIM_ID | MIIM_TYPE;
|
mii.fMask = MIIM_ID | MIIM_TYPE;
|
||||||
mii.fType = MFT_STRING;
|
mii.fType = MFT_STRING;
|
||||||
mii.dwTypeData = strText.GetBuffer();
|
mii.dwTypeData = itemText;
|
||||||
mii.cch = wcslen(mii.dwTypeData);
|
mii.wID = idCmdFirst + IDC_ACTION;
|
||||||
mii.wID = m_idCmdLast;
|
|
||||||
if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
|
if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
|
||||||
{
|
{
|
||||||
m_idCmdAction = m_idCmdLast++;
|
idHighest = max(idHighest, mii.wID);
|
||||||
++indexMenu;
|
++indexMenu;
|
||||||
++Count;
|
|
||||||
}
|
}
|
||||||
|
return idHighest >= idCmdFirst ? MAKE_HRESULT(SEVERITY_SUCCESS, 0, idHighest - idCmdFirst + 1) : E_FAIL;
|
||||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst + Count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP
|
STDMETHODIMP
|
||||||
|
@ -395,7 +320,7 @@ CCopyMoveToMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
|
||||||
|
|
||||||
if (IS_INTRESOURCE(lpici->lpVerb))
|
if (IS_INTRESOURCE(lpici->lpVerb))
|
||||||
{
|
{
|
||||||
if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdAction)
|
if (LOWORD(lpici->lpVerb) == IDC_ACTION)
|
||||||
hr = DoAction(lpici);
|
hr = DoAction(lpici);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -415,6 +340,12 @@ CCopyMoveToMenu::GetCommandString(
|
||||||
LPSTR pszName,
|
LPSTR pszName,
|
||||||
UINT cchMax)
|
UINT cchMax)
|
||||||
{
|
{
|
||||||
|
if ((uType | GCS_UNICODE) == GCS_VALIDATEW)
|
||||||
|
return idCmd == IDC_ACTION ? S_OK : S_FALSE;
|
||||||
|
|
||||||
|
if (uType == GCS_VERBW && idCmd == IDC_ACTION)
|
||||||
|
return SHAnsiToUnicode(GetVerb(), (LPWSTR)pszName, 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);
|
||||||
|
|
||||||
|
@ -431,9 +362,25 @@ CCopyMoveToMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
STDMETHODIMP
|
STDMETHODIMP
|
||||||
CCopyMoveToMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
|
CCopyMoveToMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
|
||||||
{
|
{
|
||||||
m_pidlFolder.Attach(ILClone(pidlFolder));
|
|
||||||
m_pDataObject = pdtobj;
|
m_pDataObject = pdtobj;
|
||||||
return S_OK;
|
HRESULT hr = E_FAIL;
|
||||||
|
if (pidlFolder)
|
||||||
|
{
|
||||||
|
hr = SHILClone(pidlFolder, &pidlFolder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pidlFolder = SHELL_DataObject_ILCloneFullItem(pdtobj, 0);
|
||||||
|
if (pidlFolder)
|
||||||
|
{
|
||||||
|
ILRemoveLastID((LPITEMIDLIST)pidlFolder);
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
m_pidlFolder.Attach(const_cast<PIDLIST_ABSOLUTE>(pidlFolder));
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP
|
STDMETHODIMP
|
||||||
|
|
|
@ -13,11 +13,10 @@ class CCopyMoveToMenu :
|
||||||
public IShellExtInit
|
public IShellExtInit
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
UINT m_idCmdFirst, m_idCmdLast, m_idCmdAction;
|
|
||||||
CComPtr<IDataObject> m_pDataObject;
|
CComPtr<IDataObject> m_pDataObject;
|
||||||
CComPtr<IUnknown> m_pSite;
|
CComPtr<IUnknown> m_pSite;
|
||||||
|
|
||||||
HRESULT DoRealFileOp(LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidl);
|
HRESULT DoRealFileOp(const CIDA *pCIDA, LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidlDestination);
|
||||||
HRESULT DoAction(LPCMINVOKECOMMANDINFO lpici);
|
HRESULT DoAction(LPCMINVOKECOMMANDINFO lpici);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -32,6 +31,7 @@ public:
|
||||||
virtual UINT GetActionTitleStringID() const = 0;
|
virtual UINT GetActionTitleStringID() const = 0;
|
||||||
virtual UINT GetFileOp() const = 0;
|
virtual UINT GetFileOp() const = 0;
|
||||||
virtual LPCSTR GetVerb() const = 0;
|
virtual LPCSTR GetVerb() const = 0;
|
||||||
|
STDMETHODIMP QueryContextMenuImpl(BOOL IsCopyOp, HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
|
||||||
|
|
||||||
// IContextMenu
|
// IContextMenu
|
||||||
STDMETHODIMP GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen) override;
|
STDMETHODIMP GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen) override;
|
||||||
|
|
|
@ -723,6 +723,17 @@ void CDefView::UpdateStatusbar()
|
||||||
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETICON, 2, pIcon, &lResult);
|
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETICON, 2, pIcon, &lResult);
|
||||||
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 2, (LPARAM)szPartText, &lResult);
|
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 2, (LPARAM)szPartText, &lResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SFGAOF att = 0;
|
||||||
|
if (cSelectedItems > 0)
|
||||||
|
{
|
||||||
|
UINT maxquery = 42; // Checking the attributes can be slow, only check small selections (_DoCopyToMoveToFolder will verify the full array)
|
||||||
|
att = SFGAO_CANCOPY | SFGAO_CANMOVE;
|
||||||
|
if (cSelectedItems <= maxquery && (!GetSelections() || FAILED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &att))))
|
||||||
|
att = 0;
|
||||||
|
}
|
||||||
|
m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, FCIDM_SHVIEW_COPYTO, (att & SFGAO_CANCOPY) != 0, &lResult);
|
||||||
|
m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, FCIDM_SHVIEW_MOVETO, (att & SFGAO_CANMOVE) != 0, &lResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CDefView::OnUpdateStatusbar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
LRESULT CDefView::OnUpdateStatusbar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
||||||
|
@ -1947,15 +1958,18 @@ LRESULT CDefView::DoColumnContextMenu(LPARAM lParam)
|
||||||
*/
|
*/
|
||||||
UINT CDefView::GetSelections()
|
UINT CDefView::GetSelections()
|
||||||
{
|
{
|
||||||
SHFree(m_apidl);
|
UINT count = m_ListView.GetSelectedCount();
|
||||||
|
if (count > m_cidl || !count || !m_apidl) // !count to free possibly large cache, !m_apidl to make sure m_apidl is a valid pointer
|
||||||
m_cidl = m_ListView.GetSelectedCount();
|
|
||||||
m_apidl = static_cast<PCUITEMID_CHILD*>(SHAlloc(m_cidl * sizeof(PCUITEMID_CHILD)));
|
|
||||||
if (!m_apidl)
|
|
||||||
{
|
{
|
||||||
m_cidl = 0;
|
SHFree(m_apidl);
|
||||||
return 0;
|
m_apidl = static_cast<PCUITEMID_CHILD*>(SHAlloc(count * sizeof(PCUITEMID_CHILD)));
|
||||||
|
if (!m_apidl)
|
||||||
|
{
|
||||||
|
m_cidl = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
m_cidl = count;
|
||||||
|
|
||||||
TRACE("-- Items selected =%u\n", m_cidl);
|
TRACE("-- Items selected =%u\n", m_cidl);
|
||||||
|
|
||||||
|
@ -2025,8 +2039,7 @@ HRESULT CDefView::OpenSelectedItems()
|
||||||
UINT uCommand;
|
UINT uCommand;
|
||||||
HRESULT hResult;
|
HRESULT hResult;
|
||||||
|
|
||||||
m_cidl = m_ListView.GetSelectedCount();
|
if (m_ListView.GetSelectedCount() == 0)
|
||||||
if (m_cidl == 0)
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
hResult = OnDefaultCommand();
|
hResult = OnDefaultCommand();
|
||||||
|
@ -2100,9 +2113,9 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cidl = m_ListView.GetSelectedCount();
|
UINT count = m_ListView.GetSelectedCount();
|
||||||
// In case we still have this left over, clean it up
|
// In case we still have this left over, clean it up
|
||||||
hResult = GetItemObject(m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
|
hResult = GetItemObject(count ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
|
||||||
MenuCleanup _(m_pCM, m_hContextMenu);
|
MenuCleanup _(m_pCM, m_hContextMenu);
|
||||||
if (FAILED_UNEXPECTEDLY(hResult))
|
if (FAILED_UNEXPECTEDLY(hResult))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3382,7 +3395,7 @@ HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_
|
||||||
m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
|
m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
|
||||||
|
|
||||||
int lvIndex;
|
int lvIndex;
|
||||||
for (UINT i = 0 ; i < m_cidl; i++)
|
for (UINT i = 0 ; i < cidl; i++)
|
||||||
{
|
{
|
||||||
lvIndex = LV_FindItemByPidl(apidl[i]);
|
lvIndex = LV_FindItemByPidl(apidl[i]);
|
||||||
if (lvIndex != -1)
|
if (lvIndex != -1)
|
||||||
|
|
|
@ -229,6 +229,9 @@ BOOL PathIsValidElement(_In_ LPCWSTR pszPath);
|
||||||
BOOL PathIsDosDevice(_In_ LPCWSTR pszName);
|
BOOL PathIsDosDevice(_In_ LPCWSTR pszName);
|
||||||
HRESULT SHILAppend(_Inout_ LPITEMIDLIST pidl, _Inout_ LPITEMIDLIST *ppidl);
|
HRESULT SHILAppend(_Inout_ LPITEMIDLIST pidl, _Inout_ LPITEMIDLIST *ppidl);
|
||||||
|
|
||||||
|
PIDLIST_ABSOLUTE SHELL_CIDA_ILCloneFull(_In_ const CIDA *pCIDA, _In_ UINT Index);
|
||||||
|
PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ UINT Index);
|
||||||
|
|
||||||
EXTERN_C HRESULT
|
EXTERN_C HRESULT
|
||||||
IUnknown_InitializeCommand(
|
IUnknown_InitializeCommand(
|
||||||
_In_ IUnknown *pUnk,
|
_In_ IUnknown *pUnk,
|
||||||
|
|
|
@ -101,3 +101,16 @@ HRESULT WINAPI SHGetAttributesFromDataObject(IDataObject* pDataObject, DWORD dwA
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PIDLIST_ABSOLUTE SHELL_CIDA_ILCloneFull(_In_ const CIDA *pCIDA, _In_ UINT Index)
|
||||||
|
{
|
||||||
|
if (Index < pCIDA->cidl)
|
||||||
|
return ILCombine(HIDA_GetPIDLFolder(pCIDA), HIDA_GetPIDLItem(pCIDA, Index));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ UINT Index)
|
||||||
|
{
|
||||||
|
CDataObjectHIDA cida(pDO);
|
||||||
|
return SUCCEEDED(cida.hr()) ? SHELL_CIDA_ILCloneFull(cida, Index) : NULL;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue