[EXPLORER-NEW]
[reactos.git] / dll / win32 / browseui / shellbrowser.cpp
index ceba070..c12143e 100644 (file)
@@ -26,8 +26,9 @@
 extern "C"
 BOOL WINAPI Shell_GetImageLists(
     _Out_  HIMAGELIST *phiml,
-    _Out_  HIMAGELIST *phimlSmall
-    );
+    _Out_  HIMAGELIST *phimlSmall);
+
+extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow);
 
 #include "newatlinterfaces.h"
 
@@ -201,7 +202,7 @@ HRESULT WINAPI SHBindToFolder(LPCITEMIDLIST path, IShellFolder **newFolder)
     CComPtr<IShellFolder>                   desktop;
 
     HRESULT hr = ::SHGetDesktopFolder(&desktop);
-    if (FAILED(hr))
+    if (FAILED_UNEXPECTEDLY(hr))
         return E_FAIL;
     if (path == NULL || path->mkid.cb == 0)
     {
@@ -732,12 +733,9 @@ CShellBrowser::~CShellBrowser()
 
 HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, long b, long c, long d)
 {
-    CComPtr<IDockingWindow>                 dockingWindow;
-    CComPtr<IStream>                        settingsStream;
     CComPtr<IPersistStreamInit>             persistStreamInit;
-    CComPtr<IOleCommandTarget>              commandTarget;
-    CComPtr<IObjectWithSite>                objectSite;
     HRESULT                                 hResult;
+    CComPtr<IUnknown> clientBar;
 
     _AtlInitialConstruct();
 
@@ -753,58 +751,49 @@ HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, long b, long c, long d)
 
 #if 0
     hResult = CoCreateInstance(CLSID_InternetToolbar, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &fClientBars[BIInternetToolbar].clientBar));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 #else
-    hResult = CreateInternetToolbar(IID_PPV_ARG(IUnknown, &fClientBars[BIInternetToolbar].clientBar));
-    if (FAILED(hResult))
+    hResult = CreateInternetToolbar(IID_PPV_ARG(IUnknown, &clientBar));
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 #endif
 
+    fClientBars[BIInternetToolbar].clientBar = clientBar;
+
     // create interfaces
-    hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
-        IID_PPV_ARG(IDockingWindow, &dockingWindow));
-    if (FAILED(hResult))
-        return hResult;
-    hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
-        IID_PPV_ARG(IPersistStreamInit, &persistStreamInit));
-    if (FAILED(hResult))
-        return hResult;
-    hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
-        IID_PPV_ARG(IOleCommandTarget, &commandTarget));
-    if (FAILED(hResult))
-        return hResult;
-    hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
-        IID_PPV_ARG(IObjectWithSite, &objectSite));
-    if (FAILED(hResult))
+    hResult = clientBar->QueryInterface(IID_PPV_ARG(IPersistStreamInit, &persistStreamInit));
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
-    hResult = objectSite->SetSite(static_cast<IShellBrowser *>(this));
-    if (FAILED(hResult))
+    hResult = IUnknown_SetSite(clientBar, static_cast<IShellBrowser *>(this));
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
-    hResult = commandTarget->Exec(&CGID_PrivCITCommands, 1, 1 /* or 0 */, NULL, NULL);
-    if (FAILED(hResult))
+    hResult = IUnknown_Exec(clientBar, CGID_PrivCITCommands, 1, 1 /* or 0 */, NULL, NULL);
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     // TODO: create settingsStream from registry entry
-    if (settingsStream.p == NULL)
+    //if (settingsStream.p)
+    //{
+    //    hResult = persistStreamInit->Load(settingsStream);
+    //    if (FAILED_UNEXPECTEDLY(hResult))
+    //        return hResult;
+    //}
+    //else
     {
         hResult = persistStreamInit->InitNew();
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
     }
