https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f844296b0a7f481fb2f4cc9e85180ce3659c60a2

commit f844296b0a7f481fb2f4cc9e85180ce3659c60a2
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Sat Mar 8 14:30:04 2025 +0100
Commit:     GitHub <nore...@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);
 

Reply via email to