Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1888 lines
58 KiB

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