[BROWSEUI] Enable the Disconnect Network Drive menu item. (#1522)
[reactos.git] / dll / win32 / browseui / shellbrowser.cpp
index 41a8ed8..2f30312 100644 (file)
 #include <shellapi.h>
 #include <htiframe.h>
 #include <strsafe.h>
-
-#define USE_CUSTOM_EXPLORERBAND 1
-
-extern "C"
-BOOL WINAPI Shell_GetImageLists(
-    _Out_  HIMAGELIST *phiml,
-    _Out_  HIMAGELIST *phimlSmall);
+#include <undocshell.h>
 
 extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow);
 
@@ -123,15 +117,8 @@ TODO:
     "language='*'\"")
 #endif // __GNUC__
 
-struct categoryCacheHeader
-{
-    long                dwSize;         // size of header only
-    long                version;        // currently 1
-    SYSTEMTIME          writeTime;      // time we were written to registry
-    long                classCount;     // number of classes following
-};
-
 static const unsigned int                   folderOptionsPageCountMax = 20;
+static const long                           BTP_DONT_UPDATE_HISTORY = 0;
 static const long                           BTP_UPDATE_CUR_HISTORY = 1;
 static const long                           BTP_UPDATE_NEXT_HISTORY = 2;
 
@@ -141,42 +128,6 @@ BOOL                                        createNewStuff = false;
 // this class is private to browseui.dll and is not registered externally?
 //DEFINE_GUID(CLSID_ShellFldSetExt, 0x6D5313C0, 0x8C62, 0x11D1, 0xB2, 0xCD, 0x00, 0x60, 0x97, 0xDF, 0x8C, 0x11);
 
-
-extern HRESULT CreateTravelLog(REFIID riid, void **ppv);
-extern HRESULT CreateBaseBar(REFIID riid, void **ppv);
-extern HRESULT CreateBaseBarSite(REFIID riid, void **ppv);
-
-// temporary
-extern HRESULT CreateInternetToolbar(REFIID riid, void **ppv);
-
-
-HMENU SHGetMenuFromID(HMENU topMenu, int theID)
-{
-    MENUITEMINFO                            menuItemInfo;
-
-    menuItemInfo.cbSize = sizeof(menuItemInfo);
-    menuItemInfo.fMask = MIIM_SUBMENU;
-    if (!GetMenuItemInfo(topMenu, theID, FALSE, &menuItemInfo))
-        return NULL;
-    return menuItemInfo.hSubMenu;
-}
-
-void SHCheckMenuItem(HMENU theMenu, int theID, BOOL checked)
-{
-    MENUITEMINFO                            menuItemInfo;
-
-    menuItemInfo.cbSize = sizeof(menuItemInfo);
-    menuItemInfo.fMask = MIIM_STATE;
-    if (GetMenuItemInfo(theMenu, theID, FALSE, &menuItemInfo))
-    {
-        if (checked)
-            menuItemInfo.fState |= MF_CHECKED;
-        else
-            menuItemInfo.fState &= ~MF_CHECKED;
-        SetMenuItemInfo(theMenu, theID, FALSE, &menuItemInfo);
-    }
-}
-
 void DeleteMenuItems(HMENU theMenu, unsigned int firstIDToDelete, unsigned int lastIDToDelete)
 {
     MENUITEMINFO                            menuItemInfo;
@@ -216,8 +167,8 @@ HRESULT WINAPI SHBindToFolder(LPCITEMIDLIST path, IShellFolder **newFolder)
     return desktop->BindToObject (path, NULL, IID_PPV_ARG(IShellFolder, newFolder));
 }
 
-static const TCHAR szCabinetWndClass[] = TEXT("CabinetWClassX");
-static const TCHAR szExploreWndClass[] = TEXT("ExploreWClassX");
+static const TCHAR szCabinetWndClass[] = TEXT("CabinetWClass");
+//static const TCHAR szExploreWndClass[] = TEXT("ExploreWClass");
 
 class CDockManager;
 class CShellBrowser;
@@ -229,7 +180,7 @@ private:
     CComPtr<IExplorerToolbar>               fExplorerToolbar;
 public:
     void Initialize(HWND parent, IUnknown *explorerToolbar);
-
+    void Destroy();
 private:
 
     // message handlers
@@ -257,6 +208,12 @@ void CToolbarProxy::Initialize(HWND parent, IUnknown *explorerToolbar)
     }
 }
 
