[BROWSEUI] Enable the Disconnect Network Drive menu item. (#1522)
[reactos.git] / dll / win32 / browseui / shellbrowser.cpp
index 791f8c7..2f30312 100644 (file)
 
 #include <shellapi.h>
 #include <htiframe.h>
-
-extern "C"
-BOOL WINAPI Shell_GetImageLists(
-    _Out_  HIMAGELIST *phiml,
-    _Out_  HIMAGELIST *phimlSmall);
+#include <strsafe.h>
+#include <undocshell.h>
 
 extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow);
 
@@ -120,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;
 
@@ -138,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;
@@ -213,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;
@@ -226,7 +180,7 @@ private:
     CComPtr<IExplorerToolbar>               fExplorerToolbar;
 public:
     void Initialize(HWND parent, IUnknown *explorerToolbar);
-
+    void Destroy();
 private:
 
     // message handlers
@@ -254,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;
@@ -287,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>,
@@ -309,6 +274,12 @@ private:
     class barInfo
     {
     public:
+        barInfo()
+        {
+            memset(&borderSpace, 0, sizeof(borderSpace));
+            hwnd = NULL;
+        }
+
         RECT                                borderSpace;
         CComPtr<IUnknown>                   clientBar;
         HWND                                hwnd;
@@ -328,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
@@ -350,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;
@@ -371,6 +348,7 @@ public:
     HRESULT FireCommandStateChange(bool newState, int commandID);
     HRESULT FireCommandStateChangeAll();
     HRESULT UpdateForwardBackState();
+    HRESULT UpdateUpState();
     void UpdateGotoMenu(HMENU theMenu);
     void UpdateViewMenu(HMENU theMenu);
 
@@ -621,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);
@@ -632,7 +612,7 @@ 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);
     LRESULT OnToggleToolbarBandVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
@@ -641,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()
     {
@@ -660,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)
@@ -672,16 +657,22 @@ public:
         COMMAND_ID_HANDLER(IDM_GOTO_FORWARD, OnGoForward)
         COMMAND_ID_HANDLER(IDM_GOTO_UPONELEVEL, OnGoUpLevel)
         COMMAND_ID_HANDLER(IDM_GOTO_HOMEPAGE, OnGoHome)
-        COMMAND_ID_HANDLER(IDM_HELP_ISTHISCOPYLEGAL, OnIsThisLegal)
+        COMMAND_ID_HANDLER(IDM_FAVORITES_ORGANIZEFAVORITES, OnOrganizeFavorites)
         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()
 
@@ -720,7 +711,6 @@ CShellBrowser::CShellBrowser()
     fCurrentDirectoryPIDL = NULL;
     fStatusBar = NULL;
     fStatusBarVisible = true;
-    memset(fClientBars, 0, sizeof(fClientBars));
     fCurrentMenuBar = NULL;
     fHistoryObject = NULL;
     fHistoryStream = NULL;
@@ -729,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;
@@ -739,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)
     {
@@ -749,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));
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return hResult;
-#else
-    hResult = CreateInternetToolbar(IID_PPV_ARG(IUnknown, &clientBar));
+    hResult = CInternetToolbar_CreateInstance(IID_PPV_ARG(IUnknown, &clientBar));
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
-#endif
 
     fClientBars[BIInternetToolbar].clientBar = clientBar;
 
@@ -802,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;
 }
@@ -832,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;
@@ -980,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;
@@ -1023,6 +1002,11 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
         saveCurrentShellView->DestroyViewWindow();
     fCurrentShellViewWindow = newShellViewWindow;
 
+    if (previousView == NULL)
+    {
+        RepositionBars();
+    }
+
     // no use
     saveCurrentShellView.Release();
     saveCurrentShellFolder.Release();
@@ -1069,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;
 }
 
@@ -1115,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;
@@ -1130,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))
@@ -1158,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)
@@ -1168,34 +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);
-    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;
+
+    if (vertical)
+    {
+        fCurrentVertBar = classID;
+        FireCommandStateChangeAll();
+    }
+
     return S_OK;
 }
 
@@ -1204,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);
@@ -1258,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(
@@ -1265,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;
@@ -1291,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);
@@ -1310,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
@@ -1509,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;
@@ -1522,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))
@@ -1570,10 +1711,16 @@ void CShellBrowser::UpdateViewMenu(HMENU theMenu)
         RemoveMenu(toolbarMenuBar, 0, MF_BYPOSITION);
         DestroyMenu(toolbarMenuBar);
 
