https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f844296b0a7f481fb2f4c…
commit f844296b0a7f481fb2f4cc9e85180ce3659c60a2
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Sat Mar 8 14:30:04 2025 +0100
Commit: GitHub <noreply(a)github.com>
CommitDate: Sat Mar 8 14:30:04 2025 +0100
[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 | 254 ++++++++++++++++++++-------
dll/win32/browseui/shellfind/CFindFolder.h | 7 +-
dll/win32/shell32/CDefView.cpp | 16 +-
dll/win32/shell32/CShellLink.cpp | 4 +-
4 files changed, 215 insertions(+), 66 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<IShellFolder> 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<IShellFolder2> 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<IShellFolder2> 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<IShellFolder> 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<PCITEMID_CHILD> 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<IShellFolder> 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 E_INVALIDARG;
+
+ CComHeapPtr<PCITEMID_CHILD> aFSPidlAlloc;
+ PCITEMID_CHILD pidlSingleBuffer, *aFSPidl = &pidlSingleBuffer; // Optimize for
single item callers
+ if (cidl != 1)
{
- return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut,
ppvOut);
- }
+ 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;
+ }
+ }
- CComHeapPtr<PCITEMID_CHILD> aFSPidl;
- aFSPidl.Allocate(cidl);
+ 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<ITEMIDLIST>
folderPidl(ILCreateFromPathW(_ILGetPath(apidl[0])));
if (!folderPidl)
return E_OUTOFMEMORY;
CComPtr<IShellFolder> pDesktopFolder;
- HRESULT hResult = SHGetDesktopFolder(&pDesktopFolder);
- if (FAILED_UNEXPECTEDLY(hResult))
- return hResult;
+ if (FAILED_UNEXPECTEDLY(hr = SHGetDesktopFolder(&pDesktopFolder)))
+ return hr;
CComPtr<IShellFolder> 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<IContextMenu> 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<IShellFolder> 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<IShellFolder> 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<IServiceProvider> 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<IShellFolder2> m_pisfInner;
+ CComPtr<IShellFolder2> m_pisfInner, m_pSfDesktop;
CComPtr<IShellFolderView> m_shellFolderView;
CComPtr<IShellBrowser> 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<IContextMenu>& 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);