+void CToolbarProxy::Destroy()
+{
+    DestroyWindow();
+    fExplorerToolbar = NULL;
+}
+
 LRESULT CToolbarProxy::OnAddBitmap(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
     long int                                result;
@@ -290,6 +247,11 @@ Switch to a new bar when it receives an Exec(CGID_IDeskBand, 1, 1, vaIn, NULL);
     rebar
 */
 
+struct MenuBandInfo {
+    GUID barGuid;
+    BOOL fVertical;
+};
+
 class CShellBrowser :
     public CWindowImpl<CShellBrowser, CWindow, CFrameWinTraits>,
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
@@ -312,6 +274,12 @@ private:
     class barInfo
     {
     public:
+        barInfo()
+        {
+            memset(&borderSpace, 0, sizeof(borderSpace));
+            hwnd = NULL;
+        }
+
         RECT                                borderSpace;
         CComPtr<IUnknown>                   clientBar;
         HWND                                hwnd;
@@ -331,11 +299,13 @@ private:
     CComPtr<ITravelLog>                     fTravelLog;
     HMENU                                   fCurrentMenuBar;
     CABINETSTATE                            fCabinetState;
+    GUID                                    fCurrentVertBar;             //The guid of the built in vertical bar that is being shown
     // The next three fields support persisted history for shell views.
     // They do not need to be reference counted.
     IOleObject                              *fHistoryObject;
     IStream                                 *fHistoryStream;
     IBindCtx                                *fHistoryBindContext;
+    HDSA menuDsa;
     HACCEL m_hAccel;
 public:
 #if 0
@@ -353,18 +323,22 @@ public:
 
     CShellBrowser();
     ~CShellBrowser();
-    HRESULT Initialize(LPITEMIDLIST pidl, long b, long c, long d);
+    HRESULT Initialize();
 public:
     HRESULT BrowseToPIDL(LPCITEMIDLIST pidl, long flags);
     HRESULT BrowseToPath(IShellFolder *newShellFolder, LPCITEMIDLIST absolutePIDL,
         FOLDERSETTINGS *folderSettings, long flags);
     HRESULT GetMenuBand(REFIID riid, void **shellMenu);
-    HRESULT GetBaseBar(bool vertical, IUnknown **theBaseBar);
+    HRESULT GetBaseBar(bool vertical, REFIID riid, void **theBaseBar);
+    BOOL IsBandLoaded(const CLSID clsidBand, bool verticali, DWORD *pdwBandID);
     HRESULT ShowBand(const CLSID &classID, bool vertical);
     HRESULT NavigateToParent();
     HRESULT DoFolderOptions();
     static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
     void RepositionBars();
+    HRESULT BuildExplorerBandMenu();
+    HRESULT BuildExplorerBandCategory(HMENU hBandsMenu, CATID category, DWORD dwPos, UINT *nbFound);
+    BOOL IsBuiltinBand(CLSID &bandID);
     virtual WNDPROC GetWindowProc()
     {
         return WindowProc;
@@ -374,6 +348,7 @@ public:
     HRESULT FireCommandStateChange(bool newState, int commandID);
     HRESULT FireCommandStateChangeAll();
     HRESULT UpdateForwardBackState();
+    HRESULT UpdateUpState();
     void UpdateGotoMenu(HMENU theMenu);
     void UpdateViewMenu(HMENU theMenu);
 
@@ -624,7 +599,9 @@ public:
     LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
     LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
     LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
     LRESULT RelayMsgToShellView(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
     LRESULT OnClose(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnFolderOptions(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnMapNetworkDrive(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
@@ -635,7 +612,6 @@ public:
     LRESULT OnGoUpLevel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnBackspace(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnGoHome(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
-    LRESULT OnIsThisLegal(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnOrganizeFavorites(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnToggleStatusBarVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnToggleToolbarLock(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
@@ -645,7 +621,10 @@ public:
     LRESULT OnToggleTextLabels(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnToolbarCustomize(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnGoTravel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
+    LRESULT OnRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
+    LRESULT OnExplorerBar(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    HRESULT OnSearch();
 
     static ATL::CWndClassInfo& GetWndClassInfo()
     {
@@ -664,9 +643,11 @@ public:
         MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
         MESSAGE_HANDLER(WM_SIZE, OnSize)
         MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
+        MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
         MESSAGE_HANDLER(WM_MEASUREITEM, RelayMsgToShellView)
         MESSAGE_HANDLER(WM_DRAWITEM, RelayMsgToShellView)
         MESSAGE_HANDLER(WM_MENUSELECT, RelayMsgToShellView)
+        MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
         COMMAND_ID_HANDLER(IDM_FILE_CLOSE, OnClose)
         COMMAND_ID_HANDLER(IDM_TOOLS_FOLDEROPTIONS, OnFolderOptions)
         COMMAND_ID_HANDLER(IDM_TOOLS_MAPNETWORKDRIVE, OnMapNetworkDrive)
@@ -677,16 +658,21 @@ public:
         COMMAND_ID_HANDLER(IDM_GOTO_UPONELEVEL, OnGoUpLevel)
         COMMAND_ID_HANDLER(IDM_GOTO_HOMEPAGE, OnGoHome)
         COMMAND_ID_HANDLER(IDM_FAVORITES_ORGANIZEFAVORITES, OnOrganizeFavorites)
-        COMMAND_ID_HANDLER(IDM_HELP_ISTHISCOPYLEGAL, OnIsThisLegal)
         COMMAND_ID_HANDLER(IDM_VIEW_STATUSBAR, OnToggleStatusBarVisible)
+        COMMAND_ID_HANDLER(IDM_VIEW_REFRESH, OnRefresh)
         COMMAND_ID_HANDLER(IDM_TOOLBARS_LOCKTOOLBARS, OnToggleToolbarLock)
         COMMAND_ID_HANDLER(IDM_TOOLBARS_STANDARDBUTTONS, OnToggleToolbarBandVisible)
         COMMAND_ID_HANDLER(IDM_TOOLBARS_ADDRESSBAR, OnToggleAddressBandVisible)
         COMMAND_ID_HANDLER(IDM_TOOLBARS_LINKSBAR, OnToggleLinksBandVisible)
         COMMAND_ID_HANDLER(IDM_TOOLBARS_TEXTLABELS, OnToggleTextLabels)
         COMMAND_ID_HANDLER(IDM_TOOLBARS_CUSTOMIZE, OnToolbarCustomize)
+        COMMAND_ID_HANDLER(IDM_EXPLORERBAR_SEARCH, OnExplorerBar)
+        COMMAND_ID_HANDLER(IDM_EXPLORERBAR_FOLDERS, OnExplorerBar)
+        COMMAND_ID_HANDLER(IDM_EXPLORERBAR_HISTORY, OnExplorerBar)
+        COMMAND_ID_HANDLER(IDM_EXPLORERBAR_FAVORITES, OnExplorerBar)
         COMMAND_ID_HANDLER(IDM_BACKSPACE, OnBackspace)
         COMMAND_RANGE_HANDLER(IDM_GOTO_TRAVEL_FIRSTTARGET, IDM_GOTO_TRAVEL_LASTTARGET, OnGoTravel)
+        COMMAND_RANGE_HANDLER(IDM_EXPLORERBAND_BEGINCUSTOM, IDM_EXPLORERBAND_ENDCUSTOM, OnExplorerBar)
         MESSAGE_HANDLER(WM_COMMAND, RelayCommands)
     END_MSG_MAP()
 
@@ -725,7 +711,6 @@ CShellBrowser::CShellBrowser()
     fCurrentDirectoryPIDL = NULL;
     fStatusBar = NULL;
     fStatusBarVisible = true;
-    memset(fClientBars, 0, sizeof(fClientBars));
     fCurrentMenuBar = NULL;
     fHistoryObject = NULL;
     fHistoryStream = NULL;
@@ -734,9 +719,11 @@ CShellBrowser::CShellBrowser()
 
 CShellBrowser::~CShellBrowser()
 {
+    if (menuDsa)
+        DSA_Destroy(menuDsa);
 }
 
-HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, long b, long c, long d)
+HRESULT CShellBrowser::Initialize()
 {
     CComPtr<IPersistStreamInit>             persistStreamInit;
     HRESULT                                 hResult;
@@ -744,6 +731,10 @@ HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, long b, long c, long d)
 
     _AtlInitialConstruct();
 
+    menuDsa = DSA_Create(sizeof(MenuBandInfo), 5);
+    if (!menuDsa)
+        return E_OUTOFMEMORY;
+
     fCabinetState.cLength = sizeof(fCabinetState);
     if (ReadCabinetState(&fCabinetState, sizeof(fCabinetState)) == FALSE)
     {
@@ -754,15 +745,9 @@ HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, long b, long c, long d)
     if (m_hWnd == NULL)
         return E_FAIL;
 
-#if 0
-    hResult = CoCreateInstance(CLSID_InternetToolbar, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &fClientBars[BIInternetToolbar].clientBar));
+    hResult = CInternetToolbar_CreateInstance(IID_PPV_ARG(IUnknown, &clientBar));
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
-#else
-    hResult = CreateInternetToolbar(IID_PPV_ARG(IUnknown, &clientBar));
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return hResult;
-#endif
 
     fClientBars[BIInternetToolbar].clientBar = clientBar;
 
@@ -807,12 +792,8 @@ HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, long b, long c, long d)
     fStatusBarVisible = true;
 
 
-    // browse 
-    hResult = BrowseToPIDL(pidl, BTP_UPDATE_NEXT_HISTORY);
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return hResult;
-
     ShowWindow(SW_SHOWNORMAL);
+    UpdateWindow();
 
     return S_OK;
 }
@@ -837,11 +818,6 @@ HRESULT CShellBrowser::BrowseToPIDL(LPCITEMIDLIST pidl, long flags)
     return S_OK;
 }
 
-BOOL WINAPI _ILIsDesktop(LPCITEMIDLIST pidl)
-{
-    return (pidl == NULL || pidl->mkid.cb == 0);
-}
-
 BOOL WINAPI _ILIsPidlSimple(LPCITEMIDLIST pidl)
 {
     LPCITEMIDLIST                           pidlnext;
@@ -985,9 +961,7 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
         ::SendMessage(fCurrentShellViewWindow, WM_SETREDRAW, 0, 0);
 
     // set site
-    hResult = newShellView->QueryInterface(IID_PPV_ARG(IObjectWithSite, &objectWithSite));
-    if (SUCCEEDED(hResult) && objectWithSite.p != NULL)
-        hResult = objectWithSite->SetSite(static_cast<IDropTarget *>(this));
+    hResult = IUnknown_SetSite(newShellView, static_cast<IDropTarget *>(this));
 
     // update folder and view
     saveCurrentShellFolder = fCurrentShellFolder;
@@ -1028,6 +1002,11 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
         saveCurrentShellView->DestroyViewWindow();
     fCurrentShellViewWindow = newShellViewWindow;
 
+    if (previousView == NULL)
+    {
+        RepositionBars();
+    }
+
     // no use
     saveCurrentShellView.Release();
     saveCurrentShellFolder.Release();
@@ -1074,29 +1053,32 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
         HIMAGELIST himlSmall, himlLarge;
 
         CComPtr<IShellFolder> sf;
-        SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
-
-        index = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen);
+        hResult = SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
+        if (SUCCEEDED(hResult))
+        {
+            index = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen);
 
-        Shell_GetImageLists(&himlLarge, &himlSmall);
+            Shell_GetImageLists(&himlLarge, &himlSmall);
 
-        HICON icSmall = ImageList_GetIcon(himlSmall, indexOpen, 0);
-        HICON icLarge = ImageList_GetIcon(himlLarge, indexOpen, 0);
+            HICON icSmall = ImageList_GetIcon(himlSmall, indexOpen, 0);
+            HICON icLarge = ImageList_GetIcon(himlLarge, indexOpen, 0);
 
-        /* Hack to make it possible to release the old icons */
-        /* Something seems to go wrong with WM_SETICON */
-        HICON oldSmall = (HICON)SendMessage(WM_GETICON, ICON_SMALL, 0);
-        HICON oldLarge = (HICON)SendMessage(WM_GETICON, ICON_BIG,   0);
+            /* Hack to make it possible to release the old icons */
+            /* Something seems to go wrong with WM_SETICON */
+            HICON oldSmall = (HICON)SendMessage(WM_GETICON, ICON_SMALL, 0);
+            HICON oldLarge = (HICON)SendMessage(WM_GETICON, ICON_BIG,   0);
 
-        SendMessage(WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icSmall));
-        SendMessage(WM_SETICON, ICON_BIG,   reinterpret_cast<LPARAM>(icLarge));
+            SendMessage(WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icSmall));
+            SendMessage(WM_SETICON, ICON_BIG,   reinterpret_cast<LPARAM>(icLarge));
 
-        DestroyIcon(oldSmall);
-        DestroyIcon(oldLarge);
+            DestroyIcon(oldSmall);
+            DestroyIcon(oldLarge);
+        }
     }
 
     FireCommandStateChangeAll();
     hResult = UpdateForwardBackState();
+    hResult = UpdateUpState();
     return S_OK;
 }
 
@@ -1120,7 +1102,7 @@ HRESULT CShellBrowser::GetMenuBand(REFIID riid, void **shellMenu)
     return deskBand->QueryInterface(riid, shellMenu);
 }
 
-HRESULT CShellBrowser::GetBaseBar(bool vertical, IUnknown **theBaseBar)
+HRESULT CShellBrowser::GetBaseBar(bool vertical, REFIID riid, void **theBaseBar)
 {
     CComPtr<IUnknown>                       newBaseBar;
     CComPtr<IDeskBar>                       deskBar;
@@ -1135,13 +1117,17 @@ HRESULT CShellBrowser::GetBaseBar(bool vertical, IUnknown **theBaseBar)
         cache = &fClientBars[BIHorizontalBaseBar].clientBar.p;
     if (*cache == NULL)
     {
-        hResult = CreateBaseBar(IID_PPV_ARG(IUnknown, &newBaseBar));
+        hResult = CBaseBar_CreateInstance(IID_PPV_ARG(IUnknown, &newBaseBar), vertical);
         if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
-        hResult = CreateBaseBarSite(IID_PPV_ARG(IUnknown, &newBaseBarSite));
+        hResult = CBaseBarSite_CreateInstance(IID_PPV_ARG(IUnknown, &newBaseBarSite), vertical);
         if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
-
+    
+        // we have to store our basebar into cache now
+        *cache = newBaseBar;
+        newBaseBar->AddRef();
+        
         // tell the new base bar about the shell browser
         hResult = IUnknown_SetSite(newBaseBar, static_cast<IDropTarget *>(this));
         if (FAILED_UNEXPECTEDLY(hResult))
@@ -1163,9 +1149,57 @@ HRESULT CShellBrowser::GetBaseBar(bool vertical, IUnknown **theBaseBar)
         if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
 
-        *cache = newBaseBar.Detach();
     }
-    return (*cache)->QueryInterface(IID_PPV_ARG(IUnknown, theBaseBar));
+    return (*cache)->QueryInterface(riid, theBaseBar);
+}
+
+BOOL CShellBrowser::IsBandLoaded(const CLSID clsidBand, bool vertical, DWORD *pdwBandID)
+{
+    HRESULT                                 hResult;
+    CComPtr<IDeskBar>                       deskBar;
+    CComPtr<IUnknown>                       baseBarSite;
+    CComPtr<IBandSite>                      bandSite;
+    CLSID                                   clsidTmp;
+    DWORD                                   numBands;
+    DWORD                                   dwBandID;
+    DWORD                                   i;
+
+    /* Get our basebarsite to be able to enumerate bands */
+    hResult = GetBaseBar(vertical, IID_PPV_ARG(IDeskBar, &deskBar));
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return FALSE;
+    hResult = deskBar->GetClient(&baseBarSite);
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return FALSE;
+    hResult = baseBarSite->QueryInterface(IID_PPV_ARG(IBandSite, &bandSite));
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return FALSE;
+
+    hResult = bandSite->EnumBands(-1, &numBands);
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return FALSE;
+
+    for(i = 0; i < numBands; i++)
+    {
+        CComPtr<IPersist> bandPersist;
+
+        hResult = bandSite->EnumBands(i, &dwBandID);
+        if (FAILED_UNEXPECTEDLY(hResult))
+            return FALSE;
+
+        hResult = bandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist, &bandPersist));
+        if (FAILED_UNEXPECTEDLY(hResult))
+            return FALSE;
+        hResult = bandPersist->GetClassID(&clsidTmp);
+        if (FAILED_UNEXPECTEDLY(hResult))
+            return FALSE;
+        if (IsEqualGUID(clsidBand, clsidTmp))
+        {
+            if (pdwBandID) *pdwBandID = dwBandID;
+            return TRUE;
+        }
+    }
+    return FALSE;
 }
 
 HRESULT CShellBrowser::ShowBand(const CLSID &classID, bool vertical)
@@ -1173,50 +1207,80 @@ HRESULT CShellBrowser::ShowBand(const CLSID &classID, bool vertical)
     CComPtr<IDockingWindow>                 dockingWindow;
     CComPtr<IUnknown>                       baseBarSite;
     CComPtr<IUnknown>                       newBand;
-    CComPtr<IUnknown>                       theBaseBar;
     CComPtr<IDeskBar>                       deskBar;
     VARIANT                                 vaIn;
     HRESULT                                 hResult;
+    DWORD                                   dwBandID;
 
-    hResult = GetBaseBar(vertical, (IUnknown **)&theBaseBar);
+    hResult = GetBaseBar(vertical, IID_PPV_ARG(IDeskBar, &deskBar));
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return hResult;
+    
+    hResult = deskBar->GetClient(&baseBarSite);
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
-#if USE_CUSTOM_EXPLORERBAND
-    TRACE("ShowBand called for CLSID %s, vertical=%d...\n", wine_dbgstr_guid(&classID), vertical);
-    if (IsEqualCLSID(CLSID_ExplorerBand, classID))
+    hResult = deskBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return hResult;
+    
+    if (!IsBandLoaded(classID, vertical, &dwBandID))
     {
-        TRACE("CLSID_ExplorerBand requested, building internal band.\n");
-        hResult = CExplorerBand_Constructor(IID_PPV_ARG(IUnknown, &newBand));
-        if (FAILED_UNEXPECTEDLY(hResult))
-            return hResult;
+        TRACE("ShowBand called for CLSID %s, vertical=%d...\n", wine_dbgstr_guid(&classID), vertical);
+        if (IsEqualCLSID(CLSID_ExplorerBand, classID))
+        {
+            TRACE("CLSID_ExplorerBand requested, building internal band.\n");
+            hResult = CExplorerBand_CreateInstance(IID_PPV_ARG(IUnknown, &newBand));
+            if (FAILED_UNEXPECTEDLY(hResult))
+                return hResult;
+        }
+        else
+        {
+            TRACE("A different CLSID requested, using CoCreateInstance.\n");
+            hResult = CoCreateInstance(classID, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &newBand));
+            if (FAILED_UNEXPECTEDLY(hResult))
+                return hResult;
+        }
     }
     else
-#endif
     {
-        TRACE("A different CLSID requested, using CoCreateInstance.\n");
-        hResult = CoCreateInstance(classID, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &newBand));
-        if (FAILED_UNEXPECTEDLY(hResult))
-            return hResult;
+        CComPtr<IBandSite>                  pBandSite;
+
+        hResult = baseBarSite->QueryInterface(IID_PPV_ARG(IBandSite, &pBandSite));
+        if (!SUCCEEDED(hResult))
+        {
+            ERR("Can't get IBandSite interface\n");
+            return E_FAIL;
+        }
+        hResult = pBandSite->GetBandObject(dwBandID, IID_PPV_ARG(IUnknown, &newBand));
+        if (!SUCCEEDED(hResult))
+        {
+            ERR("Can't find band object\n");
+            return E_FAIL;
+        }
+
+        // It's hackish, but we should be able to show the wanted band until we
+        // find the proper way to do this (but it seems to work to add a new band)
+        // Here we'll just re-add the existing band to the site, causing it to display.
     }
-    hResult = theBaseBar->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return hResult;
-    hResult = deskBar->GetClient(&baseBarSite);
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return hResult;
-    hResult = theBaseBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return hResult;
     V_VT(&vaIn) = VT_UNKNOWN;
     V_UNKNOWN(&vaIn) = newBand.p;
     hResult = IUnknown_Exec(baseBarSite, CGID_IDeskBand, 1, 1, &vaIn, NULL);
     if (FAILED_UNEXPECTEDLY(hResult))
+    {
         return hResult;
+    }
+
     hResult = dockingWindow->ShowDW(TRUE);
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
+    if (vertical)
+    {
+        fCurrentVertBar = classID;
+        FireCommandStateChangeAll();
+    }
+
     return S_OK;
 }
 
