Index: dll/win32/browseui/shellbrowser.cpp
===================================================================
--- dll/win32/browseui/shellbrowser.cpp	(révision 70688)
+++ dll/win32/browseui/shellbrowser.cpp	(copie de travail)
@@ -24,7 +24,7 @@
 #include <htiframe.h>
 #include <strsafe.h>
 
-#define USE_CUSTOM_EXPLORERBAND 1
+#define USE_CUSTOM_EXPLORERBAND 0
 
 extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow);
 
@@ -328,6 +328,7 @@
         FOLDERSETTINGS *folderSettings, long flags);
     HRESULT GetMenuBand(REFIID riid, void **shellMenu);
     HRESULT GetBaseBar(bool vertical, IUnknown **theBaseBar);
+    BOOL IsBandLoaded(const CLSID clsidBand, bool verticali, DWORD *pdwBandID);
     HRESULT ShowBand(const CLSID &classID, bool vertical);
     HRESULT NavigateToParent();
     HRESULT DoFolderOptions();
@@ -1111,7 +1112,10 @@
         hResult = CreateBaseBarSite(IID_PPV_ARG(IUnknown, &newBaseBarSite));
         if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
-
+    
+        // we have to store our basebar into cache now
+        *cache = newBaseBar;
+        
         // tell the new base bar about the shell browser
         hResult = IUnknown_SetSite(newBaseBar, static_cast<IDropTarget *>(this));
         if (FAILED_UNEXPECTEDLY(hResult))
@@ -1133,11 +1137,62 @@
         if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
 
-        *cache = newBaseBar.Detach();
     }
     return (*cache)->QueryInterface(IID_PPV_ARG(IUnknown, theBaseBar));
 }
 
