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

commit 7ede53491013e6db1ac85dcfaa683dee3ef56084
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Wed Aug 14 12:00:47 2024 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Wed Aug 14 12:00:47 2024 +0900

    [SHDOCVW][SDK] Support Favorites bar Part 2 (#7223)
    
    Implement Favorites bar.
    JIRA issue: CORE-19686
    - Introduce CNSCBand class to commonize
      some code of CFavBand and CExplorerBand
      classes.
    - Implement Favorites bar.
    - Fix IBandNavigate and INamespaceProxy
      interfaces.
---
 dll/win32/shdocvw/CExplorerBand.cpp | 1625 ++++-------------------------------
 dll/win32/shdocvw/CExplorerBand.h   |  230 +----
 dll/win32/shdocvw/CFavBand.cpp      |  567 ++----------
 dll/win32/shdocvw/CFavBand.h        |  156 +---
 dll/win32/shdocvw/CMakeLists.txt    |    1 +
 dll/win32/shdocvw/CNSCBand.cpp      | 1487 ++++++++++++++++++++++++++++++++
 dll/win32/shdocvw/CNSCBand.h        |  231 +++++
 sdk/include/reactos/shlobj_undoc.h  |    4 +-
 8 files changed, 2051 insertions(+), 2250 deletions(-)

diff --git a/dll/win32/shdocvw/CExplorerBand.cpp 
b/dll/win32/shdocvw/CExplorerBand.cpp
index 8a60321a706..aa70c06c5c2 100644
--- a/dll/win32/shdocvw/CExplorerBand.cpp
+++ b/dll/win32/shdocvw/CExplorerBand.cpp
@@ -7,8 +7,6 @@
  */
 
 #include "objects.h"
-#include <commoncontrols.h>
-#include <undocshell.h>
 
 #include <wine/debug.h>
 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
@@ -21,1545 +19,298 @@ WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
  */
 
 CExplorerBand::CExplorerBand()
-    : m_pSite(NULL)
-    , m_fVisible(FALSE)
-    , m_mtxBlockNavigate(0)
-    , m_dwBandID(0)
-    , m_isEditing(FALSE)
-    , m_pidlCurrent(NULL)
 {
 }
 
 CExplorerBand::~CExplorerBand()
 {
-    if (m_pidlCurrent)
-    {
-        ILFree(m_pidlCurrent);
-    }
-}
-
-void CExplorerBand::InitializeExplorerBand()
-{
-    // Init the treeview here
-    HRESULT hr = SHGetDesktopFolder(&m_pDesktop);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return;
-
-    LPITEMIDLIST pidl;
-    hr = SHGetFolderLocation(m_hWnd, CSIDL_DESKTOP, NULL, 0, &pidl);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return;
-
-    IImageList * piml;
-    hr = SHGetImageList(SHIL_SMALL, IID_PPV_ARG(IImageList, &piml));
-    if (FAILED_UNEXPECTEDLY(hr))
-        return;
-
-    TreeView_SetImageList(m_hWnd, (HIMAGELIST)piml, TVSIL_NORMAL);
-
-    // Insert the root node
-    m_hRoot = InsertItem(NULL, m_pDesktop, pidl, pidl, FALSE);
-    if (!m_hRoot)
-    {
-        ERR("Failed to create root item\n");
-        return;
-    }
-
-    NodeInfo* pNodeInfo = GetNodeInfo(m_hRoot);
-
-    // Insert child nodes
-    InsertSubitems(m_hRoot, pNodeInfo);
-    TreeView_Expand(m_hWnd, m_hRoot, TVE_EXPAND);
-
-    // Navigate to current folder position
-    NavigateToCurrentFolder();
-
-#define TARGET_EVENTS ( \
-    SHCNE_DRIVEADD | SHCNE_MKDIR | SHCNE_CREATE | SHCNE_DRIVEREMOVED | 
SHCNE_RMDIR | \
-    SHCNE_DELETE | SHCNE_RENAMEFOLDER | SHCNE_RENAMEITEM | SHCNE_UPDATEDIR | \
-    SHCNE_UPDATEITEM | SHCNE_ASSOCCHANGED \
-)
-    // Register shell notification
-    SHChangeNotifyEntry shcne = { pidl, TRUE };
-    m_shellRegID = SHChangeNotifyRegister(m_hWnd,
-                                          SHCNRF_NewDelivery | 
SHCNRF_ShellLevel,
-                                          TARGET_EVENTS,
-                                          WM_USER_SHELLEVENT,
-                                          1, &shcne);
-    if (!m_shellRegID)
-    {
-        ERR("Something went wrong, error %08x\n", GetLastError());
-    }
-
-    // Register browser connection endpoint
-    CComPtr<IWebBrowser2> browserService;
-    hr = IUnknown_QueryService(m_pSite, SID_SWebBrowserApp, 
IID_PPV_ARG(IWebBrowser2, &browserService));
-    if (FAILED_UNEXPECTEDLY(hr))
-        return;
-
-    hr = AtlAdvise(browserService, dynamic_cast<IDispatch*>(this), 
DIID_DWebBrowserEvents, &m_adviseCookie);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return;
-
-    ILFree(pidl);
-}
-
-void CExplorerBand::DestroyExplorerBand()
-{
-    HRESULT hr;
-    CComPtr <IWebBrowser2> browserService;
-
-    TRACE("Cleaning up explorer band ...\n");
-
-    hr = IUnknown_QueryService(m_pSite, SID_SWebBrowserApp, 
IID_PPV_ARG(IWebBrowser2, &browserService));
-    if (FAILED_UNEXPECTEDLY(hr))
-        return;
-
-    hr = AtlUnadvise(browserService, DIID_DWebBrowserEvents, m_adviseCookie);
-    /* Remove all items of the treeview */
-    RevokeDragDrop(m_hWnd);
-    TreeView_DeleteAllItems(m_hWnd);
-    m_pDesktop = NULL;
-    m_hRoot = NULL;
-    TRACE("Cleanup done !\n");
-}
-
-CExplorerBand::NodeInfo* CExplorerBand::GetNodeInfo(HTREEITEM hItem)
-{
-    TVITEM tvItem;
-
-    tvItem.mask = TVIF_PARAM;
-    tvItem.hItem = hItem;
-
-    if (!TreeView_GetItem(m_hWnd, &tvItem))
-        return 0;
-
-    return reinterpret_cast<NodeInfo*>(tvItem.lParam);
-}
-
-static HRESULT GetCurrentLocationFromView(IShellView &View, PIDLIST_ABSOLUTE 
&pidl)
-{
-    CComPtr<IFolderView> pfv;
-    CComPtr<IShellFolder> psf;
-    HRESULT hr = View.QueryInterface(IID_PPV_ARG(IFolderView, &pfv));
-    if (SUCCEEDED(hr) && SUCCEEDED(hr = 
pfv->GetFolder(IID_PPV_ARG(IShellFolder, &psf))))
-        hr = SHELL_GetIDListFromObject(psf, &pidl);
-    return hr;
-}
-
-HRESULT CExplorerBand::GetCurrentLocation(PIDLIST_ABSOLUTE &pidl)
-{
-    pidl = NULL;
-    CComPtr<IShellBrowser> psb;
-    HRESULT hr = IUnknown_QueryService(m_pSite, SID_STopLevelBrowser, 
IID_PPV_ARG(IShellBrowser, &psb));
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
-
-    CComPtr<IBrowserService> pbs;
-    if (SUCCEEDED(hr = psb->QueryInterface(IID_PPV_ARG(IBrowserService, 
&pbs))))
-        if (SUCCEEDED(hr = pbs->GetPidl(&pidl)) && pidl)
-            return hr;
-
-    CComPtr<IShellView> psv;
-    if (!FAILED_UNEXPECTEDLY(hr = psb->QueryActiveShellView(&psv)))
-        if (SUCCEEDED(hr = psv.p ? GetCurrentLocationFromView(*psv.p, pidl) : 
E_FAIL))
-            return hr;
-    return hr;
-}
-
-HRESULT CExplorerBand::IsCurrentLocation(PCIDLIST_ABSOLUTE pidl)
-{
-    if (!pidl)
-        return E_INVALIDARG;
-    HRESULT hr = E_FAIL;
-    PIDLIST_ABSOLUTE location = m_pidlCurrent;
-    if (location || SUCCEEDED(hr = GetCurrentLocation(location)))
-        hr = SHELL_IsEqualAbsoluteID(location, pidl) ? S_OK : S_FALSE;
-    if (location != m_pidlCurrent)
-        ILFree(location);
-    return hr;
-}
-
-HRESULT CExplorerBand::ExecuteCommand(CComPtr<IContextMenu>& menu, UINT nCmd)
-{
-    CComPtr<IOleWindow>                 pBrowserOleWnd;
-    CMINVOKECOMMANDINFO                 cmi;
-    HWND                                browserWnd;
-    HRESULT                             hr;
-
-    hr = IUnknown_QueryService(m_pSite, SID_SShellBrowser, 
IID_PPV_ARG(IOleWindow, &pBrowserOleWnd));
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
-
-    hr = pBrowserOleWnd->GetWindow(&browserWnd);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
-
-    ZeroMemory(&cmi, sizeof(cmi));
-    cmi.cbSize = sizeof(cmi);
-    cmi.lpVerb = MAKEINTRESOURCEA(nCmd);
-    cmi.hwnd = browserWnd;
-    if (GetKeyState(VK_SHIFT) & 0x8000)
-        cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
-    if (GetKeyState(VK_CONTROL) & 0x8000)
-        cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
-
-    return menu->InvokeCommand(&cmi);
-}
-
-HRESULT CExplorerBand::UpdateBrowser(LPITEMIDLIST pidlGoto)
-{
-    CComPtr<IShellBrowser>              pBrowserService;
-    HRESULT                             hr;
-
-    hr = IUnknown_QueryService(m_pSite, SID_STopLevelBrowser, 
IID_PPV_ARG(IShellBrowser, &pBrowserService));
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
-
-    hr = pBrowserService->BrowseObject(pidlGoto, SBSP_SAMEBROWSER | 
SBSP_ABSOLUTE);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
-
-    ILFree(m_pidlCurrent);
-    return SHILClone(pidlGoto, &m_pidlCurrent);
-}
-
-// *** notifications handling ***
-BOOL CExplorerBand::OnTreeItemExpanding(LPNMTREEVIEW pnmtv)
-{
-    NodeInfo *pNodeInfo;
-
-    if (pnmtv->action == TVE_COLLAPSE) {
-        if (pnmtv->itemNew.hItem == m_hRoot)
-        {
-            // Prenvent root from collapsing
-            pnmtv->itemNew.mask |= TVIF_STATE;
-            pnmtv->itemNew.stateMask |= TVIS_EXPANDED;
-            pnmtv->itemNew.state &= ~TVIS_EXPANDED;
-            pnmtv->action = TVE_EXPAND;
-            return TRUE;
-        }
-    }
-    if (pnmtv->action == TVE_EXPAND) {
-        // Grab our directory PIDL
-        pNodeInfo = GetNodeInfo(pnmtv->itemNew.hItem);
-        // We have it, let's try
-        if (pNodeInfo && !pNodeInfo->expanded)
-            if (!InsertSubitems(pnmtv->itemNew.hItem, pNodeInfo)) {
-                // remove subitem "+" since we failed to add subitems
-                TV_ITEM tvItem;
-
-                tvItem.mask = TVIF_CHILDREN;
-                tvItem.hItem = pnmtv->itemNew.hItem;
-                tvItem.cChildren = 0;
-
-                TreeView_SetItem(m_hWnd, &tvItem);
-            }
-    }
-    return FALSE;
-}
-
-BOOL CExplorerBand::OnTreeItemDeleted(LPNMTREEVIEW pnmtv)
-{
-    // Navigate to parent when deleting selected item
-    HTREEITEM hItem = pnmtv->itemOld.hItem;
-    HTREEITEM hParent = TreeView_GetParent(m_hWnd, hItem);
-    if (hParent && TreeView_GetSelection(m_hWnd) == hItem)
-        TreeView_SelectItem(m_hWnd, hParent);
-
-    /* Destroy memory associated to our node */
-    NodeInfo* pNode = GetNodeInfo(hItem);
-    if (!pNode)
-        return FALSE;
-
-    ILFree(pNode->relativePidl);
-    ILFree(pNode->absolutePidl);
-    delete pNode;
-
-    return TRUE;
-}
-
-void CExplorerBand::OnSelectionChanged(LPNMTREEVIEW pnmtv)
-{
-    NodeInfo* pNodeInfo = GetNodeInfo(pnmtv->itemNew.hItem);
-
-    /* Prevents navigation if selection is initiated inside the band */
-    if (m_mtxBlockNavigate)
-        return;
-
-    UpdateBrowser(pNodeInfo->absolutePidl);
-
-    SetFocus();
-    // Expand the node
-    //TreeView_Expand(m_hWnd, pnmtv->itemNew.hItem, TVE_EXPAND);
-}
-
-void CExplorerBand::OnTreeItemDragging(LPNMTREEVIEW pnmtv, BOOL isRightClick)
-{
-    if (!pnmtv->itemNew.lParam)
-        return;
-
-    NodeInfo* pNodeInfo = GetNodeInfo(pnmtv->itemNew.hItem);
-
-    HRESULT hr;
-    CComPtr<IShellFolder> pSrcFolder;
-    LPCITEMIDLIST pLast;
-    hr = SHBindToParent(pNodeInfo->absolutePidl, IID_PPV_ARG(IShellFolder, 
&pSrcFolder), &pLast);
-    if (!SUCCEEDED(hr))
-        return;
-
-    SFGAOF attrs = SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK;
-    pSrcFolder->GetAttributesOf(1, &pLast, &attrs);
-
-    DWORD dwEffect = 0;
-    if (attrs & SFGAO_CANCOPY)
-        dwEffect |= DROPEFFECT_COPY;
-    if (attrs & SFGAO_CANMOVE)
-        dwEffect |= DROPEFFECT_MOVE;
-    if (attrs & SFGAO_CANLINK)
-        dwEffect |= DROPEFFECT_LINK;
-
-    CComPtr<IDataObject> pObj;
-    hr = pSrcFolder->GetUIObjectOf(m_hWnd, 1, &pLast, IID_IDataObject, 0, 
(LPVOID*)&pObj);
-    if (!SUCCEEDED(hr))
-        return;
-
-    DoDragDrop(pObj, this, dwEffect, &dwEffect);
-}
-
-// *** ATL event handlers ***
-LRESULT CExplorerBand::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, 
BOOL &bHandled)
-{
-    HTREEITEM                           item;
-    NodeInfo                            *info;
-    HMENU                               treeMenu;
-    POINT                               pt;
-    CComPtr<IShellFolder>               pFolder;
-    CComPtr<IContextMenu>               contextMenu;
-    HRESULT                             hr;
-    UINT                                uCommand;
-    LPITEMIDLIST                        pidlChild;
-    UINT                                cmdBase = max(FCIDM_SHVIEWFIRST, 1);
-    UINT                                cmf = CMF_EXPLORE;
-    SFGAOF                              attr = SFGAO_CANRENAME;
-    BOOL                                startedRename = FALSE;
-
-    treeMenu = NULL;
-    item = TreeView_GetSelection(m_hWnd);
-    bHandled = TRUE;
-    if (!item)
-    {
-        goto Cleanup;
-    }
-
-    pt.x = LOWORD(lParam);
-    pt.y = HIWORD(lParam);
-    if ((UINT)lParam == (UINT)-1)
-    {
-        RECT r;
-        if (TreeView_GetItemRect(m_hWnd, item, &r, TRUE))
-        {
-            pt.x = (r.left + r.right) / 2; // Center of
-            pt.y = (r.top + r.bottom) / 2; // item rectangle
-        }
-        ClientToScreen(&pt);
-    }
-
-    info = GetNodeInfo(item);
-    if (!info)
-    {
-        ERR("No node data, something has gone wrong !\n");
-        goto Cleanup;
-    }
-    hr = SHBindToParent(info->absolutePidl, IID_PPV_ARG(IShellFolder, 
&pFolder),
-        (LPCITEMIDLIST*)&pidlChild);
-    if (!SUCCEEDED(hr))
-    {
-        ERR("Can't bind to folder!\n");
-        goto Cleanup;
-    }
-    hr = pFolder->GetUIObjectOf(m_hWnd, 1, (LPCITEMIDLIST*)&pidlChild, 
IID_IContextMenu,
-        NULL, reinterpret_cast<void**>(&contextMenu));
-    if (!SUCCEEDED(hr))
-    {
-        ERR("Can't get IContextMenu interface\n");
-        goto Cleanup;
-    }
-
-    IUnknown_SetSite(contextMenu, (IDeskBand *)this);
-
-    if (SUCCEEDED(pFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidlChild, 
&attr)) && (attr & SFGAO_CANRENAME))
-        cmf |= CMF_CANRENAME;
-
-    treeMenu = CreatePopupMenu();
-    hr = contextMenu->QueryContextMenu(treeMenu, 0, cmdBase, FCIDM_SHVIEWLAST, 
cmf);
-    if (!SUCCEEDED(hr))
-    {
-        WARN("Can't get context menu for item\n");
-        DestroyMenu(treeMenu);
-        goto Cleanup;
-    }
-
-    uCommand = TrackPopupMenu(treeMenu, TPM_LEFTALIGN | TPM_RETURNCMD | 
TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
-        pt.x, pt.y, 0, m_hWnd, NULL);
-    if (uCommand)
-    {
-        uCommand -= cmdBase;
-
-        // Do DFM_CMD_RENAME in the treeview
-        if ((cmf & CMF_CANRENAME) && SHELL_IsVerb(contextMenu, uCommand, 
L"rename"))
-        {
-            HTREEITEM oldSelected = m_oldSelected;
-            SetFocus();
-            startedRename = TreeView_EditLabel(m_hWnd, item) != NULL;
-            m_oldSelected = oldSelected; // Restore after TVN_BEGINLABELEDIT
-            goto Cleanup;
-        }
-
-        hr = ExecuteCommand(contextMenu, uCommand);
-    }
-
-Cleanup:
-    if (contextMenu)
-        IUnknown_SetSite(contextMenu, NULL);
-    if (treeMenu)
-        DestroyMenu(treeMenu);
-    if (startedRename)
-    {
-        // The treeview disables drawing of the edited item so we must make 
sure
-        // the correct item is selected (on right-click -> rename on 
not-current folder).
-        // TVN_ENDLABELEDIT becomes responsible for restoring the selection.
-    }
-    else
-    {
-        ++m_mtxBlockNavigate;
-        TreeView_SelectItem(m_hWnd, m_oldSelected);
-        --m_mtxBlockNavigate;
-    }
-    return TRUE;
-}
-
-LRESULT CExplorerBand::ContextMenuHack(UINT uMsg, WPARAM wParam, LPARAM 
lParam, BOOL &bHandled)
-{
-    bHandled = FALSE;
-    if (uMsg == WM_RBUTTONDOWN)
-    {
-        TVHITTESTINFO info;
-        info.pt.x = LOWORD(lParam);
-        info.pt.y = HIWORD(lParam);
-        info.flags = TVHT_ONITEM;
-        info.hItem = NULL;
-
-        // Save the current location
-        m_oldSelected = TreeView_GetSelection(m_hWnd);
-
-        // Move to the item selected by the treeview (don't change right pane)
-        TreeView_HitTest(m_hWnd, &info);
-        ++m_mtxBlockNavigate;
-        TreeView_SelectItem(m_hWnd, info.hItem);
-        --m_mtxBlockNavigate;
-    }
-    return FALSE; /* let the wndproc process the message */
-}
-
-// WM_USER_SHELLEVENT
-LRESULT CExplorerBand::OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, 
BOOL &bHandled)
-{
-    // 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;
-}
-
-BOOL
-CExplorerBand::IsTreeItemInEnum(
-    _In_ HTREEITEM hItem,
-    _In_ IEnumIDList *pEnum)
-{
-    NodeInfo* pNodeInfo = GetNodeInfo(hItem);
-    if (!pNodeInfo)
-        return FALSE;
-
-    pEnum->Reset();
-
-    CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
-    while (pEnum->Next(1, &pidlTemp, NULL) == S_OK)
-    {
-        if (ILIsEqual(pidlTemp, pNodeInfo->relativePidl))
-            return TRUE;
-
-        pidlTemp.Free();
-    }
-
-    return FALSE;
-}
-
-BOOL
-CExplorerBand::TreeItemHasThisChild(
-    _In_ HTREEITEM hItem,
-    _In_ PCITEMID_CHILD pidlChild)
-{
-    for (hItem = TreeView_GetChild(m_hWnd, hItem); hItem;
-         hItem = TreeView_GetNextSibling(m_hWnd, hItem))
-    {
-        NodeInfo* pNodeInfo = GetNodeInfo(hItem);
-        if (ILIsEqual(pNodeInfo->relativePidl, pidlChild))
-            return TRUE;
-    }
-
-    return FALSE;
-}
-
-HRESULT
-CExplorerBand::GetItemEnum(
-    _Out_ CComPtr<IEnumIDList>& pEnum,
-    _In_ HTREEITEM hItem)
-{
-    NodeInfo* pNodeInfo = GetNodeInfo(hItem);
-
-    CComPtr<IShellFolder> psfDesktop;
-    HRESULT hr = SHGetDesktopFolder(&psfDesktop);
-    if (FAILED(hr))
-        return hr;
-
-    CComPtr<IShellFolder> pFolder;
-    hr = psfDesktop->BindToObject(pNodeInfo->absolutePidl, NULL, 
IID_PPV_ARG(IShellFolder, &pFolder));
-    if (FAILED(hr))
-        return hr;
-
-    return pFolder->EnumObjects(NULL, SHCONTF_FOLDERS, &pEnum);
-}
-
-BOOL CExplorerBand::ItemHasAnyChild(_In_ HTREEITEM hItem)
-{
-    CComPtr<IEnumIDList> pEnum;
-    HRESULT hr = GetItemEnum(pEnum, hItem);
-    if (FAILED(hr))
-        return FALSE;
-
-    CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
-    hr = pEnum->Next(1, &pidlTemp, NULL);
-    return SUCCEEDED(hr);
-}
-
-void CExplorerBand::RefreshRecurse(_In_ HTREEITEM hTarget)
-{
-    NodeInfo* pNodeInfo = GetNodeInfo(hTarget);
-
-    CComPtr<IEnumIDList> pEnum;
-    HRESULT hrEnum = GetItemEnum(pEnum, hTarget);
-
-    // Delete zombie items
-    HTREEITEM hItem, hNextItem;
-    for (hItem = TreeView_GetChild(m_hWnd, hTarget); hItem; hItem = hNextItem)
-    {
-        hNextItem = TreeView_GetNextSibling(m_hWnd, hItem);
-
-        if (SUCCEEDED(hrEnum) && !IsTreeItemInEnum(hItem, pEnum))
-            TreeView_DeleteItem(m_hWnd, hItem);
-    }
-
-    pEnum = NULL;
-    hrEnum = GetItemEnum(pEnum, hTarget);
-
-    // Insert new items and update items
-    if (SUCCEEDED(hrEnum))
-    {
-        CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
-        while (pEnum->Next(1, &pidlTemp, NULL) == S_OK)
-        {
-            if (!TreeItemHasThisChild(hTarget, pidlTemp))
-            {
-                CComHeapPtr<ITEMIDLIST> 
pidlAbsolute(ILCombine(pNodeInfo->absolutePidl, pidlTemp));
-                InsertItem(hTarget, pidlAbsolute, pidlTemp, TRUE);
-            }
-            pidlTemp.Free();
-        }
-    }
-
-    // Update children and recurse
-    for (hItem = TreeView_GetChild(m_hWnd, hTarget); hItem; hItem = hNextItem)
-    {
-        hNextItem = TreeView_GetNextSibling(m_hWnd, hItem);
-
-        TV_ITEMW item = { TVIF_HANDLE | TVIF_CHILDREN };
-        item.hItem = hItem;
-        item.cChildren = ItemHasAnyChild(hItem);
-        TreeView_SetItem(m_hWnd, &item);
-
-        if (TreeView_GetItemState(m_hWnd, hItem, TVIS_EXPANDEDONCE) & 
TVIS_EXPANDEDONCE)
-            RefreshRecurse(hItem);
-    }
-}
-
-void CExplorerBand::Refresh()
-{
-    SendMessage(WM_SETREDRAW, FALSE, 0);
-    RefreshRecurse(m_hRoot);
-    SendMessage(WM_SETREDRAW, TRUE, 0);
-    InvalidateRect(NULL, TRUE);
-}
-
-#define TIMER_ID_REFRESH 9999
-
-LRESULT CExplorerBand::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
-{
-    if (wParam != TIMER_ID_REFRESH)
-        return 0;
-
-    KillTimer(TIMER_ID_REFRESH);
-
-    // FIXME: Avoid full refresh and optimize for speed
-    Refresh();
-
-    return 0;
-}
-
-void
-CExplorerBand::OnChangeNotify(
-    _In_opt_ LPCITEMIDLIST pidl0,
-    _In_opt_ LPCITEMIDLIST pidl1,
-    _In_ LONG lEvent)
-{
-    switch (lEvent)
-    {
-        case SHCNE_DRIVEADD:
-        case SHCNE_MKDIR:
-        case SHCNE_CREATE:
-        case SHCNE_DRIVEREMOVED:
-        case SHCNE_RMDIR:
-        case SHCNE_DELETE:
-        case SHCNE_RENAMEFOLDER:
-        case SHCNE_RENAMEITEM:
-        case SHCNE_UPDATEDIR:
-        case SHCNE_UPDATEITEM:
-        case SHCNE_ASSOCCHANGED:
-        {
-            KillTimer(TIMER_ID_REFRESH);
-            SetTimer(TIMER_ID_REFRESH, 500, NULL);
-            break;
-        }
-        default:
-        {
-            TRACE("lEvent: 0x%08lX\n", lEvent);
-            break;
-        }
-    }
-}
-
-LRESULT CExplorerBand::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, 
BOOL &bHandled)
-{
-    m_bFocused = TRUE;
-    IUnknown_OnFocusChangeIS(m_pSite, reinterpret_cast<IUnknown*>(this), TRUE);
-    bHandled = FALSE;
-    return TRUE;
-}
-
-LRESULT CExplorerBand::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, 
BOOL &bHandled)
-{
-    IUnknown_OnFocusChangeIS(m_pSite, reinterpret_cast<IUnknown*>(this), 
FALSE);
-    bHandled = FALSE;
-    return TRUE;
-}
-
-// *** Helper functions ***
-HTREEITEM
-CExplorerBand::InsertItem(
-    _In_opt_ HTREEITEM hParent,
-    _Inout_ IShellFolder *psfParent,
-    _In_ LPCITEMIDLIST pElt,
-    _In_ LPCITEMIDLIST pEltRelative,
-    _In_ BOOL bSort)
-{
-    TV_INSERTSTRUCT                     tvInsert;
-    HTREEITEM                           htiCreated;
-
-    /* Get the attributes of the node */
-    SFGAOF attrs = SFGAO_STREAM | SFGAO_HASSUBFOLDER;
-    HRESULT hr = psfParent->GetAttributesOf(1, &pEltRelative, &attrs);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return NULL;
-
-    /* Ignore streams */
-    if (attrs & SFGAO_STREAM)
-    {
-        TRACE("Ignoring stream\n");
-        return NULL;
-    }
-
-    /* Get the name of the node */
-    WCHAR wszDisplayName[MAX_PATH];
-    STRRET strret;
-    hr = psfParent->GetDisplayNameOf(pEltRelative, SHGDN_INFOLDER, &strret);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return NULL;
-
-    hr = StrRetToBufW(&strret, pEltRelative, wszDisplayName, MAX_PATH);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return NULL;
-
-    /* Get the icon of the node */
-    INT iIcon = SHMapPIDLToSystemImageListIndex(psfParent, pEltRelative, NULL);
-
-    NodeInfo* pChildInfo = new NodeInfo;
-    if (!pChildInfo)
-    {
-        ERR("Failed to allocate NodeInfo\n");
-        return FALSE;
-    }
-
-    // Store our node info
-    pChildInfo->absolutePidl = ILClone(pElt);
-    pChildInfo->relativePidl = ILClone(pEltRelative);
-    pChildInfo->expanded = FALSE;
-
-    // Set up our treeview template
-    tvInsert.hParent = hParent;
-    tvInsert.hInsertAfter = TVI_LAST;
-    tvInsert.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | 
TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
-    tvInsert.item.cchTextMax = MAX_PATH;
-    tvInsert.item.pszText = wszDisplayName;
-    tvInsert.item.iImage = tvInsert.item.iSelectedImage = iIcon;
-    tvInsert.item.cChildren = (attrs & SFGAO_HASSUBFOLDER) ? 1 : 0;
-    tvInsert.item.lParam = (LPARAM)pChildInfo;
-
-    htiCreated = TreeView_InsertItem(m_hWnd, &tvInsert);
-
-    if (bSort)
-    {
-        TVSORTCB sortCallback;
-        sortCallback.hParent = hParent;
-        sortCallback.lpfnCompare = CompareTreeItems;
-        sortCallback.lParam = (LPARAM)(PVOID)m_pDesktop;
-        SendMessage(TVM_SORTCHILDRENCB, 0, (LPARAM)&sortCallback);
-    }
-
-    return htiCreated;
-}
-
-/* This is the slow version of the above method */
-HTREEITEM
-CExplorerBand::InsertItem(
-    _In_opt_ HTREEITEM hParent,
-    _In_ LPCITEMIDLIST pElt,
-    _In_ LPCITEMIDLIST pEltRelative,
-    _In_ BOOL bSort)
-{
-    CComPtr<IShellFolder> psfFolder;
-    HRESULT hr = SHBindToParent(pElt, IID_PPV_ARG(IShellFolder, &psfFolder), 
NULL);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return NULL;
-
-    return InsertItem(hParent, psfFolder, pElt, pEltRelative, bSort);
-}
-
-BOOL CExplorerBand::InsertSubitems(HTREEITEM hItem, NodeInfo *pNodeInfo)
-{
-    CComPtr<IEnumIDList>                pEnumIDList;
-    LPITEMIDLIST                        pidlSub;
-    LPITEMIDLIST                        entry;
-    SHCONTF                             EnumFlags;
-    HRESULT                             hr;
-    ULONG                               fetched;
-    ULONG                               uItemCount;
-    CComPtr<IShellFolder>               pFolder;
-    TVSORTCB                            sortCallback;
-
-    entry = pNodeInfo->absolutePidl;
-    fetched = 1;
-    uItemCount = 0;
-    EnumFlags = SHCONTF_FOLDERS;
-
-    hr = SHGetFolderLocation(m_hWnd, CSIDL_DESKTOP, NULL, 0, &pidlSub);
-    if (!SUCCEEDED(hr))
-    {
-        ERR("Can't get desktop PIDL !\n");
-        return FALSE;
-    }
-
-    if (!m_pDesktop->CompareIDs(NULL, pidlSub, entry))
-    {
-        // We are the desktop, so use pDesktop as pFolder
-        pFolder = m_pDesktop;
-    }
-    else
-    {
-        // Get an IShellFolder of our pidl
-        hr = m_pDesktop->BindToObject(entry, NULL, IID_PPV_ARG(IShellFolder, 
&pFolder));
-        if (!SUCCEEDED(hr))
-        {
-            ILFree(pidlSub);
-            ERR("Can't bind folder to desktop !\n");
-            return FALSE;
-        }
-    }
-    ILFree(pidlSub);
-
-    // TODO: handle hidden folders according to settings !
-    EnumFlags |= SHCONTF_INCLUDEHIDDEN;
-
-    // Enum through objects
-    hr = pFolder->EnumObjects(NULL,EnumFlags,&pEnumIDList);
-
-    // avoid broken IShellFolder implementations that return null pointer with 
success
-    if (!SUCCEEDED(hr) || !pEnumIDList)
-    {
-        ERR("Can't enum the folder !\n");
-        return FALSE;
-    }
-
-    /* Don't redraw while we add stuff into the tree */
-    SendMessage(WM_SETREDRAW, FALSE, 0);
-    while(SUCCEEDED(pEnumIDList->Next(1, &pidlSub, &fetched)) && pidlSub && 
fetched)
-    {
-        LPITEMIDLIST pidlSubComplete;
-        pidlSubComplete = ILCombine(entry, pidlSub);
-
-        if (InsertItem(hItem, pFolder, pidlSubComplete, pidlSub, FALSE))
-            uItemCount++;
-        ILFree(pidlSubComplete);
-        ILFree(pidlSub);
-    }
-    pNodeInfo->expanded = TRUE;
-    /* Let's do sorting */
-    sortCallback.hParent = hItem;
-    sortCallback.lpfnCompare = CompareTreeItems;
-    sortCallback.lParam = (LPARAM)(PVOID)m_pDesktop;
-    SendMessage(TVM_SORTCHILDRENCB, 0, (LPARAM)&sortCallback);
-
-    /* Now we can redraw */
-    SendMessage(WM_SETREDRAW, TRUE, 0);
-
-    return (uItemCount > 0) ? TRUE : FALSE;
-}
-
-/**
- * Navigate to a given PIDL in the treeview, and return matching tree item 
handle
- *  - dest: The absolute PIDL we should navigate in the treeview
- *  - item: Handle of the tree item matching the PIDL
- *  - bExpand: expand collapsed nodes in order to find the right element
- *  - bInsert: insert the element at the right place if we don't find it
- *  - bSelect: select the item after we found it
- */
-BOOL CExplorerBand::NavigateToPIDL(LPCITEMIDLIST dest, HTREEITEM *item, BOOL 
bExpand, BOOL bInsert,
-        BOOL bSelect)
-{
-    HTREEITEM                           current;
-    HTREEITEM                           tmp;
-    HTREEITEM                           parent;
-    NodeInfo                            *nodeData;
-    LPITEMIDLIST                        relativeChild;
-    TVITEM                              tvItem;
-
-    if (!item)
-        return FALSE;
-
-    current = m_hRoot;
-    parent = NULL;
-    while (TRUE)
-    {
-        nodeData = GetNodeInfo(current);
-        if (!nodeData)
-        {
-            ERR("Something has gone wrong, no data associated to node !\n");
-            *item = NULL;
-            return FALSE;
-        }
-        // If we found our node, give it back
-        if (!m_pDesktop->CompareIDs(0, nodeData->absolutePidl, dest))
-        {
-            if (bSelect)
-                TreeView_SelectItem(m_hWnd, current);
-            *item = current;
-            return TRUE;
-        }
-
-        // Check if we are a parent of the requested item
-        relativeChild = ILFindChild(nodeData->absolutePidl, dest);
-        if (relativeChild != 0)
-        {
-            // Notify treeview we have children
-            tvItem.mask = TVIF_CHILDREN;
-            tvItem.hItem = current;
-            tvItem.cChildren = 1;
-            TreeView_SetItem(m_hWnd, &tvItem);
-
-            // If we can expand and the node isn't expanded yet, do it
-            if (bExpand)
-            {
-                if (!nodeData->expanded)
-                    InsertSubitems(current, nodeData);
-                TreeView_Expand(m_hWnd, current, TVE_EXPAND);
-            }
-
-            // Try to get a child
-            tmp = TreeView_GetChild(m_hWnd, current);
-            if (tmp)
-            {
-                // We have a child, let's continue with it
-                parent = current;
-                current = tmp;
-                continue;
-            }
-
-            if (bInsert && nodeData->expanded)
-            {
-                // Happens when we have to create a subchild inside a child
-                current = InsertItem(current, dest, relativeChild, TRUE);
-            }
-            // We end up here, without any children, so we found nothing
-            // Tell the parent node it has children
-            ZeroMemory(&tvItem, sizeof(tvItem));
-            *item = NULL;
-            return FALSE;
-        }
-
-        // Find sibling
-        tmp = TreeView_GetNextSibling(m_hWnd, current);
-        if (tmp)
-        {
-            current = tmp;
-            continue;
-        }
-        if (bInsert)
-        {
-            current = InsertItem(parent, dest, ILFindLastID(dest), TRUE);
-            *item = current;
-            return TRUE;
-        }
-        *item = NULL;
-        return FALSE;
-    }
-    UNREACHABLE;
-}
-
-BOOL CExplorerBand::NavigateToCurrentFolder()
-{
-    LPITEMIDLIST                        explorerPidl;
-    HTREEITEM                           dummy;
-    BOOL                                result;
-
-    HRESULT hr = GetCurrentLocation(explorerPidl);
-    if (FAILED_UNEXPECTEDLY(hr))
-    {
-        ERR("Unable to get browser PIDL !\n");
-        return FALSE;
-    }
-    ++m_mtxBlockNavigate;
-    /* find PIDL into our explorer */
-    result = NavigateToPIDL(explorerPidl, &dummy, TRUE, FALSE, TRUE);
-    --m_mtxBlockNavigate;
-    ILFree(explorerPidl);
-    return result;
-}
-
-// *** Tree item sorting callback ***
-int CALLBACK CExplorerBand::CompareTreeItems(LPARAM p1, LPARAM p2, LPARAM p3)
-{
-    NodeInfo *info1 = (NodeInfo*)p1;
-    NodeInfo *info2 = (NodeInfo*)p2;
-    IShellFolder *pDesktop = (IShellFolder *)p3;
-
-    HRESULT hr = pDesktop->CompareIDs(0, info1->absolutePidl, 
info2->absolutePidl);
-    if (FAILED(hr))
-        return 0;
-
-    return (SHORT)HRESULT_CODE(hr);
-}
-
-// *** IOleWindow methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::GetWindow(HWND *lphwnd)
-{
-    if (!lphwnd)
-        return E_INVALIDARG;
-    *lphwnd = m_hWnd;
-    return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE CExplorerBand::ContextSensitiveHelp(BOOL fEnterMode)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-
-// *** IDockingWindow methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::CloseDW(DWORD dwReserved)
-{
-    // We do nothing, we don't have anything to save yet
-    TRACE("CloseDW called\n");
-    return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE CExplorerBand::ResizeBorderDW(const RECT *prcBorder, 
IUnknown *punkToolbarSite, BOOL fReserved)
-{
-    /* Must return E_NOTIMPL according to MSDN */
-    return E_NOTIMPL;
-}
-
-HRESULT STDMETHODCALLTYPE CExplorerBand::ShowDW(BOOL fShow)
-{
-    m_fVisible = fShow;
-    ShowWindow(fShow);
-    return S_OK;
 }
 
-
-// *** IDeskBand methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::GetBandInfo(DWORD dwBandID, DWORD 
dwViewMode, DESKBANDINFO *pdbi)
+STDMETHODIMP CExplorerBand::GetClassID(CLSID *pClassID)
 {
-    if (!pdbi)
-    {
-        return E_INVALIDARG;
-    }
-    this->m_dwBandID = dwBandID;
-
-    if (pdbi->dwMask & DBIM_MINSIZE)
-    {
-        pdbi->ptMinSize.x = 200;
-        pdbi->ptMinSize.y = 30;
-    }
-
-    if (pdbi->dwMask & DBIM_MAXSIZE)
-    {
-        pdbi->ptMaxSize.y = -1;
-    }
-
-    if (pdbi->dwMask & DBIM_INTEGRAL)
-    {
-        pdbi->ptIntegral.y = 1;
-    }
-
-    if (pdbi->dwMask & DBIM_ACTUAL)
-    {
-        pdbi->ptActual.x = 200;
-        pdbi->ptActual.y = 30;
-    }
-
-    if (pdbi->dwMask & DBIM_TITLE)
-    {
-        if (!LoadStringW(_AtlBaseModule.GetResourceInstance(), 
IDS_FOLDERSLABEL, pdbi->wszTitle, _countof(pdbi->wszTitle)))
-            return HRESULT_FROM_WIN32(GetLastError());
-    }
-
-    if (pdbi->dwMask & DBIM_MODEFLAGS)
-    {
-        pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
-    }
-
-    if (pdbi->dwMask & DBIM_BKCOLOR)
-    {
-        pdbi->dwMask &= ~DBIM_BKCOLOR;
-    }
+    if (!pClassID)
+        return E_POINTER;
+    *pClassID = CLSID_ExplorerBand;
     return S_OK;
 }
 
-
-// *** IObjectWithSite methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::SetSite(IUnknown *pUnkSite)
+INT CExplorerBand::_GetRootCsidl()
 {
-    HRESULT hr;
-    HWND parentWnd;
-
-    if (pUnkSite == m_pSite)
-        return S_OK;
-
-    TRACE("SetSite called \n");
-    if (!pUnkSite)
-    {
-        DestroyExplorerBand();
-        DestroyWindow();
-        m_hWnd = NULL;
-    }
-
-    if (pUnkSite != m_pSite)
-    {
-        m_pSite = NULL;
-    }
-
-    if(!pUnkSite)
-        return S_OK;
-
-    hr = IUnknown_GetWindow(pUnkSite, &parentWnd);
-    if (!SUCCEEDED(hr))
-    {
-        ERR("Could not get parent's window ! Status: %08lx\n", hr);
-        return E_INVALIDARG;
-    }
-
-    m_pSite = pUnkSite;
-
-    if (m_hWnd)
-    {
-        // Change its parent
-        SetParent(parentWnd);
-    }
-    else
-    {
-        HWND wnd = CreateWindow(WC_TREEVIEW, NULL,
-            WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TVS_HASLINES | 
TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_EDITLABELS /* | TVS_SINGLEEXPAND*/ , 
// remove TVS_SINGLEEXPAND for now since it has strange behaviour
-            0, 0, 0, 0, parentWnd, NULL, _AtlBaseModule.GetModuleInstance(), 
NULL);
-
-        // Subclass the window
-        SubclassWindow(wnd);
-
-        // Initialize our treeview now
-        InitializeExplorerBand();
-        RegisterDragDrop(m_hWnd, dynamic_cast<IDropTarget*>(this));
-    }
-    return S_OK;
+    return CSIDL_DESKTOP;
 }
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::GetSite(REFIID riid, void **ppvSite)
+DWORD CExplorerBand::_GetTVStyle()
 {
-    if (!ppvSite)
-        return E_POINTER;
-    *ppvSite = m_pSite;
-    return S_OK;
+    // Remove TVS_SINGLEEXPAND for now since it has strange behaviour
+    return WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | 
TVS_HASLINES |
+           TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_EDITLABELS /* | 
TVS_SINGLEEXPAND*/;
 }
 
-
-// *** IOleCommandTarget methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::QueryStatus(const GUID 
*pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
+DWORD CExplorerBand::_GetTVExStyle()
 {
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
+    return 0;
 }
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::Exec(const GUID *pguidCmdGroup, DWORD 
nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
+DWORD CExplorerBand::_GetEnumFlags()
 {
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
+    return SHCONTF_FOLDERS;
 }
 
-
-// *** IServiceProvider methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::QueryService(REFGUID guidService, 
REFIID riid, void **ppvObject)
+BOOL CExplorerBand::_GetTitle(LPWSTR pszTitle, INT cchTitle)
 {
-    /* FIXME: we probably want to handle more services here */
-    return IUnknown_QueryService(m_pSite, SID_SShellBrowser, riid, ppvObject);
+    return ::LoadStringW(instance, IDS_FOLDERSLABEL, pszTitle, cchTitle);
 }
 
-
-// *** IInputObject methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::UIActivateIO(BOOL fActivate, LPMSG 
lpMsg)
+BOOL CExplorerBand::_WantsRootItem()
 {
-    if (fActivate)
-    {
-        //SetFocus();
-        SetActiveWindow();
-    }
-    // TODO: handle message
-    if(lpMsg)
-    {
-        TranslateMessage(lpMsg);
-        DispatchMessage(lpMsg);
-    }
-    return S_OK;
+    return TRUE;
 }
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::HasFocusIO()
+// Called when the user has selected an item.
+STDMETHODIMP CExplorerBand::OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl)
 {
-    return m_bFocused ? S_OK : S_FALSE;
+    return Invoke(pidl);
 }
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::TranslateAcceleratorIO(LPMSG lpMsg)
+// Handles a user action on an item.
+STDMETHODIMP CExplorerBand::Invoke(_In_ PCIDLIST_ABSOLUTE pidl)
 {
-    if (lpMsg->hwnd == m_hWnd ||
-        (m_isEditing && IsChild(lpMsg->hwnd)))
-    {
-        TranslateMessage(lpMsg);
-        DispatchMessage(lpMsg);
+    /* Prevents navigation if selection is initiated inside the band */
+    if (m_mtxBlockNavigate)
         return S_OK;
-    }
-
-    return S_FALSE;
-}
 