@@ -1225,6 +1289,11 @@ HRESULT CShellBrowser::NavigateToParent()
     LPITEMIDLIST newDirectory = ILClone(fCurrentDirectoryPIDL);
     if (newDirectory == NULL)
         return E_OUTOFMEMORY;
+    if (_ILIsDesktop(newDirectory))
+    {
+        ILFree(newDirectory);
+        return E_INVALIDARG;
+    }
     ILRemoveLastID(newDirectory);
     HRESULT hResult = BrowseToPIDL(newDirectory, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
     ILFree(newDirectory);
@@ -1279,6 +1348,9 @@ HRESULT CShellBrowser::DoFolderOptions()
     if (FAILED_UNEXPECTEDLY(hResult))
         return E_FAIL;
 
+// CORE-11140 : Disabled this bit, because it prevents the folder options from showing.
+//              It returns 'E_NOTIMPL'
+#if 0
     if (fCurrentShellView != NULL)
     {
         hResult = fCurrentShellView->AddPropertySheetPages(
@@ -1286,13 +1358,15 @@ HRESULT CShellBrowser::DoFolderOptions()
         if (FAILED_UNEXPECTEDLY(hResult))
             return E_FAIL;
     }
+#endif
 
     // show sheet
+    CStringW strFolderOptions(MAKEINTRESOURCEW(IDS_FOLDER_OPTIONS));
     m_PropSheet.dwSize = sizeof(PROPSHEETHEADER);
     m_PropSheet.dwFlags = 0;
     m_PropSheet.hwndParent = m_hWnd;
     m_PropSheet.hInstance = _AtlBaseModule.GetResourceInstance();
-    m_PropSheet.pszCaption = _T("Folder Options");
+    m_PropSheet.pszCaption = strFolderOptions;
     m_PropSheet.nStartPage = 0;
     PropertySheet(&m_PropSheet);
     return S_OK;
@@ -1312,18 +1386,22 @@ LRESULT CALLBACK CShellBrowser::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam,
     previousMessage = pThis->m_pCurrentMsg;
     pThis->m_pCurrentMsg = &msg;
 
-    CComPtr<IMenuBand> menuBand;
-    hResult = pThis->GetMenuBand(IID_PPV_ARG(IMenuBand, &menuBand));
-    if (SUCCEEDED(hResult) && menuBand.p != NULL)
+    /* If the shell browser is initialized, let the menu band preprocess the messages */
+    if (pThis->fCurrentDirectoryPIDL)
     {
-        hResult = menuBand->TranslateMenuMessage(&msg, &lResult);
-        if (hResult == S_OK)
-            return lResult;
-        uMsg = msg.message;
-        wParam = msg.wParam;
-        lParam = msg.lParam;
+        CComPtr<IMenuBand> menuBand;
+        hResult = pThis->GetMenuBand(IID_PPV_ARG(IMenuBand, &menuBand));
+        if (SUCCEEDED(hResult) && menuBand.p != NULL)
+        {
+            hResult = menuBand->TranslateMenuMessage(&msg, &lResult);
+            if (hResult == S_OK)
+                return lResult;
+            uMsg = msg.message;
+            wParam = msg.wParam;
+            lParam = msg.lParam;
+        }
+        menuBand.Release();
     }
-    menuBand.Release();
 
     handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
     ATLASSERT(pThis->m_pCurrentMsg == &msg);
@@ -1331,10 +1409,10 @@ LRESULT CALLBACK CShellBrowser::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam,
     {
         if (uMsg == WM_NCDESTROY)
         {
-            saveWindowProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWL_WNDPROC));
+            saveWindowProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hWnd, GWLP_WNDPROC));
             lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
