[BROWSEUI] CExplorerBand: Use SHCNRF_NewDelivery method (#7133)

Refactoring. Optimize for speed.
JIRA issue: CORE-12619
- Update file headers.
- Make some parameter type LPITEMIDLIST
  LPCITEMIDLIST (Add const).
- Add OnChangeNotify method.
- Use SHCNRF_NewDelivery method for speed.
- Add some SAL annotations.
This commit is contained in:
Katayama Hirofumi MZ 2024-07-14 10:50:18 +09:00 committed by GitHub
parent 4093d0e164
commit 7bec458077
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 85 additions and 64 deletions

View file

@ -1,22 +1,9 @@
/* /*
* ReactOS Explorer * PROJECT: ReactOS Explorer
* * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com> * PURPOSE: Explorer bar
* Copyright 2020 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> * COPYRIGHT: Copyright 2016 Sylvain Deverre <deverre.sylv@gmail.com>
* * Copyright 2020-2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "precomp.h" #include "precomp.h"
@ -87,7 +74,9 @@ HRESULT GetDisplayName(LPCITEMIDLIST pidlDirectory,TCHAR *szDisplayName,UINT cch
ill-formed PIDL stripped from useful data that parses incorrectly with SHGetFileInfo. ill-formed PIDL stripped from useful data that parses incorrectly with SHGetFileInfo.
So we need to re-enumerate subfolders until we find one with the same name. So we need to re-enumerate subfolders until we find one with the same name.
*/ */
HRESULT _ReparsePIDL(LPITEMIDLIST buggyPidl, LPITEMIDLIST *cleanPidl) HRESULT _ReparsePIDL(
_In_ LPCITEMIDLIST buggyPidl,
_Out_ LPITEMIDLIST *cleanPidl)
{ {
HRESULT hr; HRESULT hr;
CComPtr<IShellFolder> folder; CComPtr<IShellFolder> folder;
@ -187,7 +176,7 @@ void CExplorerBand::InitializeExplorerBand()
TreeView_SetImageList(m_hWnd, (HIMAGELIST)piml, TVSIL_NORMAL); TreeView_SetImageList(m_hWnd, (HIMAGELIST)piml, TVSIL_NORMAL);
// Insert the root node // Insert the root node
m_hRoot = InsertItem(0, m_pDesktop, pidl, pidl, FALSE); m_hRoot = InsertItem(NULL, m_pDesktop, pidl, pidl, FALSE);
if (!m_hRoot) if (!m_hRoot)
{ {
ERR("Failed to create root item\n"); ERR("Failed to create root item\n");
@ -208,7 +197,7 @@ void CExplorerBand::InitializeExplorerBand()
shcne.fRecursive = TRUE; shcne.fRecursive = TRUE;
m_shellRegID = SHChangeNotifyRegister( m_shellRegID = SHChangeNotifyRegister(
m_hWnd, m_hWnd,
SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_RecursiveInterrupt, SHCNRF_NewDelivery | SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_RecursiveInterrupt,
SHCNE_DISKEVENTS | SHCNE_RENAMEFOLDER | SHCNE_RMDIR | SHCNE_MKDIR, SHCNE_DISKEVENTS | SHCNE_RENAMEFOLDER | SHCNE_RMDIR | SHCNE_MKDIR,
WM_USER_SHELLEVENT, WM_USER_SHELLEVENT,
1, 1,
@ -580,35 +569,59 @@ LRESULT CExplorerBand::ContextMenuHack(UINT uMsg, WPARAM wParam, LPARAM lParam,
return FALSE; /* let the wndproc process the message */ return FALSE; /* let the wndproc process the message */
} }
// WM_USER_SHELLEVENT
LRESULT CExplorerBand::OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) LRESULT CExplorerBand::OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{ {
LPITEMIDLIST *dest; // We use SHCNRF_NewDelivery method
HANDLE hChange = (HANDLE)wParam;
DWORD dwProcID = (DWORD)lParam;
PIDLIST_ABSOLUTE *ppidl = NULL;
LONG lEvent;
HANDLE hLock = SHChangeNotification_Lock(hChange, dwProcID, &ppidl, &lEvent);
if (hLock == NULL)
{
ERR("hLock == NULL\n");
return 0;
}
OnChangeNotify(ppidl[0], ppidl[1], (lEvent & ~SHCNE_INTERRUPT));
SHChangeNotification_Unlock(hLock);
return 0;
}
void
CExplorerBand::OnChangeNotify(
_In_opt_ LPCITEMIDLIST pidl0,
_In_opt_ LPCITEMIDLIST pidl1,
_In_ LONG lEvent)
{
LPITEMIDLIST clean; LPITEMIDLIST clean;
HTREEITEM pItem; HTREEITEM pItem;
dest = (LPITEMIDLIST*)wParam;
/* TODO: handle shell notifications */ /* TODO: handle shell notifications */
switch(lParam & ~SHCNE_INTERRUPT) switch (lEvent)
{ {
case SHCNE_MKDIR: case SHCNE_MKDIR:
if (!SUCCEEDED(_ReparsePIDL(dest[0], &clean))) if (!SUCCEEDED(_ReparsePIDL(pidl0, &clean)))
{ {
ERR("Can't reparse PIDL to a valid one\n"); ERR("Can't reparse PIDL to a valid one\n");
return FALSE; break;
} }
NavigateToPIDL(clean, &pItem, FALSE, TRUE, FALSE); NavigateToPIDL(clean, &pItem, FALSE, TRUE, FALSE);
ILFree(clean); ILFree(clean);
break; break;
case SHCNE_RMDIR: case SHCNE_RMDIR:
DeleteItem(dest[0]); DeleteItem(pidl0);
break; break;
case SHCNE_RENAMEFOLDER: case SHCNE_RENAMEFOLDER:
if (!SUCCEEDED(_ReparsePIDL(dest[1], &clean))) if (!SUCCEEDED(_ReparsePIDL(pidl1, &clean)))
{ {
ERR("Can't reparse PIDL to a valid one\n"); ERR("Can't reparse PIDL to a valid one\n");
return FALSE; break;
} }
if (NavigateToPIDL(dest[0], &pItem, FALSE, FALSE, FALSE)) if (NavigateToPIDL(pidl0, &pItem, FALSE, FALSE, FALSE))
RenameItem(pItem, clean); RenameItem(pItem, clean);
ILFree(clean); ILFree(clean);
break; break;
@ -619,7 +632,6 @@ LRESULT CExplorerBand::OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOO
default: default:
TRACE("Unhandled message\n"); TRACE("Unhandled message\n");
} }
return TRUE;
} }
LRESULT CExplorerBand::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) LRESULT CExplorerBand::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
@ -638,7 +650,13 @@ LRESULT CExplorerBand::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL
} }
// *** Helper functions *** // *** Helper functions ***
HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, IShellFolder *psfParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort) HTREEITEM
CExplorerBand::InsertItem(
_In_opt_ HTREEITEM hParent,
_Inout_ IShellFolder *psfParent,
_In_ LPCITEMIDLIST pElt,
_In_ LPCITEMIDLIST pEltRelative,
_In_ BOOL bSort)
{ {
TV_INSERTSTRUCT tvInsert; TV_INSERTSTRUCT tvInsert;
HTREEITEM htiCreated; HTREEITEM htiCreated;
@ -707,7 +725,12 @@ HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, IShellFolder *psfParent,
} }
/* This is the slow version of the above method */ /* This is the slow version of the above method */
HTREEITEM CExplorerBand::InsertItem(HTREEITEM hParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort) HTREEITEM
CExplorerBand::InsertItem(
_In_opt_ HTREEITEM hParent,
_In_ LPCITEMIDLIST pElt,
_In_ LPCITEMIDLIST pEltRelative,
_In_ BOOL bSort)
{ {
CComPtr<IShellFolder> psfFolder; CComPtr<IShellFolder> psfFolder;
HRESULT hr = SHBindToParent(pElt, IID_PPV_ARG(IShellFolder, &psfFolder), NULL); HRESULT hr = SHBindToParent(pElt, IID_PPV_ARG(IShellFolder, &psfFolder), NULL);
@ -805,7 +828,7 @@ BOOL CExplorerBand::InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo)
* - bInsert: insert the element at the right place if we don't find it * - bInsert: insert the element at the right place if we don't find it
* - bSelect: select the item after we found it * - bSelect: select the item after we found it
*/ */
BOOL CExplorerBand::NavigateToPIDL(LPITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, BOOL bInsert, BOOL CExplorerBand::NavigateToPIDL(LPCITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, BOOL bInsert,
BOOL bSelect) BOOL bSelect)
{ {
HTREEITEM current; HTREEITEM current;
@ -917,7 +940,7 @@ BOOL CExplorerBand::NavigateToCurrentFolder()
return result; return result;
} }
BOOL CExplorerBand::DeleteItem(LPITEMIDLIST idl) BOOL CExplorerBand::DeleteItem(LPCITEMIDLIST idl)
{ {
HTREEITEM toDelete; HTREEITEM toDelete;
TVITEM tvItem; TVITEM tvItem;
@ -950,7 +973,7 @@ BOOL CExplorerBand::DeleteItem(LPITEMIDLIST idl)
return TRUE; return TRUE;
} }
BOOL CExplorerBand::RenameItem(HTREEITEM toRename, LPITEMIDLIST newPidl) BOOL CExplorerBand::RenameItem(HTREEITEM toRename, LPCITEMIDLIST newPidl)
{ {
WCHAR wszDisplayName[MAX_PATH]; WCHAR wszDisplayName[MAX_PATH];
TVITEM itemInfo; TVITEM itemInfo;
@ -1000,7 +1023,7 @@ BOOL CExplorerBand::RenameItem(HTREEITEM toRename, LPITEMIDLIST newPidl)
return TRUE; return TRUE;
} }
BOOL CExplorerBand::RefreshTreePidl(HTREEITEM tree, LPITEMIDLIST pidlParent) BOOL CExplorerBand::RefreshTreePidl(HTREEITEM tree, LPCITEMIDLIST pidlParent)
{ {
HTREEITEM tmp; HTREEITEM tmp;
NodeInfo *pInfo; NodeInfo *pInfo;
@ -1340,7 +1363,6 @@ HRESULT STDMETHODCALLTYPE CExplorerBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
return E_NOTIMPL; return E_NOTIMPL;
} }
// *** IWinEventHandler methods *** // *** IWinEventHandler methods ***
HRESULT STDMETHODCALLTYPE CExplorerBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) HRESULT STDMETHODCALLTYPE CExplorerBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{ {

View file

@ -1,28 +1,14 @@
/* /*
* ReactOS Explorer * PROJECT: ReactOS Explorer
* * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com> * PURPOSE: Explorer bar
* Copyright 2020 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> * COPYRIGHT: Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com>
* * Copyright 2020-2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#pragma once #pragma once
#define WM_USER_SHELLEVENT WM_USER+88 #define WM_USER_SHELLEVENT (WM_USER + 88)
#define WM_USER_FOLDEREVENT WM_USER+88
class CExplorerBand : class CExplorerBand :
public CComCoClass<CExplorerBand, &CLSID_ExplorerBand>, public CComCoClass<CExplorerBand, &CLSID_ExplorerBand>,
@ -95,16 +81,29 @@ private:
// *** Helper functions *** // *** Helper functions ***
NodeInfo* GetNodeInfo(HTREEITEM hItem); NodeInfo* GetNodeInfo(HTREEITEM hItem);
HRESULT UpdateBrowser(LPITEMIDLIST pidlGoto); HRESULT UpdateBrowser(LPITEMIDLIST pidlGoto);
HTREEITEM InsertItem(HTREEITEM hParent, IShellFolder *psfParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort); HTREEITEM InsertItem(
HTREEITEM InsertItem(HTREEITEM hParent, LPITEMIDLIST pElt, LPITEMIDLIST pEltRelative, BOOL bSort); _In_opt_ HTREEITEM hParent,
_Inout_ IShellFolder *psfParent,
_In_ LPCITEMIDLIST pElt,
_In_ LPCITEMIDLIST pEltRelative,
_In_ BOOL bSort);
HTREEITEM InsertItem(
_In_opt_ HTREEITEM hParent,
_In_ LPCITEMIDLIST pElt,
_In_ LPCITEMIDLIST pEltRelative,
_In_ BOOL bSort);
BOOL InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo); BOOL InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo);
BOOL NavigateToPIDL(LPITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, BOOL bInsert, BOOL bSelect); BOOL NavigateToPIDL(LPCITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, BOOL bInsert, BOOL bSelect);
BOOL DeleteItem(LPITEMIDLIST toDelete); BOOL DeleteItem(LPCITEMIDLIST toDelete);
BOOL RenameItem(HTREEITEM toRename, LPITEMIDLIST newPidl); BOOL RenameItem(HTREEITEM toRename, LPCITEMIDLIST newPidl);
BOOL RefreshTreePidl(HTREEITEM tree, LPITEMIDLIST pidlParent); BOOL RefreshTreePidl(HTREEITEM tree, LPCITEMIDLIST pidlParent);
BOOL NavigateToCurrentFolder(); BOOL NavigateToCurrentFolder();
HRESULT GetCurrentLocation(PIDLIST_ABSOLUTE &pidl); HRESULT GetCurrentLocation(PIDLIST_ABSOLUTE &pidl);
HRESULT IsCurrentLocation(PCIDLIST_ABSOLUTE pidl); HRESULT IsCurrentLocation(PCIDLIST_ABSOLUTE pidl);
void OnChangeNotify(
_In_opt_ LPCITEMIDLIST pidl0,
_In_opt_ LPCITEMIDLIST pidl1,
_In_ LONG lEvent);
// *** Tree item sorting callback *** // *** Tree item sorting callback ***
static int CALLBACK CompareTreeItems(LPARAM p1, LPARAM p2, LPARAM p3); static int CALLBACK CompareTreeItems(LPARAM p1, LPARAM p2, LPARAM p3);