+BOOL CShellBrowser::IsBandLoaded(const CLSID clsidBand, bool vertical, DWORD *pdwBandID)
+{
+    HRESULT                                 hResult;
+    CComPtr<IUnknown>                       baseBar;
+    CComPtr<IDeskBar>                       deskBar;
+    CComPtr<IUnknown>                       baseBarSite;
+    CComPtr<IBandSite>                      bandSite;
+    CComPtr<IPersist>                       bandPersist;
+    CLSID                                   clsidTmp;
+    DWORD                                   numBands;
+    DWORD                                   dwBandID;
+    DWORD                                   i;
+
+    /* Get our basebarsite to be able to enumerate bands */
+    hResult = GetBaseBar(vertical, (IUnknown **)&baseBar);
+    if(FAILED_UNEXPECTEDLY(hResult))
+        return FALSE;
+    hResult = baseBar->QueryInterface(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++)
+    {
+        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(dwBandID) *pdwBandID = dwBandID;
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
 HRESULT CShellBrowser::ShowBand(const CLSID &classID, bool vertical)
 {
     CComPtr<IDockingWindow>                 dockingWindow;
@@ -1147,42 +1202,62 @@
     CComPtr<IDeskBar>                       deskBar;
     VARIANT                                 vaIn;
     HRESULT                                 hResult;
+    DWORD                                   dwBandID;
 
     hResult = GetBaseBar(vertical, (IUnknown **)&theBaseBar);
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
-
-#if USE_CUSTOM_EXPLORERBAND
-    TRACE("ShowBand called for CLSID %s, vertical=%d...\n", wine_dbgstr_guid(&classID), vertical);
-    if (IsEqualCLSID(CLSID_ExplorerBand, classID))
-    {
-        TRACE("CLSID_ExplorerBand requested, building internal band.\n");
-        hResult = CExplorerBand_Constructor(IID_PPV_ARG(IUnknown, &newBand));
-        if (FAILED_UNEXPECTEDLY(hResult))
-            return hResult;
-    }
-    else
-#endif
-    {
-        TRACE("A different CLSID requested, using CoCreateInstance.\n");
-        hResult = CoCreateInstance(classID, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &newBand));
-        if (FAILED_UNEXPECTEDLY(hResult))
-            return hResult;
-    }
+    
+    // Try to grab IDeskbar's interface of our basebar
     hResult = theBaseBar->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
+
+    // Get the deskBar's client
     hResult = deskBar->GetClient(&baseBarSite);
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
+
+    // Get IDockingWindow's interface of our basebar
     hResult = theBaseBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
+    
+    if(!IsBandLoaded(classID, vertical, &dwBandID))
+    {
+        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;
@@ -3122,15 +3197,39 @@
 
         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();
+            pdw = NULL;
+            /* For some reasons, it's like we miss some AddRef in ATL when QueryInterface on
+             * same interface or inherited one, so we are removing already removed (!) object.
+             * TODO: check with MSVC's ATL to see if this behaviour happens too
+             */
+            bar.Detach();
+            pClient.Detach();
+            pBarSite.Detach();
             ReleaseCComPtrExpectZero(fClientBars[i].clientBar);
         }
         ReleaseCComPtrExpectZero(fTravelLog);
Index: dll/win32/browseui/basebar.cpp
===================================================================
--- dll/win32/browseui/basebar.cpp	(révision 70688)
+++ dll/win32/browseui/basebar.cpp	(copie de travail)
@@ -30,11 +30,10 @@
 */
 /*
 TODO:
-  **Make base bar support resizing
+  **Make base bar support resizing -- almost done (need to support integral ?)
     Add context menu for base bar
     Fix base bar to correctly initialize fVertical field
-    Fix base bar to correctly reposition its base bar site when resized
-
+    Fix base bar to correctly reposition its base bar site when resized -- done ?
 */
 
 class CBaseBar :
@@ -170,6 +169,7 @@
 
 CBaseBar::~CBaseBar()
 {
+    TRACE("CBaseBar deleted\n");
 }
 
 HRESULT CBaseBar::ReserveBorderSpace()
@@ -305,10 +305,13 @@
     HWND                                    ownerWindow;
     HRESULT                                 hResult;
 
-    if (punkClient == NULL)
-        fClient.Release();
-    else
+    /* Clean up old client */
+    if (fClient)
     {
+        fClient = NULL;
+    }
+    if(punkClient)
+    {
         hResult = punkClient->QueryInterface(IID_PPV_ARG(IUnknown, &fClient));
         if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
@@ -350,6 +353,7 @@
 HRESULT STDMETHODCALLTYPE CBaseBar::ShowDW(BOOL fShow)
 {
     fVisible = fShow ? true : false;
+    ShowWindow(fShow);
     ReserveBorderSpace();
     return S_OK;
 }
@@ -356,8 +360,11 @@
 
 HRESULT STDMETHODCALLTYPE CBaseBar::CloseDW(DWORD dwReserved)
 {
-    fVisible = false;
-    ReserveBorderSpace();
+    ShowDW(0);
+    // Detach to our client
+    SetClient(NULL);
+    // Destroy our site
+    SetSite(NULL);
     return S_OK;
 }
 
@@ -430,6 +437,27 @@
 
 LRESULT CBaseBar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
+    DWORD                                   dwWidth;
+    DWORD                                   dwHeight;
+    CComPtr<IOleWindow>                     pClient;
+    HWND                                    clientHwnd;
+    HRESULT                                 hr;
+
+    if(fVisible)
+    {
+        dwWidth = LOWORD(lParam);
+        dwHeight = HIWORD(lParam);
+
+        // substract resizing grips to child's window size
+        if(fVertical)
+            dwWidth -= GetSystemMetrics(SM_CXFRAME);
+        else
+            dwHeight -= GetSystemMetrics(SM_CXFRAME);
+        hr = fClient->QueryInterface(IID_PPV_ARG(IOleWindow, &pClient));
+        hr = pClient->GetWindow(&clientHwnd);
+        ::SetWindowPos(clientHwnd, NULL, 0, 0, dwWidth, dwHeight, NULL);
+        bHandled = TRUE;
+    }
     return 0;
 }
 
@@ -482,20 +510,21 @@
 LRESULT CBaseBar::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
     POINT                                   newLocation;
-    //int                                     delta;
+    int                                     delta;
 
     if (fTracking)
     {
         newLocation.x = (short)LOWORD(lParam);
         newLocation.y = (short)HIWORD(lParam);
-#if 0
         if (fVertical)
             delta = newLocation.x - fLastLocation.x;
         else
             delta = newLocation.y - fLastLocation.y;
-
-#endif
+        if(fNeededSize + delta < 0)
+            return 0;
+        fNeededSize += delta;
         fLastLocation = newLocation;
+        ReserveBorderSpace();
     }
     return 0;
 }
Index: dll/win32/browseui/basebarsite.cpp
===================================================================
--- dll/win32/browseui/basebarsite.cpp	(révision 70688)
+++ dll/win32/browseui/basebarsite.cpp	(copie de travail)
@@ -27,14 +27,13 @@
 
 /*
 TODO:
-****Fix so an already created bar will be detected and just shown instead of added again
-****When a new bar is added, initiate a resize
-  **Add owner draw for base bar
+****When a new bar is added, resize correctly the band inside instead of keeping current size.
+   *Translate close button label
+  **Add owner draw for base bar -- hackplemented atm
   **Make label text in base bar always draw in black
-  **Make base bar show close box
-  **Create close toolbar button
-  **Fix to delete all CBarInfo on deletion
-
+ ***Set rebar band style flags accordingly to what band object asked.
+ ***Set rebar style accordingly to direction
+****This class should also manage start menu bands ? (another kind of explorer bands)
 */
 
 class CBaseBarSite :
@@ -65,6 +64,8 @@
 //    HWND                                    fRebarWindow;           // rebar for top of window
     CComPtr<IUnknown>                       fDeskBarSite;
     DWORD                                   fNextBandID;
+    HWND                                    toolbarWnd;
+    HIMAGELIST                              toolImageList;
 public:
     CBaseBarSite();
     ~CBaseBarSite();
@@ -125,9 +126,15 @@
 
     // message handlers
     LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+    LRESULT OnCustomDraw(LPNMCUSTOMDRAW pnmcd);
 
+    HRESULT FindBandByGUID(REFIID pGuid, DWORD *pdwBandID);
+    HRESULT ShowBand(DWORD dwBandID);
+
 BEGIN_MSG_MAP(CBaseBarSite)
-    MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
+//    MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
+    MESSAGE_HANDLER(WM_COMMAND, OnCommand)
 END_MSG_MAP()
 
 BEGIN_COM_MAP(CBaseBarSite)
@@ -155,6 +162,7 @@
 
 CBaseBarSite::~CBaseBarSite()
 {
+    TRACE("CBaseBarSite deleted\n");
 }
 
 HRESULT CBaseBarSite::InsertBar(IUnknown *newBar)
@@ -169,6 +177,7 @@
     DESKBANDINFO                            deskBandInfo;
     DWORD                                   thisBandID;
     HRESULT                                 hResult;
+    CLSID                                   tmp;
 
     hResult = newBar->QueryInterface(IID_PPV_ARG(IPersist, &persist));
     if (FAILED_UNEXPECTEDLY(hResult))
@@ -185,9 +194,21 @@
     hResult = newBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
+    // Check if the GUID already exists
+    hResult = persist->GetClassID(&tmp);
+    if(!SUCCEEDED(hResult))
+    {
+        return E_INVALIDARG;
+    }
+    if(FindBandByGUID(tmp, &thisBandID) == S_OK)
+    {
+        return ShowBand(thisBandID);
+    }
+
     hResult = site->SetSite(static_cast<IOleWindow *>(this));
     if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
+
     ATLTRY(newInfo = new CBarInfo);
     if (newInfo == NULL)
         return E_OUTOFMEMORY;
@@ -196,7 +217,7 @@
     thisBandID = fNextBandID++;
     newInfo->fTheBar = newBar;
     newInfo->fBandID = thisBandID;
-    hResult = persist->GetClassID(&newInfo->fBarClass);
+    newInfo->fBarClass = tmp;
 
     // get band info
     deskBandInfo.dwMask = DBIM_MINSIZE | DBIM_ACTUAL | DBIM_TITLE;
@@ -208,11 +229,14 @@
     bandInfo.cbSize = sizeof(bandInfo);
     bandInfo.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_TEXT |
         RBBIM_LPARAM | RBBIM_ID;
-    bandInfo.fStyle = RBBS_NOGRIPPER | RBBS_VARIABLEHEIGHT;
+    bandInfo.fStyle = RBBS_TOPALIGN | RBBS_VARIABLEHEIGHT;
     bandInfo.lpText = deskBandInfo.wszTitle;
     hResult = oleWindow->GetWindow(&bandInfo.hwndChild);
+    /* It seems Windows XP doesn't take account of band minsize */
+#if 0
     bandInfo.cxMinChild = 200; //deskBandInfo.ptMinSize.x;
     bandInfo.cyMinChild = 200; //deskBandInfo.ptMinSize.y;
+#endif
     bandInfo.cx = 0;
     bandInfo.wID = thisBandID;
     bandInfo.cyChild = -1; //deskBandInfo.ptActual.y;
@@ -221,15 +245,10 @@
     bandInfo.cxIdeal = 0; //deskBandInfo.ptActual.x;
     bandInfo.lParam = reinterpret_cast<LPARAM>(newInfo);
     SendMessage(RB_INSERTBANDW, -1, reinterpret_cast<LPARAM>(&bandInfo));
-
-    // this call is what makes the tree fill with contents
-    hResult = dockingWindow->ShowDW(TRUE);
-    if (FAILED_UNEXPECTEDLY(hResult))
-        return hResult;
-    // for now
+    hResult = ShowBand(newInfo->fBandID);
     fCurrentActiveBar = newInfo;
-    return S_OK;
-}
+    return hResult;
+ }
 
 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetWindow(HWND *lphwnd)
 {
@@ -281,7 +300,7 @@
     CComPtr<IDeskBar>                       deskBar;
     CComPtr<IWinEventHandler>               winEventHandler;
     NMHDR                                   *notifyHeader;
-    RECT                                    newBounds;
+    // RECT                                    newBounds;
     HRESULT                                 hResult;
 
     hResult = S_OK;
@@ -288,11 +307,23 @@
     if (uMsg == WM_NOTIFY)
     {
         notifyHeader = (NMHDR *)lParam;
-        if (notifyHeader->hwndFrom == m_hWnd && notifyHeader->code == RBN_AUTOSIZE)
+        if (notifyHeader->hwndFrom == m_hWnd)
         {
-            hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
-            GetClientRect(&newBounds);
-            hResult = deskBar->OnPosRectChangeDB(&newBounds);
+            switch(notifyHeader->code)
+            {
+                case RBN_AUTOSIZE:
+                    // For now, don't notify basebar we tried to resize ourselves, we don't
+                    // get correct values at the moment.
+#if 0
+                    hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
+                    GetClientRect(&newBounds);
+                    hResult = deskBar->OnPosRectChangeDB(&newBounds);
+                    
+#endif
+                    break;
+                case NM_CUSTOMDRAW:
+                    return OnCustomDraw((LPNMCUSTOMDRAW)lParam);
+            }
         }
     }
     if (fCurrentActiveBar != NULL)
@@ -319,12 +350,26 @@
 {
     CComPtr<IOleWindow>                     oleWindow;
     HWND                                    ownerWindow;
-    HRESULT                                 hResult;
+    HRESULT                                 hResult;  
+    DWORD                                   dwBandID;
+    
+    if (punkSite == NULL)
+    {
 
-    if (punkSite == NULL)
-        fDeskBarSite.Release();
+        TRACE("Destroying site \n");
+        /* Cleanup our bands */
+        while(SUCCEEDED(EnumBands(-1, &dwBandID)) && dwBandID)
+        {
+            hResult = EnumBands(0, &dwBandID);
+            RemoveBand(dwBandID);
+        }
+        fDeskBarSite = NULL;
+    }
     else
     {
+        TBBUTTON closeBtn;
+        HBITMAP hBmp;
+
         hResult = punkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
         if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
@@ -334,13 +379,50 @@
         hResult = oleWindow->GetWindow(&ownerWindow);
         if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
-        m_hWnd = CreateWindow(REBARCLASSNAMEW, NULL, WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS |
-                    WS_CLIPCHILDREN |
+
+        /* Create site window */
+        HWND tmp = CreateWindow(REBARCLASSNAMEW, NULL, WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS |
+                    WS_CLIPCHILDREN | WS_BORDER | 
                     RBS_VARHEIGHT | RBS_REGISTERDROP | RBS_AUTOSIZE | RBS_VERTICALGRIPPER | RBS_DBLCLKTOGGLE |
-                    CCS_LEFT | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE, 0, 0, 0, 0, ownerWindow, NULL,
+                    CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_VERT, 0, 0, 0, 0, ownerWindow, NULL,
                     _AtlBaseModule.GetModuleInstance(), NULL);
+
+        /* Give window management to ATL */
+        SubclassWindow(tmp);
+
         SendMessage(RB_SETTEXTCOLOR, 0, CLR_DEFAULT);
         SendMessage(RB_SETBKCOLOR, 0, CLR_DEFAULT);
+
+        /* Create close toolbar and imagelist */
+        toolbarWnd = CreateWindow(TOOLBARCLASSNAMEW, NULL,
+            WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
+            TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_TOOLTIPS | 
+            CCS_NOMOVEY | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NODIVIDER
+            , 0, 0, 0, 0, m_hWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
+
+        toolImageList = ImageList_Create(13, 11, ILC_COLOR24 | ILC_MASK, 3, 0);
+
+        hBmp = (HBITMAP)LoadImage(_AtlBaseModule.GetModuleInstance(),
+            MAKEINTRESOURCE(IDB_BANDBUTTONS), IMAGE_BITMAP, 0, 0,
+            LR_LOADTRANSPARENT);
+
+        ImageList_AddMasked(toolImageList, hBmp, RGB(192, 192, 192));
+        DeleteObject(hBmp);
+
+        SendMessage(toolbarWnd, TB_SETIMAGELIST, 0, (LPARAM)toolImageList);
+        
+        /* Add button to toolbar */
+        closeBtn.iBitmap = MAKELONG(1, 0);
+        closeBtn.idCommand = IDM_BASEBAR_CLOSE;
+        closeBtn.fsState = TBSTATE_ENABLED;
+        closeBtn.fsStyle = BTNS_BUTTON;
+        ZeroMemory(closeBtn.bReserved, sizeof(closeBtn.bReserved));
+        closeBtn.dwData = 0;
+        closeBtn.iString = (INT_PTR)L"Close";
+
+        SendMessage(toolbarWnd, TB_INSERTBUTTON, 0, (LPARAM)&closeBtn);
+        SendMessage(toolbarWnd, TB_SETMAXTEXTROWS, 0, 0);
+        //SendMessage(toolbarWnd, TB_AUTOSIZE, 0, 0);
     }
     return S_OK;
 }
@@ -389,12 +471,26 @@
 
 HRESULT STDMETHODCALLTYPE CBaseBarSite::EnumBands(UINT uBand, DWORD *pdwBandID)
 {
+    REBARBANDINFO bandInfo;
+
+    if(pdwBandID == NULL)
+        return E_INVALIDARG;
     if (uBand == 0xffffffff)
     {
         *pdwBandID = (DWORD)SendMessage(RB_GETBANDCOUNT, 0, 0);
         return S_OK;
     }
-    return E_NOTIMPL;
+    /* Grab our band info */
+    memset(&bandInfo, 0, sizeof(bandInfo));
+    bandInfo.cbSize = sizeof(bandInfo);
+    bandInfo.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_TEXT |
+        RBBIM_LPARAM | RBBIM_ID;
+
+    // Grab our bandinfo from rebar control
+    if(!SendMessage(RB_GETBANDINFO, uBand, reinterpret_cast<LPARAM>(&bandInfo)))
+        return E_INVALIDARG;
+    *pdwBandID = bandInfo.wID;
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryBand(DWORD dwBandID, IDeskBand **ppstb,
@@ -410,14 +506,92 @@
 
 HRESULT STDMETHODCALLTYPE CBaseBarSite::RemoveBand(DWORD dwBandID)
 {
-    return E_NOTIMPL;
+    REBARBANDINFO                   bandInfo;
+    HRESULT                         hr;
+    CBarInfo                        *pInfo;
+    CComPtr<IObjectWithSite>        pSite;
+    CComPtr<IDockingWindow>         pDockWnd;
+    DWORD                           index;
+
+    // Retrieve the right index of the coolbar knowing the id
+    index = SendMessage(RB_IDTOINDEX, dwBandID, 0);
+    if(index == 0xffffffff)
+       return E_INVALIDARG;
+
+    // Query band info to retrieve lParam containing our pointer
+    memset(&bandInfo, 0, sizeof(bandInfo));
+    bandInfo.cbSize = sizeof(bandInfo);
+    bandInfo.fMask = RBBIM_LPARAM;
+    if(!SendMessage(RB_GETBANDINFO, index, reinterpret_cast<LPARAM>(&bandInfo)))
+    {
+        ERR("This shouldn't happen !\n");
+        return E_INVALIDARG;
+    }
+    pInfo = reinterpret_cast<CBarInfo*>(bandInfo.lParam);
+    if(!pInfo)
+        return E_INVALIDARG;
+
+    hr = pInfo->fTheBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &pDockWnd));
+    if(!SUCCEEDED(hr))
+    {
+        ERR("Can't get docking window interface\n");
+        return E_NOINTERFACE;
+    }
+    hr = pInfo->fTheBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pSite));
+    if(!SUCCEEDED(hr))
+    {
+        ERR("Can't detach window from site !\n");
+        return E_NOINTERFACE;
+    }
+    /* Windows sends a CloseDW before setting site to NULL */
+    pDockWnd->CloseDW(0);
+    pSite->SetSite(NULL);
+
+    // Delete the band from rebar
+    if(!SendMessage(RB_DELETEBAND, index, 0))
+    {
+        ERR("Can't delete the band !\n");
+        return E_INVALIDARG;
+    }
+    if(pInfo == fCurrentActiveBar)
+    {
+        // FIXME: what to do when we are deleting active bar ? Let's assume we remove it for now
+        fCurrentActiveBar = NULL;
+    }
+    ATLTRY(delete pInfo);
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CBaseBarSite::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv)
 {
+    REBARBANDINFO               bandInfo;
+    HRESULT                     hr;
+    CBarInfo                    *pInfo;
+    DWORD                       index;
+
     if (ppv == NULL)
         return E_POINTER;
-    return E_NOTIMPL;
+
+    // Retrieve the right index of the coolbar knowing the id
+    index = SendMessage(RB_IDTOINDEX, dwBandID, 0);
+    if(index == 0xffffffff)
+       return E_INVALIDARG;
+
+    // Query band info to retrieve lParam containing our pointer
+    memset(&bandInfo, 0, sizeof(bandInfo));
+    bandInfo.cbSize = sizeof(bandInfo);
+    bandInfo.fMask = RBBIM_LPARAM;
+    if(!SendMessage(RB_GETBANDINFO, index, reinterpret_cast<LPARAM>(&bandInfo)))
+    {
+        ERR("This shouldn't happen !\n");
+        return E_INVALIDARG;
+    }
+
+    pInfo = reinterpret_cast<CBarInfo*>(bandInfo.lParam);
+    hr = pInfo->fTheBar->QueryInterface(riid, ppv);
+    if(!SUCCEEDED(hr))
+        return E_NOINTERFACE;
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE CBaseBarSite::SetBandSiteInfo(const BANDSITEINFO *pbsinfo)
@@ -475,6 +649,107 @@
     return 0;
 }
 
+LRESULT CBaseBarSite::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    HRESULT                             hResult;
+    CComPtr<IDockingWindow>             parentSite;
+
+    if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDM_BASEBAR_CLOSE)
+    {
+        hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IDockingWindow, &parentSite));
+        if(!SUCCEEDED(hResult))
+        {
+            return E_FAIL;
+        }
+        parentSite->ShowDW(FALSE);
+        bHandled = TRUE;
+    }
+    return 0;
+}
+
+LRESULT CBaseBarSite::OnCustomDraw(LPNMCUSTOMDRAW pnmcd)
+{
+    switch(pnmcd->dwDrawStage)
+    {
+        case CDDS_PREPAINT:
+            return CDRF_NOTIFYITEMDRAW;
+        case CDDS_ITEMPREPAINT:
+            // TODO: this code is hack that only works for vertical bands, and doesn't support themes
+            // yet. Maybe it should live in its own function too.
+            DrawEdge(pnmcd->hdc, &pnmcd->rc, EDGE_ETCHED, BF_BOTTOM);
+            // We also resize our close button
+            ::SetWindowPos(toolbarWnd, HWND_TOP, pnmcd->rc.right - 22, 2, 20, 18, SWP_SHOWWINDOW);
+            return CDRF_DODEFAULT;
+        default:
+            break;
+    }
+    return CDRF_DODEFAULT;
+}
+
+HRESULT CBaseBarSite::FindBandByGUID(REFGUID pGuid, DWORD *pdwBandID)
+{
+    DWORD                       numBands;
+    DWORD                       i;
+    HRESULT                     hr;
+    REBARBANDINFO               bandInfo;
+    CBarInfo                    *realInfo;
+
+    hr = EnumBands(-1, &numBands);
+    if(!SUCCEEDED(hr))
+    {
+        ERR("Can't get band count\n");
+        return E_FAIL;
+    }
+    for(i = 0; i < numBands; i++)
+    {
+        bandInfo.fMask = RBBIM_LPARAM;
+        if(!SendMessage(RB_GETBANDINFO, i, reinterpret_cast<LPARAM>(&bandInfo)))
+        {
+            ERR("Can't get band info\n");
+            return E_FAIL;
+        }
+        realInfo = (CBarInfo*)bandInfo.lParam;
+        if(IsEqualGUID(pGuid, realInfo->fBarClass))
+        {
+            *pdwBandID = realInfo->fBandID;
+            return S_OK;
+        }
+    }
+    return S_FALSE;
+}
+
+HRESULT CBaseBarSite::ShowBand(DWORD dwBandID)
+{
+    UINT                        index;
+    CComPtr<IDockingWindow>     dockingWindow;
+    HRESULT                     hResult;
+
+    // show our band
+    hResult = GetBandObject(dwBandID, IID_PPV_ARG(IDockingWindow, &dockingWindow));
+    if(!SUCCEEDED(hResult))
+    {
+        return E_FAIL;
+    }
+    hResult = dockingWindow->ShowDW(TRUE);
+
+    // Hide old band while adding new one
+    if(fCurrentActiveBar && fCurrentActiveBar->fBandID != dwBandID)
+    {
+        DWORD index;
+        index = SendMessage(RB_IDTOINDEX, fCurrentActiveBar->fBandID, 0);
+        if(index != 0xffffffff)
+            SendMessage(RB_SHOWBAND, index, 0);
+    }
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return hResult;
+
+    // Display the current band
+    index = SendMessage(RB_IDTOINDEX, dwBandID, 0);
+    if(index != 0xffffffff)
+        SendMessage(RB_SHOWBAND, index, 1);
+    return S_OK;
+}
+
 HRESULT CreateBaseBarSite(REFIID riid, void **ppv)
 {
     return ShellObjectCreator<CBaseBarSite>(riid, ppv);
