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