-// *** IPersist methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::GetClassID(CLSID *pClassID)
-{
-    if (!pClassID)
-        return E_POINTER;
-    memcpy(pClassID, &CLSID_ExplorerBand, sizeof(CLSID));
+    _UpdateBrowser(pidl);
+    m_hwndTreeView.SetFocus();
     return S_OK;
 }
 
-
-// *** IPersistStream methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::IsDirty()
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-HRESULT STDMETHODCALLTYPE CExplorerBand::Load(IStream *pStm)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-HRESULT STDMETHODCALLTYPE CExplorerBand::Save(IStream *pStm, BOOL fClearDirty)
+void CExplorerBand::_SortItems(HTREEITEM hParent)
 {
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
+    TVSORTCB sortCallback;
+    sortCallback.hParent = hParent;
+    sortCallback.lpfnCompare = _CompareTreeItems;
+    sortCallback.lParam = (LPARAM)(PVOID)m_pDesktop; // m_pDesktop is not a 
pointer
+    TreeView_SortChildrenCB(m_hwndTreeView, &sortCallback, 0);
 }
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
+INT CALLBACK CExplorerBand::_CompareTreeItems(LPARAM p1, LPARAM p2, LPARAM p3)
 {
-    // TODO: calculate max size
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
+    CItemData *info1 = (CItemData*)p1;
+    CItemData *info2 = (CItemData*)p2;
+    IShellFolder *pDesktop = (IShellFolder *)p3;
+    HRESULT hr = pDesktop->CompareIDs(0, info1->absolutePidl, 
info2->absolutePidl);
+    if (FAILED(hr))
+        return 0;
+    return (SHORT)HRESULT_CODE(hr);
 }
 