-            if (saveWindowProc == reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWL_WNDPROC)))
-                SetWindowLongPtr(hWnd, GWL_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
+            if (saveWindowProc == reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hWnd, GWLP_WNDPROC)))
+                ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
             pThis->m_dwState |= WINSTATE_DESTROYED;
         }
         else
@@ -1530,9 +1608,22 @@ HRESULT CShellBrowser::UpdateForwardBackState()
     return S_OK;
 }
 
+HRESULT CShellBrowser::UpdateUpState()
+{
+    bool canGoUp;
+    HRESULT hResult;
+
+    canGoUp = true;
+    if (_ILIsDesktop(fCurrentDirectoryPIDL))
+        canGoUp = false;
+    hResult = FireCommandStateChange(canGoUp, 3);
+    return S_OK;
+}
+
 void CShellBrowser::UpdateGotoMenu(HMENU theMenu)
 {
     CComPtr<ITravelLog>                     travelLog;
+    CComPtr<ITravelEntry>                   unusedEntry;
     int                                     position;
     MENUITEMINFO                            menuItemInfo;
     HRESULT                                 hResult;
@@ -1543,6 +1634,35 @@ void CShellBrowser::UpdateGotoMenu(HMENU theMenu)
     hResult = GetTravelLog(&travelLog);
     if (FAILED_UNEXPECTEDLY(hResult))
         return;
+
+    hResult = travelLog->GetTravelEntry(static_cast<IDropTarget *>(this),
+                                        TLOG_BACK,
+                                        &unusedEntry);
+
+    if (SUCCEEDED(hResult))
+    {
+        SHEnableMenuItem(theMenu, IDM_GOTO_BACK, TRUE);
+        unusedEntry.Release();
+    }
+    else
+        SHEnableMenuItem(theMenu, IDM_GOTO_BACK, FALSE);
+
+    hResult = travelLog->GetTravelEntry(static_cast<IDropTarget *>(this),
+                                        TLOG_FORE,
+                                        &unusedEntry);
+
+    if (SUCCEEDED(hResult))
+    {
+        SHEnableMenuItem(theMenu, IDM_GOTO_FORWARD, TRUE);
+        unusedEntry.Release();
+    }
+    else
+        SHEnableMenuItem(theMenu, IDM_GOTO_FORWARD, FALSE);
+
+    SHEnableMenuItem(theMenu,
+                     IDM_GOTO_UPONELEVEL,
+                     !_ILIsDesktop(fCurrentDirectoryPIDL));
+
     hResult = travelLog->InsertMenuEntries(static_cast<IDropTarget *>(this), theMenu, position,
         IDM_GOTO_TRAVEL_FIRSTTARGET, IDM_GOTO_TRAVEL_LASTTARGET, TLMENUF_BACKANDFORTH | TLMENUF_CHECKCURRENT);
     if (SUCCEEDED(hResult))
@@ -1612,9 +1732,124 @@ void CShellBrowser::UpdateViewMenu(HMENU theMenu)
         SetMenuItemInfo(theMenu, IDM_VIEW_TOOLBARS, FALSE, &menuItemInfo);
     }
     SHCheckMenuItem(theMenu, IDM_VIEW_STATUSBAR, fStatusBarVisible ? TRUE : FALSE);