-    else
-    {
-        hResult = persistStreamInit->Load(settingsStream);
-        if (FAILED(hResult))
-            return hResult;
-    }
-    hResult = dockingWindow->ShowDW(TRUE);
-    if (FAILED(hResult))
+
+    hResult = IUnknown_ShowDW(clientBar, TRUE);
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
-    fToolbarProxy.Initialize(m_hWnd, fClientBars[BIInternetToolbar].clientBar);
+    fToolbarProxy.Initialize(m_hWnd, clientBar);
+
 
     // create status bar
     fStatusBar = CreateWindow(STATUSCLASSNAMEW, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
@@ -812,9 +801,10 @@ HRESULT CShellBrowser::Initialize(LPITEMIDLIST pidl, long b, long c, long d)
                     _AtlBaseModule.GetModuleInstance(), 0);
     fStatusBarVisible = true;
 
+
     // browse 
     hResult = BrowseToPIDL(pidl, BTP_UPDATE_NEXT_HISTORY);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     ShowWindow(SW_SHOWNORMAL);
@@ -831,13 +821,13 @@ HRESULT CShellBrowser::BrowseToPIDL(LPCITEMIDLIST pidl, long flags)
     // called by shell view to browse to new folder
     // also called by explorer band to navigate to new folder
     hResult = SHBindToFolder(pidl, &newFolder);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     newFolderSettings.ViewMode = FVM_ICON;
     newFolderSettings.fFlags = 0;
     hResult = BrowseToPath(newFolder, pidl, &newFolderSettings, flags);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     return S_OK;
 }
@@ -907,17 +897,32 @@ HRESULT IEGetNameAndFlagsEx(LPITEMIDLIST pidl, SHGDNF uFlags, long param10,
     LPWSTR pszBuf, UINT cchBuf, SFGAOF *rgfInOut)
 {
     CComPtr<IShellFolder>                   parentFolder;
-    LPITEMIDLIST                            childPIDL;
+    LPITEMIDLIST                            childPIDL = NULL;
     STRRET                                  L108;
     HRESULT                                 hResult;
 
     hResult = SHBindToFolderIDListParent(NULL, pidl, &IID_PPV_ARG(IShellFolder, &parentFolder), &childPIDL);
+    if (FAILED(hResult))
+        goto cleanup;
+
     hResult = parentFolder->GetDisplayNameOf(childPIDL, uFlags, &L108);
+    if (FAILED(hResult))
+        goto cleanup;
+
     StrRetToBufW(&L108, childPIDL, pszBuf, cchBuf);
     if (rgfInOut)
+    {
         hResult = parentFolder->GetAttributesOf(1, const_cast<LPCITEMIDLIST *>(&childPIDL), rgfInOut);
-    ILFree(childPIDL);
-    return S_OK;
+        if (FAILED(hResult))
+            goto cleanup;
+    }
+
+    hResult = S_OK;
+
+cleanup:
+    if (childPIDL)
+        ILFree(childPIDL);
+    return hResult;
 }
 
 long IEGetNameAndFlags(LPITEMIDLIST pidl, SHGDNF uFlags, LPWSTR pszBuf, UINT cchBuf, SFGAOF *rgfInOut)
@@ -946,7 +951,7 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
         return E_INVALIDARG;
 
     hResult = GetTravelLog(&travelLog);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
 
     // update history
@@ -957,9 +962,14 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
         // what to do with error? Do we want to halt browse because state save failed?
     }
 
+    if (fCurrentShellView)
+    {
+        fCurrentShellView->UIActivate(SVUIA_DEACTIVATE);
+    }
+
     // create view object
     hResult = newShellFolder->CreateViewObject(m_hWnd, IID_PPV_ARG(IShellView, &newShellView));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     previousView = fCurrentShellViewWindow;
 
@@ -990,7 +1000,7 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
     // create view window
     hResult = newShellView->CreateViewWindow(saveCurrentShellView, folderSettings,
         this, &shellViewWindowBounds, &newShellViewWindow);
-    if (FAILED(hResult) || newShellViewWindow == NULL)
+    if (FAILED_UNEXPECTEDLY(hResult) || newShellViewWindow == NULL)
     {
         fCurrentShellView = saveCurrentShellView;
         fCurrentShellFolder = saveCurrentShellFolder;
@@ -1068,11 +1078,17 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
         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);
+
         SendMessage(WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icSmall));
         SendMessage(WM_SETICON, ICON_BIG,   reinterpret_cast<LPARAM>(icLarge));