-// *** IWinEventHandler methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::OnWinEvent(HWND hWnd, UINT uMsg, 
WPARAM wParam, LPARAM lParam, LRESULT *theResult)
+HRESULT CExplorerBand::_CreateTreeView(HWND hwndParent)
 {
-    BOOL bHandled;
-    LRESULT result;
+    HRESULT hr = CNSCBand::_CreateTreeView(hwndParent);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
-    if (uMsg == WM_NOTIFY)
+    // Insert the root node
+    m_hRoot = _InsertItem(NULL, m_pDesktop, m_pidlRoot, m_pidlRoot, FALSE);
+    if (!m_hRoot)
     {
-        NMHDR *pNotifyHeader = (NMHDR*)lParam;
-        switch (pNotifyHeader->code)
-        {
-            case TVN_ITEMEXPANDING:
-                result = OnTreeItemExpanding((LPNMTREEVIEW)lParam);
-                if (theResult)
-                    *theResult = result;
-                break;
-            case TVN_SELCHANGED:
-                OnSelectionChanged((LPNMTREEVIEW)lParam);
-                break;
-            case TVN_DELETEITEM:
-                OnTreeItemDeleted((LPNMTREEVIEW)lParam);
-                break;
-            case NM_RCLICK:
-                OnContextMenu(WM_CONTEXTMENU, (WPARAM)m_hWnd, GetMessagePos(), 
bHandled);
-                if (theResult)
-                    *theResult = 1;
-                break;
-            case TVN_BEGINDRAG:
-            case TVN_BEGINRDRAG:
-                OnTreeItemDragging((LPNMTREEVIEW)lParam, pNotifyHeader->code 
== TVN_BEGINRDRAG);
-                break;
-            case TVN_BEGINLABELEDITW:
-            {
-                // TODO: put this in a function ? (mostly copypasta from 
CDefView)
-                DWORD dwAttr = SFGAO_CANRENAME;
-                LPNMTVDISPINFO dispInfo = (LPNMTVDISPINFO)lParam;
-                CComPtr<IShellFolder> pParent;
-                LPCITEMIDLIST pChild;
-                HRESULT hr;
-
-                if (theResult)
-                    *theResult = 1;
-                NodeInfo *info = GetNodeInfo(dispInfo->item.hItem);
-                if (!info)
-                    return E_FAIL;
-                hr = SHBindToParent(info->absolutePidl, 
IID_PPV_ARG(IShellFolder, &pParent), &pChild);
-                if (!SUCCEEDED(hr) || !pParent.p)
-                    return E_FAIL;
-
-                hr = pParent->GetAttributesOf(1, &pChild, &dwAttr);
-                if (SUCCEEDED(hr) && (dwAttr & SFGAO_CANRENAME))
-                {
-                    if (theResult)
-                        *theResult = 0;
-                    m_isEditing = TRUE;
-                    m_oldSelected = NULL;
-                }
-                return S_OK;
-            }
-            case TVN_ENDLABELEDITW:
-            {
-                LPNMTVDISPINFO dispInfo = (LPNMTVDISPINFO)lParam;
-                NodeInfo *info = GetNodeInfo(dispInfo->item.hItem);
-                HRESULT hr;
-
-                m_isEditing = FALSE;
-                if (m_oldSelected)
-                {
-                    ++m_mtxBlockNavigate;
-                    TreeView_SelectItem(m_hWnd, m_oldSelected);
-                    --m_mtxBlockNavigate;
-                }
-
-                if (theResult)
-                    *theResult = 0;
-                if (dispInfo->item.pszText)
-                {
-                    LPITEMIDLIST pidlNew;
-                    CComPtr<IShellFolder> pParent;
-                    LPCITEMIDLIST pidlChild;
-                    BOOL RenamedCurrent = 
IsCurrentLocation(info->absolutePidl) == S_OK;
-
-                    hr = SHBindToParent(info->absolutePidl, 
IID_PPV_ARG(IShellFolder, &pParent), &pidlChild);
-                    if (!SUCCEEDED(hr) || !pParent.p)
-                        return E_FAIL;
-
-                    hr = pParent->SetNameOf(m_hWnd, pidlChild, 
dispInfo->item.pszText, SHGDN_INFOLDER, &pidlNew);
-                    if(SUCCEEDED(hr) && pidlNew)
-                    {
-                        CComPtr<IPersistFolder2> pPersist;
-                        LPITEMIDLIST pidlParent, pidlNewAbs;
-
-                        hr = 
pParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pPersist));
-                        if(!SUCCEEDED(hr))
-                            return E_FAIL;
-
-                        hr = pPersist->GetCurFolder(&pidlParent);
-                        if(!SUCCEEDED(hr))
-                            return E_FAIL;
-                        pidlNewAbs = ILCombine(pidlParent, pidlNew);
-
-                        if (RenamedCurrent)
-                        {
-                            // Navigate to our new location
-                            UpdateBrowser(pidlNewAbs);
-                        }
-                        else
-                        {
-                            // Tell everyone in case SetNameOf forgot, this 
causes IShellView to update itself when we renamed a child
-                            SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_IDLIST, 
info->absolutePidl, pidlNewAbs);
-                        }
-
-                        ILFree(pidlParent);
-                        ILFree(pidlNewAbs);
-                        ILFree(pidlNew);
-                        if (theResult)
-                            *theResult = 1;
-                    }
-                    return S_OK;
-                }
-            }
-            default:
-                break;
-        }
+        ERR("Failed to create root item\n");
+        return E_FAIL;
     }
-    return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE CExplorerBand::IsWindowOwner(HWND hWnd)
-{
-    return (hWnd == m_hWnd) ? S_OK : S_FALSE;
-}
+    TreeView_Expand(m_hwndTreeView, m_hRoot, TVE_EXPAND);
 
-// *** IBandNavigate methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::Select(long paramC)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
+    // Navigate to current folder position
+    _NavigateToCurrentFolder();
 
-// *** INamespaceProxy ***
+    // Register browser connection endpoint
+    CComPtr<IWebBrowser2> browserService;
+    hr = IUnknown_QueryService(m_pSite, SID_SWebBrowserApp, 
IID_PPV_ARG(IWebBrowser2, &browserService));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
-/// Returns the ITEMIDLIST that should be navigated when an item is invoked.
-STDMETHODIMP CExplorerBand::GetNavigateTarget(
-    _In_ PCIDLIST_ABSOLUTE pidl,
-    _Out_ PIDLIST_ABSOLUTE ppidlTarget,
-    _Out_ ULONG *pulAttrib)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
+    // Communicate via IDispatch
+    hr = AtlAdvise(browserService, dynamic_cast<IDispatch*>(this), 
DIID_DWebBrowserEvents, &m_adviseCookie);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
-/// Handles a user action on an item.
-STDMETHODIMP CExplorerBand::Invoke(_In_ PCIDLIST_ABSOLUTE pidl)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
+    return hr;
 }
 
-/// Called when the user has selected an item.
-STDMETHODIMP CExplorerBand::OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl)
+void CExplorerBand::_DestroyTreeView()
 {
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
+    CComPtr<IWebBrowser2> browserService;
+    HRESULT hr = IUnknown_QueryService(m_pSite, SID_SWebBrowserApp,
+                                       IID_PPV_ARG(IWebBrowser2, 
&browserService));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return;
 
-/// Returns flags used to update the tree control.
-STDMETHODIMP CExplorerBand::RefreshFlags(
-    _Out_ DWORD *pdwStyle,
-    _Out_ DWORD *pdwExStyle,
-    _Out_ DWORD *dwEnum)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
+    AtlUnadvise(browserService, DIID_DWebBrowserEvents, m_adviseCookie);
 
-STDMETHODIMP CExplorerBand::CacheItem(_In_ PCIDLIST_ABSOLUTE pidl)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
+    CNSCBand::_DestroyTreeView();
 }
 
 // *** IDispatch methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::GetTypeInfoCount(UINT *pctinfo)
+
+STDMETHODIMP CExplorerBand::GetTypeInfoCount(UINT *pctinfo)
 {
     UNIMPLEMENTED;
     return E_NOTIMPL;
 }
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::GetTypeInfo(UINT iTInfo, LCID lcid, 
ITypeInfo **ppTInfo)
+STDMETHODIMP CExplorerBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo 
**ppTInfo)
 {
     UNIMPLEMENTED;
     return E_NOTIMPL;
 }
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::GetIDsOfNames(REFIID riid, LPOLESTR 
*rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+STDMETHODIMP CExplorerBand::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, 
UINT cNames, LCID lcid, DISPID *rgDispId)
 {
     UNIMPLEMENTED;
     return E_NOTIMPL;
 }
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::Invoke(DISPID dispIdMember, REFIID 
riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, 
EXCEPINFO *pExcepInfo, UINT *puArgErr)
+STDMETHODIMP
+CExplorerBand::Invoke(
+    DISPID dispIdMember,
+    REFIID riid,
+    LCID lcid,
+    WORD wFlags,
+    DISPPARAMS *pDispParams,
+    VARIANT *pVarResult,
+    EXCEPINFO *pExcepInfo,
+    UINT *puArgErr)
 {
     switch (dispIdMember)
     {
         case DISPID_DOWNLOADCOMPLETE:
         case DISPID_NAVIGATECOMPLETE2:
-           TRACE("DISPID_NAVIGATECOMPLETE2 received\n");
-           NavigateToCurrentFolder();
-           return S_OK;
+        {
+            TRACE("dispId %d received\n", dispIdMember);
+            _NavigateToCurrentFolder();
+            return S_OK;
+        }
     }
     TRACE("Unknown dispid requested: %08x\n", dispIdMember);
     return E_INVALIDARG;
 }
 
-// *** IDropTarget methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::DragEnter(IDataObject *pObj, DWORD 
glfKeyState, POINTL pt, DWORD *pdwEffect)
+BOOL CExplorerBand::_NavigateToCurrentFolder()
 {
-    ERR("Entering drag\n");
-    m_pCurObject = pObj;
-    m_oldSelected = TreeView_GetSelection(m_hWnd);
-    return DragOver(glfKeyState, pt, pdwEffect);
-}
+    CComHeapPtr<ITEMIDLIST> pidl;
+    HRESULT hr = _GetCurrentLocation(&pidl);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return FALSE;
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::DragOver(DWORD glfKeyState, POINTL 
pt, DWORD *pdwEffect)
-{
-    TVHITTESTINFO                           info;
-    CComPtr<IShellFolder>                   pShellFldr;
-    NodeInfo                                *nodeInfo;
-    //LPCITEMIDLIST                         pChild;
-    HRESULT                                 hr;
+    // Find PIDL into our explorer
+    ++m_mtxBlockNavigate;
+    HTREEITEM hItem;
+    BOOL result = _NavigateToPIDL(pidl, &hItem, TRUE, FALSE, TRUE);
+    --m_mtxBlockNavigate;
+
+    return result;
+}
 
-    info.pt.x = pt.x;
-    info.pt.y = pt.y;
-    info.flags = TVHT_ONITEM;
-    info.hItem = NULL;
-    ScreenToClient(&info.pt);
+/**
+ * Navigate to a given PIDL in the treeview, and return matching tree item 
handle
+ *  - dest: The absolute PIDL we should navigate in the treeview
+ *  - item: Handle of the tree item matching the PIDL
+ *  - bExpand: expand collapsed nodes in order to find the right element
+ *  - bInsert: insert the element at the right place if we don't find it
+ *  - bSelect: select the item after we found it
+ */
+BOOL
+CExplorerBand::_NavigateToPIDL(
+    _In_ LPCITEMIDLIST dest,
+    _Out_ HTREEITEM *phItem,
+    _In_ BOOL bExpand,
+    _In_ BOOL bInsert,
+    _In_ BOOL bSelect)
+{
+    if (!phItem)
+        return FALSE;
 
-    // Move to the item selected by the treeview (don't change right pane)
-    TreeView_HitTest(m_hWnd, &info);
+    *phItem = NULL;
 
-    if (info.hItem)
+    HTREEITEM hItem = TreeView_GetFirstVisible(m_hwndTreeView);
+    HTREEITEM hParent = NULL, tmp;
+    while (TRUE)
     {
-        ++m_mtxBlockNavigate;
-        TreeView_SelectItem(m_hWnd, info.hItem);
-        --m_mtxBlockNavigate;
-        // Delegate to shell folder
-        if (m_pDropTarget && info.hItem != m_childTargetNode)
+        CItemData *pItemData = GetItemData(hItem);
+        if (!pItemData)
+        {
+            ERR("Something has gone wrong, no data associated to node\n");
+            return FALSE;
+        }
+
+        // If we found our node, give it back
+        if (!m_pDesktop->CompareIDs(0, pItemData->absolutePidl, dest))
         {
-            m_pDropTarget = NULL;
+            if (bSelect)
+                TreeView_SelectItem(m_hwndTreeView, hItem);
+            *phItem = hItem;
+            return TRUE;
         }
-        if (info.hItem != m_childTargetNode)
+
+        // Check if we are a parent of the requested item
+        TVITEMW tvItem;
+        LPITEMIDLIST relativeChild = ILFindChild(pItemData->absolutePidl, 
dest);
+        if (relativeChild)
         {
-            nodeInfo = GetNodeInfo(info.hItem);
-            if (!nodeInfo)
-                return E_FAIL;
-#if 0
-            hr = SHBindToParent(nodeInfo->absolutePidl, 
IID_PPV_ARG(IShellFolder, &pShellFldr), &pChild);
-            if (!SUCCEEDED(hr))
-                return E_FAIL;
-            hr = pShellFldr->GetUIObjectOf(m_hWnd, 1, &pChild, 
IID_IDropTarget, NULL, reinterpret_cast<void**>(&pDropTarget));
-            if (!SUCCEEDED(hr))
-                return E_FAIL;
-#endif
-            if(_ILIsDesktop(nodeInfo->absolutePidl))
-                pShellFldr = m_pDesktop;
-            else
+            // Notify treeview we have children
+            tvItem.mask = TVIF_CHILDREN;
+            tvItem.hItem = hItem;
+            tvItem.cChildren = 1;
+            TreeView_SetItem(m_hwndTreeView, &tvItem);
+
+            // If we can expand and the node isn't expanded yet, do it
+            if (bExpand)
             {
-                hr = m_pDesktop->BindToObject(nodeInfo->absolutePidl, 0, 
IID_PPV_ARG(IShellFolder, &pShellFldr));
-                if (!SUCCEEDED(hr))
+                if (!pItemData->expanded)
                 {
-                    /* Don't allow dnd since we couldn't get our folder object 
*/
-                    ERR("Can't bind to folder object\n");
-                    *pdwEffect = DROPEFFECT_NONE;
-                    return E_FAIL;
+                    _InsertSubitems(hItem, pItemData->absolutePidl);
+                    pItemData->expanded = TRUE;
                 }
+                TreeView_Expand(m_hwndTreeView, hItem, TVE_EXPAND);
+            }
+
+            // Try to get a child
+            tmp = TreeView_GetChild(m_hwndTreeView, hItem);
+            if (tmp)
+            {
+                // We have a child, let's continue with it
+                hParent = hItem;
+                hItem = tmp;
+                continue;
             }
-            hr = pShellFldr->CreateViewObject(m_hWnd, IID_PPV_ARG(IDropTarget, 
&m_pDropTarget));
-            if (!SUCCEEDED(hr))
+
+            if (bInsert && pItemData->expanded)
             {
-                /* Don't allow dnd since we couldn't get our drop target */
-                ERR("Can't get drop target for folder object\n");
-                *pdwEffect = DROPEFFECT_NONE;
-                return E_FAIL;
+                // Happens when we have to create a subchild inside a child
+                hItem = _InsertItem(hItem, dest, relativeChild, TRUE);
             }
-            hr = m_pDropTarget->DragEnter(m_pCurObject, glfKeyState, pt, 
pdwEffect);
-            m_childTargetNode = info.hItem;
+
+            // We end up here, without any children, so we found nothing
+            // Tell the parent node it has children
+            ZeroMemory(&tvItem, sizeof(tvItem));
+            return FALSE;
         }
-        if (m_pDropTarget)
+
+        // Find sibling
+        tmp = TreeView_GetNextSibling(m_hwndTreeView, hItem);
+        if (tmp)
         {
-            hr = m_pDropTarget->DragOver(glfKeyState, pt, pdwEffect);
+            hItem = tmp;
+            continue;
         }
-    }
-    else
-    {
-        m_childTargetNode = NULL;
-        m_pDropTarget = NULL;
-        *pdwEffect = DROPEFFECT_NONE;
-    }
-    return S_OK;
-}
-
-HRESULT STDMETHODCALLTYPE CExplorerBand::DragLeave()
-{
-    ++m_mtxBlockNavigate;
-    TreeView_SelectItem(m_hWnd, m_oldSelected);
-    --m_mtxBlockNavigate;
-    m_childTargetNode = NULL;
-    if (m_pCurObject)
-    {
-        m_pCurObject = NULL;
-    }
-    return S_OK;
-}
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::Drop(IDataObject *pObj, DWORD 
glfKeyState, POINTL pt, DWORD *pdwEffect)
-{
-    if (!m_pDropTarget)
-        return E_FAIL;
-    m_pDropTarget->Drop(pObj, glfKeyState, pt, pdwEffect);
-    DragLeave();
-    return S_OK;
-}
+        if (bInsert)
+        {
+            *phItem = hItem = _InsertItem(hParent, dest, ILFindLastID(dest), 
TRUE);
+            return TRUE;
+        }
 