+}
 
-    // TODO: Implement
-    SHEnableMenuItem(theMenu, IDM_VIEW_EXPLORERBAR, FALSE);
+HRESULT CShellBrowser::BuildExplorerBandMenu()
+{
+    HMENU                                   hBandsMenu;
+    UINT                                    nbFound;
+
+    hBandsMenu = SHGetMenuFromID(fCurrentMenuBar, IDM_VIEW_EXPLORERBAR);
+    if (!hBandsMenu)
+    {
+        OutputDebugString(L"No menu !\n");
+        return E_FAIL;
+    }
+    DSA_DeleteAllItems(menuDsa);
+    BuildExplorerBandCategory(hBandsMenu, CATID_InfoBand, 4, NULL);
+    BuildExplorerBandCategory(hBandsMenu, CATID_CommBand, 20, &nbFound);
+    if (!nbFound)
+    {
+        // Remove separator
+        DeleteMenu(hBandsMenu, IDM_EXPLORERBAR_SEPARATOR, MF_BYCOMMAND); 
+    }
+    // Remove media menu since XP does it (according to API Monitor)
+    DeleteMenu(hBandsMenu, IDM_EXPLORERBAR_MEDIA, MF_BYCOMMAND);
+    return S_OK;
+}
+
+HRESULT CShellBrowser::BuildExplorerBandCategory(HMENU hBandsMenu, CATID category, DWORD dwPos, UINT *nbFound)
+{
+    HRESULT                                 hr;
+    CComPtr<IEnumGUID>                      pEnumGUID;
+    WCHAR                                   wszBandName[MAX_PATH];
+    WCHAR                                   wszBandGUID[MAX_PATH];
+    WCHAR                                   wRegKey[MAX_PATH];
+    UINT                                    cBands;
+    DWORD                                   dwRead;
+    DWORD                                   dwDataSize;
+    GUID                                    iter;
+    MenuBandInfo                            mbi;
+
+    mbi.fVertical = IsEqualGUID(category, CATID_InfoBand);
+    cBands = 0;
+    hr = SHEnumClassesOfCategories(1, &category, 0, NULL, &pEnumGUID);
+    if (FAILED_UNEXPECTEDLY(hr))
+    {
+        return hr;
+    }
+    do
+    {
+        pEnumGUID->Next(1, &iter, &dwRead);
+        if (dwRead)
+        {
+            // Get the band name
+            if (IsBuiltinBand(iter))
+                continue;
+            if (!StringFromGUID2(iter, wszBandGUID, MAX_PATH))
+                continue;
+            StringCchPrintfW(wRegKey, MAX_PATH, L"CLSID\\%s", wszBandGUID);
+            dwDataSize = MAX_PATH;
+            SHGetValue(HKEY_CLASSES_ROOT, wRegKey, NULL, NULL, wszBandName, &dwDataSize);
+
+            mbi.barGuid = iter;
+            InsertMenu(hBandsMenu, dwPos + cBands, MF_BYPOSITION, IDM_EXPLORERBAND_BEGINCUSTOM + DSA_GetItemCount(menuDsa), wszBandName);
+            DSA_AppendItem(menuDsa, &mbi);
+            cBands++;
+        }
+    }
+    while (dwRead > 0);
+    if (nbFound)
+        *nbFound = cBands;
+    return S_OK;
+}
+
+BOOL CShellBrowser::IsBuiltinBand(CLSID &bandID)
+{
+    if (IsEqualCLSID(bandID, CLSID_ExplorerBand))
+        return TRUE;
+    if (IsEqualCLSID(bandID, CLSID_SH_SearchBand) || IsEqualCLSID(bandID, CLSID_SearchBand))
+        return TRUE;
+    if (IsEqualCLSID(bandID, CLSID_IE_SearchBand) || IsEqualCLSID(bandID, CLSID_FileSearchBand))
+        return TRUE;
+    if (IsEqualCLSID(bandID, CLSID_SH_HistBand))
+        return TRUE;
+    if (IsEqualCLSID(bandID, CLSID_SH_FavBand))
+        return TRUE;
+    if (IsEqualCLSID(bandID, CLSID_ChannelsBand))
+        return TRUE;
+    return FALSE;
+}
+
+HRESULT CShellBrowser::OnSearch()
+{
+    CComPtr<IObjectWithSite>                objectWithSite;
+    CComPtr<IContextMenu>                   contextMenu;
+    CMINVOKECOMMANDINFO                     commandInfo;
+    const char                              *searchGUID = "{169A0691-8DF9-11d1-A1C4-00C04FD75D13}";
+    HRESULT                                 hResult;
+
+    // TODO: Query shell if this command is enabled first
+
+    memset(&commandInfo, 0, sizeof(commandInfo));
+    commandInfo.cbSize = sizeof(commandInfo);
+    commandInfo.hwnd = m_hWnd;
+    commandInfo.lpParameters = searchGUID;
+    commandInfo.nShow = SW_SHOWNORMAL;
+
+    hResult = CoCreateInstance(CLSID_ShellSearchExt, NULL, CLSCTX_INPROC_SERVER,
+        IID_PPV_ARG(IContextMenu, &contextMenu));
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return 0;
+    hResult = contextMenu->QueryInterface(IID_PPV_ARG(IObjectWithSite, &objectWithSite));
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return 0;
+    hResult = objectWithSite->SetSite(dynamic_cast<IShellBrowser*>(this));
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return 0;
+    hResult = contextMenu->InvokeCommand(&commandInfo);
+    hResult = objectWithSite->SetSite(NULL);
+    return hResult;
 }
 
 bool IUnknownIsEqual(IUnknown *int1, IUnknown *int2)
