[BROWSEUI]
[reactos.git] / reactos / dll / win32 / browseui / shellbrowser.cpp
index 59691cc..db05015 100644 (file)
 #include <htiframe.h>
 #include <strsafe.h>
 
-extern "C"
-BOOL WINAPI Shell_GetImageLists(
-    _Out_  HIMAGELIST *phiml,
-    _Out_  HIMAGELIST *phimlSmall);
-
 extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow);
 
 #include "newatlinterfaces.h"
@@ -121,15 +116,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;
 
@@ -139,42 +127,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;
@@ -227,7 +179,7 @@ private:
     CComPtr<IExplorerToolbar>               fExplorerToolbar;
 public:
     void Initialize(HWND parent, IUnknown *explorerToolbar);
-
+    void Destroy();
 private:
 
     // message handlers
@@ -255,6 +207,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;
@@ -288,6 +246,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>,
@@ -334,6 +297,7 @@ private:
     IOleObject                              *fHistoryObject;
     IStream                                 *fHistoryStream;
     IBindCtx                                *fHistoryBindContext;
+    HDSA menuDsa;
     HACCEL m_hAccel;
 public:
 #if 0
@@ -351,18 +315,22 @@ public:
 
     CShellBrowser();
     ~CShellBrowser();
-    HRESULT Initialize(LPITEMIDLIST pidl, long b, long c, long d);
+    HRESULT Initialize(LPITEMIDLIST pidl, DWORD dwFlags);
 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;
@@ -372,6 +340,7 @@ public:
     HRESULT FireCommandStateChange(bool newState, int commandID);
     HRESULT FireCommandStateChangeAll();
     HRESULT UpdateForwardBackState();
+    HRESULT UpdateUpState();
     void UpdateGotoMenu(HMENU theMenu);
     void UpdateViewMenu(HMENU theMenu);
 
@@ -622,6 +591,7 @@ 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 OnClose(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
     LRESULT OnFolderOptions(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
@@ -633,7 +603,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);
@@ -643,7 +612,9 @@ 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 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()
     {
@@ -662,6 +633,7 @@ 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)
@@ -675,7 +647,6 @@ 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_TOOLBARS_LOCKTOOLBARS, OnToggleToolbarLock)
         COMMAND_ID_HANDLER(IDM_TOOLBARS_STANDARDBUTTONS, OnToggleToolbarBandVisible)
@@ -683,8 +654,13 @@ public:
         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()
 
@@ -732,9 +708,11 @@ CShellBrowser::CShellBrowser()
 
 CShellBrowser::~CShellBrowser()
 {
+    if (menuDsa)
+        DSA_Destroy(menuDsa);
 }
 
-HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, long b, long c, long d)
+HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, DWORD dwFlags)
 {
     CComPtr<IPersistStreamInit>             persistStreamInit;
     HRESULT                                 hResult;
@@ -742,6 +720,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)
     {
@@ -752,15 +734,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;
 
@@ -810,6 +786,9 @@ HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, long b, long c, long d)
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
+    if ((dwFlags & SBSP_EXPLOREMODE) != NULL)
+        ShowBand(CLSID_ExplorerBand, true);
+
     ShowWindow(SW_SHOWNORMAL);
 
     return S_OK;
@@ -983,9 +962,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;
@@ -1072,29 +1049,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;
 }
 
@@ -1118,7 +1098,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;
@@ -1133,13 +1113,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))
@@ -1161,9 +1145,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)
@@ -1171,34 +1203,74 @@ 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);
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return hResult;
-    hResult = CoCreateInstance(classID, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &newBand));
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return hResult;
-    hResult = theBaseBar->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
+    hResult = GetBaseBar(vertical, 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));
+
+    hResult = deskBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
+    
+    if (!IsBandLoaded(classID, vertical, &dwBandID))
+    {
+        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
+    {
+        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.
+    }
     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;
+
     return S_OK;
 }
 
@@ -1207,6 +1279,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);
@@ -1261,6 +1338,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(
@@ -1268,6 +1348,7 @@ HRESULT CShellBrowser::DoFolderOptions()
         if (FAILED_UNEXPECTEDLY(hResult))
             return E_FAIL;
     }
+#endif
 
     // show sheet
     m_PropSheet.dwSize = sizeof(PROPSHEETHEADER);
@@ -1313,10 +1394,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, GWL_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, GWL_WNDPROC)))
+                ::SetWindowLongPtr(hWnd, GWL_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
             pThis->m_dwState |= WINSTATE_DESTROYED;
         }
         else
@@ -1512,9 +1593,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;
@@ -1525,6 +1619,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))
@@ -1594,9 +1717,124 @@ void CShellBrowser::UpdateViewMenu(HMENU theMenu)
         SetMenuItemInfo(theMenu, IDM_VIEW_TOOLBARS, FALSE, &menuItemInfo);
     }
     SHCheckMenuItem(theMenu, IDM_VIEW_STATUSBAR, fStatusBarVisible ? TRUE : 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;
+}
 