-        SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_STANDARDBUTTONS, commandList[0].cmdf);
-        SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_ADDRESSBAR, commandList[1].cmdf & OLECMDF_ENABLED);
-        SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_LINKSBAR, commandList[2].cmdf & OLECMDF_ENABLED);
-        SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_LOCKTOOLBARS, commandList[3].cmdf & OLECMDF_ENABLED);
+        // TODO: Implement
+        SHEnableMenuItem(toolbarMenu, IDM_TOOLBARS_STANDARDBUTTONS, commandList[0].cmdf & OLECMDF_ENABLED);
+        SHEnableMenuItem(toolbarMenu, IDM_TOOLBARS_ADDRESSBAR, commandList[1].cmdf & OLECMDF_ENABLED);
+        SHEnableMenuItem(toolbarMenu, IDM_TOOLBARS_LINKSBAR, commandList[2].cmdf & OLECMDF_ENABLED);
+        SHEnableMenuItem(toolbarMenu, IDM_TOOLBARS_CUSTOMIZE, commandList[4].cmdf & OLECMDF_ENABLED);
+
+        SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_STANDARDBUTTONS, commandList[0].cmdf & OLECMDF_LATCHED);
+        SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_ADDRESSBAR, commandList[1].cmdf & OLECMDF_LATCHED);
+        SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_LINKSBAR, commandList[2].cmdf & OLECMDF_LATCHED);
+        SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_LOCKTOOLBARS, commandList[3].cmdf & OLECMDF_LATCHED);
         if ((commandList[4].cmdf & OLECMDF_ENABLED) == 0)
             DeleteMenu(toolbarMenu, IDM_TOOLBARS_CUSTOMIZE, MF_BYCOMMAND);
         DeleteMenu(toolbarMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
@@ -1587,6 +1734,124 @@ void CShellBrowser::UpdateViewMenu(HMENU theMenu)
     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;
+}
+
+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)
 {
     CComPtr<IUnknown>                       int1Retry;
@@ -1680,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;
@@ -1722,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)
@@ -1785,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;
@@ -1862,10 +2190,23 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU h
     hResult = GetMenuBand(IID_PPV_ARG(IShellMenu, &shellMenu));
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
-    hResult = shellMenu->SetMenu(hmenuShared, NULL, SMSET_DONTOWN);
+
+    if (!hmenuShared)
+    {
+        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;
 }
 
@@ -1890,7 +2231,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SetStatusTextSB(LPCOLESTR pszStatusText
     {
 
     }
-    return E_NOTIMPL;
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CShellBrowser::EnableModelessSB(BOOL fEnable)
@@ -1907,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)
@@ -1920,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;
@@ -1946,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);
@@ -2086,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;
     }
@@ -2541,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++)
@@ -2598,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()
@@ -2818,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;
@@ -2995,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;
@@ -3058,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();
@@ -3143,6 +3534,9 @@ LRESULT CShellBrowser::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam,
     }
     else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_TOOLS))
     {
+        // FIXME: Remove once implemented
+        SHEnableMenuItem(theMenu, IDM_TOOLS_MAPNETWORKDRIVE, FALSE);
+        SHEnableMenuItem(theMenu, IDM_TOOLS_SYNCHRONIZE, FALSE);
         menuIndex = 4;
     }
     else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_HELP))
@@ -3155,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)
@@ -3162,11 +3562,20 @@ LRESULT CShellBrowser::RelayMsgToShellView(UINT uMsg, WPARAM wParam, LPARAM lPar
     return 0;
 }
 
-LRESULT CShellBrowser::OnClose(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
+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);
+}
+
 LRESULT CShellBrowser::OnFolderOptions(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
     HRESULT hResult = DoFolderOptions();
@@ -3185,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;
 }
 
@@ -3238,23 +3645,38 @@ LRESULT CShellBrowser::OnBackspace(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOO
     return 0;
 }
 
-HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, DWORD dwFlags);
-
-LRESULT CShellBrowser::OnIsThisLegal(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
+LRESULT CShellBrowser::OnOrganizeFavorites(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
-    LPITEMIDLIST desktopPIDL;
-    HRESULT hResult = SHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, 0, &desktopPIDL);
-    if (SUCCEEDED(hResult))
+    CComPtr<IShellFolder> psfDesktop;
+    LPITEMIDLIST pidlFavs;
+    HRESULT hr;
+    hr = SHGetSpecialFolderLocation(m_hWnd, CSIDL_FAVORITES, &pidlFavs);
+    if (FAILED(hr))
     {
-        hResult = SHOpenNewFrame(desktopPIDL, NULL, -1, 1);
+        hr = SHGetSpecialFolderLocation(m_hWnd, CSIDL_COMMON_FAVORITES, &pidlFavs);
+        if (FAILED(hr))
+            return 0;
     }
+
+    hr = SHGetDesktopFolder(&psfDesktop);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return 0;
+
+    hr = SHInvokeDefaultCommand(m_hWnd, psfDesktop, pidlFavs);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return 0;
+
     return 0;
 }
 
 LRESULT CShellBrowser::OnToggleStatusBarVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
     fStatusBarVisible = !fStatusBarVisible;
-    // TODO: trigger a relayout of contained items
+    if (fStatusBar)
+    {
+        ::ShowWindow(fStatusBar, fStatusBarVisible ? SW_SHOW : SW_HIDE);
+        RepositionBars();
+    }
     return 0;
 }
 
@@ -3306,11 +3728,52 @@ LRESULT CShellBrowser::OnToolbarCustomize(WORD wNotifyCode, WORD wID, HWND hWndC
     return 0;
 }
 
+LRESULT CShellBrowser::OnRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
+{
+    if (fCurrentShellView)
+        fCurrentShellView->Refresh();
+    return 0;
+}
+
 LRESULT CShellBrowser::OnGoTravel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
 {
     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)
@@ -3318,72 +3781,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(REFIID riid, void **ppv)
 {
-    HRESULT hr;
-    IEThreadParamBlock * parameters = (IEThreadParamBlock *) lpThreadParameter;
-
-    OleInitialize(NULL);
-
-    ATLTRY(hr = ExplorerMessageLoop(parameters));
-
-    OleUninitialize();
-
-    SHDestroyIETHREADPARAM(parameters);
-
-    return hr;
+    return ShellObjectCreatorInit<CShellBrowser>(riid, ppv);
 }