commonsb.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 58k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "priv.h"
  2. #include "sccls.h"
  3. #include "resource.h"
  4. #include "commonsb.h"
  5. #include "inpobj.h"
  6. #include "multimon.h"
  7. #include "mmhelper.h"
  8. #include "dockbar.h"        // for DRAG_MOVE etc.
  9. #include "mluisupp.h"
  10. #define DM_HTTPEQUIV        TF_SHDNAVIGATE
  11. #define DM_NAV              TF_SHDNAVIGATE
  12. #define DM_ZONE             TF_SHDNAVIGATE
  13. #define DM_IEDDE            DM_TRACE
  14. #define DM_CANCELMODE       0
  15. #define DM_UIWINDOW         0
  16. #define DM_ENABLEMODELESS   TF_SHDNAVIGATE
  17. #define DM_EXPLORERMENU     0
  18. #define DM_BACKFORWARD      0
  19. #define DM_PROTOCOL         0
  20. #define DM_ITBAR            0
  21. #define DM_STARTUP          0
  22. #define DM_AUTOLIFE         0
  23. #define DM_PALETTE          0
  24. #define DM_PERSIST          0       // trace IPS::Load, ::Save, etc.
  25. #define DM_VIEWSTREAM       DM_TRACE
  26. #define DM_FOCUS            0
  27. #define DM_FOCUS2           0           // like DM_FOCUS, but verbose
  28. #define DM_ACCELERATOR      0
  29. #define TF_PERF             TF_CUSTOM2
  30. #define DM_MISC             DM_TRACE    // misc/tmp stuff
  31. PZONEICONNAMECACHE g_pZoneIconNameCache = NULL;
  32. DWORD g_dwZoneCount = 0;
  33. //***   create, ctor/init/dtor, QI/AddRef/Release {
  34. // So CDesktopBrowser can access us...
  35. HRESULT CCommonBrowser_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  36. {
  37.     CCommonBrowser *pcb = new CCommonBrowser(punkOuter);
  38.     if (pcb)
  39.     {
  40.         *ppunk = pcb->_GetInner();
  41.         return S_OK;
  42.     }
  43.     *ppunk = NULL;
  44.     return E_OUTOFMEMORY;
  45. }
  46. CCommonBrowser::CCommonBrowser(IUnknown* punkAgg) :
  47.    CAggregatedUnknown(punkAgg),
  48.    _cRef(1)
  49. {
  50.     // cache "out" pointers
  51.     _QueryOuterInterface(IID_IBrowserService2, (LPVOID*)&_pbsOuter);
  52.     // warning: can't call SUPER/_psbInner until _Initialize has been called
  53.     // (since that's what does the aggregation)
  54. }
  55. HRESULT CCommonBrowser::_Initialize(HWND hwnd, IUnknown *pauto)
  56. {
  57.     IUnknown* punk;
  58.     //
  59.     //  I hope we have an IBrowserService2 to talk to.
  60.     //
  61.     if (!_pbsOuter) {
  62.         return E_FAIL;
  63.     }
  64.     HRESULT hres = CoCreateInstance(CLSID_CBaseBrowser, SAFECAST(this, IShellBrowser*), CLSCTX_INPROC_SERVER, IID_IUnknown, (LPVOID*)&punk);
  65.     if (EVAL(SUCCEEDED(hres))) {
  66.         hres = SetInner(punk);  // paired w/ Release in outer (TBS::Release)
  67.         if (EVAL(SUCCEEDED(hres))) {
  68.             hres = _pbsInner->_Initialize(hwnd, pauto);
  69.             ASSERT(SUCCEEDED(hres));
  70.         }
  71.     }
  72.     EVAL(FDSA_Initialize(SIZEOF(TOOLBARITEM), ITB_CGROW, &_fdsaTBar, _aTBar, ITB_CSTATIC));
  73.     return hres;
  74. }
  75. CCommonBrowser::~CCommonBrowser()
  76. {
  77.     // First, release outer interfaces, since the
  78.     // outer object is in the process of destroying itself.
  79.     RELEASEOUTERINTERFACE(_pbsOuter);
  80.     // Second, release the inner guy so it knows to clean up
  81.     // Note: this should come third, but the inner guy's cached
  82.     // outer interfaces are already dead (they point to our
  83.     // aggregator) and we don't have the compiler to fix up
  84.     // the vtables for us...
  85.     // (I have no idea what that comment means -raymondc)
  86.     RELEASEINNERINTERFACE(_GetOuter(), _pbsInner);
  87.     RELEASEINNERINTERFACE(_GetOuter(), _psbInner);
  88.     RELEASEINNERINTERFACE(_GetOuter(), _pdtInner);
  89.     RELEASEINNERINTERFACE(_GetOuter(), _pspInner);
  90.     RELEASEINNERINTERFACE(_GetOuter(), _pctInner);
  91.     RELEASEINNERINTERFACE(_GetOuter(), _piosInner);   // BUGBUG split: nuke this
  92.     // _punkInner goes last because it is the one that really destroys
  93.     // the inner.
  94.     ATOMICRELEASE(_punkInner);   // paired w/ CCI aggregation
  95.     
  96.     // Last, clean up our stuff. Better make sure
  97.     // none of the below use any of the above vtables...
  98.     _CloseAndReleaseToolbars(FALSE);
  99.     FDSA_Destroy(&_fdsaTBar);
  100. }
  101. HRESULT CCommonBrowser::SetAcceleratorMenu(HACCEL hacc) 
  102. {
  103.     if(_hacc)
  104.         DestroyAcceleratorTable(_hacc);
  105.     _hacc = hacc;
  106.     return S_OK;
  107. }
  108. HRESULT CCommonBrowser::v_InternalQueryInterface(REFIID riid, LPVOID * ppvObj)
  109. {
  110.     static const QITAB qit[] = {
  111.         // perf: last tuned 980728
  112.         QITABENT(CCommonBrowser, IServiceProvider),     // IID_IServiceProvider
  113.         QITABENT(CCommonBrowser, IOleCommandTarget),    // IID_IServiceProvider
  114.         QITABENTMULTI(CCommonBrowser, IBrowserService, IBrowserService2), // IID_IServiceProvider
  115.         QITABENT(CCommonBrowser, IShellBrowser),        // IID_IServiceProvider
  116.         QITABENT(CCommonBrowser, IBrowserService2),     // IID_IServiceProvider
  117.         QITABENTMULTI(CCommonBrowser, IOleWindow, IShellBrowser),     // rare IID_IServiceProvider
  118.         QITABENT(CCommonBrowser, IDockingWindowSite),   // rare IID_IDockingWindowSite
  119.         QITABENT(CCommonBrowser, IDockingWindowFrame),  // rare IID_IDockingWindowFrame
  120.         QITABENT(CCommonBrowser, IInputObjectSite),     // rare IID_IInputObjectSite
  121.         QITABENT(CCommonBrowser, IDropTarget),          // rare IID_IDropTarget
  122.         { 0 },
  123.     };
  124.     HRESULT hres = QISearch(this, qit, riid, ppvObj);
  125.     if (FAILED(hres))
  126.     {
  127.         if (_punkInner)
  128.         {
  129.             return _punkInner->QueryInterface(riid, ppvObj);
  130.         }
  131.     }
  132.     return hres;
  133. }
  134. //
  135. //  Accept punk as our inner (contained) object to which we forward a lot of
  136. //  things we don't want to deal with.
  137. //
  138. //  Warning!  The refcount on the punk is *transferred* to us through this
  139. //  method.  This is contrary to OLE convention.
  140. //
  141. HRESULT CCommonBrowser::SetInner(IUnknown* punk)
  142. {
  143.     HRESULT hres;
  144.     //
  145.     //  It's okay to shove the interesting things directly into
  146.     //  our members, because if any of them go wrong, we fail
  147.     //  the _Initialize and our destructor will release them all.
  148. #define INNERCACHE(iid, p) do { 
  149.     hres = SHQueryInnerInterface(_GetOuter(), punk, iid, (LPVOID*)&p); 
  150.     if (!EVAL(SUCCEEDED(hres))) return E_FAIL; 
  151.     } while (0)
  152.     // Do not AddRef; the caller is tranferring the ref to us
  153.     _punkInner = punk;
  154.     INNERCACHE(IID_IBrowserService2, _pbsInner);
  155.     INNERCACHE(IID_IShellBrowser, _psbInner);
  156.     INNERCACHE(IID_IDropTarget, _pdtInner);
  157.     INNERCACHE(IID_IServiceProvider, _pspInner);
  158.     INNERCACHE(IID_IOleCommandTarget, _pctInner);
  159.     INNERCACHE(IID_IInputObjectSite, _piosInner);
  160. #undef INNERCACHE
  161.     _pbsInner->GetBaseBrowserData(&_pbbd);
  162.     if (!EVAL(_pbbd)) return E_FAIL; // o.w. zillions-o-GPFs on _pbbd->foo
  163.     return S_OK;
  164. }
  165. // }
  166. // {
  167. #define CALL_INNER(_result, _function, _arglist, _args) 
  168. _result CCommonBrowser:: _function _arglist { return _pbsInner-> _function _args ; }                                            
  169. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  170.  
  171. // *** IBrowserService2 specific methods ***
  172. CALL_INNER_HRESULT(GetParentSite, (  IOleInPlaceSite** ppipsite), (  ppipsite) );
  173. CALL_INNER_HRESULT(SetTitle, ( IShellView* psv, LPCWSTR pszName), ( psv, pszName) );
  174. CALL_INNER_HRESULT(GetTitle, ( IShellView* psv, LPWSTR pszName, DWORD cchName), ( psv, pszName, cchName) );
  175. CALL_INNER_HRESULT(GetOleObject, (  IOleObject** ppobjv), (  ppobjv) );
  176. // think about this one.. I'm not sure we want to expose this -- Chee
  177. // BUGBUG:: Yep soon we should have interface instead.
  178. // My impression is that we won't document this whole interface???
  179. CALL_INNER_HRESULT(GetTravelLog, ( ITravelLog** pptl), ( pptl) );
  180. CALL_INNER_HRESULT(ShowControlWindow, ( UINT id, BOOL fShow), ( id, fShow) );
  181. CALL_INNER_HRESULT(IsControlWindowShown, ( UINT id, BOOL *pfShown), ( id, pfShown) );
  182. CALL_INNER_HRESULT(IEGetDisplayName, ( LPCITEMIDLIST pidl, LPWSTR pwszName, UINT uFlags), ( pidl, pwszName, uFlags) );
  183. CALL_INNER_HRESULT(IEParseDisplayName, ( UINT uiCP, LPCWSTR pwszPath, LPITEMIDLIST * ppidlOut), ( uiCP, pwszPath, ppidlOut) );
  184. CALL_INNER_HRESULT(DisplayParseError, ( HRESULT hres, LPCWSTR pwszPath), ( hres, pwszPath) );
  185. CALL_INNER_HRESULT(NavigateToPidl, ( LPCITEMIDLIST pidl, DWORD grfHLNF), ( pidl, grfHLNF) );
  186. CALL_INNER_HRESULT(SetNavigateState, ( BNSTATE bnstate), ( bnstate) );
  187. CALL_INNER_HRESULT(GetNavigateState,  ( BNSTATE *pbnstate), ( pbnstate) );
  188. CALL_INNER_HRESULT(NotifyRedirect,  (  IShellView* psv, LPCITEMIDLIST pidl, BOOL *pfDidBrowse), (  psv, pidl, pfDidBrowse) );
  189. CALL_INNER_HRESULT(UpdateWindowList,  (), () );
  190. CALL_INNER_HRESULT(UpdateBackForwardState,  (), () );
  191. CALL_INNER_HRESULT(SetFlags, ( DWORD dwFlags, DWORD dwFlagMask), ( dwFlags, dwFlagMask) );
  192. CALL_INNER_HRESULT(GetFlags, ( DWORD *pdwFlags), ( pdwFlags) );
  193. // Tells if it can navigate now or not.
  194. CALL_INNER_HRESULT(CanNavigateNow,  (), () );
  195. CALL_INNER_HRESULT(GetPidl,  ( LPITEMIDLIST *ppidl), ( ppidl) );
  196. CALL_INNER_HRESULT(SetReferrer,  ( LPITEMIDLIST pidl), ( pidl) );
  197. CALL_INNER(DWORD,  GetBrowserIndex ,(), () );
  198. CALL_INNER_HRESULT(GetBrowserByIndex, ( DWORD dwID, IUnknown **ppunk), ( dwID, ppunk) );
  199. CALL_INNER_HRESULT(GetHistoryObject, ( IOleObject **ppole, IStream **pstm, IBindCtx **ppbc), ( ppole, pstm, ppbc) );
  200. CALL_INNER_HRESULT(SetHistoryObject, ( IOleObject *pole, BOOL fIsLocalAnchor), ( pole, fIsLocalAnchor) );
  201. CALL_INNER_HRESULT(CacheOLEServer, ( IOleObject *pole), ( pole) );
  202. CALL_INNER_HRESULT(GetSetCodePage, ( VARIANT* pvarIn, VARIANT* pvarOut), ( pvarIn, pvarOut) );
  203. CALL_INNER_HRESULT(OnHttpEquiv, ( IShellView* psv, BOOL fDone, VARIANT* pvarargIn, VARIANT* pvarargOut), ( psv, fDone, pvarargIn, pvarargOut) );
  204. CALL_INNER_HRESULT(GetPalette, (  HPALETTE * hpal ), (  hpal ) );
  205. CALL_INNER_HRESULT(RegisterWindow, ( BOOL fUnregister, int swc), ( fUnregister, swc) );
  206. CALL_INNER(LRESULT,  WndProcBS ,(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam), (hwnd, uMsg, wParam, lParam) );
  207. CALL_INNER_HRESULT(OnSize, (WPARAM wParam), (wParam));
  208. CALL_INNER_HRESULT(OnCreate, (LPCREATESTRUCT pcs), (pcs));
  209. CALL_INNER(LRESULT,  OnCommand, (WPARAM wParam, LPARAM lParam), (wParam, lParam));
  210. CALL_INNER_HRESULT(OnDestroy, (), ());
  211. CALL_INNER(LRESULT,  OnNotify, (NMHDR * pnm), (pnm));
  212. CALL_INNER_HRESULT(OnSetFocus, (), ());
  213. CALL_INNER_HRESULT(GetBaseBrowserData,( LPCBASEBROWSERDATA* ppbd ), ( ppbd ));
  214. CALL_INNER(LPBASEBROWSERDATA, PutBaseBrowserData,(), ());
  215. CALL_INNER_HRESULT(CreateViewWindow, (IShellView* psvNew, IShellView* psvOld, LPRECT prcView, HWND* phwnd), (psvNew, psvOld, prcView, phwnd));;
  216. CALL_INNER_HRESULT(SetTopBrowser, (), ());
  217. CALL_INNER_HRESULT(OnFrameWindowActivateBS, (BOOL fActive), (fActive));
  218. CALL_INNER_HRESULT(ReleaseShellView, (), ());
  219. CALL_INNER_HRESULT(ActivatePendingView, (), ());
  220. CALL_INNER_HRESULT(InitializeDownloadManager, (), ());
  221. CALL_INNER_HRESULT(InitializeTransitionSite, (), ());
  222. CALL_INNER_HRESULT(Offline, (int iCmd), (iCmd));
  223. CALL_INNER_HRESULT(AllowViewResize, (BOOL f), (f));
  224. CALL_INNER_HRESULT(SetActivateState, (UINT u), (u));
  225. CALL_INNER_HRESULT(UpdateSecureLockIcon, (int eSecureLock), (eSecureLock));
  226. CALL_INNER_HRESULT(CreateBrowserPropSheetExt, (REFIID riid, LPVOID *ppvOut), (riid, ppvOut));
  227. CALL_INNER_HRESULT(SetAsDefFolderSettings,(  ), ( ));
  228. CALL_INNER_HRESULT(GetViewRect,( RECT* prc ), ( prc ));
  229. CALL_INNER_HRESULT(GetViewWindow,( HWND * phwnd ), ( phwnd ));
  230. CALL_INNER_HRESULT(InitializeTravelLog,( ITravelLog* ptl, DWORD dw ), ( ptl, dw ));
  231. CALL_INNER_HRESULT(_UIActivateView, (UINT uState), (uState) );
  232. CALL_INNER_HRESULT(_UpdateViewRectSize,(), ());
  233. CALL_INNER_HRESULT(_GetEffectiveClientArea, (LPRECT lprcBorder, HMONITOR hmon), (lprcBorder, hmon));
  234. CALL_INNER_HRESULT(_ResizeView,(), ());
  235.     // BEGIN REVIEW:  review names and need of each.  
  236.     // 
  237.     // this first set could be basebrowser only members.  no one overrides
  238. CALL_INNER_HRESULT(_CancelPendingNavigationAsync, (), () );
  239. CALL_INNER_HRESULT(_MaySaveChanges, (), () ); 
  240. CALL_INNER_HRESULT(_PauseOrResumeView, ( BOOL fPaused), ( fPaused) );
  241. CALL_INNER_HRESULT(_DisableModeless, (), () );
  242.     
  243.     // rethink these... are all of these necessary?
  244. CALL_INNER_HRESULT(_NavigateToPidl, ( LPCITEMIDLIST pidl, DWORD grfHLNF, DWORD dwFlags), ( pidl, grfHLNF, dwFlags));
  245. CALL_INNER_HRESULT(_TryShell2Rename, ( IShellView* psv, LPCITEMIDLIST pidlNew), ( psv, pidlNew));
  246. CALL_INNER_HRESULT(_SwitchActivationNow, () , ( ));
  247. CALL_INNER_HRESULT(_CancelPendingView, (), () );
  248.     //END REVIEW:
  249. // overridden by cdesktopbrowser
  250. CALL_INNER(IStream*, v_GetViewStream, (LPCITEMIDLIST pidl, DWORD grfMode, LPCWSTR pwszName), (pidl, grfMode, pwszName));
  251. #undef CALL_INNER
  252. #undef CALL_INNER_HRESULT
  253. // }
  254. // {
  255. #define CALL_INNER(_result, _function, _arglist, _args) 
  256. _result CCommonBrowser:: _function _arglist { return _psbInner-> _function _args ; }                                            
  257. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  258.     // IShellBrowser (same as IOleInPlaceFrame)
  259.     // IOleWindow
  260. CALL_INNER_HRESULT(GetWindow, (HWND * lphwnd), (lphwnd));
  261. CALL_INNER_HRESULT(ContextSensitiveHelp, (BOOL fEnterMode), (fEnterMode));
  262. CALL_INNER_HRESULT(InsertMenusSB, (HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths), (hmenuShared, lpMenuWidths));
  263. CALL_INNER_HRESULT(SetMenuSB, (HMENU hmenuShared, HOLEMENU holemenu, HWND hwnd), (hmenuShared, holemenu, hwnd));
  264. CALL_INNER_HRESULT(RemoveMenusSB, (HMENU hmenuShared), (hmenuShared));
  265. CALL_INNER_HRESULT(SetStatusTextSB, (LPCOLESTR lpszStatusText), (lpszStatusText));
  266. CALL_INNER_HRESULT(EnableModelessSB, (BOOL fEnable), (fEnable));
  267. CALL_INNER_HRESULT(BrowseObject, (LPCITEMIDLIST pidl, UINT wFlags), (pidl, wFlags));
  268. CALL_INNER_HRESULT(GetControlWindow, (UINT id, HWND * lphwnd), (id, lphwnd));
  269. CALL_INNER_HRESULT(SendControlMsg, (UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret), (id, uMsg, wParam, lParam, pret));
  270. CALL_INNER_HRESULT(QueryActiveShellView, (struct IShellView ** ppshv), (ppshv));
  271. CALL_INNER_HRESULT(OnViewWindowActive, (struct IShellView * ppshv), (ppshv));
  272. CALL_INNER_HRESULT(SetToolbarItems, (LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags), (lpButtons, nButtons, uFlags));
  273. #undef CALL_INNER
  274. #undef CALL_INNER_HRESULT
  275. // }
  276. // {
  277. #define CALL_INNER(_result, _function, _arglist, _args) 
  278. _result CCommonBrowser:: _function _arglist { return _pdtInner-> _function _args ; }
  279. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  280.     // *** IDropTarget ***
  281. CALL_INNER_HRESULT(DragEnter, (IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect), (pdtobj, grfKeyState, pt, pdwEffect));
  282. CALL_INNER_HRESULT(DragOver, (DWORD grfKeyState, POINTL pt, DWORD *pdwEffect), (grfKeyState, pt, pdwEffect));
  283. CALL_INNER_HRESULT(DragLeave, (void), ());
  284. CALL_INNER_HRESULT(Drop, (IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect), (pdtobj, grfKeyState, pt, pdwEffect));
  285. #undef CALL_INNER
  286. #undef CALL_INNER_HRESULT
  287. // }
  288. // {
  289. #define CALL_INNER(_result, _function, _arglist, _args) 
  290. _result CCommonBrowser:: _function _arglist { return _pspInner-> _function _args ; }
  291. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  292.     // IServiceProvider
  293. CALL_INNER_HRESULT(QueryService, (REFGUID guidService, REFIID riid, LPVOID* ppvObj), (guidService, riid, ppvObj) );
  294. #undef CALL_INNER
  295. #undef CALL_INNER_HRESULT
  296. // }
  297. // {
  298. #define CALL_INNER(_result, _function, _arglist, _args) 
  299. _result CCommonBrowser:: _function _arglist { return _pctInner-> _function _args ; }
  300. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  301.     // IOleCommandTarget
  302. CALL_INNER_HRESULT(QueryStatus, (const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext), (pguidCmdGroup, cCmds, rgCmds, pcmdtext) );
  303. #undef CALL_INNER
  304. #undef CALL_INNER_HRESULT
  305. // }
  306. HRESULT CCommonBrowser::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  307. {
  308.     if (pguidCmdGroup && IsEqualGUID(CGID_Explorer, *pguidCmdGroup)) 
  309.     {
  310.         if (nCmdID == SBCMDID_CACHEINETZONEICON)
  311.         {
  312.             if (!pvarargIn || pvarargIn->vt != VT_BOOL || !pvarargOut)
  313.                 return ERROR_INVALID_PARAMETER;
  314.             pvarargOut->vt = VT_UI4;
  315.             ENTERCRITICAL;
  316.             pvarargOut->ulVal = _CacheZonesIconsAndNames(pvarargIn->boolVal);
  317.             LEAVECRITICAL;
  318.             return S_OK;
  319.         }    
  320.     }
  321.     return _pctInner->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  322. }
  323. // {
  324. #define CALL_INNER(_result, _function, _arglist, _args) 
  325. _result CCommonBrowser:: _function _arglist { return _piosInner-> _function _args ; }
  326. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  327. #undef CALL_INNER
  328. #undef CALL_INNER_HRESULT
  329. // }
  330. HRESULT CCommonBrowser::TranslateAcceleratorSB(LPMSG lpmsg, WORD wID)
  331. {
  332.     HRESULT hres = S_FALSE;
  333.     
  334.     TraceMsg(0, "ief TR CCommonBrowser::TranslateAcceleratorSB called");
  335.     if (!_CanHandleAcceleratorNow())
  336.     {
  337.         TraceMsg(0, "Ignoring TranslateAccelerator, not active");
  338.         return S_FALSE;
  339.     }
  340.     
  341.     // If we're NOT top level, assume virtual TranslateAcceleratorSB
  342.     // handles this request. (See CVOCBrowser.)
  343.     // CDefView may call this before it passes it down to extended view
  344.     if (_hacc && ::TranslateAcceleratorWrap(_pbbd->_hwnd, _hacc, lpmsg)) {
  345.         TraceMsg(DM_ACCELERATOR, "CSB::TranslateAcceleratorSB TA(_hacc) ate %x,%x",
  346.                  lpmsg->message, lpmsg->wParam);
  347.         // We don't want to eat this escape because some controls on the
  348.         // page rely on ESC getting dispatched. Besides, dispatching it won't
  349.         // hurt us...
  350.         if (lpmsg->wParam != VK_ESCAPE)
  351.             hres = S_OK;
  352.     }
  353.     return hres;
  354. }
  355. //////////////////////////////////////////////////////////////////////////////////
  356. //
  357. // Code to get the ViewStateStream of the "Explorer" OCX
  358. //
  359. //////////////////////////////////////////////////////////////////////////////////
  360. HRESULT CCommonBrowser::GetViewStateStream(DWORD grfMode, IStream **ppstm)
  361. {
  362.     // NOTE: We can't use _pidlCur or _pidlPending here. Both are NULL
  363.     // when we goto a new directory. _pidlPending is initialized later in
  364.     // _CreateNewShellView. So, we use for which the NewShellView is created.
  365.     LPCITEMIDLIST pidl = _pbbd->_pidlNewShellView;
  366.     
  367.     if (!pidl)
  368.         pidl = _pbbd->_pidlPending;
  369.     
  370.     if (!pidl)
  371.         pidl = _pbbd->_pidlCur;
  372.     *ppstm = _pbsOuter->v_GetViewStream(pidl, grfMode, L"ViewView2");
  373.     // If getting the new one (for read) failed, try the old one.
  374.     if ((grfMode == STGM_READ) && (!*ppstm || SHIsEmptyStream(*ppstm)))
  375.     {
  376.         if (*ppstm)
  377.             (*ppstm)->Release();
  378.         *ppstm = _pbsOuter->v_GetViewStream(pidl, grfMode, L"ViewView");
  379.         TraceMsg(DM_VIEWSTREAM, "CBB::GetViewStateStream tried old stream (%x)", *ppstm);
  380.     }
  381.     
  382.     return *ppstm ? NOERROR : E_OUTOFMEMORY;
  383. }
  384. //
  385. // Returns the border rectangle for the shell view.
  386. //
  387. HRESULT CCommonBrowser::_GetViewBorderRect(RECT* prc)
  388. {
  389.     _pbsOuter->_GetEffectiveClientArea(prc, NULL);  // BUGBUG hmon?
  390.     //
  391.     // Extract the border taken by all "frame" toolbars
  392.     //
  393.     for (int i=0; i < _GetToolbarCount(); i++) {
  394.       LPTOOLBARITEM ptbi = _GetToolbarItem(i);
  395.       prc->left += ptbi->rcBorderTool.left;
  396.       prc->top += ptbi->rcBorderTool.top;
  397.       prc->right -= ptbi->rcBorderTool.right;
  398.       prc->bottom -= ptbi->rcBorderTool.bottom;
  399.     }
  400.     return S_OK;
  401. }
  402. // NOTE: these toolbar functions are still part of CBaseBrowser2
  403. // so they keep working. right now they are in IBrowserService2 and
  404. // forwarded down.
  405. void CCommonBrowser::_ReleaseToolbarItem(int itb, BOOL fClose)
  406. {
  407.     IDockingWindow *ptbTmp;
  408.     // grab it and NULL it out to eliminate race condition.
  409.     // (actually, there's still a v. small window btwn the 2 statements).
  410.     //
  411.     // e.g. if you close a WebBar and then quickly shutdown windows,
  412.     // the close destroys the window etc. but then the shutdown code
  413.     // does _SaveToolbars which tries to do ->Save on that destroyed guy.
  414.     //
  415.     // BUGBUG note however that this now means that the entry is marked
  416.     // 'free' so someone else might grab it out from under us and start
  417.     // trashing it.
  418.     LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  419.     ptbTmp = ptbi->ptbar;
  420.     ptbi->ptbar = NULL;
  421.     if (fClose)
  422.     {
  423.         ptbTmp->CloseDW(0);
  424.     }
  425.     IUnknown_SetSite(ptbTmp, NULL);
  426.     if (ptbi->pwszItem)
  427.     {
  428.         LocalFree(ptbi->pwszItem);
  429.         ptbi->pwszItem = NULL;
  430.     }
  431.     ptbTmp->Release();
  432. }
  433. //***   CBB::_AllocToolbarItem -- find/create free slot in _aTBar toolbar array
  434. // ENTRY/EXIT
  435. //  hres    [out] S_OK|itb on success; o.w. E_FAIL
  436. //  _aTBar  [inout] possibly grown
  437. int CCommonBrowser::_AllocToolbarItem()
  438. {
  439.     int itb, iCount;
  440.     LPTOOLBARITEM ptbi;
  441.     // try to recycle a dead one
  442.     iCount = FDSA_GetItemCount(&_fdsaTBar);
  443.     for (itb = 0; itb < iCount; ++itb) {
  444.         ptbi = (LPTOOLBARITEM)FDSA_GetItemPtr(&_fdsaTBar, itb, TOOLBARITEM);
  445.         ASSERT(ptbi != NULL);
  446.         if (ptbi && ptbi->ptbar == NULL) {
  447.             ASSERT(itb < ITB_MAX);
  448.             return itb;
  449.         }
  450.     }
  451.     // no luck recycling, create a new one
  452.     static TOOLBARITEM tbiTmp /*=0*/;
  453.     int i;
  454.     if ((i = FDSA_AppendItem(&_fdsaTBar, &tbiTmp)) == -1) {
  455.         TraceMsg(DM_WARNING, "cbb._ati: ret=-1");
  456.         return -1;  // warning: same as ITB_VIEW (!)
  457.     }
  458.     ASSERT(i == itb);
  459. #ifdef DEBUG
  460.     {
  461.         ptbi = (LPTOOLBARITEM) FDSA_GetItemPtr(&_fdsaTBar, itb, TOOLBARITEM);
  462.         ASSERT(ptbi != NULL);
  463.         for (int j = 0; j < SIZEOF(*ptbi); ++j)
  464.             ASSERT(*(((char *)ptbi) + j) == 0);
  465.     }
  466. #endif
  467.     ASSERT(i < ITB_MAX);
  468.     return i;
  469. }
  470. HRESULT CCommonBrowser::_CloseAndReleaseToolbars(BOOL fClose)
  471. {
  472.     for (int itb=0; itb < _GetToolbarCount(); itb++)
  473.     {
  474.         LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  475.         if (ptbi->ptbar)
  476.         {
  477.             _ReleaseToolbarItem(itb, fClose);
  478.         }
  479.     }
  480.     return S_OK;
  481. }
  482. //
  483. // Implementation of CBaseBrowser2::ShowToolbar
  484. //
  485. // Make toolbar visible or not and update our conception of whether it
  486. // should be shown
  487. //
  488. // Returns: S_OK, if successfully done.
  489. //          E_INVALIDARG, duh.
  490. //
  491. HRESULT CCommonBrowser::ShowToolbar(IUnknown* punkSrc, BOOL fShow)
  492. {
  493.     UINT itb = _FindTBar(punkSrc);
  494.     if (itb==(UINT)-1) {
  495.         return E_INVALIDARG;
  496.     }
  497.     LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  498.     // The _FindTBar function should assure us that ptbi->ptbar is non-NULL.
  499.     ASSERT( ptbi->ptbar );
  500.     ptbi->ptbar->ShowDW(fShow);
  501.     ptbi->fShow = fShow;
  502.     return S_OK;
  503. }
  504. //***   IDockingWindowFrame::* {
  505. //
  506. // Implementation of IDockingWindowFrame::AddToolbar
  507. //
  508. //  Add the specified toolbar (as punkSrc) to this toolbar site and
  509. // make it visible.
  510. //
  511. // Returns: S_OK, if successfully done.
  512. //          E_FAIL, if failed (exceeded maximum).
  513. //          E_NOINTERFACE, the toolbar does not support an approriate interface.
  514. //
  515. HRESULT CCommonBrowser::AddToolbar(IUnknown* punk, LPCWSTR pszItem, DWORD dwAddFlags)
  516. {
  517.     HRESULT hres = E_FAIL;
  518.     int itb;
  519.     // Find the first empty spot. 
  520.     if ((itb = _AllocToolbarItem()) != -1) {
  521.         LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  522.         ASSERT(ptbi != NULL);
  523.         ASSERT(ptbi->ptbar == NULL);
  524.         hres = punk->QueryInterface(IID_IDockingWindow, (LPVOID*)&ptbi->ptbar);
  525.         if (SUCCEEDED(hres) && ptbi->ptbar) {
  526.             if (pszItem) {
  527.                 UINT cb = (lstrlenW(pszItem)+1) * SIZEOF(pszItem[0]);
  528.                 ptbi->pwszItem = (LPWSTR)LocalAlloc(LPTR, cb);
  529.                 if (ptbi->pwszItem==NULL) {
  530.                     hres = E_OUTOFMEMORY;
  531.                     ATOMICRELEASE(ptbi->ptbar);
  532.                     return hres;
  533.                 }
  534.                 memcpy(ptbi->pwszItem, pszItem, cb);
  535.             }
  536.             ptbi->fShow = (! (dwAddFlags & DWFAF_HIDDEN)); // shown
  537.             IUnknown_SetSite(ptbi->ptbar, SAFECAST(this, IShellBrowser*));
  538.             ptbi->ptbar->ShowDW(ptbi->fShow);
  539.         } else {
  540.             // ERROR: all toolbars should implement IDockingWindow
  541.             // call tjgreen if this rips
  542.             ASSERT(0);
  543.         }
  544.     }
  545.     return hres;
  546. }
  547. //
  548. // Implementation of IDockingWindowFrame::RemoveToolbar
  549. //
  550. HRESULT CCommonBrowser::RemoveToolbar(IUnknown* punkSrc, DWORD dwRemoveFlags)
  551. {
  552.     UINT itb = _FindTBar(punkSrc);
  553.     if (itb==(UINT)-1) {
  554.         return E_INVALIDARG;
  555.     }
  556.     _ReleaseToolbarItem(itb, TRUE);
  557.     // Clear the rect and resize the inner ones (including the view).
  558.     // BUGBUG note the semi-hoaky post-release partying on rcBorderTool
  559.     SetRect(&_GetToolbarItem(itb)->rcBorderTool, 0, 0, 0, 0);
  560.     _pbsOuter->_ResizeNextBorder(itb+1);
  561.     return S_OK;
  562. }
  563. //
  564. // Implementation of IDockingWindowFrame::FindToolbar
  565. //
  566. HRESULT CCommonBrowser::FindToolbar(LPCWSTR pwszItem, REFIID riid, LPVOID* ppvObj)
  567. {
  568.     HRESULT hres = E_INVALIDARG;
  569.     *ppvObj = NULL;
  570.     if (pwszItem)
  571.     {
  572.         hres = S_FALSE;
  573.         for (int itb=0; itb < _GetToolbarCount(); itb++)
  574.         {
  575.             LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  576.             if (ptbi->pwszItem && StrCmpIW(ptbi->pwszItem, pwszItem)==0)
  577.             {
  578.                 if ( ptbi->ptbar )
  579.                 {
  580.                     hres = ptbi->ptbar->QueryInterface(riid, ppvObj);
  581.                 }
  582.                 else
  583.                 {
  584.                     TraceMsg( TF_WARNING, "ptbi->ptbar is NULL in FindToolbar" );
  585.                     hres = E_FAIL;
  586.                 }
  587.                 break;
  588.             }
  589.         }
  590.     }
  591.     return hres;
  592. }
  593. // }
  594. UINT CCommonBrowser::_FindTBar(IUnknown* punkSrc)
  595. {
  596. #ifdef DEBUG
  597.     static long nQuick = 0;
  598.     static long nSlow = 0;
  599. #endif
  600.     ASSERT(punkSrc);
  601.     // Quick check without QI
  602.     LPTOOLBARITEM ptbi;
  603.     for (int i=0; i < _GetToolbarCount(); i++) {
  604.         ptbi = _GetToolbarItem(i);
  605.         if (punkSrc==ptbi->ptbar) {
  606. #ifdef DEBUG
  607.             // I wonder if we ever hit this case...
  608.             InterlockedIncrement(&nQuick);
  609.             TraceMsg(TF_PERF, "_FindTBar QUICK=%d SLOW=%d", nQuick, nSlow);
  610. #endif            
  611.             return i;
  612.         }
  613.     }
  614.     // If failed, do the real COM object identity check. 
  615.     for (i=0; i < _GetToolbarCount(); i++) {
  616.         ptbi = _GetToolbarItem(i);
  617.         if (ptbi->ptbar) {
  618.             if (SHIsSameObject(ptbi->ptbar, punkSrc)) {
  619. #ifdef DEBUG        
  620.                 InterlockedIncrement(&nSlow);
  621.                 TraceMsg(TF_PERF, "_FindTBar QUICK=%d SLOW=%d", nQuick, nSlow);
  622. #endif            
  623.                 return i;
  624.             }
  625.         }
  626.     }
  627.     return (UINT)-1;
  628. }
  629. HRESULT CCommonBrowser::v_ShowHideChildWindows(BOOL fChildOnly)
  630. {
  631.     for (UINT itb=0; itb < (UINT)_GetToolbarCount(); itb++) {
  632.         LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  633.         if (ptbi->ptbar) {
  634.             // BUGBUG split: do we need _fKioskMode?
  635.             ptbi->ptbar->ShowDW(/*!_fKioskMode &&*/ ptbi->fShow);
  636.         }
  637.     }
  638.     if (!fChildOnly) {
  639.         _pbsInner->v_ShowHideChildWindows(fChildOnly);
  640.     }
  641.     return S_OK;
  642. }
  643. //***   _Load/_SaveToolbars {
  644. #ifdef DEBUG
  645. extern unsigned long DbStreamTell(IStream *pstm);
  646. #else
  647. #define DbStreamTell(pstm)      ((ULONG) 0)
  648. #endif
  649. const static DWORD c_BBSVersion = 0x00000011; // Increment when the stream is changed.
  650. #define MAX_ITEMID 128 // enough for item id
  651. HRESULT CCommonBrowser::_SaveToolbars(IStream* pstm)
  652. {
  653.     HRESULT hres = S_OK;
  654.     DWORD count = 0;
  655.     TraceMsg(DM_PERSIST, "cbb.stb enter(this=%x pstm=%x) tell()=%x", this, pstm, DbStreamTell(pstm));
  656.     if (pstm==NULL) {
  657.         for (UINT itb=0; itb < (UINT)_GetToolbarCount(); itb++) {
  658.             LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  659.             if (ptbi->ptbar) {
  660.                 IPersistStream* ppstm;
  661.                 HRESULT hresT = ptbi->ptbar->QueryInterface(IID_IPersistStream, (LPVOID*)&ppstm);
  662.                 if (SUCCEEDED(hresT)) {
  663.                     ppstm->Release();
  664.                     count++;
  665.                 }
  666.             }
  667.         }
  668.         TraceMsg(DM_PERSIST, "cbb.stb leave count=%d", count);
  669.         return (count>0) ? S_OK : S_FALSE;
  670.     }
  671.     ULARGE_INTEGER liStart;
  672.     pstm->Write(&c_BBSVersion, SIZEOF(c_BBSVersion), NULL);
  673.     // Remember the current location, where we writes count. 
  674.     pstm->Seek(c_li0, STREAM_SEEK_CUR, &liStart);
  675.     TraceMsg(DM_PERSIST, "cbb.stb seek(count)=%x", liStart.LowPart);
  676.     hres = pstm->Write(&count, SIZEOF(count), NULL);
  677.     if (hres==S_OK) {
  678.         for (UINT itb=0; itb < (UINT)_GetToolbarCount(); itb++) {
  679.             LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  680.             if (ptbi->ptbar) {
  681.                 IPersistStream* ppstm;
  682.                 HRESULT hresT = ptbi->ptbar->QueryInterface(IID_IPersistStream, (LPVOID*)&ppstm);
  683.                 if (SUCCEEDED(hresT)) {
  684.                     DWORD cchName = 0;
  685.                     if (ptbi->pwszItem &&
  686.                         (cchName=lstrlenW(ptbi->pwszItem)) &&
  687.                         cchName < MAX_ITEMID)
  688.                     {
  689.                         TraceMsg(DM_PERSIST, "cbb.stb pwszItem=<%ls>", ptbi->pwszItem);
  690.                         pstm->Write(&cchName, SIZEOF(cchName), NULL);
  691.                         pstm->Write(ptbi->pwszItem, cchName*SIZEOF(WCHAR), NULL);
  692.                     } else {
  693.                         TraceMsg(DM_PERSIST, "cbb.stb lstrlenW(pwszItem)=%d", cchName);
  694.                         pstm->Write(&cchName, SIZEOF(cchName), NULL);
  695.                     }
  696.                     TraceMsg(DM_PERSIST, "cbb.stb enter OleSaveToStream tell()=%x", DbStreamTell(pstm));
  697.                     hres = OleSaveToStream(ppstm, pstm);
  698.                     TraceMsg(DM_PERSIST, "cbb.stb leave OleSaveToStream tell()=%x", DbStreamTell(pstm));
  699.                     ppstm->Release();
  700.     
  701.                     if (FAILED(hres)) {
  702.                         break;
  703.                     }
  704.                     count++;
  705.                 }
  706.             }
  707.         }
  708.         // Remember the end
  709.         ULARGE_INTEGER liEnd;
  710.         pstm->Seek(c_li0, STREAM_SEEK_CUR, &liEnd);
  711.         TraceMsg(DM_PERSIST, "cbb.stb seek(end save)=%x", DbStreamTell(pstm));
  712.         // Seek back to the original location
  713.         TraceMsg(DM_PERSIST, "cbb.stb fix count=%d", count);
  714.         LARGE_INTEGER liT;
  715.         liT.HighPart = 0;
  716.         liT.LowPart = liStart.LowPart; 
  717.         pstm->Seek(liT, STREAM_SEEK_SET, NULL);
  718.         hres = pstm->Write(&count, SIZEOF(count), NULL);
  719.         // Seek forward to the end
  720.         liT.LowPart = liEnd.LowPart;
  721.         pstm->Seek(liT, STREAM_SEEK_SET, NULL);
  722.         TraceMsg(DM_PERSIST, "cbb.stb seek(end restore)=%x", DbStreamTell(pstm));
  723.     }
  724.     TraceMsg(DM_PERSIST, "cbb.stb leave tell()=%x", DbStreamTell(pstm));
  725.     return hres;
  726. }
  727. HRESULT IUnknown_GetClientDB(IUnknown *punk, IUnknown **ppdbc)
  728. {
  729.     HRESULT hr;
  730.     IDeskBar *pdb;
  731.     *ppdbc = NULL;
  732.     hr = punk->QueryInterface(IID_IDeskBar, (void **)&pdb);
  733.     if (SUCCEEDED(hr)) {
  734.         hr = pdb->GetClient(ppdbc);
  735.         pdb->Release();
  736.     }
  737.     return hr;
  738. }
  739. HRESULT CCommonBrowser::_LoadToolbars(IStream* pstm)
  740. {
  741.     HRESULT hres;
  742.     DWORD dwVersion;
  743.     TraceMsg(DM_PERSIST, "cbb.ltb enter(this=%x pstm=%x) tell()=%x", this, pstm, DbStreamTell(pstm));
  744.     hres = pstm->Read(&dwVersion, SIZEOF(dwVersion), NULL);
  745.     if (hres == S_OK && dwVersion == c_BBSVersion) {
  746.         DWORD count;
  747.         hres = pstm->Read(&count, SIZEOF(count), NULL);
  748.         if (hres == S_OK) {
  749.             for (UINT i=0; i<count && SUCCEEDED(hres); i++) {
  750.                 DWORD cchName = 0;
  751.                 hres = pstm->Read(&cchName, SIZEOF(cchName), NULL);
  752.                 if (hres == S_OK)
  753.                 {
  754.                     WCHAR wszName[MAX_ITEMID];
  755.                     wszName[0] = 0;
  756.                     // BUGBUG: if cchName >= ARRAYSIZE(wszName) then we're misaligned in the stream!
  757.                     if (cchName && cchName<ARRAYSIZE(wszName)) {
  758.                         hres = pstm->Read(wszName, cchName*SIZEOF(WCHAR), NULL);
  759.                     }
  760.                     TraceMsg(DM_PERSIST, "cbb.ltb name=<%ls>", wszName);
  761.     
  762.                     if (hres==S_OK) {
  763.                         IDockingWindow* pstb;
  764.                         TraceMsg(DM_PERSIST, "cbb.ltb enter OleLoadFromStream tell()=%x", DbStreamTell(pstm));
  765.                         hres = OleLoadFromStream(pstm, IID_IDockingWindow, (LPVOID*)&pstb);
  766.                         TraceMsg(DM_PERSIST, "cbb.ltb leave OleLoadFromStream tell()=%x", DbStreamTell(pstm));
  767.                         if (SUCCEEDED(hres)) {
  768.                             IUnknown *pDbc = NULL;
  769.                             // nt5:216944: turn off size negotiation during
  770.                             // load.  o.w. persisted size gets nuked.
  771.                             IUnknown_GetClientDB(pstb, &pDbc);
  772.                             if (pDbc)
  773.                                 DBC_ExecDrag(pDbc, DRAG_MOVE);
  774.                             hres = AddToolbar(pstb, wszName[0] ? wszName : NULL, NULL);
  775.                             if (pDbc) {
  776.                                 DBC_ExecDrag(pDbc, 0);
  777.                                 pDbc->Release();
  778.                             }
  779.                             pstb->Release();
  780.                         }
  781.                     }
  782.                 }
  783.             }
  784.         }
  785.     } else {
  786.         hres = E_FAIL;
  787.     }
  788.     TraceMsg(DM_PERSIST, "cbb.ltb leave tell()=%x", DbStreamTell(pstm));
  789.     return hres;
  790. }
  791. // }
  792. //***   IDockingWindowSite::* {
  793. HRESULT CCommonBrowser::_GetBorderDWHelper(IUnknown* punkSrc, LPRECT lprectBorder, BOOL bUseHmonitor)
  794. {
  795.     UINT itb = _FindTBar(punkSrc);
  796.     if (itb==(UINT)-1) {
  797.         return E_INVALIDARG;
  798.     
  799.     }
  800.     ASSERT(lprectBorder);
  801.     LPTOOLBARITEM ptbThis = _GetToolbarItem(itb);
  802.     MONITORINFO mi;
  803.     mi.cbSize = sizeof(mi);
  804.     if (bUseHmonitor && ptbThis && ptbThis->hMon)
  805.         _pbsOuter->_GetEffectiveClientArea(lprectBorder, ptbThis->hMon);
  806.     else
  807.         _pbsOuter->_GetEffectiveClientArea(lprectBorder, NULL); // BUGBUG hmon?
  808.     //
  809.     // Subtract border area taken by "outer toolbars"
  810.     //
  811.     for (UINT i=0; i<itb; i++) {
  812.         LPTOOLBARITEM ptbi = _GetToolbarItem(i);
  813.         if ((!bUseHmonitor) || (ptbi->hMon == ptbThis->hMon)) {
  814.             lprectBorder->left += ptbi->rcBorderTool.left;
  815.             lprectBorder->top += ptbi->rcBorderTool.top;
  816.             lprectBorder->right -= ptbi->rcBorderTool.right;
  817.             lprectBorder->bottom -= ptbi->rcBorderTool.bottom;
  818.         }
  819.     }
  820.     return S_OK;
  821. }
  822. //
  823. // This is an implementation of IDockingWindowSite::GetBorderDW.
  824. //
  825. //  This function returns a bounding rectangle for the specified toolbar
  826. // (by punkSrc). It gets the effective client area, then subtract border
  827. // area taken by "outer" toolbars. 
  828. // 
  829. HRESULT CCommonBrowser::GetBorderDW(IUnknown* punkSrc, LPRECT lprectBorder)
  830. {
  831.     return _GetBorderDWHelper(punkSrc, lprectBorder, FALSE);
  832. }
  833. HRESULT CCommonBrowser::RequestBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths)
  834. {
  835.     ASSERT(IS_VALID_READ_PTR(pborderwidths, BORDERWIDTHS));
  836.     return S_OK;
  837. }
  838. HRESULT CCommonBrowser::SetBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths)
  839. {
  840.     UINT itb = _FindTBar(punkSrc);
  841.     if (itb==(UINT)-1) {
  842.         return E_INVALIDARG;
  843.     }
  844.     TraceMsg(DM_UIWINDOW, "ief UIW::SetBorderSpace pborderwidths=%x,%x,%x,%x",
  845.              pborderwidths->left, pborderwidths->top, pborderwidths->right, pborderwidths->bottom);
  846.     _GetToolbarItem(itb)->rcBorderTool = *pborderwidths;
  847.     _pbsOuter->_ResizeNextBorder(itb+1);
  848.     return S_OK;
  849. }
  850. // }
  851. // IDockingWindowSite helpers {
  852. HRESULT CCommonBrowser::_ResizeNextBorderHelper(UINT itb, BOOL bUseHmonitor)
  853. {
  854.     //
  855.     // NOTES: (Documentation)
  856.     //  Note that we don't call _pact->ResizeBorder if we call
  857.     //  ITB::ResizeBorder. We assume that the toolbar will
  858.     //  always call back our SetBorderST, which then,
  859.     //  calls _pact->ResizeBorder. This must be documented.
  860.     //  (SatoNa)
  861.     // Find the next toolbar (even non-visible one)
  862.     IDockingWindow* ptbarNext = NULL;
  863.     if ((int) itb < _GetToolbarCount()) {
  864.         LPTOOLBARITEM ptbThis = _GetToolbarItem(itb);
  865.         for (int i=itb; i < _GetToolbarCount(); i++) {
  866.             LPTOOLBARITEM ptbi = _GetToolbarItem(i);
  867.             if (ptbi->ptbar && ((!bUseHmonitor) || (ptbi->hMon == ptbThis->hMon))) {
  868.                 ptbarNext = ptbi->ptbar;
  869.                 break;
  870.             }
  871.         }
  872.     }
  873.     RECT rc;
  874.     if (ptbarNext) {
  875.         GetBorderDW(ptbarNext, &rc);
  876.         ptbarNext->ResizeBorderDW(&rc, (IShellBrowser*)this, TRUE);
  877.     } else {
  878.         // BUGBUG split: _pbsInner->_ResizeNextBorder(itb) ?
  879.         _pbsOuter->_ResizeView();
  880.     }
  881.     return S_OK;
  882. HRESULT CCommonBrowser::_ResizeNextBorder(UINT itb)
  883. {
  884.     _ResizeNextBorderHelper(itb, FALSE);
  885.     return S_OK;
  886. }
  887. // }
  888. //
  889. // Hack alert!
  890. //
  891. // IE grabs the focus via _FixToolbarFocus when it shouldn't.  For example if a
  892. // java app in a seperate window contains an edit control and the address bar
  893. // had focus before the java app.  In this scenario the first time a user types
  894. // in the edit control IE grabs back the focus.  IE bug#59007.
  895. //
  896. // To prevent IE from incorrectly grabbing the focus this fuction checks that
  897. // top level parent of the toolbar is the same as the top level parent of the 
  898. // window that has focus.
  899. // 
  900. BOOL CCommonBrowser::_TBWindowHasFocus(UINT itb)
  901. {
  902.     ASSERT(itb < ITB_MAX);
  903.     BOOL fRet = TRUE;
  904.     HWND hwndFocus = GetFocus();
  905.     while (GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD)
  906.         hwndFocus = GetParent(hwndFocus);
  907.     if (hwndFocus)
  908.     {
  909.         LPTOOLBARITEM pti = _GetToolbarItem(itb);
  910.         if (pti && pti->ptbar)
  911.         {
  912.             HWND hwndTB;
  913.             if (SUCCEEDED(pti->ptbar->GetWindow(&hwndTB)) && hwndTB)
  914.             {
  915.                 fRet = (S_OK == SHIsChildOrSelf(hwndFocus, hwndTB));
  916.             }
  917.         }
  918.     }
  919.     return fRet;
  920. }
  921. DWORD CCommonBrowser::_CacheZonesIconsAndNames(BOOL fRefresh)
  922. {
  923.     ASSERTCRITICAL;
  924.     if (g_pZoneIconNameCache)      // If we've already cached the zones, just return the zone count unless we want to refresh cache
  925.     {
  926.         if (fRefresh)
  927.         {
  928.             for (int nIndex=0; (DWORD)nIndex < g_dwZoneCount; nIndex++)
  929.             {
  930.                 if ((g_pZoneIconNameCache+nIndex)->pszZonesName)
  931.                     LocalFree((g_pZoneIconNameCache+nIndex)->pszZonesName);
  932.                 if ((g_pZoneIconNameCache+nIndex)->hiconZones)
  933.                     DestroyIcon((g_pZoneIconNameCache+nIndex)->hiconZones);
  934.             }
  935.             LocalFree(g_pZoneIconNameCache);
  936.             g_pZoneIconNameCache = NULL;
  937.             g_dwZoneCount = 0;
  938.         }
  939.         else
  940.             return(g_dwZoneCount);
  941.     }
  942.     // Create ZoneManager
  943.     if (!_pizm)
  944.         CoCreateInstance(CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, IID_IInternetZoneManager, (void **)&_pizm);
  945.     if (_pizm)
  946.     {
  947.         DWORD dwZoneEnum;
  948.         if (SUCCEEDED(_pizm->CreateZoneEnumerator(&dwZoneEnum, &g_dwZoneCount, 0)))
  949.         {
  950.             if ((g_pZoneIconNameCache = (PZONEICONNAMECACHE)LocalAlloc(LPTR, g_dwZoneCount * sizeof(ZONEICONNAMECACHE))) == NULL)
  951.             {
  952.                 g_dwZoneCount = 0;
  953.                 return(0);
  954.             }
  955.                 
  956.             for (int nIndex=0; (DWORD)nIndex < g_dwZoneCount; nIndex++)
  957.             {
  958.                 DWORD           dwZone;
  959.                 UINT            cchLen;
  960.                 ZONEATTRIBUTES  za = {sizeof(ZONEATTRIBUTES)};
  961.                 WORD            iIcon=0;
  962.                 HICON           hIcon = NULL;
  963.                 _pizm->GetZoneAt(dwZoneEnum, nIndex, &dwZone);
  964.                 // get the zone attributes for this zone
  965.                 _pizm->GetZoneAttributes(dwZone, &za);
  966.                 cchLen = lstrlen(za.szDisplayName) + 1;
  967.                 if (((g_pZoneIconNameCache+nIndex)->pszZonesName = (TCHAR *)LocalAlloc(LPTR, cchLen*sizeof(TCHAR))) == NULL)
  968.                 {
  969.                     g_dwZoneCount = nIndex;
  970.                     return(g_dwZoneCount);
  971.                 }
  972.                 
  973.                 // Zone icons are in two formats.
  974.                 // wininet.dll#1200 where 1200 is the res id.
  975.                 // or foo.ico directly pointing to an icon file.
  976.                 // search for the '#'
  977.                 LPWSTR pwsz = StrChrW(za.szIconPath, TEXTW('#'));
  978.                 if (pwsz)
  979.                 {
  980.                     TCHAR           szIconPath[MAX_PATH];        
  981.                     // if we found it, then we have the foo.dll#00001200 format
  982.                     pwsz[0] = TEXTW('');
  983.                     SHUnicodeToTChar(za.szIconPath, szIconPath, ARRAYSIZE(szIconPath));
  984.                     iIcon = (WORD)StrToIntW(pwsz+1);
  985.                     ExtractIconEx(szIconPath,(UINT)(-1*iIcon), NULL, &hIcon, 1 );
  986.                 }
  987.                 else
  988.                     hIcon = (HICON)ExtractAssociatedIconExW(HINST_THISDLL, za.szIconPath, (LPWORD)&iIcon, &iIcon);
  989.                 // If mirrored system, mirror icon so that it get unmirrored again
  990.                 // when displayed
  991.                 if (IS_BIDI_LOCALIZED_SYSTEM())
  992.                 {        
  993.                    MirrorIcon(&hIcon, NULL);
  994.                 }                    
  995.                 (g_pZoneIconNameCache+nIndex)->hiconZones = hIcon;
  996.                 StrNCpy((g_pZoneIconNameCache+nIndex)->pszZonesName, za.szDisplayName, cchLen);
  997.             }
  998.             _pizm->DestroyZoneEnumerator(dwZoneEnum);
  999.         }
  1000.     }
  1001.     return(g_dwZoneCount);
  1002. }
  1003. BOOL _QITest(IUnknown* punk, REFIID riid);
  1004. BOOL CCommonBrowser::_ShouldTranslateAccelerator(MSG* pmsg)
  1005. {
  1006.     // We should only translate an acclerator if
  1007.     //
  1008.     // (a) the window is the frame or a child of the frame
  1009.     //     or a child of a defview window (NT5 Bug # 357186).
  1010.     //     (need to check this because you can have, for
  1011.     //     example, a toplevel java applet window running
  1012.     //     on our thread)
  1013.     //
  1014.     //     and
  1015.     //
  1016.     // (b) it's on our thread (need to check this because
  1017.     //     old-style OLE controls on a web page can run
  1018.     //     on the desktop thread)
  1019.     //
  1020.     BOOL fTranslate = FALSE;
  1021.     fTranslate = (SHIsChildOrSelf(_pbbd->_hwnd, pmsg->hwnd) == S_OK);
  1022.     if (!fTranslate) 
  1023.     {
  1024.        HWND hwnd = NULL;
  1025.        if (_pbbd->_psv && (_QITest(SAFECAST(_pbbd->_psv, IUnknown*), IID_CDefView))
  1026.             &&  SUCCEEDED(_pbbd->_psv->GetWindow(&hwnd)))
  1027.        {
  1028.           fTranslate = (SHIsChildOrSelf(hwnd, pmsg->hwnd) == S_OK);
  1029.        }
  1030.     }
  1031.     
  1032.     if (fTranslate)
  1033.     {
  1034.         DWORD dwThread = GetWindowThreadProcessId(_pbbd->_hwnd, NULL);
  1035.         HWND hwndMsg = pmsg->hwnd;
  1036.         while (GetWindowLong(hwndMsg, GWL_STYLE) & WS_CHILD)
  1037.         {
  1038.             hwndMsg = GetParent(hwndMsg);
  1039.         }
  1040.         DWORD dwMsgThread = hwndMsg ? GetWindowThreadProcessId(hwndMsg, NULL) : 0;
  1041.         if (dwThread == dwMsgThread)
  1042.         {
  1043.             return TRUE;
  1044.         }
  1045.     }
  1046.     return FALSE;
  1047. }
  1048. HRESULT CCommonBrowser::v_MayTranslateAccelerator(MSG* pmsg)
  1049. {
  1050.     if (!(WM_KEYFIRST <= pmsg->message && pmsg->message <= WM_KEYLAST))
  1051.         return S_FALSE;
  1052.     BOOL fToolbarHasFocus = _HasToolbarFocus();
  1053.     if (fToolbarHasFocus)
  1054.     {
  1055.         ASSERT(_get_itbLastFocus() < (UINT)_GetToolbarCount());
  1056.         // toolbar has focus -- give it first chance to translate
  1057.         //
  1058.         // Notes:
  1059.         //  Notice that we don't give a chance to translate its accelerators
  1060.         // to other toolbars. This is by-design right now. We might want to
  1061.         // change it later, but it will be tricky to do it right. 
  1062.         //
  1063.         if (UnkTranslateAcceleratorIO(_GetToolbarItem(_get_itbLastFocus())->ptbar, pmsg) == S_OK)
  1064.             return(S_OK);
  1065.     }
  1066.     else
  1067.     {
  1068.         UINT itbLastFocus = _get_itbLastFocus();
  1069.         if (itbLastFocus != ITB_VIEW && _TBWindowHasFocus(itbLastFocus))
  1070.         {
  1071.             // view got focus back, update cache
  1072.             _FixToolbarFocus();
  1073.         }
  1074.         // view has focus -- give it first chance to translate
  1075.         // View doesn't necessarily have focus.  Added a check.
  1076.         //
  1077.         if (_pbbd->_psv )                 // If we have a shell view
  1078.         {
  1079.             HWND hwnd;
  1080.             // Note: Not everyone supports GetWindow (go figure)
  1081.             // In which case, we try the GetFocus() window.
  1082.             if (FAILED(_pbbd->_psv->GetWindow(&hwnd)))
  1083.             {
  1084.                 hwnd = GetFocus();
  1085.             }
  1086.             // check if view or its child has focus
  1087.             // before it checked for browser or a child but if user
  1088.             // clicked on Show Desktop in quick launch
  1089.             // defview is deparented from the desktop and this call
  1090.             // fails which prevents tabbing to Active Desktop
  1091.             // (done in CDefView::TranslateAccelerator
  1092.             if (SHIsChildOrSelf(hwnd, pmsg->hwnd) == S_OK)
  1093.             {
  1094.                 if ( _pbbd->_psv->TranslateAccelerator(pmsg) == NOERROR )  // and the shell view translated the message
  1095.                 {
  1096.                     ASSERT(! ((pmsg->message == WM_SYSCHAR) && 
  1097.                               pmsg->wParam == 's'));
  1098.         
  1099.                     return S_OK;
  1100.                 }
  1101.             }
  1102.         }
  1103.     }
  1104.     // Then, handle our own accelerators (with special code for TAB key).
  1105.     if (_ShouldTranslateAccelerator(pmsg))
  1106.     {
  1107.         if (IsVK_TABCycler(pmsg))
  1108.             return _CycleFocus(pmsg);
  1109.         BOOL fFwdItbar = FALSE;
  1110.         // BUGBUG: Why not just include F4 and Alt-D in ACCEL_MERGE,
  1111.         // which gets localized?
  1112.         if (pmsg->message == WM_KEYDOWN && pmsg->wParam == VK_F4)
  1113.         {
  1114.             fFwdItbar = TRUE;
  1115.         }
  1116.         if(pmsg->message == WM_SYSCHAR)
  1117.         {
  1118.             static CHAR szAccel[2] = "";
  1119.             CHAR   szChar [2] = "";
  1120.             
  1121.             
  1122.             if ('' == szAccel[0])
  1123.                 MLLoadStringA(IDS_ADDRBAND_ACCELLERATOR, szAccel, ARRAYSIZE(szAccel));
  1124.             szChar[0] = (CHAR)pmsg->wParam;
  1125.             
  1126.             if (lstrcmpiA(szChar,szAccel) == 0)
  1127.             {
  1128.                 fFwdItbar = TRUE;
  1129.             }    
  1130.         }
  1131.         if (fFwdItbar)
  1132.         {
  1133.             IDockingWindow *ptbar = _GetToolbarItem(ITB_ITBAR)->ptbar;
  1134.             if (UnkTranslateAcceleratorIO(ptbar, pmsg) == S_OK)
  1135.                 return S_OK;
  1136.         } 
  1137.         if (TranslateAcceleratorSB(pmsg, 0) == S_OK)
  1138.             return S_OK;
  1139.     }
  1140.     // If a toolbar has focus, we ask the view last. 
  1141.     if (fToolbarHasFocus)
  1142.     {
  1143.         if (_pbbd->_psv && _pbbd->_psv->TranslateAccelerator(pmsg) == NOERROR)
  1144.             return S_OK;
  1145.     }
  1146.     return S_FALSE;
  1147. }
  1148. HRESULT CCommonBrowser::_CycleFocus(LPMSG lpMsg)
  1149. {
  1150.     UINT citb = 1;
  1151.     if (GetKeyState(VK_SHIFT) < 0)
  1152.     {
  1153.         // go backward
  1154.         citb = (UINT)-1;
  1155.     }
  1156.     UINT itbCur = _get_itbLastFocus();
  1157.     //
  1158.     //  Find the next visible toolbar and set the focus to it. Otherwise,
  1159.     // set the focus to the view window.
  1160.     //
  1161.     HWND hwndFocusNext;
  1162.     LPTOOLBARITEM ptbi;
  1163.     if (_pbsOuter->v_MayGetNextToolbarFocus(lpMsg, itbCur, citb, &ptbi, &hwndFocusNext) == S_OK)
  1164.     {
  1165.         // Found a toolbar to take focus, nothing more to do.
  1166.         // BUGBUG do we (or caller) need to do SetStatusTextSB?
  1167.         return S_OK;
  1168.     }
  1169.     if (!(hwndFocusNext && IsWindowVisible(hwndFocusNext)))
  1170.     {
  1171.         // Didn't find anyone.  Set focus on the view.
  1172.         hwndFocusNext = _pbbd->_hwndView;
  1173.     }
  1174.     _SetFocus(ptbi, hwndFocusNext, lpMsg);
  1175.     return S_OK;
  1176. }
  1177. //***   v_MayGetNextToolbarFocus -- get next in TAB order (and maybe SetFocus)
  1178. // ENTRY/EXIT
  1179. //  hres    E_FAIL for no candidate, S_FALSE for candidate, S_OK for 100% done
  1180. //          (S_OK only used by derived class for now)
  1181. HRESULT CCommonBrowser::v_MayGetNextToolbarFocus(LPMSG lpMsg,
  1182.     UINT itbCur, int citb,
  1183.     LPTOOLBARITEM * pptbi, HWND * phwnd)
  1184. {
  1185.     HWND hwnd = 0;
  1186.     LPTOOLBARITEM ptbi = NULL;
  1187.     if (itbCur == ITB_VIEW)
  1188.     {
  1189.         ASSERT(citb == 1 || citb == -1);
  1190.         if (citb == 1)
  1191.             itbCur = 0;
  1192.         else
  1193.             itbCur = _GetToolbarCount() - 1;
  1194.     }
  1195.     else
  1196.     {
  1197.         itbCur += citb;
  1198.     }
  1199.     // (semi-tricky: loop on an unsigned so get 0..n or n..0 w/ single loop)
  1200.     for (UINT i = itbCur; i < (UINT)_GetToolbarCount(); i += citb)
  1201.     {
  1202.         ptbi = _GetToolbarItem(i);
  1203.         // NOTE: _MayUIActTAB checks ptbi->ptbar for NULL
  1204.         if (_MayUIActTAB(ptbi->ptbar, lpMsg, ptbi->fShow, &hwnd) == S_OK)
  1205.         {
  1206.             *pptbi = ptbi;
  1207.             *phwnd = hwnd;
  1208.             return S_FALSE;
  1209.         }
  1210.     }
  1211.     *pptbi = NULL;
  1212.     *phwnd = 0;
  1213.     return E_FAIL;
  1214. }
  1215. BOOL _QITest(IUnknown* punk, REFIID riid)
  1216. {
  1217.     ASSERT(punk);
  1218.     BOOL fRet = FALSE;
  1219.     if (SUCCEEDED(punk->QueryInterface(riid, (void**)&punk)))
  1220.     {
  1221.         punk->Release();
  1222.         fRet = TRUE;
  1223.     }
  1224.     return fRet;
  1225. }
  1226. __inline BOOL _IsV4DefView(IShellView* psv)
  1227. {
  1228.     if (GetUIVersion() < 5)
  1229.         return _QITest(SAFECAST(psv, IUnknown*), IID_CDefView);
  1230.     return FALSE;
  1231. }
  1232. __inline BOOL _IsOldView(IShellView* psv)
  1233. {
  1234.     //
  1235.     // Current CDocObjectView and v4 and greater CDefView
  1236.     // implement IShellView2
  1237.     //
  1238.     return (FALSE == _QITest(SAFECAST(psv, IUnknown*), IID_IShellView2));
  1239. }
  1240. HRESULT CCommonBrowser::_SetFocus(LPTOOLBARITEM ptbi, HWND hwnd, LPMSG lpMsg)
  1241. {
  1242.     // Clear the upper layer of status text
  1243.     SetStatusTextSB(NULL);
  1244.     if (hwnd == _pbbd->_hwndView)
  1245.     {
  1246.         if (_pbbd->_psv)
  1247.         {
  1248.             BOOL fTranslate = TRUE, fActivate = TRUE;
  1249.             if (!lpMsg)
  1250.             {
  1251.                 // NULL message, so nothing to translate
  1252.                 fTranslate = FALSE;
  1253.             }
  1254.             else if (_IsV4DefView(_pbbd->_psv) || _IsOldView(_pbbd->_psv))
  1255.             {
  1256.                 // These views expect only to be UI-activated
  1257.                 fTranslate = FALSE;
  1258.             }
  1259.             else if (IsVK_CtlTABCycler(lpMsg))
  1260.             {
  1261.                 // Don't let trident translate ctl-tab.  Since it's always
  1262.                 // UI-active, it will reject focus.
  1263.                 fTranslate = FALSE;
  1264.             }
  1265.             else
  1266.             {
  1267.                 // Normal case - do not activate the view.  TranslateAccelerator will do the right thing.
  1268.                 fActivate = FALSE;
  1269.             }
  1270.             if (fActivate)
  1271.                 _UIActivateView(SVUIA_ACTIVATE_FOCUS);
  1272.             if (fTranslate)
  1273.                 _pbbd->_psv->TranslateAccelerator(lpMsg);
  1274.         }
  1275.         else
  1276.         {
  1277.             // IE3 compat (we used to do for all hwnd's)
  1278.             SetFocus(hwnd);
  1279.         }
  1280.         // Update our cache
  1281.         _OnFocusChange(ITB_VIEW);
  1282.     }
  1283.     return S_OK;
  1284. }
  1285. HRESULT CCommonBrowser::_FindActiveTarget(REFIID riid, LPVOID* ppvOut)
  1286. {
  1287.     HRESULT hres = E_FAIL;
  1288.     *ppvOut = NULL;
  1289.     BOOL fToolbarHasFocus = _HasToolbarFocus();
  1290.     if (fToolbarHasFocus) {
  1291.         hres = _GetToolbarItem(_get_itbLastFocus())->ptbar->QueryInterface(riid, ppvOut);
  1292.     } else if (_pbbd->_psv) {
  1293.         if (_get_itbLastFocus() != ITB_VIEW) {
  1294.             // view got focus back, update cache
  1295.             _FixToolbarFocus();
  1296.         }
  1297.         if (_pbbd->_psv != NULL)
  1298.         {
  1299.             hres = _pbbd->_psv->QueryInterface(riid, ppvOut);
  1300.         }
  1301.     }
  1302.     return hres;
  1303. }
  1304. BOOL CCommonBrowser::_HasToolbarFocus(void)
  1305. {
  1306.     UINT uLast = _get_itbLastFocus();
  1307.     if (uLast < ITB_MAX)
  1308.     {
  1309.         LPTOOLBARITEM ptbi = _GetToolbarItem(uLast);
  1310.         if (ptbi)
  1311.         {
  1312.             // NOTE: UnkHasFocusIO checks ptbi->ptbar for NULL
  1313.             return (UnkHasFocusIO(ptbi->ptbar) == S_OK);
  1314.         }
  1315.     }
  1316.     return FALSE;
  1317. }
  1318. //***   _FixToolbarFocus -- fake a UIActivate from the view
  1319. // NOTES
  1320. //  The view never goes 'truly' non-UIActive so we never get notified when 
  1321. //  it goes 'truly' UIActive.  we fake it here by mucking w/ our cache.
  1322. //
  1323. HRESULT CCommonBrowser::_FixToolbarFocus(void)
  1324. {
  1325.     _OnFocusChange(ITB_VIEW);               // ... and update cache
  1326.     _UIActivateView(SVUIA_ACTIVATE_FOCUS);  // steal the focus
  1327.     return S_OK;
  1328. }
  1329. HRESULT CCommonBrowser::_OnFocusChange(UINT itb)
  1330. {
  1331.     UINT itbPrevFocus = _get_itbLastFocus();
  1332.     if (itbPrevFocus != itb)
  1333.     {
  1334.         //
  1335.         //  If the view is losing the focus (within the explorer),
  1336.         // we should let it know. We should update _itbLastFocus before
  1337.         // calling UIActivate, because it will call our InsertMenu back.
  1338.         //
  1339.         _put_itbLastFocus(itb);
  1340.         if (itbPrevFocus == ITB_VIEW)
  1341.         {
  1342.             // DocHost will ignore this (since deactivating the view is taboo).
  1343.             // ShellView will respect it (so menu merge works).
  1344.             _UIActivateView(SVUIA_ACTIVATE_NOFOCUS);
  1345.         }
  1346.         else
  1347.         {
  1348.             HRESULT hres;
  1349.             IDockingWindow *ptb;
  1350.             // BUGBUG uh-oh not sure what we do if NULL
  1351.             // we do get NULL the 1st time we click on the SearchBand
  1352.             ptb = _GetToolbarItem(itbPrevFocus)->ptbar;
  1353.             hres = UnkUIActivateIO(ptb, FALSE, NULL);
  1354.         }
  1355.     }
  1356.     return S_OK;
  1357. }
  1358. HRESULT CCommonBrowser::OnFocusChangeIS(IUnknown* punkSrc, BOOL fSetFocus)
  1359. {
  1360.     UINT itb = _FindTBar(punkSrc);
  1361.     if (itb == ITB_VIEW)
  1362.     {
  1363.         return E_INVALIDARG;
  1364.     }
  1365.     //
  1366.     //  Note that we keep track of which toolbar got the focus last.
  1367.     // We can't reliably monitor the kill focus event because OLE's
  1368.     // window procedure hook (for merged menu dispatching code) changes
  1369.     // focus around. 
  1370.     //
  1371.     if (fSetFocus)
  1372.     {
  1373.         _OnFocusChange(itb);
  1374.         // Then, notify it to the shellview. 
  1375.         // BUGBUG split: should this go in basesb?
  1376.         if (_pbbd->_pctView)
  1377.         {
  1378.             _pbbd->_pctView->Exec(NULL, OLECMDID_ONTOOLBARACTIVATED, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  1379.         }
  1380.     }
  1381.     else if (itb == _get_itbLastFocus())
  1382.     {
  1383.         //
  1384.         // The toolbar which currently has focus is giving it up.
  1385.         // Move focus to the view when this happens.
  1386.         //
  1387.         _FixToolbarFocus();
  1388.     }
  1389.     return S_OK;
  1390. }
  1391. //***   toolbar/view broadcast {
  1392. //***   _ExecChildren -- broadcast Exec to view and toolbars
  1393. // NOTES
  1394. //  we might do *both* punkBar and fBroadcast if we want to send stuff
  1395. //  to both the view and to all toolbars, e.g. 'stop' or 'refresh'.
  1396. //
  1397. //  BUGBUG n.b. the tray isn't a real toolbar, so it won't get called (sigh...).
  1398. HRESULT CCommonBrowser::_ExecChildren(IUnknown *punkBar, BOOL fBroadcast, const GUID *pguidCmdGroup,
  1399.     DWORD nCmdID, DWORD nCmdexecopt,
  1400.     VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1401. {
  1402.     // 1st, send to specified guy (if requested)
  1403.     if (punkBar != NULL) {
  1404.         // send to specified guy
  1405.         _pbsInner->_ExecChildren(punkBar, FALSE, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1406.     }
  1407.     // 2nd, broadcast to all (if requested)
  1408.     if (fBroadcast) {
  1409.         for (int itb=0; itb<_GetToolbarCount(); itb++) {
  1410.             LPTOOLBARITEM ptbi;
  1411.             ptbi = _GetToolbarItem(itb);
  1412.             // NOTE: IUnknown_Exec checks ptbi->ptbar for NULL
  1413.             IUnknown_Exec(ptbi->ptbar, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1414.         }
  1415.     }
  1416.     return S_OK;
  1417. }
  1418. HRESULT CCommonBrowser::_SendChildren(HWND hwndBar, BOOL fBroadcast, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1419. {
  1420.     // 1st, send to specified guy (if requested)
  1421.     if (hwndBar != NULL) {
  1422.         // send to specified guy
  1423.         _pbsInner->_SendChildren(hwndBar, FALSE, uMsg, wParam, lParam);
  1424.     }
  1425.     // 2nd, broadcast to all (if requested)
  1426.     if (fBroadcast) {
  1427.         for (int itb=0; itb < _GetToolbarCount(); itb++) {
  1428.             LPTOOLBARITEM ptbi;
  1429.             HWND hwndToolbar;
  1430.             ptbi = _GetToolbarItem(itb);
  1431.             if (ptbi->ptbar && SUCCEEDED(ptbi->ptbar->GetWindow(&hwndToolbar)))
  1432.                 SendMessage(hwndToolbar, uMsg, wParam, lParam);
  1433.         }
  1434.     }
  1435.     return S_OK;
  1436. }
  1437. LRESULT CCommonBrowser::ForwardViewMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1438. {
  1439.      return _pbbd->_hwndView ? SendMessage(_pbbd->_hwndView, uMsg, wParam, lParam) : 0;
  1440. }
  1441. // }
  1442. LPTOOLBARITEM CCommonBrowser::_GetToolbarItem(int itb)
  1443. {
  1444.     ASSERT(itb != ITB_VIEW);
  1445.     ASSERT(itb < ITB_MAX);
  1446.     // ==0 for semi-bogus CBB::_OnFocusChange code
  1447.     ASSERT(itb < FDSA_GetItemCount(&_fdsaTBar) || itb == 0);
  1448.     LPTOOLBARITEM ptbi = FDSA_GetItemPtr(&_fdsaTBar, itb, TOOLBARITEM);
  1449.     ASSERT(ptbi != NULL);
  1450.     return ptbi;
  1451. }
  1452. HRESULT _ConvertPathToPidl(IBrowserService2 *pbs, HWND hwnd, LPCTSTR pszPath, LPITEMIDLIST * ppidl)
  1453. {
  1454.     HRESULT hres = E_FAIL;
  1455.     WCHAR wszCmdLine[MAX_URL_STRING]; // must be with pszPath
  1456.     TCHAR szParsedUrl[MAX_URL_STRING] = {''};
  1457.     TCHAR szFixedUrl[MAX_URL_STRING];
  1458.     DWORD dwUrlLen = ARRAYSIZE(szParsedUrl);
  1459.     LPCTSTR pUrlToUse = pszPath;
  1460.     // Copy the command line into a temporary buffer
  1461.     // so we can remove the surrounding quotes (if 
  1462.     // they exist)
  1463.     StrCpyN(szFixedUrl, pszPath, ARRAYSIZE(szFixedUrl));
  1464.     PathUnquoteSpaces(szFixedUrl);
  1465.     
  1466.     if (ParseURLFromOutsideSource(szFixedUrl, szParsedUrl, &dwUrlLen, NULL))
  1467.         pUrlToUse = szParsedUrl;
  1468.     
  1469.     SHTCharToUnicode(pUrlToUse, wszCmdLine, ARRAYSIZE(wszCmdLine));
  1470.     
  1471.     hres = pbs->IEParseDisplayName(CP_ACP, wszCmdLine, ppidl);
  1472.     pbs->DisplayParseError(hres, wszCmdLine);
  1473.     return hres;
  1474. }