[BROWSEUI]
[reactos.git] / dll / win32 / browseui / internettoolbar.cpp
index 669183a..68b939e 100644 (file)
@@ -30,6 +30,23 @@ toolbar, and address band for an explorer window
 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
 
 #define USE_CUSTOM_MENUBAND 1
+HMODULE g_hRShell = NULL;
+
+#if 1
+// TODO: declare these GUIDs and interfaces in the right place (whatever that may be)
+
+IID IID_IAugmentedShellFolder = { 0x91EA3F8C, 0xC99B, 0x11D0, { 0x98, 0x15, 0x00, 0xC0, 0x4F, 0xD9, 0x19, 0x72 } };
+CLSID CLSID_MergedFolder = { 0x26FDC864, 0xBE88, 0x46E7, { 0x92, 0x35, 0x03, 0x2D, 0x8E, 0xA5, 0x16, 0x2E } };
+
+interface IAugmentedShellFolder : public IShellFolder
+{
+    virtual HRESULT STDMETHODCALLTYPE AddNameSpace(LPGUID, IShellFolder *, LPCITEMIDLIST, ULONG) = 0;
+    virtual HRESULT STDMETHODCALLTYPE GetNameSpaceID(LPCITEMIDLIST, LPGUID) = 0;
+    virtual HRESULT STDMETHODCALLTYPE QueryNameSpace(ULONG, LPGUID, IShellFolder **) = 0;
+    virtual HRESULT STDMETHODCALLTYPE EnumNameSpace(ULONG, PULONG) = 0;
+};
+
+#endif
 
 // navigation controls and menubar just send a message to parent window
 /*
@@ -73,12 +90,19 @@ extern HRESULT CreateBrandBand(REFIID riid, void **ppv);
 extern HRESULT CreateBandProxy(REFIID riid, void **ppv);
 extern HRESULT CreateAddressBand(REFIID riid, void **ppv);
 
+typedef HRESULT(WINAPI * PMENUBAND_CONSTRUCTOR)(REFIID riid, void **ppv);
+typedef HRESULT(WINAPI * PMERGEDFOLDER_CONSTRUCTOR)(REFIID riid, void **ppv);
+
+HMODULE hRShell = NULL;
+PMERGEDFOLDER_CONSTRUCTOR pCMergedFolder_Constructor = NULL;
+PMENUBAND_CONSTRUCTOR     pCMenuBand_Constructor = NULL;
+
 HRESULT IUnknown_HasFocusIO(IUnknown * punk)
 {
     CComPtr<IInputObject> pio;
     HRESULT hr;
     hr = punk->QueryInterface(IID_PPV_ARG(IInputObject, &pio));
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
     return pio->HasFocusIO();
 }
@@ -90,7 +114,7 @@ HRESULT IUnknown_TranslateAcceleratorIO(IUnknown * punk, MSG * pmsg)
     if (!punk)
         return E_FAIL;
     hr = punk->QueryInterface(IID_PPV_ARG(IInputObject, &pio));
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
     return pio->TranslateAcceleratorIO(pmsg);
 }
@@ -133,8 +157,6 @@ HRESULT IUnknown_CloseDW(IUnknown * punk, DWORD dwReserved)
     return S_OK;
 }
 
-typedef HRESULT(*PMENUBAND_CONSTRUCTOR)(REFIID riid, void **ppv);
-
 class CInternetToolbar;
 
 class CDockSite :
@@ -228,10 +250,10 @@ HRESULT CDockSite::Initialize(IUnknown *containedBand, CInternetToolbar *browser
     fBandID = bandID;
     fFlags = flags;
     hResult = IUnknown_SetSite(containedBand, static_cast<IOleWindow *>(this));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = IUnknown_GetWindow(containedBand, &fChildWindow);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     memset(&bandInfo, 0, sizeof(bandInfo));
@@ -252,7 +274,7 @@ HRESULT CDockSite::GetRBBandInfo(REBARBANDINFOW &bandInfo)
     HRESULT                                 hResult;
 
     hResult = fContainedBand->QueryInterface(IID_PPV_ARG(IDeskBand, &deskBand));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     fDeskBandInfo.dwMask = DBIM_BKCOLOR | DBIM_MODEFLAGS | DBIM_TITLE | DBIM_ACTUAL |
@@ -365,7 +387,7 @@ HRESULT STDMETHODCALLTYPE CDockSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdI
                 bandInfo.lpText = textBuffer;
                 bandInfo.cch = sizeof(textBuffer) / sizeof(TCHAR);
                 hResult = GetRBBandInfo(bandInfo);
-                if (FAILED(hResult))
+                if (FAILED_UNEXPECTEDLY(hResult))
                     return hResult;
                 index = (int)SendMessage(fRebarWindow, RB_IDTOINDEX, fBandID, 0);
                 SendMessage(fRebarWindow, RB_SETBANDINFOW, index, (LPARAM)&bandInfo);
@@ -391,6 +413,105 @@ CMenuCallback::~CMenuCallback()
 {
 }
 
+static HRESULT BindToDesktop(LPCITEMIDLIST pidl, IShellFolder ** ppsfResult)
+{
+    HRESULT hr;
+    CComPtr<IShellFolder> psfDesktop;
+
+    *ppsfResult = NULL;
+
+    hr = SHGetDesktopFolder(&psfDesktop);
+    if (FAILED(hr))
+        return hr;
+
+    hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, ppsfResult));
+
+    return hr;
+}
+
+static HRESULT GetFavoritesFolder(IShellFolder ** ppsfFavorites, LPITEMIDLIST * ppidl)
+{
+    HRESULT hr;
+    LPITEMIDLIST pidlUserFavorites;
+    LPITEMIDLIST pidlCommonFavorites;
+    CComPtr<IShellFolder> psfUserFavorites;
+    CComPtr<IShellFolder> psfCommonFavorites;
+    CComPtr<IAugmentedShellFolder> pasf;
+
+    if (ppsfFavorites)
+        *ppsfFavorites = NULL;
+    
+    if (ppidl)
+        *ppidl = NULL;
+
+    hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidlUserFavorites);
+    if (FAILED(hr))
+        return hr;
+
+    if (FAILED(SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_FAVORITES, &pidlCommonFavorites)))
+    {
+        hr = BindToDesktop(pidlUserFavorites, ppsfFavorites);
+        *ppidl = pidlUserFavorites;
+        return hr;
+    }
+
+    hr = BindToDesktop(pidlUserFavorites, &psfUserFavorites);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    hr = BindToDesktop(pidlCommonFavorites, &psfCommonFavorites);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+#if 1
+    if (!hRShell)
+    {
+        hRShell = GetModuleHandle(L"rshell.dll");
+        if (!hRShell)
+            hRShell = LoadLibrary(L"rshell.dll");
+    }
+
+    if (!pCMergedFolder_Constructor)
+        pCMergedFolder_Constructor = (PMERGEDFOLDER_CONSTRUCTOR) GetProcAddress(hRShell, "CMergedFolder_Constructor");
+
+    if (pCMergedFolder_Constructor)
+    {
+        hr = pCMergedFolder_Constructor(IID_PPV_ARG(IAugmentedShellFolder, &pasf));
+    }
+    else
+    {
+        hr = E_FAIL;
+    }
+#else
+    hr = CoCreateInstance(CLSID_MergedFolder, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IAugmentedShellFolder, &pasf));
+#endif
+    if (FAILED_UNEXPECTEDLY(hr))
+    {
+        *ppsfFavorites = psfUserFavorites.Detach();
+        *ppidl = pidlUserFavorites;
+        ILFree(pidlCommonFavorites);
+        return hr;
+    }
+
+    hr = pasf->AddNameSpace(NULL, psfUserFavorites, pidlUserFavorites, 0xFF00);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    hr = pasf->AddNameSpace(NULL, psfCommonFavorites, pidlCommonFavorites, 0);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    hr = pasf->QueryInterface(IID_PPV_ARG(IShellFolder, ppsfFavorites));
+    pasf.Release();
+
+    // TODO: obtain the folder's PIDL
+
+    ILFree(pidlCommonFavorites);
+    ILFree(pidlUserFavorites);
+
+    return hr;
+}
+
 HRESULT STDMETHODCALLTYPE CMenuCallback::GetObject(LPSMDATA psmd, REFIID riid, void **ppvObject)
 {
     CComPtr<IShellMenu>                     parentMenu;
@@ -415,21 +536,28 @@ HRESULT STDMETHODCALLTYPE CMenuCallback::GetObject(LPSMDATA psmd, REFIID riid, v
     {
         // create favorites menu
         hResult = psmd->punk->QueryInterface(IID_PPV_ARG(IShellMenu, &parentMenu));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         hResult = parentMenu->GetMenu(&parentHMenu, &ownerWindow, NULL);
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         favoritesHMenu = GetSubMenu(parentHMenu, 3);
         if (favoritesHMenu == NULL)
             return E_FAIL;
 #if USE_CUSTOM_MENUBAND
-        HMODULE hrs = LoadLibrary(L"rshell.dll");
+        if (!hRShell)
+        {
+            hRShell = GetModuleHandle(L"rshell.dll");
+            if (!hRShell)
+                hRShell = LoadLibrary(L"rshell.dll");
+        }
 
-        PMENUBAND_CONSTRUCTOR func = (PMENUBAND_CONSTRUCTOR) GetProcAddress(hrs, "CMenuBand_Constructor");
-        if (func)
+        if (!pCMenuBand_Constructor)
+            pCMenuBand_Constructor = (PMENUBAND_CONSTRUCTOR) GetProcAddress(hRShell, "CMenuBand_Constructor");
+
+        if (pCMenuBand_Constructor)
         {
-            hResult = func(IID_PPV_ARG(IShellMenu, &newMenu));
+            hResult = pCMenuBand_Constructor(IID_PPV_ARG(IShellMenu, &newMenu));
         }
         else
         {
@@ -440,29 +568,32 @@ HRESULT STDMETHODCALLTYPE CMenuCallback::GetObject(LPSMDATA psmd, REFIID riid, v
         hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER,
             IID_PPV_ARG(IShellMenu, &newMenu));
 #endif
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         hResult = newMenu->Initialize(this, FCIDM_MENU_FAVORITES, -1, SMINIT_VERTICAL | SMINIT_CACHED);
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         hResult = newMenu->SetMenu(favoritesHMenu, ownerWindow, SMSET_TOP | SMSET_DONTOWN);
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
-        hResult = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &favoritesPIDL);
-        if (FAILED(hResult))
+
+        RegCreateKeyEx(HKEY_CURRENT_USER, szFavoritesKey,
+                0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &orderRegKey, &disposition);
+
+        hResult = GetFavoritesFolder(&favoritesFolder, &favoritesPIDL);
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
-        hResult = SHBindToFolder(favoritesPIDL, &favoritesFolder);
+
+        hResult = newMenu->SetShellFolder(favoritesFolder, favoritesPIDL, orderRegKey, SMSET_BOTTOM | SMINIT_CACHED | SMINV_ID);
+        if (favoritesPIDL)
+            ILFree(favoritesPIDL);
+
         if (FAILED(hResult))
             return hResult;
-        RegCreateKeyEx(HKEY_CURRENT_USER, szFavoritesKey,
-                0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &orderRegKey, &disposition);
-        hResult = newMenu->SetShellFolder(favoritesFolder, favoritesPIDL, orderRegKey, SMSET_BOTTOM | 0x18);
-        ILFree(favoritesPIDL);
-        if (SUCCEEDED(hResult))
-            fFavoritesMenu.Attach(newMenu.Detach());
+            
+        fFavoritesMenu = newMenu;
     }
-    if (fFavoritesMenu.p == NULL)
-        return E_FAIL;
+
     return fFavoritesMenu->QueryInterface(riid, ppvObject);
 }
 
@@ -501,6 +632,7 @@ HRESULT STDMETHODCALLTYPE CMenuCallback::CallbackSM(LPSMDATA psmd, UINT uMsg, WP
         case SMC_GETSFOBJECT:
             break;
         case SMC_SFEXEC:
+            SHInvokeDefaultCommand(psmd->hwnd, psmd->psf, psmd->pidlItem);
             break;
         case SMC_SFSELECTITEM:
             break;
@@ -536,7 +668,7 @@ HRESULT STDMETHODCALLTYPE CMenuCallback::CallbackSM(LPSMDATA psmd, UINT uMsg, WP
         case 49:
             break;
         case 0x10000000:
-            break;
+            return S_OK;
     }
     return S_FALSE;
 }
@@ -547,14 +679,15 @@ CInternetToolbar::CInternetToolbar()
     fLocked = false;
     fMenuBandWindow = NULL;
     fNavigationWindow = NULL;
-    fMenuCallback.AddRef();
+    fMenuCallback = new CComObject<CMenuCallback>();
     fToolbarWindow = NULL;
     fAdviseCookie = 0;
+
+    fMenuCallback->AddRef();
 }
 
 CInternetToolbar::~CInternetToolbar()
 {
-    fMenuCallback.Release();
 }
 
 void CInternetToolbar::AddDockItem(IUnknown *newItem, int bandID, int flags)
@@ -571,10 +704,10 @@ HRESULT CInternetToolbar::ReserveBorderSpace(LONG maxHeight)
     RECT                                    availableBorderSpace;
 
     HRESULT hResult = fSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &dockingWindowSite));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = dockingWindowSite->GetBorderDW(static_cast<IDockingWindow *>(this), &availableBorderSpace);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     if (availableBorderSpace.top > maxHeight)
@@ -585,73 +718,75 @@ HRESULT CInternetToolbar::ReserveBorderSpace(LONG maxHeight)
     return ResizeBorderDW(&availableBorderSpace, fSite, FALSE);
 }
 
-HRESULT CInternetToolbar::CreateMenuBar(IShellMenu **menuBar)
+HRESULT CInternetToolbar::CreateMenuBar(IShellMenu **pMenuBar)
 {
-    CComPtr<IOleCommandTarget>              siteCommandTarget;
-    CComPtr<IOleWindow>                     oleWindow;
-    CComPtr<IOleCommandTarget>              commandTarget;
+    CComPtr<IShellMenu>                     menubar;
     CComPtr<IShellMenuCallback>             callback;
     VARIANT                                 menuOut;
     HWND                                    ownerWindow;
     HRESULT                                 hResult;
 
+    if (!pMenuBar)
+        return E_POINTER;
+
+    *pMenuBar = NULL;
+
+    hResult = E_FAIL;
 #if USE_CUSTOM_MENUBAND
-    HMODULE hrs = LoadLibraryW(L"rshell.dll");
+    if (!g_hRShell) g_hRShell = GetModuleHandleW(L"rshell.dll");
+    
+    if (!g_hRShell) g_hRShell = LoadLibraryW(L"rshell.dll");
 
-    if (!hrs)
+    if (g_hRShell)
     {
-        DbgPrint("Failed: %d\n", GetLastError());
-        return E_FAIL;
+        PMENUBAND_CONSTRUCTOR func = (PMENUBAND_CONSTRUCTOR) GetProcAddress(g_hRShell, "CMenuBand_Constructor");
+        if (func)
+        {
+            hResult = func(IID_PPV_ARG(IShellMenu, &menubar));
+        }
     }
+#endif
 
-    PMENUBAND_CONSTRUCTOR func = (PMENUBAND_CONSTRUCTOR) GetProcAddress(hrs, "CMenuBand_Constructor");
-    if (func)
-    {
-        hResult = func(IID_PPV_ARG(IShellMenu, menuBar));
-    }
-    else
-    {
-        DbgPrint("Failed: %d\n", GetLastError());
-        hResult = E_FAIL;
-    }
-    
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
     {
         hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER,
-            IID_PPV_ARG(IShellMenu, menuBar));
+            IID_PPV_ARG(IShellMenu, &menubar));
+        if (FAILED_UNEXPECTEDLY(hResult))
+            return hResult;
     }
-#else
-    hResult = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER,
-        IID_PPV_ARG(IShellMenu, menuBar));
-#endif
-    if (FAILED(hResult))
-        return hResult;
-    hResult = fMenuCallback.QueryInterface(IID_PPV_ARG(IShellMenuCallback, &callback));
-    if (FAILED(hResult))
-        return hResult;
-    hResult = (*menuBar)->Initialize(callback, -1, ANCESTORDEFAULT, SMINIT_HORIZONTAL | SMINIT_TOPLEVEL);
-    if (FAILED(hResult))
-        return hResult;
-    hResult = fSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
-    if (FAILED(hResult))
-        return hResult;
-    hResult = oleWindow->GetWindow(&ownerWindow);
-    if (FAILED(hResult))
-        return hResult;
-    hResult = fSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &siteCommandTarget));
-    if (FAILED(hResult))
-        return hResult;
-    hResult = siteCommandTarget->Exec(&CGID_Explorer, 0x35, 0, NULL, &menuOut);
-    if (FAILED(hResult))
+    
+    hResult = fMenuCallback->QueryInterface(IID_PPV_ARG(IShellMenuCallback, &callback));
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
-    if (V_VT(&menuOut) != VT_INT_PTR || V_INTREF(&menuOut) == NULL)
-        return E_FAIL;
-    hResult = (*menuBar)->SetMenu((HMENU)V_INTREF(&menuOut), ownerWindow, SMSET_DONTOWN);
-    if (FAILED(hResult))
+
+    hResult = menubar->Initialize(callback, -1, ANCESTORDEFAULT, SMINIT_HORIZONTAL | SMINIT_TOPLEVEL);
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
-    hResult = IUnknown_Exec(*menuBar, CGID_MenuBand, 3, 1, NULL, NULL);
-    if (FAILED(hResult))
+
+    // Set Menu
+    {
+        hResult = IUnknown_Exec(fSite, CGID_Explorer, 0x35, 0, NULL, &menuOut);
+        if (FAILED_UNEXPECTEDLY(hResult))
+            return hResult;
+
+        if (V_VT(&menuOut) != VT_INT_PTR || V_INTREF(&menuOut) == NULL)
+            return E_FAIL;
+
+        hResult = IUnknown_GetWindow(fSite, &ownerWindow);
+        if (FAILED_UNEXPECTEDLY(hResult))
+            return hResult;
+
+        hResult = menubar->SetMenu((HMENU) V_INTREF(&menuOut), ownerWindow, SMSET_DONTOWN);
+        if (FAILED_UNEXPECTEDLY(hResult))
+            return hResult;
+    }
+
+    hResult = IUnknown_Exec(menubar, CGID_MenuBand, 3, 1, NULL, NULL);
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
+
+    *pMenuBar = menubar.Detach();
+
     return S_OK;
 }
 
@@ -744,16 +879,16 @@ HRESULT CInternetToolbar::CreateAndInitBandProxy()
     HRESULT                                 hResult;
 
     hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = serviceProvider->QueryService(SID_IBandProxy, IID_PPV_ARG(IBandProxy, &fBandProxy));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
     {
         hResult = CreateBandProxy(IID_PPV_ARG(IBandProxy, &fBandProxy));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         hResult = fBandProxy->SetSite(fSite);
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
     }
     return S_OK;
@@ -861,27 +996,6 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::ShowDW(BOOL fShow)
     return S_OK;
 }
 
-template<class T>
-void ReleaseCComPtrExpectZero(CComPtr<T>& cptr, BOOL forceRelease = FALSE)
-{
-    if (cptr.p != NULL)
-    {
-        int nrc = cptr->Release();
-        if (nrc > 0)
-        {
-            DbgPrint("WARNING: Unexpected RefCount > 0 (%d)!\n", nrc);
-            if (forceRelease)
-            {
-                while (nrc > 0)
-                {
-                    nrc = cptr->Release();
-                }
-            }
-        }
-        cptr.Detach();
-    }
-}
-
 HRESULT STDMETHODCALLTYPE CInternetToolbar::CloseDW(DWORD dwReserved)
 {
     HRESULT                     hResult;
@@ -938,15 +1052,15 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::ResizeBorderDW(LPCRECT prcBorder,
     CComPtr<IDockingWindowSite> dockingWindowSite;
     
     HRESULT hResult = fSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &dockingWindowSite));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     hResult = dockingWindowSite->RequestBorderSpaceDW(static_cast<IDockingWindow *>(this), &neededBorderSpace);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     hResult = dockingWindowSite->SetBorderSpaceDW(static_cast<IDockingWindow *>(this), &neededBorderSpace);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     return S_OK;
@@ -990,7 +1104,7 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::InitNew()
 
     /* Create and attach the menubar to the rebar */
     hResult = CreateMenuBar(&menuBar);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     AddDockItem(menuBar, ITBBID_MENUBAND, CDockSite::ITF_NOTITLE | CDockSite::ITF_NEWBANDALWAYS | CDockSite::ITF_GRIPPERALWAYS);
 