@@ -1710,15 +1945,28 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::QueryStatus(const GUID *pguidCmdGroup,
             {
                 case 0x1c:  // search
                     prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
+                    if (IsEqualCLSID(CLSID_SH_SearchBand, fCurrentVertBar) ||
+                        IsEqualCLSID(CLSID_SearchBand, fCurrentVertBar) ||
+                        IsEqualCLSID(CLSID_IE_SearchBand, fCurrentVertBar) ||
+                        IsEqualCLSID(CLSID_FileSearchBand, fCurrentVertBar))
+                    {
+                        prgCmds->cmdf |= OLECMDF_LATCHED;
+                    }
                     break;
                 case 0x1d:  // history
                     prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
+                    if (IsEqualCLSID(CLSID_SH_HistBand, fCurrentVertBar))
+                        prgCmds->cmdf |= OLECMDF_LATCHED;
                     break;
                 case 0x1e:  // favorites
                     prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
+                    if (IsEqualCLSID(CLSID_SH_FavBand, fCurrentVertBar))
+                        prgCmds->cmdf |= OLECMDF_LATCHED;
                     break;
                 case 0x23:  // folders
-                    prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_LATCHED;
+                    prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
+                    if (IsEqualCLSID(CLSID_ExplorerBand, fCurrentVertBar))
+                        prgCmds->cmdf |= OLECMDF_LATCHED;
                     break;
                 default:
                     prgCmds->cmdf = 0;
@@ -1752,12 +2000,59 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::Exec(const GUID *pguidCmdGroup, DWORD n
 {
     HRESULT                                 hResult;
 
+    if (!pguidCmdGroup)
+    {
+        TRACE("Unhandled null CGID %d %d %p %p\n", nCmdID, nCmdexecopt, pvaIn, pvaOut);
+        return E_NOTIMPL;
+    }
     if (IsEqualIID(*pguidCmdGroup, CGID_Explorer))
     {
         switch (nCmdID)
         {
-            case 0x23:
-                hResult = ShowBand(CLSID_ExplorerBand, true);
+            case 0x1c: //Toggle Search
+                if (IsEqualCLSID(CLSID_SH_SearchBand, fCurrentVertBar) ||
+                    IsEqualCLSID(CLSID_SearchBand, fCurrentVertBar) ||
+                    IsEqualCLSID(CLSID_IE_SearchBand, fCurrentVertBar) ||
+                    IsEqualCLSID(CLSID_FileSearchBand, fCurrentVertBar))
+                {
+                    hResult = IUnknown_ShowDW(fClientBars[BIVerticalBaseBar].clientBar.p, FALSE);
+                    memset(&fCurrentVertBar, 0, sizeof(fCurrentVertBar));
+                    FireCommandStateChangeAll();
+                }
+                else
+                {
+                    OnSearch();
+                }
+                return S_OK;
+            case 0x1d: //Toggle History
+            case 0x1e: //Toggle Favorites
+            case 0x23: //Toggle Folders
+                const GUID* pclsid;
+                if (nCmdID == 0x1d) pclsid = &CLSID_SH_HistBand;
+                else if (nCmdID == 0x1e) pclsid = &CLSID_SH_FavBand;
+                else pclsid = &CLSID_ExplorerBand;
+
+                if (IsEqualCLSID(*pclsid, fCurrentVertBar))
+                {
+                    hResult = IUnknown_ShowDW(fClientBars[BIVerticalBaseBar].clientBar.p, FALSE);
+                    memset(&fCurrentVertBar, 0, sizeof(fCurrentVertBar));
+                    FireCommandStateChangeAll();
+                }
+                else
+                {
+                    hResult = ShowBand(*pclsid, true);
+                }
+                return S_OK;
+            case 0x22:
+                //Sent when a band closes
+                if (V_VT(pvaIn) != VT_UNKNOWN)
+                    return E_INVALIDARG;
+
+                if (IUnknownIsEqual(V_UNKNOWN(pvaIn), fClientBars[BIVerticalBaseBar].clientBar.p))
+                {
+                    memset(&fCurrentVertBar, 0, sizeof(fCurrentVertBar));
+                    FireCommandStateChangeAll();
+                }
                 return S_OK;
             case 0x27:
                 if (nCmdexecopt == 1)
@@ -1815,6 +2110,9 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::Exec(const GUID *pguidCmdGroup, DWORD n
             case 0x12:
                 // refresh on toolbar clicked
                 return S_OK;
+            case 0x26:
+                // called for unknown bands ?
+                return S_OK;
             case 0x4d:
                 // tell the view if it should hide the task pane or not
                 return (fClientBars[BIVerticalBaseBar].clientBar.p == NULL) ? S_FALSE : S_OK;
@@ -1893,20 +2191,22 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU h
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
-    if (hmenuShared)
+    if (!hmenuShared)
     {
-        // FIXME: Figure out the proper way to do this.
-        HMENU hMenuFavs = GetSubMenu(hmenuShared, 3);
-        if (hMenuFavs)
-        {
-            DeleteMenu(hMenuFavs, IDM_FAVORITES_EMPTY, MF_BYCOMMAND);
-        }
+        hmenuShared = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_MAINMENU));
+    }
+    // FIXME: Figure out the proper way to do this.
+    HMENU hMenuFavs = GetSubMenu(hmenuShared, 3);
+    if (hMenuFavs)
+    {
+        DeleteMenu(hMenuFavs, IDM_FAVORITES_EMPTY, MF_BYCOMMAND);
     }
 
     hResult = shellMenu->SetMenu(hmenuShared, m_hWnd, SMSET_DONTOWN);
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     fCurrentMenuBar = hmenuShared;
+    BuildExplorerBandMenu();
     return S_OK;
 }
 
@@ -1931,7 +2231,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SetStatusTextSB(LPCOLESTR pszStatusText
     {
 
     }
-    return E_NOTIMPL;
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CShellBrowser::EnableModelessSB(BOOL fEnable)
@@ -1948,7 +2248,13 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::TranslateAcceleratorSB(MSG *pmsg, WORD
 
 HRESULT STDMETHODCALLTYPE CShellBrowser::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
 {
-    return BrowseToPIDL(pidl, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
+    if ((wFlags & SBSP_EXPLOREMODE) != NULL)
+        ShowBand(CLSID_ExplorerBand, true);
+
+    long flags = BTP_UPDATE_NEXT_HISTORY;
+    if (fTravelLog)
+        flags |= BTP_UPDATE_CUR_HISTORY;
+    return BrowseToPIDL(pidl, flags);
 }
 
 HRESULT STDMETHODCALLTYPE CShellBrowser::GetViewStateStream(DWORD grfMode, IStream **ppStrm)
@@ -1961,7 +2267,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::GetControlWindow(UINT id, HWND *lphwnd)
     if (lphwnd == NULL)
         return E_POINTER;
     *lphwnd = NULL;
-    switch(id)
+    switch (id)
     {
         case FCW_TOOLBAR:
             *lphwnd = fToolbarProxy.m_hWnd;
@@ -1987,7 +2293,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SendControlMsg(
 
     if (pret != NULL)
         *pret = 0;
-    switch(id)
+    switch (id)
     {
         case FCW_TOOLBAR:
             result = fToolbarProxy.SendMessage(uMsg, wParam, lParam);
@@ -2127,7 +2433,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::GetTravelLog(ITravelLog **pptl)
     *pptl = NULL;
     if (fTravelLog.p == NULL)
     {
-        hResult = CreateTravelLog(IID_PPV_ARG(ITravelLog, &fTravelLog));
+        hResult = CTravelLog_CreateInstance(IID_PPV_ARG(ITravelLog, &fTravelLog));
         if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
     }
@@ -2582,8 +2888,6 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::_SetFocus(LPTOOLBARITEM ptbi, HWND hwnd
     return E_NOTIMPL;
 }
 
-extern HRESULT IUnknown_HasFocusIO(IUnknown * punk);
-extern HRESULT IUnknown_TranslateAcceleratorIO(IUnknown * punk, MSG * pmsg);
 HRESULT STDMETHODCALLTYPE CShellBrowser::v_MayTranslateAccelerator(MSG *pmsg)
 {
     for (int i = 0; i < 3; i++)
@@ -2639,7 +2943,17 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::GoSearch()
 HRESULT STDMETHODCALLTYPE CShellBrowser::Navigate(BSTR URL, VARIANT *Flags,
     VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
 {
-    return E_NOTIMPL;
+    CComHeapPtr<ITEMIDLIST> pidl;
+    HRESULT hResult;
+    CComPtr<IShellFolder> pDesktop;
+
+    hResult = SHGetDesktopFolder(&pDesktop);
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return hResult;
+    hResult = pDesktop->ParseDisplayName(NULL, NULL, URL, NULL, &pidl, NULL);
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return hResult;
+    return BrowseObject(pidl, 1);
 }
 
 HRESULT STDMETHODCALLTYPE CShellBrowser::Refresh()
@@ -2859,14 +3173,23 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::put_FullScreen(VARIANT_BOOL bFullScreen
 HRESULT STDMETHODCALLTYPE CShellBrowser::Navigate2(VARIANT *URL, VARIANT *Flags,
     VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
 {
+    LPITEMIDLIST pidl = NULL;
+    HRESULT hResult;
     // called from drive combo box to navigate to a directory
-    if (V_VT(URL) != (VT_ARRAY | VT_UI1))
-        return E_INVALIDARG;
-    if (V_ARRAY(URL)->cDims != 1 || V_ARRAY(URL)->cbElements != 1)
-        return E_INVALIDARG;
+    // Also called by search band to display shell results folder view
 
-    LPITEMIDLIST pidl = static_cast<LPITEMIDLIST>(V_ARRAY(URL)->pvData);
-    HRESULT hResult = BrowseToPIDL(pidl, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
+    if (V_VT(URL) == VT_BSTR)
+    {
+        return this->Navigate(V_BSTR(URL), Flags, TargetFrameName, PostData, Headers);
+    }
+    if (V_VT(URL) == (VT_ARRAY | VT_UI1))
+    {
+        if (V_ARRAY(URL)->cDims != 1 || V_ARRAY(URL)->cbElements != 1)
+            return E_INVALIDARG;
+
+        pidl = static_cast<LPITEMIDLIST>(V_ARRAY(URL)->pvData);
+    }
+    hResult = BrowseToPIDL(pidl, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     return S_OK;
@@ -3036,7 +3359,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::LoadHistory(IStream *pStream, IBindCtx
     fHistoryObject = viewHistoryObject;
     fHistoryStream = pStream;
     fHistoryBindContext = pbc;
-    hResult = BrowseToPIDL(pidl, BTP_UPDATE_CUR_HISTORY);
+    hResult = BrowseToPIDL(pidl, BTP_DONT_UPDATE_HISTORY);
     fHistoryObject = NULL;
     fHistoryStream = NULL;
     fHistoryBindContext = NULL;
@@ -3099,25 +3422,52 @@ LRESULT CShellBrowser::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
 LRESULT CShellBrowser::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
     HRESULT hr;
+
+    /* The current thread is about to go down so render any IDataObject that may be left in the clipboard */
+    OleFlushClipboard();
+
     // TODO: rip down everything
     {
+        fToolbarProxy.Destroy();
+
         fCurrentShellView->DestroyViewWindow();
         fCurrentShellView->UIActivate(SVUIA_DEACTIVATE);
-        ReleaseCComPtrExpectZero(fCurrentShellView);
 
         for (int i = 0; i < 3; i++)
         {
+            CComPtr<IDockingWindow> pdw;
+            CComPtr<IDeskBar> bar;
+            CComPtr<IUnknown> pBarSite;
+            CComPtr<IDeskBarClient> pClient;
             if (fClientBars[i].clientBar == NULL)
                 continue;
-            IDockingWindow * pdw;
+
             hr = fClientBars[i].clientBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &pdw));
             if (FAILED_UNEXPECTEDLY(hr))
                 continue;
-            pdw->ShowDW(FALSE);
+            
+            /* We should destroy our basebarsite too */
+            hr = pdw->QueryInterface(IID_PPV_ARG(IDeskBar, &bar));
+            if (SUCCEEDED(hr))
+            {
+                hr = bar->GetClient(&pBarSite);
+                if (SUCCEEDED(hr) && pBarSite)
+                {
+                    hr = pBarSite->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pClient));
+                    if (SUCCEEDED(hr))
+                        pClient->SetDeskBarSite(NULL);
+                }
+            }
             pdw->CloseDW(0);
-            pdw->Release();
+
+            pClient = NULL;
+            pBarSite = NULL;
+            pdw = NULL;
+            bar = NULL;
             ReleaseCComPtrExpectZero(fClientBars[i].clientBar);
         }
+        ReleaseCComPtrExpectZero(fCurrentShellView);
         ReleaseCComPtrExpectZero(fTravelLog);
 
         fCurrentShellFolder.Release();
@@ -3186,9 +3536,7 @@ LRESULT CShellBrowser::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam,
     {
         // FIXME: Remove once implemented
         SHEnableMenuItem(theMenu, IDM_TOOLS_MAPNETWORKDRIVE, FALSE);
-        SHEnableMenuItem(theMenu, IDM_TOOLS_DISCONNECTNETWORKDRIVE, FALSE);
         SHEnableMenuItem(theMenu, IDM_TOOLS_SYNCHRONIZE, FALSE);
-        SHEnableMenuItem(theMenu, IDM_TOOLS_FOLDEROPTIONS, FALSE);
         menuIndex = 4;
     }
     else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_HELP))
@@ -3201,6 +3549,12 @@ LRESULT CShellBrowser::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam,
     return ret;
 }
 
+LRESULT CShellBrowser::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    ::SetFocus(fCurrentShellViewWindow);
+    return 0;
+}
+
 LRESULT CShellBrowser::RelayMsgToShellView(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
     if (fCurrentShellViewWindow != NULL)
@@ -3208,6 +3562,15 @@ LRESULT CShellBrowser::RelayMsgToShellView(UINT uMsg, WPARAM wParam, LPARAM lPar
     return 0;
 }
 
+LRESULT CShellBrowser::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    LPVOID lpEnvironment;
+    RegenerateUserEnvironment(&lpEnvironment, TRUE);
+
+    SHPropagateMessage(m_hWnd, uMsg, wParam, lParam, TRUE);
+    return 0;
+}
+
 LRESULT CShellBrowser::OnClose(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
     return SendMessage(WM_CLOSE);
@@ -3231,9 +3594,7 @@ LRESULT CShellBrowser::OnMapNetworkDrive(WORD wNotifyCode, WORD wID, HWND hWndCt
 
 LRESULT CShellBrowser::OnDisconnectNetworkDrive(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
-#ifndef __REACTOS__
     WNetDisconnectDialog(m_hWnd, RESOURCETYPE_DISK);
-#endif /* __REACTOS__ */
     return 0;
 }
 
@@ -3308,33 +3669,6 @@ LRESULT CShellBrowser::OnOrganizeFavorites(WORD wNotifyCode, WORD wID, HWND hWnd
     return 0;
 }
 
-LRESULT CShellBrowser::OnIsThisLegal(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
-{
-    /* TODO: Implement properly */
-
-    LPCWSTR strSite = L"https://www.reactos.org/user-faq";
-
-    /* TODO: Make localizable */
-    LPCWSTR strCaption = L"Sorry";
-    LPCWSTR strMessage = L"ReactOS could not browse to '%s' (error %d). Please make sure there is a web browser installed.";
-    WCHAR tmpMessage[512];
-
-    /* TODO: Read from the registry */
-    LPCWSTR strVerb = NULL; /* default */
-    LPCWSTR strPath = strSite;
-    LPCWSTR strParams = NULL;
-
-    /* The return value is defined as HINSTANCE for backwards compatibility only, the cast is needed */
-    int result = (int) ShellExecuteW(m_hWnd, strVerb, strPath, strParams, NULL, SW_SHOWNORMAL);
-    if (result <= 32)
-    {
-        StringCchPrintfW(tmpMessage, 512, strMessage, strSite, result);
-        MessageBoxExW(m_hWnd, tmpMessage, strCaption, MB_OK, 0);
-    }
-
-    return 0;
-}
-
 LRESULT CShellBrowser::OnToggleStatusBarVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
     fStatusBarVisible = !fStatusBarVisible;
@@ -3394,84 +3728,60 @@ LRESULT CShellBrowser::OnToolbarCustomize(WORD wNotifyCode, WORD wID, HWND hWndC
     return 0;
 }
 
-LRESULT CShellBrowser::OnGoTravel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
+LRESULT CShellBrowser::OnRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
+    if (fCurrentShellView)
+        fCurrentShellView->Refresh();
     return 0;
 }
 
-LRESULT CShellBrowser::RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+LRESULT CShellBrowser::OnGoTravel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
-    if (HIWORD(wParam) == 0 && LOWORD(wParam) < FCIDM_SHVIEWLAST && fCurrentShellViewWindow != NULL)
-        return SendMessage(fCurrentShellViewWindow, uMsg, wParam, lParam);
     return 0;
 }
 
-static HRESULT ExplorerMessageLoop(IEThreadParamBlock * parameters)
+LRESULT CShellBrowser::OnExplorerBar(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
-    CComPtr<CShellBrowser>    theCabinet;
-    HRESULT                   hResult;
-    MSG Msg;
-    BOOL Ret;
-
-    // Tell the thread ref we are using it.
-    if (parameters && parameters->offsetF8)
-        parameters->offsetF8->AddRef();
-    
-    ATLTRY(theCabinet = new CComObject<CShellBrowser>);
-    if (theCabinet == NULL)
-    {
-        return E_OUTOFMEMORY;
-    }
-    
-    hResult = theCabinet->Initialize(parameters->directoryPIDL, 0, 0, 0);
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return E_OUTOFMEMORY;
-
-    while ((Ret = GetMessage(&Msg, NULL, 0, 0)) != 0)
-    {
-        if (Ret == -1)
-        {
-            // Error: continue or exit?
-            break;
-        }
-
-        if (Msg.message == WM_QUIT)
-            break;
-
-        if (theCabinet->v_MayTranslateAccelerator(&Msg) != S_OK)
-        {
-            TranslateMessage(&Msg);
-            DispatchMessage(&Msg);
-        }
-    }
-
-    int nrc = theCabinet->Release();
-    if (nrc > 0)
+    // TODO: HACK ! use the proper mechanism to show the band (i.e. pass the BSTR to basebar)
+    if (wID >= IDM_EXPLORERBAND_BEGINCUSTOM && wID <= IDM_EXPLORERBAND_ENDCUSTOM)
     {
-        DbgPrint("WARNING: There are %d references to the CShellBrowser active or leaked.\n", nrc);
-    }
-
-    theCabinet.Detach();
-
-    // Tell the thread ref we are not using it anymore.
-    if (parameters && parameters->offsetF8)
-        parameters->offsetF8->Release();
-
-    return hResult;
+        MenuBandInfo *mbi;
+        mbi = (MenuBandInfo*)DSA_GetItemPtr(menuDsa, (wID - IDM_EXPLORERBAND_BEGINCUSTOM));
+        if (!mbi)
+            return 0;
+        ShowBand(mbi->barGuid, mbi->fVertical);
+        bHandled = TRUE;
+        return 1;
+    }
+    switch (wID)
+    {
+    case IDM_EXPLORERBAR_SEARCH:
+        Exec(&CLSID_CommonButtons, 0x123, 1, NULL, NULL);
+        break;
+    case IDM_EXPLORERBAR_FOLDERS:
+        ShowBand(CLSID_ExplorerBand, true);
+        break;
+    case IDM_EXPLORERBAR_HISTORY:
+        ShowBand(CLSID_SH_HistBand, true);
+        break;
+    case IDM_EXPLORERBAR_FAVORITES:
+        ShowBand(CLSID_SH_FavBand, true);
+        break;
+    default:
+        WARN("Unknown id %x\n", wID);
+    }
+    bHandled = TRUE;
+    return 1;
 }
 
-DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter)
+LRESULT CShellBrowser::RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    HRESULT hr;
-    IEThreadParamBlock * parameters = (IEThreadParamBlock *) lpThreadParameter;
-
-    OleInitialize(NULL);
-
-    ATLTRY(hr = ExplorerMessageLoop(parameters));
-
-    OleUninitialize();
-
-    SHDestroyIETHREADPARAM(parameters);
+    if (HIWORD(wParam) == 0 && LOWORD(wParam) < FCIDM_SHVIEWLAST && fCurrentShellViewWindow != NULL)
+        return SendMessage(fCurrentShellViewWindow, uMsg, wParam, lParam);
+    return 0;
+}
 
-    return hr;
+HRESULT CShellBrowser_CreateInstance(REFIID riid, void **ppv)
+{
+    return ShellObjectCreatorInit<CShellBrowser>(riid, ppv);
 }