-    }
 
-    // TODO: Update the window icon
+        DestroyIcon(oldSmall);
+        DestroyIcon(oldLarge);
+    }
 
     FireCommandStateChangeAll();
     hResult = UpdateForwardBackState();
@@ -1086,18 +1102,17 @@ HRESULT CShellBrowser::GetMenuBand(REFIID riid, void **shellMenu)
     CComPtr<IDeskBand>                      deskBand;
     HRESULT                                 hResult;
 
-    if (fClientBars[BIInternetToolbar].clientBar.p == NULL)
+    if (!fClientBars[BIInternetToolbar].clientBar)
         return E_FAIL;
-    hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
-        IID_PPV_ARG(IServiceProvider, &serviceProvider));
-    if (FAILED(hResult))
-        return hResult;
-    hResult = serviceProvider->QueryService(SID_IBandSite, IID_PPV_ARG(IBandSite, &bandSite));
-    if (FAILED(hResult))
+
+    hResult = IUnknown_QueryService(fClientBars[BIInternetToolbar].clientBar, SID_IBandSite, IID_PPV_ARG(IBandSite, &bandSite));
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
+
     hResult = bandSite->QueryBand(1, &deskBand, NULL, NULL, 0);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
+
     return deskBand->QueryInterface(riid, shellMenu);
 }
 
@@ -1118,34 +1133,34 @@ HRESULT CShellBrowser::GetBaseBar(bool vertical, IUnknown **theBaseBar)
     if (*cache == NULL)
     {
         hResult = CreateBaseBar(IID_PPV_ARG(IUnknown, &newBaseBar));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         hResult = CreateBaseBarSite(IID_PPV_ARG(IUnknown, &newBaseBarSite));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
 
         // tell the new base bar about the shell browser
         hResult = newBaseBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &objectWithSite));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         hResult = objectWithSite->SetSite(static_cast<IDropTarget *>(this));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
 
         // tell the new base bar about the new base bar site
         hResult = newBaseBar->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         hResult = deskBar->SetClient(newBaseBarSite);
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
 
         // tell the new base bar site about the new base bar
         hResult = newBaseBarSite->QueryInterface(IID_PPV_ARG(IDeskBarClient, &deskBarClient));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
         hResult = deskBarClient->SetDeskBarSite(newBaseBar);
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
 
         *cache = newBaseBar.Detach();
@@ -1167,30 +1182,30 @@ HRESULT CShellBrowser::ShowBand(const CLSID &classID, bool vertical)
     __debugbreak();
 
     hResult = GetBaseBar(vertical, (IUnknown **)&theBaseBar);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = CoCreateInstance(classID, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &newBand));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = theBaseBar->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = deskBar->GetClient(&baseBarSite);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = theBaseBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = baseBarSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     V_VT(&vaIn) = VT_UNKNOWN;
     V_UNKNOWN(&vaIn) = newBand.p;
     hResult = oleCommandTarget->Exec(&CGID_IDeskBand, 1, 1, &vaIn, NULL);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = dockingWindow->ShowDW(TRUE);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     return S_OK;
 }
@@ -1206,7 +1221,7 @@ HRESULT CShellBrowser::NavigateToParent()
     ILRemoveLastID(newDirectory);
     hResult = BrowseToPIDL(newDirectory, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
     ILFree(newDirectory);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     return S_OK;
 }
@@ -1239,7 +1254,7 @@ HRESULT CShellBrowser::DoFolderOptions()
     // create sheet object
     hResult = CoCreateInstance(CLSID_ShellFldSetExt, NULL, CLSCTX_INPROC_SERVER,
         IID_PPV_ARG(IShellPropSheetExt, &folderOptionsSheet));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return E_FAIL;
 
     // must set site in order for Apply to all Folders on Advanced page to be enabled
