[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:
Whindmar Saksit 2024-06-25 00:29:35 +02:00 committed by GitHub
parent df5affedce
commit d24675b63d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 128 additions and 145 deletions

View file

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

View file

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

View file

@ -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;

View file

@ -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)

View file

@ -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,

View file

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