-// *** IDropSource methods ***
-HRESULT STDMETHODCALLTYPE CExplorerBand::QueryContinueDrag(BOOL 
fEscapePressed, DWORD grfKeyState)
-{
-    if (fEscapePressed)
-        return DRAGDROP_S_CANCEL;
-    if ((grfKeyState & MK_LBUTTON) || (grfKeyState & MK_RBUTTON))
-        return S_OK;
-    return DRAGDROP_S_DROP;
-}
+        return FALSE;
+    }
 
-HRESULT STDMETHODCALLTYPE CExplorerBand::GiveFeedback(DWORD dwEffect)
-{
-    return DRAGDROP_S_USEDEFAULTCURSORS;
+    UNREACHABLE;
 }
diff --git a/dll/win32/shdocvw/CExplorerBand.h 
b/dll/win32/shdocvw/CExplorerBand.h
index 5c307deacce..6a2597605f8 100644
--- a/dll/win32/shdocvw/CExplorerBand.h
+++ b/dll/win32/shdocvw/CExplorerBand.h
@@ -8,185 +8,27 @@
 
 #pragma once
 
-#define WM_USER_SHELLEVENT (WM_USER + 88)
+#include "CNSCBand.h"
 
-class CExplorerBand :
-    public CComCoClass<CExplorerBand, &CLSID_ExplorerBand>,
-    public CComObjectRootEx<CComMultiThreadModelNoCS>,
-    public IDeskBand,
-    public IObjectWithSite,
-    public IInputObject,
-    public IPersistStream,
-    public IOleCommandTarget,
-    public IServiceProvider,
-    public IBandNavigate,
-    public IWinEventHandler,
-    public INamespaceProxy,
-    public IDispatch,
-    public IDropSource,
-    public IDropTarget,
-    public CWindowImpl<CExplorerBand, CWindow, CControlWinTraits>
+class CExplorerBand
+    : public CNSCBand
+    , public CComCoClass<CExplorerBand, &CLSID_ExplorerBand>
+    , public CComObjectRootEx<CComMultiThreadModelNoCS>
+    , public IDispatch
 {
-private:
-    class NodeInfo
-    {
-    public:
-        LPITEMIDLIST absolutePidl;
-        LPITEMIDLIST relativePidl;
-        BOOL expanded;
-    };
-
-    // *** BaseBarSite information ***
-    CComPtr<IUnknown> m_pSite;
-    CComPtr<IShellFolder> m_pDesktop;
-
-    // *** tree explorer band stuff ***
-    BOOL m_fVisible;
-    BYTE m_mtxBlockNavigate; // A "lock" that prevents internal selection 
changes to initiate a navigation to the newly selected item.
-    BOOL m_bFocused;
-    DWORD m_dwBandID;
-    BOOL m_isEditing;
-    HIMAGELIST m_hImageList;
-    HTREEITEM  m_hRoot;
-    HTREEITEM  m_oldSelected;
-    LPITEMIDLIST m_pidlCurrent; // Note: This is NULL until the first user 
navigation!
-
-    // *** notification cookies ***
-    DWORD m_adviseCookie;
-    ULONG m_shellRegID;
-
-    // *** Drop target information ***
-    CComPtr<IDropTarget> m_pDropTarget;
-    HTREEITEM m_childTargetNode;
-    CComPtr<IDataObject> m_pCurObject;
-
-    void InitializeExplorerBand();
-    void DestroyExplorerBand();
-    HRESULT ExecuteCommand(CComPtr<IContextMenu>& menu, UINT nCmd);
-
-    // *** notifications handling ***
-    BOOL OnTreeItemExpanding(LPNMTREEVIEW pnmtv);
-    void OnSelectionChanged(LPNMTREEVIEW pnmtv);
-    BOOL OnTreeItemDeleted(LPNMTREEVIEW pnmtv);
-    void OnTreeItemDragging(LPNMTREEVIEW pnmtv, BOOL isRightClick);
-
-    // *** ATL event handlers ***
-    LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
-    LRESULT ContextMenuHack(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
-    LRESULT OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
-    LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
-    LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
-    LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
-
-    // *** Helper functions ***
-    NodeInfo* GetNodeInfo(HTREEITEM hItem);
-    HRESULT UpdateBrowser(LPITEMIDLIST pidlGoto);
-    HTREEITEM InsertItem(
-        _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 NavigateToPIDL(LPCITEMIDLIST dest, HTREEITEM *item, BOOL bExpand, 
BOOL bInsert, BOOL bSelect);
-    BOOL NavigateToCurrentFolder();
-    HRESULT GetCurrentLocation(PIDLIST_ABSOLUTE &pidl);
-    HRESULT IsCurrentLocation(PCIDLIST_ABSOLUTE pidl);
-    void OnChangeNotify(
-        _In_opt_ LPCITEMIDLIST pidl0,
-        _In_opt_ LPCITEMIDLIST pidl1,
-        _In_ LONG lEvent);
-    void Refresh();
-    void RefreshRecurse(_In_ HTREEITEM hItem);
-    BOOL IsTreeItemInEnum(_In_ HTREEITEM hItem, _In_ IEnumIDList *pEnum);
-    BOOL TreeItemHasThisChild(_In_ HTREEITEM hItem, _In_ PCITEMID_CHILD 
pidlChild);
-    HRESULT GetItemEnum(_Out_ CComPtr<IEnumIDList>& pEnum, _In_ HTREEITEM 
hItem);
-    BOOL ItemHasAnyChild(_In_ HTREEITEM hItem);
-
-    // *** Tree item sorting callback ***
-    static int CALLBACK CompareTreeItems(LPARAM p1, LPARAM p2, LPARAM p3);
-
 public:
     CExplorerBand();
     virtual ~CExplorerBand();
 
-    // *** IOleWindow methods ***
-    STDMETHOD(GetWindow)(HWND *lphwnd) override;
-    STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) override;
-
-    // *** IDockingWindow methods ***
-    STDMETHOD(CloseDW)(DWORD dwReserved) override;
-    STDMETHOD(ResizeBorderDW)(const RECT *prcBorder, IUnknown 
*punkToolbarSite, BOOL fReserved) override;
-    STDMETHOD(ShowDW)(BOOL fShow) override;
-
-    // *** IDeskBand methods ***
-    STDMETHOD(GetBandInfo)(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO 
*pdbi) override;
-
-    // *** IObjectWithSite methods ***
-    STDMETHOD(SetSite)(IUnknown *pUnkSite) override;
-    STDMETHOD(GetSite)(REFIID riid, void **ppvSite) override;
-
-    // *** IOleCommandTarget methods ***
-    STDMETHOD(QueryStatus)(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD 
prgCmds [], OLECMDTEXT *pCmdText) override;
-    STDMETHOD(Exec)(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD 
nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) override;
-
-    // *** IServiceProvider methods ***
-    STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void 
**ppvObject) override;
-
-    // *** IInputObject methods ***
-    STDMETHOD(UIActivateIO)(BOOL fActivate, LPMSG lpMsg) override;
-    STDMETHOD(HasFocusIO)() override;
-    STDMETHOD(TranslateAcceleratorIO)(LPMSG lpMsg) override;
-
-    // *** IPersist methods ***
-    STDMETHOD(GetClassID)(CLSID *pClassID) override;
-
-    // *** IPersistStream methods ***
-    STDMETHOD(IsDirty)() override;
-    STDMETHOD(Load)(IStream *pStm) override;
-    STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty) override;
-    STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize) override;
-
-    // *** IWinEventHandler methods ***
-    STDMETHOD(OnWinEvent)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, 
LRESULT *theResult) override;
-    STDMETHOD(IsWindowOwner)(HWND hWnd) override;
-
-    // *** IBandNavigate methods ***
-    STDMETHOD(Select)(long paramC) override;
-
-    // *** INamespaceProxy ***
-    STDMETHOD(GetNavigateTarget)(
-        _In_ PCIDLIST_ABSOLUTE pidl,
-        _Out_ PIDLIST_ABSOLUTE ppidlTarget,
-        _Out_ ULONG *pulAttrib) override;
-    STDMETHOD(Invoke)(_In_ PCIDLIST_ABSOLUTE pidl) override;
-    STDMETHOD(OnSelectionChanged)(_In_ PCIDLIST_ABSOLUTE pidl) override;
-    STDMETHOD(RefreshFlags)(
-        _Out_ DWORD *pdwStyle,
-        _Out_ DWORD *pdwExStyle,
-        _Out_ DWORD *dwEnum) override;
-    STDMETHOD(CacheItem)(_In_ PCIDLIST_ABSOLUTE pidl) override;
+    STDMETHODIMP GetClassID(CLSID *pClassID) override;
+    STDMETHODIMP OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl) override;
+    STDMETHODIMP Invoke(_In_ PCIDLIST_ABSOLUTE pidl) override;
 
     // *** IDispatch methods ***
-    STDMETHOD(GetTypeInfoCount)(UINT *pctinfo) override;
-    STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) 
override;
-    STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR *rgszNames, UINT cNames, 
LCID lcid, DISPID *rgDispId) override;
-    STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD 
wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, 
UINT *puArgErr) override;
-
-    // *** IDropTarget methods ***
-    STDMETHOD(DragEnter)(IDataObject *pObj, DWORD glfKeyState, POINTL pt, 
DWORD *pdwEffect) override;
-    STDMETHOD(DragOver)(DWORD glfKeyState, POINTL pt, DWORD *pdwEffect) 
override;
-    STDMETHOD(DragLeave)() override;
-    STDMETHOD(Drop)(IDataObject *pObj, DWORD glfKeyState, POINTL pt, DWORD 
*pdwEffect) override;
-
-    // *** IDropSource methods ***
-    STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState) 
override;
-    STDMETHOD(GiveFeedback)(DWORD dwEffect) override;
+    STDMETHODIMP GetTypeInfoCount(UINT *pctinfo) override;
+    STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) 
override;
+    STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, 
LCID lcid, DISPID *rgDispId) override;
+    STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD 
wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, 
UINT *puArgErr) override;
 
     DECLARE_REGISTRY_RESOURCEID(IDR_EXPLORERBAND)
     DECLARE_NOT_AGGREGATABLE(CExplorerBand)
@@ -194,27 +36,39 @@ public:
     DECLARE_PROTECT_FINAL_CONSTRUCT()
 
     BEGIN_COM_MAP(CExplorerBand)
-        COM_INTERFACE_ENTRY_IID(IID_IDispatch, IDispatch)
-        COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
-        COM_INTERFACE_ENTRY_IID(IID_IBandNavigate, IBandNavigate)
-        COM_INTERFACE_ENTRY_IID(IID_INamespaceProxy, INamespaceProxy)
-        COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDeskBand)
-        COM_INTERFACE_ENTRY2_IID(IID_IDockingWindow, IDockingWindow, IDeskBand)
         COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
+        COM_INTERFACE_ENTRY2_IID(IID_IDockingWindow, IDockingWindow, IDeskBand)
+        COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDeskBand)
         COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
-        COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
-        COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
         COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
-        COM_INTERFACE_ENTRY2_IID(IID_IPersist, IPersist, IPersistStream)
         COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
+        COM_INTERFACE_ENTRY2_IID(IID_IPersist, IPersist, IPersistStream)
+        COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
+        COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
+        COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
+        COM_INTERFACE_ENTRY_IID(IID_IBandNavigate, IBandNavigate)
+        COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
+        COM_INTERFACE_ENTRY_IID(IID_INamespaceProxy, INamespaceProxy)
+        COM_INTERFACE_ENTRY_IID(IID_IDispatch, IDispatch)
+        COM_INTERFACE_ENTRY2_IID(IID_IUnknown, IUnknown, IDispatch)
     END_COM_MAP()
 
-    BEGIN_MSG_MAP(CExplorerBand)
-        MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
-        MESSAGE_HANDLER(WM_USER_SHELLEVENT, OnShellEvent)
-        MESSAGE_HANDLER(WM_RBUTTONDOWN, ContextMenuHack)
-        MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
-        MESSAGE_HANDLER(WM_TIMER, OnTimer)
-        // MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
-    END_MSG_MAP()
+protected:
+    INT _GetRootCsidl() override;
+    DWORD _GetTVStyle() override;
+    DWORD _GetTVExStyle() override;
+    DWORD _GetEnumFlags() override;
+    HRESULT _CreateTreeView(HWND hwndParent) override;
+    void _DestroyTreeView() override;
+    BOOL _WantsRootItem() override;
+    BOOL _GetTitle(LPWSTR pszTitle, INT cchTitle) override;
+    void _SortItems(HTREEITEM hParent) override;
+    BOOL _NavigateToCurrentFolder();
+    BOOL _NavigateToPIDL(
+        _In_ LPCITEMIDLIST dest,
+        _Out_ HTREEITEM *phItem,
+        _In_ BOOL bExpand,
+        _In_ BOOL bInsert,
+        _In_ BOOL bSelect);
+    static INT CALLBACK _CompareTreeItems(LPARAM p1, LPARAM p2, LPARAM p3); // 
Used by _SortItems
 };
diff --git a/dll/win32/shdocvw/CFavBand.cpp b/dll/win32/shdocvw/CFavBand.cpp
index bc00c3943bb..b79f2e27be2 100644
--- a/dll/win32/shdocvw/CFavBand.cpp
+++ b/dll/win32/shdocvw/CFavBand.cpp
@@ -11,40 +11,64 @@
 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
 
 CFavBand::CFavBand()
-    : m_fVisible(FALSE)
-    , m_bFocused(FALSE)
-    , m_dwBandID(0)
-    , m_hToolbarImageList(NULL)
-    , m_hTreeViewImageList(NULL)
 {
-    SHDOCVW_LockModule();
-    SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &m_pidlFav);
 }
 
 CFavBand::~CFavBand()
 {
-    if (m_hToolbarImageList)
-    {
-        ImageList_Destroy(m_hToolbarImageList);
-        m_hToolbarImageList = NULL;
-    }
-    if (m_hTreeViewImageList)
+}
+
+STDMETHODIMP CFavBand::GetClassID(CLSID *pClassID)
+{
+    if (!pClassID)
+        return E_POINTER;
+    *pClassID = CLSID_SH_FavBand;
+    return S_OK;
+}
+
+INT CFavBand::_GetRootCsidl()
+{
+    return CSIDL_FAVORITES;
+}
+
+DWORD CFavBand::_GetTVStyle()
+{
+    // Remove TVS_SINGLEEXPAND for now since it has strange behaviour
+    return TVS_NOHSCROLL | TVS_NONEVENHEIGHT | TVS_FULLROWSELECT | TVS_INFOTIP 
|
+           /*TVS_SINGLEEXPAND | TVS_TRACKSELECT |*/ TVS_SHOWSELALWAYS | 
TVS_EDITLABELS |
+           WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 
WS_TABSTOP;
+}
+
+DWORD CFavBand::_GetTVExStyle()
+{
+    return WS_EX_CLIENTEDGE;
+}
+
+DWORD CFavBand::_GetEnumFlags()
+{
+    return SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
+}
+
+BOOL CFavBand::_GetTitle(LPWSTR pszTitle, INT cchTitle)
+{
+#define IDS_FAVORITES 47 // Borrowed from shell32.dll
+    HINSTANCE hShell32 = ::LoadLibraryExW(L"shell32.dll", NULL, 
LOAD_LIBRARY_AS_DATAFILE);
+    if (hShell32)
     {
-        ImageList_Destroy(m_hTreeViewImageList);
-        m_hTreeViewImageList = NULL;
+        ::LoadStringW(hShell32, IDS_FAVORITES, pszTitle, cchTitle);
+        ::FreeLibrary(hShell32);
+        return TRUE;
     }
-    SHDOCVW_UnlockModule();
+    return FALSE;
+#undef IDS_FAVORITES
 }
 
-VOID CFavBand::OnFinalMessage(HWND)
+BOOL CFavBand::_WantsRootItem()
 {
-    // The message loop is finished, now we can safely destruct!
-    Release();
+    return FALSE;
 }
 
-// *** helper methods ***
-
-BOOL CFavBand::CreateToolbar()
+HRESULT CFavBand::_CreateToolbar(HWND hwndParent)
 {
 #define IDB_SHELL_EXPLORER_SM 216 // Borrowed from browseui.dll
     HINSTANCE hinstBrowseUI = LoadLibraryExW(L"browseui.dll", NULL, 
LOAD_LIBRARY_AS_DATAFILE);
@@ -58,23 +82,23 @@ BOOL CFavBand::CreateToolbar()
 #undef IDB_SHELL_EXPLORER_SM
     ATLASSERT(hbmToolbar);
     if (!hbmToolbar)
-        return FALSE;
+        return E_FAIL;
 
     m_hToolbarImageList = ImageList_Create(16, 16, ILC_COLOR32, 0, 8);
     ATLASSERT(m_hToolbarImageList);
     if (!m_hToolbarImageList)
-        return FALSE;
+        return E_FAIL;
 
     ImageList_Add(m_hToolbarImageList, hbmToolbar, NULL);
     DeleteObject(hbmToolbar);
 
     DWORD style = WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_LIST | 
CCS_NODIVIDER |
                   TBSTYLE_WRAPABLE;
-    HWND hwndTB = ::CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style, 0, 0, 
0, 0, m_hWnd,
-                                    (HMENU)(LONG_PTR)IDW_TOOLBAR, instance, 
NULL);
+    HWND hwndTB = ::CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style, 0, 0, 
0, 0, hwndParent,
+                                    (HMENU)UlongToHandle(IDW_TOOLBAR), 
instance, NULL);
     ATLASSERT(hwndTB);
     if (!hwndTB)
-        return FALSE;
+        return E_FAIL;
 
     m_hwndToolbar.Attach(hwndTB);
     m_hwndToolbar.SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 
0);
@@ -102,480 +126,57 @@ BOOL CFavBand::CreateToolbar()
     tbb[iButton].iString = (INT)m_hwndToolbar.SendMessage(TB_ADDSTRING, 0, 
(LPARAM)szzOrganize);
     ++iButton;
     ATLASSERT(iButton == _countof(tbb));
+    m_hwndToolbar.SendMessage(TB_ADDBUTTONS, iButton, (LPARAM)&tbb);
 
-    LRESULT ret = m_hwndToolbar.SendMessage(TB_ADDBUTTONS, iButton, 
(LPARAM)&tbb);
-    ATLASSERT(ret);
-
-    return ret;
-}
-
-BOOL CFavBand::CreateTreeView()
-{
-    m_hTreeViewImageList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 
64, 0);
-    ATLASSERT(m_hTreeViewImageList);
-    if (!m_hTreeViewImageList)
-        return FALSE;
-
-    DWORD style = TVS_NOHSCROLL | TVS_NONEVENHEIGHT | TVS_FULLROWSELECT | 
TVS_INFOTIP |
-                  TVS_SINGLEEXPAND | TVS_TRACKSELECT | TVS_SHOWSELALWAYS | 
TVS_EDITLABELS |
-                  WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 
WS_TABSTOP;
-    HWND hwndTV = ::CreateWindowExW(WS_EX_CLIENTEDGE, WC_TREEVIEWW, NULL, 
style, 0, 0, 0, 0,
-                                    m_hWnd, (HMENU)(ULONG_PTR)IDW_TREEVIEW, 
instance, NULL);
-    ATLASSERT(hwndTV);
-    if (!hwndTV)
-        return FALSE;
-
-    m_hwndTreeView.Attach(hwndTV);
-    TreeView_SetImageList(m_hwndTreeView, m_hTreeViewImageList, TVSIL_NORMAL);
-
-    return TRUE;
-}
-
-// *** message handlers ***
-
-LRESULT CFavBand::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
-{
-    INITCOMMONCONTROLSEX iccx = { sizeof(iccx), ICC_TREEVIEW_CLASSES | 
ICC_BAR_CLASSES };
-    if (!::InitCommonControlsEx(&iccx) || !CreateToolbar() || 
!CreateTreeView())
-        return -1;
-
-    return 0;
-}
-
-LRESULT CFavBand::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
-{
-    m_hwndTreeView.DestroyWindow();
-    m_hwndToolbar.DestroyWindow();
-    return 0;
-}
-
-LRESULT CFavBand::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
-{
-    if (!m_hwndTreeView)
-        return 0;
-
-    RECT rc;
-    GetClientRect(&rc);
-    LONG cx = rc.right, cy = rc.bottom;
-
-    RECT rcTB;
-    m_hwndToolbar.SendMessage(TB_AUTOSIZE, 0, 0);
-    m_hwndToolbar.GetWindowRect(&rcTB);
-
-    LONG cyTB = rcTB.bottom - rcTB.top;
-    m_hwndTreeView.MoveWindow(0, cyTB, cx, cy - cyTB);
-
-    return 0;
-}
-
-LRESULT CFavBand::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
-{
-    m_bFocused = TRUE;
-    IUnknown_OnFocusChangeIS(m_pSite, reinterpret_cast<IUnknown*>(this), TRUE);
-    return 0;
-}
-
-LRESULT CFavBand::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
-{
-    IUnknown_OnFocusChangeIS(m_pSite, reinterpret_cast<IUnknown*>(this), 
FALSE);
-    m_bFocused = FALSE;
-    return 0;
-}
-
-LRESULT CFavBand::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
-{
-    switch (LOWORD(wParam))
-    {
-        case ID_ADD:
-        {
-            UNIMPLEMENTED;
-            SHELL_ErrorBox(m_hWnd, ERROR_NOT_SUPPORTED);
-            break;
-        }
-        case ID_ORGANIZE:
-        {
-            SHELLEXECUTEINFOW sei = { sizeof(sei), SEE_MASK_IDLIST };
-            sei.hwnd = m_hWnd;
-            sei.nShow = SW_SHOWNORMAL;
-            sei.lpIDList = m_pidlFav;
-            ::ShellExecuteExW(&sei);
-            break;
-        }
-    }
-    return 0;
-}
-
-// *** IOleWindow ***
-
-STDMETHODIMP CFavBand::GetWindow(HWND *lphwnd)
-{
-    if (!lphwnd)
-        return E_INVALIDARG;
-    *lphwnd = m_hWnd;
     return S_OK;
 }
 