@@ -1250,23 +1265,23 @@ HRESULT CShellBrowser::DoFolderOptions()
 
 #if 0
     hResult = CoCreateInstance(CLSID_GlobalFolderSettings, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IGlobalFolderSettings, &globalSettings));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return E_FAIL;
     hResult = globalSettings->Get(&shellState, sizeof(shellState));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return E_FAIL;
 #endif
 
     // add pages
     hResult = folderOptionsSheet->AddPages(AddFolderOptionsPage, reinterpret_cast<LPARAM>(&m_PropSheet));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return E_FAIL;
 
     if (fCurrentShellView != NULL)
     {
         hResult = fCurrentShellView->AddPropertySheetPages(
             0, AddFolderOptionsPage, reinterpret_cast<LPARAM>(&m_PropSheet));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return E_FAIL;
     }
 
@@ -1286,7 +1301,6 @@ LRESULT CALLBACK CShellBrowser::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam,
     CShellBrowser                           *pThis = reinterpret_cast<CShellBrowser *>(hWnd);
     _ATL_MSG                                msg(pThis->m_hWnd, uMsg, wParam, lParam);
     LRESULT                                 lResult;
-    CComPtr<IMenuBand>                      menuBand;
     const _ATL_MSG                          *previousMessage;
     BOOL                                    handled;
     WNDPROC                                 saveWindowProc;
@@ -1296,6 +1310,7 @@ 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)
     {
@@ -1306,6 +1321,7 @@ LRESULT CALLBACK CShellBrowser::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam,
         wParam = msg.wParam;
         lParam = msg.lParam;
     }
+    menuBand.Release();
 
     handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
     ATLASSERT(pThis->m_pCurrentMsg == &msg);
@@ -1493,7 +1509,7 @@ HRESULT CShellBrowser::UpdateForwardBackState()
     canGoBack = false;
     canGoForward = false;
     hResult = GetTravelLog(&travelLog);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = travelLog->GetTravelEntry(static_cast<IDropTarget *>(this), TLOG_BACK, &unusedEntry);
     if (SUCCEEDED(hResult))
@@ -1523,7 +1539,7 @@ void CShellBrowser::UpdateGotoMenu(HMENU theMenu)
 
     position = GetMenuItemCount(theMenu);
     hResult = GetTravelLog(&travelLog);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return;
     hResult = travelLog->InsertMenuEntries(static_cast<IDropTarget *>(this), theMenu, position,
         IDM_GOTO_TRAVEL_FIRSTTARGET, IDM_GOTO_TRAVEL_LASTTARGET, TLMENUF_BACKANDFORTH | TLMENUF_CHECKCURRENT);
@@ -1562,12 +1578,19 @@ void CShellBrowser::UpdateViewMenu(HMENU theMenu)
         IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
     if (SUCCEEDED(hResult))
         hResult = oleCommandTarget->QueryStatus(&CGID_PrivCITCommands, 5, commandList, NULL);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         DeleteMenu(theMenu, IDM_VIEW_TOOLBARS, MF_BYCOMMAND);
     else
     {
+        menuItemInfo.cbSize = sizeof(menuItemInfo);
+        menuItemInfo.fMask = MIIM_SUBMENU;
+        GetMenuItemInfo(theMenu, IDM_VIEW_TOOLBARS, FALSE, &menuItemInfo);
+        DestroyMenu(menuItemInfo.hSubMenu);
+
         toolbarMenuBar = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_CONTEXTMENU));
         toolbarMenu = GetSubMenu(toolbarMenuBar, 0);
+        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);
@@ -1597,10 +1620,10 @@ bool IUnknownIsEqual(IUnknown *int1, IUnknown *int2)
     if (int1 == NULL || int2 == NULL)
         return false;
     hResult = int1->QueryInterface(IID_PPV_ARG(IUnknown, &int1Retry));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return false;
     hResult = int2->QueryInterface(IID_PPV_ARG(IUnknown, &int2Retry));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return false;
     if (int1Retry == int2Retry)
         return true;
@@ -1837,11 +1860,14 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::ContextSensitiveHelp(BOOL fEnterMode)
 HRESULT STDMETHODCALLTYPE CShellBrowser::InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
 {
     HMENU mainMenu = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_MAINMENU));
+
     Shell_MergeMenus(hmenuShared, mainMenu, 0, 0, FCIDM_BROWSERLAST, MM_SUBMENUSHAVEIDS);
 
     int GCCU(itemCount3) = GetMenuItemCount(hmenuShared);
     Unused(itemCount3);
 