-    // TODO: Implement
-    SHEnableMenuItem(theMenu, IDM_VIEW_EXPLORERBAR, FALSE);
+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)
@@ -1734,6 +1972,11 @@ 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)
@@ -1797,6 +2040,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;
@@ -1827,6 +2073,20 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::Exec(const GUID *pguidCmdGroup, DWORD n
                 break;
         }
     }
+    else if (IsEqualIID(*pguidCmdGroup, CLSID_CommonButtons))
+    {
+        // Windows seems to use this as proxy for toolbar buttons.
+        // We use it for search band for now to remove code duplication,
+        // let's see if it could be useful in the future.
+        switch (nCmdID)
+        {
+            case 0x123:
+                // Show search band from toolbar
+                OnSearch();
+                return S_OK;
+        }
+        return E_NOTIMPL;
+    }
     else
     {
         return E_NOTIMPL;
@@ -1875,20 +2135,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;
 }
 
@@ -1913,7 +2175,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SetStatusTextSB(LPCOLESTR pszStatusText
     {
 
     }
-    return E_NOTIMPL;
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CShellBrowser::EnableModelessSB(BOOL fEnable)
@@ -1930,6 +2192,9 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::TranslateAcceleratorSB(MSG *pmsg, WORD
 
 HRESULT STDMETHODCALLTYPE CShellBrowser::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
 {
+    if ((wFlags & SBSP_EXPLOREMODE) != NULL)
+        ShowBand(CLSID_ExplorerBand, true);
+
     return BrowseToPIDL(pidl, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
 }
 
@@ -1943,7 +2208,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;
@@ -1969,7 +2234,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SendControlMsg(
 
     if (pret != NULL)
         *pret = 0;
-    switch(id)
+    switch (id)
     {
         case FCW_TOOLBAR:
             result = fToolbarProxy.SendMessage(uMsg, wParam, lParam);
@@ -2109,7 +2374,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;
     }
@@ -2564,8 +2829,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++)
@@ -2621,7 +2884,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()
@@ -2841,14 +3114,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
+
+    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;
 
-    LPITEMIDLIST pidl = static_cast<LPITEMIDLIST>(V_ARRAY(URL)->pvData);
-    HRESULT hResult = BrowseToPIDL(pidl, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
+        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;
@@ -3018,7 +3300,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;
@@ -3081,25 +3363,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();
@@ -3170,7 +3479,8 @@ LRESULT CShellBrowser::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam,
         SHEnableMenuItem(theMenu, IDM_TOOLS_MAPNETWORKDRIVE, FALSE);
         SHEnableMenuItem(theMenu, IDM_TOOLS_DISCONNECTNETWORKDRIVE, FALSE);
         SHEnableMenuItem(theMenu, IDM_TOOLS_SYNCHRONIZE, FALSE);
-        SHEnableMenuItem(theMenu, IDM_TOOLS_FOLDEROPTIONS, FALSE);
+        FIXME("Folder options dialog is stubbed: CORE-11141\n");
+        SHEnableMenuItem(theMenu, IDM_TOOLS_FOLDEROPTIONS, FALSE);  // Remove when CORE-11141 is fixed.
         menuIndex = 4;
     }
     else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_HELP))
@@ -3183,6 +3493,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)
@@ -3290,33 +3606,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;
@@ -3381,6 +3670,40 @@ LRESULT CShellBrowser::OnGoTravel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL
     return 0;
 }
 
+LRESULT CShellBrowser::OnExplorerBar(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
+{
+    // 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)
+    {
+        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;
+}
+
 LRESULT CShellBrowser::RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
     if (HIWORD(wParam) == 0 && LOWORD(wParam) < FCIDM_SHVIEWLAST && fCurrentShellViewWindow != NULL)
@@ -3388,72 +3711,7 @@ LRESULT CShellBrowser::RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BO
     return 0;
 }
 
-static HRESULT ExplorerMessageLoop(IEThreadParamBlock * parameters)
-{
-    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)
-    {
-        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;
-}
-
-DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter)
+HRESULT CShellBrowser_CreateInstance(LPITEMIDLIST pidl, DWORD dwFlags, REFIID riid, void **ppv)
 {
-    HRESULT hr;
-    IEThreadParamBlock * parameters = (IEThreadParamBlock *) lpThreadParameter;
-
-    OleInitialize(NULL);
-
-    ATLTRY(hr = ExplorerMessageLoop(parameters));
-
-    OleUninitialize();
-
-    SHDestroyIETHREADPARAM(parameters);
-
-    return hr;
+    return ShellObjectCreatorInit<CShellBrowser>(pidl, dwFlags, riid, ppv);
 }