-STDMETHODIMP CFavBand::ContextSensitiveHelp(BOOL fEnterMode)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-// *** IDockingWindow ***
-
-STDMETHODIMP CFavBand::CloseDW(DWORD dwReserved)
-{
-    // We do nothing, we don't have anything to save yet
-    TRACE("CloseDW called\n");
-    return S_OK;
-}
-
-STDMETHODIMP CFavBand::ResizeBorderDW(const RECT *prcBorder, IUnknown 
*punkToolbarSite, BOOL fReserved)
-{
-    /* Must return E_NOTIMPL according to MSDN */
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::ShowDW(BOOL fShow)
-{
-    m_fVisible = fShow;
-    ShowWindow(fShow ? SW_SHOW : SW_HIDE);
-    return S_OK;
-}
-
-// *** IDeskBand ***
-
-STDMETHODIMP CFavBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, 
DESKBANDINFO *pdbi)
+// Called when the user has selected an item.
+STDMETHODIMP CFavBand::OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl)
 {
-    if (!pdbi)
-        return E_INVALIDARG;
+    CComHeapPtr<ITEMIDLIST> pidlTarget;
+    DWORD attrs = SFGAO_FOLDER | SFGAO_LINK;
+    HRESULT hr = GetNavigateTarget(pidl, &pidlTarget, &attrs);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
-    m_dwBandID = dwBandID;
+    if ((attrs & (SFGAO_FOLDER | SFGAO_LINK)) == (SFGAO_FOLDER | SFGAO_LINK))
+        return _UpdateBrowser(pidlTarget);
 
-    if (pdbi->dwMask & DBIM_MINSIZE)
+    if (attrs & SFGAO_FOLDER)
     {
-        pdbi->ptMinSize.x = 200;
-        pdbi->ptMinSize.y = 30;
-    }
-
-    if (pdbi->dwMask & DBIM_MAXSIZE)
-        pdbi->ptMaxSize.y = -1;
-
-    if (pdbi->dwMask & DBIM_INTEGRAL)
-        pdbi->ptIntegral.y = 1;
-
-    if (pdbi->dwMask & DBIM_ACTUAL)
-    {
-        pdbi->ptActual.x = 200;
-        pdbi->ptActual.y = 30;
-    }
-
-    if (pdbi->dwMask & DBIM_TITLE)
-    {
-#define IDS_FAVORITES 47 // Borrowed from shell32.dll
-        HINSTANCE hShell32 = LoadLibraryExW(L"shell32.dll", NULL, 
LOAD_LIBRARY_AS_DATAFILE);
-        if (hShell32)
+        HTREEITEM hItem = TreeView_GetSelection(m_hwndTreeView);
+        CItemData *pItemData = GetItemData(hItem);
+        if (pItemData && !pItemData->expanded)
         {
-            LoadStringW(hShell32, IDS_FAVORITES, pdbi->wszTitle, 
_countof(pdbi->wszTitle));
-            FreeLibrary(hShell32);
+            _InsertSubitems(hItem, pItemData->absolutePidl);
+            pItemData->expanded = TRUE;
         }
-#undef IDS_FAVORITES
-    }
-
-    if (pdbi->dwMask & DBIM_MODEFLAGS)
-        pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
-
-    if (pdbi->dwMask & DBIM_BKCOLOR)
-        pdbi->dwMask &= ~DBIM_BKCOLOR;
-
-    return S_OK;
-}
-
-// *** IObjectWithSite ***
-
-STDMETHODIMP CFavBand::SetSite(IUnknown *pUnkSite)
-{
-    HRESULT hr;
-
-    if (pUnkSite == m_pSite)
-        return S_OK;
-
-    TRACE("SetSite called\n");
-
-    if (!pUnkSite)
-    {
-        DestroyWindow();
-        m_hWnd = NULL;
-    }
-
-    if (pUnkSite != m_pSite)
-        m_pSite = NULL;
-
-    if (!pUnkSite)
-        return S_OK;
-
-    HWND hwndParent;
-    hr = IUnknown_GetWindow(pUnkSite, &hwndParent);
-    if (!SUCCEEDED(hr))
-    {
-        ERR("Could not get parent's window! 0x%08lX\n", hr);
-        return E_INVALIDARG;
-    }
-
-    m_pSite = pUnkSite;
-
-    if (m_hWnd)
-    {
-        SetParent(hwndParent); // Change its parent
-    }
-    else
-    {
-        this->Create(hwndParent, NULL, NULL, WS_CHILD | WS_VISIBLE, 0, 
(UINT)0, NULL);
-    }
-
-    return S_OK;
-}
-
-STDMETHODIMP CFavBand::GetSite(REFIID riid, void **ppvSite)
-{
-    if (!ppvSite)
-        return E_POINTER;
-    *ppvSite = m_pSite;
-    return S_OK;
-}
-
-// *** IOleCommandTarget ***
-
-STDMETHODIMP CFavBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, 
OLECMD prgCmds [], OLECMDTEXT *pCmdText)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD 
nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-// *** IServiceProvider ***
-
-STDMETHODIMP CFavBand::QueryService(REFGUID guidService, REFIID riid, void 
**ppvObject)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-// *** IServiceProvider ***
-
-STDMETHODIMP CFavBand::QueryContextMenu(
-    HMENU hmenu,
-    UINT indexMenu,
-    UINT idCmdFirst,
-    UINT idCmdLast,
-    UINT uFlags)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::InvokeCommand(
-    LPCMINVOKECOMMANDINFO lpici)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::GetCommandString(
-    UINT_PTR idCmd,
-    UINT uType,
-    UINT *pwReserved,
-    LPSTR pszName,
-    UINT cchMax)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-// *** IInputObject ***
-
-STDMETHODIMP CFavBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
-{
-    if (fActivate)
-    {
-        //SetFocus();
-        SetActiveWindow();
-    }
-
-    if (lpMsg)
-    {
-        TranslateMessage(lpMsg);
-        DispatchMessage(lpMsg);
-    }
-
-    return S_OK;
-}
-
-STDMETHODIMP CFavBand::HasFocusIO()
-{
-    return m_bFocused ? S_OK : S_FALSE;
-}
-
-STDMETHODIMP CFavBand::TranslateAcceleratorIO(LPMSG lpMsg)
-{
-    if (lpMsg->hwnd == m_hWnd)
-    {
-        TranslateMessage(lpMsg);
-        DispatchMessage(lpMsg);
+        TreeView_Expand(m_hwndTreeView, hItem, TVE_EXPAND);
         return S_OK;
     }
 
-    return S_FALSE;
-}
-
-// *** IPersist ***
-
-STDMETHODIMP CFavBand::GetClassID(CLSID *pClassID)
-{
-    if (!pClassID)
-        return E_POINTER;
-    *pClassID = CLSID_SH_FavBand;
-    return S_OK;
+    SHELLEXECUTEINFOW info = { sizeof(info) };
+    info.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_IDLIST;
+    info.hwnd = m_hWnd;
+    info.nShow = SW_SHOWNORMAL;
+    info.lpIDList = pidlTarget;
+    ShellExecuteExW(&info);
+    return hr;
 }
 
-
-// *** IPersistStream ***
-
-STDMETHODIMP CFavBand::IsDirty()
+void CFavBand::_SortItems(HTREEITEM hParent)
 {
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
+    TreeView_SortChildren(m_hwndTreeView, hParent, 0); // Sort by name
 }
 
-STDMETHODIMP CFavBand::Load(IStream *pStm)
+HRESULT CFavBand::_CreateTreeView(HWND hwndParent)
 {
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
+    HRESULT hr = CNSCBand::_CreateTreeView(hwndParent);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
-STDMETHODIMP CFavBand::Save(IStream *pStm, BOOL fClearDirty)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
-{
-    // TODO: calculate max size
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-// *** IWinEventHandler ***
-
-STDMETHODIMP CFavBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam, LRESULT *theResult)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::IsWindowOwner(HWND hWnd)
-{
-    return (hWnd == m_hWnd) ? S_OK : S_FALSE;
-}
-
-// *** IBandNavigate ***
-
-STDMETHODIMP CFavBand::Select(long paramC)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-// *** INamespaceProxy ***
-
-/// Returns the ITEMIDLIST that should be navigated when an item is invoked.
-STDMETHODIMP CFavBand::GetNavigateTarget(
-    _In_ PCIDLIST_ABSOLUTE pidl,
-    _Out_ PIDLIST_ABSOLUTE ppidlTarget,
-    _Out_ ULONG *pulAttrib)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-/// Handles a user action on an item.
-STDMETHODIMP CFavBand::Invoke(_In_ PCIDLIST_ABSOLUTE pidl)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-/// Called when the user has selected an item.
-STDMETHODIMP CFavBand::OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-/// Returns flags used to update the tree control.
-STDMETHODIMP CFavBand::RefreshFlags(
-    _Out_ DWORD *pdwStyle,
-    _Out_ DWORD *pdwExStyle,
-    _Out_ DWORD *dwEnum)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::CacheItem(
-    _In_ PCIDLIST_ABSOLUTE pidl)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-// *** IDispatch ***
-
-STDMETHODIMP CFavBand::GetTypeInfoCount(UINT *pctinfo)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::GetIDsOfNames(
-    REFIID riid,
-    LPOLESTR *rgszNames,
-    UINT cNames,
-    LCID lcid,
-    DISPID *rgDispId)
-{
-    UNIMPLEMENTED;
-    return E_NOTIMPL;
-}
-
-STDMETHODIMP CFavBand::Invoke(
-    DISPID dispIdMember,
-    REFIID riid,
-    LCID lcid,
-    WORD wFlags,
-    DISPPARAMS *pDispParams,
-    VARIANT *pVarResult,
-    EXCEPINFO *pExcepInfo,
-    UINT *puArgErr)
-{
-    switch (dispIdMember)
-    {
-        case DISPID_DOWNLOADCOMPLETE:
-        case DISPID_NAVIGATECOMPLETE2:
-            // FIXME: Update current location
-            return S_OK;
-    }
-    return E_INVALIDARG;
+    TreeView_SetItemHeight(m_hwndTreeView, 24);
+    _InsertSubitems(TVI_ROOT, m_pidlRoot);
+    return hr;
 }
diff --git a/dll/win32/shdocvw/CFavBand.h b/dll/win32/shdocvw/CFavBand.h
index 1b91e04779c..62619096491 100644
--- a/dll/win32/shdocvw/CFavBand.h
+++ b/dll/win32/shdocvw/CFavBand.h
@@ -7,129 +7,27 @@
 
 #pragma once
 
-#define FAVBANDCLASSNAME L"ReactOS Favorites Band"
-
 #ifdef __cplusplus
+
+#include "CNSCBand.h"
+
 class CFavBand
-    : public CComCoClass<CFavBand, &CLSID_SH_FavBand>
+    : public CNSCBand
+    , public CComCoClass<CFavBand, &CLSID_SH_FavBand>
     , public CComObjectRootEx<CComMultiThreadModelNoCS>
-    , public CWindowImpl<CFavBand>
-    , public IDispatch
-    , public IDeskBand
-    , public IObjectWithSite
-    , public IInputObject
-    , public IPersistStream
-    , public IOleCommandTarget
-    , public IServiceProvider
-    , public IContextMenu
-    , public IBandNavigate
-    , public IWinEventHandler
-    , public INamespaceProxy
 {
 public:
-    DECLARE_WND_CLASS_EX(FAVBANDCLASSNAME, 0, COLOR_3DFACE)
-    static LPCWSTR GetWndClassName() { return FAVBANDCLASSNAME; }
-
     CFavBand();
     virtual ~CFavBand();
 
-    // *** IOleWindow methods ***
-    STDMETHODIMP GetWindow(HWND *lphwnd) override;
-    STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) override;
-
-    // *** IDockingWindow methods ***
-    STDMETHODIMP CloseDW(DWORD dwReserved) override;
-    STDMETHODIMP ResizeBorderDW(const RECT *prcBorder, IUnknown 
*punkToolbarSite, BOOL fReserved) override;
-    STDMETHODIMP ShowDW(BOOL fShow) override;
-
-    // *** IDeskBand methods ***
-    STDMETHODIMP GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO 
*pdbi) override;
-
-    // *** IObjectWithSite methods ***
-    STDMETHODIMP SetSite(IUnknown *pUnkSite) override;
-    STDMETHODIMP GetSite(REFIID riid, void **ppvSite) override;
-
-    // *** IOleCommandTarget methods ***
-    STDMETHODIMP QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD 
prgCmds [], OLECMDTEXT *pCmdText) override;
-    STDMETHODIMP Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD 
nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) override;
-
-    // *** IServiceProvider methods ***
-    STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void 
**ppvObject) override;
-
-    // *** IContextMenu methods ***
-    STDMETHODIMP QueryContextMenu(
-        HMENU hmenu,
-        UINT indexMenu,
-        UINT idCmdFirst,
-        UINT idCmdLast,
-        UINT uFlags) override;
-    STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpici) override;
-    STDMETHODIMP GetCommandString(
-        UINT_PTR idCmd,
-        UINT uType,
-        UINT *pwReserved,
-        LPSTR pszName,
-        UINT cchMax) override;
-
-    // *** IInputObject methods ***
-    STDMETHODIMP UIActivateIO(BOOL fActivate, LPMSG lpMsg) override;
-    STDMETHODIMP HasFocusIO() override;
-    STDMETHODIMP TranslateAcceleratorIO(LPMSG lpMsg) override;
-
-    // *** IPersist methods ***
     STDMETHODIMP GetClassID(CLSID *pClassID) override;
-
-    // *** IPersistStream methods ***
-    STDMETHODIMP IsDirty() override;
-    STDMETHODIMP Load(IStream *pStm) override;
-    STDMETHODIMP Save(IStream *pStm, BOOL fClearDirty) override;
-    STDMETHODIMP GetSizeMax(ULARGE_INTEGER *pcbSize) override;
-
-    // *** IWinEventHandler methods ***
-    STDMETHODIMP OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam, LRESULT *theResult) override;
-    STDMETHODIMP IsWindowOwner(HWND hWnd) override;
-
-    // *** IBandNavigate methods ***
-    STDMETHODIMP Select(long paramC) override;
-
-    // *** INamespaceProxy methods ***
-    STDMETHODIMP GetNavigateTarget(
-        _In_ PCIDLIST_ABSOLUTE pidl,
-        _Out_ PIDLIST_ABSOLUTE ppidlTarget,
-        _Out_ ULONG *pulAttrib) override;
-    STDMETHODIMP Invoke(_In_ PCIDLIST_ABSOLUTE pidl) override;
-    STDMETHODIMP OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl) override;
-    STDMETHODIMP RefreshFlags(
-        _Out_ DWORD *pdwStyle,
-        _Out_ DWORD *pdwExStyle,
-        _Out_ DWORD *dwEnum) override;
-    STDMETHODIMP CacheItem(_In_ PCIDLIST_ABSOLUTE pidl) override;
-
-    // *** IDispatch methods ***
-    STDMETHODIMP GetTypeInfoCount(UINT *pctinfo) override;
-    STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) 
override;
-    STDMETHODIMP GetIDsOfNames(
-        REFIID riid,
-        LPOLESTR *rgszNames,
-        UINT cNames,
-        LCID lcid,
-        DISPID *rgDispId) override;
-    STDMETHODIMP Invoke(
-        DISPID dispIdMember,
-        REFIID riid,
-        LCID lcid,
-        WORD wFlags,
-        DISPPARAMS *pDispParams,
-        VARIANT *pVarResult,
-        EXCEPINFO *pExcepInfo,
-        UINT *puArgErr) override;
+    STDMETHODIMP OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl);
 
     DECLARE_REGISTRY_RESOURCEID(IDR_FAVBAND)
     DECLARE_NOT_AGGREGATABLE(CFavBand)
     DECLARE_PROTECT_FINAL_CONSTRUCT()
 
     BEGIN_COM_MAP(CFavBand)
-        COM_INTERFACE_ENTRY_IID(IID_IDispatch, IDispatch)
         COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
         COM_INTERFACE_ENTRY2_IID(IID_IDockingWindow, IDockingWindow, IDeskBand)
         COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDeskBand)
@@ -146,38 +44,16 @@ public:
         COM_INTERFACE_ENTRY_IID(IID_INamespaceProxy, INamespaceProxy)
     END_COM_MAP()
 
-    BEGIN_MSG_MAP(CFavBand)
-        MESSAGE_HANDLER(WM_CREATE, OnCreate)
-        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
-        MESSAGE_HANDLER(WM_SIZE, OnSize)
-        MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
-        MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
-        MESSAGE_HANDLER(WM_COMMAND, OnCommand)
-    END_MSG_MAP()
-
 protected:
-    BOOL m_fVisible;
-    BOOL m_bFocused;
-    DWORD m_dwBandID;
-    CComPtr<IUnknown> m_pSite;
-    CComHeapPtr<ITEMIDLIST> m_pidlFav;
-    HIMAGELIST m_hToolbarImageList;
-    HIMAGELIST m_hTreeViewImageList;
-    CToolbar<> m_hwndToolbar;
-    CTreeView m_hwndTreeView;
-
-    VOID OnFinalMessage(HWND) override;
-
-    // *** helper methods ***
-    BOOL CreateToolbar();
-    BOOL CreateTreeView();
-
-    // *** message handlers ***
-    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
-    LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
-    LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    INT _GetRootCsidl() override;
+    DWORD _GetTVStyle() override;
+    DWORD _GetTVExStyle() override;
+    DWORD _GetEnumFlags() override;
+    BOOL _GetTitle(LPWSTR pszTitle, INT cchTitle) override;
+    HRESULT _CreateTreeView(HWND hwndParent) override;
+    HRESULT _CreateToolbar(HWND hwndParent) override;
+    BOOL _WantsRootItem() override;
+    void _SortItems(HTREEITEM hParent) override;
 };
+
 #endif // def __cplusplus
diff --git a/dll/win32/shdocvw/CMakeLists.txt b/dll/win32/shdocvw/CMakeLists.txt
index 71ab7e8ddb3..764663a42ed 100644
--- a/dll/win32/shdocvw/CMakeLists.txt
+++ b/dll/win32/shdocvw/CMakeLists.txt
@@ -34,6 +34,7 @@ add_cd_file(TARGET shdocvw DESTINATION reactos/system32 FOR 
all)
 add_library(shdocvw_sublib OBJECT
     CExplorerBand.cpp
     CFavBand.cpp
+    CNSCBand.cpp
     mrulist.cpp
     objects.cpp
     utility.cpp)