@@ -1002,7 +1116,7 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::InitNew()
 #if 0
     /* Create and attach the brand/logo to the rebar */
     hResult = CreateBrandBand(&logoBar);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     AddDockItem(logoBar, ITBBID_BRANDBAND, CDockSite::ITF_NOGRIPPER | CDockSite::ITF_NOTITLE | CDockSite::ITF_FIXEDSIZE);
     fLogoBar.Attach(logoBar.Detach());                  // transfer the ref count
@@ -1010,17 +1124,17 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::InitNew()
 
     /* Create and attach the standard toolbar to the rebar */
     hResult = CreateToolsBar(&toolsBar);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     AddDockItem(toolsBar, ITBBID_TOOLSBAND, CDockSite::ITF_NOTITLE | CDockSite::ITF_NEWBANDALWAYS | CDockSite::ITF_GRIPPERALWAYS);
     fControlsBar.Attach(toolsBar.Detach());             // transfer the ref count
     hResult = IUnknown_GetWindow(fControlsBar, &fToolbarWindow);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     /* Create and attach the address/navigation toolbar to the rebar */
     hResult = CreateAddressBand(&navigationBar);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     AddDockItem(navigationBar, ITBBID_ADDRESSBAND, CDockSite::ITF_NEWBANDALWAYS | CDockSite::ITF_GRIPPERALWAYS);
     fNavigationBar.Attach(navigationBar.Detach());
