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.

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