From f844296b0a7f481fb2f4cc9e85180ce3659c60a2 Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Sat, 8 Mar 2025 14:30:04 +0100 Subject: [PATCH] [BROWSEUI][SHELL32] Fix FindFolder icons (#7756) - Shortcut icons require the correct IShellFolder because it needs the full path. - Items in a drive root needs the final backslash to be part of the path. CORE-18692 --- dll/win32/browseui/shellfind/CFindFolder.cpp | 256 ++++++++++++++----- dll/win32/browseui/shellfind/CFindFolder.h | 7 +- dll/win32/shell32/CDefView.cpp | 16 +- dll/win32/shell32/CShellLink.cpp | 4 +- 4 files changed, 216 insertions(+), 67 deletions(-) diff --git a/dll/win32/browseui/shellfind/CFindFolder.cpp b/dll/win32/browseui/shellfind/CFindFolder.cpp index 4a08b8a0852..2937663b087 100644 --- a/dll/win32/browseui/shellfind/CFindFolder.cpp +++ b/dll/win32/browseui/shellfind/CFindFolder.cpp @@ -84,7 +84,7 @@ struct FolderViewColumns int cxChar; }; -static FolderViewColumns g_ColumnDefs[] = +static const FolderViewColumns g_ColumnDefs[] = { {IDS_COL_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30}, {IDS_COL_LOCATION, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30}, @@ -92,6 +92,7 @@ static FolderViewColumns g_ColumnDefs[] = }; CFindFolder::CFindFolder() : + m_pidl(NULL), m_hStopEvent(NULL) { } @@ -106,26 +107,32 @@ static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath) } LPITEMIDLIST lpLastFSPidl = ILFindLastID(lpFSPidl); - int pathLen = (PathFindFileNameW(lpszPath) - lpszPath) * sizeof(WCHAR); - int cbData = sizeof(WORD) + pathLen + lpLastFSPidl->mkid.cb; + SIZE_T cbPath = (PathFindFileNameW(lpszPath) - lpszPath + 1) * sizeof(WCHAR); + SIZE_T cbData = sizeof(WORD) + cbPath + lpLastFSPidl->mkid.cb; + if (cbData > 0xffff) + return NULL; LPITEMIDLIST pidl = (LPITEMIDLIST) SHAlloc(cbData + sizeof(WORD)); if (!pidl) return NULL; LPBYTE p = (LPBYTE) pidl; - *((WORD *) p) = cbData; - p += sizeof(WORD); + p += sizeof(WORD); // mkid.cb - memcpy(p, lpszPath, pathLen); - p += pathLen - sizeof(WCHAR); - *((WCHAR *) p) = '\0'; - p += sizeof(WCHAR); + PWSTR path = (PWSTR)p; + memcpy(p, lpszPath, cbPath); + p += cbPath; + ((PWSTR)p)[-1] = UNICODE_NULL; // "C:\" not "C:" (required by ILCreateFromPathW and matches Windows) + if (!PathIsRootW(path)) + { + p -= sizeof(WCHAR); + ((PWSTR)p)[-1] = UNICODE_NULL; // "C:\folder" + } memcpy(p, lpLastFSPidl, lpLastFSPidl->mkid.cb); p += lpLastFSPidl->mkid.cb; - *((WORD *) p) = 0; - + pidl->mkid.cb = p - (LPBYTE)pidl; + ((LPITEMIDLIST)p)->mkid.cb = 0; // Terminator return pidl; } @@ -144,6 +151,74 @@ static LPCITEMIDLIST _ILGetFSPidl(LPCITEMIDLIST pidl) + ((wcslen((LPCWSTR) pidl->mkid.abID) + 1) * sizeof(WCHAR))); } +static PIDLIST_ABSOLUTE _ILCreateAbsolute(LPCITEMIDLIST pidlChild) +{ + PIDLIST_ABSOLUTE pidl = NULL; + if (PIDLIST_ABSOLUTE pidlFolder = SHSimpleIDListFromPath(_ILGetPath(pidl))) // FIXME: SHELL32_CreateSimpleIDListFromPath(, DIRECTORY) + { + pidl = ILCombine(pidlFolder, _ILGetFSPidl(pidl)); + ILFree(pidlFolder); + } + return pidl; +} + +HRESULT CFindFolder::GetFSFolderAndChild(LPCITEMIDLIST pidl, IShellFolder **ppSF, PCUITEMID_CHILD *ppidlLast) +{ + ATLASSERT(m_pSfDesktop); + PCWSTR path = _ILGetPath(pidl); + if (!path || !path[0]) + return E_INVALIDARG; + PIDLIST_ABSOLUTE pidlFolder = ILCreateFromPathW(path); // FIXME: SHELL32_CreateSimpleIDListFromPath(, DIRECTORY); + if (!pidlFolder) + return E_FAIL; + HRESULT hr = m_pSfDesktop->BindToObject(pidlFolder, NULL, IID_PPV_ARG(IShellFolder, ppSF)); + ILFree(pidlFolder); + if (ppidlLast) + *ppidlLast = _ILGetFSPidl(pidl); + return hr; +} + +HRESULT CFindFolder::GetFSFolder2AndChild(LPCITEMIDLIST pidl, IShellFolder2 **ppSF, PCUITEMID_CHILD *ppidlLast) +{ + CComPtr pSF1; + HRESULT hr = GetFSFolderAndChild(pidl, &pSF1, ppidlLast); + if (SUCCEEDED(hr)) + hr = pSF1->QueryInterface(IID_PPV_ARG(IShellFolder2, ppSF)); + return hr; +} + +static int CALLBACK ILFreeHelper(void *pItem, void *pCaller) +{ + ILFree((LPITEMIDLIST)pItem); + return TRUE; +} + +void CFindFolder::FreePidlArray(HDPA hDpa) +{ + DPA_DestroyCallback(hDpa, ILFreeHelper, NULL); +} + +HDPA CFindFolder::CreateAbsolutePidlArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl) +{ + HDPA hDpa = DPA_Create(cidl / 2); + if (hDpa) + { + for (UINT i = 0; i < cidl; ++i) + { + PIDLIST_ABSOLUTE pidl = _ILCreateAbsolute(apidl[i]); + if (pidl) + { + if (DPA_InsertPtr(hDpa, i, pidl) >= 0) + continue; + ILFree(pidl); + } + FreePidlArray(hDpa); + return NULL; + } + } + return hDpa; +} + struct _SearchData { HWND hwnd; @@ -666,9 +741,9 @@ STDMETHODIMP CFindFolder::EnumSearches(IEnumExtraSearch **ppenum) STDMETHODIMP CFindFolder::GetDefaultColumn(DWORD, ULONG *pSort, ULONG *pDisplay) { if (pSort) - *pSort = 0; + *pSort = COL_NAME_INDEX; if (pDisplay) - *pDisplay = 0; + *pDisplay = COL_NAME_INDEX; return S_OK; } @@ -684,17 +759,31 @@ STDMETHODIMP CFindFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags) STDMETHODIMP CFindFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv) { - return m_pisfInner->GetDetailsEx(pidl, pscid, pv); + // FIXME: Handle COL_LOCATION_INDEX and COL_RELEVANCE_INDEX + CComPtr pFolder; + PCUITEMID_CHILD pChild; + if (SUCCEEDED(GetFSFolder2AndChild(pidl, &pFolder, &pChild))) + return pFolder->GetDetailsEx(pChild, pscid, pv); + return E_FAIL; } STDMETHODIMP CFindFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *pDetails) { if (iColumn >= _countof(g_ColumnDefs)) - return m_pisfInner->GetDetailsOf(_ILGetFSPidl(pidl), iColumn - _countof(g_ColumnDefs) + 1, pDetails); + { + UINT FSColumn = iColumn - _countof(g_ColumnDefs) + 1; + if (pidl) + { + CComPtr pFolder; + PCUITEMID_CHILD pChild; + if (SUCCEEDED(GetFSFolder2AndChild(pidl, &pFolder, &pChild))) + return pFolder->GetDetailsOf(pChild, FSColumn, pDetails); + } + return m_pisfInner->GetDetailsOf(pidl, FSColumn, pDetails); // Column header info + } pDetails->cxChar = g_ColumnDefs[iColumn].cxChar; pDetails->fmt = g_ColumnDefs[iColumn].fmt; - if (!pidl) return SHSetStrRet(&pDetails->str, _AtlBaseModule.GetResourceInstance(), g_ColumnDefs[iColumn].iResource); @@ -709,7 +798,8 @@ STDMETHODIMP CFindFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELL return SHSetStrRet(&pDetails->str, ""); } - return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str); + ATLASSERT(iColumn == COL_NAME_INDEX); + return GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &pDetails->str); } STDMETHODIMP CFindFolder::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid) @@ -734,8 +824,12 @@ STDMETHODIMP CFindFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIS STDMETHODIMP CFindFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) { - UNIMPLEMENTED; - return E_NOTIMPL; + HRESULT hr; + CComPtr pInnerFolder; + PCUITEMID_CHILD pidlChild; + if (FAILED_UNEXPECTEDLY(hr = GetFSFolderAndChild(pidl, &pInnerFolder, &pidlChild))) + return hr; + return pInnerFolder->BindToObject(pidlChild, pbcReserved, riid, ppvOut); } STDMETHODIMP CFindFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) @@ -759,6 +853,7 @@ STDMETHODIMP CFindFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PC wColumn -= _countof(g_ColumnDefs) - 1; break; } + // FIXME: DefView does not like the way we sort return m_pisfInner->CompareIDs(HIWORD(lParam) | wColumn, _ILGetFSPidl(pidl1), _ILGetFSPidl(pidl2)); } @@ -783,14 +878,24 @@ STDMETHODIMP CFindFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * STDMETHODIMP CFindFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut) { - CComHeapPtr aFSPidl; - aFSPidl.Allocate(cidl); - for (UINT i = 0; i < cidl; i++) + if (!cidl) { - aFSPidl[i] = _ILGetFSPidl(apidl[i]); + *rgfInOut &= SFGAO_BROWSABLE; // TODO: SFGAO_CANRENAME? + return S_OK; } - return m_pisfInner->GetAttributesOf(cidl, aFSPidl, rgfInOut); + HRESULT hr = E_INVALIDARG; + for (UINT i = 0; i < cidl; ++i) + { + CComPtr pFolder; + PCUITEMID_CHILD pidlChild; + if (FAILED_UNEXPECTEDLY(hr = GetFSFolderAndChild(apidl[i], &pFolder, &pidlChild))) + break; + if (FAILED(hr = pFolder->GetAttributesOf(1, &pidlChild, rgfInOut))) + break; + } + *rgfInOut &= ~SFGAO_CANRENAME; // FIXME: Handle SetNameOf + return hr; } class CFindFolderContextMenu : @@ -805,7 +910,7 @@ class CFindFolderContextMenu : //// *** IContextMenu methods *** STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { - m_firstCmdId = indexMenu; + m_firstCmdId = idCmdFirst; _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst++, MFT_STRING, MAKEINTRESOURCEW(IDS_SEARCH_OPEN_FOLDER), MFS_ENABLED); _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst++, MFT_SEPARATOR, NULL, 0); return m_pInner->QueryContextMenu(hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); @@ -818,7 +923,7 @@ class CFindFolderContextMenu : return m_pInner->InvokeCommand(lpcmi); } - if (LOWORD(lpcmi->lpVerb) < m_firstCmdId + ADDITIONAL_MENU_ITEMS) + if (LOWORD(lpcmi->lpVerb) >= m_firstCmdId && LOWORD(lpcmi->lpVerb) < m_firstCmdId + ADDITIONAL_MENU_ITEMS) { PCUITEMID_CHILD *apidl; UINT cidl; @@ -838,9 +943,11 @@ class CFindFolderContextMenu : return S_OK; } + // FIXME: We can't block FCIDM_SHVIEW_REFRESH here, add items on SFVM_LISTREFRESHED instead CMINVOKECOMMANDINFOEX actualCmdInfo; memcpy(&actualCmdInfo, lpcmi, lpcmi->cbSize); - actualCmdInfo.lpVerb -= ADDITIONAL_MENU_ITEMS; + if (LOWORD(lpcmi->lpVerb) < FCIDM_SHVIEW_ARRANGE) // HACKFIX for DefView using direct FCIDM_SHVIEW ids + actualCmdInfo.lpVerb -= ADDITIONAL_MENU_ITEMS; return m_pInner->InvokeCommand((CMINVOKECOMMANDINFO *)&actualCmdInfo); } @@ -866,16 +973,39 @@ public: END_COM_MAP() }; +int CALLBACK CFindFolder::SortItemsForDataObject(void *p1, void *p2, LPARAM lparam) +{ + // For Delete/Move operations, a subfolder/file needs to come before the parent folder + return ::ILGetSize((LPCITEMIDLIST)p1) - ::ILGetSize((LPCITEMIDLIST)p2); +} + STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT *prgfInOut, LPVOID *ppvOut) { + HRESULT hr; if (cidl <= 0) - { - return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut); - } + return E_INVALIDARG; - CComHeapPtr aFSPidl; - aFSPidl.Allocate(cidl); + CComHeapPtr aFSPidlAlloc; + PCITEMID_CHILD pidlSingleBuffer, *aFSPidl = &pidlSingleBuffer; // Optimize for single item callers + if (cidl != 1) + { + if (riid == IID_IDataObject) + { + if (HDPA hDpa = CreateAbsolutePidlArray(cidl, apidl)) + { + DPA_Sort(hDpa, SortItemsForDataObject, NULL); + ITEMIDLIST pidlRoot = {}; + hr = SHCreateFileDataObject(&pidlRoot, cidl, (PCUITEMID_CHILD_ARRAY)DPA_GetPtrPtr(hDpa), + NULL, (IDataObject**)ppvOut); + FreePidlArray(hDpa); + return hr; + } + } + + aFSPidlAlloc.Allocate(cidl); + aFSPidl = aFSPidlAlloc; + } for (UINT i = 0; i < cidl; i++) { aFSPidl[i] = _ILGetFSPidl(apidl[i]); @@ -883,30 +1013,38 @@ STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHI if (riid == IID_IContextMenu) { + // FIXME: Use CDefFolderMenu_Create2(..., AddFSClassKeysToArray()) CComHeapPtr folderPidl(ILCreateFromPathW(_ILGetPath(apidl[0]))); if (!folderPidl) return E_OUTOFMEMORY; CComPtr pDesktopFolder; - HRESULT hResult = SHGetDesktopFolder(&pDesktopFolder); - if (FAILED_UNEXPECTEDLY(hResult)) - return hResult; + if (FAILED_UNEXPECTEDLY(hr = SHGetDesktopFolder(&pDesktopFolder))) + return hr; CComPtr pShellFolder; - hResult = pDesktopFolder->BindToObject(folderPidl, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder)); - if (FAILED_UNEXPECTEDLY(hResult)) - return hResult; + hr = pDesktopFolder->BindToObject(folderPidl, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; CComPtr pContextMenu; - hResult = pShellFolder->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, (LPVOID *)&pContextMenu); - if (FAILED_UNEXPECTEDLY(hResult)) - return hResult; + hr = pShellFolder->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, (void**)&pContextMenu); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; return CFindFolderContextMenu::Create(m_shellFolderView, pContextMenu, (IContextMenu **)ppvOut); } - return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut); + CComPtr pFolder; + if (FAILED_UNEXPECTEDLY(hr = GetFSFolderAndChild(apidl[0], &pFolder))) + return hr; + return pFolder->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut); } STDMETHODIMP CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName) { - return m_pisfInner->GetDisplayNameOf(_ILGetFSPidl(pidl), dwFlags, pName); + HRESULT hr; + CComPtr pFolder; + PCUITEMID_CHILD pidlChild; + if (FAILED_UNEXPECTEDLY(hr = GetFSFolderAndChild(pidl, &pFolder, &pidlChild))) + return hr; + return pFolder->GetDisplayNameOf(pidlChild, dwFlags, pName); } STDMETHODIMP CFindFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, @@ -933,11 +1071,7 @@ STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) SubclassWindow((HWND) wParam); // Get shell browser for updating status bar text - CComPtr pServiceProvider; - HRESULT hr = m_shellFolderView->QueryInterface(IID_PPV_ARG(IServiceProvider, &pServiceProvider)); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - hr = pServiceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &m_shellBrowser)); + HRESULT hr = IUnknown_QueryService(m_shellFolderView, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &m_shellBrowser)); if (FAILED_UNEXPECTEDLY(hr)) return hr; @@ -946,9 +1080,9 @@ STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) hr = m_shellBrowser->QueryInterface(IID_PPV_ARG(IWebBrowser2, &pWebBrowser2)); if (FAILED_UNEXPECTEDLY(hr)) return hr; - WCHAR pwszGuid[MAX_PATH]; - StringFromGUID2(CLSID_FileSearchBand, pwszGuid, _countof(pwszGuid)); - CComVariant searchBar(pwszGuid); + WCHAR wszGuid[39]; + StringFromGUID2(CLSID_FileSearchBand, wszGuid, _countof(wszGuid)); + CComVariant searchBar(wszGuid); return pWebBrowser2->ShowBrowserBar(&searchBar, NULL, NULL); } case SFVM_WINDOWCLOSING: @@ -973,6 +1107,7 @@ STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) } return hr; } + // TODO: SFVM_GETCOLUMNSTREAM } return E_NOTIMPL; } @@ -980,21 +1115,20 @@ STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) //// *** IPersistFolder2 methods *** STDMETHODIMP CFindFolder::GetCurFolder(PIDLIST_ABSOLUTE *pidl) { - *pidl = ILClone(m_pidl); - return S_OK; + return SHILClone(m_pidl, pidl); } // *** IPersistFolder methods *** STDMETHODIMP CFindFolder::Initialize(PCIDLIST_ABSOLUTE pidl) { - m_pidl = ILClone(pidl); - if (!m_pidl) - return E_OUTOFMEMORY; - - return SHELL32_CoCreateInitSF(m_pidl, - NULL, - NULL, - &CLSID_ShellFSFolder, + if (m_pidl) + return E_UNEXPECTED; + HRESULT hr; + if (FAILED(hr = SHGetDesktopFolder((IShellFolder**)&m_pSfDesktop))) + return hr; + if (FAILED(hr = SHILClone(pidl, &m_pidl))) + return hr; + return SHELL32_CoCreateInitSF(m_pidl, NULL, NULL, &CLSID_ShellFSFolder, IID_PPV_ARG(IShellFolder2, &m_pisfInner)); } diff --git a/dll/win32/browseui/shellfind/CFindFolder.h b/dll/win32/browseui/shellfind/CFindFolder.h index a19651bde49..142a3e6265c 100644 --- a/dll/win32/browseui/shellfind/CFindFolder.h +++ b/dll/win32/browseui/shellfind/CFindFolder.h @@ -64,11 +64,16 @@ class CFindFolder : private: LPITEMIDLIST m_pidl; - CComPtr m_pisfInner; + CComPtr m_pisfInner, m_pSfDesktop; CComPtr m_shellFolderView; CComPtr m_shellBrowser; HANDLE m_hStopEvent; + HRESULT GetFSFolderAndChild(LPCITEMIDLIST pidl, IShellFolder **ppSF, PCUITEMID_CHILD *ppidlLast = NULL); + HRESULT GetFSFolder2AndChild(LPCITEMIDLIST pidl, IShellFolder2 **ppSF, PCUITEMID_CHILD *ppidlLast = NULL); + void FreePidlArray(HDPA hDpa); + HDPA CreateAbsolutePidlArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl); + static int CALLBACK SortItemsForDataObject(void *p1, void *p2, LPARAM lparam); void NotifyConnections(DISPID id); static DWORD WINAPI SearchThreadProc(LPVOID lpParameter); diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp index d78feeb7f86..46322dfec26 100644 --- a/dll/win32/shell32/CDefView.cpp +++ b/dll/win32/shell32/CDefView.cpp @@ -336,6 +336,7 @@ public: HRESULT CheckViewMode(HMENU hmenuView); LRESULT DoColumnContextMenu(LRESULT lParam); UINT GetSelections(); + SFGAOF GetSelectionAttributes(SFGAOF Query); HRESULT OpenSelectedItems(); void OnDeactivate(); void DoActivate(UINT uState); @@ -1841,7 +1842,7 @@ HRESULT CDefView::FillFileMenu() HMENU hmenu = CreatePopupMenu(); - UINT cmf = GetContextMenuFlags(m_pShellBrowser, SFGAO_CANRENAME); + UINT cmf = GetContextMenuFlags(m_pShellBrowser, GetSelectionAttributes(SFGAO_CANRENAME)); hr = m_pFileMenu->QueryContextMenu(hmenu, 0, DVIDM_CONTEXTMENU_FIRST, DVIDM_CONTEXTMENU_LAST, cmf); if (FAILED_UNEXPECTEDLY(hr)) return hr; @@ -2101,6 +2102,14 @@ UINT CDefView::GetSelections() return m_cidl; } +SFGAOF CDefView::GetSelectionAttributes(SFGAOF Query) +{ + if (!GetSelections()) + return 0; + SFGAOF Attr = Query; + return SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &Attr)) ? (Attr & Query) : 0; +} + HRESULT CDefView::InvokeContextMenuCommand(CComPtr& pCM, LPCSTR lpVerb, POINT* pt) { CMINVOKECOMMANDINFOEX cmi; @@ -2232,7 +2241,7 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b if (FAILED_UNEXPECTEDLY(hResult)) return 0; - UINT cmf = GetContextMenuFlags(m_pShellBrowser, SFGAO_CANRENAME); + UINT cmf = GetContextMenuFlags(m_pShellBrowser, GetSelectionAttributes(SFGAO_CANRENAME)); // Use 1 as the first id we want. 0 means that user canceled the menu hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, CONTEXT_MENU_BASE_ID, DVIDM_CONTEXTMENU_LAST, cmf); if (FAILED_UNEXPECTEDLY(hResult)) @@ -3350,7 +3359,7 @@ HRESULT CDefView::SaveViewState(IStream *pStream) cols.Signature = PERSISTCOLUMNS::SIG; cols.Count = 0; LVCOLUMN lvc; - lvc.mask = LVCF_WIDTH | LVCF_SUBITEM; + lvc.mask = LVCF_WIDTH; for (UINT i = 0, j = 0; i < PERSISTCOLUMNS::MAXCOUNT && ListView_GetColumn(m_ListView, j, &lvc); ++j) { HRESULT hr = MapListColumnToFolderColumn(j); @@ -3405,6 +3414,7 @@ HRESULT CDefView::SaveViewState(IStream *pStream) if (SUCCEEDED(hr)) hr = pStream->Write(&cols, cbColumns, &written); } + // TODO: else if (SUCCEEDED(_DoFolderViewCB(SFVM_GETCOLUMNSTREAM))) if (pStream) pStream->Release(); return hr; diff --git a/dll/win32/shell32/CShellLink.cpp b/dll/win32/shell32/CShellLink.cpp index b60987d40a3..162d91c64d8 100644 --- a/dll/win32/shell32/CShellLink.cpp +++ b/dll/win32/shell32/CShellLink.cpp @@ -1790,6 +1790,7 @@ HRESULT STDMETHODCALLTYPE CShellLink::GetIconLocation(UINT uFlags, PWSTR pszIcon } else { + // TODO: If GetIconLocation succeeded, why are we setting GIL_NOTFILENAME? And are we not PERINSTANCE? *pwFlags = GIL_NOTFILENAME | GIL_PERCLASS; } @@ -2575,13 +2576,12 @@ HRESULT STDMETHODCALLTYPE CShellLink::QueryContextMenu(HMENU hMenu, UINT indexMe if (!InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii)) return E_FAIL; - UNREFERENCED_PARAMETER(indexMenu); - return MAKE_HRESULT(SEVERITY_SUCCESS, 0, id); } HRESULT CShellLink::DoOpenFileLocation() { + // TODO: SHOpenFolderAndSelectItems WCHAR szParams[MAX_PATH + 64]; StringCbPrintfW(szParams, sizeof(szParams), L"/select,%s", m_sPath);