xref: /reactos/dll/win32/browseui/shellbrowser.cpp (revision 6c74e69d)
1 /*
2  * ReactOS Explorer
3  *
4  * Copyright 2009 Andrew Hill <ash77 at domain reactos.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 #include "precomp.h"
22 
23 #include <shellapi.h>
24 #include <htiframe.h>
25 #include <strsafe.h>
26 
27 extern HRESULT IUnknown_ShowDW(IUnknown * punk, BOOL fShow);
28 
29 #include "newatlinterfaces.h"
30 
31 /*
32 TODO:
33   **Provide implementation of new and delete that use LocalAlloc
34   **Persist history for shell view isn't working correctly, possibly because of the mismatch between traveling and updating the travel log. The
35         view doesn't restore the selection correctly.
36   **Build explorer.exe, browseui.dll, comctl32.dll, shdocvw.dll, shell32.dll, shlwapi.dll into a directory and run them for testing...
37   **Add brand band bitmaps to shell32.dll
38   **If Go button on address bar is clicked, each time a new duplicate entry is added to travel log
39 ****The current entry is updated in travel log before doing the travel, which means when traveling back the update of the
40         current state overwrites the wrong entry's contents. This needs to be changed.
41 ****Fix close of browser window to release all objects
42 ****Given only a GUID in ShowBrowserBar, what is the correct way to determine if the bar is vertical or horizontal?
43   **When a new bar is added to base bar site, how is base bar told so it can resize?
44   **Does the base bar site have a classid?
45   **What should refresh command send to views to make them refresh?
46   **When new bar is created, what status notifications need to be fired?
47   **How does keyboard filtering dispatch?
48   **For deferred persist history load, how does the view connect up and get the state?
49     How does context menu send open, cut, rename commands to its site (the shell view)?
50   **Fix browser to implement IProfferService and hold onto brand band correctly - this will allow animations.
51 
52   **Route View->Toolbars commands to internet toolbar
53   **Handle travel log items in View->Go
54   **Fix ShowBrowserBar to pass correct size on when bar is shown
55 ****Fix SetBorderSpaceDW to cascade resize to subsequent bars
56 ****Make ShowToolbar check if bar is already created before creating it again
57 ****Shell should fill in the list of explorer bars in the View submenus
58   **Add folder menu in the file menu
59   **Fix CShellBrowser::GetBorderDW to compute available size correctly
60   **When a new bar is shown, re-fire the navigate event. This makes the explorer band select the correct folder
61   **Implement support for refresh. Forward refresh to explorer bar (refresh on toolbar and in menu is dispatched different)
62     Make folders toolbar item update state appropriately
63     Read list of bands from registry on launch
64     Read list of bars from registry on launch
65     If the folders or search bars don't exist, disable the toolbar buttons
66     If the favorites or history bars don't exist, disable the toolbar butons
67     Fix Apply to all Folders in Folder Options
68     Implement close command
69     Add explorer band context menu to file menu
70     Add code to allow restore of internet toolbar from registry
71     Fix code that calls FireNavigateComplete to pass the correct new path
72 
73     What are the other command ids for QueryStatus/FireCommandStateChange?
74 
75     Add handler for cabinet settings change
76     Add handler for system metrics change (renegotiate border space?)
77     Add handler for theme change and forward to contained windows
78 
79     When folders are shown, the status bar text should change
80     Add code to save/restore shell view settings
81     Implement tabbing between frames
82     Fix handling of focus everywhere
83     Most keyboard shortcuts don't work, such as F2 for rename, F5 for refresh (see list in "explorer keyboard shortcuts")
84 
85     The status bar doesn't show help text for items owned by frame during menu tracking
86     Stub out frame command handlers
87     "Arrange icons by" group is not checked properly
88 
89     When folders are hidden, icon is the same as the current shell object being displayed. When folders are shown,
90         the icon is always an open folder with magnifying glass
91     Fix bars to calculate height correctly
92     Hookup policies for everything...
93     Investigate toolbar message WM_USER+93
94     Investigate toolbar message WM_USER+100 (Adds extra padding between parts of buttons with BTNS_DROPDOWN | BTNS_SHOWTEXT style
95 
96     Vertical Explorer Bar		CATID_InfoBand
97     Horizontal Explorer Bar		CATID_CommBand
98     Desk Band					CATID_DeskBand
99 
100     cache of bars
101     HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021493-0000-0000-C000-000000000046}\Enum
102     HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021494-0000-0000-C000-000000000046}\Enum
103 
104     create key here with CLSID of bar to register tool band
105     HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Toolbar
106 
107 */
108 
109 #ifndef __GNUC__
110 #pragma comment(linker, \
111     "\"/manifestdependency:type='Win32' "\
112     "name='Microsoft.Windows.Common-Controls' "\
113     "version='6.0.0.0' "\
114     "processorArchitecture='*' "\
115     "publicKeyToken='6595b64144ccf1df' "\
116     "language='*'\"")
117 #endif // __GNUC__
118 
119 static const unsigned int                   folderOptionsPageCountMax = 20;
120 static const long                           BTP_DONT_UPDATE_HISTORY = 0;
121 static const long                           BTP_UPDATE_CUR_HISTORY = 1;
122 static const long                           BTP_UPDATE_NEXT_HISTORY = 2;
123 
124 BOOL                                        createNewStuff = false;
125 
126 
127 // this class is private to browseui.dll and is not registered externally?
128 //DEFINE_GUID(CLSID_ShellFldSetExt, 0x6D5313C0, 0x8C62, 0x11D1, 0xB2, 0xCD, 0x00, 0x60, 0x97, 0xDF, 0x8C, 0x11);
129 
130 void DeleteMenuItems(HMENU theMenu, unsigned int firstIDToDelete, unsigned int lastIDToDelete)
131 {
132     MENUITEMINFO                            menuItemInfo;
133     int                                     menuItemCount;
134     int                                     curIndex;
135 
136     menuItemCount = GetMenuItemCount(theMenu);
137     curIndex = 0;
138     while (curIndex < menuItemCount)
139     {
140         menuItemInfo.cbSize = sizeof(menuItemInfo);
141         menuItemInfo.fMask = MIIM_ID;
142         if (GetMenuItemInfo(theMenu, curIndex, TRUE, &menuItemInfo) &&
143             menuItemInfo.wID >= firstIDToDelete && menuItemInfo.wID <= lastIDToDelete)
144         {
145             DeleteMenu(theMenu, curIndex, MF_BYPOSITION);
146             menuItemCount--;
147         }
148         else
149             curIndex++;
150     }
151 }
152 
153 HRESULT WINAPI SHBindToFolder(LPCITEMIDLIST path, IShellFolder **newFolder)
154 {
155     CComPtr<IShellFolder>                   desktop;
156 
157     HRESULT hr = ::SHGetDesktopFolder(&desktop);
158     if (FAILED_UNEXPECTEDLY(hr))
159         return E_FAIL;
160     if (path == NULL || path->mkid.cb == 0)
161     {
162         *newFolder = desktop;
163         desktop.p->AddRef ();
164         return S_OK;
165     }
166     return desktop->BindToObject (path, NULL, IID_PPV_ARG(IShellFolder, newFolder));
167 }
168 
169 static const TCHAR szCabinetWndClass[] = TEXT("CabinetWClass");
170 //static const TCHAR szExploreWndClass[] = TEXT("ExploreWClass");
171 
172 class CDockManager;
173 class CShellBrowser;
174 
175 class CToolbarProxy :
176     public CWindowImpl<CToolbarProxy, CWindow, CControlWinTraits>
177 {
178 private:
179     CComPtr<IExplorerToolbar>               fExplorerToolbar;
180 public:
181     void Initialize(HWND parent, IUnknown *explorerToolbar);
182     void Destroy();
183 private:
184 
185     // message handlers
186     LRESULT OnAddBitmap(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
187     LRESULT OnForwardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
188 
189     BEGIN_MSG_MAP(CToolbarProxy)
190         MESSAGE_HANDLER(TB_ADDBITMAP, OnAddBitmap)
191         MESSAGE_RANGE_HANDLER(WM_USER, 0x7fff, OnForwardMessage)
192     END_MSG_MAP()
193 };
194 
195 void CToolbarProxy::Initialize(HWND parent, IUnknown *explorerToolbar)
196 {
197     HWND                                    myWindow;
198     HRESULT                                 hResult;
199 
200     myWindow = SHCreateWorkerWindowW(0, parent, 0, WS_CHILD, NULL, 0);
201     if (myWindow != NULL)
202     {
203         SubclassWindow(myWindow);
204         SetWindowPos(NULL, -32000, -32000, 0, 0, SWP_NOOWNERZORDER | SWP_NOZORDER);
205         hResult = explorerToolbar->QueryInterface(
206             IID_PPV_ARG(IExplorerToolbar, &fExplorerToolbar));
207     }
208 }
209 
210 void CToolbarProxy::Destroy()
211 {
212     DestroyWindow();
213     fExplorerToolbar = NULL;
214 }
215 
216 LRESULT CToolbarProxy::OnAddBitmap(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
217 {
218     long int                                result;
219     HRESULT                                 hResult;
220 
221     result = 0;
222     if (fExplorerToolbar.p != NULL)
223     {
224         hResult = fExplorerToolbar->AddBitmap(&CGID_ShellBrowser, 1, (long)wParam,
225             reinterpret_cast<TBADDBITMAP *>(lParam), &result, RGB(192, 192, 192));
226         hResult = fExplorerToolbar->AddBitmap(&CGID_ShellBrowser, 2, (long)wParam,
227             reinterpret_cast<TBADDBITMAP *>(lParam), &result, RGB(192, 192, 192));
228     }
229     return result;
230 }
231 
232 LRESULT CToolbarProxy::OnForwardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
233 {
234     LRESULT                                 result;
235     HRESULT                                 hResult;
236 
237     result = 0;
238     if (fExplorerToolbar.p != NULL)
239         hResult = fExplorerToolbar->SendToolbarMsg(&CGID_ShellBrowser, uMsg, wParam, lParam, &result);
240     return result;
241 }
242 
243 /*
244 Switch to a new bar when it receives an Exec(CGID_IDeskBand, 1, 1, vaIn, NULL);
245     where vaIn will be a VT_UNKNOWN with the new bar. It also sends a RB_SHOWBAND to the
246     rebar
247 */
248 
249 struct MenuBandInfo {
250     GUID barGuid;
251     BOOL fVertical;
252 };
253 
254 class CShellBrowser :
255     public CWindowImpl<CShellBrowser, CWindow, CFrameWinTraits>,
256     public CComObjectRootEx<CComMultiThreadModelNoCS>,
257     public IShellBrowser,
258     public IDropTarget,
259     public IServiceProvider,
260     public IProfferServiceImpl<CShellBrowser>,
261     public IShellBrowserService,
262     public IWebBrowser2,
263     public ITravelLogClient,
264     public IPersistHistory,
265     public IDockingWindowSite,
266     public IOleCommandTarget,
267     public IBrowserService2,
268     public IConnectionPointContainerImpl<CShellBrowser>,
269     public MyIConnectionPointImpl<CShellBrowser, &DIID_DWebBrowserEvents2>,
270     public MyIConnectionPointImpl<CShellBrowser, &DIID_DWebBrowserEvents>
271 {
272 private:
273     class barInfo
274     {
275     public:
276         barInfo()
277         {
278             memset(&borderSpace, 0, sizeof(borderSpace));
279             hwnd = NULL;
280         }
281 
282         RECT                                borderSpace;
283         CComPtr<IUnknown>                   clientBar;
284         HWND                                hwnd;
285     };
286     static const int                        BIInternetToolbar = 0;
287     static const int                        BIVerticalBaseBar = 1;
288     static const int                        BIHorizontalBaseBar = 2;
289 
290     HWND                                    fCurrentShellViewWindow;    // our currently hosted shell view window
291     CComPtr<IShellFolder>                   fCurrentShellFolder;        //
292     CComPtr<IShellView>                     fCurrentShellView;          //
293     LPITEMIDLIST                            fCurrentDirectoryPIDL;      //
294     HWND                                    fStatusBar;
295     CToolbarProxy                           fToolbarProxy;
296     barInfo                                 fClientBars[3];
297     CComPtr<ITravelLog>                     fTravelLog;
298     HMENU                                   fCurrentMenuBar;
299     GUID                                    fCurrentVertBar;             //The guid of the built in vertical bar that is being shown
300     // The next three fields support persisted history for shell views.
301     // They do not need to be reference counted.
302     IOleObject                              *fHistoryObject;
303     IStream                                 *fHistoryStream;
304     IBindCtx                                *fHistoryBindContext;
305     HDSA menuDsa;
306     HACCEL m_hAccel;
307     ShellSettings m_settings;
308     SBFOLDERSETTINGS m_deffoldersettings;
309 public:
310 #if 0
311     ULONG InternalAddRef()
312     {
313         OutputDebugString(_T("AddRef\n"));
314         return CComObjectRootEx<CComMultiThreadModelNoCS>::InternalAddRef();
315     }
316     ULONG InternalRelease()
317     {
318         OutputDebugString(_T("Release\n"));
319         return CComObjectRootEx<CComMultiThreadModelNoCS>::InternalRelease();
320     }
321 #endif
322 
323     CShellBrowser();
324     ~CShellBrowser();
325     HRESULT Initialize();
326 public:
327     HRESULT BrowseToPIDL(LPCITEMIDLIST pidl, long flags);
328     HRESULT BrowseToPath(IShellFolder *newShellFolder, LPCITEMIDLIST absolutePIDL,
329         FOLDERSETTINGS *folderSettings, long flags);
330     HRESULT GetMenuBand(REFIID riid, void **shellMenu);
331     HRESULT GetBaseBar(bool vertical, REFIID riid, void **theBaseBar);
332     BOOL IsBandLoaded(const CLSID clsidBand, bool vertical, DWORD *pdwBandID);
333     HRESULT ShowBand(const CLSID &classID, bool vertical);
334     HRESULT NavigateToParent();
335     HRESULT DoFolderOptions();
336     HRESULT ApplyBrowserDefaultFolderSettings(IShellView *pvs);
337     static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
338     void RepositionBars();
339     HRESULT BuildExplorerBandMenu();
340     HRESULT BuildExplorerBandCategory(HMENU hBandsMenu, CATID category, DWORD dwPos, UINT *nbFound);
341     BOOL IsBuiltinBand(CLSID &bandID);
342     virtual WNDPROC GetWindowProc()
343     {
344         return WindowProc;
345     }
346     HRESULT FireEvent(DISPID dispIdMember, int argCount, VARIANT *arguments);
347     HRESULT FireNavigateComplete(const wchar_t *newDirectory);
348     HRESULT FireCommandStateChange(bool newState, int commandID);
349     HRESULT FireCommandStateChangeAll();
350     HRESULT UpdateForwardBackState();
351     HRESULT UpdateUpState();
352     void UpdateGotoMenu(HMENU theMenu);
353     void UpdateViewMenu(HMENU theMenu);
354     HRESULT IsInternetToolbarBandShown(UINT ITId);
355     void RefreshCabinetState();
356     void UpdateWindowTitle();
357     void SaveITBarLayout();
358 
359 /*    // *** IDockingWindowFrame methods ***
360     STDMETHOD(AddToolbar)(IUnknown *punkSrc, LPCWSTR pwszItem, DWORD dwAddFlags) override;
361     STDMETHOD(RemoveToolbar)(IUnknown *punkSrc, DWORD dwRemoveFlags) override;
362     STDMETHOD(FindToolbar)(LPCWSTR pwszItem, REFIID riid, void **ppv) override;
363     */
364 
365     // *** IDockingWindowSite methods ***
366     STDMETHOD(GetBorderDW)(IUnknown* punkObj, LPRECT prcBorder) override;
367     STDMETHOD(RequestBorderSpaceDW)(IUnknown* punkObj, LPCBORDERWIDTHS pbw) override;
368     STDMETHOD(SetBorderSpaceDW)(IUnknown* punkObj, LPCBORDERWIDTHS pbw) override;
369 
370     // *** IOleCommandTarget methods ***
371     STDMETHOD(QueryStatus)(const GUID *pguidCmdGroup, ULONG cCmds,
372         OLECMD prgCmds[  ], OLECMDTEXT *pCmdText) override;
373     STDMETHOD(Exec)(const GUID *pguidCmdGroup, DWORD nCmdID,
374         DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) override;
375 
376     // *** IOleWindow methods ***
377     STDMETHOD(GetWindow)(HWND *lphwnd) override;
378     STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) override;
379 
380     // *** IShellBrowser methods ***
381     STDMETHOD(InsertMenusSB)(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override;
382     STDMETHOD(SetMenuSB)(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject) override;
383     STDMETHOD(RemoveMenusSB)(HMENU hmenuShared) override;
384     STDMETHOD(SetStatusTextSB)(LPCOLESTR pszStatusText) override;
385     STDMETHOD(EnableModelessSB)(BOOL fEnable) override;
386     STDMETHOD(TranslateAcceleratorSB)(MSG *pmsg, WORD wID) override;
387     STDMETHOD(BrowseObject)(LPCITEMIDLIST pidl, UINT wFlags) override;
388     STDMETHOD(GetViewStateStream)(DWORD grfMode, IStream **ppStrm) override;
389     STDMETHOD(GetControlWindow)(UINT id, HWND *lphwnd) override;
390     STDMETHOD(SendControlMsg)(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret) override;
391     STDMETHOD(QueryActiveShellView)(IShellView **ppshv) override;
392     STDMETHOD(OnViewWindowActive)(IShellView *ppshv) override;
393     STDMETHOD(SetToolbarItems)(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags) override;
394 
395     // *** IDropTarget methods ***
396     STDMETHOD(DragEnter)(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) override;
397     STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) override;
398     STDMETHOD(DragLeave)() override;
399     STDMETHOD(Drop)(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) override;
400 
401     // *** IServiceProvider methods ***
402     STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void **ppvObject) override;
403 
404     // *** IShellBowserService methods ***
405     STDMETHOD(GetPropertyBag)(long flags, REFIID riid, void **ppvObject) override;
406 
407     // *** IDispatch methods ***
408     STDMETHOD(GetTypeInfoCount)(UINT *pctinfo) override;
409     STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) override;
410     STDMETHOD(GetIDsOfNames)(
411         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) override;
412     STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
413         DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) override;
414 
415     // *** IBrowserService methods ***
416     STDMETHOD(GetParentSite)(IOleInPlaceSite **ppipsite) override;
417     STDMETHOD(SetTitle)(IShellView *psv, LPCWSTR pszName) override;
418     STDMETHOD(GetTitle)(IShellView *psv, LPWSTR pszName, DWORD cchName) override;
419     STDMETHOD(GetOleObject)(IOleObject **ppobjv) override;
420     STDMETHOD(GetTravelLog)(ITravelLog **pptl) override;
421     STDMETHOD(ShowControlWindow)(UINT id, BOOL fShow) override;
422     STDMETHOD(IsControlWindowShown)(UINT id, BOOL *pfShown) override;
423     STDMETHOD(IEGetDisplayName)(LPCITEMIDLIST pidl, LPWSTR pwszName, UINT uFlags) override;
424     STDMETHOD(IEParseDisplayName)(UINT uiCP, LPCWSTR pwszPath, LPITEMIDLIST *ppidlOut) override;
425     STDMETHOD(DisplayParseError)(HRESULT hres, LPCWSTR pwszPath) override;
426     STDMETHOD(NavigateToPidl)(LPCITEMIDLIST pidl, DWORD grfHLNF) override;
427     STDMETHOD(SetNavigateState)(BNSTATE bnstate) override;
428     STDMETHOD(GetNavigateState)(BNSTATE *pbnstate) override;
429     STDMETHOD(NotifyRedirect)(IShellView *psv, LPCITEMIDLIST pidl, BOOL *pfDidBrowse) override;
430     STDMETHOD(UpdateWindowList)() override;
431     STDMETHOD(UpdateBackForwardState)() override;
432     STDMETHOD(SetFlags)(DWORD dwFlags, DWORD dwFlagMask) override;
433     STDMETHOD(GetFlags)(DWORD *pdwFlags) override;
434     STDMETHOD(CanNavigateNow)( void) override;
435     STDMETHOD(GetPidl)(LPITEMIDLIST *ppidl) override;
436     STDMETHOD(SetReferrer)(LPCITEMIDLIST pidl) override;
437     STDMETHOD_(DWORD, GetBrowserIndex)() override;
438     STDMETHOD(GetBrowserByIndex)(DWORD dwID, IUnknown **ppunk) override;
439     STDMETHOD(GetHistoryObject)(IOleObject **ppole, IStream **pstm, IBindCtx **ppbc) override;
440     STDMETHOD(SetHistoryObject)(IOleObject *pole, BOOL fIsLocalAnchor) override;
441     STDMETHOD(CacheOLEServer)(IOleObject *pole) override;
442     STDMETHOD(GetSetCodePage)(VARIANT *pvarIn, VARIANT *pvarOut) override;
443     STDMETHOD(OnHttpEquiv)(IShellView *psv, BOOL fDone, VARIANT *pvarargIn, VARIANT *pvarargOut) override;
444     STDMETHOD(GetPalette)(HPALETTE *hpal) override;
445     STDMETHOD(RegisterWindow)(BOOL fForceRegister, int swc) override;
446 
447     // *** IBrowserService2 methods ***
448     STDMETHOD_(LRESULT, WndProcBS)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
449     STDMETHOD(SetAsDefFolderSettings)() override;
450     STDMETHOD(GetViewRect)(RECT *prc) override;
451     STDMETHOD(OnSize)(WPARAM wParam) override;
452     STDMETHOD(OnCreate)(struct tagCREATESTRUCTW *pcs) override;
453     STDMETHOD_(LRESULT, OnCommand)(WPARAM wParam, LPARAM lParam) override;
454     STDMETHOD(OnDestroy)() override;
455     STDMETHOD_(LRESULT, OnNotify)(struct tagNMHDR *pnm) override;
456     STDMETHOD(OnSetFocus)() override;
457     STDMETHOD(OnFrameWindowActivateBS)(BOOL fActive) override;
458     STDMETHOD(ReleaseShellView)() override;
459     STDMETHOD(ActivatePendingView)() override;
460     STDMETHOD(CreateViewWindow)(IShellView *psvNew, IShellView *psvOld, LPRECT prcView, HWND *phwnd) override;
461     STDMETHOD(CreateBrowserPropSheetExt)(REFIID riid, void **ppv) override;
462     STDMETHOD(GetViewWindow)(HWND *phwndView) override;
463     STDMETHOD(GetBaseBrowserData)(LPCBASEBROWSERDATA *pbbd) override;
464     STDMETHOD_(LPBASEBROWSERDATA, PutBaseBrowserData)(void) override;
465     STDMETHOD(InitializeTravelLog)(ITravelLog *ptl, DWORD dw) override;
466     STDMETHOD(SetTopBrowser)() override;
467     STDMETHOD(Offline)(int iCmd) override;
468     STDMETHOD(AllowViewResize)(BOOL f) override;
469     STDMETHOD(SetActivateState)(UINT u) override;
470     STDMETHOD(UpdateSecureLockIcon)(int eSecureLock) override;
471     STDMETHOD(InitializeDownloadManager)() override;
472     STDMETHOD(InitializeTransitionSite)() override;
473     STDMETHOD(_Initialize)(HWND hwnd, IUnknown *pauto) override;
474     STDMETHOD(_CancelPendingNavigationAsync)( void) override;
475     STDMETHOD(_CancelPendingView)() override;
476     STDMETHOD(_MaySaveChanges)() override;
477     STDMETHOD(_PauseOrResumeView)(BOOL fPaused) override;
478     STDMETHOD(_DisableModeless)() override;
479     STDMETHOD(_NavigateToPidl)(LPCITEMIDLIST pidl, DWORD grfHLNF, DWORD dwFlags) override;
480     STDMETHOD(_TryShell2Rename)(IShellView *psv, LPCITEMIDLIST pidlNew) override;
481     STDMETHOD(_SwitchActivationNow)() override;
482     STDMETHOD(_ExecChildren)(IUnknown *punkBar, BOOL fBroadcast, const GUID *pguidCmdGroup,
483         DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut) override;
484     STDMETHOD(_SendChildren)(
485         HWND hwndBar, BOOL fBroadcast, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
486     STDMETHOD(GetFolderSetData)(struct tagFolderSetData *pfsd) override;
487     STDMETHOD(_OnFocusChange)(UINT itb) override;
488     STDMETHOD(v_ShowHideChildWindows)(BOOL fChildOnly) override;
489     STDMETHOD_(UINT, _get_itbLastFocus)() override;
490     STDMETHOD(_put_itbLastFocus)(UINT itbLastFocus) override;
491     STDMETHOD(_UIActivateView)(UINT uState) override;
492     STDMETHOD(_GetViewBorderRect)(RECT *prc) override;
493     STDMETHOD(_UpdateViewRectSize)() override;
494     STDMETHOD(_ResizeNextBorder)(UINT itb) override;
495     STDMETHOD(_ResizeView)() override;
496     STDMETHOD(_GetEffectiveClientArea)(LPRECT lprectBorder, HMONITOR hmon) override;
497     STDMETHOD_(IStream *, v_GetViewStream)(LPCITEMIDLIST pidl, DWORD grfMode, LPCWSTR pwszName) override;
498     STDMETHOD_(LRESULT, ForwardViewMsg)(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
499     STDMETHOD(SetAcceleratorMenu)(HACCEL hacc) override;
500     STDMETHOD_(int, _GetToolbarCount)() override;
501     STDMETHOD_(LPTOOLBARITEM, _GetToolbarItem)(int itb) override;
502     STDMETHOD(_SaveToolbars)(IStream *pstm) override;
503     STDMETHOD(_LoadToolbars)(IStream *pstm) override;
504     STDMETHOD(_CloseAndReleaseToolbars)(BOOL fClose) override;
505     STDMETHOD(v_MayGetNextToolbarFocus)(LPMSG lpMsg, UINT itbNext,
506         int citb, LPTOOLBARITEM *pptbi, HWND *phwnd) override;
507     STDMETHOD(_ResizeNextBorderHelper)(UINT itb, BOOL bUseHmonitor) override;
508     STDMETHOD_(UINT, _FindTBar)(IUnknown *punkSrc) override;
509     STDMETHOD(_SetFocus)(LPTOOLBARITEM ptbi, HWND hwnd, LPMSG lpMsg) override;
510     STDMETHOD(v_MayTranslateAccelerator)(MSG *pmsg) override;
511     STDMETHOD(_GetBorderDWHelper)(IUnknown *punkSrc, LPRECT lprectBorder, BOOL bUseHmonitor) override;
512     STDMETHOD(v_CheckZoneCrossing)(LPCITEMIDLIST pidl) override;
513 
514     // *** IWebBrowser methods ***
515     STDMETHOD(GoBack)() override;
516     STDMETHOD(GoForward)() override;
517     STDMETHOD(GoHome)() override;
518     STDMETHOD(GoSearch)() override;
519     STDMETHOD(Navigate)(BSTR URL, VARIANT *Flags, VARIANT *TargetFrameName,
520         VARIANT *PostData, VARIANT *Headers) override;
521     STDMETHOD(Refresh)() override;
522     STDMETHOD(Refresh2)(VARIANT *Level) override;
523     STDMETHOD(Stop)() override;
524     STDMETHOD(get_Application)(IDispatch **ppDisp) override;
525     STDMETHOD(get_Parent)(IDispatch **ppDisp) override;
526     STDMETHOD(get_Container)(IDispatch **ppDisp) override;
527     STDMETHOD(get_Document)(IDispatch **ppDisp) override;
528     STDMETHOD(get_TopLevelContainer)(VARIANT_BOOL *pBool) override;
529     STDMETHOD(get_Type)(BSTR *Type) override;
530     STDMETHOD(get_Left)(long *pl) override;
531     STDMETHOD(put_Left)(long Left) override;
532     STDMETHOD(get_Top)(long *pl) override;
533     STDMETHOD(put_Top)(long Top) override;
534     STDMETHOD(get_Width)(long *pl) override;
535     STDMETHOD(put_Width)(long Width) override;
536     STDMETHOD(get_Height)(long *pl) override;
537     STDMETHOD(put_Height)(long Height) override;
538     STDMETHOD(get_LocationName)(BSTR *LocationName) override;
539     STDMETHOD(get_LocationURL)(BSTR *LocationURL) override;
540     STDMETHOD(get_Busy)(VARIANT_BOOL *pBool) override;
541 
542     // *** IWebBrowserApp methods ***
543     STDMETHOD(Quit)() override;
544     STDMETHOD(ClientToWindow)(int *pcx, int *pcy) override;
545     STDMETHOD(PutProperty)(BSTR Property, VARIANT vtValue) override;
546     STDMETHOD(GetProperty)(BSTR Property, VARIANT *pvtValue) override;
547     STDMETHOD(get_Name)(BSTR *Name) override;
548     STDMETHOD(get_HWND)(SHANDLE_PTR *pHWND) override;
549     STDMETHOD(get_FullName)(BSTR *FullName) override;
550     STDMETHOD(get_Path)(BSTR *Path) override;
551     STDMETHOD(get_Visible)(VARIANT_BOOL *pBool) override;
552     STDMETHOD(put_Visible)(VARIANT_BOOL Value) override;
553     STDMETHOD(get_StatusBar)(VARIANT_BOOL *pBool) override;
554     STDMETHOD(put_StatusBar)(VARIANT_BOOL Value) override;
555     STDMETHOD(get_StatusText)(BSTR *StatusText) override;
556     STDMETHOD(put_StatusText)(BSTR StatusText) override;
557     STDMETHOD(get_ToolBar)(int *Value) override;
558     STDMETHOD(put_ToolBar)(int Value) override;
559     STDMETHOD(get_MenuBar)(VARIANT_BOOL *Value) override;
560     STDMETHOD(put_MenuBar)(VARIANT_BOOL Value) override;
561     STDMETHOD(get_FullScreen)(VARIANT_BOOL *pbFullScreen) override;
562     STDMETHOD(put_FullScreen)(VARIANT_BOOL bFullScreen) override;
563 
564     // *** IWebBrowser2 methods ***
565     STDMETHOD(Navigate2)(VARIANT *URL, VARIANT *Flags, VARIANT *TargetFrameName,
566         VARIANT *PostData, VARIANT *Headers) override;
567     STDMETHOD(QueryStatusWB)(OLECMDID cmdID, OLECMDF *pcmdf) override;
568     STDMETHOD(ExecWB)(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt,
569         VARIANT *pvaIn, VARIANT *pvaOut) override;
570     STDMETHOD(ShowBrowserBar)(VARIANT *pvaClsid, VARIANT *pvarShow, VARIANT *pvarSize) override;
571     STDMETHOD(get_ReadyState)(READYSTATE *plReadyState) override;
572     STDMETHOD(get_Offline)(VARIANT_BOOL *pbOffline) override;
573     STDMETHOD(put_Offline)(VARIANT_BOOL bOffline) override;
574     STDMETHOD(get_Silent)(VARIANT_BOOL *pbSilent) override;
575     STDMETHOD(put_Silent)(VARIANT_BOOL bSilent) override;
576     STDMETHOD(get_RegisterAsBrowser)(VARIANT_BOOL *pbRegister) override;
577     STDMETHOD(put_RegisterAsBrowser)(VARIANT_BOOL bRegister) override;
578     STDMETHOD(get_RegisterAsDropTarget)(VARIANT_BOOL *pbRegister) override;
579     STDMETHOD(put_RegisterAsDropTarget)(VARIANT_BOOL bRegister) override;
580     STDMETHOD(get_TheaterMode)(VARIANT_BOOL *pbRegister) override;
581     STDMETHOD(put_TheaterMode)(VARIANT_BOOL bRegister) override;
582     STDMETHOD(get_AddressBar)(VARIANT_BOOL *Value) override;
583     STDMETHOD(put_AddressBar)(VARIANT_BOOL Value) override;
584     STDMETHOD(get_Resizable)(VARIANT_BOOL *Value) override;
585     STDMETHOD(put_Resizable)(VARIANT_BOOL Value) override;
586 
587     // *** ITravelLogClient methods ***
588     STDMETHOD(FindWindowByIndex)(DWORD dwID, IUnknown **ppunk) override;
589     STDMETHOD(GetWindowData)(IStream *pStream, LPWINDOWDATA pWinData) override;
590     STDMETHOD(LoadHistoryPosition)(LPWSTR pszUrlLocation, DWORD dwPosition) override;
591 
592     // *** IPersist methods ***
593     STDMETHOD(GetClassID)(CLSID *pClassID) override;
594 
595     // *** IPersistHistory methods ***
596     STDMETHOD(LoadHistory)(IStream *pStream, IBindCtx *pbc) override;
597     STDMETHOD(SaveHistory)(IStream *pStream) override;
598     STDMETHOD(SetPositionCookie)(DWORD dwPositioncookie) override;
599     STDMETHOD(GetPositionCookie)(DWORD *pdwPositioncookie) override;
600 
601     // message handlers
602     LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
603     LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
604     LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
605     LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
606     LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
607     LRESULT RelayMsgToShellView(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
608     LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
609     LRESULT OnClose(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
610     LRESULT OnFolderOptions(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
611     LRESULT OnMapNetworkDrive(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
612     LRESULT OnDisconnectNetworkDrive(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
613     LRESULT OnAboutReactOS(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
614     LRESULT OnGoBack(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
615     LRESULT OnGoForward(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
616     LRESULT OnGoUpLevel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
617     LRESULT OnBackspace(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
618     LRESULT OnGoHome(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
619     LRESULT OnAddToFavorites(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
620     LRESULT OnOrganizeFavorites(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
621     LRESULT OnToggleStatusBarVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
622     LRESULT OnToggleToolbarLock(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
623     LRESULT OnToggleToolbarBandVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
624     LRESULT OnToggleAddressBandVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
625     LRESULT OnToggleLinksBandVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
626     LRESULT OnToggleTextLabels(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
627     LRESULT OnToolbarCustomize(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
628     LRESULT OnGoTravel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
629     LRESULT OnRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
630     LRESULT OnExplorerBar(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
631     LRESULT RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
632     LRESULT OnSettingsChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
633     LRESULT OnGetSettingsPtr(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
634     LRESULT OnAppCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
635     HRESULT OnSearch();
636 
637     static ATL::CWndClassInfo& GetWndClassInfo()
638     {
639         static ATL::CWndClassInfo wc =
640         {
641             { sizeof(WNDCLASSEX), CS_DBLCLKS, StartWindowProc,
642               0, 0, NULL, LoadIcon(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDI_CABINET)),
643               LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, szCabinetWndClass, NULL },
644             NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
645         };
646         return wc;
647     }
648 
649     BEGIN_MSG_MAP(CShellBrowser)
650         MESSAGE_HANDLER(WM_CREATE, OnCreate)
651         MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
652         MESSAGE_HANDLER(WM_SIZE, OnSize)
653         MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
654         MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
655         MESSAGE_HANDLER(WM_MEASUREITEM, RelayMsgToShellView)
656         MESSAGE_HANDLER(WM_DRAWITEM, RelayMsgToShellView)
657         MESSAGE_HANDLER(WM_MENUSELECT, RelayMsgToShellView)
658         MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
659         COMMAND_ID_HANDLER(IDM_FILE_CLOSE, OnClose)
660         COMMAND_ID_HANDLER(IDM_TOOLS_FOLDEROPTIONS, OnFolderOptions)
661         COMMAND_ID_HANDLER(IDM_TOOLS_MAPNETWORKDRIVE, OnMapNetworkDrive)
662         COMMAND_ID_HANDLER(IDM_TOOLS_DISCONNECTNETWORKDRIVE, OnDisconnectNetworkDrive)
663         COMMAND_ID_HANDLER(IDM_HELP_ABOUT, OnAboutReactOS)
664         COMMAND_ID_HANDLER(IDM_GOTO_BACK, OnGoBack)
665         COMMAND_ID_HANDLER(IDM_GOTO_FORWARD, OnGoForward)
666         COMMAND_ID_HANDLER(IDM_GOTO_UPONELEVEL, OnGoUpLevel)
667         COMMAND_ID_HANDLER(IDM_GOTO_HOMEPAGE, OnGoHome)
668         COMMAND_ID_HANDLER(IDM_FAVORITES_ADDTOFAVORITES, OnAddToFavorites)
669         COMMAND_ID_HANDLER(IDM_FAVORITES_ORGANIZEFAVORITES, OnOrganizeFavorites)
670         COMMAND_ID_HANDLER(IDM_VIEW_STATUSBAR, OnToggleStatusBarVisible)
671         COMMAND_ID_HANDLER(IDM_VIEW_REFRESH, OnRefresh)
672         COMMAND_ID_HANDLER(IDM_TOOLBARS_LOCKTOOLBARS, OnToggleToolbarLock)
673         COMMAND_ID_HANDLER(IDM_TOOLBARS_STANDARDBUTTONS, OnToggleToolbarBandVisible)
674         COMMAND_ID_HANDLER(IDM_TOOLBARS_ADDRESSBAR, OnToggleAddressBandVisible)
675         COMMAND_ID_HANDLER(IDM_TOOLBARS_LINKSBAR, OnToggleLinksBandVisible)
676         COMMAND_ID_HANDLER(IDM_TOOLBARS_TEXTLABELS, OnToggleTextLabels)
677         COMMAND_ID_HANDLER(IDM_TOOLBARS_CUSTOMIZE, OnToolbarCustomize)
678         COMMAND_ID_HANDLER(IDM_EXPLORERBAR_SEARCH, OnExplorerBar)
679         COMMAND_ID_HANDLER(IDM_EXPLORERBAR_FOLDERS, OnExplorerBar)
680         COMMAND_ID_HANDLER(IDM_EXPLORERBAR_HISTORY, OnExplorerBar)
681         COMMAND_ID_HANDLER(IDM_EXPLORERBAR_FAVORITES, OnExplorerBar)
682         COMMAND_ID_HANDLER(IDM_BACKSPACE, OnBackspace)
683         COMMAND_RANGE_HANDLER(IDM_GOTO_TRAVEL_FIRSTTARGET, IDM_GOTO_TRAVEL_LASTTARGET, OnGoTravel)
684         COMMAND_RANGE_HANDLER(IDM_EXPLORERBAND_BEGINCUSTOM, IDM_EXPLORERBAND_ENDCUSTOM, OnExplorerBar)
685         MESSAGE_HANDLER(WM_COMMAND, RelayCommands)
686         MESSAGE_HANDLER(BWM_SETTINGCHANGE, OnSettingsChange)
687         MESSAGE_HANDLER(BWM_GETSETTINGSPTR, OnGetSettingsPtr)
688         MESSAGE_HANDLER(WM_APPCOMMAND, OnAppCommand)
689     END_MSG_MAP()
690 
691     BEGIN_CONNECTION_POINT_MAP(CShellBrowser)
692         CONNECTION_POINT_ENTRY(DIID_DWebBrowserEvents2)
693         CONNECTION_POINT_ENTRY(DIID_DWebBrowserEvents)
694     END_CONNECTION_POINT_MAP()
695 
696     BEGIN_COM_MAP(CShellBrowser)
697         COM_INTERFACE_ENTRY_IID(IID_IDockingWindowSite, IDockingWindowSite)
698         COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
699         COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDockingWindowSite)
700         COM_INTERFACE_ENTRY_IID(IID_IShellBrowser, IShellBrowser)
701         COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
702         COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
703         COM_INTERFACE_ENTRY_IID(IID_IProfferService, IProfferService)
704         COM_INTERFACE_ENTRY_IID(IID_IShellBrowserService, IShellBrowserService)
705         COM_INTERFACE_ENTRY_IID(IID_IDispatch, IDispatch)
706         COM_INTERFACE_ENTRY_IID(IID_IConnectionPointContainer, IConnectionPointContainer)
707         COM_INTERFACE_ENTRY_IID(IID_IWebBrowser, IWebBrowser)
708         COM_INTERFACE_ENTRY_IID(IID_IWebBrowserApp, IWebBrowserApp)
709         COM_INTERFACE_ENTRY_IID(IID_IWebBrowser2, IWebBrowser2)
710         COM_INTERFACE_ENTRY_IID(IID_ITravelLogClient, ITravelLogClient)
711         COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
712         COM_INTERFACE_ENTRY_IID(IID_IPersistHistory, IPersistHistory)
713         COM_INTERFACE_ENTRY_IID(IID_IBrowserService, IBrowserService)
714         COM_INTERFACE_ENTRY_IID(IID_IBrowserService2, IBrowserService2)
715     END_COM_MAP()
716 };
717 
718 extern HRESULT CreateProgressDialog(REFIID riid, void **ppv);
719 
720 CShellBrowser::CShellBrowser()
721 {
722     fCurrentShellViewWindow = NULL;
723     fCurrentDirectoryPIDL = NULL;
724     fStatusBar = NULL;
725     fCurrentMenuBar = NULL;
726     fHistoryObject = NULL;
727     fHistoryStream = NULL;
728     fHistoryBindContext = NULL;
729     m_settings.Load();
730     m_deffoldersettings.Load();
731     gCabinetState.Load();
732 }
733 
734 CShellBrowser::~CShellBrowser()
735 {
736     if (menuDsa)
737         DSA_Destroy(menuDsa);
738 }
739 
740 HRESULT CShellBrowser::Initialize()
741 {
742     CComPtr<IPersistStreamInit>             persistStreamInit;
743     HRESULT                                 hResult;
744     CComPtr<IUnknown> clientBar;
745 
746     _AtlInitialConstruct();
747 
748     menuDsa = DSA_Create(sizeof(MenuBandInfo), 5);
749     if (!menuDsa)
750         return E_OUTOFMEMORY;
751 
752     // create window
753     Create(HWND_DESKTOP);
754     if (m_hWnd == NULL)
755         return E_FAIL;
756 
757     hResult = CInternetToolbar_CreateInstance(IID_PPV_ARG(IUnknown, &clientBar));
758     if (FAILED_UNEXPECTEDLY(hResult))
759         return hResult;
760 
761     fClientBars[BIInternetToolbar].clientBar = clientBar;
762 
763     // create interfaces
764     hResult = clientBar->QueryInterface(IID_PPV_ARG(IPersistStreamInit, &persistStreamInit));
765     if (FAILED_UNEXPECTEDLY(hResult))
766         return hResult;
767 
768     hResult = IUnknown_SetSite(clientBar, static_cast<IShellBrowser *>(this));
769     if (FAILED_UNEXPECTEDLY(hResult))
770         return hResult;
771 
772     hResult = IUnknown_Exec(clientBar, CGID_PrivCITCommands, 1, 1 /* or 0 */, NULL, NULL);
773     if (FAILED_UNEXPECTEDLY(hResult))
774         return hResult;
775 
776     CComPtr<IStream> pITBarStream;
777     hResult = CInternetToolbar::GetStream(ITBARSTREAM_EXPLORER, STGM_READ, &pITBarStream);
778     hResult = SUCCEEDED(hResult) ? persistStreamInit->Load(pITBarStream) : persistStreamInit->InitNew();
779     if (FAILED_UNEXPECTEDLY(hResult))
780         return hResult;
781 
782     hResult = IUnknown_ShowDW(clientBar, TRUE);
783     if (FAILED_UNEXPECTEDLY(hResult))
784         return hResult;
785 
786     fToolbarProxy.Initialize(m_hWnd, clientBar);
787 
788     // create status bar
789     DWORD dwStatusStyle = WS_CHILD | WS_CLIPSIBLINGS | SBARS_SIZEGRIP | SBARS_TOOLTIPS;
790     if (m_settings.fStatusBarVisible)
791         dwStatusStyle |= WS_VISIBLE;
792     fStatusBar = ::CreateWindowExW(0, STATUSCLASSNAMEW, NULL, dwStatusStyle,
793                                    0, 0, 500, 20, m_hWnd, (HMENU)IDC_STATUSBAR,
794                                    _AtlBaseModule.GetModuleInstance(), 0);
795 
796     ShowWindow(SW_SHOWNORMAL);
797     UpdateWindow();
798 
799     return S_OK;
800 }
801 
802 HRESULT CShellBrowser::ApplyBrowserDefaultFolderSettings(IShellView *pvs)
803 {
804     HRESULT hr;
805     if (pvs)
806     {
807         m_settings.Save();
808         SBFOLDERSETTINGS &sbfs = m_deffoldersettings, defsbfs;
809         if (FAILED(pvs->GetCurrentInfo(&sbfs.FolderSettings)))
810         {
811             defsbfs.InitializeDefaults();
812             sbfs = defsbfs;
813         }
814         hr = CGlobalFolderSettings::SaveBrowserSettings(sbfs);
815     }
816     else
817     {
818         m_settings.Reset();
819         hr = CGlobalFolderSettings::ResetBrowserSettings();
820     }
821     return hr;
822 }
823 
824 HRESULT CShellBrowser::BrowseToPIDL(LPCITEMIDLIST pidl, long flags)
825 {
826     CComPtr<IShellFolder>   newFolder;
827     FOLDERSETTINGS          newFolderSettings = m_deffoldersettings.FolderSettings;
828     HRESULT                 hResult;
829     CLSID                   clsid;
830     BOOL                    HasIconViewType;
831 
832     // called by shell view to browse to new folder
833     // also called by explorer band to navigate to new folder
834     hResult = SHBindToFolder(pidl, &newFolder);
835     if (FAILED_UNEXPECTEDLY(hResult))
836         return hResult;
837     // HACK & FIXME: Get view mode from shellbag when fully implemented.
838     IUnknown_GetClassID(newFolder, &clsid);
839     HasIconViewType = clsid == CLSID_MyComputer || clsid == CLSID_ControlPanel ||
840                       clsid == CLSID_ShellDesktop;
841 
842     if (HasIconViewType)
843         newFolderSettings.ViewMode = FVM_ICON;
844     hResult = BrowseToPath(newFolder, pidl, &newFolderSettings, flags);
845     if (FAILED_UNEXPECTEDLY(hResult))
846         return hResult;
847     return S_OK;
848 }
849 
850 BOOL WINAPI _ILIsPidlSimple(LPCITEMIDLIST pidl)
851 {
852     LPCITEMIDLIST                           pidlnext;
853     WORD                                    length;
854     BOOL                                    ret;
855 
856     ret = TRUE;
857     if (! _ILIsDesktop(pidl))
858     {
859         length = pidl->mkid.cb;
860         pidlnext =
861             reinterpret_cast<LPCITEMIDLIST>(
862                 reinterpret_cast<const BYTE *>(pidl) + length);
863         if (pidlnext->mkid.cb != 0)
864             ret = FALSE;
865     }
866     return ret;
867 }
868 
869 HRESULT WINAPI SHBindToFolderIDListParent(IShellFolder *unused, LPCITEMIDLIST pidl,
870     const IID *riid, LPVOID *ppv, LPITEMIDLIST *ppidlLast)
871 {
872     CComPtr<IShellFolder>                   psf;
873     LPITEMIDLIST                            pidlChild;
874     LPITEMIDLIST                            pidlParent;
875     HRESULT                                 hResult;
876 
877     hResult = E_FAIL;
878     if (ppv == NULL)
879         return E_POINTER;
880     *ppv = NULL;
881     if (ppidlLast != NULL)
882         *ppidlLast = NULL;
883     if (_ILIsPidlSimple(pidl))
884     {
885         if (ppidlLast != NULL)
886             *ppidlLast = ILClone(pidl);
887         hResult = SHGetDesktopFolder((IShellFolder **)ppv);
888     }
889     else
890     {
891         pidlChild = ILClone(ILFindLastID(pidl));
892         pidlParent = ILClone(pidl);
893         ILRemoveLastID(pidlParent);
894         hResult = SHGetDesktopFolder(&psf);
895         if (SUCCEEDED(hResult))
896             hResult = psf->BindToObject(pidlParent, NULL, *riid, ppv);
897         if (SUCCEEDED(hResult) && ppidlLast != NULL)
898             *ppidlLast = pidlChild;
899         else
900             ILFree(pidlChild);
901         ILFree(pidlParent);
902     }
903     return hResult;
904 }
905 
906 HRESULT IEGetNameAndFlagsEx(LPITEMIDLIST pidl, SHGDNF uFlags, long param10,
907     LPWSTR pszBuf, UINT cchBuf, SFGAOF *rgfInOut)
908 {
909     CComPtr<IShellFolder>                   parentFolder;
910     LPITEMIDLIST                            childPIDL = NULL;
911     STRRET                                  L108;
912     HRESULT                                 hResult;
913 
914     hResult = SHBindToFolderIDListParent(NULL, pidl, &IID_PPV_ARG(IShellFolder, &parentFolder), &childPIDL);
915     if (FAILED(hResult))
916         goto cleanup;
917 
918     hResult = parentFolder->GetDisplayNameOf(childPIDL, uFlags, &L108);
919     if (FAILED(hResult))
920         goto cleanup;
921 
922     StrRetToBufW(&L108, childPIDL, pszBuf, cchBuf);
923     if (rgfInOut)
924     {
925         hResult = parentFolder->GetAttributesOf(1, const_cast<LPCITEMIDLIST *>(&childPIDL), rgfInOut);
926         if (FAILED(hResult))
927             goto cleanup;
928     }
929 
930     hResult = S_OK;
931 
932 cleanup:
933     if (childPIDL)
934         ILFree(childPIDL);
935     return hResult;
936 }
937 
938 HRESULT IEGetNameAndFlags(LPITEMIDLIST pidl, SHGDNF uFlags, LPWSTR pszBuf, UINT cchBuf, SFGAOF *rgfInOut)
939 {
940     return IEGetNameAndFlagsEx(pidl, uFlags, 0, pszBuf, cchBuf, rgfInOut);
941 }
942 
943 HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
944     LPCITEMIDLIST absolutePIDL, FOLDERSETTINGS *folderSettings, long flags)
945 {
946     CComPtr<IShellFolder>                   saveCurrentShellFolder;
947     CComPtr<IShellView>                     saveCurrentShellView;
948     CComPtr<IShellView>                     newShellView;
949     CComPtr<ITravelLog>                     travelLog;
950     HWND                                    newShellViewWindow;
951     BOOL                                    windowUpdateIsLocked;
952     RECT                                    shellViewWindowBounds;
953     HWND                                    previousView;
954     HCURSOR                                 saveCursor;
955     wchar_t                                 newTitle[MAX_PATH];
956     SHGDNF                                  nameFlags;
957     HRESULT                                 hResult;
958 
959     if (newShellFolder == NULL)
960         return E_INVALIDARG;
961 
962     hResult = GetTravelLog(&travelLog);
963     if (FAILED_UNEXPECTEDLY(hResult))
964         return hResult;
965 
966     // update history
967     if (flags & BTP_UPDATE_CUR_HISTORY)
968     {
969         if (travelLog->CountEntries(static_cast<IDropTarget *>(this)) > 0)
970             hResult = travelLog->UpdateEntry(static_cast<IDropTarget *>(this), FALSE);
971         // what to do with error? Do we want to halt browse because state save failed?
972     }
973 
974     if (fCurrentShellView)
975     {
976         fCurrentShellView->UIActivate(SVUIA_DEACTIVATE);
977     }
978 
979     // create view object
980     hResult = newShellFolder->CreateViewObject(m_hWnd, IID_PPV_ARG(IShellView, &newShellView));
981     if (FAILED_UNEXPECTEDLY(hResult))
982         return hResult;
983     previousView = fCurrentShellViewWindow;
984 
985     // enter updating section
986     saveCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
987     windowUpdateIsLocked = LockWindowUpdate(TRUE);
988     if (fCurrentShellView != NULL)
989         ::SendMessage(fCurrentShellViewWindow, WM_SETREDRAW, 0, 0);
990 
991     // set site
992     hResult = IUnknown_SetSite(newShellView, static_cast<IDropTarget *>(this));
993 
994     // update folder and view
995     saveCurrentShellFolder = fCurrentShellFolder;
996     saveCurrentShellView = fCurrentShellView;
997     fCurrentShellFolder = newShellFolder;
998     fCurrentShellView = newShellView;
999 
1000     // get boundary
1001     if (previousView != NULL)
1002         ::GetWindowRect(previousView, &shellViewWindowBounds);
1003     else
1004         ZeroMemory(&shellViewWindowBounds, sizeof(shellViewWindowBounds));
1005     ::MapWindowPoints(0, m_hWnd, reinterpret_cast<POINT *>(&shellViewWindowBounds), 2);
1006 
1007     // update current pidl
1008     ILFree(fCurrentDirectoryPIDL);
1009     fCurrentDirectoryPIDL = ILClone(absolutePIDL);
1010 
1011     // create view window
1012     hResult = newShellView->CreateViewWindow(saveCurrentShellView, folderSettings,
1013         this, &shellViewWindowBounds, &newShellViewWindow);
1014     if (FAILED_UNEXPECTEDLY(hResult) || newShellViewWindow == NULL)
1015     {
1016         fCurrentShellView = saveCurrentShellView;
1017         fCurrentShellFolder = saveCurrentShellFolder;
1018         ::SendMessage(fCurrentShellViewWindow, WM_SETREDRAW, 1, 0);
1019         if (windowUpdateIsLocked)
1020             LockWindowUpdate(FALSE);
1021         SetCursor(saveCursor);
1022         return hResult;
1023     }
1024 
1025     // update view window
1026     if (saveCurrentShellView != NULL)
1027         saveCurrentShellView->DestroyViewWindow();
1028     fCurrentShellViewWindow = newShellViewWindow;
1029 
1030     if (previousView == NULL)
1031     {
1032         RepositionBars();
1033     }
1034 
1035     // no use
1036     saveCurrentShellView.Release();
1037     saveCurrentShellFolder.Release();
1038 
1039     hResult = newShellView->UIActivate(SVUIA_ACTIVATE_FOCUS);
1040 
1041     // leave updating section
1042     if (windowUpdateIsLocked)
1043         LockWindowUpdate(FALSE);
1044     SetCursor(saveCursor);
1045 
1046     // update history
1047     if (flags & BTP_UPDATE_NEXT_HISTORY)
1048     {
1049         hResult = travelLog->AddEntry(static_cast<IDropTarget *>(this), FALSE);
1050         hResult = travelLog->UpdateEntry(static_cast<IDropTarget *>(this), FALSE);
1051     }
1052 
1053     // completed
1054     nameFlags = SHGDN_FORADDRESSBAR | SHGDN_FORPARSING;
1055     hResult = IEGetNameAndFlags(fCurrentDirectoryPIDL, nameFlags, newTitle,
1056         sizeof(newTitle) / sizeof(wchar_t), NULL);
1057     if (SUCCEEDED(hResult))
1058     {
1059         FireNavigateComplete(newTitle);
1060     }
1061     else
1062     {
1063         FireNavigateComplete(L"ERROR");
1064     }
1065 
1066     UpdateWindowTitle();
1067 
1068     LPCITEMIDLIST pidlChild;
1069     INT index, indexOpen;
1070     HIMAGELIST himlSmall, himlLarge;
1071 
1072     CComPtr<IShellFolder> sf;
1073     hResult = SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
1074     if (SUCCEEDED(hResult))
1075     {
1076         index = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen);
1077 
1078         Shell_GetImageLists(&himlLarge, &himlSmall);
1079 
1080         HICON icSmall = ImageList_GetIcon(himlSmall, indexOpen, 0);
1081         HICON icLarge = ImageList_GetIcon(himlLarge, indexOpen, 0);
1082 
1083         /* Hack to make it possible to release the old icons */
1084         /* Something seems to go wrong with WM_SETICON */
1085         HICON oldSmall = (HICON)SendMessage(WM_GETICON, ICON_SMALL, 0);
1086         HICON oldLarge = (HICON)SendMessage(WM_GETICON, ICON_BIG,   0);
1087 
1088         SendMessage(WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icSmall));
1089         SendMessage(WM_SETICON, ICON_BIG,   reinterpret_cast<LPARAM>(icLarge));
1090 
1091         DestroyIcon(oldSmall);
1092         DestroyIcon(oldLarge);
1093     }
1094 
1095     FireCommandStateChangeAll();
1096     hResult = UpdateForwardBackState();
1097     hResult = UpdateUpState();
1098     return S_OK;
1099 }
1100 
1101 HRESULT CShellBrowser::GetMenuBand(REFIID riid, void **shellMenu)
1102 {
1103     CComPtr<IBandSite>                      bandSite;
1104     CComPtr<IDeskBand>                      deskBand;
1105     HRESULT                                 hResult;
1106 
1107     if (!fClientBars[BIInternetToolbar].clientBar)
1108         return E_FAIL;
1109 
1110     hResult = IUnknown_QueryService(fClientBars[BIInternetToolbar].clientBar, SID_IBandSite, IID_PPV_ARG(IBandSite, &bandSite));
1111     if (FAILED_UNEXPECTEDLY(hResult))
1112         return hResult;
1113 
1114     hResult = bandSite->QueryBand(1, &deskBand, NULL, NULL, 0);
1115     if (FAILED_UNEXPECTEDLY(hResult))
1116         return hResult;
1117 
1118     return deskBand->QueryInterface(riid, shellMenu);
1119 }
1120 
1121 HRESULT CShellBrowser::GetBaseBar(bool vertical, REFIID riid, void **theBaseBar)
1122 {
1123     CComPtr<IUnknown>                       newBaseBar;
1124     CComPtr<IDeskBar>                       deskBar;
1125     CComPtr<IUnknown>                       newBaseBarSite;
1126     CComPtr<IDeskBarClient>                 deskBarClient;
1127     IUnknown                                **cache;
1128     HRESULT                                 hResult;
1129 
1130     if (vertical)
1131         cache = &fClientBars[BIVerticalBaseBar].clientBar.p;
1132     else
1133         cache = &fClientBars[BIHorizontalBaseBar].clientBar.p;
1134     if (*cache == NULL)
1135     {
1136         hResult = CBaseBar_CreateInstance(IID_PPV_ARG(IUnknown, &newBaseBar), vertical);
1137         if (FAILED_UNEXPECTEDLY(hResult))
1138             return hResult;
1139         hResult = CBaseBarSite_CreateInstance(IID_PPV_ARG(IUnknown, &newBaseBarSite), vertical);
1140         if (FAILED_UNEXPECTEDLY(hResult))
1141             return hResult;
1142 
1143         // we have to store our basebar into cache now
1144         *cache = newBaseBar;
1145         (*cache)->AddRef();
1146 
1147         // tell the new base bar about the shell browser
1148         hResult = IUnknown_SetSite(newBaseBar, static_cast<IDropTarget *>(this));
1149         if (FAILED_UNEXPECTEDLY(hResult))
1150             return hResult;
1151 
1152         // tell the new base bar about the new base bar site
1153         hResult = newBaseBar->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
1154         if (FAILED_UNEXPECTEDLY(hResult))
1155             return hResult;
1156         hResult = deskBar->SetClient(newBaseBarSite);
1157         if (FAILED_UNEXPECTEDLY(hResult))
1158             return hResult;
1159 
1160         // tell the new base bar site about the new base bar
1161         hResult = newBaseBarSite->QueryInterface(IID_PPV_ARG(IDeskBarClient, &deskBarClient));
1162         if (FAILED_UNEXPECTEDLY(hResult))
1163             return hResult;
1164         hResult = deskBarClient->SetDeskBarSite(newBaseBar);
1165         if (FAILED_UNEXPECTEDLY(hResult))
1166             return hResult;
1167 
1168     }
1169     return (*cache)->QueryInterface(riid, theBaseBar);
1170 }
1171 
1172 BOOL CShellBrowser::IsBandLoaded(const CLSID clsidBand, bool vertical, DWORD *pdwBandID)
1173 {
1174     HRESULT                                 hResult;
1175     CComPtr<IDeskBar>                       deskBar;
1176     CComPtr<IUnknown>                       baseBarSite;
1177     CComPtr<IBandSite>                      bandSite;
1178     CLSID                                   clsidTmp;
1179     DWORD                                   numBands;
1180     DWORD                                   dwBandID;
1181     DWORD                                   i;
1182 
1183     /* Get our basebarsite to be able to enumerate bands */
1184     hResult = GetBaseBar(vertical, IID_PPV_ARG(IDeskBar, &deskBar));
1185     if (FAILED_UNEXPECTEDLY(hResult))
1186         return FALSE;
1187     hResult = deskBar->GetClient(&baseBarSite);
1188     if (FAILED_UNEXPECTEDLY(hResult))
1189         return FALSE;
1190     hResult = baseBarSite->QueryInterface(IID_PPV_ARG(IBandSite, &bandSite));
1191     if (FAILED_UNEXPECTEDLY(hResult))
1192         return FALSE;
1193 
1194     hResult = bandSite->EnumBands(-1, &numBands);
1195     if (FAILED_UNEXPECTEDLY(hResult))
1196         return FALSE;
1197 
1198     for(i = 0; i < numBands; i++)
1199     {
1200         CComPtr<IPersist> bandPersist;
1201 
1202         hResult = bandSite->EnumBands(i, &dwBandID);
1203         if (FAILED_UNEXPECTEDLY(hResult))
1204             return FALSE;
1205 
1206         hResult = bandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist, &bandPersist));
1207         if (FAILED_UNEXPECTEDLY(hResult))
1208             return FALSE;
1209         hResult = bandPersist->GetClassID(&clsidTmp);
1210         if (FAILED_UNEXPECTEDLY(hResult))
1211             return FALSE;
1212         if (IsEqualGUID(clsidBand, clsidTmp))
1213         {
1214             if (pdwBandID) *pdwBandID = dwBandID;
1215             return TRUE;
1216         }
1217     }
1218     return FALSE;
1219 }
1220 
1221 HRESULT CShellBrowser::ShowBand(const CLSID &classID, bool vertical)
1222 {
1223     CComPtr<IDockingWindow>                 dockingWindow;
1224     CComPtr<IUnknown>                       baseBarSite;
1225     CComPtr<IUnknown>                       newBand;
1226     CComPtr<IDeskBar>                       deskBar;
1227     VARIANT                                 vaIn;
1228     HRESULT                                 hResult;
1229     DWORD                                   dwBandID;
1230 
1231     hResult = GetBaseBar(vertical, IID_PPV_ARG(IDeskBar, &deskBar));
1232     if (FAILED_UNEXPECTEDLY(hResult))
1233         return hResult;
1234 
1235     hResult = deskBar->GetClient(&baseBarSite);
1236     if (FAILED_UNEXPECTEDLY(hResult))
1237         return hResult;
1238 
1239     hResult = deskBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
1240     if (FAILED_UNEXPECTEDLY(hResult))
1241         return hResult;
1242 
1243     if (!IsBandLoaded(classID, vertical, &dwBandID))
1244     {
1245         TRACE("ShowBand called for CLSID %s, vertical=%d...\n", wine_dbgstr_guid(&classID), vertical);
1246         if (IsEqualCLSID(CLSID_ExplorerBand, classID))
1247         {
1248             TRACE("CLSID_ExplorerBand requested, building internal band.\n");
1249             hResult = CExplorerBand_CreateInstance(IID_PPV_ARG(IUnknown, &newBand));
1250             if (FAILED_UNEXPECTEDLY(hResult))
1251                 return hResult;
1252         }
1253         else if (IsEqualCLSID(classID, CLSID_FileSearchBand))
1254         {
1255             TRACE("CLSID_FileSearchBand requested, building internal band.\n");
1256             hResult = CSearchBar_CreateInstance(IID_PPV_ARG(IUnknown, &newBand));
1257             if (FAILED_UNEXPECTEDLY(hResult))
1258                 return hResult;
1259         }
1260         else
1261         {
1262             TRACE("A different CLSID requested, using CoCreateInstance.\n");
1263             hResult = CoCreateInstance(classID, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &newBand));
1264             if (FAILED_UNEXPECTEDLY(hResult))
1265                 return hResult;
1266         }
1267     }
1268     else
1269     {
1270         CComPtr<IBandSite>                  pBandSite;
1271 
1272         hResult = baseBarSite->QueryInterface(IID_PPV_ARG(IBandSite, &pBandSite));
1273         if (!SUCCEEDED(hResult))
1274         {
1275             ERR("Can't get IBandSite interface\n");
1276             return E_FAIL;
1277         }
1278         hResult = pBandSite->GetBandObject(dwBandID, IID_PPV_ARG(IUnknown, &newBand));
1279         if (!SUCCEEDED(hResult))
1280         {
1281             ERR("Can't find band object\n");
1282             return E_FAIL;
1283         }
1284 
1285         // It's hackish, but we should be able to show the wanted band until we
1286         // find the proper way to do this (but it seems to work to add a new band)
1287         // Here we'll just re-add the existing band to the site, causing it to display.
1288     }
1289     V_VT(&vaIn) = VT_UNKNOWN;
1290     V_UNKNOWN(&vaIn) = newBand.p;
1291     hResult = IUnknown_Exec(baseBarSite, CGID_IDeskBand, 1, 1, &vaIn, NULL);
1292     if (FAILED_UNEXPECTEDLY(hResult))
1293     {
1294         return hResult;
1295     }
1296 
1297     hResult = dockingWindow->ShowDW(TRUE);
1298     if (FAILED_UNEXPECTEDLY(hResult))
1299         return hResult;
1300 
1301     if (vertical)
1302     {
1303         fCurrentVertBar = classID;
1304         FireCommandStateChangeAll();
1305     }
1306 
1307     return S_OK;
1308 }
1309 
1310 HRESULT CShellBrowser::NavigateToParent()
1311 {
1312     LPITEMIDLIST newDirectory = ILClone(fCurrentDirectoryPIDL);
1313     if (newDirectory == NULL)
1314         return E_OUTOFMEMORY;
1315     if (_ILIsDesktop(newDirectory))
1316     {
1317         ILFree(newDirectory);
1318         return E_INVALIDARG;
1319     }
1320     ILRemoveLastID(newDirectory);
1321     HRESULT hResult = BrowseToPIDL(newDirectory, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
1322     ILFree(newDirectory);
1323     if (FAILED_UNEXPECTEDLY(hResult))
1324         return hResult;
1325     return S_OK;
1326 }
1327 
1328 BOOL CALLBACK AddFolderOptionsPage(HPROPSHEETPAGE thePage, LPARAM lParam)
1329 {
1330     PROPSHEETHEADER* sheetInfo = reinterpret_cast<PROPSHEETHEADER*>(lParam);
1331     if (sheetInfo->nPages >= folderOptionsPageCountMax)
1332         return FALSE;
1333     sheetInfo->phpage[sheetInfo->nPages] = thePage;
1334     sheetInfo->nPages++;
1335     return TRUE;
1336 }
1337 
1338 HRESULT CShellBrowser::DoFolderOptions()
1339 {
1340     CComPtr<IShellPropSheetExt>             folderOptionsSheet;
1341     PROPSHEETHEADER                         m_PropSheet;
1342     HPROPSHEETPAGE                          m_psp[folderOptionsPageCountMax];
1343 //    CComPtr<IGlobalFolderSettings>          globalSettings;
1344 //    SHELLSTATE2                             shellState;
1345     HRESULT                                 hResult;
1346 
1347     memset(m_psp, 0, sizeof(m_psp));
1348     memset(&m_PropSheet, 0, sizeof(m_PropSheet));
1349 
1350     // create sheet object
1351     hResult = CoCreateInstance(CLSID_ShellFldSetExt, NULL, CLSCTX_INPROC_SERVER,
1352         IID_PPV_ARG(IShellPropSheetExt, &folderOptionsSheet));
1353     if (FAILED_UNEXPECTEDLY(hResult))
1354         return E_FAIL;
1355 
1356     // must set site in order for Apply to all Folders on Advanced page to be enabled
1357     hResult = IUnknown_SetSite(folderOptionsSheet, static_cast<IDispatch *>(this));
1358     m_PropSheet.phpage = m_psp;
1359 
1360 #if 0
1361     hResult = CoCreateInstance(CLSID_GlobalFolderSettings, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IGlobalFolderSettings, &globalSettings));
1362     if (FAILED_UNEXPECTEDLY(hResult))
1363         return E_FAIL;
1364     hResult = globalSettings->Get(&shellState, sizeof(shellState));
1365     if (FAILED_UNEXPECTEDLY(hResult))
1366         return E_FAIL;
1367 #endif
1368 
1369     // add pages
1370     hResult = folderOptionsSheet->AddPages(AddFolderOptionsPage, reinterpret_cast<LPARAM>(&m_PropSheet));
1371     if (FAILED_UNEXPECTEDLY(hResult))
1372         return E_FAIL;
1373 
1374     if (fCurrentShellView)
1375     {
1376         hResult = fCurrentShellView->AddPropertySheetPages(
1377             0, AddFolderOptionsPage, reinterpret_cast<LPARAM>(&m_PropSheet));
1378         if (FAILED_UNEXPECTEDLY(hResult))
1379             return E_FAIL;
1380     }
1381 
1382     // show sheet
1383     CStringW strFolderOptions(MAKEINTRESOURCEW(IDS_FOLDER_OPTIONS));
1384     m_PropSheet.dwSize = sizeof(PROPSHEETHEADER);
1385     m_PropSheet.dwFlags = 0;
1386     m_PropSheet.hwndParent = m_hWnd;
1387     m_PropSheet.hInstance = _AtlBaseModule.GetResourceInstance();
1388     m_PropSheet.pszCaption = strFolderOptions;
1389     m_PropSheet.nStartPage = 0;
1390     PropertySheet(&m_PropSheet);
1391     return S_OK;
1392 }
1393 
1394 LRESULT CALLBACK CShellBrowser::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1395 {
1396     CShellBrowser                           *pThis = reinterpret_cast<CShellBrowser *>(hWnd);
1397     _ATL_MSG                                msg(pThis->m_hWnd, uMsg, wParam, lParam);
1398     LRESULT                                 lResult;
1399     const _ATL_MSG                          *previousMessage;
1400     BOOL                                    handled;
1401     WNDPROC                                 saveWindowProc;
1402     HRESULT                                 hResult;
1403 
1404     hWnd = pThis->m_hWnd;
1405     previousMessage = pThis->m_pCurrentMsg;
1406     pThis->m_pCurrentMsg = &msg;
1407 
1408     /* If the shell browser is initialized, let the menu band preprocess the messages */
1409     if (pThis->fCurrentDirectoryPIDL)
1410     {
1411         CComPtr<IMenuBand> menuBand;
1412         hResult = pThis->GetMenuBand(IID_PPV_ARG(IMenuBand, &menuBand));
1413         if (SUCCEEDED(hResult) && menuBand.p != NULL)
1414         {
1415             hResult = menuBand->TranslateMenuMessage(&msg, &lResult);
1416             if (hResult == S_OK)
1417                 return lResult;
1418             uMsg = msg.message;
1419             wParam = msg.wParam;
1420             lParam = msg.lParam;
1421         }
1422         menuBand.Release();
1423     }
1424 
1425     handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
1426     ATLASSERT(pThis->m_pCurrentMsg == &msg);
1427     if (handled == FALSE)
1428     {
1429         if (uMsg == WM_NCDESTROY)
1430         {
1431             saveWindowProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hWnd, GWLP_WNDPROC));
1432             lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1433             if (saveWindowProc == reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hWnd, GWLP_WNDPROC)))
1434                 ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
1435             pThis->m_dwState |= WINSTATE_DESTROYED;
1436         }
1437         else
1438             lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
1439     }
1440     pThis->m_pCurrentMsg = previousMessage;
1441     if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0)
1442     {
1443         pThis->m_dwState &= ~WINSTATE_DESTROYED;
1444         pThis->m_hWnd = NULL;
1445         pThis->OnFinalMessage(hWnd);
1446     }
1447     return lResult;
1448 }
1449 
1450 void CShellBrowser::RepositionBars()
1451 {
1452     RECT                                    clientRect;
1453     RECT                                    statusRect;
1454     int                                     x;
1455 
1456     GetClientRect(&clientRect);
1457 
1458     if (m_settings.fStatusBarVisible && fStatusBar)
1459     {
1460         ::GetWindowRect(fStatusBar, &statusRect);
1461         ::SetWindowPos(fStatusBar, NULL, clientRect.left, clientRect.bottom - (statusRect.bottom - statusRect.top),
1462                             clientRect.right - clientRect.left,
1463                             statusRect.bottom - statusRect.top, SWP_NOOWNERZORDER | SWP_NOZORDER);
1464         clientRect.bottom -= statusRect.bottom - statusRect.top;
1465     }
1466 
1467     for (x = 0; x < 3; x++)
1468     {
1469         HWND hwnd = fClientBars[x].hwnd;
1470         RECT borderSpace = fClientBars[x].borderSpace;
1471         if (hwnd == NULL && fClientBars[x].clientBar != NULL)
1472         {
1473             IUnknown_GetWindow(fClientBars[x].clientBar, &hwnd);
1474             fClientBars[x].hwnd = hwnd;
1475         }
1476         if (hwnd != NULL)
1477         {
1478             RECT toolbarRect = clientRect;
1479             if (borderSpace.top != 0)
1480             {
1481                 toolbarRect.bottom = toolbarRect.top + borderSpace.top;
1482             }
1483             else if (borderSpace.bottom != 0)
1484             {
1485                 toolbarRect.top = toolbarRect.bottom - borderSpace.bottom;
1486             }
1487             else if (borderSpace.left != 0)
1488             {
1489                 toolbarRect.right = toolbarRect.left + borderSpace.left;
1490             }
1491             else if (borderSpace.right != 0)
1492             {
1493                 toolbarRect.left = toolbarRect.right - borderSpace.right;
1494             }
1495 
1496             ::SetWindowPos(hwnd, NULL,
1497                 toolbarRect.left,
1498                 toolbarRect.top,
1499                 toolbarRect.right - toolbarRect.left,
1500                 toolbarRect.bottom - toolbarRect.top,
1501                 SWP_NOOWNERZORDER | SWP_NOZORDER);
1502 
1503             if (borderSpace.top != 0)
1504             {
1505                 clientRect.top = toolbarRect.bottom;
1506             }
1507             else if (borderSpace.bottom != 0)
1508             {
1509                 clientRect.bottom = toolbarRect.top;
1510             }
1511             else if (borderSpace.left != 0)
1512             {
1513                 clientRect.left = toolbarRect.right;
1514             }
1515             else if (borderSpace.right != 0)
1516             {
1517                 clientRect.right = toolbarRect.left;
1518             }
1519         }
1520     }
1521     ::SetWindowPos(fCurrentShellViewWindow, NULL, clientRect.left, clientRect.top,
1522                         clientRect.right - clientRect.left,
1523                         clientRect.bottom - clientRect.top, SWP_NOOWNERZORDER | SWP_NOZORDER);
1524 }
1525 
1526 HRESULT CShellBrowser::FireEvent(DISPID dispIdMember, int argCount, VARIANT *arguments)
1527 {
1528     DISPPARAMS                          params;
1529     CComDynamicUnkArray                 &vec = IConnectionPointImpl<CShellBrowser, &DIID_DWebBrowserEvents2>::m_vec;
1530     CComDynamicUnkArray                 &vec2 = IConnectionPointImpl<CShellBrowser, &DIID_DWebBrowserEvents>::m_vec;
1531     HRESULT                             hResult;
1532 
1533     params.rgvarg = arguments;
1534     params.rgdispidNamedArgs = NULL;
1535     params.cArgs = argCount;
1536     params.cNamedArgs = 0;
1537     IUnknown** pp = vec.begin();
1538     while (pp < vec.end())
1539     {
1540         if (*pp != NULL)
1541         {
1542             CComPtr<IDispatch>          theDispatch;
1543 
1544             hResult = (*pp)->QueryInterface(IID_PPV_ARG(IDispatch, &theDispatch));
1545             hResult = theDispatch->Invoke(dispIdMember, GUID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, NULL);
1546         }
1547         pp++;
1548     }
1549     pp = vec2.begin();
1550     while (pp < vec2.end())
1551     {
1552         if (*pp != NULL)
1553         {
1554             CComPtr<IDispatch>          theDispatch;
1555 
1556             hResult = (*pp)->QueryInterface(IID_PPV_ARG(IDispatch, &theDispatch));
1557             hResult = theDispatch->Invoke(dispIdMember, GUID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, NULL);
1558         }
1559         pp++;
1560     }
1561     return S_OK;
1562 }
1563 
1564 HRESULT CShellBrowser::FireNavigateComplete(const wchar_t *newDirectory)
1565 {
1566     // these two variants intentionally to do use CComVariant because it would double free/release
1567     // or does not need to dispose at all
1568     VARIANT                             varArg[2];
1569     VARIANT                             varArgs;
1570     CComBSTR                            tempString(newDirectory);
1571 
1572     V_VT(&varArgs) = VT_BSTR;
1573     V_BSTR(&varArgs) = tempString.m_str;
1574 
1575     V_VT(&varArg[0]) = VT_VARIANT | VT_BYREF;
1576     V_VARIANTREF(&varArg[0]) = &varArgs;
1577     V_VT(&varArg[1]) = VT_DISPATCH;
1578     V_DISPATCH(&varArg[1]) = (IDispatch *)this;
1579 
1580     return FireEvent(DISPID_NAVIGATECOMPLETE2, 2, varArg);
1581 }
1582 
1583 HRESULT CShellBrowser::FireCommandStateChange(bool newState, int commandID)
1584 {
1585     VARIANT                             varArg[2];
1586 
1587     V_VT(&varArg[0]) = VT_BOOL;
1588     V_BOOL(&varArg[0]) = newState ? VARIANT_TRUE : VARIANT_FALSE;
1589     V_VT(&varArg[1]) = VT_I4;
1590     V_I4(&varArg[1]) = commandID;
1591 
1592     return FireEvent(DISPID_COMMANDSTATECHANGE, 2, varArg);
1593 }
1594 
1595 HRESULT CShellBrowser::FireCommandStateChangeAll()
1596 {
1597     return FireCommandStateChange(false, -1);
1598 }
1599 
1600 HRESULT CShellBrowser::UpdateForwardBackState()
1601 {
1602     CComPtr<ITravelLog>                     travelLog;
1603     CComPtr<ITravelEntry>                   unusedEntry;
1604     bool                                    canGoBack;
1605     bool                                    canGoForward;
1606     HRESULT                                 hResult;
1607 
1608     canGoBack = false;
1609     canGoForward = false;
1610     hResult = GetTravelLog(&travelLog);
1611     if (FAILED_UNEXPECTEDLY(hResult))
1612         return hResult;
1613     hResult = travelLog->GetTravelEntry(static_cast<IDropTarget *>(this), TLOG_BACK, &unusedEntry);
1614     if (SUCCEEDED(hResult))
1615     {
1616         canGoBack = true;
1617         unusedEntry.Release();
1618     }
1619     hResult = travelLog->GetTravelEntry(static_cast<IDropTarget *>(this), TLOG_FORE, &unusedEntry);
1620     if (SUCCEEDED(hResult))
1621     {
1622         canGoForward = true;
1623         unusedEntry.Release();
1624     }
1625     hResult = FireCommandStateChange(canGoBack, 2);
1626     hResult = FireCommandStateChange(canGoForward, 1);
1627     return S_OK;
1628 }
1629 
1630 HRESULT CShellBrowser::UpdateUpState()
1631 {
1632     bool canGoUp;
1633     HRESULT hResult;
1634 
1635     canGoUp = true;
1636     if (_ILIsDesktop(fCurrentDirectoryPIDL))
1637         canGoUp = false;
1638     hResult = FireCommandStateChange(canGoUp, 3);
1639     return S_OK;
1640 }
1641 
1642 void CShellBrowser::UpdateGotoMenu(HMENU theMenu)
1643 {
1644     CComPtr<ITravelLog>                     travelLog;
1645     CComPtr<ITravelEntry>                   unusedEntry;
1646     int                                     position;
1647     MENUITEMINFO                            menuItemInfo;
1648     HRESULT                                 hResult;
1649 
1650     DeleteMenuItems(theMenu, IDM_GOTO_TRAVEL_FIRST, IDM_GOTO_TRAVEL_LAST);
1651 
1652     position = GetMenuItemCount(theMenu);
1653     hResult = GetTravelLog(&travelLog);
1654     if (FAILED_UNEXPECTEDLY(hResult))
1655         return;
1656 
1657     hResult = travelLog->GetTravelEntry(static_cast<IDropTarget *>(this),
1658                                         TLOG_BACK,
1659                                         &unusedEntry);
1660 
1661     if (SUCCEEDED(hResult))
1662     {
1663         SHEnableMenuItem(theMenu, IDM_GOTO_BACK, TRUE);
1664         unusedEntry.Release();
1665     }
1666     else
1667         SHEnableMenuItem(theMenu, IDM_GOTO_BACK, FALSE);
1668 
1669     hResult = travelLog->GetTravelEntry(static_cast<IDropTarget *>(this),
1670                                         TLOG_FORE,
1671                                         &unusedEntry);
1672 
1673     if (SUCCEEDED(hResult))
1674     {
1675         SHEnableMenuItem(theMenu, IDM_GOTO_FORWARD, TRUE);
1676         unusedEntry.Release();
1677     }
1678     else
1679         SHEnableMenuItem(theMenu, IDM_GOTO_FORWARD, FALSE);
1680 
1681     SHEnableMenuItem(theMenu,
1682                      IDM_GOTO_UPONELEVEL,
1683                      !_ILIsDesktop(fCurrentDirectoryPIDL));
1684 
1685     hResult = travelLog->InsertMenuEntries(static_cast<IDropTarget *>(this), theMenu, position,
1686         IDM_GOTO_TRAVEL_FIRSTTARGET, IDM_GOTO_TRAVEL_LASTTARGET, TLMENUF_BACKANDFORTH | TLMENUF_CHECKCURRENT);
1687     if (SUCCEEDED(hResult))
1688     {
1689         menuItemInfo.cbSize = sizeof(menuItemInfo);
1690         menuItemInfo.fMask = MIIM_TYPE | MIIM_ID;
1691         menuItemInfo.fType = MF_SEPARATOR;
1692         menuItemInfo.wID = IDM_GOTO_TRAVEL_SEP;
1693         InsertMenuItem(theMenu, position, TRUE, &menuItemInfo);
1694     }
1695 }
1696 
1697 void CShellBrowser::UpdateViewMenu(HMENU theMenu)
1698 {
1699     CComPtr<ITravelLog>                     travelLog;
1700     HMENU                                   gotoMenu;
1701     OLECMD                                  commandList[5];
1702     HMENU                                   toolbarMenuBar;
1703     HMENU                                   toolbarMenu;
1704     MENUITEMINFO                            menuItemInfo;
1705     HRESULT                                 hResult;
1706 
1707     gotoMenu = SHGetMenuFromID(theMenu, FCIDM_MENU_EXPLORE);
1708     if (gotoMenu != NULL)
1709         UpdateGotoMenu(gotoMenu);
1710 
1711     commandList[0].cmdID = ITID_TOOLBARBANDSHOWN;
1712     commandList[1].cmdID = ITID_ADDRESSBANDSHOWN;
1713     commandList[2].cmdID = ITID_LINKSBANDSHOWN;
1714     commandList[3].cmdID = ITID_TOOLBARLOCKED;
1715     commandList[4].cmdID = ITID_CUSTOMIZEENABLED;
1716 
1717     hResult = IUnknown_QueryStatus(fClientBars[BIInternetToolbar].clientBar,
1718                                    CGID_PrivCITCommands, 5, commandList, NULL);
1719     if (FAILED_UNEXPECTEDLY(hResult))
1720         DeleteMenu(theMenu, IDM_VIEW_TOOLBARS, MF_BYCOMMAND);
1721     else
1722     {
1723         menuItemInfo.cbSize = sizeof(menuItemInfo);
1724         menuItemInfo.fMask = MIIM_SUBMENU;
1725         GetMenuItemInfo(theMenu, IDM_VIEW_TOOLBARS, FALSE, &menuItemInfo);
1726         DestroyMenu(menuItemInfo.hSubMenu);
1727 
1728         toolbarMenuBar = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_CONTEXTMENU));
1729         toolbarMenu = GetSubMenu(toolbarMenuBar, 0);
1730         RemoveMenu(toolbarMenuBar, 0, MF_BYPOSITION);
1731         DestroyMenu(toolbarMenuBar);
1732 
1733         // TODO: Implement
1734         SHEnableMenuItem(toolbarMenu, IDM_TOOLBARS_STANDARDBUTTONS, commandList[0].cmdf & OLECMDF_ENABLED);
1735         SHEnableMenuItem(toolbarMenu, IDM_TOOLBARS_ADDRESSBAR, commandList[1].cmdf & OLECMDF_ENABLED);
1736         SHEnableMenuItem(toolbarMenu, IDM_TOOLBARS_LINKSBAR, commandList[2].cmdf & OLECMDF_ENABLED);
1737         SHEnableMenuItem(toolbarMenu, IDM_TOOLBARS_CUSTOMIZE, commandList[4].cmdf & OLECMDF_ENABLED);
1738 
1739         SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_STANDARDBUTTONS, commandList[0].cmdf & OLECMDF_LATCHED);
1740         SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_ADDRESSBAR, commandList[1].cmdf & OLECMDF_LATCHED);
1741         SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_LINKSBAR, commandList[2].cmdf & OLECMDF_LATCHED);
1742         SHCheckMenuItem(toolbarMenu, IDM_TOOLBARS_LOCKTOOLBARS, commandList[3].cmdf & OLECMDF_LATCHED);
1743         if ((commandList[4].cmdf & OLECMDF_ENABLED) == 0)
1744             DeleteMenu(toolbarMenu, IDM_TOOLBARS_CUSTOMIZE, MF_BYCOMMAND);
1745         DeleteMenu(toolbarMenu, IDM_TOOLBARS_TEXTLABELS, MF_BYCOMMAND);
1746         DeleteMenu(toolbarMenu, IDM_TOOLBARS_GOBUTTON, MF_BYCOMMAND);
1747 
1748         menuItemInfo.cbSize = sizeof(menuItemInfo);
1749         menuItemInfo.fMask = MIIM_SUBMENU;
1750         menuItemInfo.hSubMenu = toolbarMenu;
1751         SetMenuItemInfo(theMenu, IDM_VIEW_TOOLBARS, FALSE, &menuItemInfo);
1752     }
1753     SHCheckMenuItem(theMenu, IDM_VIEW_STATUSBAR, m_settings.fStatusBarVisible ? TRUE : FALSE);
1754 }
1755 
1756 HRESULT CShellBrowser::BuildExplorerBandMenu()
1757 {
1758     HMENU                                   hBandsMenu;
1759     UINT                                    nbFound;
1760 
1761     hBandsMenu = SHGetMenuFromID(fCurrentMenuBar, IDM_VIEW_EXPLORERBAR);
1762     if (!hBandsMenu)
1763     {
1764         OutputDebugString(L"No menu !\n");
1765         return E_FAIL;
1766     }
1767     DSA_DeleteAllItems(menuDsa);
1768     BuildExplorerBandCategory(hBandsMenu, CATID_InfoBand, 4, NULL);
1769     BuildExplorerBandCategory(hBandsMenu, CATID_CommBand, 20, &nbFound);
1770     if (!nbFound)
1771     {
1772         // Remove separator
1773         DeleteMenu(hBandsMenu, IDM_EXPLORERBAR_SEPARATOR, MF_BYCOMMAND);
1774     }
1775     // Remove media menu since XP does it (according to API Monitor)
1776     DeleteMenu(hBandsMenu, IDM_EXPLORERBAR_MEDIA, MF_BYCOMMAND);
1777     return S_OK;
1778 }
1779 
1780 HRESULT CShellBrowser::BuildExplorerBandCategory(HMENU hBandsMenu, CATID category, DWORD dwPos, UINT *nbFound)
1781 {
1782     HRESULT                                 hr;
1783     CComPtr<IEnumGUID>                      pEnumGUID;
1784     WCHAR                                   wszBandName[MAX_PATH];
1785     WCHAR                                   wszBandGUID[MAX_PATH];
1786     WCHAR                                   wRegKey[MAX_PATH];
1787     UINT                                    cBands;
1788     DWORD                                   dwRead;
1789     DWORD                                   dwDataSize;
1790     GUID                                    iter;
1791     MenuBandInfo                            mbi;
1792 
1793     mbi.fVertical = IsEqualGUID(category, CATID_InfoBand);
1794     cBands = 0;
1795     hr = SHEnumClassesOfCategories(1, &category, 0, NULL, &pEnumGUID);
1796     if (FAILED_UNEXPECTEDLY(hr))
1797     {
1798         return hr;
1799     }
1800     do
1801     {
1802         pEnumGUID->Next(1, &iter, &dwRead);
1803         if (dwRead)
1804         {
1805             // Get the band name
1806             if (IsBuiltinBand(iter))
1807                 continue;
1808             if (!StringFromGUID2(iter, wszBandGUID, MAX_PATH))
1809                 continue;
1810             StringCchPrintfW(wRegKey, MAX_PATH, L"CLSID\\%s", wszBandGUID);
1811             dwDataSize = MAX_PATH;
1812             SHGetValue(HKEY_CLASSES_ROOT, wRegKey, NULL, NULL, wszBandName, &dwDataSize);
1813 
1814             mbi.barGuid = iter;
1815             InsertMenu(hBandsMenu, dwPos + cBands, MF_BYPOSITION, IDM_EXPLORERBAND_BEGINCUSTOM + DSA_GetItemCount(menuDsa), wszBandName);
1816             DSA_AppendItem(menuDsa, &mbi);
1817             cBands++;
1818         }
1819     }
1820     while (dwRead > 0);
1821     if (nbFound)
1822         *nbFound = cBands;
1823     return S_OK;
1824 }
1825 
1826 BOOL CShellBrowser::IsBuiltinBand(CLSID &bandID)
1827 {
1828     if (IsEqualCLSID(bandID, CLSID_ExplorerBand))
1829         return TRUE;
1830     if (IsEqualCLSID(bandID, CLSID_SH_SearchBand) || IsEqualCLSID(bandID, CLSID_SearchBand))
1831         return TRUE;
1832     if (IsEqualCLSID(bandID, CLSID_IE_SearchBand) || IsEqualCLSID(bandID, CLSID_FileSearchBand))
1833         return TRUE;
1834     if (IsEqualCLSID(bandID, CLSID_SH_HistBand))
1835         return TRUE;
1836     if (IsEqualCLSID(bandID, CLSID_SH_FavBand))
1837         return TRUE;
1838     if (IsEqualCLSID(bandID, CLSID_ChannelsBand))
1839         return TRUE;
1840     return FALSE;
1841 }
1842 
1843 HRESULT CShellBrowser::OnSearch()
1844 {
1845     CComPtr<IObjectWithSite>                objectWithSite;
1846     CComPtr<IContextMenu>                   contextMenu;
1847     CMINVOKECOMMANDINFO                     commandInfo;
1848     const char                              *searchGUID = "{169A0691-8DF9-11d1-A1C4-00C04FD75D13}";
1849     HRESULT                                 hResult;
1850 
1851     // TODO: Query shell if this command is enabled first
1852 
1853     memset(&commandInfo, 0, sizeof(commandInfo));
1854     commandInfo.cbSize = sizeof(commandInfo);
1855     commandInfo.hwnd = m_hWnd;
1856     commandInfo.lpParameters = searchGUID;
1857     commandInfo.nShow = SW_SHOWNORMAL;
1858 
1859     hResult = CoCreateInstance(CLSID_ShellSearchExt, NULL, CLSCTX_INPROC_SERVER,
1860         IID_PPV_ARG(IContextMenu, &contextMenu));
1861     if (FAILED_UNEXPECTEDLY(hResult))
1862         return 0;
1863     hResult = contextMenu->QueryInterface(IID_PPV_ARG(IObjectWithSite, &objectWithSite));
1864     if (FAILED_UNEXPECTEDLY(hResult))
1865         return 0;
1866     hResult = objectWithSite->SetSite(dynamic_cast<IShellBrowser*>(this));
1867     if (FAILED_UNEXPECTEDLY(hResult))
1868         return 0;
1869     hResult = contextMenu->InvokeCommand(&commandInfo);
1870     hResult = objectWithSite->SetSite(NULL);
1871     return hResult;
1872 }
1873 
1874 bool IUnknownIsEqual(IUnknown *int1, IUnknown *int2)
1875 {
1876     CComPtr<IUnknown>                       int1Retry;
1877     CComPtr<IUnknown>                       int2Retry;
1878     HRESULT                                 hResult;
1879 
1880     if (int1 == int2)
1881         return true;
1882     if (int1 == NULL || int2 == NULL)
1883         return false;
1884     hResult = int1->QueryInterface(IID_PPV_ARG(IUnknown, &int1Retry));
1885     if (FAILED_UNEXPECTEDLY(hResult))
1886         return false;
1887     hResult = int2->QueryInterface(IID_PPV_ARG(IUnknown, &int2Retry));
1888     if (FAILED_UNEXPECTEDLY(hResult))
1889         return false;
1890     if (int1Retry == int2Retry)
1891         return true;
1892     return false;
1893 }
1894 
1895 HRESULT STDMETHODCALLTYPE CShellBrowser::GetBorderDW(IUnknown *punkObj, LPRECT prcBorder)
1896 {
1897     static const INT excludeItems[] = { 1, 1, 1, IDC_STATUSBAR, 0, 0 };
1898 
1899     RECT availableBounds;
1900 
1901     GetEffectiveClientRect(m_hWnd, &availableBounds, excludeItems);
1902     for (INT x = 0; x < 3; x++)
1903     {
1904         if (fClientBars[x].clientBar.p != NULL && !IUnknownIsEqual(fClientBars[x].clientBar, punkObj))
1905         {
1906             availableBounds.top += fClientBars[x].borderSpace.top;
1907             availableBounds.left += fClientBars[x].borderSpace.left;
1908             availableBounds.bottom -= fClientBars[x].borderSpace.bottom;
1909             availableBounds.right -= fClientBars[x].borderSpace.right;
1910         }
1911     }
1912     *prcBorder = availableBounds;
1913     return S_OK;
1914 }
1915 
1916 HRESULT STDMETHODCALLTYPE CShellBrowser::RequestBorderSpaceDW(IUnknown* punkObj, LPCBORDERWIDTHS pbw)
1917 {
1918     return S_OK;
1919 }
1920 
1921 HRESULT STDMETHODCALLTYPE CShellBrowser::SetBorderSpaceDW(IUnknown* punkObj, LPCBORDERWIDTHS pbw)
1922 {
1923     for (INT x = 0; x < 3; x++)
1924     {
1925         if (IUnknownIsEqual(fClientBars[x].clientBar, punkObj))
1926         {
1927             fClientBars[x].borderSpace = *pbw;
1928             // if this bar changed size, it cascades and forces all subsequent bars to resize
1929             RepositionBars();
1930             return S_OK;
1931         }
1932     }
1933     return E_INVALIDARG;
1934 }
1935 
1936 HRESULT STDMETHODCALLTYPE CShellBrowser::QueryStatus(const GUID *pguidCmdGroup,
1937     ULONG cCmds, OLECMD prgCmds[  ], OLECMDTEXT *pCmdText)
1938 {
1939     CComPtr<IOleCommandTarget>              commandTarget;
1940     HRESULT                                 hResult;
1941 
1942     if (prgCmds == NULL)
1943         return E_INVALIDARG;
1944     if (pguidCmdGroup == NULL)
1945     {
1946         if (fCurrentShellView.p != NULL)
1947         {
1948             hResult = fCurrentShellView->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &commandTarget));
1949             if (SUCCEEDED(hResult) && commandTarget.p != NULL)
1950                 return commandTarget->QueryStatus(NULL, 1, prgCmds, pCmdText);
1951         }
1952         while (cCmds != 0)
1953         {
1954             prgCmds->cmdf = 0;
1955             prgCmds++;
1956             cCmds--;
1957         }
1958     }
1959     else if (IsEqualIID(*pguidCmdGroup, CGID_Explorer))
1960     {
1961         while (cCmds != 0)
1962         {
1963             switch (prgCmds->cmdID)
1964             {
1965                 case 0x1c:  // search
1966                     prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1967                     if (IsEqualCLSID(CLSID_SH_SearchBand, fCurrentVertBar) ||
1968                         IsEqualCLSID(CLSID_SearchBand, fCurrentVertBar) ||
1969                         IsEqualCLSID(CLSID_IE_SearchBand, fCurrentVertBar) ||
1970                         IsEqualCLSID(CLSID_FileSearchBand, fCurrentVertBar))
1971                     {
1972                         prgCmds->cmdf |= OLECMDF_LATCHED;
1973                     }
1974                     break;
1975                 case 0x1d:  // history
1976                     prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1977                     if (IsEqualCLSID(CLSID_SH_HistBand, fCurrentVertBar))
1978                         prgCmds->cmdf |= OLECMDF_LATCHED;
1979                     break;
1980                 case 0x1e:  // favorites
1981                     prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1982                     if (IsEqualCLSID(CLSID_SH_FavBand, fCurrentVertBar))
1983                         prgCmds->cmdf |= OLECMDF_LATCHED;
1984                     break;
1985                 case SBCMDID_EXPLORERBARFOLDERS:  // folders
1986                     prgCmds->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
1987                     if (IsEqualCLSID(CLSID_ExplorerBand, fCurrentVertBar))
1988                         prgCmds->cmdf |= OLECMDF_LATCHED;
1989                     break;
1990                 default:
1991                     prgCmds->cmdf = 0;
1992                     break;
1993             }
1994             prgCmds++;
1995             cCmds--;
1996         }
1997     }
1998     else if (IsEqualIID(*pguidCmdGroup, CGID_ShellBrowser))
1999     {
2000         while (cCmds != 0)
2001         {
2002             switch (prgCmds->cmdID)
2003             {
2004                 case IDM_GOTO_UPONELEVEL:
2005                     prgCmds->cmdf = OLECMDF_SUPPORTED;
2006                     if (fCurrentDirectoryPIDL->mkid.cb != 0)
2007                         prgCmds->cmdf |= OLECMDF_ENABLED;
2008                     break;
2009             }
2010             prgCmds++;
2011             cCmds--;
2012         }
2013     }
2014     return S_OK;
2015 }
2016 
2017 HRESULT STDMETHODCALLTYPE CShellBrowser::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
2018     DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
2019 {
2020     HRESULT                                 hResult;
2021 
2022     if (!pguidCmdGroup)
2023     {
2024         TRACE("Unhandled null CGID %d %d %p %p\n", nCmdID, nCmdexecopt, pvaIn, pvaOut);
2025         return E_NOTIMPL;
2026     }
2027     if (IsEqualIID(*pguidCmdGroup, CGID_Explorer))
2028     {
2029         switch (nCmdID)
2030         {
2031             case 0x1c: //Toggle Search
2032             case 0x1d: //Toggle History
2033             case 0x1e: //Toggle Favorites
2034             case SBCMDID_EXPLORERBARFOLDERS: //Toggle Folders
2035                 const GUID* pclsid;
2036                 if (nCmdID == 0x1c) pclsid = &CLSID_FileSearchBand;
2037                 else if (nCmdID == 0x1d) pclsid = &CLSID_SH_HistBand;
2038                 else if (nCmdID == 0x1e) pclsid = &CLSID_SH_FavBand;
2039                 else pclsid = &CLSID_ExplorerBand;
2040 
2041                 if (IsEqualCLSID(*pclsid, fCurrentVertBar))
2042                 {
2043                     hResult = IUnknown_ShowDW(fClientBars[BIVerticalBaseBar].clientBar.p, FALSE);
2044                     memset(&fCurrentVertBar, 0, sizeof(fCurrentVertBar));
2045                     FireCommandStateChangeAll();
2046                 }
2047                 else
2048                 {
2049                     hResult = ShowBand(*pclsid, true);
2050                 }
2051                 return S_OK;
2052             case 0x22:
2053                 //Sent when a band closes
2054                 if (V_VT(pvaIn) != VT_UNKNOWN)
2055                     return E_INVALIDARG;
2056 
2057                 if (IUnknownIsEqual(V_UNKNOWN(pvaIn), fClientBars[BIVerticalBaseBar].clientBar.p))
2058                 {
2059                     memset(&fCurrentVertBar, 0, sizeof(fCurrentVertBar));
2060                     FireCommandStateChangeAll();
2061                 }
2062                 return S_OK;
2063             case 0x27:
2064                 if (nCmdexecopt == 1)
2065                 {
2066                     // pvaIn is a VT_UNKNOWN with a band that is being hidden
2067                 }
2068                 else
2069                 {
2070                     // update zones part of the status bar
2071                 }
2072                 return S_OK;
2073             case 0x35: // don't do this, and the internet toolbar doesn't create a menu band
2074                 V_VT(pvaOut) = VT_INT_PTR;
2075                 V_INTREF(pvaOut) = reinterpret_cast<INT *>(
2076                     LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_MAINMENU)));
2077                 return S_OK;
2078             case 0x38:
2079                 // indicate if this cabinet was opened as a browser
2080                 return S_FALSE;
2081             default:
2082                 return E_NOTIMPL;
2083         }
2084     }
2085     else if (IsEqualIID(*pguidCmdGroup, CGID_InternetButtons))
2086     {
2087         switch (nCmdID)
2088         {
2089             case 0x23:
2090                 // placeholder
2091                 return S_OK;
2092         }
2093     }
2094     else if (IsEqualIID(*pguidCmdGroup, CGID_Theater))
2095     {
2096         switch (nCmdID)
2097         {
2098             case 6:
2099                 // what is theater mode and why do we receive this?
2100                 return E_NOTIMPL;
2101         }
2102     }
2103     else if (IsEqualIID(*pguidCmdGroup, CGID_MenuBand))
2104     {
2105         switch (nCmdID)
2106         {
2107             case 14:
2108                 // initialize favorites menu
2109                 return S_OK;
2110         }
2111     }
2112     else if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView))
2113     {
2114         switch (nCmdID)
2115         {
2116             case 0x12:
2117                 // refresh on toolbar clicked
2118                 return S_OK;
2119             case 0x26:
2120                 // called for unknown bands ?
2121                 return S_OK;
2122             case 0x4d:
2123                 // tell the view if it should hide the task pane or not
2124                 return (fClientBars[BIVerticalBaseBar].clientBar.p == NULL) ? S_FALSE : S_OK;
2125         }
2126     }
2127     else if (IsEqualIID(*pguidCmdGroup, CGID_ShellBrowser))
2128     {
2129         switch (nCmdID)
2130         {
2131             case 40994:
2132                 return NavigateToParent();
2133             case IDM_NOTIFYITBARDIRTY:
2134                 SaveITBarLayout();
2135                 break;
2136         }
2137     }
2138     else if (IsEqualIID(*pguidCmdGroup, CGID_IExplorerToolbar))
2139     {
2140         switch (nCmdID)
2141         {
2142             case 0x7063:
2143                 return DoFolderOptions();
2144         }
2145     }
2146     else if (IsEqualIID(*pguidCmdGroup, CGID_DefView))
2147     {
2148         switch (nCmdID)
2149         {
2150             case DVCMDID_RESET_DEFAULTFOLDER_SETTINGS:
2151                 IUnknown_Exec(fCurrentShellView, CGID_DefView, nCmdID, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
2152                 break;
2153         }
2154     }
2155     else
2156     {
2157         return E_NOTIMPL;
2158     }
2159     return E_NOTIMPL;
2160 }
2161 
2162 HRESULT STDMETHODCALLTYPE CShellBrowser::GetWindow(HWND *lphwnd)
2163 {
2164     if (lphwnd == NULL)
2165         return E_POINTER;
2166     *lphwnd = m_hWnd;
2167     return S_OK;
2168 }
2169 
2170 HRESULT STDMETHODCALLTYPE CShellBrowser::ContextSensitiveHelp(BOOL fEnterMode)
2171 {
2172     return E_NOTIMPL;
2173 }
2174 
2175 HRESULT STDMETHODCALLTYPE CShellBrowser::InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
2176 {
2177     HMENU mainMenu = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_MAINMENU));
2178 
2179     Shell_MergeMenus(hmenuShared, mainMenu, 0, 0, FCIDM_BROWSERLAST, MM_SUBMENUSHAVEIDS);
2180 
2181     int GCCU(itemCount3) = GetMenuItemCount(hmenuShared);
2182     Unused(itemCount3);
2183 
2184     DestroyMenu(mainMenu);
2185 
2186     lpMenuWidths->width[0] = 2;
2187     lpMenuWidths->width[2] = 3;
2188     lpMenuWidths->width[4] = 1;
2189     return S_OK;
2190 }
2191 
2192 HRESULT STDMETHODCALLTYPE CShellBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject)
2193 {
2194     CComPtr<IShellMenu>                     shellMenu;
2195     HRESULT                                 hResult;
2196 
2197     if (hmenuShared && IsMenu(hmenuShared) == FALSE)
2198         return E_FAIL;
2199     hResult = GetMenuBand(IID_PPV_ARG(IShellMenu, &shellMenu));
2200     if (FAILED_UNEXPECTEDLY(hResult))
2201         return hResult;
2202 
2203     if (!hmenuShared)
2204     {
2205         hmenuShared = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_CABINET_MAINMENU));
2206     }
2207     // FIXME: Figure out the proper way to do this.
2208     HMENU hMenuFavs = GetSubMenu(hmenuShared, 3);
2209     if (hMenuFavs)
2210     {
2211         DeleteMenu(hMenuFavs, IDM_FAVORITES_EMPTY, MF_BYCOMMAND);
2212     }
2213 
2214     hResult = shellMenu->SetMenu(hmenuShared, m_hWnd, SMSET_DONTOWN);
2215     if (FAILED_UNEXPECTEDLY(hResult))
2216         return hResult;
2217     fCurrentMenuBar = hmenuShared;
2218     BuildExplorerBandMenu();
2219     return S_OK;
2220 }
2221 
2222 HRESULT STDMETHODCALLTYPE CShellBrowser::RemoveMenusSB(HMENU hmenuShared)
2223 {
2224     if (hmenuShared == fCurrentMenuBar)
2225     {
2226         //DestroyMenu(fCurrentMenuBar);
2227         SetMenuSB(NULL, NULL, NULL);
2228     }
2229     return S_OK;
2230 }
2231 
2232 HRESULT STDMETHODCALLTYPE CShellBrowser::SetStatusTextSB(LPCOLESTR pszStatusText)
2233 {
2234     //
2235     if (pszStatusText)
2236     {
2237         ::SetWindowText(fStatusBar, pszStatusText);
2238     }
2239     else
2240     {
2241 
2242     }
2243     return S_OK;
2244 }
2245 
2246 HRESULT STDMETHODCALLTYPE CShellBrowser::EnableModelessSB(BOOL fEnable)
2247 {
2248     return E_NOTIMPL;
2249 }
2250 
2251 HRESULT STDMETHODCALLTYPE CShellBrowser::TranslateAcceleratorSB(MSG *pmsg, WORD wID)
2252 {
2253     if (!::TranslateAcceleratorW(m_hWnd, m_hAccel, pmsg))
2254         return S_FALSE;
2255     return S_OK;
2256 }
2257 
2258 HRESULT STDMETHODCALLTYPE CShellBrowser::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
2259 {
2260     if ((wFlags & SBSP_EXPLOREMODE) != NULL)
2261         ShowBand(CLSID_ExplorerBand, true);
2262 
2263     long flags = BTP_UPDATE_NEXT_HISTORY;
2264     if (fTravelLog)
2265         flags |= BTP_UPDATE_CUR_HISTORY;
2266     return BrowseToPIDL(pidl, flags);
2267 }
2268 
2269 HRESULT STDMETHODCALLTYPE CShellBrowser::GetViewStateStream(DWORD grfMode, IStream **ppStrm)
2270 {
2271     return E_NOTIMPL;
2272 }
2273 
2274 HRESULT STDMETHODCALLTYPE CShellBrowser::GetControlWindow(UINT id, HWND *lphwnd)
2275 {
2276     if (lphwnd == NULL)
2277         return E_POINTER;
2278     *lphwnd = NULL;
2279     switch (id)
2280     {
2281         case FCW_TOOLBAR:
2282             *lphwnd = fToolbarProxy.m_hWnd;
2283             return S_OK;
2284         case FCW_STATUS:
2285             *lphwnd = fStatusBar;
2286             return S_OK;
2287         case FCW_TREE:
2288         {
2289             BOOL shown;
2290             if (SUCCEEDED(IsControlWindowShown(id, &shown)) && shown)
2291                 return IUnknown_GetWindow(fClientBars[BIVerticalBaseBar].clientBar.p, lphwnd);
2292             return S_FALSE;
2293         }
2294         case FCW_PROGRESS:
2295             // is this a progress dialog?
2296             return S_OK;
2297     }
2298     return S_OK;
2299 }
2300 
2301 HRESULT STDMETHODCALLTYPE CShellBrowser::SendControlMsg(
2302     UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret)
2303 {
2304     LPARAM                                  result;
2305 
2306     if (pret != NULL)
2307         *pret = 0;
2308     switch (id)
2309     {
2310         case FCW_TOOLBAR:
2311             result = fToolbarProxy.SendMessage(uMsg, wParam, lParam);
2312             if (pret != NULL)
2313                 *pret = result;
2314             break;
2315         case FCW_STATUS:
2316             result = SendMessage(fStatusBar, uMsg, wParam, lParam);
2317             if (pret != NULL)
2318                 *pret = result;
2319             break;
2320     }
2321     return S_OK;
2322 }
2323 
2324 HRESULT STDMETHODCALLTYPE CShellBrowser::QueryActiveShellView(IShellView **ppshv)
2325 {
2326     if (ppshv == NULL)
2327         return E_POINTER;
2328     *ppshv = fCurrentShellView;
2329     if (fCurrentShellView.p != NULL)
2330     {
2331         fCurrentShellView.p->AddRef();
2332         return S_OK;
2333     }
2334     return E_FAIL;
2335 }
2336 
2337 HRESULT STDMETHODCALLTYPE CShellBrowser::OnViewWindowActive(IShellView *ppshv)
2338 {
2339     return E_NOTIMPL;
2340 }
2341 
2342 HRESULT STDMETHODCALLTYPE CShellBrowser::SetToolbarItems(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags)
2343 {
2344     return E_NOTIMPL;
2345 }
2346 
2347 HRESULT STDMETHODCALLTYPE CShellBrowser::DragEnter(
2348     IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2349 {
2350     return E_NOTIMPL;
2351 }
2352 
2353 HRESULT STDMETHODCALLTYPE CShellBrowser::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2354 {
2355     return E_NOTIMPL;
2356 }
2357 
2358 HRESULT STDMETHODCALLTYPE CShellBrowser::DragLeave()
2359 {
2360     return E_NOTIMPL;
2361 }
2362 
2363 HRESULT STDMETHODCALLTYPE CShellBrowser::Drop(
2364     IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2365 {
2366     return E_NOTIMPL;
2367 }
2368 
2369 HRESULT STDMETHODCALLTYPE CShellBrowser::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
2370 {
2371     // view does a query for SID_STopLevelBrowser, IID_IShellBrowserService
2372     // the returned interface has a method GetPropertyBag on it
2373     if (IsEqualIID(guidService, SID_STopLevelBrowser))
2374         return this->QueryInterface(riid, ppvObject);
2375     if (IsEqualIID(guidService, SID_SShellBrowser))
2376         return this->QueryInterface(riid, ppvObject);
2377     if (IsEqualIID(guidService, SID_ITargetFrame2))
2378         return this->QueryInterface(riid, ppvObject);
2379     if (IsEqualIID(guidService, SID_IWebBrowserApp))        // without this, the internet toolbar won't reflect notifications
2380         return this->QueryInterface(riid, ppvObject);
2381     if (IsEqualIID(guidService, SID_SProxyBrowser))
2382         return this->QueryInterface(riid, ppvObject);
2383     if (IsEqualIID(guidService, SID_IExplorerToolbar) && fClientBars[BIInternetToolbar].clientBar.p)
2384         return fClientBars[BIInternetToolbar].clientBar->QueryInterface(riid, ppvObject);
2385     if (IsEqualIID(riid, IID_IShellBrowser))
2386         return this->QueryInterface(riid, ppvObject);
2387     return E_NOINTERFACE;
2388 }
2389 
2390 static BOOL _ILIsNetworkPlace(LPCITEMIDLIST pidl)
2391 {
2392     WCHAR szPath[MAX_PATH];
2393     return SHGetPathFromIDListWrapW(pidl, szPath) && PathIsUNCW(szPath);
2394 }
2395 
2396 HRESULT STDMETHODCALLTYPE CShellBrowser::GetPropertyBag(long flags, REFIID riid, void **ppvObject)
2397 {
2398     if (ppvObject == NULL)
2399         return E_POINTER;
2400 
2401     *ppvObject = NULL;
2402 
2403     LPITEMIDLIST pidl;
2404     HRESULT hr = GetPidl(&pidl);
2405     if (FAILED_UNEXPECTEDLY(hr))
2406         return E_FAIL;
2407 
2408     // FIXME: pidl for Internet etc.
2409 
2410     if (_ILIsNetworkPlace(pidl))
2411         flags |= SHGVSPB_ROAM;
2412 
2413     hr = SHGetViewStatePropertyBag(pidl, L"Shell", flags, riid, ppvObject);
2414 
2415     ILFree(pidl);
2416     return hr;
2417 }
2418 
2419 HRESULT STDMETHODCALLTYPE CShellBrowser::GetTypeInfoCount(UINT *pctinfo)
2420 {
2421     return E_NOTIMPL;
2422 }
2423 
2424 HRESULT STDMETHODCALLTYPE CShellBrowser::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
2425 {
2426     return E_NOTIMPL;
2427 }
2428 
2429 HRESULT STDMETHODCALLTYPE CShellBrowser::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames,
2430     UINT cNames, LCID lcid, DISPID *rgDispId)
2431 {
2432     return E_NOTIMPL;
2433 }
2434 
2435 HRESULT STDMETHODCALLTYPE CShellBrowser::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
2436     WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
2437 {
2438     return E_NOTIMPL;
2439 }
2440 
2441 HRESULT STDMETHODCALLTYPE CShellBrowser::GetParentSite(IOleInPlaceSite **ppipsite)
2442 {
2443     return E_NOTIMPL;
2444 }
2445 
2446 HRESULT STDMETHODCALLTYPE CShellBrowser::SetTitle(IShellView *psv, LPCWSTR pszName)
2447 {
2448     return E_NOTIMPL;
2449 }
2450 
2451 HRESULT STDMETHODCALLTYPE CShellBrowser::GetTitle(IShellView *psv, LPWSTR pszName, DWORD cchName)
2452 {
2453     return E_NOTIMPL;
2454 }
2455 
2456 HRESULT STDMETHODCALLTYPE CShellBrowser::GetOleObject(IOleObject **ppobjv)
2457 {
2458     return E_NOTIMPL;
2459 }
2460 
2461 HRESULT STDMETHODCALLTYPE CShellBrowser::GetTravelLog(ITravelLog **pptl)
2462 {
2463     HRESULT                                 hResult;
2464 
2465     // called by toolbar when displaying tooltips
2466     if (pptl == NULL)
2467         return E_FAIL;
2468 
2469     *pptl = NULL;
2470     if (fTravelLog.p == NULL)
2471     {
2472         hResult = CTravelLog_CreateInstance(IID_PPV_ARG(ITravelLog, &fTravelLog));
2473         if (FAILED_UNEXPECTEDLY(hResult))
2474             return hResult;
2475     }
2476     *pptl = fTravelLog.p;
2477     fTravelLog.p->AddRef();
2478     return S_OK;
2479 }
2480 
2481 HRESULT STDMETHODCALLTYPE CShellBrowser::ShowControlWindow(UINT id, BOOL fShow)
2482 {
2483     BOOL shown;
2484     if (FAILED(IsControlWindowShown(id, &shown)))
2485         return E_NOTIMPL;
2486     else if (!shown == !fShow) // Negated for true boolean comparison
2487         return S_OK;
2488     else switch (id)
2489     {
2490         case FCW_STATUS:
2491             OnToggleStatusBarVisible(0, 0, NULL, shown);
2492             return S_OK;
2493         case FCW_TREE:
2494             return Exec(&CGID_Explorer, SBCMDID_EXPLORERBARFOLDERS, 0, NULL, NULL);
2495         case FCW_ADDRESSBAR:
2496             return IUnknown_Exec(fClientBars[BIInternetToolbar].clientBar,
2497                                  CGID_PrivCITCommands, ITID_ADDRESSBANDSHOWN, 0, NULL, NULL);
2498     }
2499     return E_NOTIMPL;
2500 }
2501 
2502 HRESULT STDMETHODCALLTYPE CShellBrowser::IsControlWindowShown(UINT id, BOOL *pfShown)
2503 {
2504     HRESULT hr = S_OK;
2505     BOOL shown = FALSE;
2506     switch (id)
2507     {
2508         case FCW_STATUS:
2509             shown = m_settings.fStatusBarVisible;
2510             break;
2511         case FCW_TREE:
2512         {
2513             OLECMD cmd = { SBCMDID_EXPLORERBARFOLDERS };
2514             hr = QueryStatus(&CGID_Explorer, 1, &cmd, NULL);
2515             shown = cmd.cmdf & OLECMDF_LATCHED;
2516             break;
2517         }
2518         case FCW_ADDRESSBAR:
2519             hr = IsInternetToolbarBandShown(ITID_ADDRESSBANDSHOWN);
2520             shown = hr == S_OK;
2521             break;
2522         default:
2523             hr = E_NOTIMPL;
2524     }
2525     if (pfShown)
2526     {
2527         *pfShown = shown;
2528         return hr;
2529     }
2530     return SUCCEEDED(hr) ? (shown ? S_OK : S_FALSE) : hr;
2531 }
2532 
2533 HRESULT CShellBrowser::IsInternetToolbarBandShown(UINT ITId)
2534 {
2535     OLECMD cmd = { ITId };
2536     HRESULT hr = IUnknown_QueryStatus(fClientBars[BIInternetToolbar].clientBar,
2537                                       CGID_PrivCITCommands, 1, &cmd, NULL);
2538     return SUCCEEDED(hr) ? (cmd.cmdf & OLECMDF_LATCHED) ? S_OK : S_FALSE : hr;
2539 }
2540 
2541 HRESULT STDMETHODCALLTYPE CShellBrowser::IEGetDisplayName(LPCITEMIDLIST pidl, LPWSTR pwszName, UINT uFlags)
2542 {
2543     return E_NOTIMPL;
2544 }
2545 
2546 HRESULT STDMETHODCALLTYPE CShellBrowser::IEParseDisplayName(UINT uiCP, LPCWSTR pwszPath, LPITEMIDLIST *ppidlOut)
2547 {
2548     return E_NOTIMPL;
2549 }
2550 
2551 HRESULT STDMETHODCALLTYPE CShellBrowser::DisplayParseError(HRESULT hres, LPCWSTR pwszPath)
2552 {
2553     return E_NOTIMPL;
2554 }
2555 
2556 HRESULT STDMETHODCALLTYPE CShellBrowser::NavigateToPidl(LPCITEMIDLIST pidl, DWORD grfHLNF)
2557 {
2558     return E_NOTIMPL;
2559 }
2560 
2561 HRESULT STDMETHODCALLTYPE CShellBrowser::SetNavigateState(BNSTATE bnstate)
2562 {
2563     return E_NOTIMPL;
2564 }
2565 
2566 HRESULT STDMETHODCALLTYPE CShellBrowser::GetNavigateState(BNSTATE *pbnstate)
2567 {
2568     return E_NOTIMPL;
2569 }
2570 
2571 HRESULT STDMETHODCALLTYPE CShellBrowser::NotifyRedirect(IShellView *psv, LPCITEMIDLIST pidl, BOOL *pfDidBrowse)
2572 {
2573     return E_NOTIMPL;
2574 }
2575 
2576 HRESULT STDMETHODCALLTYPE CShellBrowser::UpdateWindowList()
2577 {
2578     return E_NOTIMPL;
2579 }
2580 
2581 HRESULT STDMETHODCALLTYPE CShellBrowser::UpdateBackForwardState()
2582 {
2583     return E_NOTIMPL;
2584 }
2585 
2586 HRESULT STDMETHODCALLTYPE CShellBrowser::SetFlags(DWORD dwFlags, DWORD dwFlagMask)
2587 {
2588     return E_NOTIMPL;
2589 }
2590 
2591 HRESULT STDMETHODCALLTYPE CShellBrowser::GetFlags(DWORD *pdwFlags)
2592 {
2593     return E_NOTIMPL;
2594 }
2595 
2596 HRESULT STDMETHODCALLTYPE CShellBrowser::CanNavigateNow()
2597 {
2598     return E_NOTIMPL;
2599 }
2600 
2601 HRESULT STDMETHODCALLTYPE CShellBrowser::GetPidl(LPITEMIDLIST *ppidl)
2602 {
2603     // called by explorer bar to get current pidl
2604     return ppidl ? SHILClone(fCurrentDirectoryPIDL, ppidl) : E_POINTER;
2605 }
2606 
2607 HRESULT STDMETHODCALLTYPE CShellBrowser::SetReferrer(LPCITEMIDLIST pidl)
2608 {
2609     return E_NOTIMPL;
2610 }
2611 
2612 DWORD STDMETHODCALLTYPE CShellBrowser::GetBrowserIndex()
2613 {
2614     return -1;
2615 }
2616 
2617 HRESULT STDMETHODCALLTYPE CShellBrowser::GetBrowserByIndex(DWORD dwID, IUnknown **ppunk)
2618 {
2619     return E_NOTIMPL;
2620 }
2621 
2622 HRESULT STDMETHODCALLTYPE CShellBrowser::GetHistoryObject(IOleObject **ppole, IStream **pstm, IBindCtx **ppbc)
2623 {
2624     if (ppole == NULL || pstm == NULL || ppbc == NULL)
2625         return E_INVALIDARG;
2626     *ppole = fHistoryObject;
2627     if (fHistoryObject != NULL)
2628         fHistoryObject->AddRef();
2629     *pstm = fHistoryStream;
2630     if (fHistoryStream != NULL)
2631         fHistoryStream->AddRef();
2632     *ppbc = fHistoryBindContext;
2633     if (fHistoryBindContext != NULL)
2634         fHistoryBindContext->AddRef();
2635     fHistoryObject = NULL;
2636     fHistoryStream = NULL;
2637     fHistoryBindContext = NULL;
2638     if (*ppole == NULL)
2639         return E_FAIL;
2640     return S_OK;
2641 }
2642 
2643 HRESULT STDMETHODCALLTYPE CShellBrowser::SetHistoryObject(IOleObject *pole, BOOL fIsLocalAnchor)
2644 {
2645     return E_NOTIMPL;
2646 }
2647 
2648 HRESULT STDMETHODCALLTYPE CShellBrowser::CacheOLEServer(IOleObject *pole)
2649 {
2650     return E_NOTIMPL;
2651 }
2652 
2653 HRESULT STDMETHODCALLTYPE CShellBrowser::GetSetCodePage(VARIANT *pvarIn, VARIANT *pvarOut)
2654 {
2655     return E_NOTIMPL;
2656 }
2657 
2658 HRESULT STDMETHODCALLTYPE CShellBrowser::OnHttpEquiv(
2659     IShellView *psv, BOOL fDone, VARIANT *pvarargIn, VARIANT *pvarargOut)
2660 {
2661     return E_NOTIMPL;
2662 }
2663 
2664 HRESULT STDMETHODCALLTYPE CShellBrowser::GetPalette(HPALETTE *hpal)
2665 {
2666     return E_NOTIMPL;
2667 }
2668 
2669 HRESULT STDMETHODCALLTYPE CShellBrowser::RegisterWindow(BOOL fForceRegister, int swc)
2670 {
2671     return E_NOTIMPL;
2672 }
2673 
2674 LRESULT STDMETHODCALLTYPE CShellBrowser::WndProcBS(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2675 {
2676     return E_NOTIMPL;
2677 }
2678 
2679 HRESULT STDMETHODCALLTYPE CShellBrowser::SetAsDefFolderSettings()
2680 {
2681     HRESULT hr = E_FAIL;
2682     if (fCurrentShellView)
2683     {
2684         hr = ApplyBrowserDefaultFolderSettings(fCurrentShellView);
2685         IUnknown_Exec(fCurrentShellView, CGID_DefView, DVCMDID_SET_DEFAULTFOLDER_SETTINGS, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
2686     }
2687     return hr;
2688 }
2689 
2690 HRESULT STDMETHODCALLTYPE CShellBrowser::GetViewRect(RECT *prc)
2691 {
2692     return E_NOTIMPL;
2693 }
2694 
2695 HRESULT STDMETHODCALLTYPE CShellBrowser::OnSize(WPARAM wParam)
2696 {
2697     return E_NOTIMPL;
2698 }
2699 
2700 HRESULT STDMETHODCALLTYPE CShellBrowser::OnCreate(struct tagCREATESTRUCTW *pcs)
2701 {
2702     m_hAccel = LoadAcceleratorsW(GetModuleHandle(L"browseui.dll"), MAKEINTRESOURCEW(256));
2703     return S_OK;
2704 }
2705 
2706 LRESULT STDMETHODCALLTYPE CShellBrowser::OnCommand(WPARAM wParam, LPARAM lParam)
2707 {
2708     return 0;
2709 }
2710 
2711 HRESULT STDMETHODCALLTYPE CShellBrowser::OnDestroy()
2712 {
2713     return E_NOTIMPL;
2714 }
2715 
2716 LRESULT STDMETHODCALLTYPE CShellBrowser::OnNotify(struct tagNMHDR *pnm)
2717 {
2718     return 0;
2719 }
2720 
2721 HRESULT STDMETHODCALLTYPE CShellBrowser::OnSetFocus()
2722 {
2723     return E_NOTIMPL;
2724 }
2725 
2726 HRESULT STDMETHODCALLTYPE CShellBrowser::OnFrameWindowActivateBS(BOOL fActive)
2727 {
2728     return E_NOTIMPL;
2729 }
2730 
2731 HRESULT STDMETHODCALLTYPE CShellBrowser::ReleaseShellView()
2732 {
2733     return E_NOTIMPL;
2734 }
2735 
2736 HRESULT STDMETHODCALLTYPE CShellBrowser::ActivatePendingView()
2737 {
2738     return E_NOTIMPL;
2739 }
2740 
2741 HRESULT STDMETHODCALLTYPE CShellBrowser::CreateViewWindow(
2742     IShellView *psvNew, IShellView *psvOld, LPRECT prcView, HWND *phwnd)
2743 {
2744     return E_NOTIMPL;
2745 }
2746 
2747 HRESULT STDMETHODCALLTYPE CShellBrowser::CreateBrowserPropSheetExt(REFIID riid, void **ppv)
2748 {
2749     return E_NOTIMPL;
2750 }
2751 
2752 HRESULT STDMETHODCALLTYPE CShellBrowser::GetViewWindow(HWND *phwndView)
2753 {
2754     return E_NOTIMPL;
2755 }
2756 
2757 HRESULT STDMETHODCALLTYPE CShellBrowser::GetBaseBrowserData(LPCBASEBROWSERDATA *pbbd)
2758 {
2759     return E_NOTIMPL;
2760 }
2761 
2762 LPBASEBROWSERDATA STDMETHODCALLTYPE CShellBrowser::PutBaseBrowserData()
2763 {
2764     return NULL;
2765 }
2766 
2767 HRESULT STDMETHODCALLTYPE CShellBrowser::InitializeTravelLog(ITravelLog *ptl, DWORD dw)
2768 {
2769     return E_NOTIMPL;
2770 }
2771 
2772 HRESULT STDMETHODCALLTYPE CShellBrowser::SetTopBrowser()
2773 {
2774     return E_NOTIMPL;
2775 }
2776 
2777 HRESULT STDMETHODCALLTYPE CShellBrowser::Offline(int iCmd)
2778 {
2779     return E_NOTIMPL;
2780 }
2781 
2782 HRESULT STDMETHODCALLTYPE CShellBrowser::AllowViewResize(BOOL f)
2783 {
2784     return E_NOTIMPL;
2785 }
2786 
2787 HRESULT STDMETHODCALLTYPE CShellBrowser::SetActivateState(UINT u)
2788 {
2789     return E_NOTIMPL;
2790 }
2791 
2792 HRESULT STDMETHODCALLTYPE CShellBrowser::UpdateSecureLockIcon(int eSecureLock)
2793 {
2794     return E_NOTIMPL;
2795 }
2796 
2797 HRESULT STDMETHODCALLTYPE CShellBrowser::InitializeDownloadManager()
2798 {
2799     return E_NOTIMPL;
2800 }
2801 
2802 HRESULT STDMETHODCALLTYPE CShellBrowser::InitializeTransitionSite()
2803 {
2804     return E_NOTIMPL;
2805 }
2806 
2807 HRESULT STDMETHODCALLTYPE CShellBrowser::_Initialize(HWND hwnd, IUnknown *pauto)
2808 {
2809     return E_NOTIMPL;
2810 }
2811 
2812 HRESULT STDMETHODCALLTYPE CShellBrowser::_CancelPendingNavigationAsync()
2813 {
2814     return E_NOTIMPL;
2815 }
2816 
2817 HRESULT STDMETHODCALLTYPE CShellBrowser::_CancelPendingView()
2818 {
2819     return E_NOTIMPL;
2820 }
2821 
2822 HRESULT STDMETHODCALLTYPE CShellBrowser::_MaySaveChanges()
2823 {
2824     return E_NOTIMPL;
2825 }
2826 
2827 HRESULT STDMETHODCALLTYPE CShellBrowser::_PauseOrResumeView(BOOL fPaused)
2828 {
2829     return E_NOTIMPL;
2830 }
2831 
2832 HRESULT STDMETHODCALLTYPE CShellBrowser::_DisableModeless()
2833 {
2834     return E_NOTIMPL;
2835 }
2836 
2837 HRESULT STDMETHODCALLTYPE CShellBrowser::_NavigateToPidl(LPCITEMIDLIST pidl, DWORD grfHLNF, DWORD dwFlags)
2838 {
2839     return E_NOTIMPL;
2840 }
2841 
2842 HRESULT STDMETHODCALLTYPE CShellBrowser::_TryShell2Rename(IShellView *psv, LPCITEMIDLIST pidlNew)
2843 {
2844     return E_NOTIMPL;
2845 }
2846 
2847 HRESULT STDMETHODCALLTYPE CShellBrowser::_SwitchActivationNow()
2848 {
2849     return E_NOTIMPL;
2850 }
2851 
2852 HRESULT STDMETHODCALLTYPE CShellBrowser::_ExecChildren(IUnknown *punkBar, BOOL fBroadcast,
2853     const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
2854 {
2855     return E_NOTIMPL;
2856 }
2857 
2858 HRESULT STDMETHODCALLTYPE CShellBrowser::_SendChildren(
2859     HWND hwndBar, BOOL fBroadcast, UINT uMsg, WPARAM wParam, LPARAM lParam)
2860 {
2861     return E_NOTIMPL;
2862 }
2863 
2864 HRESULT STDMETHODCALLTYPE CShellBrowser::GetFolderSetData(struct tagFolderSetData *pfsd)
2865 {
2866     return E_NOTIMPL;
2867 }
2868 
2869 HRESULT STDMETHODCALLTYPE CShellBrowser::_OnFocusChange(UINT itb)
2870 {
2871     return E_NOTIMPL;
2872 }
2873 
2874 HRESULT STDMETHODCALLTYPE CShellBrowser::v_ShowHideChildWindows(BOOL fChildOnly)
2875 {
2876     return E_NOTIMPL;
2877 }
2878 
2879 UINT STDMETHODCALLTYPE CShellBrowser::_get_itbLastFocus()
2880 {
2881     return 0;
2882 }
2883 
2884 HRESULT STDMETHODCALLTYPE CShellBrowser::_put_itbLastFocus(UINT itbLastFocus)
2885 {
2886     return E_NOTIMPL;
2887 }
2888 
2889 HRESULT STDMETHODCALLTYPE CShellBrowser::_UIActivateView(UINT uState)
2890 {
2891     return E_NOTIMPL;
2892 }
2893 
2894 HRESULT STDMETHODCALLTYPE CShellBrowser::_GetViewBorderRect(RECT *prc)
2895 {
2896     return E_NOTIMPL;
2897 }
2898 
2899 HRESULT STDMETHODCALLTYPE CShellBrowser::_UpdateViewRectSize()
2900 {
2901     return E_NOTIMPL;
2902 }
2903 
2904 HRESULT STDMETHODCALLTYPE CShellBrowser::_ResizeNextBorder(UINT itb)
2905 {
2906     return E_NOTIMPL;
2907 }
2908 
2909 HRESULT STDMETHODCALLTYPE CShellBrowser::_ResizeView()
2910 {
2911     return E_NOTIMPL;
2912 }
2913 
2914 HRESULT STDMETHODCALLTYPE CShellBrowser::_GetEffectiveClientArea(LPRECT lprectBorder, HMONITOR hmon)
2915 {
2916     return E_NOTIMPL;
2917 }
2918 
2919 IStream *STDMETHODCALLTYPE CShellBrowser::v_GetViewStream(LPCITEMIDLIST pidl, DWORD grfMode, LPCWSTR pwszName)
2920 {
2921     return NULL;
2922 }
2923 
2924 LRESULT STDMETHODCALLTYPE CShellBrowser::ForwardViewMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
2925 {
2926     return 0;
2927 }
2928 
2929 HRESULT STDMETHODCALLTYPE CShellBrowser::SetAcceleratorMenu(HACCEL hacc)
2930 {
2931     return E_NOTIMPL;
2932 }
2933 
2934 int STDMETHODCALLTYPE CShellBrowser::_GetToolbarCount()
2935 {
2936     return 0;
2937 }
2938 
2939 LPTOOLBARITEM STDMETHODCALLTYPE CShellBrowser::_GetToolbarItem(int itb)
2940 {
2941     return NULL;
2942 }
2943 
2944 HRESULT STDMETHODCALLTYPE CShellBrowser::_SaveToolbars(IStream *pstm)
2945 {
2946     return E_NOTIMPL;
2947 }
2948 
2949 HRESULT STDMETHODCALLTYPE CShellBrowser::_LoadToolbars(IStream *pstm)
2950 {
2951     return E_NOTIMPL;
2952 }
2953 
2954 HRESULT STDMETHODCALLTYPE CShellBrowser::_CloseAndReleaseToolbars(BOOL fClose)
2955 {
2956     return E_NOTIMPL;
2957 }
2958 
2959 HRESULT STDMETHODCALLTYPE CShellBrowser::v_MayGetNextToolbarFocus(
2960     LPMSG lpMsg, UINT itbNext, int citb, LPTOOLBARITEM *pptbi, HWND *phwnd)
2961 {
2962     return E_NOTIMPL;
2963 }
2964 
2965 HRESULT STDMETHODCALLTYPE CShellBrowser::_ResizeNextBorderHelper(UINT itb, BOOL bUseHmonitor)
2966 {
2967     return E_NOTIMPL;
2968 }
2969 
2970 UINT STDMETHODCALLTYPE CShellBrowser::_FindTBar(IUnknown *punkSrc)
2971 {
2972     return 0;
2973 }
2974 
2975 HRESULT STDMETHODCALLTYPE CShellBrowser::_SetFocus(LPTOOLBARITEM ptbi, HWND hwnd, LPMSG lpMsg)
2976 {
2977     return E_NOTIMPL;
2978 }
2979 
2980 HRESULT STDMETHODCALLTYPE CShellBrowser::v_MayTranslateAccelerator(MSG *pmsg)
2981 {
2982     for (int i = 0; i < 3; i++)
2983     {
2984         if (IUnknown_TranslateAcceleratorIO(fClientBars[i].clientBar, pmsg) == S_OK)
2985             return S_OK;
2986     }
2987 
2988     if (!fCurrentShellView)
2989         return S_FALSE;
2990 
2991     return fCurrentShellView->TranslateAcceleratorW(pmsg);
2992 }
2993 
2994 HRESULT STDMETHODCALLTYPE CShellBrowser::_GetBorderDWHelper(IUnknown *punkSrc, LPRECT lprectBorder, BOOL bUseHmonitor)
2995 {
2996     return E_NOTIMPL;
2997 }
2998 
2999 HRESULT STDMETHODCALLTYPE CShellBrowser::v_CheckZoneCrossing(LPCITEMIDLIST pidl)
3000 {
3001     return E_NOTIMPL;
3002 }
3003 
3004 HRESULT STDMETHODCALLTYPE CShellBrowser::GoBack()
3005 {
3006     CComPtr<ITravelLog> travelLog;
3007     HRESULT hResult = GetTravelLog(&travelLog);
3008     if (FAILED_UNEXPECTEDLY(hResult))
3009         return hResult;
3010     return travelLog->Travel(static_cast<IDropTarget *>(this), TLOG_BACK);
3011 }
3012 
3013 HRESULT STDMETHODCALLTYPE CShellBrowser::GoForward()
3014 {
3015     CComPtr<ITravelLog> travelLog;
3016     HRESULT hResult = GetTravelLog(&travelLog);
3017     if (FAILED_UNEXPECTEDLY(hResult))
3018         return hResult;
3019     return travelLog->Travel(static_cast<IDropTarget *>(this), TLOG_FORE);
3020 }
3021 
3022 HRESULT STDMETHODCALLTYPE CShellBrowser::GoHome()
3023 {
3024     return E_NOTIMPL;
3025 }
3026 
3027 HRESULT STDMETHODCALLTYPE CShellBrowser::GoSearch()
3028 {
3029     return E_NOTIMPL;
3030 }
3031 
3032 HRESULT STDMETHODCALLTYPE CShellBrowser::Navigate(BSTR URL, VARIANT *Flags,
3033     VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
3034 {
3035     CComHeapPtr<ITEMIDLIST> pidl;
3036     HRESULT hResult;
3037     CComPtr<IShellFolder> pDesktop;
3038 
3039     hResult = SHGetDesktopFolder(&pDesktop);
3040     if (FAILED_UNEXPECTEDLY(hResult))
3041         return hResult;
3042     hResult = pDesktop->ParseDisplayName(NULL, NULL, URL, NULL, &pidl, NULL);
3043     if (FAILED_UNEXPECTEDLY(hResult))
3044         return hResult;
3045     return BrowseObject(pidl, 1);
3046 }
3047 
3048 HRESULT STDMETHODCALLTYPE CShellBrowser::Refresh()
3049 {
3050     VARIANT                                 level;
3051 
3052     V_VT(&level) = VT_I4;
3053     V_I4(&level) = 4;
3054     return Refresh2(&level);
3055 }
3056 
3057 HRESULT STDMETHODCALLTYPE CShellBrowser::Refresh2(VARIANT *Level)
3058 {
3059     CComPtr<IOleCommandTarget>              oleCommandTarget;
3060     HRESULT                                 hResult;
3061 
3062     hResult = fCurrentShellView->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
3063     if (FAILED_UNEXPECTEDLY(hResult))
3064         return hResult;
3065     return oleCommandTarget->Exec(NULL, 22, 1, Level, NULL);
3066 }
3067 
3068 HRESULT STDMETHODCALLTYPE CShellBrowser::Stop()
3069 {
3070     return E_NOTIMPL;
3071 }
3072 
3073 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Application(IDispatch **ppDisp)
3074 {
3075     return E_NOTIMPL;
3076 }
3077 
3078 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Parent(IDispatch **ppDisp)
3079 {
3080     return E_NOTIMPL;
3081 }
3082 
3083 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Container(IDispatch **ppDisp)
3084 {
3085     return E_NOTIMPL;
3086 }
3087 
3088 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Document(IDispatch **ppDisp)
3089 {
3090     return E_NOTIMPL;
3091 }
3092 
3093 HRESULT STDMETHODCALLTYPE CShellBrowser::get_TopLevelContainer(VARIANT_BOOL *pBool)
3094 {
3095     return E_NOTIMPL;
3096 }
3097 
3098 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Type(BSTR *Type)
3099 {
3100     return E_NOTIMPL;
3101 }
3102 #ifdef __exdisp_h__
3103 #define long LONG
3104 #endif
3105 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Left(long *pl)
3106 {
3107     return E_NOTIMPL;
3108 }
3109 
3110 HRESULT STDMETHODCALLTYPE CShellBrowser::put_Left(long Left)
3111 {
3112     return E_NOTIMPL;
3113 }
3114 
3115 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Top(long *pl)
3116 {
3117     return E_NOTIMPL;
3118 }
3119 
3120 HRESULT STDMETHODCALLTYPE CShellBrowser::put_Top(long Top)
3121 {
3122     return E_NOTIMPL;
3123 }
3124 
3125 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Width(long *pl)
3126 {
3127     return E_NOTIMPL;
3128 }
3129 
3130 HRESULT STDMETHODCALLTYPE CShellBrowser::put_Width(long Width)
3131 {
3132     return E_NOTIMPL;
3133 }
3134 
3135 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Height(long *pl)
3136 {
3137     return E_NOTIMPL;
3138 }
3139 
3140 HRESULT STDMETHODCALLTYPE CShellBrowser::put_Height(long Height)
3141 {
3142     return E_NOTIMPL;
3143 }
3144 #ifdef __exdisp_h__
3145 #undef long
3146 #endif
3147 HRESULT STDMETHODCALLTYPE CShellBrowser::get_LocationName(BSTR *LocationName)
3148 {
3149     return E_NOTIMPL;
3150 }
3151 
3152 HRESULT STDMETHODCALLTYPE CShellBrowser::get_LocationURL(BSTR *LocationURL)
3153 {
3154     return E_NOTIMPL;
3155 }
3156 
3157 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Busy(VARIANT_BOOL *pBool)
3158 {
3159     return E_NOTIMPL;
3160 }
3161 
3162 HRESULT STDMETHODCALLTYPE CShellBrowser::Quit()
3163 {
3164     return E_NOTIMPL;
3165 }
3166 
3167 HRESULT STDMETHODCALLTYPE CShellBrowser::ClientToWindow(int *pcx, int *pcy)
3168 {
3169     return E_NOTIMPL;
3170 }
3171 
3172 HRESULT STDMETHODCALLTYPE CShellBrowser::PutProperty(BSTR Property, VARIANT vtValue)
3173 {
3174     return E_NOTIMPL;
3175 }
3176 
3177 HRESULT STDMETHODCALLTYPE CShellBrowser::GetProperty(BSTR Property, VARIANT *pvtValue)
3178 {
3179     return E_NOTIMPL;
3180 }
3181 
3182 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Name(BSTR *Name)
3183 {
3184     return E_NOTIMPL;
3185 }
3186 
3187 HRESULT STDMETHODCALLTYPE CShellBrowser::get_HWND(SHANDLE_PTR *pHWND)
3188 {
3189     return E_NOTIMPL;
3190 }
3191 
3192 HRESULT STDMETHODCALLTYPE CShellBrowser::get_FullName(BSTR *FullName)
3193 {
3194     return E_NOTIMPL;
3195 }
3196 
3197 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Path(BSTR *Path)
3198 {
3199     return E_NOTIMPL;
3200 }
3201 
3202 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Visible(VARIANT_BOOL *pBool)
3203 {
3204     return E_NOTIMPL;
3205 }
3206 
3207 HRESULT STDMETHODCALLTYPE CShellBrowser::put_Visible(VARIANT_BOOL Value)
3208 {
3209     return E_NOTIMPL;
3210 }
3211 
3212 HRESULT STDMETHODCALLTYPE CShellBrowser::get_StatusBar(VARIANT_BOOL *pBool)
3213 {
3214     return E_NOTIMPL;
3215 }
3216 
3217 HRESULT STDMETHODCALLTYPE CShellBrowser::put_StatusBar(VARIANT_BOOL Value)
3218 {
3219     return E_NOTIMPL;
3220 }
3221 
3222 HRESULT STDMETHODCALLTYPE CShellBrowser::get_StatusText(BSTR *StatusText)
3223 {
3224     return E_NOTIMPL;
3225 }
3226 
3227 HRESULT STDMETHODCALLTYPE CShellBrowser::put_StatusText(BSTR StatusText)
3228 {
3229     return E_NOTIMPL;
3230 }
3231 
3232 HRESULT STDMETHODCALLTYPE CShellBrowser::get_ToolBar(int *Value)
3233 {
3234     return E_NOTIMPL;
3235 }
3236 
3237 HRESULT STDMETHODCALLTYPE CShellBrowser::put_ToolBar(int Value)
3238 {
3239     return E_NOTIMPL;
3240 }
3241 
3242 HRESULT STDMETHODCALLTYPE CShellBrowser::get_MenuBar(VARIANT_BOOL *Value)
3243 {
3244     return E_NOTIMPL;
3245 }
3246 
3247 HRESULT STDMETHODCALLTYPE CShellBrowser::put_MenuBar(VARIANT_BOOL Value)
3248 {
3249     return E_NOTIMPL;
3250 }
3251 
3252 HRESULT STDMETHODCALLTYPE CShellBrowser::get_FullScreen(VARIANT_BOOL *pbFullScreen)
3253 {
3254     return E_NOTIMPL;
3255 }
3256 
3257 HRESULT STDMETHODCALLTYPE CShellBrowser::put_FullScreen(VARIANT_BOOL bFullScreen)
3258 {
3259     return E_NOTIMPL;
3260 }
3261 
3262 HRESULT STDMETHODCALLTYPE CShellBrowser::Navigate2(VARIANT *URL, VARIANT *Flags,
3263     VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
3264 {
3265     LPITEMIDLIST pidl = NULL;
3266     HRESULT hResult;
3267     // called from drive combo box to navigate to a directory
3268     // Also called by search band to display shell results folder view
3269 
3270     if (V_VT(URL) == VT_BSTR)
3271     {
3272         return this->Navigate(V_BSTR(URL), Flags, TargetFrameName, PostData, Headers);
3273     }
3274     if (V_VT(URL) == (VT_ARRAY | VT_UI1))
3275     {
3276         if (V_ARRAY(URL)->cDims != 1 || V_ARRAY(URL)->cbElements != 1)
3277             return E_INVALIDARG;
3278 
3279         pidl = static_cast<LPITEMIDLIST>(V_ARRAY(URL)->pvData);
3280     }
3281     hResult = BrowseToPIDL(pidl, BTP_UPDATE_CUR_HISTORY | BTP_UPDATE_NEXT_HISTORY);
3282     if (FAILED_UNEXPECTEDLY(hResult))
3283         return hResult;
3284     return S_OK;
3285 }
3286 
3287 HRESULT STDMETHODCALLTYPE CShellBrowser::QueryStatusWB(OLECMDID cmdID, OLECMDF *pcmdf)
3288 {
3289     return E_NOTIMPL;
3290 }
3291 
3292 HRESULT STDMETHODCALLTYPE CShellBrowser::ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt,
3293     VARIANT *pvaIn, VARIANT *pvaOut)
3294 {
3295     return E_NOTIMPL;
3296 }
3297 
3298 HRESULT STDMETHODCALLTYPE CShellBrowser::ShowBrowserBar(VARIANT *pvaClsid, VARIANT *pvarShow, VARIANT *pvarSize)
3299 {
3300     CLSID                                   classID;
3301     bool                                    vertical;
3302 
3303     // called to show search bar
3304     if (V_VT(pvaClsid) != VT_BSTR)
3305         return E_INVALIDARG;
3306     CLSIDFromString(V_BSTR(pvaClsid), &classID);
3307     // TODO: properly compute the value of vertical
3308     vertical = true;
3309     return ShowBand(classID, vertical);
3310 }
3311 
3312 HRESULT STDMETHODCALLTYPE CShellBrowser::get_ReadyState(READYSTATE *plReadyState)
3313 {
3314     return E_NOTIMPL;
3315 }
3316 
3317 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Offline(VARIANT_BOOL *pbOffline)
3318 {
3319     return E_NOTIMPL;
3320 }
3321 
3322 HRESULT STDMETHODCALLTYPE CShellBrowser::put_Offline(VARIANT_BOOL bOffline)
3323 {
3324     return E_NOTIMPL;
3325 }
3326 
3327 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Silent(VARIANT_BOOL *pbSilent)
3328 {
3329     return E_NOTIMPL;
3330 }
3331 
3332 HRESULT STDMETHODCALLTYPE CShellBrowser::put_Silent(VARIANT_BOOL bSilent)
3333 {
3334     return E_NOTIMPL;
3335 }
3336 
3337 HRESULT STDMETHODCALLTYPE CShellBrowser::get_RegisterAsBrowser(VARIANT_BOOL *pbRegister)
3338 {
3339     return E_NOTIMPL;
3340 }
3341 
3342 HRESULT STDMETHODCALLTYPE CShellBrowser::put_RegisterAsBrowser(VARIANT_BOOL bRegister)
3343 {
3344     return E_NOTIMPL;
3345 }
3346 
3347 HRESULT STDMETHODCALLTYPE CShellBrowser::get_RegisterAsDropTarget(VARIANT_BOOL *pbRegister)
3348 {
3349     return E_NOTIMPL;
3350 }
3351 
3352 HRESULT STDMETHODCALLTYPE CShellBrowser::put_RegisterAsDropTarget(VARIANT_BOOL bRegister)
3353 {
3354     return E_NOTIMPL;
3355 }
3356 
3357 HRESULT STDMETHODCALLTYPE CShellBrowser::get_TheaterMode(VARIANT_BOOL *pbRegister)
3358 {
3359     return E_NOTIMPL;
3360 }
3361 
3362 HRESULT STDMETHODCALLTYPE CShellBrowser::put_TheaterMode(VARIANT_BOOL bRegister)
3363 {
3364     return E_NOTIMPL;
3365 }
3366 
3367 HRESULT STDMETHODCALLTYPE CShellBrowser::get_AddressBar(VARIANT_BOOL *Value)
3368 {
3369     return E_NOTIMPL;
3370 }
3371 
3372 HRESULT STDMETHODCALLTYPE CShellBrowser::put_AddressBar(VARIANT_BOOL Value)
3373 {
3374     return E_NOTIMPL;
3375 }
3376 
3377 HRESULT STDMETHODCALLTYPE CShellBrowser::get_Resizable(VARIANT_BOOL *Value)
3378 {
3379     return E_NOTIMPL;
3380 }
3381 
3382 HRESULT STDMETHODCALLTYPE CShellBrowser::put_Resizable(VARIANT_BOOL Value)
3383 {
3384     return E_NOTIMPL;
3385 }
3386 
3387 HRESULT STDMETHODCALLTYPE CShellBrowser::FindWindowByIndex(DWORD dwID, IUnknown **ppunk)
3388 {
3389     return E_NOTIMPL;
3390 }
3391 
3392 HRESULT STDMETHODCALLTYPE CShellBrowser::GetWindowData(IStream *pStream, LPWINDOWDATA pWinData)
3393 {
3394     if (pWinData == NULL)
3395         return E_POINTER;
3396 
3397     pWinData->dwWindowID = -1;
3398     pWinData->uiCP = 0;
3399     pWinData->pidl = ILClone(fCurrentDirectoryPIDL);
3400     pWinData->lpszUrl = NULL;
3401     pWinData->lpszUrlLocation = NULL;
3402     pWinData->lpszTitle = NULL;
3403     return S_OK;
3404 }
3405 
3406 HRESULT STDMETHODCALLTYPE CShellBrowser::LoadHistoryPosition(LPWSTR pszUrlLocation, DWORD dwPosition)
3407 {
3408     return E_NOTIMPL;
3409 }
3410 
3411 HRESULT STDMETHODCALLTYPE CShellBrowser::GetClassID(CLSID *pClassID)
3412 {
3413     return E_NOTIMPL;
3414 }
3415 
3416 HRESULT STDMETHODCALLTYPE CShellBrowser::LoadHistory(IStream *pStream, IBindCtx *pbc)
3417 {
3418     CComPtr<IPersistHistory>                viewPersistHistory;
3419     CComPtr<IOleObject>                     viewHistoryObject;
3420     persistState                            oldState;
3421     ULONG                                   numRead;
3422     LPITEMIDLIST                            pidl;
3423     HRESULT                                 hResult;
3424 
3425     hResult = pStream->Read(&oldState, sizeof(oldState), &numRead);
3426     if (FAILED_UNEXPECTEDLY(hResult))
3427         return hResult;
3428     if (numRead != sizeof(oldState) || oldState.dwSize != sizeof(oldState))
3429         return E_FAIL;
3430     if (oldState.browseType != 2)
3431         return E_FAIL;
3432     pidl = static_cast<LPITEMIDLIST>(CoTaskMemAlloc(oldState.pidlSize));
3433     if (pidl == NULL)
3434         return E_OUTOFMEMORY;
3435     hResult = pStream->Read(pidl, oldState.pidlSize, &numRead);
3436     if (FAILED_UNEXPECTEDLY(hResult))
3437     {
3438         ILFree(pidl);
3439         return hResult;
3440     }
3441     if (numRead != oldState.pidlSize)
3442     {
3443         ILFree(pidl);
3444         return E_FAIL;
3445     }
3446     hResult = CoCreateInstance(oldState.persistClass, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER,
3447         IID_PPV_ARG(IOleObject, &viewHistoryObject));
3448     fHistoryObject = viewHistoryObject;
3449     fHistoryStream = pStream;
3450     fHistoryBindContext = pbc;
3451     hResult = BrowseToPIDL(pidl, BTP_DONT_UPDATE_HISTORY);
3452     fHistoryObject = NULL;
3453     fHistoryStream = NULL;
3454     fHistoryBindContext = NULL;
3455     ILFree(pidl);
3456     if (FAILED_UNEXPECTEDLY(hResult))
3457         return hResult;
3458     return S_OK;
3459 }
3460 
3461 HRESULT STDMETHODCALLTYPE CShellBrowser::SaveHistory(IStream *pStream)
3462 {
3463     CComPtr<IPersistHistory>                viewPersistHistory;
3464     persistState                            newState;
3465     HRESULT                                 hResult;
3466 
3467     hResult = fCurrentShellView->GetItemObject(
3468         SVGIO_BACKGROUND, IID_PPV_ARG(IPersistHistory, &viewPersistHistory));
3469     memset(&newState, 0, sizeof(newState));
3470     newState.dwSize = sizeof(newState);
3471     newState.browseType = 2;
3472     newState.browserIndex = GetBrowserIndex();
3473     if (viewPersistHistory.p != NULL)
3474     {
3475         hResult = viewPersistHistory->GetClassID(&newState.persistClass);
3476         if (FAILED_UNEXPECTEDLY(hResult))
3477             return hResult;
3478     }
3479     newState.pidlSize = ILGetSize(fCurrentDirectoryPIDL);
3480     hResult = pStream->Write(&newState, sizeof(newState), NULL);
3481     if (FAILED_UNEXPECTEDLY(hResult))
3482         return hResult;
3483     hResult = pStream->Write(fCurrentDirectoryPIDL, newState.pidlSize, NULL);
3484     if (FAILED_UNEXPECTEDLY(hResult))
3485         return hResult;
3486     if (viewPersistHistory.p != NULL)
3487     {
3488         hResult = viewPersistHistory->SaveHistory(pStream);
3489         if (FAILED_UNEXPECTEDLY(hResult))
3490             return hResult;
3491     }
3492     return S_OK;
3493 }
3494 
3495 HRESULT STDMETHODCALLTYPE CShellBrowser::SetPositionCookie(DWORD dwPositioncookie)
3496 {
3497     return E_NOTIMPL;
3498 }
3499 
3500 HRESULT STDMETHODCALLTYPE CShellBrowser::GetPositionCookie(DWORD *pdwPositioncookie)
3501 {
3502     return E_NOTIMPL;
3503 }
3504 
3505 LRESULT CShellBrowser::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
3506 {
3507     OnCreate(reinterpret_cast<LPCREATESTRUCT> (lParam));
3508     return 0;
3509 }
3510 
3511 LRESULT CShellBrowser::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
3512 {
3513     HRESULT hr;
3514 
3515     /* The current thread is about to go down so render any IDataObject that may be left in the clipboard */
3516     OleFlushClipboard();
3517 
3518     // TODO: rip down everything
3519     {
3520         fToolbarProxy.Destroy();
3521 
3522         fCurrentShellView->DestroyViewWindow();
3523         fCurrentShellView->UIActivate(SVUIA_DEACTIVATE);
3524 
3525         for (int i = 0; i < 3; i++)
3526         {
3527             CComPtr<IDockingWindow> pdw;
3528             CComPtr<IDeskBar> bar;
3529             CComPtr<IUnknown> pBarSite;
3530             CComPtr<IDeskBarClient> pClient;
3531 
3532             if (fClientBars[i].clientBar == NULL)
3533                 continue;
3534 
3535             hr = fClientBars[i].clientBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &pdw));
3536             if (FAILED_UNEXPECTEDLY(hr))
3537                 continue;
3538 
3539             /* We should destroy our basebarsite too */
3540             hr = pdw->QueryInterface(IID_PPV_ARG(IDeskBar, &bar));
3541             if (SUCCEEDED(hr))
3542             {
3543                 hr = bar->GetClient(&pBarSite);
3544                 if (SUCCEEDED(hr) && pBarSite)
3545                 {
3546                     hr = pBarSite->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pClient));
3547                     if (SUCCEEDED(hr))
3548                         pClient->SetDeskBarSite(NULL);
3549                 }
3550             }
3551             pdw->CloseDW(0);
3552 
3553             pClient = NULL;
3554             pBarSite = NULL;
3555             pdw = NULL;
3556             bar = NULL;
3557             ReleaseCComPtrExpectZero(fClientBars[i].clientBar);
3558         }
3559         ReleaseCComPtrExpectZero(fCurrentShellView);
3560         ReleaseCComPtrExpectZero(fTravelLog);
3561 
3562         fCurrentShellFolder.Release();
3563         ILFree(fCurrentDirectoryPIDL);
3564         ::DestroyWindow(fStatusBar);
3565         DestroyMenu(fCurrentMenuBar);
3566     }
3567     PostQuitMessage(0);
3568     return 0;
3569 }
3570 
3571 LRESULT CShellBrowser::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
3572 {
3573     CComPtr<IDockingWindow>                 dockingWindow;
3574     RECT                                    availableBounds;
3575     static const INT                        excludeItems[] = {1, 1, 1, IDC_STATUSBAR, 0, 0};
3576     HRESULT                                 hResult;
3577 
3578     if (wParam != SIZE_MINIMIZED)
3579     {
3580         GetEffectiveClientRect(m_hWnd, &availableBounds, excludeItems);
3581         for (INT x = 0; x < 3; x++)
3582         {
3583             if (fClientBars[x].clientBar != NULL)
3584             {
3585                 hResult = fClientBars[x].clientBar->QueryInterface(
3586                     IID_PPV_ARG(IDockingWindow, &dockingWindow));
3587                 if (SUCCEEDED(hResult) && dockingWindow != NULL)
3588                 {
3589                     hResult = dockingWindow->ResizeBorderDW(
3590                         &availableBounds, static_cast<IDropTarget *>(this), TRUE);
3591                     break;
3592                 }
3593             }
3594         }
3595         RepositionBars();
3596     }
3597     return 1;
3598 }
3599 
3600 LRESULT CShellBrowser::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
3601 {
3602     HMENU  theMenu;
3603     LPARAM menuIndex = lParam;
3604 
3605     theMenu = reinterpret_cast<HMENU>(wParam);
3606 
3607     if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_FILE))
3608     {
3609         menuIndex = 0;
3610     }
3611     else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_EDIT))
3612     {
3613         menuIndex = 1;
3614     }
3615     else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_VIEW))
3616     {
3617         UpdateViewMenu(theMenu);
3618         menuIndex = 2;
3619     }
3620     else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_FAVORITES))
3621     {
3622         menuIndex = 3;
3623     }
3624     else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_TOOLS))
3625     {
3626         // FIXME: Remove once implemented
3627         SHEnableMenuItem(theMenu, IDM_TOOLS_MAPNETWORKDRIVE, FALSE);
3628         SHEnableMenuItem(theMenu, IDM_TOOLS_SYNCHRONIZE, FALSE);
3629         menuIndex = 4;
3630     }
3631     else if (theMenu == SHGetMenuFromID(fCurrentMenuBar, FCIDM_MENU_HELP))
3632     {
3633         menuIndex = 5;
3634     }
3635 
3636     LRESULT ret = RelayMsgToShellView(uMsg, wParam, menuIndex, bHandled);
3637 
3638     return ret;
3639 }
3640 
3641 LRESULT CShellBrowser::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
3642 {
3643     ::SetFocus(fCurrentShellViewWindow);
3644     return 0;
3645 }
3646 
3647 LRESULT CShellBrowser::RelayMsgToShellView(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
3648 {
3649     if (fCurrentShellViewWindow != NULL)
3650         return SendMessage(fCurrentShellViewWindow, uMsg, wParam, lParam);
3651     return 0;
3652 }
3653 
3654 LRESULT CShellBrowser::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
3655 {
3656     RefreshCabinetState();
3657     SHPropagateMessage(m_hWnd, uMsg, wParam, lParam, TRUE);
3658     return 0;
3659 }
3660 
3661 LRESULT CShellBrowser::OnClose(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3662 {
3663     return SendMessage(WM_CLOSE);
3664 }
3665 
3666 LRESULT CShellBrowser::OnFolderOptions(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3667 {
3668     HRESULT hResult = DoFolderOptions();
3669     if (FAILED(hResult))
3670         TRACE("DoFolderOptions failed with hResult=%08lx\n", hResult);
3671     return 0;
3672 }
3673 
3674 LRESULT CShellBrowser::OnMapNetworkDrive(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3675 {
3676 #ifndef __REACTOS__
3677     WNetConnectionDialog(m_hWnd, RESOURCETYPE_DISK);
3678 #endif /* __REACTOS__ */
3679     return 0;
3680 }
3681 
3682 LRESULT CShellBrowser::OnDisconnectNetworkDrive(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3683 {
3684     WNetDisconnectDialog(m_hWnd, RESOURCETYPE_DISK);
3685     return 0;
3686 }
3687 
3688 LRESULT CShellBrowser::OnAboutReactOS(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3689 {
3690     ShellAbout(m_hWnd, _T("ReactOS"), NULL, NULL);
3691     return 0;
3692 }
3693 
3694 LRESULT CShellBrowser::OnGoBack(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3695 {
3696     HRESULT hResult = GoBack();
3697     if (FAILED(hResult))
3698         TRACE("GoBack failed with hResult=%08lx\n", hResult);
3699     return 0;
3700 }
3701 
3702 LRESULT CShellBrowser::OnGoForward(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3703 {
3704     HRESULT hResult = GoForward();
3705     if (FAILED(hResult))
3706         TRACE("GoForward failed with hResult=%08lx\n", hResult);
3707     return 0;
3708 }
3709 
3710 LRESULT CShellBrowser::OnGoUpLevel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3711 {
3712     HRESULT hResult = NavigateToParent();
3713     if (FAILED(hResult))
3714         TRACE("NavigateToParent failed with hResult=%08lx\n", hResult);
3715     return 0;
3716 }
3717 
3718 LRESULT CShellBrowser::OnGoHome(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3719 {
3720     HRESULT hResult = GoHome();
3721     if (FAILED(hResult))
3722         TRACE("GoHome failed with hResult=%08lx\n", hResult);
3723     return 0;
3724 }
3725 
3726 LRESULT CShellBrowser::OnBackspace(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3727 {
3728     // FIXME: This does not appear to be what windows does.
3729     HRESULT hResult = NavigateToParent();
3730     if (FAILED(hResult))
3731         TRACE("NavigateToParent failed with hResult=%08lx\n", hResult);
3732     return 0;
3733 }
3734 
3735 static BOOL
3736 CreateShortcut(
3737     IN LPCWSTR pszLnkFileName,
3738     IN LPCITEMIDLIST pidl,
3739     IN LPCWSTR pszDescription OPTIONAL)
3740 {
3741     IPersistFile *pPF;
3742     IShellLinkW *pSL;
3743     HRESULT hr = CoInitialize(NULL);
3744     if (FAILED(hr))
3745         return hr;
3746 
3747     hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
3748                           IID_IShellLinkW, (LPVOID*)&pSL);
3749     if (SUCCEEDED(hr))
3750     {
3751         pSL->SetIDList(pidl);
3752 
3753         if (pszDescription)
3754             pSL->SetDescription(pszDescription);
3755 
3756         hr = pSL->QueryInterface(IID_IPersistFile, (LPVOID*)&pPF);
3757         if (SUCCEEDED(hr))
3758         {
3759             hr = pPF->Save(pszLnkFileName, TRUE);
3760             pPF->Release();
3761         }
3762         pSL->Release();
3763     }
3764 
3765     CoUninitialize();
3766 
3767     return SUCCEEDED(hr);
3768 }
3769 
3770 HRESULT GetFavsLocation(HWND hWnd, LPITEMIDLIST *pPidl)
3771 {
3772     HRESULT hr = SHGetSpecialFolderLocation(hWnd, CSIDL_FAVORITES, pPidl);
3773     if (FAILED(hr))
3774         hr = SHGetSpecialFolderLocation(hWnd, CSIDL_COMMON_FAVORITES, pPidl);
3775 
3776     return hr;
3777 }
3778 
3779 LRESULT CShellBrowser::OnAddToFavorites(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3780 {
3781     LPITEMIDLIST pidlFavs;
3782     HRESULT hr = GetFavsLocation(m_hWnd, &pidlFavs);
3783     if (FAILED_UNEXPECTEDLY(hr))
3784         return 0;
3785 
3786     SHFILEINFOW fileInfo = { NULL };
3787     if (!SHGetFileInfoW((LPCWSTR)fCurrentDirectoryPIDL, 0, &fileInfo, sizeof(fileInfo),
3788                         SHGFI_PIDL | SHGFI_DISPLAYNAME))
3789     {
3790         return 0;
3791     }
3792 
3793     WCHAR szPath[MAX_PATH];
3794     SHGetPathFromIDListW(pidlFavs, szPath);
3795     PathAppendW(szPath, fileInfo.szDisplayName);
3796     PathAddExtensionW(szPath, L".lnk");
3797 
3798     CreateShortcut(szPath, fCurrentDirectoryPIDL, NULL);
3799     return 0;
3800 }
3801 
3802 LRESULT CShellBrowser::OnOrganizeFavorites(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3803 {
3804     CComPtr<IShellFolder> psfDesktop;
3805     LPITEMIDLIST pidlFavs;
3806     HRESULT hr = GetFavsLocation(m_hWnd, &pidlFavs);
3807     if (FAILED_UNEXPECTEDLY(hr))
3808         return 0;
3809 
3810     hr = SHGetDesktopFolder(&psfDesktop);
3811     if (FAILED_UNEXPECTEDLY(hr))
3812     {
3813         ILFree(pidlFavs);
3814         return 0;
3815     }
3816 
3817     hr = SHInvokeDefaultCommand(m_hWnd, psfDesktop, pidlFavs);
3818     ILFree(pidlFavs);
3819     if (FAILED_UNEXPECTEDLY(hr))
3820         return 0;
3821 
3822     return 0;
3823 }
3824 
3825 LRESULT CShellBrowser::OnToggleStatusBarVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3826 {
3827     m_settings.fStatusBarVisible = !m_settings.fStatusBarVisible;
3828     m_settings.Save();
3829     SendMessageW(BWM_SETTINGCHANGE, 0, (LPARAM)&m_settings);
3830     return 0;
3831 }
3832 
3833 LRESULT CShellBrowser::OnToggleToolbarLock(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3834 {
3835     HRESULT hResult;
3836     hResult = IUnknown_Exec(fClientBars[BIInternetToolbar].clientBar,
3837                             CGID_PrivCITCommands, ITID_TOOLBARLOCKED, 0, NULL, NULL);
3838     return 0;
3839 }
3840 
3841 LRESULT CShellBrowser::OnToggleToolbarBandVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3842 {
3843     HRESULT hResult;
3844     hResult = IUnknown_Exec(fClientBars[BIInternetToolbar].clientBar,
3845                             CGID_PrivCITCommands, ITID_TOOLBARBANDSHOWN, 0, NULL, NULL);
3846     return 0;
3847 }
3848 
3849 LRESULT CShellBrowser::OnToggleAddressBandVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3850 {
3851     HRESULT hResult;
3852     hResult = IUnknown_Exec(fClientBars[BIInternetToolbar].clientBar,
3853                             CGID_PrivCITCommands, ITID_ADDRESSBANDSHOWN, 0, NULL, NULL);
3854     return 0;
3855 }
3856 
3857 LRESULT CShellBrowser::OnToggleLinksBandVisible(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3858 {
3859     HRESULT hResult;
3860     hResult = IUnknown_Exec(fClientBars[BIInternetToolbar].clientBar,
3861                             CGID_PrivCITCommands, ITID_LINKSBANDSHOWN, 0, NULL, NULL);
3862     return 0;
3863 }
3864 
3865 LRESULT CShellBrowser::OnToggleTextLabels(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3866 {
3867     HRESULT hResult;
3868     hResult = IUnknown_Exec(fClientBars[BIInternetToolbar].clientBar,
3869                             CGID_PrivCITCommands, ITID_TEXTLABELS, 0, NULL, NULL);
3870     return 0;
3871 }
3872 
3873 LRESULT CShellBrowser::OnToolbarCustomize(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3874 {
3875     HRESULT hResult;
3876     hResult = IUnknown_Exec(fClientBars[BIInternetToolbar].clientBar,
3877                             CGID_PrivCITCommands, ITID_CUSTOMIZEENABLED, 0, NULL, NULL);
3878     return 0;
3879 }
3880 
3881 LRESULT CShellBrowser::OnRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3882 {
3883     if (fCurrentShellView)
3884         fCurrentShellView->Refresh();
3885     return 0;
3886 }
3887 
3888 LRESULT CShellBrowser::OnGoTravel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3889 {
3890     return 0;
3891 }
3892 
3893 LRESULT CShellBrowser::OnExplorerBar(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled)
3894 {
3895     // TODO: HACK ! use the proper mechanism to show the band (i.e. pass the BSTR to basebar)
3896     if (wID >= IDM_EXPLORERBAND_BEGINCUSTOM && wID <= IDM_EXPLORERBAND_ENDCUSTOM)
3897     {
3898         MenuBandInfo *mbi;
3899         mbi = (MenuBandInfo*)DSA_GetItemPtr(menuDsa, (wID - IDM_EXPLORERBAND_BEGINCUSTOM));
3900         if (!mbi)
3901             return 0;
3902         ShowBand(mbi->barGuid, mbi->fVertical);
3903         bHandled = TRUE;
3904         return 1;
3905     }
3906     switch (wID)
3907     {
3908     case IDM_EXPLORERBAR_SEARCH:
3909         ShowBand(CLSID_FileSearchBand, true);
3910         break;
3911     case IDM_EXPLORERBAR_FOLDERS:
3912         ShowBand(CLSID_ExplorerBand, true);
3913         break;
3914     case IDM_EXPLORERBAR_HISTORY:
3915         ShowBand(CLSID_SH_HistBand, true);
3916         break;
3917     case IDM_EXPLORERBAR_FAVORITES:
3918         ShowBand(CLSID_SH_FavBand, true);
3919         break;
3920     default:
3921         WARN("Unknown id %x\n", wID);
3922     }
3923     bHandled = TRUE;
3924     return 1;
3925 }
3926 
3927 LRESULT CShellBrowser::RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
3928 {
3929     if (HIWORD(wParam) == 0 && LOWORD(wParam) < FCIDM_SHVIEWLAST && fCurrentShellViewWindow != NULL)
3930         return SendMessage(fCurrentShellViewWindow, uMsg, wParam, lParam);
3931     return 0;
3932 }
3933 
3934 LRESULT CShellBrowser::OnSettingsChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
3935 {
3936     /* Refresh child windows */
3937     ::SendMessageW(fClientBars[BIInternetToolbar].hwnd, uMsg, wParam, lParam);
3938 
3939     /* Refresh status bar */
3940     if (fStatusBar)
3941     {
3942         ::ShowWindow(fStatusBar, m_settings.fStatusBarVisible ? SW_SHOW : SW_HIDE);
3943         RepositionBars();
3944     }
3945 
3946     return 0;
3947 }
3948 
3949 LRESULT CShellBrowser::OnGetSettingsPtr(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
3950 {
3951     if (!lParam)
3952         return ERROR_INVALID_PARAMETER;
3953 
3954     *(ShellSettings**)lParam = &m_settings;
3955     return NO_ERROR;
3956 }
3957 
3958 // WM_APPCOMMAND
3959 LRESULT CShellBrowser::OnAppCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
3960 {
3961     UINT uCmd = GET_APPCOMMAND_LPARAM(lParam);
3962     switch (uCmd)
3963     {
3964         case APPCOMMAND_BROWSER_BACKWARD:
3965             GoBack();
3966             break;
3967 
3968         case APPCOMMAND_BROWSER_FORWARD:
3969             GoForward();
3970             break;
3971 
3972         default:
3973             FIXME("uCmd: %u\n", uCmd);
3974             break;
3975     }
3976     return 0;
3977 }
3978 
3979 HRESULT CShellBrowser_CreateInstance(REFIID riid, void **ppv)
3980 {
3981     return ShellObjectCreatorInit<CShellBrowser>(riid, ppv);
3982 }
3983 
3984 void CShellBrowser::RefreshCabinetState()
3985 {
3986     gCabinetState.Load();
3987     UpdateWindowTitle();
3988 }
3989 
3990 void CShellBrowser::UpdateWindowTitle()
3991 {
3992     WCHAR title[MAX_PATH];
3993     SHGDNF flags = SHGDN_FORADDRESSBAR;
3994 
3995     if (gCabinetState.fFullPathTitle)
3996         flags |= SHGDN_FORPARSING;
3997 
3998     if (SUCCEEDED(IEGetNameAndFlags(fCurrentDirectoryPIDL, flags, title, _countof(title), NULL)))
3999         SetWindowText(title);
4000 }
4001 
4002 void CShellBrowser::SaveITBarLayout()
4003 {
4004     if (!gCabinetState.fSaveLocalView)
4005         return;
4006 #if 0 // If CDesktopBrowser aggregates us, skip saving
4007     FOLDERSETTINGS fs;
4008     if (fCurrentShellView && SUCCEEDED(fCurrentShellView->GetCurrentInfo(&fs)) && (fs.fFlags & FWF_DESKTOP))
4009         return;
4010 #endif
4011 
4012     CComPtr<IPersistStreamInit> pPSI;
4013     CComPtr<IStream> pITBarStream;
4014     if (!fClientBars[BIInternetToolbar].clientBar.p)
4015         return;
4016     HRESULT hr = fClientBars[BIInternetToolbar].clientBar->QueryInterface(IID_PPV_ARG(IPersistStreamInit, &pPSI));
4017     if (FAILED(hr))
4018         return;
4019     if (FAILED(hr = CInternetToolbar::GetStream(ITBARSTREAM_EXPLORER, STGM_WRITE, &pITBarStream)))
4020         return;
4021     pPSI->Save(pITBarStream, TRUE);
4022 }
4023