diff --git a/dll/win32/shdocvw/CNSCBand.cpp b/dll/win32/shdocvw/CNSCBand.cpp
new file mode 100644
index 00000000000..976acb50a7d
--- /dev/null
+++ b/dll/win32/shdocvw/CNSCBand.cpp
@@ -0,0 +1,1487 @@
+/*
+ * PROJECT:     ReactOS shdocvw
+ * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE:     NameSpace Control Band
+ * COPYRIGHT:   Copyright 2024 Katayama Hirofumi MZ 
<katayama.hirofumi...@gmail.com>
+ */
+
+#include "objects.h"
+#include <shlobj.h>
+#include <commoncontrols.h>
+#include <undocshell.h>
+
+#define TIMER_ID_REFRESH 9999
+
+#include <wine/debug.h>
+WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
+
+HRESULT
+SHDOCVW_GetPathOfShortcut(
+    _In_opt_ HWND hWnd,
+    _In_ LPCWSTR pszLnkFile,
+    _Out_ LPWSTR pszPath)
+{
+    *pszPath = UNICODE_NULL;
+    CComPtr<IShellLink> pShellLink;
+    HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL,  CLSCTX_INPROC_SERVER,
+                                  IID_PPV_ARG(IShellLink, &pShellLink));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    CComPtr<IPersistFile> pPersistFile;
+    hr = pShellLink->QueryInterface(IID_PPV_ARG(IPersistFile, &pPersistFile));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    hr = pPersistFile->Load(pszLnkFile, STGM_READ);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    WIN32_FIND_DATA find;
+    hr = pShellLink->GetPath(pszPath, MAX_PATH, &find, 0);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    return S_OK;
+}
+
+HRESULT
+SHDOCVW_CreateShortcut(
+    _In_ LPCWSTR pszLnkFileName, 
+    _In_ PCIDLIST_ABSOLUTE pidlTarget,
+    _In_opt_ LPCWSTR pszDescription)
+{
+    HRESULT hr;
+
+    CComPtr<IShellLink> psl;
+    hr = CoCreateInstance(CLSID_ShellLink, NULL,  CLSCTX_INPROC_SERVER,
+                          IID_PPV_ARG(IShellLink, &psl));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    psl->SetIDList(pidlTarget);
+
+    if (pszDescription)
+        psl->SetDescription(pszDescription);
+
+    CComPtr<IPersistFile> ppf;
+    hr = psl->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    return ppf->Save(pszLnkFileName, TRUE);
+}
+
+CNSCBand::CNSCBand()
+{
+    SHDOCVW_LockModule();
+
+    INITCOMMONCONTROLSEX iccx = { sizeof(iccx), ICC_TREEVIEW_CLASSES | 
ICC_BAR_CLASSES };
+    ::InitCommonControlsEx(&iccx);
+}
+
+CNSCBand::~CNSCBand()
+{
+    if (m_hToolbarImageList)
+    {
+        ImageList_Destroy(m_hToolbarImageList);
+        m_hToolbarImageList = NULL;
+    }
+    SHDOCVW_UnlockModule();
+}
+
+VOID CNSCBand::OnFinalMessage(HWND)
+{
+    // The message loop is finished, now we can safely destruct!
+    static_cast<IDeskBand *>(this)->Release();
+}
+
+// *** helper methods ***
+
+CNSCBand::CItemData* CNSCBand::GetItemData(_In_ HTREEITEM hItem)
+{
+    if (hItem == TVI_ROOT)
+        return NULL;
+
+    TVITEMW tvItem = { TVIF_PARAM, hItem };
+    if (!TreeView_GetItem(m_hwndTreeView, &tvItem))
+        return NULL;
+
+    return reinterpret_cast<CItemData*>(tvItem.lParam);
+}
+
+static HRESULT
+SHDOCVW_GetCurrentLocationFromView(_In_ IShellView& View, _In_ 
PIDLIST_ABSOLUTE *ppidl)
+{
+    CComPtr<IFolderView> pfv;
+    CComPtr<IShellFolder> psf;
+    HRESULT hr = View.QueryInterface(IID_PPV_ARG(IFolderView, &pfv));
+    if (SUCCEEDED(hr) && SUCCEEDED(hr = 
pfv->GetFolder(IID_PPV_ARG(IShellFolder, &psf))))
+        hr = SHELL_GetIDListFromObject(psf, ppidl);
+    return hr;
+}
+
+HRESULT CNSCBand::_GetCurrentLocation(_Out_ PIDLIST_ABSOLUTE *ppidl)
+{
+    *ppidl = NULL;
+    CComPtr<IShellBrowser> psb;
+    HRESULT hr = IUnknown_QueryService(m_pSite, SID_STopLevelBrowser, 
IID_PPV_ARG(IShellBrowser, &psb));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    CComPtr<IBrowserService> pbs;
+    if (SUCCEEDED(hr = psb->QueryInterface(IID_PPV_ARG(IBrowserService, 
&pbs))))
+        if (SUCCEEDED(hr = pbs->GetPidl(ppidl)) && *ppidl)
+            return hr;
+
+    CComPtr<IShellView> psv;
+    if (!FAILED_UNEXPECTEDLY(hr = psb->QueryActiveShellView(&psv)))
+        if (SUCCEEDED(hr = psv.p ? SHDOCVW_GetCurrentLocationFromView(*psv.p, 
ppidl) : E_FAIL))
+            return hr;
+    return hr;
+}
+
+HRESULT CNSCBand::_IsCurrentLocation(_In_ PCIDLIST_ABSOLUTE pidl)
+{
+    if (!pidl)
+        return E_INVALIDARG;
+    HRESULT hr = E_FAIL;
+    PIDLIST_ABSOLUTE location = NULL;
+    hr = _GetCurrentLocation(&location);
+    if (SUCCEEDED(hr))
+        hr = SHELL_IsEqualAbsoluteID(location, pidl) ? S_OK : S_FALSE;
+    ILFree(location);
+    return hr;
+}
+
+HRESULT CNSCBand::_ExecuteCommand(_In_ CComPtr<IContextMenu>& menu, _In_ UINT 
nCmd)
+{
+    CComPtr<IOleWindow> pBrowserOleWnd;
+    HRESULT hr = IUnknown_QueryService(m_pSite, SID_SShellBrowser,
+                                       IID_PPV_ARG(IOleWindow, 
&pBrowserOleWnd));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    HWND browserWnd;
+    hr = pBrowserOleWnd->GetWindow(&browserWnd);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    CMINVOKECOMMANDINFO cmi = { sizeof(cmi) };
+    cmi.lpVerb = MAKEINTRESOURCEA(nCmd);
+    cmi.hwnd = browserWnd;
+    if (::GetKeyState(VK_SHIFT) < 0)
+        cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
+    if (::GetKeyState(VK_CONTROL) < 0)
+        cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
+
+    return menu->InvokeCommand(&cmi);
+}
+
+void CNSCBand::_RegisterChangeNotify()
+{
+#define TARGET_EVENTS ( \
+    SHCNE_DRIVEADD | SHCNE_MKDIR | SHCNE_CREATE | SHCNE_DRIVEREMOVED | 
SHCNE_RMDIR | \
+    SHCNE_DELETE | SHCNE_RENAMEFOLDER | SHCNE_RENAMEITEM | SHCNE_UPDATEDIR | \
+    SHCNE_UPDATEITEM | SHCNE_ASSOCCHANGED \
+)
+    // Register shell notification
+    SHChangeNotifyEntry shcne = { m_pidlRoot, TRUE };
+    m_shellRegID = SHChangeNotifyRegister(m_hWnd,
+                                          SHCNRF_NewDelivery | 
SHCNRF_ShellLevel,
+                                          TARGET_EVENTS,
+                                          WM_USER_SHELLEVENT,
+                                          1, &shcne);
+    if (!m_shellRegID)
+    {
+        ERR("Something went wrong, error %08x\n", GetLastError());
+    }
+}
+
+void CNSCBand::_UnregisterChangeNotify()
+{
+    SHChangeNotifyDeregister(m_shellRegID);
+    m_shellRegID = 0;
+}
+
+void CNSCBand::_DestroyTreeView()
+{
+    TRACE("Cleaning up treeview...\n");
+    /* Remove all items of the treeview */
+    ::RevokeDragDrop(m_hwndTreeView);
+    TreeView_DeleteAllItems(m_hwndTreeView);
+    m_hwndTreeView.DestroyWindow();
+    m_pDesktop = NULL;
+    m_hRoot = NULL;
+    TRACE("Cleanup ok\n");
+}
+
+void CNSCBand::_DestroyToolbar()
+{
+    m_hwndToolbar.DestroyWindow();
+}
+
+HRESULT CNSCBand::_CreateTreeView(HWND hwndParent)
+{
+    RefreshFlags(&m_dwTVStyle, &m_dwTVExStyle, &m_dwEnumFlags);
+    HWND hwndTV = ::CreateWindowExW(m_dwTVExStyle, WC_TREEVIEWW, NULL, 
m_dwTVStyle, 0, 0, 0, 0,
+                                    hwndParent, 
(HMENU)UlongToHandle(IDW_TREEVIEW), instance, NULL);
+    ATLASSERT(hwndTV);
+    if (!hwndTV)
+        return E_FAIL;
+
+    m_hwndTreeView.Attach(hwndTV);
+    ::RegisterDragDrop(m_hwndTreeView, dynamic_cast<IDropTarget*>(this));
+
+    // Init the treeview here
+    HRESULT hr = SHGetDesktopFolder(&m_pDesktop);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    m_pidlRoot.Free();
+    hr = SHGetFolderLocation(m_hWnd, _GetRootCsidl(), NULL, 0, &m_pidlRoot);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    // Create image list and set
+    IImageList *piml;
+    hr = SHGetImageList(SHIL_SMALL, IID_PPV_ARG(IImageList, &piml));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    TreeView_SetImageList(m_hwndTreeView, (HIMAGELIST)piml, TVSIL_NORMAL);
+    return S_OK;
+}
+
+BOOL
+CNSCBand::_IsTreeItemInEnum(
+    _In_ HTREEITEM hItem,
+    _In_ IEnumIDList *pEnum)
+{
+    CItemData* pItemData = GetItemData(hItem);
+    if (!pItemData)
+        return FALSE;
+
+    pEnum->Reset();
+
+    CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
+    while (pEnum->Next(1, &pidlTemp, NULL) == S_OK)
+    {
+        if (ILIsEqual(pidlTemp, pItemData->relativePidl))
+            return TRUE;
+
+        pidlTemp.Free();
+    }
+
+    return FALSE;
+}
+
+BOOL
+CNSCBand::_TreeItemHasThisChild(
+    _In_ HTREEITEM hItem,
+    _In_ PCITEMID_CHILD pidlChild)
+{
+    for (hItem = TreeView_GetChild(m_hwndTreeView, hItem); hItem;
+         hItem = TreeView_GetNextSibling(m_hwndTreeView, hItem))
+    {
+        CItemData* pItemData = GetItemData(hItem);
+        if (ILIsEqual(pItemData->relativePidl, pidlChild))
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+HRESULT
+CNSCBand::_GetItemEnum(
+    _Out_ CComPtr<IEnumIDList>& pEnum,
+    _In_ HTREEITEM hItem,
+    _Out_opt_ IShellFolder **ppFolder)
+{
+    CComPtr<IShellFolder> psfDesktop;
+    HRESULT hr = SHGetDesktopFolder(&psfDesktop);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    CComPtr<IShellFolder> pFolder;
+    if (!ppFolder)
+        ppFolder = &pFolder;
+
+    if (hItem == m_hRoot && hItem)
+    {
+        *ppFolder = psfDesktop;
+        (*ppFolder)->AddRef();
+    }
+    else
+    {
+        CItemData* pItemData = GetItemData(hItem);
+        if (!pItemData && hItem == TVI_ROOT && !_WantsRootItem())
+            hr = psfDesktop->BindToObject(m_pidlRoot, NULL, 
IID_PPV_ARG(IShellFolder, ppFolder));
+        else
+            hr = psfDesktop->BindToObject(pItemData->absolutePidl, NULL, 
IID_PPV_ARG(IShellFolder, ppFolder));
+        if (FAILED_UNEXPECTEDLY(hr))
+            return hr;
+    }
+
+    return (*ppFolder)->EnumObjects(NULL, _GetEnumFlags(), &pEnum);
+}
+
+BOOL CNSCBand::_ItemHasAnyChild(_In_ HTREEITEM hItem)
+{
+    CComPtr<IEnumIDList> pEnum;
+    HRESULT hr = _GetItemEnum(pEnum, hItem);
+    if (FAILED(hr))
+        return FALSE;
+
+    CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
+    hr = pEnum->Next(1, &pidlTemp, NULL);
+    return SUCCEEDED(hr);
+}
+
+void CNSCBand::_RefreshRecurse(_In_ HTREEITEM hTarget)
+{
+    CComPtr<IEnumIDList> pEnum;
+    HRESULT hrEnum = _GetItemEnum(pEnum, hTarget);
+
+    // Delete zombie items
+    HTREEITEM hItem, hNextItem;
+    for (hItem = TreeView_GetChild(m_hwndTreeView, hTarget); hItem; hItem = 
hNextItem)
+    {
+        hNextItem = TreeView_GetNextSibling(m_hwndTreeView, hItem);
+
+        if (SUCCEEDED(hrEnum) && !_IsTreeItemInEnum(hItem, pEnum))
+            TreeView_DeleteItem(m_hwndTreeView, hItem);
+    }
+
+    pEnum = NULL;
+    hrEnum = _GetItemEnum(pEnum, hTarget);
+
+    CItemData* pItemData = ((hTarget == TVI_ROOT) ? NULL : 
GetItemData(hTarget));
+
+    // Insert new items and update items
+    if (SUCCEEDED(hrEnum))
+    {
+        CComHeapPtr<ITEMIDLIST_RELATIVE> pidlTemp;
+        while (pEnum->Next(1, &pidlTemp, NULL) == S_OK)
+        {
+            if (!_TreeItemHasThisChild(hTarget, pidlTemp))
+            {
+                if (pItemData)
+                {
+                    CComHeapPtr<ITEMIDLIST> 
pidlAbsolute(ILCombine(pItemData->absolutePidl, pidlTemp));
+                    _InsertItem(hTarget, pidlAbsolute, pidlTemp, TRUE);
+                }
+                else
+                {
+                    CComHeapPtr<ITEMIDLIST> pidlAbsolute(ILCombine(m_pidlRoot, 
pidlTemp));
+                    _InsertItem(hTarget, pidlAbsolute, pidlTemp, TRUE);
+                }
+            }
+            pidlTemp.Free();
+        }
+    }
+
+    // Update children and recurse
+    for (hItem = TreeView_GetChild(m_hwndTreeView, hTarget); hItem; hItem = 
hNextItem)
+    {
+        hNextItem = TreeView_GetNextSibling(m_hwndTreeView, hItem);
+
+        TV_ITEMW item = { TVIF_HANDLE | TVIF_CHILDREN };
+        item.hItem = hItem;
+        item.cChildren = _ItemHasAnyChild(hItem);
+        TreeView_SetItem(m_hwndTreeView, &item);
+
+        if (TreeView_GetItemState(m_hwndTreeView, hItem, TVIS_EXPANDEDONCE) & 
TVIS_EXPANDEDONCE)
+            _RefreshRecurse(hItem);
+    }
+}
+
+void CNSCBand::_Refresh()
+{
+    m_hwndTreeView.SendMessage(WM_SETREDRAW, FALSE, 0);
+    _RefreshRecurse(_WantsRootItem() ? m_hRoot : TVI_ROOT);
+    m_hwndTreeView.SendMessage(WM_SETREDRAW, TRUE, 0);
+}
+
+LRESULT CNSCBand::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
+{
+    KillTimer(wParam);
+
+    if (wParam == TIMER_ID_REFRESH)
+        _Refresh();
+
+    return 0;
+}
+
+void
+CNSCBand::OnChangeNotify(
+    _In_opt_ LPCITEMIDLIST pidl0,
+    _In_opt_ LPCITEMIDLIST pidl1,
+    _In_ LONG lEvent)
+{
+    switch (lEvent)
+    {
+        case SHCNE_DRIVEADD:
+        case SHCNE_MKDIR:
+        case SHCNE_CREATE:
+        case SHCNE_DRIVEREMOVED:
+        case SHCNE_RMDIR:
+        case SHCNE_DELETE:
+        case SHCNE_RENAMEFOLDER:
+        case SHCNE_RENAMEITEM:
+        case SHCNE_UPDATEDIR:
+        case SHCNE_UPDATEITEM:
+        case SHCNE_ASSOCCHANGED:
+        {
+            KillTimer(TIMER_ID_REFRESH);
+            SetTimer(TIMER_ID_REFRESH, 500, NULL);
+            break;
+        }
+        default:
+        {
+            TRACE("lEvent: 0x%08lX\n", lEvent);
+            break;
+        }
+    }
+}
+
+HTREEITEM
+CNSCBand::_InsertItem(
+    _In_opt_ HTREEITEM hParent,
+    _Inout_ IShellFolder *psfParent,
+    _In_ LPCITEMIDLIST pElt,
+    _In_ LPCITEMIDLIST pEltRelative,
+    _In_ BOOL bSort)
+{
+    /* Get the attributes of the node */
+    SFGAOF attrs = SFGAO_STREAM | SFGAO_HASSUBFOLDER;
+    HRESULT hr = psfParent->GetAttributesOf(1, &pEltRelative, &attrs);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return NULL;
+
+    /* Get the name of the node */
+    WCHAR wszDisplayName[MAX_PATH];
+    STRRET strret;
+    hr = psfParent->GetDisplayNameOf(pEltRelative, SHGDN_INFOLDER, &strret);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return NULL;
+
+    hr = StrRetToBufW(&strret, pEltRelative, wszDisplayName, MAX_PATH);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return NULL;
+
+    /* Get the icon of the node */
+    INT iIcon = SHMapPIDLToSystemImageListIndex(psfParent, pEltRelative, NULL);
+
+    CItemData* pChildInfo = new CItemData;
+    if (!pChildInfo)
+    {
+        ERR("Failed to allocate CItemData\n");
+        return NULL;
+    }
+    pChildInfo->absolutePidl.Attach(ILClone(pElt));
+    pChildInfo->relativePidl.Attach(ILClone(pEltRelative));
+
+    // Set up our treeview template
+    TV_INSERTSTRUCT tvInsert = { hParent, TVI_LAST };
+    tvInsert.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | 
TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
+    tvInsert.item.cchTextMax = MAX_PATH;
+    tvInsert.item.pszText = wszDisplayName;
+    tvInsert.item.iImage = tvInsert.item.iSelectedImage = iIcon;
+    tvInsert.item.lParam = (LPARAM)pChildInfo;
+
+    if (!(attrs & SFGAO_STREAM) && (attrs & SFGAO_HASSUBFOLDER))
+        tvInsert.item.cChildren = 1;
+
+    HTREEITEM htiCreated = TreeView_InsertItem(m_hwndTreeView, &tvInsert);
+
+    if (bSort)
+        _SortItems(hParent);
+
+    return htiCreated;
+}
+
+/* This is the slow version of the above method */
+HTREEITEM
+CNSCBand::_InsertItem(
+    _In_opt_ HTREEITEM hParent,
+    _In_ LPCITEMIDLIST pElt,
+    _In_ LPCITEMIDLIST pEltRelative,
+    _In_ BOOL bSort)
+{
+    CComPtr<IShellFolder> psfFolder;
+    HRESULT hr = SHBindToParent(pElt, IID_PPV_ARG(IShellFolder, &psfFolder), 
NULL);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return NULL;
+
+    return _InsertItem(hParent, psfFolder, pElt, pEltRelative, bSort);
+}
+
+BOOL CNSCBand::_InsertSubitems(HTREEITEM hItem, LPCITEMIDLIST entry)
+{
+    ULONG fetched = 1, uItemCount = 0;
+
+    CComPtr<IEnumIDList> pEnum;
+    CComPtr<IShellFolder> pFolder;
+    HRESULT hr = _GetItemEnum(pEnum, hItem, &pFolder);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return FALSE;
+
+    /* Don't redraw while we add stuff into the tree */
+    m_hwndTreeView.SendMessage(WM_SETREDRAW, FALSE, 0);
+
+    LPITEMIDLIST pidlSub;
+    while (SUCCEEDED(pEnum->Next(1, &pidlSub, &fetched)) && pidlSub && fetched)
+    {
+        LPITEMIDLIST pidlSubComplete;
+        pidlSubComplete = ILCombine(entry, pidlSub);
+
+        if (_InsertItem(hItem, pFolder, pidlSubComplete, pidlSub, FALSE))
+            ++uItemCount;
+
+        ILFree(pidlSubComplete);
+        ILFree(pidlSub);
+    }
+
+    /* Let's do sorting */
+    _SortItems(hItem);
+
+    /* Now we can redraw */
+    m_hwndTreeView.SendMessage(WM_SETREDRAW, TRUE, 0);
+
+    return (uItemCount > 0);
+}
+
+// *** message handlers ***
+
+LRESULT CNSCBand::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
+{
+    if (FAILED_UNEXPECTEDLY(_CreateToolbar(m_hWnd)))
+        return -1;
+    if (FAILED_UNEXPECTEDLY(_CreateTreeView(m_hWnd)))
+        return -1;
+    return 0;
+}
+
+LRESULT CNSCBand::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
+{
+    _DestroyTreeView();
+    _DestroyToolbar();
+    _UnregisterChangeNotify();
+    return 0;
+}
+
+LRESULT CNSCBand::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
+{
+    if (!m_hwndTreeView)
+        return 0;
+
+    RECT rc;
+    GetClientRect(&rc);
+    LONG cx = rc.right, cy = rc.bottom;
+
+    RECT rcTB;
+    LONG cyTB = 0;
+    if (m_hwndToolbar)
+    {
+        m_hwndToolbar.SendMessage(TB_AUTOSIZE, 0, 0);
+        m_hwndToolbar.GetWindowRect(&rcTB);
+        cyTB = rcTB.bottom - rcTB.top;
+    }
+
+    m_hwndTreeView.MoveWindow(0, cyTB, cx, cy - cyTB);
+    return 0;
+}
+
+LRESULT CNSCBand::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
+{
+    m_bFocused = TRUE;
+    IUnknown_OnFocusChangeIS(m_pSite, reinterpret_cast<IUnknown*>(this), TRUE);
+    bHandled = FALSE;
+    return 0;
+}
+
+LRESULT CNSCBand::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
+{
+    IUnknown_OnFocusChangeIS(m_pSite, reinterpret_cast<IUnknown*>(this), 
FALSE);
+    m_bFocused = FALSE;
+    return 0;
+}
+
+HRESULT CNSCBand::_AddFavorite()
+{
+    CComHeapPtr<ITEMIDLIST> pidlCurrent;
+    _GetCurrentLocation(&pidlCurrent);
+
+    WCHAR szCurDir[MAX_PATH];
+    if (!ILGetDisplayName(pidlCurrent, szCurDir))
+    {
+        FIXME("\n");
+        return E_FAIL;
+    }
+
+    WCHAR szPath[MAX_PATH], szSuffix[32];
+    SHGetSpecialFolderPathW(m_hWnd, szPath, CSIDL_FAVORITES, TRUE);
+    PathAppendW(szPath, PathFindFileNameW(szCurDir));
+
+    const INT ich = lstrlenW(szPath);
+    for (INT iTry = 2; iTry <= 9999; ++iTry)
+    {
+        PathAddExtensionW(szPath, L".lnk");
+        if (!PathFileExistsW(szPath))
+            break;
+        szPath[ich] = UNICODE_NULL;
+        wsprintfW(szSuffix, L" (%d)", iTry);
+        lstrcatW(szPath, szSuffix);
+    }
+
+    TRACE("%S, %S\n", szCurDir, szPath);
+
+    return SHDOCVW_CreateShortcut(szPath, pidlCurrent, NULL);
+}
+
+LRESULT CNSCBand::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
+{
+    switch (LOWORD(wParam))
+    {
+        case ID_ADD:
+        {
+            _AddFavorite();
+            break;
+        }
+        case ID_ORGANIZE:
+        {
+            SHELLEXECUTEINFOW sei = { sizeof(sei), SEE_MASK_INVOKEIDLIST };
+            sei.hwnd = m_hWnd;
+            sei.nShow = SW_SHOWNORMAL;
+            sei.lpIDList = m_pidlRoot;
+            ::ShellExecuteExW(&sei);
+            break;
+        }
+    }
+    return 0;
+}
+
+BOOL CNSCBand::OnTreeItemExpanding(_In_ LPNMTREEVIEW pnmtv)
+{
+    CItemData *pItemData;
+
+    if (pnmtv->action == TVE_COLLAPSE)
+    {
+        if (pnmtv->itemNew.hItem == m_hRoot)
+        {
+            // Prenvent root from collapsing
+            pnmtv->itemNew.mask |= TVIF_STATE;
+            pnmtv->itemNew.stateMask |= TVIS_EXPANDED;
+            pnmtv->itemNew.state &= ~TVIS_EXPANDED;
+            pnmtv->action = TVE_EXPAND;
+            return TRUE;
+        }
+    }
+
+    if (pnmtv->action == TVE_EXPAND)
+    {
+        // Grab our directory PIDL
+        pItemData = GetItemData(pnmtv->itemNew.hItem);
+        // We have it, let's try
+        if (pItemData && !pItemData->expanded)
+        {
+            if (_InsertSubitems(pnmtv->itemNew.hItem, pItemData->absolutePidl))
+            {
+                pItemData->expanded = TRUE;
+            }
+            else
+            {
+                // remove subitem "+" since we failed to add subitems
+                TVITEMW tvItem = { TVIF_CHILDREN, pnmtv->itemNew.hItem };
+                tvItem.cChildren = 0;
+                TreeView_SetItem(m_hwndTreeView, &tvItem);
+            }
+        }
+    }
+    return FALSE;
+}
+
+BOOL CNSCBand::OnTreeItemDeleted(_In_ LPNMTREEVIEW pnmtv)
+{
+    // Navigate to parent when deleting selected item
+    HTREEITEM hItem = pnmtv->itemOld.hItem;
+    HTREEITEM hParent = TreeView_GetParent(m_hwndTreeView, hItem);
+    if (hParent && TreeView_GetSelection(m_hwndTreeView) == hItem)
+        TreeView_SelectItem(m_hwndTreeView, hParent);
+
+    /* Destroy memory associated to our node */
+    CItemData* pItemData = GetItemData(hItem);
+    if (!pItemData)
+        return FALSE;
+
+    delete pItemData;
+
+    return TRUE;
+}
+
+void CNSCBand::_OnSelectionChanged(_In_ LPNMTREEVIEW pnmtv)
+{
+    HTREEITEM hItem = pnmtv->itemNew.hItem;
+    if (!hItem)
+        return;
+    CItemData* pItemData = GetItemData(hItem);
+    if (pItemData)
+        OnSelectionChanged(pItemData->absolutePidl);
+}
+
+void CNSCBand::OnTreeItemDragging(_In_ LPNMTREEVIEW pnmtv, _In_ BOOL 
isRightClick)
+{
+    CItemData* pItemData = GetItemData(pnmtv->itemNew.hItem);
+    if (!pItemData)
+        return;
+
+    HRESULT hr;
+    CComPtr<IShellFolder> pSrcFolder;
+    LPCITEMIDLIST pLast;
+    hr = SHBindToParent(pItemData->absolutePidl, IID_PPV_ARG(IShellFolder, 
&pSrcFolder), &pLast);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return;
+
+    SFGAOF attrs = SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK;
+    pSrcFolder->GetAttributesOf(1, &pLast, &attrs);
+
+    DWORD dwEffect = 0;
+    if (attrs & SFGAO_CANCOPY)
+        dwEffect |= DROPEFFECT_COPY;
+    if (attrs & SFGAO_CANMOVE)
+        dwEffect |= DROPEFFECT_MOVE;
+    if (attrs & SFGAO_CANLINK)
+        dwEffect |= DROPEFFECT_LINK;
+
+    CComPtr<IDataObject> pObj;
+    hr = pSrcFolder->GetUIObjectOf(m_hWnd, 1, &pLast, IID_IDataObject, 0, 
(LPVOID*)&pObj);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return;
+
+    DoDragDrop(pObj, this, dwEffect, &dwEffect);
+}
+
+LRESULT CNSCBand::OnBeginLabelEdit(_In_ LPNMTVDISPINFO dispInfo)
+{
+    // TODO: put this in a function ? (mostly copypasta from CDefView)
+    DWORD dwAttr = SFGAO_CANRENAME;
+    CComPtr<IShellFolder> pParent;
+    LPCITEMIDLIST pChild;
+    HRESULT hr;
+
+    CItemData *info = GetItemData(dispInfo->item.hItem);
+    if (!info)
+        return FALSE;
+
+    hr = SHBindToParent(info->absolutePidl, IID_PPV_ARG(IShellFolder, 
&pParent), &pChild);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return FALSE;
+
+    hr = pParent->GetAttributesOf(1, &pChild, &dwAttr);
+    if (SUCCEEDED(hr) && (dwAttr & SFGAO_CANRENAME))
+    {
+        m_isEditing = TRUE;
+        m_oldSelected = NULL;
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+HRESULT CNSCBand::_UpdateBrowser(LPCITEMIDLIST pidlGoto)
+{
+    CComPtr<IShellBrowser> pBrowserService;
+    HRESULT hr = IUnknown_QueryService(m_pSite, SID_STopLevelBrowser,
+                                       IID_PPV_ARG(IShellBrowser, 
&pBrowserService));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    hr = pBrowserService->BrowseObject(pidlGoto, SBSP_SAMEBROWSER | 
SBSP_ABSOLUTE);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    return S_OK;
+}
+
+LRESULT CNSCBand::OnEndLabelEdit(_In_ LPNMTVDISPINFO dispInfo)
+{
+    CItemData *info = GetItemData(dispInfo->item.hItem);
+    HRESULT hr;
+
+    m_isEditing = FALSE;
+    if (m_oldSelected)
+    {
+        ++m_mtxBlockNavigate;
+        TreeView_SelectItem(m_hwndTreeView, m_oldSelected);
+        --m_mtxBlockNavigate;
+    }
+
+    if (!dispInfo->item.pszText)
+        return FALSE;
+
+    CComPtr<IShellFolder> pParent;
+    LPCITEMIDLIST pidlChild;
+    BOOL RenamedCurrent = _IsCurrentLocation(info->absolutePidl) == S_OK;
+
+    hr = SHBindToParent(info->absolutePidl, IID_PPV_ARG(IShellFolder, 
&pParent), &pidlChild);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return FALSE;
+
+    CComHeapPtr<ITEMIDLIST> pidlNew;
+    hr = pParent->SetNameOf(m_hWnd, pidlChild, dispInfo->item.pszText, 
SHGDN_INFOLDER, &pidlNew);
+    if (SUCCEEDED(hr) && pidlNew)
+    {
+        CComPtr<IPersistFolder2> pPersist;
+        hr = pParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pPersist));
+        if (FAILED_UNEXPECTEDLY(hr))
+            return FALSE;
+
+        CComHeapPtr<ITEMIDLIST> pidlParent;
+        hr = pPersist->GetCurFolder(&pidlParent);
+        if (FAILED_UNEXPECTEDLY(hr))
+            return FALSE;
+
+        CComHeapPtr<ITEMIDLIST> pidlNewAbs(ILCombine(pidlParent, pidlNew));
+        if (RenamedCurrent)
+        {
+            _UpdateBrowser(pidlNewAbs);
+        }
+        else
+        {
+            // Tell everyone if SetNameOf forgot, this causes IShellView to 
update itself when we rename a child
+            SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_IDLIST, 
info->absolutePidl, pidlNewAbs);
+        }
+
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+LRESULT CNSCBand::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
+{
+    NMHDR *pnmhdr = (NMHDR*)lParam;
+    switch (pnmhdr->code)
+    {
+        case TVN_ITEMEXPANDING:
+            return OnTreeItemExpanding((LPNMTREEVIEW)lParam);
+        //case TVN_SINGLEEXPAND:
+        case TVN_SELCHANGED:
+            if (pnmhdr->hwndFrom == m_hwndTreeView)
+                _OnSelectionChanged((LPNMTREEVIEW)lParam);
+            break;
+        case TVN_DELETEITEM:
+            OnTreeItemDeleted((LPNMTREEVIEW)lParam);
+            break;
+        case NM_CLICK:
+        case NM_RCLICK:
+            if (pnmhdr->hwndFrom == m_hwndTreeView)
+            {
+                TVHITTESTINFO HitTest;
+                ::GetCursorPos(&HitTest.pt);
+                ::ScreenToClient(m_hwndTreeView, &HitTest.pt);
+                TreeView_HitTest(m_hwndTreeView, &HitTest);
+
+                if (HitTest.flags & (TVHT_ABOVE | TVHT_BELOW | TVHT_NOWHERE))
+                    return TRUE; // Prevents click processing
+
+                if (HitTest.flags & TVHT_ONITEMBUTTON) // [+] / [-]
+                    break; // Do default processing
+
+                // Generate selection notification even if same item
+                m_hwndTreeView.SendMessage(WM_SETREDRAW, FALSE, 0);
+                TreeView_SelectItem(m_hwndTreeView, NULL);
+                TreeView_SelectItem(m_hwndTreeView, HitTest.hItem);
+                m_hwndTreeView.SendMessage(WM_SETREDRAW, TRUE, 0);
+
+                if (pnmhdr->code == NM_CLICK)
+                    return TRUE; // Prevents click processing
+            }
+            break;
+        case TVN_BEGINDRAG:
+        case TVN_BEGINRDRAG:
+            OnTreeItemDragging((LPNMTREEVIEW)lParam, pnmhdr->code == 
TVN_BEGINRDRAG);
+            break;
+        case TVN_BEGINLABELEDITW:
+            return OnBeginLabelEdit((LPNMTVDISPINFO)lParam);
+        case TVN_ENDLABELEDITW:
+            return OnEndLabelEdit((LPNMTVDISPINFO)lParam);
+        default:
+            break;
+    }
+
+    return 0;
+}
+
+// Temporary menu
+struct CMenuTemp
+{
+    HMENU m_hMenu = NULL;
+    CMenuTemp(HMENU hMenu) : m_hMenu(hMenu)
+    {
+    }
+    ~CMenuTemp()
+    {
+        if (m_hMenu)
+            ::DestroyMenu(m_hMenu);
+    }
+    operator HMENU() const
+    {
+        return m_hMenu;
+    }
+};
+
+// *** ATL event handlers ***
+LRESULT CNSCBand::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
+{
+    HWND hwndTarget = reinterpret_cast<HWND>(wParam);
+    if (hwndTarget && (hwndTarget == m_hwndToolbar || hwndTarget == m_hWnd))
+    {
+        FIXME("Show 'Close Toolbar' menu\n");
+        return 0;
+    }
+
+    HTREEITEM hItem = TreeView_GetSelection(m_hwndTreeView);
+    if (!hItem)
+        return 0;
+
+    POINT pt = { (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) };
+    if ((UINT)lParam == (UINT)-1)
+    {
+        RECT rc;
+        if (TreeView_GetItemRect(m_hwndTreeView, hItem, &rc, TRUE))
+        {
+            // Center of item rectangle
+            pt.x = (rc.left + rc.right) / 2;
+            pt.y = (rc.top + rc.bottom) / 2;
+        }
+        ClientToScreen(&pt);
+    }
+
+    CItemData *info = GetItemData(hItem);
+    if (!info)
+    {
+        ERR("No node data, something has gone wrong\n");
+        return 0;
+    }
+
+    CComPtr<IShellFolder> pFolder;
+    LPCITEMIDLIST pidlChild;
+    HRESULT hr = SHBindToParent(info->absolutePidl, IID_PPV_ARG(IShellFolder, 
&pFolder), &pidlChild);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return 0;
+
+    CComPtr<IContextMenu> contextMenu;
+    hr = pFolder->GetUIObjectOf(m_hWnd, 1, &pidlChild, 
IID_NULL_PPV_ARG(IContextMenu, &contextMenu));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return 0;
+
+    IUnknown_SetSite(contextMenu, (IDeskBand *)this);
+
+    UINT cmf = CMF_EXPLORE;
+    SFGAOF attr = SFGAO_CANRENAME;
+    hr = pFolder->GetAttributesOf(1, &pidlChild, &attr);
+    if (SUCCEEDED(hr) && (attr & SFGAO_CANRENAME))
+        cmf |= CMF_CANRENAME;
+
+    CMenuTemp menuTemp(::CreatePopupMenu());
+    UINT idCmdFirst = max(FCIDM_SHVIEWFIRST, 1);
+    hr = contextMenu->QueryContextMenu(menuTemp, 0, idCmdFirst, 
FCIDM_SHVIEWLAST, cmf);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return 0;
+
+    enum { flags = TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | 
TPM_RIGHTBUTTON };
+    UINT uCommand = ::TrackPopupMenu(menuTemp, flags, pt.x, pt.y, 0, m_hWnd, 
NULL);
+    if (uCommand)
+    {
+        uCommand -= idCmdFirst;
+
+        // Do DFM_CMD_RENAME in the treeview
+        if ((cmf & CMF_CANRENAME) && SHELL_IsVerb(contextMenu, uCommand, 
L"rename"))
+        {
+            m_hwndTreeView.SetFocus();
+            if (TreeView_EditLabel(m_hwndTreeView, hItem))
+                m_oldSelected = hItem;
+            return 0;
+        }
+
+        hr = _ExecuteCommand(contextMenu, uCommand);
+    }
+
+    return TRUE;
+}
+
+// WM_USER_SHELLEVENT
+LRESULT CNSCBand::OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled)
+{
+    // 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)
+    {
+        ERR("!hLock\n");
+        return 0;
+    }
+
+    OnChangeNotify(ppidl[0], ppidl[1], (lEvent & ~SHCNE_INTERRUPT));
+
+    SHChangeNotification_Unlock(hLock);
+    return 0;
+}
+
+// *** IOleWindow ***
+
+STDMETHODIMP CNSCBand::GetWindow(HWND *lphwnd)
+{
+    if (!lphwnd)
+        return E_INVALIDARG;
+    *lphwnd = m_hWnd;
+    return S_OK;
+}
+
+STDMETHODIMP CNSCBand::ContextSensitiveHelp(BOOL fEnterMode)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+// *** IDockingWindow ***
+
+STDMETHODIMP CNSCBand::CloseDW(DWORD dwReserved)
+{
+    // We do nothing, we don't have anything to save yet
+    TRACE("CloseDW called\n");
+    return S_OK;
+}
+
+STDMETHODIMP CNSCBand::ResizeBorderDW(const RECT *prcBorder, IUnknown 
*punkToolbarSite, BOOL fReserved)
+{
+    /* Must return E_NOTIMPL according to MSDN */
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CNSCBand::ShowDW(BOOL fShow)
+{
+    m_fVisible = fShow;
+    ShowWindow(fShow ? SW_SHOW : SW_HIDE);
+    return S_OK;
+}
+
+// *** IDeskBand ***
+
+STDMETHODIMP CNSCBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, 
DESKBANDINFO *pdbi)
+{
+    if (!pdbi)
+        return E_INVALIDARG;
+
+    m_dwBandID = dwBandID;
+
+    if (pdbi->dwMask & DBIM_MINSIZE)
+    {
+        pdbi->ptMinSize.x = 200;
+        pdbi->ptMinSize.y = 30;
+    }
+
+    if (pdbi->dwMask & DBIM_MAXSIZE)
+        pdbi->ptMaxSize.y = -1;
+
+    if (pdbi->dwMask & DBIM_INTEGRAL)
+        pdbi->ptIntegral.y = 1;
+
+    if (pdbi->dwMask & DBIM_ACTUAL)
+    {
+        pdbi->ptActual.x = 200;
+        pdbi->ptActual.y = 30;
+    }
+
+    if (pdbi->dwMask & DBIM_TITLE)
+    {
+        _GetTitle(pdbi->wszTitle, _countof(pdbi->wszTitle));
+    }
+
+    if (pdbi->dwMask & DBIM_MODEFLAGS)
+        pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
+
+    if (pdbi->dwMask & DBIM_BKCOLOR)
+        pdbi->dwMask &= ~DBIM_BKCOLOR;
+
+    return S_OK;
+}
+
+// *** IObjectWithSite ***
+
+STDMETHODIMP CNSCBand::SetSite(IUnknown *pUnkSite)
+{
+    HRESULT hr;
+
+    if (pUnkSite == m_pSite)
+        return S_OK;
+
+    TRACE("SetSite called\n");
+
+    if (!pUnkSite)
+    {
+        DestroyWindow();
+        m_hWnd = NULL;
+    }
+
+    if (pUnkSite != m_pSite)
+        m_pSite = NULL;
+
+    if (!pUnkSite)
+        return S_OK;
+
+    HWND hwndParent;
+    hr = IUnknown_GetWindow(pUnkSite, &hwndParent);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return E_INVALIDARG;
+
+    m_pSite = pUnkSite;
+
+    if (m_hWnd)
+    {
+        SetParent(hwndParent); // Change its parent
+    }
+    else
+    {
+        enum { style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | 
WS_CLIPCHILDREN };
+        this->Create(hwndParent, NULL, NULL, style, 0, 0U, NULL);
+    }
+
+    _RegisterChangeNotify();
+
+    return S_OK;
+}
+
+STDMETHODIMP CNSCBand::GetSite(REFIID riid, void **ppvSite)
+{
+    if (!ppvSite)
+        return E_POINTER;
+    *ppvSite = m_pSite;
+    return S_OK;
+}
+
+// *** IOleCommandTarget ***
+
+STDMETHODIMP CNSCBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, 
OLECMD prgCmds [], OLECMDTEXT *pCmdText)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CNSCBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD 
nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+// *** IServiceProvider ***
+
+STDMETHODIMP CNSCBand::QueryService(REFGUID guidService, REFIID riid, void 
**ppvObject)
+{
+    return IUnknown_QueryService(m_pSite, guidService, riid, ppvObject);
+}
+
+// *** IContextMenu ***
+
+STDMETHODIMP CNSCBand::QueryContextMenu(
+    HMENU hmenu,
+    UINT indexMenu,
+    UINT idCmdFirst,
+    UINT idCmdLast,
+    UINT uFlags)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CNSCBand::InvokeCommand(
+    LPCMINVOKECOMMANDINFO lpici)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CNSCBand::GetCommandString(
+    UINT_PTR idCmd,
+    UINT uType,
+    UINT *pwReserved,
+    LPSTR pszName,
+    UINT cchMax)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+// *** IInputObject ***
+
+STDMETHODIMP CNSCBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
+{
+    if (fActivate)
+    {
+        m_hwndTreeView.SetFocus();
+    }
+
+    if (lpMsg)
+    {
+        TranslateMessage(lpMsg);
+        DispatchMessage(lpMsg);
+    }
+
+    return S_OK;
+}
+
+STDMETHODIMP CNSCBand::HasFocusIO()
+{
+    return m_bFocused ? S_OK : S_FALSE;
+}
+
+STDMETHODIMP CNSCBand::TranslateAcceleratorIO(LPMSG lpMsg)
+{
+    if (lpMsg->hwnd == m_hWnd ||
+        (m_isEditing && IsChild(lpMsg->hwnd)))
+    {
+        TranslateMessage(lpMsg);
+        DispatchMessage(lpMsg);
+        return S_OK;
+    }
+
+    return S_FALSE;
+}
+
+// *** IPersist ***
+
+STDMETHODIMP CNSCBand::GetClassID(CLSID *pClassID)
+{
+    return E_NOTIMPL;
+}
+
+// *** IPersistStream ***
+
+STDMETHODIMP CNSCBand::IsDirty()
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CNSCBand::Load(IStream *pStm)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CNSCBand::Save(IStream *pStm, BOOL fClearDirty)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP CNSCBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+// *** IWinEventHandler ***
+
+STDMETHODIMP CNSCBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam, LRESULT *theResult)
+{
+    return S_OK;
+}
+
+STDMETHODIMP CNSCBand::IsWindowOwner(HWND hWnd)
+{
+    return SHIsChildOrSelf(m_hWnd, hWnd);
+}
+
+// *** IBandNavigate ***
+
+STDMETHODIMP CNSCBand::Select(LPCITEMIDLIST pidl)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+// *** INamespaceProxy ***
+
+// Returns the ITEMIDLIST that should be navigated when an item is invoked.
+STDMETHODIMP CNSCBand::GetNavigateTarget(
+    _In_ PCIDLIST_ABSOLUTE pidl,
+    _Out_ PIDLIST_ABSOLUTE *ppidlTarget,
+    _Out_ ULONG *pulAttrib)
+{
+    *pulAttrib = 0;
+    WCHAR szPath[MAX_PATH];
+    if (!SHGetPathFromIDListW(pidl, szPath))
+        return E_FAIL;
+
+    if (lstrcmpiW(PathFindExtensionW(szPath), L".lnk") == 0) // shortcut file?
+    {
+        WCHAR szTarget[MAX_PATH];
+        HRESULT hr = SHDOCVW_GetPathOfShortcut(m_hWnd, szPath, szTarget);
+        if (SUCCEEDED(hr))
+        {
+            lstrcpynW(szPath, szTarget, _countof(szPath));
+            *pulAttrib |= SFGAO_LINK;
+        }
+    }
+
+    if (PathIsDirectoryW(szPath) || PathIsRootW(szPath))
+        *pulAttrib |= SFGAO_FOLDER;
+
+    *ppidlTarget = ILCreateFromPathW(szPath);
+    return S_OK;
+}
+
+// Handles a user action on an item.
+STDMETHODIMP CNSCBand::Invoke(_In_ PCIDLIST_ABSOLUTE pidl)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+// Called when the user has selected an item.
+STDMETHODIMP CNSCBand::OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl)
+{
+    return S_OK;
+}
+
+// Returns flags used to update the tree control.
+STDMETHODIMP CNSCBand::RefreshFlags(
+    _Out_ DWORD *pdwStyle,
+    _Out_ DWORD *pdwExStyle,
+    _Out_ DWORD *dwEnum)
+{
+    *pdwStyle = _GetTVStyle();
+    *pdwExStyle = _GetTVExStyle();
+    *dwEnum = _GetEnumFlags();
+    return S_OK;
+}
+
+STDMETHODIMP CNSCBand::CacheItem(
+    _In_ PCIDLIST_ABSOLUTE pidl)
+{
+    UNIMPLEMENTED;
+    return E_NOTIMPL;
+}
+
+// *** IDropTarget methods ***
+STDMETHODIMP CNSCBand::DragEnter(IDataObject *pObj, DWORD glfKeyState, POINTL 
pt, DWORD *pdwEffect)
+{
+    ERR("Entering drag\n");
+    m_pCurObject = pObj;
+    m_oldSelected = TreeView_GetSelection(m_hwndTreeView);
+    return DragOver(glfKeyState, pt, pdwEffect);
+}
+
+STDMETHODIMP CNSCBand::DragOver(DWORD glfKeyState, POINTL pt, DWORD *pdwEffect)
+{
+    TVHITTESTINFO info;
+    info.pt.x = pt.x;
+    info.pt.y = pt.y;
+    info.flags = TVHT_ONITEM;
+    info.hItem = NULL;
+    ScreenToClient(&info.pt);
+
+    // Move to the item selected by the treeview (don't change right pane)
+    TreeView_HitTest(m_hwndTreeView, &info);
+
+    HRESULT hr;
+    if (!info.hItem)
+    {
+        m_childTargetNode = NULL;
+        m_pDropTarget = NULL;
+        *pdwEffect = DROPEFFECT_NONE;
+        return S_OK;
+    }
+
+    ++m_mtxBlockNavigate;
+    TreeView_SelectItem(m_hwndTreeView, info.hItem);
+    --m_mtxBlockNavigate;
+
+    // Delegate to shell folder
+    if (m_pDropTarget && info.hItem != m_childTargetNode)
+        m_pDropTarget = NULL;
+
+    if (info.hItem != m_childTargetNode)
+    {
+        CItemData *pItemData = GetItemData(info.hItem);
+        if (!pItemData)
+            return E_FAIL;
+
+        CComPtr<IShellFolder> pFolder;
+        if (_ILIsDesktop(pItemData->absolutePidl))
+        {
+            pFolder = m_pDesktop;
+        }
+        else
+        {
+            hr = m_pDesktop->BindToObject(pItemData->absolutePidl, 0, 
IID_PPV_ARG(IShellFolder, &pFolder));
+            if (!SUCCEEDED(hr))
+            {
+                /* Don't allow dnd since we couldn't get our folder object */
+                ERR("Can't bind to folder object\n");
+                *pdwEffect = DROPEFFECT_NONE;
+                return E_FAIL;
+            }
+        }
+
+        hr = pFolder->CreateViewObject(m_hWnd, IID_PPV_ARG(IDropTarget, 
&m_pDropTarget));
+        if (!SUCCEEDED(hr))
+        {
+            /* Don't allow dnd since we couldn't get our drop target */
+            ERR("Can't get drop target for folder object\n");
+            *pdwEffect = DROPEFFECT_NONE;
+            return E_FAIL;
+        }
+
+        hr = m_pDropTarget->DragEnter(m_pCurObject, glfKeyState, pt, 
pdwEffect);
+        m_childTargetNode = info.hItem;
+    }
+
+    if (m_pDropTarget)
+        hr = m_pDropTarget->DragOver(glfKeyState, pt, pdwEffect);
+
+    return S_OK;
+}
+
+STDMETHODIMP CNSCBand::DragLeave()
+{
+    ++m_mtxBlockNavigate;
+    TreeView_SelectItem(m_hwndTreeView, m_oldSelected);
+    --m_mtxBlockNavigate;
+    m_childTargetNode = NULL;
+    if (m_pCurObject)
+        m_pCurObject = NULL;
+    return S_OK;
+}
+
+STDMETHODIMP CNSCBand::Drop(IDataObject *pObj, DWORD glfKeyState, POINTL pt, 
DWORD *pdwEffect)
+{
+    if (!m_pDropTarget)
+        return E_FAIL;
+    m_pDropTarget->Drop(pObj, glfKeyState, pt, pdwEffect);
+    DragLeave();
+    return S_OK;
+}
+
+// *** IDropSource methods ***
+
+STDMETHODIMP CNSCBand::QueryContinueDrag(BOOL fEscapePressed, DWORD 
grfKeyState)
+{
+    if (fEscapePressed)
+        return DRAGDROP_S_CANCEL;
+    if ((grfKeyState & MK_LBUTTON) || (grfKeyState & MK_RBUTTON))
+        return S_OK;
+    return DRAGDROP_S_DROP;
+}
+
+STDMETHODIMP CNSCBand::GiveFeedback(DWORD dwEffect)
+{
+    return DRAGDROP_S_USEDEFAULTCURSORS;
+}
diff --git a/dll/win32/shdocvw/CNSCBand.h b/dll/win32/shdocvw/CNSCBand.h
new file mode 100644
index 00000000000..f6c06afeb98
--- /dev/null
+++ b/dll/win32/shdocvw/CNSCBand.h
@@ -0,0 +1,231 @@
+/*
+ * PROJECT:     ReactOS shdocvw
+ * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE:     NameSpace Control Band
+ * COPYRIGHT:   Copyright 2024 Katayama Hirofumi MZ 
<katayama.hirofumi...@gmail.com>
+ */
+
+#pragma once
+
+#define NSCBANDCLASSNAME L"ReactOS NameSpace Control Band"
+
+#define WM_USER_SHELLEVENT (WM_USER + 88)
+
+#ifdef __cplusplus
+class CNSCBand
+    : public CWindowImpl<CNSCBand>
+    , public IDeskBand
+    , public IObjectWithSite
+    , public IInputObject
+    , public IPersistStream
+    , public IOleCommandTarget
+    , public IServiceProvider
+    , public IContextMenu
+    , public IBandNavigate
+    , public IWinEventHandler
+    , public INamespaceProxy
+    , public IDropTarget
+    , public IDropSource
+{
+public:
+    DECLARE_WND_CLASS_EX(NSCBANDCLASSNAME, 0, COLOR_3DFACE)
+    static LPCWSTR GetWndClassName() { return NSCBANDCLASSNAME; }
+
+    CNSCBand();
+    virtual ~CNSCBand();
+
+    // The node of TreeView
+    struct CItemData
+    {
+        CComHeapPtr<ITEMIDLIST> absolutePidl;
+        CComHeapPtr<ITEMIDLIST> relativePidl;
+        BOOL expanded = FALSE;
+    };
+    CItemData* GetItemData(_In_ HTREEITEM hItem);
+
+    // *** IOleWindow methods ***
+    STDMETHODIMP GetWindow(HWND *lphwnd) override;
+    STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) override;
+
+    // *** IDockingWindow methods ***
+    STDMETHODIMP CloseDW(DWORD dwReserved) override;
+    STDMETHODIMP ResizeBorderDW(const RECT *prcBorder, IUnknown 
*punkToolbarSite, BOOL fReserved) override;
+    STDMETHODIMP ShowDW(BOOL fShow) override;
+
+    // *** IDeskBand methods ***
+    STDMETHODIMP GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO 
*pdbi) override;
+
+    // *** IObjectWithSite methods ***
+    STDMETHODIMP SetSite(IUnknown *pUnkSite) override;
+    STDMETHODIMP GetSite(REFIID riid, void **ppvSite) override;
+
+    // *** IOleCommandTarget methods ***
+    STDMETHODIMP QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD 
prgCmds [], OLECMDTEXT *pCmdText) override;
+    STDMETHODIMP Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD 
nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) override;
+
+    // *** IServiceProvider methods ***
+    STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void 
**ppvObject) override;
+
+    // *** IContextMenu methods ***
+    STDMETHODIMP QueryContextMenu(
+        HMENU hmenu,
+        UINT indexMenu,
+        UINT idCmdFirst,
+        UINT idCmdLast,
+        UINT uFlags) override;
+    STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpici) override;
+    STDMETHODIMP GetCommandString(
+        UINT_PTR idCmd,
+        UINT uType,
+        UINT *pwReserved,
+        LPSTR pszName,
+        UINT cchMax) override;
+
+    // *** IInputObject methods ***
+    STDMETHODIMP UIActivateIO(BOOL fActivate, LPMSG lpMsg) override;
+    STDMETHODIMP HasFocusIO() override;
+    STDMETHODIMP TranslateAcceleratorIO(LPMSG lpMsg) override;
+
+    // *** IPersist methods ***
+    STDMETHODIMP GetClassID(CLSID *pClassID) override;
+
+    // *** IPersistStream methods ***
+    STDMETHODIMP IsDirty() override;
+    STDMETHODIMP Load(IStream *pStm) override;
+    STDMETHODIMP Save(IStream *pStm, BOOL fClearDirty) override;
+    STDMETHODIMP GetSizeMax(ULARGE_INTEGER *pcbSize) override;
+
+    // *** IWinEventHandler methods ***
+    STDMETHODIMP OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM 
lParam, LRESULT *theResult) override;
+    STDMETHODIMP IsWindowOwner(HWND hWnd) override;
+
+    // *** IBandNavigate methods ***
+    STDMETHODIMP Select(LPCITEMIDLIST pidl) override;
+
+    // *** INamespaceProxy methods ***
+    STDMETHODIMP GetNavigateTarget(
+        _In_ PCIDLIST_ABSOLUTE pidl,
+        _Out_ PIDLIST_ABSOLUTE *ppidlTarget,
+        _Out_ ULONG *pulAttrib) override;
+    STDMETHODIMP Invoke(_In_ PCIDLIST_ABSOLUTE pidl) override;
+    STDMETHODIMP OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl) override;
+    STDMETHODIMP RefreshFlags(
+        _Out_ DWORD *pdwStyle,
+        _Out_ DWORD *pdwExStyle,
+        _Out_ DWORD *dwEnum) override;
+    STDMETHODIMP CacheItem(_In_ PCIDLIST_ABSOLUTE pidl) override;
+
+    // *** IDropTarget methods ***
+    STDMETHODIMP DragEnter(IDataObject *pObj, DWORD glfKeyState, POINTL pt, 
DWORD *pdwEffect) override;
+    STDMETHODIMP DragOver(DWORD glfKeyState, POINTL pt, DWORD *pdwEffect) 
override;
+    STDMETHODIMP DragLeave() override;
+    STDMETHODIMP Drop(IDataObject *pObj, DWORD glfKeyState, POINTL pt, DWORD 
*pdwEffect) override;
+
+    // *** IDropSource methods ***
+    STDMETHODIMP QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) 
override;
+    STDMETHODIMP GiveFeedback(DWORD dwEffect) override;
+
+protected:
+    DWORD m_dwTVStyle = 0;
+    DWORD m_dwTVExStyle = 0;
+    DWORD m_dwEnumFlags = 0;
+    BOOL m_fVisible = FALSE;
+    BOOL m_bFocused = FALSE;
+    DWORD m_dwBandID = 0;
+    CComPtr<IUnknown> m_pSite;
+    CComPtr<IShellFolder> m_pDesktop;
+    CComHeapPtr<ITEMIDLIST> m_pidlRoot;
+    HIMAGELIST m_hToolbarImageList = NULL;
+    CToolbar<> m_hwndToolbar;
+    CTreeView m_hwndTreeView;
+    LONG m_mtxBlockNavigate = 0; // A "lock" that prevents internal selection 
changes to initiate a navigation to the newly selected item.
+    BOOL m_isEditing = FALSE;
+    HTREEITEM m_hRoot = NULL;
+    HTREEITEM m_oldSelected = NULL;
+    DWORD m_adviseCookie = 0;
+    ULONG m_shellRegID = 0;
+
+    // *** Drop target information ***
+    CComPtr<IDropTarget> m_pDropTarget;
+    HTREEITEM m_childTargetNode = NULL;
+    CComPtr<IDataObject> m_pCurObject;
+
+    VOID OnFinalMessage(HWND) override;
+
+    // *** helper methods ***
+    virtual INT _GetRootCsidl() = 0;
+    virtual HRESULT _CreateTreeView(HWND hwndParent);
+    virtual HRESULT _CreateToolbar(HWND hwndParent) { return S_OK; }
+    virtual void _DestroyTreeView();
+    virtual void _DestroyToolbar();
+    virtual DWORD _GetTVStyle() = 0;
+    virtual DWORD _GetTVExStyle() = 0;
+    virtual DWORD _GetEnumFlags() = 0;
+    virtual BOOL _GetTitle(LPWSTR pszTitle, INT cchTitle) = 0;
+    virtual BOOL _WantsRootItem() = 0;
+    virtual void _SortItems(HTREEITEM hParent) = 0;
+    void _RegisterChangeNotify();
+    void _UnregisterChangeNotify();
+    BOOL OnTreeItemExpanding(_In_ LPNMTREEVIEW pnmtv);
+    BOOL OnTreeItemDeleted(_In_ LPNMTREEVIEW pnmtv);
+    void _OnSelectionChanged(_In_ LPNMTREEVIEW pnmtv);
+    void OnTreeItemDragging(_In_ LPNMTREEVIEW pnmtv, _In_ BOOL isRightClick);
+    LRESULT OnBeginLabelEdit(_In_ LPNMTVDISPINFO dispInfo);
+    LRESULT OnEndLabelEdit(_In_ LPNMTVDISPINFO dispInfo);
+    void OnChangeNotify(
+        _In_opt_ LPCITEMIDLIST pidl0,
+        _In_opt_ LPCITEMIDLIST pidl1,
+        _In_ LONG lEvent);
+    HRESULT _ExecuteCommand(_In_ CComPtr<IContextMenu>& menu, _In_ UINT nCmd);
+    HTREEITEM _InsertItem(
+        _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, LPCITEMIDLIST entry);
+    HRESULT _UpdateBrowser(LPCITEMIDLIST pidlGoto);
+    HRESULT _GetCurrentLocation(_Out_ PIDLIST_ABSOLUTE *ppidl);
+    HRESULT _IsCurrentLocation(_In_ PCIDLIST_ABSOLUTE pidl);
+    void _Refresh();
+    void _RefreshRecurse(_In_ HTREEITEM hItem);
+    BOOL _IsTreeItemInEnum(_In_ HTREEITEM hItem, _In_ IEnumIDList *pEnum);
+    BOOL _TreeItemHasThisChild(_In_ HTREEITEM hItem, _In_ PCITEMID_CHILD 
pidlChild);
+    HRESULT _GetItemEnum(
+        _Out_ CComPtr<IEnumIDList>& pEnum,
+        _In_ HTREEITEM hItem,
+        _Out_opt_ IShellFolder **ppFolder = NULL);
+    BOOL _ItemHasAnyChild(_In_ HTREEITEM hItem);
+    HRESULT _AddFavorite();
+
+    // *** ATL message handlers ***
+    LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
+    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
+    LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
+    LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    LRESULT OnShellEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL 
&bHandled);
+
+    BEGIN_MSG_MAP(CNSCBand)
+        MESSAGE_HANDLER(WM_CREATE, OnCreate)
+        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+        MESSAGE_HANDLER(WM_SIZE, OnSize)
+        MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
+        MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
+        MESSAGE_HANDLER(WM_COMMAND, OnCommand)
+        MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
+        MESSAGE_HANDLER(WM_TIMER, OnTimer)
+        MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
+        MESSAGE_HANDLER(WM_USER_SHELLEVENT, OnShellEvent)
+    END_MSG_MAP()
+};
+#endif // def __cplusplus
diff --git a/sdk/include/reactos/shlobj_undoc.h 
b/sdk/include/reactos/shlobj_undoc.h
index c572dc36930..c9796909aa1 100644
--- a/sdk/include/reactos/shlobj_undoc.h
+++ b/sdk/include/reactos/shlobj_undoc.h
@@ -506,7 +506,7 @@ DECLARE_INTERFACE_(IBandNavigate, IUnknown)
        STDMETHOD_(ULONG,AddRef)(THIS) PURE;
        STDMETHOD_(ULONG,Release)(THIS) PURE;
         /*** IBandNavigate ***/
