diff --git a/dll/win32/browseui/internettoolbar.cpp b/dll/win32/browseui/internettoolbar.cpp index 5d16b051e4f..f094e9a5d86 100644 --- a/dll/win32/browseui/internettoolbar.cpp +++ b/dll/win32/browseui/internettoolbar.cpp @@ -75,6 +75,19 @@ TODO: extern HRESULT WINAPI SHBindToFolder(LPCITEMIDLIST path, IShellFolder **newFolder); +struct ITBARSTATE +{ + static const UINT SIG = ('R' << 0) | ('O' << 8) | ('S' << 16) | (('i' ^ 't' ^ 'b') << 24); + UINT cbSize; + UINT Signature; // Note: Windows has something else here (12 bytes) + UINT StdToolbar : 1; + UINT Addressbar : 1; + UINT Linksbar : 1; + UINT Throbber : 1; // toastytech.com/files/throboff.html + UINT Menubar : 1; // ..\Explorer\Advanced\AlwaysShowMenus for NT6? + // Note: Windows 8/10 stores the Ribbon state in ..\Explorer\Ribbon +}; + HRESULT IUnknown_RelayWinEvent(IUnknown * punk, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) { CComPtr menuWinEventHandler; @@ -614,6 +627,7 @@ CInternetToolbar::CInternetToolbar() fToolbarWindow = NULL; fAdviseCookie = 0; pSettings = NULL; + fIgnoreChanges = FALSE; } CInternetToolbar::~CInternetToolbar() @@ -893,6 +907,7 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::ShowDW(BOOL fShow) return hResult; } +#if 0 // Why should showing the IDockingWindow change all bands? Related to CORE-17236 if (fMenuBar) { hResult = IUnknown_ShowDW(fMenuBar, fShow); @@ -918,6 +933,7 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::ShowDW(BOOL fShow) if (FAILED_UNEXPECTEDLY(hResult)) return hResult; } +#endif return S_OK; } @@ -1001,6 +1017,14 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::GetClassID(CLSID *pClassID) return S_OK; } +HRESULT CInternetToolbar::SetDirty() +{ + if (fIgnoreChanges) + return S_OK; + IUnknown_Exec(fSite, CGID_ShellBrowser, IDM_NOTIFYITBARDIRTY, 0, NULL, NULL); + return S_OK; +} + HRESULT STDMETHODCALLTYPE CInternetToolbar::IsDirty() { return E_NOTIMPL; @@ -1008,12 +1032,35 @@ HRESULT STDMETHODCALLTYPE CInternetToolbar::IsDirty() HRESULT STDMETHODCALLTYPE CInternetToolbar::Load(IStream *pStm) { - return E_NOTIMPL; + fIgnoreChanges = TRUE; + HRESULT hr = InitNew(); + ITBARSTATE state; + if (SUCCEEDED(hr)) + { + hr = S_FALSE; + ULONG cb = sizeof(state); + if (pStm->Read(&state, cb, &cb) == S_OK && state.Signature == state.SIG) + { + SetBandVisibility(ITBBID_MENUBAND, state.Menubar); + SetBandVisibility(ITBBID_TOOLSBAND, state.StdToolbar); + SetBandVisibility(ITBBID_ADDRESSBAND, state.Addressbar); + //SetBandVisibility(ITBBID_?, state.Linksbar); + //SetBandVisibility(ITBBID_?, state.Throbber); + hr = S_OK; + } + } + fIgnoreChanges = FALSE; + return hr; } HRESULT STDMETHODCALLTYPE CInternetToolbar::Save(IStream *pStm, BOOL fClearDirty) { - return E_NOTIMPL; + ITBARSTATE state = { sizeof(state), state.SIG }; + state.Menubar = IsBandVisible(ITBBID_MENUBAND) == S_OK; + state.StdToolbar = IsBandVisible(ITBBID_TOOLSBAND) == S_OK; + state.Addressbar = IsBandVisible(ITBBID_ADDRESSBAND) == S_OK; + state.Linksbar = FALSE; + return pStm->Write(&state, sizeof(state), NULL); } HRESULT STDMETHODCALLTYPE CInternetToolbar::GetSizeMax(ULARGE_INTEGER *pcbSize) @@ -1080,24 +1127,34 @@ HRESULT CInternetToolbar::IsBandVisible(int BandID) return (bandInfo.fStyle & RBBS_HIDDEN) ? S_FALSE : S_OK; } -HRESULT CInternetToolbar::ToggleBandVisibility(int BandID) +HRESULT CInternetToolbar::SetBandVisibility(int BandID, int Show) { int index = (int)SendMessage(fMainReBar, RB_IDTOINDEX, BandID, 0); + REBARBANDINFOW bandInfo = {sizeof(REBARBANDINFOW), RBBIM_STYLE | RBBIM_CHILD}; + if (!SendMessage(fMainReBar, RB_GETBANDINFOW, index, (LPARAM)&bandInfo)) + return E_FAIL; - REBARBANDINFOW bandInfo = {sizeof(REBARBANDINFOW), RBBIM_STYLE}; - SendMessage(fMainReBar, RB_GETBANDINFOW, index, (LPARAM)&bandInfo); - - if (bandInfo.fStyle & RBBS_HIDDEN) + if (Show < 0) + bandInfo.fStyle ^= RBBS_HIDDEN; // Toggle + else if (Show) bandInfo.fStyle &= ~RBBS_HIDDEN; else bandInfo.fStyle |= RBBS_HIDDEN; + bandInfo.fMask &= ~RBBIM_CHILD; + ::ShowWindow(bandInfo.hwndChild, (bandInfo.fStyle & RBBS_HIDDEN) ? SW_HIDE : SW_SHOW); // CORE-17236 SendMessage(fMainReBar, RB_SETBANDINFOW, index, (LPARAM)&bandInfo); ReserveBorderSpace(0); + SetDirty(); return S_OK; } +HRESULT CInternetToolbar::ToggleBandVisibility(int BandID) +{ + return SetBandVisibility(BandID, -1); +} + HRESULT STDMETHODCALLTYPE CInternetToolbar::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText) { @@ -1685,7 +1742,6 @@ LRESULT CInternetToolbar::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, if (hitTestInfo.iBand == -1) return 0; - pSettings->Load(); rebarBandInfo.cbSize = sizeof(rebarBandInfo); rebarBandInfo.fMask = RBBIM_ID; SendMessage(fMainReBar, RB_GETBANDINFOW, hitTestInfo.iBand, (LPARAM)&rebarBandInfo); @@ -1930,3 +1986,19 @@ LRESULT CInternetToolbar::OnSettingsChange(UINT uMsg, WPARAM wParam, LPARAM lPar return 0; } + +HRESULT CInternetToolbar::GetStream(UINT StreamFor, DWORD Stgm, IStream **ppS) +{ + WCHAR path[MAX_PATH]; + LPCWSTR subkey = NULL; + switch (StreamFor) + { + case ITBARSTREAM_SHELLBROWSER: subkey = L"ShellBrowser"; break; + case ITBARSTREAM_WEBBROWSER: subkey = L"WebBrowser"; break; + case ITBARSTREAM_EXPLORER: subkey = L"Explorer"; break; + default: return E_INVALIDARG; + } + wsprintfW(path, L"Software\\Microsoft\\Internet Explorer\\Toolbar\\%s", subkey); + *ppS = SHOpenRegStream2W(HKEY_CURRENT_USER, path, L"RosITBarLayout", Stgm); // ROS prefix until we figure out the correct format + return *ppS ? S_OK : E_FAIL; +} diff --git a/dll/win32/browseui/internettoolbar.h b/dll/win32/browseui/internettoolbar.h index 997b0a10a13..873788c90b2 100644 --- a/dll/win32/browseui/internettoolbar.h +++ b/dll/win32/browseui/internettoolbar.h @@ -20,6 +20,10 @@ #pragma once +#define ITBARSTREAM_SHELLBROWSER 0 +#define ITBARSTREAM_WEBBROWSER 1 +#define ITBARSTREAM_EXPLORER 2 + static const int gSearchCommandID = 1003; static const int gFoldersCommandID = 1004; static const int gMoveToCommandID = FCIDM_SHVIEW_MOVETO; @@ -93,6 +97,7 @@ public: POINT fStartPosition; LONG fStartHeight; ShellSettings *pSettings; + BOOL fIgnoreChanges; public: CInternetToolbar(); virtual ~CInternetToolbar(); @@ -104,9 +109,13 @@ public: HRESULT CommandStateChanged(bool newValue, int commandID); HRESULT CreateAndInitBandProxy(); HRESULT IsBandVisible(int BandID); + HRESULT SetBandVisibility(int BandID, int Show); HRESULT ToggleBandVisibility(int BandID); HRESULT SetState(const GUID *pguidCmdGroup, long commandID, OLECMD* pcmd); void RefreshLockedToolbarState(); + HRESULT SetDirty(); + + static HRESULT GetStream(UINT StreamFor, DWORD Stgm, IStream **ppS); public: // *** IInputObject specific methods *** diff --git a/dll/win32/browseui/resource.h b/dll/win32/browseui/resource.h index 9620a89eeb5..fecbd49a2df 100644 --- a/dll/win32/browseui/resource.h +++ b/dll/win32/browseui/resource.h @@ -73,6 +73,7 @@ /* Random id for band close button, feel free to change it */ #define IDM_BASEBAR_CLOSE 0xA200 +#define IDM_NOTIFYITBARDIRTY 0xA239 /* Arbitrary id */ /* User-installed explorer band IDs according to API Monitor traces */ #define IDM_EXPLORERBAND_BEGINCUSTOM 0xA240 diff --git a/dll/win32/browseui/settings.cpp b/dll/win32/browseui/settings.cpp index 0c0cf45b94d..89fb28f3666 100644 --- a/dll/win32/browseui/settings.cpp +++ b/dll/win32/browseui/settings.cpp @@ -35,6 +35,7 @@ void ShellSettings::Load() void CabinetStateSettings::Load() { + this->cLength = sizeof(CABINETSTATE); ReadCabinetState(this, this->cLength); /* Overrides */ diff --git a/dll/win32/browseui/shellbrowser.cpp b/dll/win32/browseui/shellbrowser.cpp index 38ab15e1535..b6af28f05b7 100644 --- a/dll/win32/browseui/shellbrowser.cpp +++ b/dll/win32/browseui/shellbrowser.cpp @@ -351,8 +351,10 @@ public: HRESULT UpdateUpState(); void UpdateGotoMenu(HMENU theMenu); void UpdateViewMenu(HMENU theMenu); + HRESULT IsInternetToolbarBandShown(UINT ITId); void RefreshCabinetState(); void UpdateWindowTitle(); + void SaveITBarLayout(); /* // *** IDockingWindowFrame methods *** STDMETHOD(AddToolbar)(IUnknown *punkSrc, LPCWSTR pwszItem, DWORD dwAddFlags) override; @@ -771,19 +773,11 @@ HRESULT CShellBrowser::Initialize() if (FAILED_UNEXPECTEDLY(hResult)) return hResult; - // TODO: create settingsStream from registry entry - //if (settingsStream.p) - //{ - // hResult = persistStreamInit->Load(settingsStream); - // if (FAILED_UNEXPECTEDLY(hResult)) - // return hResult; - //} - //else - { - hResult = persistStreamInit->InitNew(); - if (FAILED_UNEXPECTEDLY(hResult)) - return hResult; - } + CComPtr pITBarStream; + hResult = CInternetToolbar::GetStream(ITBARSTREAM_EXPLORER, STGM_READ, &pITBarStream); + hResult = SUCCEEDED(hResult) ? persistStreamInit->Load(pITBarStream) : persistStreamInit->InitNew(); + if (FAILED_UNEXPECTEDLY(hResult)) + return hResult; hResult = IUnknown_ShowDW(clientBar, TRUE); if (FAILED_UNEXPECTEDLY(hResult)) @@ -2136,6 +2130,9 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::Exec(const GUID *pguidCmdGroup, DWORD n { case 40994: return NavigateToParent(); + case IDM_NOTIFYITBARDIRTY: + SaveITBarLayout(); + break; } } else if (IsEqualIID(*pguidCmdGroup, CGID_IExplorerToolbar)) @@ -2383,7 +2380,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::QueryService(REFGUID guidService, REFII return this->QueryInterface(riid, ppvObject); if (IsEqualIID(guidService, SID_SProxyBrowser)) return this->QueryInterface(riid, ppvObject); - if (IsEqualIID(guidService, SID_IExplorerToolbar)) + if (IsEqualIID(guidService, SID_IExplorerToolbar) && fClientBars[BIInternetToolbar].clientBar.p) return fClientBars[BIInternetToolbar].clientBar->QueryInterface(riid, ppvObject); if (IsEqualIID(riid, IID_IShellBrowser)) return this->QueryInterface(riid, ppvObject); @@ -2495,6 +2492,9 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::ShowControlWindow(UINT id, BOOL fShow) return S_OK; case FCW_TREE: return Exec(&CGID_Explorer, SBCMDID_EXPLORERBARFOLDERS, 0, NULL, NULL); + case FCW_ADDRESSBAR: + return IUnknown_Exec(fClientBars[BIInternetToolbar].clientBar, + CGID_PrivCITCommands, ITID_ADDRESSBANDSHOWN, 0, NULL, NULL); } return E_NOTIMPL; } @@ -2515,6 +2515,10 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::IsControlWindowShown(UINT id, BOOL *pfS shown = cmd.cmdf & OLECMDF_LATCHED; break; } + case FCW_ADDRESSBAR: + hr = IsInternetToolbarBandShown(ITID_ADDRESSBANDSHOWN); + shown = hr == S_OK; + break; default: hr = E_NOTIMPL; } @@ -2526,6 +2530,14 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::IsControlWindowShown(UINT id, BOOL *pfS return SUCCEEDED(hr) ? (shown ? S_OK : S_FALSE) : hr; } +HRESULT CShellBrowser::IsInternetToolbarBandShown(UINT ITId) +{ + OLECMD cmd = { ITId }; + HRESULT hr = IUnknown_QueryStatus(fClientBars[BIInternetToolbar].clientBar, + CGID_PrivCITCommands, 1, &cmd, NULL); + return SUCCEEDED(hr) ? (cmd.cmdf & OLECMDF_LATCHED) ? S_OK : S_FALSE : hr; +} + HRESULT STDMETHODCALLTYPE CShellBrowser::IEGetDisplayName(LPCITEMIDLIST pidl, LPWSTR pwszName, UINT uFlags) { return E_NOTIMPL; @@ -3986,3 +3998,25 @@ void CShellBrowser::UpdateWindowTitle() if (SUCCEEDED(IEGetNameAndFlags(fCurrentDirectoryPIDL, flags, title, _countof(title), NULL))) SetWindowText(title); } + +void CShellBrowser::SaveITBarLayout() +{ + if (!gCabinetState.fSaveLocalView) + return; +#if 0 // If CDesktopBrowser aggregates us, skip saving + FOLDERSETTINGS fs; + if (fCurrentShellView && SUCCEEDED(fCurrentShellView->GetCurrentInfo(&fs)) && (fs.fFlags & FWF_DESKTOP)) + return; +#endif + + CComPtr pPSI; + CComPtr pITBarStream; + if (!fClientBars[BIInternetToolbar].clientBar.p) + return; + HRESULT hr = fClientBars[BIInternetToolbar].clientBar->QueryInterface(IID_PPV_ARG(IPersistStreamInit, &pPSI)); + if (FAILED(hr)) + return; + if (FAILED(hr = CInternetToolbar::GetStream(ITBARSTREAM_EXPLORER, STGM_WRITE, &pITBarStream))) + return; + pPSI->Save(pITBarStream, TRUE); +} diff --git a/sdk/include/reactos/browseui_undoc.h b/sdk/include/reactos/browseui_undoc.h index 3104a4dbd5a..fc210f09435 100644 --- a/sdk/include/reactos/browseui_undoc.h +++ b/sdk/include/reactos/browseui_undoc.h @@ -25,6 +25,8 @@ extern "C" { #endif /* defined(__cplusplus) */ +#define FCW_ADDRESSBAR 9 // GetControlWindow/IsControlWindowShown + // Name is IETHREADPARAM according to symbols / mangled function names #ifdef _WIN64 typedef struct IEThreadParamBlock