+    DestroyMenu(mainMenu);
+
     lpMenuWidths->width[0] = 2;
     lpMenuWidths->width[2] = 3;
     lpMenuWidths->width[4] = 1;
@@ -1853,13 +1879,13 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU h
     CComPtr<IShellMenu>                     shellMenu;
     HRESULT                                 hResult;
 
-    if (IsMenu(hmenuShared) == FALSE)
+    if (hmenuShared && IsMenu(hmenuShared) == FALSE)
         return E_FAIL;
     hResult = GetMenuBand(IID_PPV_ARG(IShellMenu, &shellMenu));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = shellMenu->SetMenu(hmenuShared, NULL, SMSET_DONTOWN);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     fCurrentMenuBar = hmenuShared;
     return S_OK;
@@ -1868,7 +1894,10 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU h
 HRESULT STDMETHODCALLTYPE CShellBrowser::RemoveMenusSB(HMENU hmenuShared)
 {
     if (hmenuShared == fCurrentMenuBar)
-        fCurrentMenuBar = NULL;
+    {
+        //DestroyMenu(fCurrentMenuBar);
+        SetMenuSB(NULL, NULL, NULL);
+    }
     return S_OK;
 }
 
@@ -2080,7 +2109,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::GetTravelLog(ITravelLog **pptl)
     if (fTravelLog.p == NULL)
     {
         hResult = CreateTravelLog(IID_PPV_ARG(ITravelLog, &fTravelLog));
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
     }
     *pptl = fTravelLog.p;
@@ -2534,15 +2563,20 @@ 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)
 {
-    if (fCurrentShellView->TranslateAcceleratorW(pmsg) != S_OK)
+    for (int i = 0; i < 3; i++)
     {
-        if (TranslateAcceleratorSB(pmsg, 0) != S_OK)
-            return S_FALSE;
-        return S_OK;
+        if (IUnknown_TranslateAcceleratorIO(fClientBars[i].clientBar, pmsg) == S_OK)
+            return S_OK;
     }
-    return S_OK;
+
+    if (!fCurrentShellView)
+        return S_FALSE;
+
+    return fCurrentShellView->TranslateAcceleratorW(pmsg);
 }
 
 HRESULT STDMETHODCALLTYPE CShellBrowser::_GetBorderDWHelper(IUnknown *punkSrc, LPRECT lprectBorder, BOOL bUseHmonitor)
@@ -2561,7 +2595,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::GoBack()
     HRESULT                                 hResult;
 
     hResult = GetTravelLog(&travelLog);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     return travelLog->Travel(static_cast<IDropTarget *>(this), TLOG_BACK);
 }
@@ -2572,7 +2606,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::GoForward()
     HRESULT                                 hResult;
 
     hResult = GetTravelLog(&travelLog);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     return travelLog->Travel(static_cast<IDropTarget *>(this), TLOG_FORE);
 }
@@ -2608,7 +2642,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::Refresh2(VARIANT *Level)
     HRESULT                                 hResult;
 
     hResult = fCurrentShellView->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     return oleCommandTarget->Exec(NULL, 22, 1, Level, NULL);
 }
