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.

2032 lines
53 KiB

  1. #include "priv.h"
  2. #include "sccls.h"
  3. #include "bands.h"
  4. #include "util.h"
  5. #include "resource.h"
  6. #include "dhuihand.h"
  7. #include "droptgt.h"
  8. #include "iface.h"
  9. #include "isfband.h"
  10. #include "itbdrop.h"
  11. #include "browband.h"
  12. #include <varutil.h>
  13. #include "legacy.h"
  14. #include "mnbandid.h"
  15. #include "mluisupp.h"
  16. #include "inetsmgr.h"
  17. #ifdef UNIX
  18. #include "unixstuff.h"
  19. #endif
  20. #define DM_PERSIST 0 // trace IPS::Load, ::Save, etc.
  21. #define DM_MENU 0 // menu code
  22. #define DM_FOCUS 0 // focus
  23. #define DM_FOCUS2 0 // like DM_FOCUS, but verbose
  24. //*** CBrowserBand {
  25. //
  26. ////////////////
  27. /// BrowserOC band
  28. CBrowserBand::CBrowserBand() :
  29. CToolBand()
  30. {
  31. _fBlockSIDProxy = TRUE;
  32. _dwModeFlags = DBIMF_FIXEDBMP | DBIMF_VARIABLEHEIGHT;
  33. _sizeMin.cx = _sizeMin.cy = 0;
  34. _sizeMax.cx = _sizeMax.cy = 32000;
  35. _fCustomTitle = FALSE;
  36. return;
  37. }
  38. CBrowserBand::~CBrowserBand()
  39. {
  40. if (_pidl)
  41. ILFree(_pidl);
  42. }
  43. HRESULT CBrowserBand::QueryInterface(REFIID riid, void **ppvObj)
  44. {
  45. static const QITAB qit[] = {
  46. QITABENT(CBrowserBand, IContextMenu), // IID_IContextMenu
  47. QITABENT(CBrowserBand, IWinEventHandler), // IID_IWinEventHandler
  48. QITABENT(CBrowserBand, IDispatch), // IID_IDispatch
  49. QITABENT(CBrowserBand, IPersistPropertyBag), // IID_IPersistPropertyBag
  50. QITABENT(CBrowserBand, IBrowserBand),
  51. { 0 },
  52. };
  53. HRESULT hres = QISearch(this, qit, riid, ppvObj);
  54. if (FAILED(hres))
  55. hres = CToolBand::QueryInterface(riid, ppvObj);
  56. return hres;
  57. }
  58. HRESULT CBrowserBand_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  59. {
  60. // aggregation checking is handled in class factory
  61. CBrowserBand * p = new CBrowserBand();
  62. if (p)
  63. {
  64. *ppunk = SAFECAST(p, IDeskBand *);
  65. return S_OK;
  66. }
  67. return E_OUTOFMEMORY;
  68. }
  69. HRESULT SHCreateBandForPidl(LPCITEMIDLIST pidl, IUnknown** ppunk, BOOL fAllowBrowserBand)
  70. {
  71. IDeskBand *ptb = NULL;
  72. BOOL fBrowserBand;
  73. DWORD dwAttrib = SFGAO_FOLDER | SFGAO_BROWSABLE;
  74. // if it's on the file system, we still might want to create a browser
  75. // band if it's a docobj (including .htm file)
  76. IEGetAttributesOf(pidl, &dwAttrib);
  77. switch (dwAttrib & (SFGAO_FOLDER | SFGAO_BROWSABLE))
  78. {
  79. case (SFGAO_FOLDER | SFGAO_BROWSABLE):
  80. TraceMsg(TF_WARNING, "SHCreateBandForPidl() Find out what the caller wants. Last time we checked, nobody would set this - what does the caller want?");
  81. case SFGAO_BROWSABLE:
  82. fBrowserBand = TRUE;
  83. break;
  84. case SFGAO_FOLDER:
  85. fBrowserBand = FALSE;
  86. break;
  87. default:
  88. // if it's not a folder nor a browseable object, we can't host it.
  89. // Happens when use drags a text file and we want to turn off the
  90. // drop to create a band.
  91. return E_FAIL;
  92. }
  93. // this was a drag of a link or folder
  94. if (fBrowserBand)
  95. {
  96. if (fAllowBrowserBand)
  97. {
  98. // create browser to show web sites
  99. ptb = CBrowserBand_Create(pidl);
  100. }
  101. }
  102. else
  103. {
  104. // create an ISF band to show folders as hotlinks
  105. CISFBand_CreateEx(NULL, pidl, IID_PPV_ARG(IDeskBand, &ptb));
  106. }
  107. *ppunk = ptb;
  108. if (ptb)
  109. return S_OK;
  110. return E_OUTOFMEMORY;
  111. }
  112. HRESULT CBrowserBand::CloseDW(DWORD dw)
  113. {
  114. _Connect(FALSE);
  115. return CToolBand::CloseDW(dw);
  116. }
  117. void CBrowserBand::_Connect(BOOL fConnect)
  118. {
  119. ConnectToConnectionPoint(SAFECAST(this, IDeskBand*), DIID_DWebBrowserEvents2, fConnect,
  120. _pauto, &_dwcpCookie, NULL);
  121. }
  122. /////////////////////////////////////////////////////////////////////////////
  123. // IDispatch::Invoke
  124. /////////////////////////////////////////////////////////////////////////////
  125. HRESULT CBrowserBand::Invoke
  126. (
  127. DISPID dispidMember,
  128. REFIID riid,
  129. LCID lcid,
  130. WORD wFlags,
  131. DISPPARAMS * pdispparams,
  132. VARIANT * pvarResult,
  133. EXCEPINFO * pexcepinfo,
  134. UINT * puArgErr
  135. )
  136. {
  137. ASSERT(pdispparams);
  138. if(!pdispparams)
  139. return E_INVALIDARG;
  140. //
  141. // NOTES: If we have a custom title, we don't need to process this call.
  142. // This code assumes DISPID_TITLECHANGE is the only id we support.
  143. // If somebody add any other, move this check below.
  144. //
  145. if (_fCustomTitle)
  146. return (S_OK);
  147. switch (dispidMember)
  148. {
  149. case DISPID_TITLECHANGE:
  150. {
  151. int iArg = pdispparams->cArgs -1;
  152. if (iArg == 0 &&
  153. (pdispparams->rgvarg[iArg].vt == VT_BSTR)) {
  154. BSTR pTitle = pdispparams->rgvarg[iArg].bstrVal;
  155. StrCpyNW(_wszTitle, pTitle, ARRAYSIZE(_wszTitle));
  156. _BandInfoChanged();
  157. }
  158. break;
  159. }
  160. }
  161. return S_OK;
  162. }
  163. ///// impl of IServiceProvider
  164. HRESULT CBrowserBand::QueryService(REFGUID guidService,
  165. REFIID riid, void **ppvObj)
  166. {
  167. *ppvObj = NULL; // assume error
  168. if (_fBlockSIDProxy && IsEqualGUID(guidService, SID_SProxyBrowser)) {
  169. return E_FAIL;
  170. }
  171. else if (IsEqualGUID(guidService, SID_STopFrameBrowser)) {
  172. // block this so SearchBand doesn't end up in global history
  173. return E_FAIL;
  174. }
  175. else if (_fBlockDrop && IsEqualGUID(guidService, SID_SDropBlocker))
  176. {
  177. return QueryInterface(riid, ppvObj);
  178. }
  179. return CToolBand::QueryService(guidService, riid, ppvObj);
  180. }
  181. HRESULT CBrowserBand::SetSite(IUnknown* punkSite)
  182. {
  183. CToolBand::SetSite(punkSite);
  184. if (punkSite != NULL) {
  185. if (!_hwnd)
  186. _CreateOCHost();
  187. } else {
  188. ATOMICRELEASE(_pauto);
  189. ATOMICRELEASE(_poipao);
  190. }
  191. return S_OK;
  192. }
  193. //*** CBrowserBand::IInputObject::* {
  194. HRESULT CBrowserBand::TranslateAcceleratorIO(LPMSG lpMsg)
  195. {
  196. #ifdef DEBUG
  197. if (lpMsg && lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F12) {
  198. // temp debug test code
  199. _DebugTestCode();
  200. }
  201. #endif
  202. if (_poipao)
  203. return _poipao->TranslateAccelerator(lpMsg);
  204. return S_FALSE;
  205. }
  206. HRESULT CBrowserBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
  207. {
  208. int iVerb = fActivate ? OLEIVERB_UIACTIVATE : OLEIVERB_INPLACEACTIVATE;
  209. HRESULT hr = OCHost_DoVerb(_hwnd, iVerb, lpMsg);
  210. // OCHost UIActivate is different than IInputObject::UIActivateIO. It
  211. // doesn't do anything with the lpMsg parameter. So, we need to pass
  212. // it to them via TranslateAccelerator. Since the only case we care
  213. // about is when they're getting tabbed into (we want them to highlight
  214. // the first/last link), just do this in the case of a tab. However,
  215. // don't give it to them if it's a ctl-tab. The rule is that you shouldn't
  216. // handle ctl-tab when UI-active (ctl-tab switches between contexts), and
  217. // since Trident is always UI-active (for perf?), they'll always reject
  218. // ctl-tab.
  219. if (IsVK_TABCycler(lpMsg) && !IsVK_CtlTABCycler(lpMsg) && _poipao)
  220. hr = _poipao->TranslateAccelerator(lpMsg);
  221. return hr;
  222. }
  223. // }
  224. //*** CBrowserBand::IOleCommandTarget::* {
  225. HRESULT CBrowserBand::QueryStatus(const GUID *pguidCmdGroup,
  226. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  227. {
  228. return MayQSForward(_pauto, OCTD_DOWN, pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  229. }
  230. HRESULT CBrowserBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  231. {
  232. // These are broadcast messages to the TRIDENT doc for GUID CGID_MSTHML
  233. if (pguidCmdGroup && IsEqualGUID(CGID_ExplorerBarDoc, *pguidCmdGroup))
  234. {
  235. if (_pauto)
  236. {
  237. LPTARGETFRAME2 ptgf;
  238. if (SUCCEEDED(_pauto->QueryInterface(IID_PPV_ARG(ITargetFrame2, &ptgf))))
  239. {
  240. LPOLECONTAINER pocDoc;
  241. if (SUCCEEDED(ptgf->GetFramesContainer(&pocDoc)) && pocDoc)
  242. {
  243. IUnknown_Exec(pocDoc, &CGID_MSHTML, nCmdID, nCmdexecopt,
  244. pvarargIn, pvarargOut);
  245. pocDoc->Release();
  246. }
  247. ptgf->Release();
  248. }
  249. }
  250. return S_OK;
  251. }
  252. else
  253. {
  254. return MayExecForward(_pauto, OCTD_DOWN, pguidCmdGroup, nCmdID, nCmdexecopt,
  255. pvarargIn, pvarargOut);
  256. }
  257. }
  258. // }
  259. HRESULT CBrowserBand::GetBandInfo(DWORD dwBandID, DWORD fViewMode,
  260. DESKBANDINFO* pdbi)
  261. {
  262. _dwBandID = dwBandID;
  263. // nt5:192868 make sure can't size to smaller than title/scrollbars
  264. // n.b. virt pdbi->pt.x,y is really phys y,x (i.e. phys long,short)
  265. pdbi->ptMinSize.x = _sizeMin.cx;
  266. pdbi->ptMinSize.y = max(16, _sizeMin.cy); // FEATURE: 16 is bogus
  267. #ifdef DEBUG
  268. if (pdbi->ptMinSize.x != 0 || pdbi->ptMinSize.y != 0)
  269. TraceMsg(DM_TRACE, "cbb.gbi: ptMinSize.(x,y)=%x,%x", pdbi->ptMinSize.x, pdbi->ptMinSize.y);
  270. #endif
  271. pdbi->ptMaxSize.x = _sizeMax.cx;
  272. pdbi->ptMaxSize.y = _sizeMax.cy;
  273. pdbi->dwModeFlags = _dwModeFlags;
  274. pdbi->ptActual.y = -1;
  275. pdbi->ptActual.x = -1;
  276. pdbi->ptIntegral.y = 1;
  277. if (_wszTitle[0]) {
  278. StrCpyNW(pdbi->wszTitle, _wszTitle, ARRAYSIZE(pdbi->wszTitle));
  279. } else if ( _fCustomTitle) {
  280. pdbi->dwMask &= ~DBIM_TITLE;
  281. }
  282. else{
  283. SHGetNameAndFlagsW(_pidl, SHGDN_NORMAL, pdbi->wszTitle, SIZECHARS(pdbi->wszTitle), NULL);
  284. }
  285. return S_OK;
  286. }
  287. void CBrowserBand::_InitBrowser(void)
  288. {
  289. ASSERT(IsWindow(_hwnd));
  290. OCHost_QueryInterface(_hwnd, IID_PPV_ARG(IWebBrowser2, &_pauto));
  291. OCHost_SetOwner(_hwnd, SAFECAST(this, IContextMenu*));
  292. if (EVAL(_pauto))
  293. {
  294. LPTARGETFRAME2 ptgf;
  295. if (SUCCEEDED(_pauto->QueryInterface(IID_PPV_ARG(ITargetFrame2, &ptgf))))
  296. {
  297. DWORD dwOptions;
  298. if (SUCCEEDED(ptgf->GetFrameOptions(&dwOptions)))
  299. {
  300. dwOptions |= FRAMEOPTIONS_BROWSERBAND | FRAMEOPTIONS_SCROLL_AUTO;
  301. ptgf->SetFrameOptions(dwOptions);
  302. }
  303. ptgf->Release();
  304. }
  305. _pauto->put_RegisterAsDropTarget(VARIANT_FALSE);
  306. // BUG do OCHost_QI
  307. // note only 1 active object (proxy)
  308. _pauto->QueryInterface(IID_PPV_ARG(IOleInPlaceActiveObject, &_poipao));
  309. ASSERT(_poipao != NULL);
  310. // set up the connection point
  311. _Connect(TRUE);
  312. }
  313. }
  314. HRESULT CBrowserBand::_NavigateOC()
  315. {
  316. HRESULT hres = E_FAIL;
  317. if (_hwnd)
  318. {
  319. ASSERT(IsWindow(_hwnd));
  320. if (!_pidl) {
  321. if (_pauto) {
  322. hres = _pauto->GoHome();
  323. }
  324. } else {
  325. IServiceProvider* psp = NULL;
  326. OCHost_QueryInterface(_hwnd, IID_PPV_ARG(IServiceProvider, &psp));
  327. if (psp)
  328. {
  329. IShellBrowser* psb;
  330. if (EVAL(SUCCEEDED(psp->QueryService(SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &psb)))))
  331. {
  332. hres = psb->BrowseObject(_pidl, SBSP_SAMEBROWSER);
  333. psb->Release();
  334. }
  335. psp->Release();
  336. }
  337. }
  338. }
  339. return hres;
  340. }
  341. HRESULT CBrowserBand::_CreateOCHost()
  342. {
  343. HRESULT hres = E_FAIL; // assume error
  344. // Register the OCHost window class
  345. SHDRC shdrc = {sizeof(SHDRC), SHDRCF_OCHOST};
  346. shdrc.cbSize = sizeof (SHDRC);
  347. shdrc.dwFlags |= SHDRCF_OCHOST;
  348. if (DllRegisterWindowClasses(&shdrc))
  349. {
  350. // Create an OCHost window
  351. _hwnd = CreateWindow(OCHOST_CLASS, NULL,
  352. WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_TABSTOP,
  353. 0, 0, 1, 1,
  354. _hwndParent, NULL, HINST_THISDLL, NULL);
  355. if (_hwnd)
  356. {
  357. OCHINITSTRUCT ocs;
  358. ocs.cbSize = SIZEOF(OCHINITSTRUCT);
  359. ocs.clsidOC = CLSID_WebBrowser;
  360. ocs.punkOwner = SAFECAST(this, IDeskBand*);
  361. hres = OCHost_InitOC(_hwnd, (LPARAM)&ocs);
  362. _InitBrowser();
  363. _NavigateOC();
  364. OCHost_DoVerb(_hwnd, OLEIVERB_INPLACEACTIVATE, FALSE);
  365. }
  366. }
  367. return hres;
  368. }
  369. //*** CBrowserBand::IWinEventHandler::* {
  370. HRESULT CBrowserBand::OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
  371. {
  372. switch (uMsg) {
  373. case WM_NOTIFY:
  374. _OnNotify((LPNMHDR)lParam);
  375. return S_OK;
  376. default:
  377. break;
  378. }
  379. return E_FAIL;
  380. }
  381. HRESULT CBrowserBand::IsWindowOwner(HWND hwnd)
  382. {
  383. HRESULT hres;
  384. hres = SHIsChildOrSelf(_hwnd, hwnd);
  385. ASSERT(hwnd != NULL || hres == S_FALSE);
  386. ASSERT(_hwnd != NULL || hres == S_FALSE);
  387. return hres;
  388. }
  389. #if 0
  390. static void HackFocus(HWND hwndFrom)
  391. {
  392. TraceMsg(DM_FOCUS, "HackFocus: GetFocus()=%x hwndOCHost=%x", GetFocus(), hwndFrom);
  393. hwndFrom = GetWindow(hwndFrom, GW_CHILD); // OCHost->shembed
  394. TraceMsg(DM_FOCUS, "HackFocus: hwndShEmbed=%x", hwndFrom);
  395. hwndFrom = GetWindow(hwndFrom, GW_CHILD); // shembed->shdocvw
  396. TraceMsg(DM_FOCUS, "HackFocus: hwndShDocVw=%x", hwndFrom);
  397. hwndFrom = GetWindow(hwndFrom, GW_CHILD); // shdocvw->iesvr
  398. TraceMsg(DM_FOCUS, "HackFocus: hwndIESvr=%x", hwndFrom);
  399. if (hwndFrom != 0) {
  400. TraceMsg(DM_FOCUS, "HackFocus: SetFocus(%x)", hwndFrom);
  401. SetFocus(hwndFrom);
  402. }
  403. return;
  404. }
  405. #endif
  406. LRESULT CBrowserBand::_OnNotify(LPNMHDR pnm)
  407. {
  408. switch (pnm->code)
  409. {
  410. case OCN_ONUIACTIVATE: // UIActivate
  411. ASSERT(SHIsSameObject(((LPOCNONUIACTIVATEMSG)pnm)->punk, _poipao));
  412. // n.b. we pass up 'this' not pnm->punk, since we always want to
  413. // be the intermediary (e.g. for UIActivateIO calls to us)
  414. IUnknown_OnFocusChangeIS(_punkSite, SAFECAST(this, IInputObject*), TRUE);
  415. return OCNONUIACTIVATE_HANDLED;
  416. case OCN_ONSETSTATUSTEXT:
  417. {
  418. HRESULT hr = E_FAIL;
  419. IShellBrowser *psb;
  420. hr = QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IShellBrowser, &psb));
  421. if (SUCCEEDED(hr)) {
  422. hr = psb->SetStatusTextSB(((LPOCNONSETSTATUSTEXTMSG)pnm)->pwszStatusText);
  423. psb->Release();
  424. }
  425. }
  426. break;
  427. case OCN_ONPOSRECTCHANGE:
  428. {
  429. LPCRECT lprcPosRect = ((LPOCNONPOSRECTCHANGEMSG)pnm)->prcPosRect;
  430. _sizeMin.cx = lprcPosRect->right - lprcPosRect->left;
  431. _sizeMin.cy = lprcPosRect->bottom - lprcPosRect->top;
  432. _BandInfoChanged();
  433. break;
  434. }
  435. default:
  436. break;
  437. }
  438. ASSERT(OCNONUIACTIVATE_HANDLED != 0);
  439. return 0;
  440. }
  441. // }
  442. //*** CBrowserBand::IPersistStream::* {
  443. HRESULT CBrowserBand::GetClassID(CLSID *pClassID)
  444. {
  445. *pClassID = CLSID_BrowserBand;
  446. return S_OK;
  447. }
  448. // mask flags for BrowserBand persistence
  449. //
  450. #define BB_ILSTREAM 0x00000001
  451. #define BB_PIDLASLINK 0x00000002
  452. // FEATURE: REVIEW: it seems to me like we should let the WebBrowserOC
  453. // persist it's location, not us...
  454. //
  455. HRESULT CBrowserBand::Load(IStream *pstm)
  456. {
  457. HRESULT hres;
  458. DWORD dw;
  459. if (_pidl) {
  460. ILFree(_pidl);
  461. }
  462. hres = pstm->Read(&dw, SIZEOF(DWORD), NULL);
  463. if (SUCCEEDED(hres))
  464. {
  465. if (dw & BB_PIDLASLINK)
  466. {
  467. hres = LoadPidlAsLink(_punkSite, pstm, &_pidl);
  468. }
  469. else if (dw & BB_ILSTREAM) // for backwards compat
  470. {
  471. hres = ILLoadFromStream(pstm, &_pidl);
  472. }
  473. }
  474. if (SUCCEEDED(hres))
  475. _NavigateOC();
  476. return hres;
  477. }
  478. HRESULT CBrowserBand::Save(IStream *pstm, BOOL fClearDirty)
  479. {
  480. HRESULT hres;
  481. DWORD dw = 0;
  482. BSTR bstrUrl = NULL;
  483. if (_pauto && SUCCEEDED(_pauto->get_LocationURL(&bstrUrl)) && bstrUrl) {
  484. TraceMsg(DM_PERSIST, "cbb.s: current/new url=%s", bstrUrl);
  485. if (_pidl) {
  486. ILFree(_pidl);
  487. _pidl = NULL; // paranoia
  488. }
  489. IECreateFromPath(bstrUrl, &_pidl);
  490. SysFreeString(bstrUrl);
  491. }
  492. if (_pidl)
  493. dw |= BB_PIDLASLINK;
  494. hres = pstm->Write(&dw, SIZEOF(DWORD), NULL);
  495. if (SUCCEEDED(hres) && (dw & BB_PIDLASLINK))
  496. hres = SavePidlAsLink(_punkSite, pstm, _pidl);
  497. return hres;
  498. }
  499. // }
  500. //*** CBrowserBand::IPersistPropertyBag::* {
  501. HRESULT CBrowserBand::Load(IPropertyBag *pPBag, IErrorLog *pErrLog)
  502. {
  503. HRESULT hres;
  504. TCHAR szUrl[MAX_URL_STRING];
  505. TraceMsg(DM_TRACE, "cbb.l(bag): enter");
  506. if (_pidl) {
  507. ILFree(_pidl);
  508. }
  509. hres = SHPropertyBag_ReadStr(pPBag, L"Url", szUrl, ARRAYSIZE(szUrl));
  510. if (SUCCEEDED(hres)) {
  511. TCHAR * pszFinalUrl;
  512. TCHAR szPlug[MAX_PATH];
  513. TCHAR szMuiPath[MAX_PATH];
  514. pszFinalUrl = szUrl;
  515. hres = SHPropertyBag_ReadStr(pPBag, L"Pluggable", szPlug, ARRAYSIZE(szPlug));
  516. if (SUCCEEDED(hres) && !StrCmpNI(TEXT("yes"), szPlug, ARRAYSIZE(szPlug)))
  517. {
  518. TCHAR * pszFile;
  519. // if this is loading html out of the windows\web folder
  520. // then we need to call SHGetWebFolderFilePath in order
  521. // to support pluggable UI
  522. pszFile = PathFindFileName(szUrl);
  523. hres = SHGetWebFolderFilePath(pszFile, szMuiPath, ARRAYSIZE(szMuiPath));
  524. if (SUCCEEDED(hres))
  525. {
  526. pszFinalUrl = szMuiPath;
  527. }
  528. }
  529. hres = IECreateFromPath(pszFinalUrl, &_pidl);
  530. if (SUCCEEDED(hres)) {
  531. _NavigateOC();
  532. }
  533. }
  534. return hres;
  535. }
  536. // }
  537. //*** CBrowserBand::IContextMenu::* {
  538. HRESULT CBrowserBand::QueryContextMenu(HMENU hmenu,
  539. UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
  540. {
  541. int i = 0;
  542. HMENU hmenuMe = LoadMenuPopup_PrivateNoMungeW(MENU_BROWBAND);
  543. i += Shell_MergeMenus(hmenu, hmenuMe, indexMenu, idCmdFirst + i, idCmdLast, MM_ADDSEPARATOR) - (idCmdFirst + i);
  544. DestroyMenu(hmenuMe);
  545. // aka (S_OK|i)
  546. return MAKE_HRESULT(ERROR_SUCCESS, FACILITY_NULL, i);
  547. }
  548. HRESULT CBrowserBand::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
  549. {
  550. TraceMsg(DM_MENU, "cbb.ic");
  551. HRESULT hres;
  552. int idCmd = -1;
  553. // FEATURE: todo: id -= _idCmdFirst ???
  554. if (!HIWORD(pici->lpVerb))
  555. idCmd = LOWORD(pici->lpVerb);
  556. //
  557. // Low memory paranoia safety check
  558. //
  559. if (!_pauto) {
  560. TraceMsg(DM_ERROR, "CBrowserBand::InvokeCommand: _pauto IS NULL");
  561. return E_OUTOFMEMORY;
  562. }
  563. switch (idCmd) {
  564. case IDM_BROWBAND_REFRESH:
  565. #ifdef DEBUG
  566. if (GetKeyState(VK_SHIFT) < 0)
  567. hres = _pauto->GoHome();
  568. else
  569. #endif
  570. hres = _pauto->Refresh();
  571. break;
  572. case IDM_BROWBAND_OPENNEW: // clone window into 'real' browser
  573. {
  574. BSTR bstrURL = NULL;
  575. // n.b. this clones the *current page* into a 'real' browser,
  576. // not the link.
  577. // FEATURE: todo: we'd really rather get and navigate to
  578. // a PIDL, but that isn't supported yet in ie4.
  579. hres = _pauto->get_LocationURL(&bstrURL);
  580. if (SUCCEEDED(hres)) {
  581. VARIANT varFlags;
  582. VariantInit(&varFlags);
  583. varFlags.vt = VT_I4;
  584. varFlags.lVal = (navOpenInNewWindow|navNoHistory);
  585. // n.b. we drop the post data etc. on the floor, oh well...
  586. hres = _pauto->Navigate(bstrURL, /*flags*/&varFlags, /*targ*/NULL, /*post*/NULL, /*hdrs*/NULL);
  587. VariantClear(&varFlags);
  588. }
  589. if (bstrURL)
  590. SysFreeString(bstrURL);
  591. ASSERT(SUCCEEDED(hres));
  592. break;
  593. }
  594. default:
  595. TraceMsg(DM_ERROR, "cbb::ic cmd=%d not handled", idCmd);
  596. break;
  597. }
  598. return S_OK;
  599. }
  600. // }
  601. SIZE CBrowserBand::_GetCurrentSize()
  602. {
  603. SIZE size;
  604. RECT rc;
  605. GetWindowRect(_hwnd, &rc);
  606. size.cx = RECTWIDTH(rc);
  607. size.cy = RECTHEIGHT(rc);
  608. return size;
  609. }
  610. // *** IBrowserBand methods ***
  611. HRESULT CBrowserBand::GetObjectBB(REFIID riid, LPVOID *ppv)
  612. {
  613. return _pauto ? _pauto->QueryInterface(riid, ppv) : E_UNEXPECTED;
  614. }
  615. #ifdef DEBUG
  616. void CBrowserBand::_DebugTestCode()
  617. {
  618. DWORD dwMask = 0x10000000; // non-NULL bogus mask
  619. BROWSERBANDINFO bbi;
  620. bbi.cbSize = SIZEOF(BROWSERBANDINFO);
  621. GetBrowserBandInfo(dwMask, &bbi);
  622. }
  623. #endif // DEBUG
  624. void CBrowserBand::_MakeSizesConsistent(LPSIZE psizeCur)
  625. {
  626. // _sizeMin overrules _sizeMax
  627. if (_dwModeFlags & DBIMF_FIXED) {
  628. // if they specified a current size, use that instead
  629. // of min size
  630. if (psizeCur)
  631. _sizeMin = *psizeCur;
  632. _sizeMax = _sizeMin;
  633. } else {
  634. _sizeMax.cx = max(_sizeMin.cx, _sizeMax.cx);
  635. _sizeMax.cy = max(_sizeMin.cy, _sizeMax.cy);
  636. if (psizeCur) {
  637. psizeCur->cx = max(_sizeMin.cx, psizeCur->cx);
  638. psizeCur->cy = max(_sizeMin.cy, psizeCur->cy);
  639. psizeCur->cx = min(_sizeMax.cx, psizeCur->cx);
  640. psizeCur->cy = min(_sizeMax.cy, psizeCur->cy);
  641. }
  642. }
  643. }
  644. HRESULT CBrowserBand::SetBrowserBandInfo(DWORD dwMask, PBROWSERBANDINFO pbbi)
  645. {
  646. if (!pbbi || pbbi->cbSize != SIZEOF(BROWSERBANDINFO))
  647. return E_INVALIDARG;
  648. if (!dwMask || (dwMask & BBIM_MODEFLAGS))
  649. _dwModeFlags = pbbi->dwModeFlags;
  650. if (!dwMask || (dwMask & BBIM_TITLE)) {
  651. if (pbbi->bstrTitle) {
  652. _fCustomTitle = TRUE;
  653. // Change the internal _wszTitle used by Browser band
  654. StrCpyNW(_wszTitle, pbbi->bstrTitle, ARRAYSIZE(_wszTitle));
  655. } else {
  656. _fCustomTitle = FALSE;
  657. }
  658. }
  659. if (!dwMask || (dwMask & BBIM_SIZEMIN))
  660. _sizeMin = pbbi->sizeMin;
  661. if (!dwMask || (dwMask & BBIM_SIZEMAX))
  662. _sizeMax = pbbi->sizeMax;
  663. if (!dwMask || (dwMask & BBIM_SIZECUR)) {
  664. SIZE sizeCur = pbbi->sizeCur;
  665. _MakeSizesConsistent(&sizeCur);
  666. // HACKHACK: the only way to tell bandsite to change the height of a horizontal
  667. // band is to give it a new min/max height pair at the desired height. the same
  668. // holds for setting the width of a vertical band. so we temporarily give bandsite
  669. // new min/max size info, then restore old min/max.
  670. SIZE sizeMinOld = _sizeMin;
  671. SIZE sizeMaxOld = _sizeMax;
  672. _sizeMin = _sizeMax = sizeCur;
  673. _BandInfoChanged();
  674. _sizeMin = sizeMinOld;
  675. _sizeMax = sizeMaxOld;
  676. } else {
  677. _MakeSizesConsistent(NULL);
  678. }
  679. _BandInfoChanged();
  680. return S_OK;
  681. }
  682. // we don't have a client to test BBIM_TITLE, so leave it unimplemented for now.
  683. #define BBIM_INVALIDFLAGS (~(BBIM_SIZEMIN | BBIM_SIZEMAX | BBIM_SIZECUR | BBIM_MODEFLAGS))
  684. HRESULT CBrowserBand::GetBrowserBandInfo(DWORD dwMask, PBROWSERBANDINFO pbbi)
  685. {
  686. if (!pbbi || pbbi->cbSize != SIZEOF(BROWSERBANDINFO))
  687. return E_INVALIDARG;
  688. if (dwMask & BBIM_INVALIDFLAGS)
  689. return E_INVALIDARG;
  690. pbbi->dwModeFlags = _dwModeFlags;
  691. pbbi->sizeMin = _sizeMin;
  692. pbbi->sizeMax = _sizeMax;
  693. pbbi->sizeCur =_GetCurrentSize();
  694. return S_OK;
  695. }
  696. IDeskBand* CBrowserBand_Create(LPCITEMIDLIST pidl)
  697. {
  698. CBrowserBand *p = new CBrowserBand();
  699. if(p) {
  700. if (pidl)
  701. p->_pidl = ILClone(pidl);
  702. }
  703. return p;
  704. }
  705. // }
  706. class CSearchSecurityMgrImpl : public CInternetSecurityMgrImpl
  707. {
  708. // *** IID_IInternetSecurityManager ***
  709. virtual STDMETHODIMP ProcessUrlAction(LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy,
  710. BYTE *pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved)
  711. {
  712. HRESULT hres = INET_E_DEFAULT_ACTION;
  713. switch (dwAction)
  714. {
  715. case URLACTION_ACTIVEX_RUN:
  716. case URLACTION_SCRIPT_RUN:
  717. case URLACTION_SCRIPT_SAFE_ACTIVEX:
  718. case URLACTION_HTML_SUBMIT_FORMS:
  719. if (_IsSafeUrl(pwszUrl))
  720. {
  721. if (cbPolicy >= SIZEOF(DWORD))
  722. {
  723. *(DWORD *)pPolicy = URLPOLICY_ALLOW;
  724. hres = S_OK;
  725. }
  726. else
  727. {
  728. hres = S_FALSE;
  729. }
  730. }
  731. break;
  732. }
  733. return hres;
  734. }
  735. };
  736. class CCustomizeSearchHelper : public CInternetSecurityMgrImpl,
  737. public IServiceProvider
  738. {
  739. public:
  740. CCustomizeSearchHelper() : _cRef(1) { }
  741. // *** IUnknown ***
  742. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  743. virtual STDMETHODIMP_(ULONG) AddRef(void);
  744. virtual STDMETHODIMP_(ULONG) Release(void);
  745. // *** IID_IInternetSecurityManager ***
  746. virtual STDMETHODIMP ProcessUrlAction(LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy,
  747. BYTE *pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved);
  748. // *** IServiceProvider ***
  749. virtual STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
  750. virtual BOOL _IsSafeUrl(LPCWSTR pwszUrl) { return TRUE; }
  751. private:
  752. ~CCustomizeSearchHelper() {};
  753. ULONG _cRef;
  754. };
  755. STDMETHODIMP_(ULONG) CCustomizeSearchHelper::AddRef()
  756. {
  757. return ++_cRef;
  758. }
  759. STDMETHODIMP_(ULONG) CCustomizeSearchHelper::Release(void)
  760. {
  761. if( 0L != --_cRef )
  762. return _cRef;
  763. delete this;
  764. return 0L;
  765. }
  766. HRESULT CCustomizeSearchHelper::QueryInterface(REFIID riid, void **ppvObj)
  767. {
  768. static const QITAB qit[] = {
  769. QITABENT(CCustomizeSearchHelper, IServiceProvider),
  770. QITABENT(CCustomizeSearchHelper, IInternetSecurityManager),
  771. { 0 },
  772. };
  773. return QISearch(this, qit, riid, ppvObj);
  774. }
  775. HRESULT CCustomizeSearchHelper::ProcessUrlAction(LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy,
  776. DWORD cbPolicy, BYTE *pContext, DWORD cbContext,
  777. DWORD dwFlags, DWORD dwReserved)
  778. {
  779. HRESULT hres = INET_E_DEFAULT_ACTION;
  780. switch (dwAction)
  781. {
  782. case URLACTION_ACTIVEX_RUN:
  783. case URLACTION_SCRIPT_RUN:
  784. case URLACTION_SCRIPT_SAFE_ACTIVEX:
  785. case URLACTION_HTML_SUBMIT_FORMS:
  786. if (cbPolicy >= SIZEOF(DWORD))
  787. {
  788. *(DWORD *)pPolicy = URLPOLICY_ALLOW;
  789. hres = S_OK;
  790. }
  791. else
  792. {
  793. hres = S_FALSE;
  794. }
  795. break;
  796. }
  797. return hres;
  798. }
  799. STDMETHODIMP CCustomizeSearchHelper::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
  800. {
  801. if (IID_IInternetSecurityManager == guidService)
  802. {
  803. return QueryInterface(riid, ppvObject);
  804. }
  805. else
  806. {
  807. *ppvObject = NULL;
  808. return E_NOINTERFACE;
  809. }
  810. }
  811. //*** CSearchBand {
  812. //
  813. ////////////////
  814. /// Search (BrowserOC) band
  815. // If you change this, change shdocvw also.
  816. const WCHAR c_wszThisBandIsYourBand[] = L"$$SearchBand$$";
  817. #define SEARCH_MENUID_OFFSET 100
  818. class CSearchBand : public CBrowserBand,
  819. public IBandNavigate,
  820. public ISearchBandTBHelper,
  821. public CSearchSecurityMgrImpl
  822. {
  823. public:
  824. // *** IUnknown ***
  825. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  826. virtual STDMETHODIMP_(ULONG) AddRef(void);
  827. virtual STDMETHODIMP_(ULONG) Release(void);
  828. // *** IDeskBand methods ***
  829. virtual STDMETHODIMP GetBandInfo(DWORD dwBandID, DWORD fViewMode,
  830. DESKBANDINFO* pdbi);
  831. // *** IPersistStream methods ***
  832. // (others use base class implementation)
  833. virtual STDMETHODIMP GetClassID(CLSID *pClassID);
  834. virtual STDMETHODIMP Load(IStream *pStm);
  835. virtual STDMETHODIMP Save(IStream *pStm, BOOL fClearDirty);
  836. // *** IBandNavigate ***
  837. virtual STDMETHODIMP Select(LPCITEMIDLIST pidl);
  838. // *** IOleCommandTarget methods ***
  839. virtual STDMETHODIMP Exec(const GUID *pguidCmdGroup,
  840. DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
  841. // *** IDockingWindow methods ***
  842. virtual STDMETHODIMP ShowDW(BOOL fShow);
  843. // *** ISearchBandTBHelper methods ***
  844. virtual STDMETHODIMP AddNextMenuItem(LPCWSTR pwszText, int idItem);
  845. virtual STDMETHODIMP ResetNextMenu();
  846. virtual STDMETHODIMP SetOCCallback(IOleCommandTarget *pOleCmdTarget);
  847. virtual STDMETHODIMP NavigateToPidl(LPCITEMIDLIST pidl);
  848. // *** IServiceProvider methods ***
  849. virtual STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, LPVOID* ppvObj);
  850. // *** IWinEventHandler ***
  851. virtual STDMETHODIMP OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres);
  852. protected:
  853. CSearchBand();
  854. virtual ~CSearchBand();
  855. virtual void _Connect(BOOL fConnect);
  856. virtual void _InitBrowser(void);
  857. virtual HRESULT _NavigateOC();
  858. void _AddButtons(BOOL fAdd);
  859. void _OnNextButtonSelect(int x, int y);
  860. void _OnNew();
  861. void _DoNext(int newPos);
  862. void _OnNextButtonClick();
  863. void _OnCustomize();
  864. void _OnHelp();
  865. void _NavigateToUrl(LPCTSTR pszUrl);
  866. void _EnsureImageListsLoaded();
  867. void _EnableNext(BOOL bEnable);
  868. void _NavigateToSearchUrl();
  869. virtual BOOL _IsSafeUrl(LPCWSTR pwszUrl);
  870. BOOL _fStrsAdded;
  871. LONG_PTR _lStrOffset;
  872. IOleCommandTarget *_pOCCmdTarget;
  873. HIMAGELIST _himlNormal;
  874. HIMAGELIST _himlHot;
  875. friend HRESULT CSearchBand_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi); // for ctor
  876. friend IDeskBand* CSearchBand_Create();
  877. HMENU _hmenuNext;
  878. HWND _hwndParent;
  879. int _nextPos;
  880. BOOL _bNewUrl; // set to true when we are QS'd for IInternetSecurityMgr, i.e. when pane is renavigated
  881. BOOL _bUseDefault; // true if we should not use our security mgr
  882. WCHAR _wszCache[MAX_URL_STRING];
  883. DWORD _nCmpLength;
  884. BOOL _bIsCacheSafe;
  885. };
  886. CSearchBand::CSearchBand() :
  887. CBrowserBand()
  888. {
  889. _fBlockSIDProxy = FALSE;
  890. _fBlockDrop = TRUE;
  891. _bNewUrl = TRUE;
  892. ASSERT(_wszCache[0] == TEXT('\0'));
  893. ASSERT(_nCmpLength == 0);
  894. ASSERT(_bIsCacheSafe == FALSE);
  895. }
  896. CSearchBand::~CSearchBand()
  897. {
  898. ResetNextMenu();
  899. if (NULL != _himlNormal)
  900. {
  901. ImageList_Destroy(_himlNormal);
  902. }
  903. if (NULL != _himlHot)
  904. {
  905. ImageList_Destroy(_himlHot);
  906. }
  907. ATOMICRELEASE(_pOCCmdTarget);
  908. }
  909. void CSearchBand::_NavigateToUrl(LPCTSTR pszUrl)
  910. {
  911. if (NULL != _pidl)
  912. {
  913. ILFree(_pidl);
  914. }
  915. IECreateFromPath(pszUrl, &_pidl);
  916. _NavigateOC();
  917. }
  918. void CSearchBand::_NavigateToSearchUrl()
  919. {
  920. TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  921. BOOL bFound;
  922. BOOL bWebSearch = FALSE;
  923. IBrowserService2 *pbs;
  924. if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService2, &pbs))))
  925. {
  926. ITEMIDLIST *pidl;
  927. if (SUCCEEDED(pbs->GetPidl(&pidl)))
  928. {
  929. // FEATURE: This code should be using IShellFolder2::GetDefaultSearchGUID() and
  930. // keying off SRCID_SWebSearch (vs. SRCID_SFileSearch/SRCID_SFindComputer/SRCID_SFindPrinter)
  931. bWebSearch = ILIsWeb(pidl);
  932. ILFree(pidl);
  933. }
  934. pbs->Release();
  935. }
  936. ResetNextMenu();
  937. if (bWebSearch)
  938. {
  939. bFound = GetDefaultInternetSearchUrl(szUrl, ARRAYSIZE(szUrl), TRUE);
  940. }
  941. else
  942. {
  943. bFound = GetSearchAssistantUrl(szUrl, ARRAYSIZE(szUrl), TRUE, FALSE);
  944. }
  945. if (bFound)
  946. {
  947. _NavigateToUrl(szUrl);
  948. }
  949. }
  950. void CSearchBand::_OnNew()
  951. {
  952. VARIANT var;
  953. var.vt = VT_BOOL;
  954. var.boolVal = VARIANT_FALSE;
  955. if (NULL != _pOCCmdTarget)
  956. {
  957. HRESULT hr = _pOCCmdTarget->Exec(NULL, SBID_SEARCH_NEW, 0, NULL, &var);
  958. if (FAILED(hr))
  959. {
  960. var.boolVal = VARIANT_FALSE;
  961. }
  962. }
  963. if ((var.vt != VT_BOOL) || (!var.boolVal))
  964. {
  965. _NavigateToSearchUrl();
  966. }
  967. }
  968. void CSearchBand::_OnNextButtonSelect(int x, int y)
  969. {
  970. HWND hwnd;
  971. if (SUCCEEDED(IUnknown_GetWindow(_punkSite, &hwnd)))
  972. {
  973. int idItem = TrackPopupMenu(_hmenuNext, TPM_RETURNCMD, x, y, 0, hwnd, NULL);
  974. if (0 != idItem)
  975. {
  976. _DoNext(GetMenuPosFromID(_hmenuNext, idItem));
  977. }
  978. }
  979. }
  980. void CSearchBand::_DoNext(int newPos)
  981. {
  982. if (NULL != _pOCCmdTarget)
  983. {
  984. CheckMenuItem(_hmenuNext, _nextPos, MF_BYPOSITION | MF_UNCHECKED);
  985. _nextPos = newPos;
  986. CheckMenuItem(_hmenuNext, _nextPos, MF_BYPOSITION | MF_CHECKED);
  987. VARIANT var;
  988. var.vt = VT_I4;
  989. var.lVal = GetMenuItemID(_hmenuNext, _nextPos) - SEARCH_MENUID_OFFSET;
  990. HRESULT hr = _pOCCmdTarget->Exec(NULL, SBID_SEARCH_NEXT, 0, &var, NULL);
  991. ASSERT(SUCCEEDED(hr));
  992. }
  993. }
  994. void CSearchBand::_OnNextButtonClick()
  995. {
  996. int newPos = _nextPos + 1;
  997. if (newPos >= GetMenuItemCount(_hmenuNext))
  998. {
  999. newPos = 0;
  1000. }
  1001. _DoNext(newPos);
  1002. }
  1003. void CSearchBand::_OnCustomize()
  1004. {
  1005. TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  1006. HWND hwnd;
  1007. IUnknown_GetWindow(_punkSite, &hwnd);
  1008. if (GetSearchAssistantUrl(szUrl, ARRAYSIZE(szUrl), TRUE, TRUE))
  1009. {
  1010. if (InternetGoOnline(szUrl, hwnd, 0))
  1011. {
  1012. IMoniker *pmk;
  1013. if (SUCCEEDED(CreateURLMoniker(NULL, szUrl, &pmk)))
  1014. {
  1015. IHostDialogHelper *pTridentAPI;
  1016. if (SUCCEEDED(CoCreateInstance(CLSID_HostDialogHelper, NULL, CLSCTX_INPROC_SERVER,
  1017. IID_PPV_ARG(IHostDialogHelper, &pTridentAPI))))
  1018. {
  1019. IUnknown *punkCustHelper = NULL;
  1020. if (_IsSafeUrl(szUrl))
  1021. {
  1022. punkCustHelper = (IUnknown *)(IServiceProvider *)new CCustomizeSearchHelper;
  1023. }
  1024. pTridentAPI->ShowHTMLDialog(hwnd, pmk, NULL, L"help:no;resizable:1", NULL, punkCustHelper);
  1025. if (NULL != punkCustHelper)
  1026. {
  1027. punkCustHelper->Release();
  1028. }
  1029. pTridentAPI->Release();
  1030. }
  1031. pmk->Release();
  1032. }
  1033. }
  1034. }
  1035. }
  1036. void CSearchBand::_OnHelp()
  1037. {
  1038. HWND hwnd;
  1039. IUnknown_GetWindow(_punkSite, &hwnd);
  1040. #ifndef UNIX
  1041. SHHtmlHelpOnDemandWrap(hwnd, TEXT("iexplore.chm > iedefault"), 0, (DWORD_PTR) TEXT("srchasst.htm"), ML_CROSSCODEPAGE);
  1042. #else
  1043. {
  1044. IServiceProvider* psp = NULL;
  1045. OCHost_QueryInterface(_hwnd, IID_PPV_ARG(IServiceProvider, &psp));
  1046. if (psp)
  1047. {
  1048. IShellBrowser* psb;
  1049. if (EVAL(SUCCEEDED(psp->QueryService(SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &psb)))))
  1050. {
  1051. UnixHelp(L"Search Help", psb);
  1052. psb->Release();
  1053. }
  1054. psp->Release();
  1055. }
  1056. }
  1057. #endif
  1058. }
  1059. HRESULT CSearchBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1060. {
  1061. if (pguidCmdGroup && IsEqualGUID(CGID_SearchBand, *pguidCmdGroup))
  1062. {
  1063. switch (nCmdID)
  1064. {
  1065. case SBID_SEARCH_NEW:
  1066. _OnNew();
  1067. return S_OK;
  1068. case SBID_SEARCH_NEXT:
  1069. if (nCmdexecopt == OLECMDEXECOPT_PROMPTUSER)
  1070. {
  1071. if ((NULL != pvarargIn) && (pvarargIn->vt == VT_I4))
  1072. {
  1073. ASSERT(NULL != _hmenuNext);
  1074. _OnNextButtonSelect(GET_X_LPARAM(pvarargIn->lVal), GET_Y_LPARAM(pvarargIn->lVal));
  1075. }
  1076. }
  1077. else
  1078. {
  1079. _OnNextButtonClick();
  1080. }
  1081. return S_OK;
  1082. case SBID_SEARCH_CUSTOMIZE:
  1083. _OnCustomize();
  1084. return S_OK;
  1085. case SBID_SEARCH_HELP:
  1086. _OnHelp();
  1087. return S_OK;
  1088. case SBID_HASPIDL:
  1089. // Simply return whether or not the band has a pidl
  1090. if (_pidl)
  1091. return S_OK;
  1092. else
  1093. return S_FALSE;
  1094. case SBID_GETPIDL:
  1095. {
  1096. HRESULT hres = E_INVALIDARG;
  1097. if (pvarargOut)
  1098. {
  1099. hres = E_OUTOFMEMORY;
  1100. VariantInit(pvarargOut); // zero init it
  1101. if (!_pidl || SUCCEEDED(InitVariantFromIDList(pvarargOut, _pidl)))
  1102. hres = S_OK;
  1103. }
  1104. return hres;
  1105. }
  1106. }
  1107. }
  1108. return CBrowserBand::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  1109. }
  1110. #define INDEX_NEXT 1
  1111. #define INDEX_CUSTOMIZE 3
  1112. static const TBBUTTON c_tbSearch[] =
  1113. {
  1114. { 0, SBID_SEARCH_NEW, TBSTATE_ENABLED, BTNS_AUTOSIZE | BTNS_SHOWTEXT, {0, 0}, 0, 0},
  1115. { 1, SBID_SEARCH_NEXT, 0, BTNS_AUTOSIZE | BTNS_DROPDOWN | BTNS_SHOWTEXT, {0, 0}, 0, 1},
  1116. { 0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0},
  1117. { I_IMAGENONE, SBID_SEARCH_CUSTOMIZE, TBSTATE_ENABLED, BTNS_AUTOSIZE | BTNS_SHOWTEXT, {0, 0}, 0, 2}
  1118. };
  1119. void CSearchBand::_EnableNext(BOOL bEnable)
  1120. {
  1121. IExplorerToolbar* piet;
  1122. if (SUCCEEDED(_punkSite->QueryInterface(IID_PPV_ARG(IExplorerToolbar, &piet))))
  1123. {
  1124. UINT state;
  1125. if (SUCCEEDED(piet->GetState(&CGID_SearchBand, SBID_SEARCH_NEXT, &state)))
  1126. {
  1127. if (bEnable)
  1128. {
  1129. state |= TBSTATE_ENABLED;
  1130. }
  1131. else
  1132. {
  1133. state &= ~TBSTATE_ENABLED;
  1134. }
  1135. piet->SetState(&CGID_SearchBand, SBID_SEARCH_NEXT, state);
  1136. }
  1137. piet->Release();
  1138. }
  1139. }
  1140. void CSearchBand::_AddButtons(BOOL fAdd)
  1141. {
  1142. IExplorerToolbar* piet;
  1143. if (SUCCEEDED(_punkSite->QueryInterface(IID_PPV_ARG(IExplorerToolbar, &piet))))
  1144. {
  1145. if (fAdd)
  1146. {
  1147. piet->SetCommandTarget((IUnknown*)SAFECAST(this, IOleCommandTarget*), &CGID_SearchBand, 0);
  1148. if (!_fStrsAdded)
  1149. {
  1150. LONG_PTR cbOffset;
  1151. piet->AddString(&CGID_SearchBand, MLGetHinst(), IDS_SEARCH_BAR_LABELS, &cbOffset);
  1152. _lStrOffset = cbOffset;
  1153. _fStrsAdded = TRUE;
  1154. }
  1155. _EnsureImageListsLoaded();
  1156. piet->SetImageList(&CGID_SearchBand, _himlNormal, _himlHot, NULL);
  1157. TBBUTTON tbSearch[ARRAYSIZE(c_tbSearch)];
  1158. UpdateButtonArray(tbSearch, c_tbSearch, ARRAYSIZE(c_tbSearch), _lStrOffset);
  1159. if (SHRestricted2(REST_NoSearchCustomization, NULL, 0))
  1160. {
  1161. tbSearch[INDEX_CUSTOMIZE].fsState &= ~TBSTATE_ENABLED;
  1162. }
  1163. if (NULL != _hmenuNext)
  1164. {
  1165. tbSearch[INDEX_NEXT].fsState |= TBSTATE_ENABLED;
  1166. }
  1167. piet->AddButtons(&CGID_SearchBand, ARRAYSIZE(tbSearch), tbSearch);
  1168. }
  1169. else
  1170. piet->SetCommandTarget(NULL, NULL, 0);
  1171. piet->Release();
  1172. }
  1173. }
  1174. void CSearchBand::_EnsureImageListsLoaded()
  1175. {
  1176. if (_himlNormal == NULL)
  1177. {
  1178. _himlNormal = ImageList_LoadImage(HINST_THISDLL,
  1179. MAKEINTRESOURCE(IDB_SEARCHBANDDEF),
  1180. 18,
  1181. 0,
  1182. RGB(255, 0, 255),
  1183. IMAGE_BITMAP,
  1184. LR_CREATEDIBSECTION);
  1185. }
  1186. if (_himlHot == NULL)
  1187. {
  1188. _himlHot = ImageList_LoadImage(HINST_THISDLL,
  1189. MAKEINTRESOURCE(IDB_SEARCHBANDHOT),
  1190. 18,
  1191. 0,
  1192. RGB(255, 0, 255),
  1193. IMAGE_BITMAP,
  1194. LR_CREATEDIBSECTION);
  1195. }
  1196. }
  1197. HRESULT CSearchBand::AddNextMenuItem(LPCWSTR pwszText, int idItem)
  1198. {
  1199. if (NULL == _hmenuNext)
  1200. {
  1201. _hmenuNext = CreatePopupMenu();
  1202. }
  1203. ASSERT(NULL != _hmenuNext);
  1204. if (NULL != _hmenuNext)
  1205. {
  1206. #ifdef DEBUG
  1207. // Check to see if an item with this ID has already been added
  1208. MENUITEMINFO dbgMii = { sizeof(dbgMii) };
  1209. dbgMii.fMask = MIIM_STATE;
  1210. if (GetMenuItemInfo(_hmenuNext, idItem + SEARCH_MENUID_OFFSET, FALSE, &dbgMii))
  1211. {
  1212. TraceMsg(DM_ERROR, "Adding duplicate menu item in CSearchBand::AddNextMenuItem");
  1213. }
  1214. #endif
  1215. int nItems = GetMenuItemCount(_hmenuNext);
  1216. MENUITEMINFOW mii = { sizeof(mii) };
  1217. mii.fMask = MIIM_ID | MIIM_TYPE;
  1218. mii.wID = (WORD)idItem + SEARCH_MENUID_OFFSET;
  1219. mii.fType = MFT_RADIOCHECK | MFT_STRING;
  1220. mii.dwTypeData = (LPWSTR)pwszText;
  1221. mii.cch = lstrlenW(pwszText);
  1222. BOOL result = InsertMenuItemW(_hmenuNext, nItems, TRUE, &mii);
  1223. if (result)
  1224. {
  1225. if (0 == nItems)
  1226. {
  1227. CheckMenuItem(_hmenuNext, 0, MF_BYPOSITION | MF_CHECKED);
  1228. _EnableNext(TRUE);
  1229. }
  1230. }
  1231. }
  1232. return S_OK;
  1233. }
  1234. HRESULT CSearchBand::ResetNextMenu()
  1235. {
  1236. if (NULL != _hmenuNext)
  1237. {
  1238. _nextPos = 0;
  1239. _EnableNext(FALSE);
  1240. DestroyMenu(_hmenuNext);
  1241. _hmenuNext = NULL;
  1242. }
  1243. return S_OK;
  1244. }
  1245. HRESULT CSearchBand::SetOCCallback(IOleCommandTarget *pOleCmdTarget)
  1246. {
  1247. ResetNextMenu();
  1248. ATOMICRELEASE(_pOCCmdTarget);
  1249. _pOCCmdTarget = pOleCmdTarget;
  1250. if (NULL != _pOCCmdTarget)
  1251. {
  1252. _pOCCmdTarget->AddRef();
  1253. }
  1254. return S_OK;
  1255. }
  1256. //
  1257. // CSearchBand::NavigateToPidl
  1258. //
  1259. // Implements ISearchBandTBHelper::NavigateToPidl
  1260. //
  1261. // This is *almost* the same as CSearchBand::Select, except that it always navigates, whereas
  1262. // CSearchBand::Select will skip navigation if the search band is already displaying that pidl.
  1263. // We need that function to retain that behavior so that the search pane retains its results when
  1264. // opened.
  1265. //
  1266. HRESULT CSearchBand::NavigateToPidl(LPCITEMIDLIST pidl)
  1267. {
  1268. ILFree(_pidl);
  1269. _pidl = ILClone(pidl);
  1270. return _NavigateOC();
  1271. }
  1272. HRESULT CSearchBand::ShowDW(BOOL fShow)
  1273. {
  1274. #ifdef UNIX
  1275. // We overide this method in order to provide renavigation if our earlier navigation
  1276. // was cancelled for some reason.
  1277. if (fShow)
  1278. {
  1279. // Should be there.
  1280. // Just being sure we are able to navigate.
  1281. ASSERT(IsWindow(_hwnd));
  1282. ASSERT( _pidl );
  1283. if (_pauto)
  1284. {
  1285. BSTR bstrURL = NULL;
  1286. TCHAR szLocation[MAX_URL_STRING];
  1287. // SHUnicodeToTChar does this - no memset
  1288. // memset(szLocation, 0, SIZEOF(szLocation));
  1289. if( SUCCEEDED(_pauto->get_LocationURL(&bstrURL)) && bstrURL )
  1290. {
  1291. // Fire navigation again if the navigation was canceled earlier for
  1292. // some reason (Maybe the proxy was not set).
  1293. SHUnicodeToTChar(bstrURL, szLocation, ARRAYSIZE(szLocation));
  1294. if( !StrCmpI( szLocation, NAVCANCELLED_URL ) ||
  1295. !StrCmpI( szLocation, OFFLINEINFO_URL ) )
  1296. _NavigateOC();
  1297. SysFreeString(bstrURL);
  1298. }
  1299. }
  1300. }
  1301. #endif
  1302. HRESULT hres = CBrowserBand::ShowDW(fShow);
  1303. _AddButtons(fShow);
  1304. return hres;
  1305. }
  1306. HRESULT CSearchBand_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  1307. {
  1308. *ppunk = NULL;
  1309. // aggregation checking is handled in class factory
  1310. HRESULT hr = CreateFromRegKey(REGSTR_PATH_EXPLORER, TEXT("WebFindBandHook"), IID_PPV_ARG(IUnknown, ppunk));
  1311. if (FAILED(hr))
  1312. {
  1313. CSearchBand *p = new CSearchBand();
  1314. if (p)
  1315. {
  1316. *ppunk = SAFECAST(p, IDeskBand*);
  1317. hr = S_OK;
  1318. }
  1319. else
  1320. {
  1321. hr = E_OUTOFMEMORY;
  1322. }
  1323. }
  1324. return hr;
  1325. }
  1326. IDeskBand* CSearchBand_Create()
  1327. {
  1328. IDeskBand* pistb = NULL;
  1329. IUnknown *punk;
  1330. HRESULT hr = CSearchBand_CreateInstance(NULL, &punk, NULL);
  1331. if (SUCCEEDED(hr))
  1332. {
  1333. punk->QueryInterface(IID_PPV_ARG(IDeskBand, &pistb));
  1334. ASSERT(pistb);
  1335. punk->Release();
  1336. }
  1337. return pistb;
  1338. }
  1339. HRESULT CSearchBand::QueryInterface(REFIID riid, void **ppvObj)
  1340. {
  1341. static const QITAB qit[] = {
  1342. QITABENT(CSearchBand, IContextMenu),
  1343. QITABENT(CSearchBand, IBandNavigate),
  1344. QITABENT(CSearchBand, ISearchBandTBHelper),
  1345. QITABENT(CSearchBand, IServiceProvider),
  1346. QITABENT(CSearchBand, IInternetSecurityManager),
  1347. { 0 },
  1348. };
  1349. HRESULT hres = QISearch(this, qit, riid, ppvObj);
  1350. if (FAILED(hres))
  1351. hres = CBrowserBand::QueryInterface(riid, ppvObj);
  1352. return hres;
  1353. }
  1354. ULONG CSearchBand::AddRef()
  1355. {
  1356. return CBrowserBand::AddRef();
  1357. }
  1358. ULONG CSearchBand::Release()
  1359. {
  1360. return CBrowserBand::Release();
  1361. }
  1362. void CSearchBand::_Connect(BOOL fConnect)
  1363. {
  1364. CBrowserBand::_Connect(fConnect);
  1365. // Now we need to expose ourselves so the control in the search assistant
  1366. // can talk to us.
  1367. if (_pauto)
  1368. {
  1369. IWebBrowserApp *pWebBrowserApp;
  1370. HRESULT hr = _pauto->QueryInterface(IID_PPV_ARG(IWebBrowserApp, &pWebBrowserApp));
  1371. if (SUCCEEDED(hr))
  1372. {
  1373. ASSERT(NULL != pWebBrowserApp);
  1374. BSTR bstrProp = SysAllocString(c_wszThisBandIsYourBand);
  1375. if (NULL != bstrProp)
  1376. {
  1377. VARIANT varThis;
  1378. if (fConnect)
  1379. {
  1380. varThis.vt = VT_UNKNOWN;
  1381. varThis.punkVal = (IBandNavigate *)this;
  1382. }
  1383. else
  1384. {
  1385. varThis.vt = VT_EMPTY;
  1386. }
  1387. pWebBrowserApp->PutProperty(bstrProp, varThis);
  1388. SysFreeString(bstrProp);
  1389. }
  1390. pWebBrowserApp->Release();
  1391. }
  1392. }
  1393. }
  1394. void CSearchBand::_InitBrowser(void)
  1395. {
  1396. CBrowserBand::_InitBrowser();
  1397. }
  1398. HRESULT CSearchBand::_NavigateOC()
  1399. {
  1400. HRESULT hres = E_FAIL;
  1401. if (_pidl) // don't want search pane to be navigated to home.
  1402. return CBrowserBand::_NavigateOC();
  1403. return hres;
  1404. }
  1405. HRESULT CSearchBand::GetBandInfo(DWORD dwBandID, DWORD fViewMode,
  1406. DESKBANDINFO* pdbi)
  1407. {
  1408. _dwBandID = dwBandID;
  1409. pdbi->dwModeFlags = DBIMF_FIXEDBMP | DBIMF_VARIABLEHEIGHT;
  1410. pdbi->ptMinSize.x = 16;
  1411. pdbi->ptMinSize.y = 0;
  1412. pdbi->ptMaxSize.x = 32000; // random
  1413. pdbi->ptMaxSize.y = 32000; // random
  1414. pdbi->ptActual.y = -1;
  1415. pdbi->ptActual.x = -1;
  1416. pdbi->ptIntegral.y = 1;
  1417. MLLoadStringW(IDS_BAND_SEARCH, pdbi->wszTitle, ARRAYSIZE(pdbi->wszTitle));
  1418. return S_OK;
  1419. }
  1420. //*** CSearchBand::IPersistStream::* {
  1421. HRESULT CSearchBand::GetClassID(CLSID *pClassID)
  1422. {
  1423. *pClassID = CLSID_SearchBand;
  1424. return S_OK;
  1425. }
  1426. HRESULT CSearchBand::Load(IStream *pstm)
  1427. {
  1428. _NavigateOC();
  1429. return S_OK;
  1430. }
  1431. HRESULT CSearchBand::Save(IStream *pstm, BOOL fClearDirty)
  1432. {
  1433. return S_OK;
  1434. }
  1435. HRESULT CSearchBand::Select(LPCITEMIDLIST pidl)
  1436. {
  1437. HRESULT hres = S_OK;
  1438. IServiceProvider *psp = NULL;
  1439. LPITEMIDLIST pidlTemp = NULL;
  1440. OCHost_QueryInterface(_hwnd, IID_PPV_ARG(IServiceProvider, &psp));
  1441. if (psp)
  1442. {
  1443. IBrowserService * pbs;
  1444. if (EVAL(SUCCEEDED(psp->QueryService(SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &pbs)))))
  1445. {
  1446. pbs->GetPidl(&pidlTemp);
  1447. pbs->Release();
  1448. }
  1449. psp->Release();
  1450. }
  1451. if ((!pidlTemp) || (!ILIsEqual(pidlTemp, pidl)))
  1452. {
  1453. ILFree(_pidl);
  1454. _pidl = ILClone(pidl);
  1455. hres = _NavigateOC();
  1456. }
  1457. ILFree(pidlTemp);
  1458. return hres;
  1459. }
  1460. STDMETHODIMP CSearchBand::QueryService(REFGUID guidService, REFIID riid, LPVOID* ppvObj)
  1461. {
  1462. HRESULT hres;
  1463. if (IsEqualGUID(guidService, SID_SInternetSecurityManager))
  1464. {
  1465. _bNewUrl = TRUE;
  1466. hres = QueryInterface(riid, ppvObj);
  1467. }
  1468. else
  1469. hres = CBrowserBand::QueryService(guidService, riid, ppvObj);
  1470. return hres;
  1471. }
  1472. HRESULT CSearchBand::OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
  1473. {
  1474. if ((WM_WININICHANGE == uMsg) && lParam &&
  1475. ((0 == StrCmpW((LPCWSTR)lParam, SEARCH_SETTINGS_CHANGEDW)) ||
  1476. (0 == StrCmpA((LPCSTR) lParam, SEARCH_SETTINGS_CHANGEDA))))
  1477. {
  1478. _NavigateToSearchUrl();
  1479. }
  1480. return CBrowserBand::OnWinEvent(hwnd, uMsg, wParam, lParam, plres);
  1481. }
  1482. BOOL CSearchBand::_IsSafeUrl(LPCWSTR pwszUrl)
  1483. {
  1484. BOOL bRet = FALSE;
  1485. HKEY hkey;
  1486. if (_bNewUrl || !_bUseDefault)
  1487. {
  1488. WCHAR wsz[MAX_URL_STRING];
  1489. DWORD cch = ARRAYSIZE(wsz);
  1490. if (SUCCEEDED(UrlCanonicalizeW(pwszUrl, wsz, &cch, 0)) && cch > 0)
  1491. {
  1492. // the first time this f-n is called, url passed in is the url of
  1493. // the top most frame -- if that's not one of our 'safe' urls we
  1494. // don't want to use this security mgr because it is possible
  1495. // that the outer frame hosts iframe w/ 'safe' site and scripts
  1496. // shell dispatch from the outside thus being able to do anything
  1497. // it wants.
  1498. if (_wszCache[0] != L'\0')
  1499. {
  1500. if ((_nCmpLength && StrCmpNIW(wsz, _wszCache, _nCmpLength) == 0)
  1501. || (!_nCmpLength && StrCmpIW(wsz, _wszCache) == 0))
  1502. return _bIsCacheSafe;
  1503. }
  1504. if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\SafeSites", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  1505. {
  1506. WCHAR wszValue[MAX_PATH];
  1507. WCHAR wszData[MAX_URL_STRING];
  1508. DWORD cbData = SIZEOF(wszData);
  1509. DWORD cchValue = ARRAYSIZE(wszValue);
  1510. for (int i=0; RegEnumValueW(hkey, i, wszValue, &cchValue, NULL, NULL, (LPBYTE)wszData, &cbData) == ERROR_SUCCESS; i++)
  1511. {
  1512. if (SHExpandEnvironmentStringsW(wszData, _wszCache, ARRAYSIZE(_wszCache)) > 0)
  1513. {
  1514. cchValue = ARRAYSIZE(_wszCache);
  1515. if (SUCCEEDED(UrlCanonicalizeW(_wszCache, _wszCache, &cchValue, 0)) && (cchValue > 0))
  1516. {
  1517. if (_wszCache[cchValue - 1] == L'*')
  1518. {
  1519. _nCmpLength = cchValue - 1;
  1520. bRet = StrCmpNIW(wsz, _wszCache, _nCmpLength) == 0;
  1521. }
  1522. else
  1523. {
  1524. _nCmpLength = 0;
  1525. bRet = StrCmpIW(wsz, _wszCache) == 0;
  1526. }
  1527. _bIsCacheSafe = bRet;
  1528. if (bRet)
  1529. break;
  1530. }
  1531. cbData = SIZEOF(_wszCache);
  1532. cchValue = ARRAYSIZE(wszValue);
  1533. }
  1534. }
  1535. RegCloseKey(hkey);
  1536. }
  1537. // we did not find the url in the list of 'safe' sites
  1538. // _wszCache now point to the last url read from the registry
  1539. // ajdust it to point pwszUrl, _bIsCacheSafe is correct already
  1540. if (!bRet)
  1541. lstrcpynW(_wszCache, wsz, ARRAYSIZE(_wszCache));
  1542. if (_bNewUrl)
  1543. {
  1544. _bNewUrl = FALSE;
  1545. _bUseDefault = !bRet;
  1546. }
  1547. }
  1548. }
  1549. return bRet;
  1550. }
  1551. //*** CCommBand {
  1552. //
  1553. ////////////////
  1554. /// Comm (BrowserOC) band
  1555. class CCommBand : public CBrowserBand
  1556. {
  1557. public:
  1558. // *** IPersistStream methods ***
  1559. // (others use base class implementation)
  1560. virtual STDMETHODIMP GetClassID(CLSID *pClassID);
  1561. virtual STDMETHODIMP Load(IStream *pStm);
  1562. virtual STDMETHODIMP Save(IStream *pStm, BOOL fClearDirty);
  1563. // *** IDockingWindow methods ***
  1564. virtual STDMETHODIMP ShowDW(BOOL fShow);
  1565. protected:
  1566. CCommBand();
  1567. virtual ~CCommBand();
  1568. friend HRESULT CCommBand_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi); // for ctor
  1569. };
  1570. CCommBand::CCommBand() :
  1571. CBrowserBand()
  1572. {
  1573. _fBlockSIDProxy = FALSE;
  1574. _fBlockDrop = TRUE;
  1575. _fCustomTitle = TRUE;
  1576. _wszTitle[0] = L'\0';
  1577. _dwModeFlags = DBIMF_VARIABLEHEIGHT;
  1578. return;
  1579. }
  1580. CCommBand::~CCommBand()
  1581. {
  1582. }
  1583. HRESULT CCommBand_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  1584. {
  1585. // aggregation checking is handled in class factory
  1586. *ppunk = NULL;
  1587. LPITEMIDLIST pidlNew;
  1588. HRESULT hr = IECreateFromPath(L"about:blank", &pidlNew);
  1589. if (SUCCEEDED(hr))
  1590. {
  1591. CCommBand *p = new CCommBand();
  1592. if (p)
  1593. {
  1594. p->_pidl = pidlNew;
  1595. *ppunk = SAFECAST(p, IDeskBand*);
  1596. hr = S_OK;
  1597. }
  1598. else
  1599. {
  1600. ILFree(pidlNew);
  1601. hr = E_OUTOFMEMORY;
  1602. }
  1603. }
  1604. return hr;
  1605. }
  1606. //*** CCommBand::IPersistStream::* {
  1607. HRESULT CCommBand::GetClassID(CLSID *pClassID)
  1608. {
  1609. *pClassID = CLSID_CommBand;
  1610. return S_OK;
  1611. }
  1612. HRESULT CCommBand::Load(IStream *pstm)
  1613. {
  1614. // _NavigateOC();
  1615. return S_OK;
  1616. }
  1617. HRESULT CCommBand::Save(IStream *pstm, BOOL fClearDirty)
  1618. {
  1619. return S_OK;
  1620. }
  1621. HRESULT CCommBand::ShowDW(BOOL fShow)
  1622. {
  1623. // so that the contained Browser OC event gets fired
  1624. if (_pauto) {
  1625. _pauto->put_Visible(fShow);
  1626. }
  1627. return CBrowserBand::ShowDW(fShow);
  1628. }
  1629. // }