Leaked source code of windows server 2003
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.

1901 lines
60 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 = ptbi->pwszItem ? lstrlenW(ptbi->pwszItem) : 0;
  705. if (cchName > 0 && cchName < MAX_ITEMID)
  706. {
  707. TraceMsg(DM_PERSIST, "cbb.stb pwszItem=<%ls>", ptbi->pwszItem);
  708. pstm->Write(&cchName, sizeof(cchName), NULL);
  709. pstm->Write(ptbi->pwszItem, cchName*sizeof(WCHAR), NULL);
  710. }
  711. else
  712. {
  713. TraceMsg(DM_PERSIST, "cbb.stb lstrlenW(pwszItem)=%d", cchName);
  714. pstm->Write(&cchName, sizeof(cchName), NULL);
  715. }
  716. TraceMsg(DM_PERSIST, "cbb.stb enter OleSaveToStream tell()=%x", DbStreamTell(pstm));
  717. hres = OleSaveToStream(ppstm, pstm);
  718. TraceMsg(DM_PERSIST, "cbb.stb leave OleSaveToStream tell()=%x", DbStreamTell(pstm));
  719. ppstm->Release();
  720. if (FAILED(hres))
  721. {
  722. break;
  723. }
  724. count++;
  725. }
  726. }
  727. }
  728. // Remember the end
  729. ULARGE_INTEGER liEnd;
  730. pstm->Seek(c_li0, STREAM_SEEK_CUR, &liEnd);
  731. TraceMsg(DM_PERSIST, "cbb.stb seek(end save)=%x", DbStreamTell(pstm));
  732. // Seek back to the original location
  733. TraceMsg(DM_PERSIST, "cbb.stb fix count=%d", count);
  734. LARGE_INTEGER liT;
  735. liT.HighPart = 0;
  736. liT.LowPart = liStart.LowPart;
  737. pstm->Seek(liT, STREAM_SEEK_SET, NULL);
  738. hres = pstm->Write(&count, sizeof(count), NULL);
  739. // Seek forward to the end
  740. liT.LowPart = liEnd.LowPart;
  741. pstm->Seek(liT, STREAM_SEEK_SET, NULL);
  742. TraceMsg(DM_PERSIST, "cbb.stb seek(end restore)=%x", DbStreamTell(pstm));
  743. }
  744. TraceMsg(DM_PERSIST, "cbb.stb leave tell()=%x", DbStreamTell(pstm));
  745. return hres;
  746. }
  747. HRESULT IUnknown_GetClientDB(IUnknown *punk, IUnknown **ppdbc)
  748. {
  749. *ppdbc = NULL;
  750. IDeskBar *pdb;
  751. HRESULT hr = punk->QueryInterface(IID_PPV_ARG(IDeskBar, &pdb));
  752. if (SUCCEEDED(hr))
  753. {
  754. hr = pdb->GetClient(ppdbc);
  755. pdb->Release();
  756. }
  757. return hr;
  758. }
  759. HRESULT CCommonBrowser::_LoadToolbars(IStream* pstm)
  760. {
  761. DWORD dwVersion;
  762. TraceMsg(DM_PERSIST, "cbb.ltb enter(this=%x pstm=%x) tell()=%x", this, pstm, DbStreamTell(pstm));
  763. HRESULT hres = pstm->Read(&dwVersion, sizeof(dwVersion), NULL);
  764. if (hres == S_OK && dwVersion == c_BBSVersion)
  765. {
  766. DWORD count;
  767. hres = pstm->Read(&count, sizeof(count), NULL);
  768. if (hres == S_OK)
  769. {
  770. for (UINT i=0; i<count && SUCCEEDED(hres); i++)
  771. {
  772. DWORD cchName = 0;
  773. hres = pstm->Read(&cchName, sizeof(cchName), NULL);
  774. if (hres == S_OK)
  775. {
  776. WCHAR wszName[MAX_ITEMID];
  777. wszName[0] = 0;
  778. // if cchName >= ARRAYSIZE(wszName) then we're misaligned in the stream!
  779. if (cchName)
  780. {
  781. if (cchName<ARRAYSIZE(wszName))
  782. {
  783. hres = pstm->Read(wszName, cchName*sizeof(WCHAR), NULL);
  784. }
  785. else
  786. {
  787. hres = E_FAIL; // We are missaligned in the stream, let's stop attempting to load
  788. }
  789. }
  790. TraceMsg(DM_PERSIST, "cbb.ltb name=<%ls>", wszName);
  791. if (hres==S_OK)
  792. {
  793. IDockingWindow* pstb;
  794. TraceMsg(DM_PERSIST, "cbb.ltb enter OleLoadFromStream tell()=%x", DbStreamTell(pstm));
  795. hres = OleLoadFromStream(pstm, IID_PPV_ARG(IDockingWindow, &pstb));
  796. TraceMsg(DM_PERSIST, "cbb.ltb leave OleLoadFromStream tell()=%x", DbStreamTell(pstm));
  797. if (SUCCEEDED(hres))
  798. {
  799. IUnknown *pDbc = NULL;
  800. // nt5:216944: turn off size negotiation during
  801. // load. o.w. persisted size gets nuked.
  802. IUnknown_GetClientDB(pstb, &pDbc);
  803. if (pDbc)
  804. DBC_ExecDrag(pDbc, DRAG_MOVE);
  805. hres = AddToolbar(pstb, wszName[0] ? wszName : NULL, NULL);
  806. if (pDbc)
  807. {
  808. DBC_ExecDrag(pDbc, 0);
  809. pDbc->Release();
  810. }
  811. pstb->Release();
  812. }
  813. }
  814. }
  815. }
  816. }
  817. }
  818. else
  819. {
  820. hres = E_FAIL;
  821. }
  822. TraceMsg(DM_PERSIST, "cbb.ltb leave tell()=%x", DbStreamTell(pstm));
  823. return hres;
  824. }
  825. // }
  826. // *** IDockingWindowSite methods ***
  827. HRESULT CCommonBrowser::_GetBorderDWHelper(IUnknown* punkSrc, LPRECT prcBorder, BOOL bUseHmonitor)
  828. {
  829. UINT itb = _FindTBar(punkSrc);
  830. if (itb == (UINT)-1)
  831. {
  832. RIPMSG(0, "GetBorderDW: invalid punkSrc");
  833. return E_INVALIDARG;
  834. }
  835. else if (!prcBorder)
  836. {
  837. RIPMSG(0, "GetBorderDW: invalid prcBorder");
  838. return E_INVALIDARG;
  839. }
  840. TOOLBARITEM *ptbThis = _GetToolbarItem(itb);
  841. if (bUseHmonitor && ptbThis && ptbThis->hMon)
  842. {
  843. _pbsOuter->_GetEffectiveClientArea(prcBorder, ptbThis->hMon);
  844. }
  845. else
  846. {
  847. _pbsOuter->_GetEffectiveClientArea(prcBorder, NULL);
  848. }
  849. //
  850. // Subtract border area taken by "outer toolbars"
  851. //
  852. for (UINT i = 0; i < itb; i++)
  853. {
  854. TOOLBARITEM *ptbi = _GetToolbarItem(i);
  855. if (!bUseHmonitor || (ptbThis && (ptbi->hMon == ptbThis->hMon)))
  856. {
  857. prcBorder->left += ptbi->rcBorderTool.left;
  858. prcBorder->top += ptbi->rcBorderTool.top;
  859. prcBorder->right -= ptbi->rcBorderTool.right;
  860. prcBorder->bottom -= ptbi->rcBorderTool.bottom;
  861. }
  862. }
  863. return S_OK;
  864. }
  865. //
  866. // This is an implementation of IDockingWindowSite::GetBorderDW.
  867. //
  868. // This function returns a bounding rectangle for the specified toolbar
  869. // (by punkSrc). It gets the effective client area, then subtract border
  870. // area taken by "outer" toolbars.
  871. //
  872. HRESULT CCommonBrowser::GetBorderDW(IUnknown* punkSrc, LPRECT prcBorder)
  873. {
  874. return _GetBorderDWHelper(punkSrc, prcBorder, FALSE);
  875. }
  876. HRESULT CCommonBrowser::RequestBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pbw)
  877. {
  878. RIP(IS_VALID_READ_PTR(pbw, BORDERWIDTHS));
  879. return S_OK;
  880. }
  881. HRESULT CCommonBrowser::SetBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pbw)
  882. {
  883. UINT itb = _FindTBar(punkSrc);
  884. if (itb == (UINT)-1)
  885. {
  886. RIPMSG(0, "GetBorderDW: invalid punkSrc");
  887. return E_INVALIDARG;
  888. }
  889. _GetToolbarItem(itb)->rcBorderTool = *pbw;
  890. _pbsOuter->_ResizeNextBorder(itb + 1);
  891. return S_OK;
  892. }
  893. HRESULT CCommonBrowser::_ResizeNextBorderHelper(UINT itb, BOOL bUseHmonitor)
  894. {
  895. //
  896. // Starting with itb, look for the next toolbar on the same
  897. // monitor (if we care about the monitor).
  898. //
  899. IDockingWindow* ptbarNext = NULL;
  900. if ((int) itb < _GetToolbarCount())
  901. {
  902. TOOLBARITEM *ptbThis = _GetToolbarItem(itb);
  903. for (int i = itb; i < _GetToolbarCount(); i++)
  904. {
  905. TOOLBARITEM *ptbi = _GetToolbarItem(i);
  906. if (ptbi->ptbar && (!bUseHmonitor || (ptbi->hMon == ptbThis->hMon)))
  907. {
  908. //
  909. // Found it, we're done
  910. //
  911. ptbarNext = ptbi->ptbar;
  912. break;
  913. }
  914. }
  915. }
  916. if (ptbarNext)
  917. {
  918. //
  919. // Get the toolbar's docking window rect and resize the
  920. // border to that.
  921. //
  922. RECT rc;
  923. GetBorderDW(ptbarNext, &rc);
  924. ptbarNext->ResizeBorderDW(&rc, (IShellBrowser*)this, TRUE);
  925. }
  926. else
  927. {
  928. //
  929. // We didn't find a toolbar, so we must be at the end
  930. // of the list. Finish up by resizing the view.
  931. //
  932. _pbsOuter->_ResizeView();
  933. }
  934. return S_OK;
  935. }
  936. HRESULT CCommonBrowser::_ResizeNextBorder(UINT itb)
  937. {
  938. _ResizeNextBorderHelper(itb, FALSE);
  939. return S_OK;
  940. }
  941. //
  942. // Hack alert!
  943. //
  944. // IE grabs the focus via _FixToolbarFocus when it shouldn't. For example if a
  945. // java app in a seperate window contains an edit control and the address bar
  946. // had focus before the java app. In this scenario the first time a user types
  947. // in the edit control IE grabs back the focus. IE bug#59007.
  948. //
  949. // To prevent IE from incorrectly grabbing the focus this fuction checks that
  950. // top level parent of the toolbar is the same as the top level parent of the
  951. // window that has focus.
  952. //
  953. BOOL CCommonBrowser::_TBWindowHasFocus(UINT itb)
  954. {
  955. ASSERT(itb < ITB_MAX);
  956. BOOL fRet = TRUE;
  957. HWND hwndFocus = GetFocus();
  958. while (GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD)
  959. hwndFocus = GetParent(hwndFocus);
  960. if (hwndFocus)
  961. {
  962. TOOLBARITEM *pti = _GetToolbarItem(itb);
  963. if (pti && pti->ptbar)
  964. {
  965. HWND hwndTB;
  966. if (SUCCEEDED(pti->ptbar->GetWindow(&hwndTB)) && hwndTB)
  967. {
  968. fRet = (S_OK == SHIsChildOrSelf(hwndFocus, hwndTB));
  969. }
  970. }
  971. }
  972. return fRet;
  973. }
  974. void DestroyZoneIconNameCache(void)
  975. {
  976. if (g_pZoneIconNameCache)
  977. {
  978. PZONEICONNAMECACHE pzinc = g_pZoneIconNameCache;
  979. for (DWORD i = 0; i < g_dwZoneCount; i++)
  980. {
  981. if (pzinc->hiconZones)
  982. DestroyIcon((HICON)pzinc->hiconZones);
  983. pzinc++;
  984. }
  985. LocalFree(g_pZoneIconNameCache);
  986. g_pZoneIconNameCache = NULL;
  987. g_dwZoneCount = 0;
  988. }
  989. }
  990. DWORD CCommonBrowser::_CacheZonesIconsAndNames(BOOL fRefresh)
  991. {
  992. ASSERTCRITICAL;
  993. if (g_pZoneIconNameCache) // If we've already cached the zones, just return the zone count unless we want to refresh cache
  994. {
  995. if (fRefresh)
  996. {
  997. DestroyZoneIconNameCache();
  998. }
  999. else
  1000. return(g_dwZoneCount);
  1001. }
  1002. // Create ZoneManager
  1003. if (!_pizm)
  1004. CoCreateInstance(CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IInternetZoneManager, &_pizm));
  1005. if (_pizm)
  1006. {
  1007. DWORD dwZoneEnum;
  1008. if (SUCCEEDED(_pizm->CreateZoneEnumerator(&dwZoneEnum, &g_dwZoneCount, 0)))
  1009. {
  1010. if ((g_pZoneIconNameCache = (PZONEICONNAMECACHE)LocalAlloc(LPTR, g_dwZoneCount * sizeof(ZONEICONNAMECACHE))) == NULL)
  1011. {
  1012. g_dwZoneCount = 0;
  1013. return 0;
  1014. }
  1015. for (int nIndex=0; (DWORD)nIndex < g_dwZoneCount; nIndex++)
  1016. {
  1017. DWORD dwZone;
  1018. ZONEATTRIBUTES za = {sizeof(ZONEATTRIBUTES)};
  1019. _pizm->GetZoneAt(dwZoneEnum, nIndex, &dwZone);
  1020. // get the zone attributes for this zone
  1021. _pizm->GetZoneAttributes(dwZone, &za);
  1022. StringCchCopyW(g_pZoneIconNameCache[nIndex].szZonesName, ARRAYSIZE(g_pZoneIconNameCache[nIndex].szZonesName), za.szDisplayName);
  1023. StringCchCopyW(g_pZoneIconNameCache[nIndex].szIconPath, ARRAYSIZE(g_pZoneIconNameCache[nIndex].szIconPath), za.szIconPath);
  1024. g_pZoneIconNameCache[nIndex].hiconZones = 0; // Load the hIcon on demand
  1025. }
  1026. _pizm->DestroyZoneEnumerator(dwZoneEnum);
  1027. }
  1028. }
  1029. return g_dwZoneCount;
  1030. }
  1031. // zero's out pIcon & pszName on failure
  1032. BOOL CCommonBrowser::_GetCachedZoneIconAndName(DWORD lZone, HICON *pIcon, LPTSTR pszName, DWORD cch)
  1033. {
  1034. BOOL bRet = FALSE;
  1035. *pIcon = NULL;
  1036. pszName[0] = 0;
  1037. ENTERCRITICAL;
  1038. if (lZone < _CacheZonesIconsAndNames(FALSE))
  1039. {
  1040. ZONEICONNAMECACHE *pzinc = &g_pZoneIconNameCache[lZone];
  1041. // if we haven't yet cached the icon for this zone, extract it now
  1042. // REVIEW: worth pulling the extraction outside the critsec?
  1043. if (!pzinc->hiconZones)
  1044. {
  1045. // Zone icons are in two formats.
  1046. // wininet.dll#1200 where 1200 is the res id.
  1047. // or foo.ico directly pointing to an icon file.
  1048. // search for the '#'
  1049. // # is a valid filename character
  1050. LPWSTR pwsz = StrChrW(pzinc->szIconPath, TEXTW('#'));
  1051. WORD iIcon = 0;
  1052. if (pwsz)
  1053. {
  1054. // if we found it, then we have the foo.dll#00001200 format
  1055. pwsz[0] = TEXTW('\0');
  1056. iIcon = (WORD)StrToIntW(pwsz+1);
  1057. ExtractIconExW(pzinc->szIconPath,(UINT)(-1*iIcon), NULL, &pzinc->hiconZones, 1);
  1058. }
  1059. else
  1060. pzinc->hiconZones = (HICON)ExtractAssociatedIconExW(HINST_THISDLL, pzinc->szIconPath, (LPWORD)&iIcon, &iIcon);
  1061. // If mirrored system, mirror icon so that it get unmirrored again when displayed
  1062. if (IS_BIDI_LOCALIZED_SYSTEM())
  1063. {
  1064. MirrorIcon(&pzinc->hiconZones, NULL);
  1065. }
  1066. }
  1067. *pIcon = CopyIcon(pzinc->hiconZones);
  1068. StringCchCopyW(pszName, cch, pzinc->szZonesName); // truncation ok (currently only used for display)
  1069. bRet = TRUE;
  1070. }
  1071. LEAVECRITICAL;
  1072. return bRet;
  1073. }
  1074. BOOL _QITest(IUnknown* punk, REFIID riid);
  1075. BOOL CCommonBrowser::_ShouldTranslateAccelerator(MSG* pmsg)
  1076. {
  1077. //
  1078. // We should only translate an acclerator if
  1079. //
  1080. // (a) the window is the frame or a child of the frame
  1081. // or a child of a defview window (NT5 Bug # 357186).
  1082. // (need to check this because you can have, for
  1083. // example, a toplevel java applet window running
  1084. // on our thread)
  1085. //
  1086. // and
  1087. //
  1088. // (b) it's on our thread (need to check this because
  1089. // old-style OLE controls on a web page can run
  1090. // on the desktop thread)
  1091. //
  1092. BOOL fTranslate = FALSE;
  1093. fTranslate = (SHIsChildOrSelf(_pbbd->_hwnd, pmsg->hwnd) == S_OK);
  1094. if (!fTranslate)
  1095. {
  1096. HWND hwnd = NULL;
  1097. if (_pbbd->_psv && (_QITest(SAFECAST(_pbbd->_psv, IUnknown*), IID_CDefView))
  1098. && SUCCEEDED(_pbbd->_psv->GetWindow(&hwnd)))
  1099. {
  1100. fTranslate = (SHIsChildOrSelf(hwnd, pmsg->hwnd) == S_OK);
  1101. }
  1102. }
  1103. if (fTranslate)
  1104. {
  1105. DWORD dwThread = GetWindowThreadProcessId(_pbbd->_hwnd, NULL);
  1106. HWND hwndMsg = pmsg->hwnd;
  1107. while (GetWindowLong(hwndMsg, GWL_STYLE) & WS_CHILD)
  1108. {
  1109. hwndMsg = GetParent(hwndMsg);
  1110. }
  1111. DWORD dwMsgThread = hwndMsg ? GetWindowThreadProcessId(hwndMsg, NULL) : 0;
  1112. if (dwThread == dwMsgThread)
  1113. {
  1114. return TRUE;
  1115. }
  1116. }
  1117. return FALSE;
  1118. }
  1119. HRESULT CCommonBrowser::v_MayTranslateAccelerator(MSG* pmsg)
  1120. {
  1121. if (!(WM_KEYFIRST <= pmsg->message && pmsg->message <= WM_KEYLAST))
  1122. return S_FALSE;
  1123. BOOL fToolbarHasFocus = _HasToolbarFocus();
  1124. if (fToolbarHasFocus)
  1125. {
  1126. ASSERT(_get_itbLastFocus() < (UINT)_GetToolbarCount());
  1127. // toolbar has focus -- give it first chance to translate
  1128. //
  1129. // Notes:
  1130. // Notice that we don't give a chance to translate its accelerators
  1131. // to other toolbars. This is by-design right now. We might want to
  1132. // change it later, but it will be tricky to do it right.
  1133. //
  1134. if (IUnknown_TranslateAcceleratorIO(_GetToolbarItem(_get_itbLastFocus())->ptbar, pmsg) == S_OK)
  1135. return(S_OK);
  1136. }
  1137. else
  1138. {
  1139. UINT itbLastFocus = _get_itbLastFocus();
  1140. if (itbLastFocus != ITB_VIEW && _TBWindowHasFocus(itbLastFocus))
  1141. {
  1142. // view got focus back, update cache
  1143. _FixToolbarFocus();
  1144. }
  1145. // view has focus -- give it first chance to translate
  1146. // View doesn't necessarily have focus. Added a check.
  1147. //
  1148. if (_pbbd->_psv) // If we have a shell view
  1149. {
  1150. HWND hwnd;
  1151. // Note: Not everyone supports GetWindow (go figure)
  1152. // In which case, we try the GetFocus() window.
  1153. if (FAILED(_pbbd->_psv->GetWindow(&hwnd)))
  1154. {
  1155. hwnd = GetFocus();
  1156. }
  1157. // check if view or its child has focus
  1158. // before it checked for browser or a child but if user
  1159. // clicked on Show Desktop in quick launch
  1160. // defview is deparented from the desktop and this call
  1161. // fails which prevents tabbing to Active Desktop
  1162. // (done in CDefView::TranslateAccelerator
  1163. if (SHIsChildOrSelf(hwnd, pmsg->hwnd) == S_OK)
  1164. {
  1165. if (_pbbd->_psv->TranslateAccelerator(pmsg) == S_OK) // and the shell view translated the message
  1166. {
  1167. return S_OK;
  1168. }
  1169. }
  1170. }
  1171. }
  1172. // Then, handle our own accelerators (with special code for TAB key).
  1173. if (_ShouldTranslateAccelerator(pmsg))
  1174. {
  1175. if (IsVK_TABCycler(pmsg))
  1176. return _CycleFocus(pmsg);
  1177. BOOL fFwdItbar = FALSE;
  1178. // FEATURE: Why not just include F4 and Alt-D in ACCEL_MERGE,
  1179. // which gets localized?
  1180. if (pmsg->message == WM_KEYDOWN && pmsg->wParam == VK_F4)
  1181. {
  1182. fFwdItbar = TRUE;
  1183. }
  1184. if (pmsg->message == WM_SYSCHAR)
  1185. {
  1186. static CHAR szAccel[2] = "\0";
  1187. CHAR szChar [2] = "\0";
  1188. if ('\0' == szAccel[0])
  1189. MLLoadStringA(IDS_ADDRBAND_ACCELLERATOR, szAccel, ARRAYSIZE(szAccel));
  1190. szChar[0] = (CHAR)pmsg->wParam;
  1191. if (lstrcmpiA(szChar,szAccel) == 0)
  1192. {
  1193. fFwdItbar = TRUE;
  1194. }
  1195. }
  1196. if (fFwdItbar)
  1197. {
  1198. IDockingWindow *ptbar = _GetToolbarItem(ITB_ITBAR)->ptbar;
  1199. if (IUnknown_TranslateAcceleratorIO(ptbar, pmsg) == S_OK)
  1200. return S_OK;
  1201. }
  1202. if (TranslateAcceleratorSB(pmsg, 0) == S_OK)
  1203. return S_OK;
  1204. }
  1205. // If a toolbar has focus, we ask the view last.
  1206. if (fToolbarHasFocus)
  1207. {
  1208. if (_pbbd->_psv && _pbbd->_psv->TranslateAccelerator(pmsg) == S_OK)
  1209. return S_OK;
  1210. }
  1211. return S_FALSE;
  1212. }
  1213. HRESULT CCommonBrowser::_CycleFocus(LPMSG lpMsg)
  1214. {
  1215. UINT citb = 1;
  1216. if (GetKeyState(VK_SHIFT) < 0)
  1217. {
  1218. // go backward
  1219. citb = (UINT)-1;
  1220. }
  1221. UINT itbCur = _get_itbLastFocus();
  1222. //
  1223. // Find the next visible toolbar and set the focus to it. Otherwise,
  1224. // set the focus to the view window.
  1225. //
  1226. HWND hwndFocusNext;
  1227. TOOLBARITEM *ptbi;
  1228. if (_pbsOuter->v_MayGetNextToolbarFocus(lpMsg, itbCur, citb, &ptbi, &hwndFocusNext) == S_OK)
  1229. {
  1230. // Found a toolbar to take focus, nothing more to do.
  1231. // FEATURE: do we (or caller) need to do SetStatusTextSB?
  1232. // It looks like no one is doing it right now.
  1233. return S_OK;
  1234. }
  1235. if (!(hwndFocusNext && IsWindowVisible(hwndFocusNext)))
  1236. {
  1237. // Didn't find anyone. Set focus on the view.
  1238. hwndFocusNext = _pbbd->_hwndView;
  1239. }
  1240. _SetFocus(ptbi, hwndFocusNext, lpMsg);
  1241. return S_OK;
  1242. }
  1243. //*** _MayUIActTAB -- attempt TAB-activation of IOleWindow/IInputObject
  1244. // ENTRY/EXIT
  1245. // powEtc IOleWindow/IInputObject pair.
  1246. // lpMsg msg causing activation (may be NULL) (typically TAB)
  1247. // fShowing currently showing?
  1248. // phwnd [OUT] hwnd for object
  1249. // hr [RET] UIActivateIO result, plus E_FAIL
  1250. // DESCRIPTION
  1251. // when TABing we only want to activate certain guys, viz. those who are
  1252. // currently showing, visible, and willing to accept activation.
  1253. HRESULT _MayUIActTAB(IOleWindow *pow, LPMSG lpMsg, BOOL fShowing, HWND *phwnd)
  1254. {
  1255. HRESULT hr = E_FAIL;
  1256. HWND hwnd = 0;
  1257. if (pow && fShowing)
  1258. {
  1259. hr = pow->GetWindow(&hwnd);
  1260. if (IsWindowVisible(hwnd))
  1261. hr = IUnknown_UIActivateIO(pow, TRUE, lpMsg);
  1262. }
  1263. if (phwnd)
  1264. *phwnd = hwnd;
  1265. return hr;
  1266. }
  1267. //*** v_MayGetNextToolbarFocus -- get next in TAB order (and maybe SetFocus)
  1268. // ENTRY/EXIT
  1269. // hres E_FAIL for no candidate, S_FALSE for candidate, S_OK for 100% done
  1270. // (S_OK only used by derived class for now)
  1271. HRESULT CCommonBrowser::v_MayGetNextToolbarFocus(LPMSG lpMsg,
  1272. UINT itbCur, int citb,
  1273. TOOLBARITEM ** pptbi, HWND * phwnd)
  1274. {
  1275. HWND hwnd = 0;
  1276. TOOLBARITEM *ptbi = NULL;
  1277. if (itbCur == ITB_VIEW)
  1278. {
  1279. ASSERT(citb == 1 || citb == -1);
  1280. if (citb == 1)
  1281. itbCur = 0;
  1282. else
  1283. itbCur = _GetToolbarCount() - 1;
  1284. }
  1285. else
  1286. {
  1287. itbCur += citb;
  1288. }
  1289. // (semi-tricky: loop on an unsigned so get 0..n or n..0 w/ single loop)
  1290. for (UINT i = itbCur; i < (UINT)_GetToolbarCount(); i += citb)
  1291. {
  1292. ptbi = _GetToolbarItem(i);
  1293. // NOTE: _MayUIActTAB checks ptbi->ptbar for NULL
  1294. if (_MayUIActTAB(ptbi->ptbar, lpMsg, ptbi->fShow, &hwnd) == S_OK)
  1295. {
  1296. *pptbi = ptbi;
  1297. *phwnd = hwnd;
  1298. return S_FALSE;
  1299. }
  1300. }
  1301. *pptbi = NULL;
  1302. *phwnd = 0;
  1303. return E_FAIL;
  1304. }
  1305. BOOL _QITest(IUnknown* punk, REFIID riid)
  1306. {
  1307. ASSERT(punk);
  1308. BOOL fRet = FALSE;
  1309. if (SUCCEEDED(punk->QueryInterface(riid, (void**)&punk)))
  1310. {
  1311. punk->Release();
  1312. fRet = TRUE;
  1313. }
  1314. return fRet;
  1315. }
  1316. __inline BOOL _IsV4DefView(IShellView* psv)
  1317. {
  1318. if (GetUIVersion() < 5)
  1319. return _QITest(SAFECAST(psv, IUnknown*), IID_CDefView);
  1320. return FALSE;
  1321. }
  1322. __inline BOOL _IsOldView(IShellView* psv)
  1323. {
  1324. //
  1325. // Current CDocObjectView and v4 and greater CDefView
  1326. // implement IShellView2
  1327. //
  1328. return (FALSE == _QITest(SAFECAST(psv, IUnknown*), IID_IShellView2));
  1329. }
  1330. HRESULT CCommonBrowser::_SetFocus(TOOLBARITEM *ptbi, HWND hwnd, LPMSG lpMsg)
  1331. {
  1332. // Clear the upper layer of status text
  1333. SetStatusTextSB(NULL);
  1334. if (hwnd == _pbbd->_hwndView)
  1335. {
  1336. if (_pbbd->_psv)
  1337. {
  1338. BOOL fTranslate = TRUE, fActivate = TRUE;
  1339. if (!lpMsg)
  1340. {
  1341. // NULL message, so nothing to translate
  1342. fTranslate = FALSE;
  1343. }
  1344. else if (_IsV4DefView(_pbbd->_psv) || _IsOldView(_pbbd->_psv))
  1345. {
  1346. // These views expect only to be UI-activated
  1347. fTranslate = FALSE;
  1348. }
  1349. else if (IsVK_CtlTABCycler(lpMsg))
  1350. {
  1351. // Don't let trident translate ctl-tab. Since it's always
  1352. // UI-active, it will reject focus.
  1353. fTranslate = FALSE;
  1354. }
  1355. else
  1356. {
  1357. // Normal case - do not activate the view. TranslateAccelerator will do the right thing.
  1358. fActivate = FALSE;
  1359. }
  1360. if (fActivate)
  1361. _UIActivateView(SVUIA_ACTIVATE_FOCUS);
  1362. if (fTranslate)
  1363. _pbbd->_psv->TranslateAccelerator(lpMsg);
  1364. }
  1365. else
  1366. {
  1367. // IE3 compat (we used to do for all hwnd's)
  1368. SetFocus(hwnd);
  1369. }
  1370. // Update our cache
  1371. _OnFocusChange(ITB_VIEW);
  1372. }
  1373. return S_OK;
  1374. }
  1375. HRESULT CCommonBrowser::_FindActiveTarget(REFIID riid, void **ppvOut)
  1376. {
  1377. HRESULT hres = E_FAIL;
  1378. *ppvOut = NULL;
  1379. BOOL fToolbarHasFocus = _HasToolbarFocus();
  1380. if (fToolbarHasFocus)
  1381. {
  1382. hres = _GetToolbarItem(_get_itbLastFocus())->ptbar->QueryInterface(riid, ppvOut);
  1383. }
  1384. else if (_pbbd->_psv)
  1385. {
  1386. if (_get_itbLastFocus() != ITB_VIEW)
  1387. {
  1388. // view got focus back, update cache
  1389. _FixToolbarFocus();
  1390. }
  1391. if (_pbbd->_psv != NULL)
  1392. {
  1393. hres = _pbbd->_psv->QueryInterface(riid, ppvOut);
  1394. }
  1395. }
  1396. return hres;
  1397. }
  1398. BOOL CCommonBrowser::_HasToolbarFocus(void)
  1399. {
  1400. UINT uLast = _get_itbLastFocus();
  1401. if (uLast < ITB_MAX)
  1402. {
  1403. TOOLBARITEM *ptbi = _GetToolbarItem(uLast);
  1404. if (ptbi)
  1405. {
  1406. // NOTE: IUnknown_HasFocusIO checks ptbi->ptbar for NULL
  1407. return (IUnknown_HasFocusIO(ptbi->ptbar) == S_OK);
  1408. }
  1409. }
  1410. return FALSE;
  1411. }
  1412. //*** _FixToolbarFocus -- fake a UIActivate from the view
  1413. // NOTES
  1414. // The view never goes 'truly' non-UIActive so we never get notified when
  1415. // it goes 'truly' UIActive. we fake it here by mucking w/ our cache.
  1416. //
  1417. HRESULT CCommonBrowser::_FixToolbarFocus(void)
  1418. {
  1419. _OnFocusChange(ITB_VIEW); // ... and update cache
  1420. _UIActivateView(SVUIA_ACTIVATE_FOCUS); // steal the focus
  1421. return S_OK;
  1422. }
  1423. HRESULT CCommonBrowser::_OnFocusChange(UINT itb)
  1424. {
  1425. UINT itbPrevFocus = _get_itbLastFocus();
  1426. if (itbPrevFocus != itb)
  1427. {
  1428. //
  1429. // If the view is losing the focus (within the explorer),
  1430. // we should let it know. We should update _itbLastFocus before
  1431. // calling UIActivate, because it will call our InsertMenu back.
  1432. //
  1433. _put_itbLastFocus(itb);
  1434. if (itbPrevFocus == ITB_VIEW)
  1435. {
  1436. // DocHost will ignore this (since deactivating the view is taboo).
  1437. // ShellView will respect it (so menu merge works).
  1438. _UIActivateView(SVUIA_ACTIVATE_NOFOCUS);
  1439. }
  1440. else
  1441. {
  1442. IDockingWindow *ptb;
  1443. // FEATURE: uh-oh not sure what we do if NULL
  1444. // we do get NULL the 1st time we click on the SearchBand
  1445. ptb = _GetToolbarItem(itbPrevFocus)->ptbar;
  1446. IUnknown_UIActivateIO(ptb, FALSE, NULL);
  1447. }
  1448. }
  1449. return S_OK;
  1450. }
  1451. HRESULT CCommonBrowser::OnFocusChangeIS(IUnknown* punkSrc, BOOL fSetFocus)
  1452. {
  1453. UINT itb = _FindTBar(punkSrc);
  1454. if (itb == ITB_VIEW)
  1455. {
  1456. return E_INVALIDARG;
  1457. }
  1458. //
  1459. // Note that we keep track of which toolbar got the focus last.
  1460. // We can't reliably monitor the kill focus event because OLE's
  1461. // window procedure hook (for merged menu dispatching code) changes
  1462. // focus around.
  1463. //
  1464. if (fSetFocus)
  1465. {
  1466. _OnFocusChange(itb);
  1467. // Then, notify it to the shellview.
  1468. if (_pbbd->_pctView)
  1469. {
  1470. _pbbd->_pctView->Exec(NULL, OLECMDID_ONTOOLBARACTIVATED, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  1471. }
  1472. }
  1473. else if (itb == _get_itbLastFocus())
  1474. {
  1475. //
  1476. // The toolbar which currently has focus is giving it up.
  1477. // Move focus to the view when this happens.
  1478. //
  1479. _FixToolbarFocus();
  1480. }
  1481. return S_OK;
  1482. }
  1483. //*** toolbar/view broadcast {
  1484. //*** _ExecChildren -- broadcast Exec to view and toolbars
  1485. // NOTES
  1486. // we might do *both* punkBar and fBroadcast if we want to send stuff
  1487. // to both the view and to all toolbars, e.g. 'stop' or 'refresh'.
  1488. //
  1489. // NOTE: n.b. the tray isn't a real toolbar, so it won't get called (sigh...).
  1490. HRESULT CCommonBrowser::_ExecChildren(IUnknown *punkBar, BOOL fBroadcast, const GUID *pguidCmdGroup,
  1491. DWORD nCmdID, DWORD nCmdexecopt,
  1492. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1493. {
  1494. // 1st, send to specified guy (if requested)
  1495. if (punkBar != NULL)
  1496. {
  1497. // send to specified guy
  1498. _pbsInner->_ExecChildren(punkBar, FALSE, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1499. }
  1500. // 2nd, broadcast to all (if requested)
  1501. if (fBroadcast)
  1502. {
  1503. for (int itb = 0; itb<_GetToolbarCount(); itb++)
  1504. {
  1505. TOOLBARITEM *ptbi = _GetToolbarItem(itb);
  1506. // NOTE: IUnknown_Exec checks ptbi->ptbar for NULL
  1507. IUnknown_Exec(ptbi->ptbar, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1508. }
  1509. }
  1510. return S_OK;
  1511. }
  1512. HRESULT CCommonBrowser::_SendChildren(HWND hwndBar, BOOL fBroadcast, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1513. {
  1514. // 1st, send to specified guy (if requested)
  1515. if (hwndBar != NULL)
  1516. {
  1517. // send to specified guy
  1518. _pbsInner->_SendChildren(hwndBar, FALSE, uMsg, wParam, lParam);
  1519. }
  1520. // 2nd, broadcast to all (if requested)
  1521. if (fBroadcast)
  1522. {
  1523. for (int itb = 0; itb < _GetToolbarCount(); itb++)
  1524. {
  1525. HWND hwndToolbar;
  1526. TOOLBARITEM *ptbi = _GetToolbarItem(itb);
  1527. if (ptbi->ptbar && SUCCEEDED(ptbi->ptbar->GetWindow(&hwndToolbar)))
  1528. SendMessage(hwndToolbar, uMsg, wParam, lParam);
  1529. }
  1530. }
  1531. return S_OK;
  1532. }
  1533. LRESULT CCommonBrowser::ForwardViewMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1534. {
  1535. return _pbbd->_hwndView ? SendMessage(_pbbd->_hwndView, uMsg, wParam, lParam) : 0;
  1536. }
  1537. // }
  1538. TOOLBARITEM *CCommonBrowser::_GetToolbarItem(int itb)
  1539. {
  1540. ASSERT(itb != ITB_VIEW);
  1541. ASSERT(itb < ITB_MAX);
  1542. // ==0 for semi-bogus CBB::_OnFocusChange code
  1543. ASSERT(itb < FDSA_GetItemCount(&_fdsaTBar) || itb == 0);
  1544. TOOLBARITEM *ptbi = FDSA_GetItemPtr(&_fdsaTBar, itb, TOOLBARITEM);
  1545. ASSERT(ptbi != NULL);
  1546. return ptbi;
  1547. }
  1548. HRESULT CCommonBrowser::SetAcceleratorMenu(HACCEL hacc)
  1549. {
  1550. if (hacc != _hacc)
  1551. {
  1552. if (_hacc)
  1553. {
  1554. DestroyAcceleratorTable(_hacc);
  1555. }
  1556. _hacc = hacc;
  1557. }
  1558. return S_OK;
  1559. }
  1560. HRESULT _ConvertPathToPidl(IBrowserService2 *pbs, HWND hwnd, LPCTSTR pszPath, LPITEMIDLIST * ppidl)
  1561. {
  1562. HRESULT hres = E_FAIL;
  1563. WCHAR wszCmdLine[MAX_URL_STRING]; // must be with pszPath
  1564. TCHAR szParsedUrl[MAX_URL_STRING] = {'\0'};
  1565. TCHAR szFixedUrl[MAX_URL_STRING];
  1566. DWORD dwUrlLen = ARRAYSIZE(szParsedUrl);
  1567. LPCTSTR pUrlToUse = pszPath;
  1568. // Copy the command line into a temporary buffer
  1569. // so we can remove the surrounding quotes (if
  1570. // they exist)
  1571. hres = StringCchCopy(szFixedUrl, ARRAYSIZE(szFixedUrl), pszPath);
  1572. if (SUCCEEDED(hres))
  1573. {
  1574. PathUnquoteSpaces(szFixedUrl);
  1575. if (ParseURLFromOutsideSource(szFixedUrl, szParsedUrl, &dwUrlLen, NULL))
  1576. pUrlToUse = szParsedUrl;
  1577. SHTCharToUnicode(pUrlToUse, wszCmdLine, ARRAYSIZE(wszCmdLine));
  1578. hres = pbs->IEParseDisplayName(CP_ACP, wszCmdLine, ppidl);
  1579. pbs->DisplayParseError(hres, wszCmdLine);
  1580. }
  1581. else
  1582. {
  1583. *ppidl = NULL;
  1584. }
  1585. return hres;
  1586. }