@@ -2820,7 +2854,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::Navigate2(VARIANT *URL, VARIANT *Flags,
         return E_INVALIDARG;
     pidl = (LPITEMIDLIST)V_ARRAY(URL)->pvData;
     hResult = BrowseToPIDL((LPITEMIDLIST)pidl, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     return S_OK;
 }
@@ -2964,7 +2998,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::LoadHistory(IStream *pStream, IBindCtx
     HRESULT                                 hResult;
 
     hResult = pStream->Read(&oldState, sizeof(oldState), &numRead);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     if (numRead != sizeof(oldState) || oldState.dwSize != sizeof(oldState))
         return E_FAIL;
@@ -2974,7 +3008,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::LoadHistory(IStream *pStream, IBindCtx
     if (pidl == NULL)
         return E_OUTOFMEMORY;
     hResult = pStream->Read(pidl, oldState.pidlSize, &numRead);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
     {
         ILFree(pidl);
         return hResult;
@@ -2994,7 +3028,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::LoadHistory(IStream *pStream, IBindCtx
     fHistoryStream = NULL;
     fHistoryBindContext = NULL;
     ILFree(pidl);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     return S_OK;
 }
@@ -3014,20 +3048,20 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::SaveHistory(IStream *pStream)
     if (viewPersistHistory.p != NULL)
     {
         hResult = viewPersistHistory->GetClassID(&newState.persistClass);
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
     }
     newState.pidlSize = ILGetSize(fCurrentDirectoryPIDL);
     hResult = pStream->Write(&newState, sizeof(newState), NULL);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     hResult = pStream->Write(fCurrentDirectoryPIDL, newState.pidlSize, NULL);
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return hResult;
     if (viewPersistHistory.p != NULL)
     {
         hResult = viewPersistHistory->SaveHistory(pStream);
-        if (FAILED(hResult))
+        if (FAILED_UNEXPECTEDLY(hResult))
             return hResult;
     }
     return S_OK;
@@ -3051,7 +3085,33 @@ LRESULT CShellBrowser::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
 
 LRESULT CShellBrowser::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
+    HRESULT hr;
     // TODO: rip down everything
+    {
+        fCurrentShellView->DestroyViewWindow();
+        fCurrentShellView->UIActivate(SVUIA_DEACTIVATE);
+        ReleaseCComPtrExpectZero(fCurrentShellView);
+
+        for (int i = 0; i < 3; i++)
+        {
+            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);
+            pdw->CloseDW(0);
+            pdw->Release();
+            ReleaseCComPtrExpectZero(fClientBars[i].clientBar);
+        }
+        ReleaseCComPtrExpectZero(fTravelLog);
+
+        fCurrentShellFolder.Release();
+        ILFree(fCurrentDirectoryPIDL);
+        ::DestroyWindow(fStatusBar);
+        DestroyMenu(fCurrentMenuBar);
+    }
     PostQuitMessage(0);
     return 0;
 }
@@ -3087,12 +3147,40 @@ LRESULT CShellBrowser::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHa
 
 LRESULT CShellBrowser::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    HMENU                                   theMenu;
+    HMENU  theMenu;
+    LPARAM menuIndex = lParam;
 
     theMenu = reinterpret_cast<HMENU>(wParam);
-    if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_VIEW))
+
+    if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_FILE))
+    {
+        menuIndex = 0;
+    }
+    else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_EDIT))
+    {
+        menuIndex = 1;
+    }
+    else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_VIEW))
+    {
         UpdateViewMenu(theMenu);
-    return RelayMsgToShellView(uMsg, wParam, lParam, bHandled);
+        menuIndex = 2;
+    }
+    else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_FAVORITES))
+    {
+        menuIndex = 3;
+    }
+    else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_TOOLS))
+    {
+        menuIndex = 4;
+    }
+    else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_HELP))
+    {
+        menuIndex = 5;
+    }
+
+    LRESULT ret = RelayMsgToShellView(uMsg, wParam, menuIndex, bHandled);
+
+    return ret;
 }
 
 LRESULT CShellBrowser::RelayMsgToShellView(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
@@ -3214,7 +3302,7 @@ LRESULT CShellBrowser::OnToggleToolbarLock(WORD wNotifyCode, WORD wID, HWND hWnd
 
     hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
         IID_PPV_ARG(IOleCommandTarget, &commandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = commandTarget->Exec(&CGID_PrivCITCommands, ITID_TOOLBARLOCKED, 0, NULL, NULL);
     return 0;
@@ -3227,7 +3315,7 @@ LRESULT CShellBrowser::OnToggleToolbarBandVisible(WORD wNotifyCode, WORD wID, HW
 
     hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
         IID_PPV_ARG(IOleCommandTarget, &commandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = commandTarget->Exec(&CGID_PrivCITCommands, ITID_TOOLBARBANDSHOWN, 0, NULL, NULL);
     return 0;
@@ -3240,7 +3328,7 @@ LRESULT CShellBrowser::OnToggleAddressBandVisible(WORD wNotifyCode, WORD wID, HW
 
     hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
         IID_PPV_ARG(IOleCommandTarget, &commandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = commandTarget->Exec(&CGID_PrivCITCommands, ITID_ADDRESSBANDSHOWN, 0, NULL, NULL);
     return 0;
@@ -3253,7 +3341,7 @@ LRESULT CShellBrowser::OnToggleLinksBandVisible(WORD wNotifyCode, WORD wID, HWND
 
     hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
         IID_PPV_ARG(IOleCommandTarget, &commandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = commandTarget->Exec(&CGID_PrivCITCommands, ITID_LINKSBANDSHOWN, 0, NULL, NULL);
     return 0;
@@ -3266,7 +3354,7 @@ LRESULT CShellBrowser::OnToggleTextLabels(WORD wNotifyCode, WORD wID, HWND hWndC
 
     hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
         IID_PPV_ARG(IOleCommandTarget, &commandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = commandTarget->Exec(&CGID_PrivCITCommands, ITID_TEXTLABELS, 0, NULL, NULL);
     return 0;
@@ -3279,7 +3367,7 @@ LRESULT CShellBrowser::OnToolbarCustomize(WORD wNotifyCode, WORD wID, HWND hWndC
 
     hResult = fClientBars[BIInternetToolbar].clientBar->QueryInterface(
         IID_PPV_ARG(IOleCommandTarget, &commandTarget));
-    if (FAILED(hResult))
+    if (FAILED_UNEXPECTEDLY(hResult))
         return 0;
     hResult = commandTarget->Exec(&CGID_PrivCITCommands, ITID_CUSTOMIZEENABLED, 0, NULL, NULL);
     return 0;
@@ -3299,31 +3387,24 @@ LRESULT CShellBrowser::RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BO
 
 static HRESULT ExplorerMessageLoop(IEThreadParamBlock * parameters)
 {
-    CComPtr<IShellBrowser>                  shellBrowser;
-    CComObject<CShellBrowser>               *theCabinet;
-    HRESULT                                 hResult;
+    CComPtr<CShellBrowser>    theCabinet;
+    HRESULT                   hResult;
     MSG Msg;
     BOOL Ret;
 
-    OleInitialize(NULL);
-
+    // Tell the thread ref we are using it.
+    if (parameters && parameters->offsetF8)
+        parameters->offsetF8->AddRef();
+    
     ATLTRY(theCabinet = new CComObject<CShellBrowser>);
     if (theCabinet == NULL)
     {
-        hResult = E_OUTOFMEMORY;
-        goto uninitialize;
-    }
-
-    hResult = theCabinet->QueryInterface(IID_PPV_ARG(IShellBrowser, &shellBrowser));
-    if (FAILED(hResult))
-    {
-        delete theCabinet;
-        goto uninitialize;
+        return E_OUTOFMEMORY;
     }
-
+    
     hResult = theCabinet->Initialize(parameters->directoryPIDL, 0, 0, 0);
-    if (FAILED(hResult))
-        goto uninitialize;
+    if (FAILED_UNEXPECTEDLY(hResult))
+        return E_OUTOFMEMORY;
 
     while ((Ret = GetMessage(&Msg, NULL, 0, 0)) != 0)
     {
@@ -3333,23 +3414,43 @@ static HRESULT ExplorerMessageLoop(IEThreadParamBlock * parameters)
             break;
         }
 
+        if (Msg.message == WM_QUIT)
+            break;
+
         if (theCabinet->v_MayTranslateAccelerator(&Msg) != S_OK)
         {
             TranslateMessage(&Msg);
             DispatchMessage(&Msg);
         }
+    }
 
-        if (Msg.message == WM_QUIT)
-            break;
+    int nrc = theCabinet->Release();
+    if (nrc > 0)
+    {
+        DbgPrint("WARNING: There are %d references to the CShellBrowser active or leaked.\n", nrc);
     }
 
-uninitialize:
-    OleUninitialize();
+    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 hr;
     IEThreadParamBlock * parameters = (IEThreadParamBlock *) lpThreadParameter;
-    return ExplorerMessageLoop(parameters);
+
+    OleInitialize(NULL);
+
+    ATLTRY(hr = ExplorerMessageLoop(parameters));
+
+    OleUninitialize();
+
+    SHDestroyIETHREADPARAM(parameters);
+
+    return hr;
 }