@@ -1042,22 +1156,28 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryStatus(const GUID *pguidCmdGrou
                     prgCmds->cmdf = OLECMDF_SUPPORTED;
                     break;
                 case ITID_TOOLBARBANDSHOWN: // toolbar visibility
-                    prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
+                    prgCmds->cmdf = OLECMDF_SUPPORTED;
+                    if (fControlsBar)
+                        prgCmds->cmdf |= OLECMDF_LATCHED;
                     break;
                 case ITID_ADDRESSBANDSHOWN: // address bar visibility
-                    prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
+                    prgCmds->cmdf = OLECMDF_SUPPORTED;
+                    if (fNavigationBar)
+                        prgCmds->cmdf |= OLECMDF_LATCHED;
                     break;
                 case ITID_LINKSBANDSHOWN:   // links bar visibility
                     prgCmds->cmdf = 0;
                     break;
                 case ITID_MENUBANDSHOWN:    // Menubar band visibility
-                    prgCmds->cmdf = 0;
+                    prgCmds->cmdf = OLECMDF_SUPPORTED;
+                    if (fMenuBar)
+                        prgCmds->cmdf |= OLECMDF_LATCHED;
                     break;
                 case ITID_AUTOHIDEENABLED:  // Auto hide enabled/disabled
                     prgCmds->cmdf = 0;
                     break;
                 case ITID_CUSTOMIZEENABLED: // customize enabled
-                    prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
+                    prgCmds->cmdf = OLECMDF_SUPPORTED;
                     break;
                 case ITID_TOOLBARLOCKED:    // lock toolbars
                     prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
@@ -1161,9 +1281,11 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::SetCommandTarget(IUnknown *theTarget
 {
     HRESULT                                 hResult;
 
+    TRACE("SetCommandTarget %p category %s param %d\n", theTarget, wine_dbgstr_guid(category), param14);
+
     fCommandTarget.Release();
     hResult = theTarget->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &fCommandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     fCommandCategory = *category;
     return S_OK;
@@ -1269,10 +1391,10 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::SetSite(IUnknown *pUnkSite)
     {
         // get window handle of owner
         hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         hResult = oleWindow->GetWindow(&ownerWindow);
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         if (ownerWindow == NULL)
             return E_FAIL;
@@ -1326,7 +1448,7 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryService(REFGUID guidService, RE
         if (fBandProxy.p == NULL)
         {
             hResult = CreateAndInitBandProxy();
-            if (FAILED(hResult))
+            if (FAILED_UNEXPECTEDLY(hResult))
                 return hResult;
         }
         return fBandProxy->QueryInterface(riid, ppvObject);
@@ -1396,26 +1518,31 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryBand(DWORD dwBandID,
 
 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
 {
+    UNIMPLEMENTED;
     return E_NOTIMPL;
 }
 
 HRESULT STDMETHODCALLTYPE CInternetToolbar::RemoveBand(DWORD dwBandID)
 {
+    UNIMPLEMENTED;
     return E_NOTIMPL;
 }
 
 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetBandObject(DWORD dwBandID, REFIID riid, void **ppv)
 {
+    UNIMPLEMENTED;
     return E_NOTIMPL;
 }
 
 HRESULT STDMETHODCALLTYPE CInternetToolbar::SetBandSiteInfo(const BANDSITEINFO *pbsinfo)
 {
+    UNIMPLEMENTED;
     return E_NOTIMPL;
 }
 
 HRESULT STDMETHODCALLTYPE CInternetToolbar::GetBandSiteInfo(BANDSITEINFO *pbsinfo)
 {
+    UNIMPLEMENTED;
     return E_NOTIMPL;
 }
 
@@ -1426,11 +1553,11 @@ LRESULT CInternetToolbar::OnTravelBack(WORD wNotifyCode, WORD wID, HWND hWndCtl,
     HRESULT                                 hResult;
 
     hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = serviceProvider->QueryService(SID_SShellBrowser,
         IID_PPV_ARG(IWebBrowser, &webBrowser));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = webBrowser->GoBack();
     return 1;
@@ -1443,11 +1570,11 @@ LRESULT CInternetToolbar::OnTravelForward(WORD wNotifyCode, WORD wID, HWND hWndC
     HRESULT                                 hResult;
 
     hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = serviceProvider->QueryService(
         SID_SShellBrowser, IID_PPV_ARG(IWebBrowser, &webBrowser));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = webBrowser->GoForward();
     return 1;
@@ -1459,7 +1586,7 @@ LRESULT CInternetToolbar::OnUpLevel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BO
     HRESULT                                 hResult;
 
     hResult = fSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = oleCommandTarget->Exec(&CGID_ShellBrowser, IDM_GOTO_UPONELEVEL, 0, NULL, NULL);
     return 1;
@@ -1483,13 +1610,13 @@ LRESULT CInternetToolbar::OnSearch(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOO
 
     hResult = CoCreateInstance(CLSID_ShellSearchExt, NULL, CLSCTX_INPROC_SERVER,
         IID_PPV_ARG(IContextMenu, &contextMenu));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = contextMenu->QueryInterface(IID_PPV_ARG(IObjectWithSite, &objectWithSite));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = objectWithSite->SetSite(fSite);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = contextMenu->InvokeCommand(&commandInfo);
     hResult = objectWithSite->SetSite(NULL);
@@ -1502,7 +1629,7 @@ LRESULT CInternetToolbar::OnFolders(WORD wNotifyCode, WORD wID, HWND hWndCtl, BO
     HRESULT                                 hResult;
 
     hResult = fSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = oleCommandTarget->Exec(&CGID_Explorer, 0x23, 0, NULL, NULL);
     return 1;
@@ -1613,7 +1740,7 @@ LRESULT CInternetToolbar::OnMenuDropDown(UINT idControl, NMHDR *pNMHDR, BOOL &bH
             V_INTREF(&inValue) = reinterpret_cast<INT *>(&bounds);
 
             if (fCommandTarget.p != NULL)
-                hResult = fCommandTarget->Exec(&fCommandCategory, 0x7031, 1, &inValue, &outValue);
+                hResult = fCommandTarget->Exec(&fCommandCategory, FCIDM_SHVIEW_AUTOARRANGE, 1, &inValue, &outValue);
             // pvaOut is VT_I4 with value 0x403
             break;
     }
@@ -1676,12 +1803,18 @@ LRESULT CInternetToolbar::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam,
         default:
             break;
     }
-
-    MENUITEMINFO mii;
-    mii.cbSize = sizeof(mii);
-    mii.fMask = MIIM_STATE;
-    mii.fState = fLocked ? MFS_CHECKED : MFS_UNCHECKED;
-    command = SetMenuItemInfo(contextMenu, IDM_TOOLBARS_LOCKTOOLBARS, FALSE, &mii);
+    
+    // TODO: Implement show/hide toolbars
+    SHEnableMenuItem(contextMenu, IDM_TOOLBARS_STANDARDBUTTONS, FALSE);
+    SHEnableMenuItem(contextMenu, IDM_TOOLBARS_ADDRESSBAR, FALSE);
+    SHEnableMenuItem(contextMenu, IDM_TOOLBARS_LINKSBAR, FALSE);
+    SHEnableMenuItem(contextMenu, IDM_TOOLBARS_CUSTOMIZE, FALSE);
+
+    SHCheckMenuItem(contextMenu, IDM_TOOLBARS_STANDARDBUTTONS, fControlsBar != NULL);
+    SHCheckMenuItem(contextMenu, IDM_TOOLBARS_ADDRESSBAR, fNavigationBar != NULL);
+    SHCheckMenuItem(contextMenu, IDM_TOOLBARS_LINKSBAR, FALSE);
+    SHCheckMenuItem(contextMenu, IDM_TOOLBARS_CUSTOMIZE, FALSE);
+    SHCheckMenuItem(contextMenu, IDM_TOOLBARS_LOCKTOOLBARS, fLocked);
 
     // TODO: use GetSystemMetrics(SM_MENUDROPALIGNMENT) to determine menu alignment
     command = TrackPopupMenu(contextMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
@@ -1752,7 +1885,7 @@ LRESULT CInternetToolbar::OnTipText(UINT idControl, NMHDR *pNMHDR, BOOL &bHandle
             hResult = travelLog->GetToolTipText(browserService,
                 (nID == (UINT)IDM_GOTO_BACK) ? TLOG_BACK : TLOG_FORE,
                 0, tempString, 299);
-            if (FAILED(hResult))
+            if (FAILED_UNEXPECTEDLY(hResult))
             {
                 bHandled = FALSE;
                 return 0;
@@ -1856,20 +1989,5 @@ LRESULT CInternetToolbar::OnLUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
 
 HRESULT CreateInternetToolbar(REFIID riid, void **ppv)
 {
-    CInternetToolbar            *theToolbar;
-    HRESULT                     hResult;
-
-    if (ppv == NULL)
-        return E_POINTER;
-    *ppv = NULL;
-    ATLTRY (theToolbar = new CComObject<CInternetToolbar>);
-    if (theToolbar == NULL)
-        return E_OUTOFMEMORY;
-    hResult = theToolbar->QueryInterface (riid, reinterpret_cast<void **>(ppv));
-    if (FAILED(hResult))
-    {
-        delete theToolbar;
-        return hResult;
-    }
-    return S_OK;
+    return ShellObjectCreator<CInternetToolbar>(riid, ppv);
 }