-       STDMETHOD(Select)(THIS_ long paramC) PURE;
+       STDMETHOD(Select)(THIS_ LPCITEMIDLIST pidl) PURE;
 };
 #undef INTERFACE
 
@@ -528,7 +528,7 @@ DECLARE_INTERFACE_(INamespaceProxy, IUnknown)
        STDMETHOD_(ULONG,AddRef)(THIS) PURE;
        STDMETHOD_(ULONG,Release)(THIS) PURE;
         /*** INamespaceProxy ***/
-       STDMETHOD(GetNavigateTarget)(THIS_ _In_ PCIDLIST_ABSOLUTE pidl, _Out_ 
PIDLIST_ABSOLUTE ppidlTarget, _Out_ ULONG *pulAttrib) PURE;
+       STDMETHOD(GetNavigateTarget)(THIS_ _In_ PCIDLIST_ABSOLUTE pidl, _Out_ 
PIDLIST_ABSOLUTE *ppidlTarget, _Out_ ULONG *pulAttrib) PURE;
        STDMETHOD(Invoke)(THIS_ _In_ PCIDLIST_ABSOLUTE pidl) PURE;
        STDMETHOD(OnSelectionChanged)(THIS_ _In_ PCIDLIST_ABSOLUTE pidl) PURE;
        STDMETHOD(RefreshFlags)(THIS_ _Out_ DWORD *pdwStyle, _Out_ DWORD 
*pdwExStyle, _Out_ DWORD *dwEnum) PURE;

Reply via email to