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.

2081 lines
56 KiB

  1. #include "priv.h"
  2. #include "caggunk.h"
  3. #include "srchasst.h"
  4. #include "dhuihand.h"
  5. #include "mlang.h" // fo char conversion
  6. #include "..\browseui\legacy.h" // for CITIDM_GETFOLDERSEARCHES
  7. #include "varutil.h"
  8. #include <wininet.h>
  9. /////////////////////////////////////////////////////////////////////////////
  10. // CSearchAssistantOC
  11. // If you change this, change browseui also.
  12. const WCHAR c_wszThisBandIsYourBand[] = L"$$SearchBand$$";
  13. // HKLM values
  14. #define REG_SZ_SEARCH L"Software\\Microsoft\\Internet Explorer\\Search"
  15. #define REG_SZ_SEARCHASSIST L"SearchAssistant"
  16. #define REG_SZ_SEARCHCFG L"CustomizeSearch"
  17. // HKCU values
  18. #define REG_SZ_IE_MAIN L"Software\\Microsoft\\Internet Explorer\\Main"
  19. #define REG_SZ_IE_SEARCURL L"Software\\Microsoft\\Internet Explorer\\SearchURL"
  20. #define REG_SZ_SEARCHBAR L"Search Bar"
  21. #define REG_SZ_USECUSTOM L"Use Custom Search URL"
  22. #define REG_SZ_AUTOSEARCH L"AutoSearch"
  23. #define REG_SZ_PROVIDER L"Provider"
  24. #define REG_SZ_USE_SEARCH_COMP L"Use Search Asst"
  25. #define SAOC_VERSION 2
  26. const WCHAR c_wszSearchProps[] = REG_SZ_SEARCH L"\\SearchProperties";
  27. STDAPI_(VARIANT_BOOL) UseCustomInternetSearch()
  28. {
  29. VARIANT_BOOL bRet;
  30. DWORD dwVal;
  31. DWORD cbVal = sizeof(dwVal);
  32. if ((SHGetValueW(HKEY_CURRENT_USER,
  33. REG_SZ_IE_MAIN,
  34. REG_SZ_USECUSTOM,
  35. NULL,
  36. &dwVal,
  37. &cbVal) == ERROR_SUCCESS) &&
  38. (FALSE != dwVal))
  39. {
  40. bRet = VARIANT_TRUE;
  41. }
  42. else
  43. {
  44. bRet = VARIANT_FALSE;
  45. }
  46. return bRet;
  47. }
  48. STDAPI_(BOOL) GetSearchAssistantUrlW(LPWSTR pwszUrl, int cchUrl, BOOL bSubstitute, BOOL bCustomize)
  49. {
  50. BOOL bResult;
  51. WCHAR wszUrlTmp[MAX_URL_STRING];
  52. WCHAR *pwszUrlRead;
  53. DWORD cb;
  54. ASSERT(pwszUrl);
  55. *pwszUrl = 0;
  56. if (bSubstitute)
  57. {
  58. cb = sizeof(wszUrlTmp);
  59. pwszUrlRead = wszUrlTmp;
  60. }
  61. else
  62. {
  63. cb = cchUrl * sizeof(WCHAR);
  64. pwszUrlRead = pwszUrl;
  65. }
  66. bResult = SHGetValueW(HKEY_LOCAL_MACHINE,
  67. REG_SZ_SEARCH,
  68. bCustomize ? REG_SZ_SEARCHCFG : REG_SZ_SEARCHASSIST,
  69. NULL, (BYTE *)pwszUrlRead, &cb) == ERROR_SUCCESS;
  70. if (bResult && bSubstitute)
  71. {
  72. bResult = SUCCEEDED(URLSubstitution(wszUrlTmp, pwszUrl, cchUrl, URLSUB_ALL));
  73. }
  74. return bResult;
  75. }
  76. STDAPI_(BOOL) GetDefaultInternetSearchUrlW(LPWSTR pwszUrl, int cchUrl, BOOL bSubstitute)
  77. {
  78. BOOL bResult = FALSE;
  79. DWORD cb;
  80. ASSERT(pwszUrl);
  81. *pwszUrl = 0;
  82. if (UseCustomInternetSearch())
  83. {
  84. // First try the user specific value
  85. cb = cchUrl * sizeof(TCHAR);
  86. bResult = SHGetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_SEARCHBAR,
  87. NULL, (BYTE *)pwszUrl, &cb) == ERROR_SUCCESS;
  88. }
  89. if (!bResult)
  90. {
  91. bResult = GetSearchAssistantUrlW(pwszUrl, cchUrl, bSubstitute, FALSE);
  92. }
  93. return bResult;
  94. }
  95. STDAPI_(BOOL) GetSearchAssistantUrlA(LPSTR pszUrl, int cchUrl, BOOL bSubstitute, BOOL bCustomize)
  96. {
  97. WCHAR wszUrl[INTERNET_MAX_URL_LENGTH];
  98. BOOL bResult = GetSearchAssistantUrlW(wszUrl, ARRAYSIZE(wszUrl), bSubstitute, bCustomize);
  99. SHUnicodeToAnsi(wszUrl, pszUrl, cchUrl);
  100. return bResult;
  101. }
  102. STDAPI_(BOOL) GetDefaultInternetSearchUrlA(LPSTR pszUrl, int cchUrl, BOOL bSubstitute)
  103. {
  104. WCHAR wszUrl[INTERNET_MAX_URL_LENGTH];
  105. BOOL bResult = GetDefaultInternetSearchUrlW(wszUrl, ARRAYSIZE(wszUrl), bSubstitute);
  106. SHUnicodeToAnsi(wszUrl, pszUrl, cchUrl);
  107. return bResult;
  108. }
  109. void SetDefaultInternetSearchUrlW(LPCWSTR pwszUrl)
  110. {
  111. DWORD dwUseCustom = FALSE;
  112. DWORD cb;
  113. if ((NULL != pwszUrl) && (0 != *pwszUrl))
  114. {
  115. cb = (lstrlenW(pwszUrl) + 1) * sizeof(WCHAR);
  116. if (SHSetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_SEARCHBAR, REG_SZ,
  117. pwszUrl, cb) == ERROR_SUCCESS)
  118. {
  119. dwUseCustom = TRUE;
  120. }
  121. }
  122. cb = sizeof(dwUseCustom);
  123. SHSetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_USECUSTOM, REG_DWORD,
  124. &dwUseCustom, cb);
  125. }
  126. HRESULT CSearch_Create(GUID *pguid, BSTR bstrTitle, BSTR bstrUrl, ISearch **ppSearch)
  127. {
  128. HRESULT hres = E_INVALIDARG;
  129. ASSERT(ppSearch);
  130. *ppSearch = NULL;
  131. if (bstrTitle && bstrUrl && pguid)
  132. {
  133. BSTR _bstrTitle = SysAllocString(bstrTitle);
  134. BSTR _bstrUrl = SysAllocString(bstrUrl);
  135. if (_bstrTitle && _bstrUrl)
  136. {
  137. CSearch *ps = new CSearch(pguid, _bstrTitle, _bstrUrl);
  138. if (ps)
  139. {
  140. hres = ps->QueryInterface(IID_ISearch, (void **)ppSearch);
  141. ps->Release();
  142. }
  143. }
  144. else
  145. {
  146. if (_bstrTitle)
  147. SysFreeString(_bstrTitle);
  148. if (_bstrUrl)
  149. SysFreeString(_bstrUrl);
  150. hres = E_OUTOFMEMORY;
  151. }
  152. }
  153. return hres;
  154. }
  155. CSearch::CSearch(GUID *pguid, BSTR bstrTitle, BSTR bstrUrl) :
  156. _cRef(1), _bstrTitle(bstrTitle), _bstrUrl(bstrUrl),
  157. CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_ISearch)
  158. {
  159. SHStringFromGUID(*pguid, _szId, ARRAYSIZE(_szId));
  160. }
  161. CSearch::~CSearch()
  162. {
  163. if (_bstrTitle)
  164. SysFreeString(_bstrTitle);
  165. if (_bstrUrl)
  166. SysFreeString(_bstrUrl);
  167. }
  168. STDMETHODIMP CSearch::QueryInterface(REFIID riid, void** ppv)
  169. {
  170. static const QITAB qit[] = {
  171. QITABENT(CSearch, ISearch),
  172. QITABENTMULTI(CSearch, IDispatch, ISearch),
  173. { 0 },
  174. };
  175. return QISearch(this, qit, riid, ppv);
  176. }
  177. STDMETHODIMP_(ULONG) CSearch::AddRef()
  178. {
  179. InterlockedIncrement(&_cRef);
  180. return _cRef;
  181. }
  182. STDMETHODIMP_(ULONG) CSearch::Release()
  183. {
  184. if (InterlockedDecrement(&_cRef) > 0)
  185. return _cRef;
  186. delete this;
  187. return 0;
  188. }
  189. HRESULT CSearch::get_Title(BSTR *pbstrTitle)
  190. {
  191. HRESULT hres = NOERROR;
  192. *pbstrTitle = SysAllocString(_bstrTitle);
  193. if (!*pbstrTitle)
  194. hres = E_OUTOFMEMORY;
  195. return hres;
  196. }
  197. HRESULT CSearch::get_Id(BSTR *pbstrId)
  198. {
  199. HRESULT hres = NOERROR;
  200. *pbstrId = SysAllocString(_szId);
  201. if (!*pbstrId)
  202. hres = E_OUTOFMEMORY;
  203. return hres;
  204. }
  205. HRESULT CSearch::get_Url(BSTR *pbstrUrl)
  206. {
  207. HRESULT hres = NOERROR;
  208. *pbstrUrl = SysAllocString(_bstrUrl);
  209. if (!*pbstrUrl)
  210. hres = E_OUTOFMEMORY;
  211. return hres;
  212. }
  213. HRESULT CSearchCollection_Create(IFolderSearches *pfs, ISearches **ppSearches)
  214. {
  215. HRESULT hres = E_INVALIDARG;
  216. ASSERT(ppSearches);
  217. *ppSearches = NULL;
  218. if (pfs)
  219. {
  220. CSearchCollection *psc = new CSearchCollection(pfs);
  221. if (psc)
  222. {
  223. hres = psc->QueryInterface(IID_ISearches, (void **)ppSearches);
  224. psc->Release();
  225. }
  226. else
  227. hres = E_OUTOFMEMORY;
  228. }
  229. return hres;
  230. }
  231. CSearchCollection::CSearchCollection(IFolderSearches *pfs) :
  232. _cRef(1), CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_ISearches)
  233. {
  234. GUID guid;
  235. if (SUCCEEDED(pfs->DefaultSearch(&guid)))
  236. SHStringFromGUID(guid, _szDefault, ARRAYSIZE(_szDefault));
  237. _hdsaItems = DSA_Create(SIZEOF(URLSEARCH), 4);
  238. if (_hdsaItems)
  239. {
  240. IEnumUrlSearch *penum;
  241. if (SUCCEEDED(pfs->EnumSearches(&penum)))
  242. {
  243. URLSEARCH us;
  244. ULONG cElt;
  245. penum->Reset();
  246. while (S_OK == penum->Next(1, &us, &cElt) && 1 == cElt)
  247. DSA_AppendItem(_hdsaItems, &us);
  248. penum->Release();
  249. }
  250. }
  251. }
  252. CSearchCollection::~CSearchCollection()
  253. {
  254. DSA_Destroy(_hdsaItems);
  255. _hdsaItems = NULL;
  256. }
  257. STDMETHODIMP CSearchCollection::QueryInterface(REFIID riid, void** ppv)
  258. {
  259. static const QITAB qit[] = {
  260. QITABENT(CSearchCollection, ISearches),
  261. QITABENTMULTI(CSearchCollection, IDispatch, ISearches),
  262. { 0 },
  263. };
  264. return QISearch(this, qit, riid, ppv);
  265. }
  266. STDMETHODIMP_(ULONG) CSearchCollection::AddRef()
  267. {
  268. InterlockedIncrement(&_cRef);
  269. return _cRef;
  270. }
  271. STDMETHODIMP_(ULONG) CSearchCollection::Release()
  272. {
  273. if (InterlockedDecrement(&_cRef) > 0)
  274. return _cRef;
  275. delete this;
  276. return 0;
  277. }
  278. STDMETHODIMP CSearchCollection::get_Count(long *plCount)
  279. {
  280. *plCount = 0;
  281. if (_hdsaItems)
  282. {
  283. *plCount = DSA_GetItemCount(_hdsaItems);
  284. }
  285. return S_OK;
  286. }
  287. STDMETHODIMP CSearchCollection::get_Default(BSTR *pbstrDefault)
  288. {
  289. HRESULT hres = E_OUTOFMEMORY;
  290. *pbstrDefault = SysAllocString(_szDefault);
  291. if (*pbstrDefault)
  292. hres = S_OK;
  293. return hres;
  294. }
  295. STDMETHODIMP CSearchCollection::Item(VARIANT index, ISearch **ppid)
  296. {
  297. HRESULT hres = E_NOTIMPL;
  298. *ppid = NULL;
  299. switch (index.vt)
  300. {
  301. case VT_I2:
  302. index.lVal = (long)index.iVal;
  303. // And fall through...
  304. case VT_I4:
  305. if ((index.lVal >= 0) && (index.lVal < DSA_GetItemCount(_hdsaItems)))
  306. {
  307. LPURLSEARCH pus;
  308. pus = (LPURLSEARCH)DSA_GetItemPtr(_hdsaItems, index.lVal);
  309. ASSERT(pus);
  310. hres = CSearch_Create(&pus->guid, pus->wszName, pus->wszUrl, ppid);
  311. }
  312. break;
  313. #if 0
  314. // should we worry about this one?
  315. case VT_BSTR:
  316. #endif
  317. }
  318. return hres;
  319. }
  320. STDMETHODIMP CSearchCollection::_NewEnum(IUnknown **ppunk)
  321. {
  322. *ppunk = NULL;
  323. return E_NOTIMPL;
  324. }
  325. CSearchAssistantOC::CSearchAssistantOC()
  326. : m_punkSite(NULL)
  327. {
  328. #ifdef UNIX
  329. m_dwSafety = 0;
  330. #endif
  331. }
  332. CSearchAssistantOC::~CSearchAssistantOC()
  333. {
  334. ATOMICRELEASE(m_pSearchBandTBHelper);
  335. ATOMICRELEASE(m_punkSite);
  336. }
  337. HRESULT CSearchAssistantOC::OnDraw(ATL_DRAWINFO& di)
  338. {
  339. return S_OK;
  340. }
  341. STDMETHODIMP CSearchAssistantOC::SetClientSite(IOleClientSite *pClientSite)
  342. {
  343. if (NULL != pClientSite)
  344. {
  345. HRESULT hr;
  346. IWebBrowser2 *pWebBrowser2;
  347. hr = IUnknown_QueryService(pClientSite, SID_SWebBrowserApp, IID_IWebBrowser2,
  348. (void **)&pWebBrowser2);
  349. if (SUCCEEDED(hr))
  350. {
  351. BSTR bstrProp = SysAllocString(c_wszThisBandIsYourBand);
  352. if (bstrProp)
  353. {
  354. VARIANT var;
  355. hr = pWebBrowser2->GetProperty(bstrProp, &var);
  356. if (SUCCEEDED(hr))
  357. {
  358. if (var.vt == VT_UNKNOWN)
  359. {
  360. ATOMICRELEASE(m_pSearchBandTBHelper);
  361. hr = var.punkVal->QueryInterface(IID_ISearchBandTBHelper,
  362. (void **)&m_pSearchBandTBHelper);
  363. ASSERT(SUCCEEDED(hr));
  364. if (m_pSearchBandTBHelper)
  365. m_pSearchBandTBHelper->SetOCCallback(this);
  366. }
  367. VariantClear(&var);
  368. }
  369. SysFreeString(bstrProp);
  370. }
  371. pWebBrowser2->Release();
  372. }
  373. }
  374. else
  375. {
  376. if (NULL != m_pSearchBandTBHelper)
  377. {
  378. m_pSearchBandTBHelper->SetOCCallback(NULL);
  379. ATOMICRELEASE(m_pSearchBandTBHelper);
  380. }
  381. }
  382. return IOleObjectImpl<CSearchAssistantOC>::SetClientSite(pClientSite);
  383. }
  384. STDMETHODIMP CSearchAssistantOC::QueryStatus(const GUID *pguidCmdGroup,
  385. ULONG cCmds,
  386. OLECMD prgCmds[],
  387. OLECMDTEXT *pCmdText)
  388. {
  389. return E_NOTIMPL;
  390. }
  391. STDMETHODIMP CSearchAssistantOC::Exec(const GUID *pguidCmdGroup,
  392. DWORD nCmdID,
  393. DWORD nCmdexecopt,
  394. VARIANT *pvaIn,
  395. VARIANT *pvaOut)
  396. {
  397. HRESULT hr = E_UNEXPECTED;
  398. if (NULL == pguidCmdGroup)
  399. {
  400. switch (nCmdID)
  401. {
  402. case SBID_SEARCH_NEXT:
  403. if ((NULL != pvaIn) && (pvaIn->vt == VT_I4))
  404. {
  405. Fire_OnNextMenuSelect(pvaIn->lVal);
  406. hr = S_OK;
  407. }
  408. else
  409. {
  410. hr = E_INVALIDARG;
  411. }
  412. break;
  413. case SBID_SEARCH_NEW:
  414. if (NULL != pvaOut)
  415. {
  416. m_bEventHandled = VARIANT_FALSE;
  417. Fire_OnNewSearch();
  418. pvaOut->vt = VT_BOOL;
  419. pvaOut->boolVal = m_bEventHandled;
  420. hr = S_OK;
  421. }
  422. else
  423. {
  424. hr = E_INVALIDARG;
  425. }
  426. break;
  427. }
  428. }
  429. return hr;
  430. }
  431. STDMETHODIMP CSearchAssistantOC::AddNextMenuItem(BSTR bstrText, long idItem)
  432. {
  433. HRESULT hr;
  434. if (IsTrustedSite())
  435. {
  436. if (NULL != m_pSearchBandTBHelper)
  437. {
  438. hr = m_pSearchBandTBHelper->AddNextMenuItem(bstrText, idItem);
  439. ASSERT(SUCCEEDED(hr));
  440. }
  441. hr = S_OK;
  442. }
  443. else
  444. {
  445. hr = E_ACCESSDENIED;
  446. }
  447. return hr;
  448. }
  449. STDMETHODIMP CSearchAssistantOC::ResetNextMenu()
  450. {
  451. HRESULT hr;
  452. if (IsTrustedSite())
  453. {
  454. if (NULL != m_pSearchBandTBHelper)
  455. {
  456. hr = m_pSearchBandTBHelper->ResetNextMenu();
  457. ASSERT(SUCCEEDED(hr));
  458. }
  459. hr = S_OK;
  460. }
  461. else
  462. {
  463. hr = E_ACCESSDENIED;
  464. }
  465. return hr;
  466. }
  467. STDMETHODIMP CSearchAssistantOC::SetDefaultSearchUrl(BSTR bstrUrl)
  468. {
  469. HRESULT hr;
  470. if (IsTrustedSite())
  471. {
  472. SetDefaultInternetSearchUrlW(bstrUrl);
  473. hr = S_OK;
  474. }
  475. else
  476. {
  477. hr = E_ACCESSDENIED;
  478. }
  479. return hr;
  480. }
  481. STDMETHODIMP CSearchAssistantOC::NavigateToDefaultSearch()
  482. {
  483. HRESULT hr;
  484. IWebBrowser2 *pWebBrowser2;
  485. hr = IUnknown_QueryService(m_spClientSite, SID_SWebBrowserApp, IID_IWebBrowser2,
  486. (void **)&pWebBrowser2);
  487. if (SUCCEEDED(hr))
  488. {
  489. WCHAR wszUrl[INTERNET_MAX_URL_LENGTH];
  490. if (GetDefaultInternetSearchUrlW(wszUrl, ARRAYSIZE(wszUrl), TRUE))
  491. {
  492. BSTR bstrUrl = SysAllocString(wszUrl);
  493. if (NULL != bstrUrl)
  494. {
  495. VARIANT varFrame;
  496. varFrame.vt = VT_BSTR;
  497. varFrame.bstrVal = SysAllocString(L"_search");
  498. if (NULL != varFrame.bstrVal)
  499. {
  500. hr = pWebBrowser2->Navigate(bstrUrl, NULL, &varFrame, NULL, NULL);
  501. ASSERT(SUCCEEDED(hr));
  502. SysFreeString(varFrame.bstrVal);
  503. }
  504. SysFreeString(bstrUrl);
  505. }
  506. }
  507. pWebBrowser2->Release();
  508. }
  509. return S_OK;
  510. }
  511. typedef struct _GUIDREST
  512. {
  513. const GUID * pguid;
  514. RESTRICTIONS rest;
  515. } GUIDREST;
  516. HRESULT CSearchAssistantOC::IsRestricted(BSTR bstrGuid, VARIANT_BOOL *pVal)
  517. {
  518. HRESULT hr;
  519. GUID guid;
  520. if (IsTrustedSite())
  521. {
  522. *pVal = VARIANT_FALSE; // default to not restricted
  523. if (SUCCEEDED(SHCLSIDFromString(bstrGuid, &guid)))
  524. {
  525. // find computer is special because if it restricted then we show
  526. // it else don't show it (restriction name is HASFINDCOMPUTER
  527. if (IsEqualGUID(guid, SRCID_SFindComputer))
  528. {
  529. if (!SHRestricted(REST_HASFINDCOMPUTERS))
  530. *pVal = VARIANT_TRUE;
  531. }
  532. else
  533. {
  534. static GUIDREST agr[] =
  535. {
  536. {&SRCID_SFileSearch, REST_NOFIND},
  537. // rest_nofindprinter does not exist yet
  538. //{&SRCID_SFindPrinter, REST_NOFINDPRINTER},
  539. };
  540. for (int i=0; i < ARRAYSIZE(agr); i++)
  541. {
  542. if (IsEqualGUID(guid, *agr[i].pguid))
  543. {
  544. if (SHRestricted(agr[i].rest))
  545. *pVal = VARIANT_TRUE;
  546. break;
  547. }
  548. }
  549. }
  550. }
  551. hr = S_OK;
  552. }
  553. else
  554. {
  555. hr = E_ACCESSDENIED;
  556. }
  557. return hr;
  558. }
  559. HRESULT CSearchAssistantOC::get_ShellFeaturesEnabled(VARIANT_BOOL *pVal)
  560. {
  561. HRESULT hr;
  562. if (IsTrustedSite())
  563. {
  564. if (pVal)
  565. {
  566. *pVal = (GetUIVersion() >= 5) ? VARIANT_TRUE : VARIANT_FALSE;
  567. hr = S_OK;
  568. }
  569. else
  570. {
  571. hr = E_INVALIDARG;
  572. }
  573. }
  574. else
  575. {
  576. hr = E_ACCESSDENIED;
  577. }
  578. return hr;
  579. }
  580. HRESULT CSearchAssistantOC::get_SearchAssistantDefault(VARIANT_BOOL *pVal)
  581. {
  582. HRESULT hr;
  583. if (IsTrustedSite())
  584. {
  585. if (pVal)
  586. {
  587. *pVal = !UseCustomInternetSearch();
  588. hr = S_OK;
  589. }
  590. else
  591. {
  592. hr = E_INVALIDARG;
  593. }
  594. }
  595. else
  596. {
  597. hr = E_ACCESSDENIED;
  598. }
  599. return hr;
  600. }
  601. STDMETHODIMP CSearchAssistantOC::get_Searches(ISearches **ppid)
  602. {
  603. HRESULT hr;
  604. *ppid = NULL;
  605. if (IsTrustedSite())
  606. {
  607. IServiceProvider *psp;
  608. hr = IUnknown_QueryService(m_spClientSite, SID_STopLevelBrowser, IID_IServiceProvider, (void**)&psp);
  609. if (SUCCEEDED(hr))
  610. {
  611. IOleCommandTarget *pct;
  612. hr = psp->QueryService(SID_SExplorerToolbar, IID_IOleCommandTarget, (void **)&pct);
  613. if (SUCCEEDED(hr))
  614. {
  615. VARIANTARG var = {0};
  616. hr = pct->Exec(&CGID_PrivCITCommands, CITIDM_GETFOLDERSEARCHES, 0, NULL, &var);
  617. if (SUCCEEDED(hr))
  618. {
  619. IFolderSearches *pfs;
  620. ASSERT(var.vt == VT_UNKNOWN && var.punkVal);
  621. hr = var.punkVal->QueryInterface(IID_IFolderSearches, (void **)&pfs);
  622. if (SUCCEEDED(hr))
  623. {
  624. hr = CSearchCollection_Create(pfs, ppid);
  625. pfs->Release();
  626. }
  627. var.punkVal->Release();
  628. }
  629. pct->Release();
  630. hr = S_OK;
  631. }
  632. psp->Release();
  633. }
  634. }
  635. else
  636. {
  637. hr = E_ACCESSDENIED;
  638. }
  639. return hr;
  640. }
  641. STDMETHODIMP CSearchAssistantOC::get_InWebFolder(VARIANT_BOOL *pVal)
  642. {
  643. HRESULT hr;
  644. if (IsTrustedSite())
  645. {
  646. ASSERT(pVal);
  647. *pVal = VARIANT_FALSE;
  648. IBrowserService2 *pbs;
  649. hr = IUnknown_QueryService(m_spClientSite, SID_STopLevelBrowser, IID_IBrowserService2, (void **)&pbs);
  650. if (SUCCEEDED(hr))
  651. {
  652. ITEMIDLIST *pidl;
  653. hr = pbs->GetPidl(&pidl);
  654. if (SUCCEEDED(hr))
  655. {
  656. // REARCHITECT: Don't use ILIsWeb(). We should use IShellFolder2::GetDefaultSearchGUID() and
  657. // test for SRCID_SWebSearch vs. SRCID_SFileSearch/SRCID_SFindComputer/SRCID_SFindPrinter.
  658. // This is because Shell Extensions need a way to indicate what kind of search they want
  659. // and ILIsWeb() doesn't provide that. An example of this is "Web Folders" won't return
  660. // TRUE from ILIsWeb(). The use of ILIsWeb() should be limited.
  661. if (ILIsWeb(pidl))
  662. {
  663. *pVal = VARIANT_TRUE;
  664. }
  665. ILFree(pidl);
  666. }
  667. pbs->Release();
  668. }
  669. hr = S_OK;
  670. }
  671. else
  672. {
  673. hr = E_ACCESSDENIED;
  674. }
  675. return hr;
  676. }
  677. void GetPerLocalePath(WCHAR *pwszKeyName, int cchKeyName)
  678. {
  679. ASSERT(cchKeyName >= (ARRAYSIZE(c_wszSearchProps) + 1));
  680. StrCpyNW(pwszKeyName, c_wszSearchProps, cchKeyName);
  681. *(pwszKeyName + (ARRAYSIZE(c_wszSearchProps) - 1)) = L'\\';
  682. GetWebLocaleAsRFC1766(pwszKeyName + ARRAYSIZE(c_wszSearchProps),
  683. cchKeyName - (ARRAYSIZE(c_wszSearchProps)));
  684. }
  685. STDMETHODIMP CSearchAssistantOC::PutProperty(VARIANT_BOOL bPerLocale, BSTR bstrName, BSTR bstrValue)
  686. {
  687. HRESULT hr;
  688. if (IsTrustedSite())
  689. {
  690. HKEY hkey;
  691. LPCWSTR pwszKeyName;
  692. WCHAR wszKeyName[MAX_PATH];
  693. DWORD dwDisposition;
  694. if (bPerLocale)
  695. {
  696. GetPerLocalePath(wszKeyName, ARRAYSIZE(wszKeyName));
  697. pwszKeyName = wszKeyName;
  698. }
  699. else
  700. {
  701. pwszKeyName = c_wszSearchProps;
  702. }
  703. if (RegCreateKeyExW(HKEY_CURRENT_USER, pwszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE,
  704. KEY_WRITE, NULL, &hkey, &dwDisposition) == ERROR_SUCCESS)
  705. {
  706. if ((NULL != bstrValue) && (bstrValue[0] != 0))
  707. {
  708. RegSetValueExW(hkey, bstrName, 0, REG_BINARY, (LPBYTE)bstrValue,
  709. SysStringByteLen(bstrValue));
  710. }
  711. else
  712. {
  713. // Empty or NULL string means remove the property
  714. RegDeleteValue(hkey, bstrName);
  715. }
  716. RegCloseKey(hkey);
  717. }
  718. hr = S_OK;
  719. }
  720. else
  721. {
  722. hr = E_ACCESSDENIED;
  723. }
  724. return hr;
  725. }
  726. STDMETHODIMP CSearchAssistantOC::GetProperty(VARIANT_BOOL bPerLocale, BSTR bstrName, BSTR *pbstrValue)
  727. {
  728. HRESULT hr;
  729. if (NULL != pbstrValue)
  730. {
  731. *pbstrValue = NULL;
  732. if (IsTrustedSite())
  733. {
  734. HKEY hkey;
  735. LPCWSTR pwszKeyName;
  736. WCHAR wszKeyName[MAX_PATH];
  737. if (bPerLocale)
  738. {
  739. GetPerLocalePath(wszKeyName, ARRAYSIZE(wszKeyName));
  740. pwszKeyName = wszKeyName;
  741. }
  742. else
  743. {
  744. pwszKeyName = c_wszSearchProps;
  745. }
  746. if (RegOpenKeyExW(HKEY_CURRENT_USER, pwszKeyName, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  747. {
  748. DWORD dwType;
  749. DWORD cbSize;
  750. if ((RegQueryValueExW(hkey, bstrName, NULL, &dwType, NULL, &cbSize) == ERROR_SUCCESS) &&
  751. (dwType == REG_BINARY))
  752. {
  753. BSTR bstrValue = SysAllocStringByteLen(NULL, cbSize);
  754. if (NULL != bstrValue)
  755. {
  756. if (RegQueryValueExW(hkey, bstrName, NULL, &dwType, (LPBYTE)bstrValue, &cbSize) == ERROR_SUCCESS)
  757. {
  758. *pbstrValue = bstrValue;
  759. }
  760. else
  761. {
  762. SysFreeString(bstrValue);
  763. }
  764. }
  765. }
  766. RegCloseKey(hkey);
  767. }
  768. hr = S_OK;
  769. }
  770. else
  771. {
  772. hr = E_ACCESSDENIED;
  773. }
  774. }
  775. else
  776. {
  777. hr = E_INVALIDARG;
  778. }
  779. return hr;
  780. }
  781. STDMETHODIMP CSearchAssistantOC::put_EventHandled(VARIANT_BOOL bHandled)
  782. {
  783. HRESULT hr;
  784. if (IsTrustedSite())
  785. {
  786. m_bEventHandled = bHandled;
  787. hr = S_OK;
  788. }
  789. else
  790. {
  791. hr = E_ACCESSDENIED;
  792. }
  793. return hr;
  794. }
  795. STDMETHODIMP CSearchAssistantOC::GetSearchAssistantURL(VARIANT_BOOL bSubstitute, VARIANT_BOOL bCustomize, BSTR *pbstrValue)
  796. {
  797. HRESULT hr;
  798. if (IsTrustedSite())
  799. {
  800. if (NULL != pbstrValue)
  801. {
  802. WCHAR wszUrl[INTERNET_MAX_URL_LENGTH];
  803. if (GetSearchAssistantUrlW(wszUrl, ARRAYSIZE(wszUrl), bSubstitute, bCustomize))
  804. {
  805. *pbstrValue = SysAllocString(wszUrl);
  806. }
  807. hr = S_OK;
  808. }
  809. else
  810. {
  811. hr = E_INVALIDARG;
  812. }
  813. }
  814. else
  815. {
  816. hr = E_ACCESSDENIED;
  817. }
  818. return hr;
  819. }
  820. STDMETHODIMP CSearchAssistantOC::NotifySearchSettingsChanged()
  821. {
  822. HRESULT hr;
  823. if (IsTrustedSite())
  824. {
  825. SendShellIEBroadcastMessage(WM_WININICHANGE, 0, (LPARAM)SEARCH_SETTINGS_CHANGED, 3000);
  826. hr = S_OK;
  827. }
  828. else
  829. {
  830. hr = E_ACCESSDENIED;
  831. }
  832. return hr;
  833. }
  834. STDMETHODIMP CSearchAssistantOC::put_ASProvider(BSTR Provider)
  835. {
  836. HRESULT hr;
  837. if (IsTrustedSite())
  838. {
  839. if (Provider)
  840. {
  841. DWORD dwRet = SHSetValueW(HKEY_CURRENT_USER, REG_SZ_IE_SEARCURL, REG_SZ_PROVIDER, REG_SZ,
  842. Provider, (lstrlenW(Provider) + 1) * sizeof(WCHAR));
  843. ASSERT(ERROR_SUCCESS == dwRet);
  844. }
  845. hr = S_OK;
  846. }
  847. else
  848. {
  849. hr = E_ACCESSDENIED;
  850. }
  851. return hr;
  852. }
  853. STDMETHODIMP CSearchAssistantOC::get_ASProvider(BSTR *pProvider)
  854. {
  855. HRESULT hr;
  856. if (IsTrustedSite())
  857. {
  858. if (NULL != pProvider)
  859. {
  860. HKEY hkey;
  861. if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CURRENT_USER, REG_SZ_IE_SEARCURL, 0, KEY_READ, &hkey))
  862. {
  863. DWORD dwType;
  864. DWORD dwSize;
  865. if ((ERROR_SUCCESS == RegQueryValueExW(hkey, REG_SZ_PROVIDER, NULL,
  866. &dwType, NULL, &dwSize)) &&
  867. (REG_SZ == dwType))
  868. {
  869. *pProvider = SysAllocStringByteLen(NULL, dwSize);
  870. if (NULL != *pProvider)
  871. {
  872. if (ERROR_SUCCESS != RegQueryValueExW(hkey, REG_SZ_PROVIDER, NULL,
  873. &dwType, (LPBYTE)*pProvider, &dwSize))
  874. {
  875. *pProvider = 0;
  876. }
  877. }
  878. }
  879. RegCloseKey(hkey);
  880. }
  881. hr = S_OK;
  882. }
  883. else
  884. {
  885. hr = E_INVALIDARG;
  886. }
  887. }
  888. else
  889. {
  890. hr = E_ACCESSDENIED;
  891. }
  892. return hr;
  893. }
  894. STDMETHODIMP CSearchAssistantOC::put_ASSetting(int Setting)
  895. {
  896. HRESULT hr;
  897. if (IsTrustedSite())
  898. {
  899. DWORD dwRet = SHSetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_AUTOSEARCH, REG_DWORD,
  900. &Setting, sizeof(DWORD));
  901. ASSERT(ERROR_SUCCESS == dwRet);
  902. hr = S_OK;
  903. }
  904. else
  905. {
  906. hr = E_ACCESSDENIED;
  907. }
  908. return hr;
  909. }
  910. STDMETHODIMP CSearchAssistantOC::get_ASSetting(int *pSetting)
  911. {
  912. HRESULT hr;
  913. if (IsTrustedSite())
  914. {
  915. if (NULL != pSetting)
  916. {
  917. DWORD dwSize = sizeof(int);
  918. *pSetting = -1;
  919. DWORD dwRet = SHGetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_AUTOSEARCH, NULL,
  920. pSetting, &dwSize);
  921. hr = S_OK;
  922. }
  923. else
  924. {
  925. hr = E_INVALIDARG;
  926. }
  927. }
  928. else
  929. {
  930. hr = E_ACCESSDENIED;
  931. }
  932. return hr;
  933. }
  934. BOOL CSearchAssistantOC::IsTrustedSite()
  935. {
  936. if (!m_bSafetyInited && m_spClientSite)
  937. {
  938. m_bSafetyInited = TRUE;
  939. IHTMLDocument2 *pHTMLDocument2;
  940. HRESULT hr = GetHTMLDoc2(m_spClientSite, &pHTMLDocument2);
  941. if (SUCCEEDED(hr))
  942. {
  943. ASSERT(NULL != pHTMLDocument2);
  944. IHTMLLocation *pHTMLLocation;
  945. hr = pHTMLDocument2->get_location(&pHTMLLocation);
  946. if (SUCCEEDED(hr) && (NULL != pHTMLLocation))
  947. {
  948. BSTR bstrUrl;
  949. pHTMLLocation->get_href(&bstrUrl);
  950. if (SUCCEEDED(hr) && (NULL != bstrUrl))
  951. {
  952. HKEY hkey;
  953. // FEATURE (tnoonan)
  954. // This code is duped with CSearchBand::_IsSafeUrl in browseui
  955. if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\SafeSites", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  956. {
  957. WCHAR wszValue[MAX_PATH];
  958. WCHAR wszData[MAX_URL_STRING];
  959. WCHAR wszExpandedUrl[MAX_URL_STRING];
  960. DWORD cbData = SIZEOF(wszData);
  961. DWORD cchValue = ARRAYSIZE(wszValue);
  962. for (int i=0; RegEnumValueW(hkey, i, wszValue, &cchValue, NULL, NULL, (LPBYTE)wszData, &cbData) == ERROR_SUCCESS; i++)
  963. {
  964. if (SHExpandEnvironmentStringsW(wszData, wszExpandedUrl, ARRAYSIZE(wszExpandedUrl)) > 0)
  965. {
  966. cchValue = ARRAYSIZE(wszExpandedUrl);
  967. if (SUCCEEDED(UrlCanonicalizeW(wszExpandedUrl, wszExpandedUrl, &cchValue, 0)))
  968. {
  969. if (cchValue > 0)
  970. {
  971. BOOL bRet;
  972. if (wszExpandedUrl[cchValue-1] == L'*')
  973. {
  974. bRet = StrCmpNIW(bstrUrl, wszExpandedUrl, cchValue - 1) == 0;
  975. }
  976. else
  977. {
  978. bRet = StrCmpIW(bstrUrl, wszExpandedUrl) == 0;
  979. }
  980. m_bIsTrustedSite = bRet ? TRUE : FALSE;
  981. if (m_bIsTrustedSite)
  982. break;
  983. }
  984. }
  985. cbData = SIZEOF(wszData);
  986. cchValue = ARRAYSIZE(wszValue);
  987. }
  988. }
  989. RegCloseKey(hkey);
  990. }
  991. SysFreeString(bstrUrl);
  992. }
  993. pHTMLLocation->Release();
  994. }
  995. pHTMLDocument2->Release();
  996. }
  997. }
  998. return m_bIsTrustedSite;
  999. }
  1000. HRESULT CSearchAssistantOC::UpdateRegistry(BOOL bRegister)
  1001. {
  1002. //this control uses selfreg.inx, not the ATL registry goo
  1003. return S_OK;
  1004. }
  1005. STDMETHODIMP CSearchAssistantOC::FindOnWeb()
  1006. {
  1007. if (!IsTrustedSite() && m_punkSite==NULL)
  1008. return E_ACCESSDENIED ;
  1009. return ShowSearchBand( SRCID_SWebSearch ) ;
  1010. }
  1011. STDMETHODIMP CSearchAssistantOC::FindFilesOrFolders()
  1012. {
  1013. if (!IsTrustedSite() && m_punkSite==NULL)
  1014. return E_ACCESSDENIED ;
  1015. return ShowSearchBand( SRCID_SFileSearch ) ;
  1016. }
  1017. STDMETHODIMP CSearchAssistantOC::FindComputer()
  1018. {
  1019. if (!IsTrustedSite() && m_punkSite==NULL)
  1020. return E_ACCESSDENIED ;
  1021. return ShowSearchBand( SRCID_SFindComputer ) ;
  1022. }
  1023. STDMETHODIMP CSearchAssistantOC::FindPrinter()
  1024. {
  1025. if (!IsTrustedSite() && m_punkSite==NULL)
  1026. return E_ACCESSDENIED ;
  1027. HRESULT hr = E_FAIL;
  1028. IShellDispatch2* psd2;
  1029. if( SUCCEEDED( (hr = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_INPROC_SERVER,
  1030. IID_IShellDispatch2, (void**)&psd2 )) ) )
  1031. {
  1032. hr = psd2->FindPrinter( NULL, NULL, NULL ) ;
  1033. psd2->Release();
  1034. }
  1035. return hr ;
  1036. }
  1037. STDMETHODIMP CSearchAssistantOC::FindPeople()
  1038. {
  1039. if (!IsTrustedSite() && m_punkSite==NULL)
  1040. {
  1041. return E_ACCESSDENIED;
  1042. }
  1043. SHELLEXECUTEINFO sei = {0};
  1044. sei.cbSize = sizeof(SHELLEXECUTEINFO);
  1045. sei.hwnd = HWND_DESKTOP;
  1046. sei.lpVerb = TEXT("open");
  1047. sei.lpFile = TEXT("wab.exe");
  1048. sei.lpParameters = TEXT("/find");
  1049. sei.lpDirectory = NULL;
  1050. sei.nShow = SW_SHOWNORMAL;
  1051. if (!ShellExecuteEx(&sei))
  1052. {
  1053. return HRESULT_FROM_WIN32(GetLastError());
  1054. }
  1055. else
  1056. {
  1057. return S_OK;
  1058. }
  1059. }
  1060. // Wininet helper method to retry autodetection
  1061. // check to make sure that the hosting page is on
  1062. // the local computer.
  1063. // stolen from the zones code by joshco
  1064. //
  1065. STDMETHODIMP CSearchAssistantOC::LocalZoneCheck( )
  1066. {
  1067. HRESULT hr = E_ACCESSDENIED;
  1068. // Return S_FALSE if we don't have a host site since we have no way of doing a
  1069. // security check. This is as far as VB 5.0 apps get.
  1070. if (!m_spClientSite)
  1071. return S_FALSE;
  1072. // 1) Get an IHTMLDocument2 pointer
  1073. // 2) Get URL from doc
  1074. // 3) Create security manager
  1075. // 4) Check if doc URL zone is local, if so everything's S_OK
  1076. // 5) Otherwise, get and compare doc URL SID to requested URL SID
  1077. IHTMLDocument2 *pHtmlDoc;
  1078. if (SUCCEEDED(GetHTMLDoc2(m_spClientSite, &pHtmlDoc)))
  1079. {
  1080. ASSERT(pHtmlDoc);
  1081. BSTR bstrDocUrl;
  1082. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl)))
  1083. {
  1084. ASSERT(bstrDocUrl);
  1085. IInternetSecurityManager *pSecMgr;
  1086. if (SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager,
  1087. NULL,
  1088. CLSCTX_INPROC_SERVER,
  1089. IID_IInternetSecurityManager,
  1090. (void **)&pSecMgr)))
  1091. {
  1092. ASSERT(pSecMgr);
  1093. DWORD dwZoneID = URLZONE_UNTRUSTED;
  1094. if (SUCCEEDED(pSecMgr->MapUrlToZone(bstrDocUrl, &dwZoneID, 0)))
  1095. {
  1096. if (dwZoneID == URLZONE_LOCAL_MACHINE)
  1097. hr = S_OK;
  1098. }
  1099. pSecMgr->Release();
  1100. }
  1101. SysFreeString(bstrDocUrl);
  1102. }
  1103. pHtmlDoc->Release();
  1104. }
  1105. else
  1106. {
  1107. // If we don't have an IHTMLDocument2 we aren't running in a browser that supports
  1108. // our OM. We shouldn't block in this case since we could potentially
  1109. // get here from other hosts (VB, WHS, etc.).
  1110. hr = S_FALSE;
  1111. }
  1112. return hr;
  1113. }
  1114. // set flags so that the next navigate will cause
  1115. // a proxy autodetection cycle
  1116. // used in dnserr.htm along with location.reload.
  1117. // added by joshco
  1118. //
  1119. STDMETHODIMP CSearchAssistantOC::NETDetectNextNavigate()
  1120. {
  1121. HRESULT hr = S_FALSE;
  1122. CHAR szConnectionName[100];
  1123. DWORD dwBufLen;
  1124. DWORD dwFlags;
  1125. BOOL fResult;
  1126. if ( LocalZoneCheck() != S_OK ) {
  1127. // some security problem.. time to bail.
  1128. hr=E_ACCESSDENIED;
  1129. goto error;
  1130. }
  1131. dwBufLen = sizeof(szConnectionName);
  1132. // find the connection name via internetconnected state
  1133. fResult = InternetGetConnectedStateExA(&dwFlags, szConnectionName,dwBufLen, 0 );
  1134. INTERNET_PER_CONN_OPTION_LISTA list;
  1135. INTERNET_PER_CONN_OPTIONA option;
  1136. list.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LISTA);
  1137. if(!fResult || (dwFlags & INTERNET_CONNECTION_LAN))
  1138. {
  1139. list.pszConnection = NULL;
  1140. }
  1141. else
  1142. {
  1143. list.pszConnection = szConnectionName;
  1144. }
  1145. list.dwOptionCount = 1;
  1146. list.pOptions = &option;
  1147. option.dwOption = INTERNET_PER_CONN_FLAGS;
  1148. dwBufLen= sizeof(list);
  1149. // now call internetsetoption to do it..
  1150. // first set this connectoid to enable autodetect
  1151. if ( ! InternetQueryOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION ,
  1152. &list,&dwBufLen) )
  1153. {
  1154. goto error;
  1155. }
  1156. option.Value.dwValue |= PROXY_TYPE_AUTO_DETECT ;
  1157. if ( ! InternetSetOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION ,
  1158. &list,sizeof(list)))
  1159. {
  1160. goto error;
  1161. }
  1162. if ( ! InternetInitializeAutoProxyDll(0) ) {
  1163. goto error;
  1164. }
  1165. // Now set the autodetect flags for this connectoid to
  1166. // do a passive detect and shut itself off if it doesnt work
  1167. option.dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS;
  1168. if ( ! InternetQueryOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION ,
  1169. &list,&dwBufLen) )
  1170. {
  1171. goto error;
  1172. }
  1173. option.Value.dwValue &= ~(AUTO_PROXY_FLAG_DETECTION_RUN) ;
  1174. if ( ! InternetSetOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION ,
  1175. &list,sizeof(list)))
  1176. {
  1177. goto error;
  1178. }
  1179. if ( ! InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED,NULL, 0) ) {
  1180. goto error;
  1181. }
  1182. hr=S_OK;
  1183. error: ;
  1184. return hr;
  1185. }
  1186. STDMETHODIMP CSearchAssistantOC::PutFindText(BSTR FindText)
  1187. {
  1188. HRESULT hr;
  1189. if (IsTrustedSite())
  1190. {
  1191. IServiceProvider *pServiceProvider;
  1192. hr = IUnknown_QueryService(m_pSearchBandTBHelper,
  1193. SID_SProxyBrowser,
  1194. IID_IServiceProvider,
  1195. (void **)&pServiceProvider);
  1196. if (SUCCEEDED(hr))
  1197. {
  1198. IWebBrowser2 *pWebBrowser2;
  1199. hr = pServiceProvider->QueryService(SID_SWebBrowserApp,
  1200. IID_IWebBrowser2,
  1201. (void **)&pWebBrowser2);
  1202. if (SUCCEEDED(hr))
  1203. {
  1204. ::PutFindText(pWebBrowser2, FindText);
  1205. pWebBrowser2->Release();
  1206. }
  1207. pServiceProvider->Release();
  1208. }
  1209. hr = S_OK;
  1210. }
  1211. else
  1212. {
  1213. hr = E_ACCESSDENIED;
  1214. }
  1215. return hr;
  1216. }
  1217. STDMETHODIMP CSearchAssistantOC::get_Version(int *pVersion)
  1218. {
  1219. if (NULL != pVersion)
  1220. {
  1221. *pVersion = SAOC_VERSION;
  1222. }
  1223. return S_OK;
  1224. }
  1225. // x_hex_digit and URLEncode were stolen from trident
  1226. inline int x_hex_digit(int c)
  1227. {
  1228. if (c >= 0 && c <= 9)
  1229. {
  1230. return c + '0';
  1231. }
  1232. if (c >= 10 && c <= 15)
  1233. {
  1234. return c - 10 + 'A';
  1235. }
  1236. return '0';
  1237. }
  1238. /*
  1239. The following array was copied directly from NCSA Mosaic 2.2
  1240. */
  1241. static const unsigned char isAcceptable[96] =
  1242. /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
  1243. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, /* 2x !"#$%&'()*+,-./ */
  1244. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x 0123456789:;<=>? */
  1245. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x @ABCDEFGHIJKLMNO */
  1246. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x PQRSTUVWXYZ[\]^_ */
  1247. 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x `abcdefghijklmno */
  1248. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}; /* 7x pqrstuvwxyz{\}~
  1249. DEL */
  1250. // Performs URL-encoding of null-terminated strings. Pass NULL in pbOut
  1251. // to find buffer length required. Note that '\0' is not written out.
  1252. int URLEncode(char * pbOut, const char * pchIn)
  1253. {
  1254. int lenOut = 0;
  1255. char * pchOut = pbOut;
  1256. ASSERT(pchIn);
  1257. for (; *pchIn; pchIn++, lenOut++)
  1258. {
  1259. if (*pchIn == ' ')
  1260. {
  1261. if (pchOut)
  1262. *pchOut++ = '+';
  1263. }
  1264. else if (*pchIn >= 32 && *pchIn <= 127 && isAcceptable[*pchIn - 32])
  1265. {
  1266. if (pchOut)
  1267. *pchOut++ = *pchIn;
  1268. }
  1269. else
  1270. {
  1271. if (pchOut)
  1272. *pchOut++ = '%';
  1273. lenOut++;
  1274. if (pchOut)
  1275. *pchOut++ = (char)x_hex_digit((*pchIn >> 4) & 0xf);
  1276. lenOut++;
  1277. if (pchOut)
  1278. *pchOut++ = (char)x_hex_digit(*pchIn & 0xf);
  1279. }
  1280. }
  1281. return lenOut;
  1282. }
  1283. STDMETHODIMP CSearchAssistantOC::EncodeString(BSTR bstrValue, BSTR bstrCharSet, VARIANT_BOOL bUseUTF8, BSTR *pbstrResult)
  1284. {
  1285. if ((NULL != bstrValue) && (NULL != pbstrResult))
  1286. {
  1287. HRESULT hr;
  1288. IMultiLanguage2 *pMultiLanguage2;
  1289. *pbstrResult = NULL;
  1290. hr = CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
  1291. IID_IMultiLanguage2, (void**)&pMultiLanguage2);
  1292. if (SUCCEEDED(hr))
  1293. {
  1294. UINT uiCodePage = CP_BOGUS;
  1295. UINT cchVal = SysStringLen(bstrValue);
  1296. DWORD dwMode = 0;
  1297. if (!bUseUTF8)
  1298. {
  1299. // We're not using UTF so try and get the code page from the
  1300. // charset.
  1301. MIMECSETINFO info;
  1302. hr = pMultiLanguage2->GetCharsetInfo(bstrCharSet, &info);
  1303. if (SUCCEEDED(hr))
  1304. {
  1305. hr = pMultiLanguage2->ConvertStringFromUnicodeEx(&dwMode,
  1306. info.uiCodePage,
  1307. bstrValue,
  1308. &cchVal,
  1309. NULL,
  1310. NULL,
  1311. MLCONVCHARF_NOBESTFITCHARS,
  1312. NULL);
  1313. if (S_OK == hr)
  1314. {
  1315. uiCodePage = info.uiCodePage;
  1316. }
  1317. }
  1318. }
  1319. else
  1320. {
  1321. uiCodePage = CP_UTF_8;
  1322. }
  1323. if (uiCodePage == CP_BOGUS)
  1324. {
  1325. // we have characters which don't work in the charset or the charset
  1326. // is unknown to MLang, maybe MLang can figure out a code page to use.
  1327. IMLangCodePages *pMLangCodePages;
  1328. // When all else fails...
  1329. uiCodePage = CP_ACP;
  1330. hr = pMultiLanguage2->QueryInterface(IID_IMLangCodePages,
  1331. (void **)&pMLangCodePages);
  1332. if (SUCCEEDED(hr))
  1333. {
  1334. DWORD dwCodePages = 0;
  1335. long cchProcessed = 0;
  1336. UINT uiTmpCP = 0;
  1337. if (SUCCEEDED(pMLangCodePages->GetStrCodePages(bstrValue, cchVal,
  1338. 0, &dwCodePages,
  1339. &cchProcessed))
  1340. &&
  1341. SUCCEEDED(pMLangCodePages->CodePagesToCodePage(dwCodePages,
  1342. 0,
  1343. &uiTmpCP)))
  1344. {
  1345. uiCodePage = uiTmpCP;
  1346. }
  1347. pMLangCodePages->Release();
  1348. }
  1349. }
  1350. dwMode = 0;
  1351. UINT cbVal = 0;
  1352. // Ask MLang how big of a buffer we need
  1353. hr = pMultiLanguage2->ConvertStringFromUnicode(&dwMode,
  1354. uiCodePage,
  1355. bstrValue,
  1356. &cchVal,
  1357. NULL,
  1358. &cbVal);
  1359. if (SUCCEEDED(hr))
  1360. {
  1361. CHAR *pszValue = new CHAR[cbVal + 1];
  1362. if (NULL != pszValue)
  1363. {
  1364. // Really convert the string
  1365. hr = pMultiLanguage2->ConvertStringFromUnicode(&dwMode,
  1366. uiCodePage,
  1367. bstrValue,
  1368. &cchVal,
  1369. pszValue,
  1370. &cbVal);
  1371. if (SUCCEEDED(hr))
  1372. {
  1373. pszValue[cbVal] = 0;
  1374. int cbEncVal = URLEncode(NULL, pszValue);
  1375. CHAR *pszEncVal = new CHAR[cbEncVal];
  1376. if (NULL != pszEncVal)
  1377. {
  1378. URLEncode(pszEncVal, pszValue);
  1379. int cchResult = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  1380. pszEncVal, cbEncVal,
  1381. NULL, 0);
  1382. *pbstrResult = SysAllocStringLen(NULL, cchResult);
  1383. if (NULL != *pbstrResult)
  1384. {
  1385. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  1386. pszEncVal, cbEncVal,
  1387. *pbstrResult, cchResult);
  1388. }
  1389. delete [] pszEncVal;
  1390. }
  1391. }
  1392. delete [] pszValue;
  1393. }
  1394. }
  1395. pMultiLanguage2->Release();
  1396. }
  1397. }
  1398. return S_OK;
  1399. }
  1400. STDMETHODIMP CSearchAssistantOC::get_ShowFindPrinter(VARIANT_BOOL *pbShowFindPrinter)
  1401. {
  1402. HRESULT hr;
  1403. if (IsTrustedSite())
  1404. {
  1405. if (NULL != pbShowFindPrinter)
  1406. {
  1407. IShellDispatch2* psd;
  1408. *pbShowFindPrinter = VARIANT_FALSE;
  1409. if (SUCCEEDED(CoCreateInstance(CLSID_Shell, 0, CLSCTX_INPROC_SERVER,
  1410. IID_IShellDispatch2, (void**)&psd)))
  1411. {
  1412. BSTR bstrName = SysAllocString( L"DirectoryServiceAvailable");
  1413. if (bstrName)
  1414. {
  1415. VARIANT varRet = {0};
  1416. if (SUCCEEDED(psd->GetSystemInformation(bstrName, &varRet)))
  1417. {
  1418. ASSERT(VT_BOOL == varRet.vt);
  1419. *pbShowFindPrinter = varRet.boolVal;
  1420. }
  1421. SysFreeString(bstrName);
  1422. }
  1423. psd->Release();
  1424. }
  1425. hr = S_OK;
  1426. }
  1427. else
  1428. {
  1429. hr = E_INVALIDARG;
  1430. }
  1431. }
  1432. else
  1433. {
  1434. hr = E_ACCESSDENIED;
  1435. }
  1436. return hr;
  1437. }
  1438. STDMETHODIMP CSearchAssistantOC::get_SearchCompanionAvailable(VARIANT_BOOL *pbAvailable)
  1439. {
  1440. HRESULT hr = E_ACCESSDENIED;
  1441. if (IsTrustedSite())
  1442. {
  1443. if (pbAvailable != NULL)
  1444. {
  1445. BOOL fSCAvailable = FALSE;
  1446. // need to determine if search companion is available on system and supports user locale
  1447. ISearchCompanionInfo* psci;
  1448. hr = CoCreateInstance(CLSID_SearchCompanionInfo, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ISearchCompanionInfo, &psci));
  1449. if (SUCCEEDED(hr))
  1450. {
  1451. hr = psci->IsSearchCompanionInetAvailable(&fSCAvailable);
  1452. psci->Release();
  1453. }
  1454. *pbAvailable = fSCAvailable ? VARIANT_TRUE : VARIANT_FALSE;
  1455. hr = S_OK;
  1456. }
  1457. else
  1458. {
  1459. hr = E_INVALIDARG;
  1460. }
  1461. }
  1462. return hr;
  1463. }
  1464. STDMETHODIMP CSearchAssistantOC::put_UseSearchCompanion(VARIANT_BOOL bUseSC)
  1465. {
  1466. HRESULT hr = E_ACCESSDENIED;
  1467. if (IsTrustedSite())
  1468. {
  1469. LPCTSTR pszUseSC = bUseSC ? TEXT("yes") : TEXT("no");
  1470. SHSetValue(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_USE_SEARCH_COMP, REG_SZ, pszUseSC, CbFromCch(lstrlen(pszUseSC) + 1));
  1471. if (bUseSC)
  1472. {
  1473. // disable "Use Custom Search URL" as SC won't launch if custom search URL is defined
  1474. DWORD dwUseCustom = FALSE;
  1475. SHSetValue(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_USECUSTOM, REG_DWORD, &dwUseCustom, sizeof(dwUseCustom));
  1476. }
  1477. hr = S_OK;
  1478. }
  1479. return hr;
  1480. }
  1481. STDMETHODIMP CSearchAssistantOC::get_UseSearchCompanion(VARIANT_BOOL *pbUseSC)
  1482. {
  1483. HRESULT hr = E_ACCESSDENIED;
  1484. if (IsTrustedSite())
  1485. {
  1486. if (pbUseSC != NULL)
  1487. {
  1488. BOOL fUseSC = SHRegGetBoolUSValue(REG_SZ_IE_MAIN, REG_SZ_USE_SEARCH_COMP, FALSE, FALSE);
  1489. *pbUseSC = fUseSC ? VARIANT_TRUE : VARIANT_FALSE;
  1490. hr = S_OK;
  1491. }
  1492. else
  1493. {
  1494. hr = E_INVALIDARG;
  1495. }
  1496. }
  1497. return hr;
  1498. }
  1499. #ifdef ENABLE_THIS_FOR_IE5X
  1500. STDMETHODIMP CSearchAssistantOC::RefreshLocation(IDispatch *pLocation)
  1501. {
  1502. HRESULT hr;
  1503. if (IsTrustedSite())
  1504. {
  1505. if (NULL != pLocation)
  1506. {
  1507. IHTMLLocation *pHTMLLocation;
  1508. IUnknown_QueryService(pLocation, IID_IHTMLLocation, IID_IHTMLLocation, (void **)&pHTMLLocation);
  1509. if (pHTMLLocation)
  1510. {
  1511. pHTMLLocation->reload(VARIANT_TRUE);
  1512. pHTMLLocation->Release();
  1513. }
  1514. }
  1515. hr = S_OK;
  1516. }
  1517. else
  1518. {
  1519. hr = E_ACCESSDENIED;
  1520. }
  1521. return hr;
  1522. }
  1523. #endif
  1524. //-------------------------------------------------------------------------//
  1525. #define REG_SZ_SHELL_SEARCH TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\") \
  1526. TEXT("Explorer\\FindExtensions\\Static\\ShellSearch")
  1527. //-------------------------------------------------------------------------//
  1528. HRESULT GetSearchURLs(
  1529. IN REFGUID guidSearch,
  1530. OUT LPTSTR pszUrl,
  1531. IN DWORD cch,
  1532. OUT OPTIONAL LPTSTR pszUrlNavNew,
  1533. OUT DWORD cchNavNew,
  1534. OUT BOOL *pfRunInProcess )
  1535. {
  1536. HRESULT hr = E_FAIL ;
  1537. DWORD cb ;
  1538. DWORD dwType ;
  1539. DWORD dwErr ;
  1540. *pfRunInProcess = FALSE ;
  1541. if( pszUrlNavNew && cchNavNew )
  1542. *pszUrlNavNew = 0 ;
  1543. if( IsEqualGUID( guidSearch, SRCID_SWebSearch ) )
  1544. {
  1545. if( GetDefaultInternetSearchUrlW( pszUrl, cch, TRUE ) )
  1546. hr = S_OK ;
  1547. }
  1548. else
  1549. {
  1550. // The shell search URL-eating stuff was adapted from
  1551. // CShellSearchExt::_GetSearchUrls() in browseui\browband.cpp,
  1552. // and should be kept in sync.
  1553. TCHAR szSubKey[32];
  1554. HKEY hkey, hkeySub;
  1555. if( (dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_SZ_SHELL_SEARCH,
  1556. 0, KEY_READ, &hkey )) != ERROR_SUCCESS )
  1557. return HRESULT_FROM_WIN32( dwErr ) ;
  1558. hr = E_FAIL ;
  1559. for( int i = 0;
  1560. wnsprintf( szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), i ),
  1561. RegOpenKey(hkey, szSubKey, &hkeySub) == ERROR_SUCCESS ;
  1562. i++ )
  1563. {
  1564. TCHAR szSearchGuid[MAX_PATH];
  1565. cb = SIZEOF(szSearchGuid);
  1566. if( SHGetValue( hkeySub, TEXT("SearchGUID"), NULL, &dwType, (BYTE*)szSearchGuid, &cb ) == ERROR_SUCCESS )
  1567. {
  1568. GUID guid;
  1569. SHCLSIDFromString(szSearchGuid, &guid);
  1570. if( IsEqualGUID( guid, guidSearch ) )
  1571. {
  1572. cb = cch * sizeof(TCHAR);
  1573. if( SHGetValue( hkeySub, TEXT("SearchGUID\\Url"), NULL,
  1574. &dwType, (BYTE*)pszUrl, &cb ) == ERROR_SUCCESS )
  1575. {
  1576. if( pszUrlNavNew && cchNavNew )
  1577. {
  1578. // See if there is a secondary URL that we should navigate to
  1579. cb = cchNavNew * sizeof(TCHAR);
  1580. SHGetValue(hkeySub, TEXT("SearchGUID\\UrlNavNew"), NULL, &dwType, (BYTE*)pszUrlNavNew, &cb);
  1581. }
  1582. // try to grab the RunInProcess flag
  1583. *pfRunInProcess = (BOOL)SHRegGetIntW( hkeySub, L"RunInProcess", 0 );
  1584. RegCloseKey(hkeySub);
  1585. hr = S_OK ;
  1586. break;
  1587. }
  1588. }
  1589. }
  1590. RegCloseKey(hkeySub);
  1591. }
  1592. RegCloseKey( hkey ) ;
  1593. }
  1594. return hr ;
  1595. }
  1596. STDMETHODIMP _IsShellSearchBand( REFGUID guidSearch )
  1597. {
  1598. if (IsEqualGUID( guidSearch, SRCID_SFileSearch ) ||
  1599. IsEqualGUID( guidSearch, SRCID_SFindComputer ) ||
  1600. IsEqualGUID( guidSearch, SRCID_SFindPrinter ) )
  1601. return S_OK;
  1602. return S_FALSE;
  1603. }
  1604. //-------------------------------------------------------------------------//
  1605. // Establishes the correct shell search dialog, etc.
  1606. STDMETHODIMP _ShowShellSearchBand( IWebBrowser2* pwb2, REFGUID guidSearch )
  1607. {
  1608. ASSERT( pwb2 );
  1609. ASSERT( S_OK == _IsShellSearchBand( guidSearch ) );
  1610. HRESULT hr;
  1611. VARIANT varBand;
  1612. if (SUCCEEDED( (hr = InitBSTRVariantFromGUID(&varBand, CLSID_FileSearchBand)) ))
  1613. {
  1614. // Retrieve the FileSearchBand's unknown from the browser frame as a VT_UNKNOWN property;
  1615. // (FileSearchBand initialized and this when he was created and hosted.)
  1616. VARIANT varFsb;
  1617. if (SUCCEEDED( (hr = pwb2->GetProperty( varBand.bstrVal, &varFsb )) ))
  1618. {
  1619. if (VT_UNKNOWN == varFsb.vt && varFsb.punkVal != NULL )
  1620. {
  1621. // Retrieve the IFileSearchBand interface
  1622. IFileSearchBand* pfsb;
  1623. if (SUCCEEDED( (hr = varFsb.punkVal->QueryInterface( IID_IFileSearchBand, (LPVOID*)&pfsb )) ))
  1624. {
  1625. // Assign the correct search type to the band
  1626. VARIANT varSearchID;
  1627. if (SUCCEEDED( (hr = InitBSTRVariantFromGUID(&varSearchID, guidSearch)) ))
  1628. {
  1629. VARIANT varNil = {0};
  1630. VARIANT_BOOL bNavToResults = VARIANT_FALSE ;
  1631. // Note [scotthan]: we only navigate to results when we create a
  1632. // new frame for the search, which we never do from srchasst.
  1633. pfsb->SetSearchParameters( &varSearchID.bstrVal, bNavToResults, &varNil, &varNil );
  1634. VariantClear( &varSearchID );
  1635. }
  1636. pfsb->Release();
  1637. }
  1638. }
  1639. VariantClear( &varFsb );
  1640. }
  1641. VariantClear( &varBand );
  1642. }
  1643. return hr;
  1644. }
  1645. //-------------------------------------------------------------------------//
  1646. // The goop to show a search band in the current browser frame.
  1647. // 6/1
  1648. HRESULT CSearchAssistantOC::ShowSearchBand( REFGUID guidSearch )
  1649. {
  1650. HRESULT hr = E_FAIL;
  1651. TCHAR szUrl[MAX_URL_STRING];
  1652. TCHAR szUrlNavNew[MAX_URL_STRING];
  1653. CLSID clsidBand;
  1654. BOOL fShellSearchBand = FALSE;
  1655. BOOL fRunInProcess = FALSE;
  1656. IUnknown* punkSite = m_punkSite ? m_punkSite : (IUnknown*)m_spClientSite;
  1657. if( !punkSite )
  1658. return E_UNEXPECTED ;
  1659. // Determine band class and whether the band supports navigation
  1660. if( (fShellSearchBand = (S_OK == _IsShellSearchBand( guidSearch ))) )
  1661. {
  1662. if (SHRestricted(REST_NOFIND) && IsEqualGUID(guidSearch, SRCID_SFileSearch))
  1663. return E_ACCESSDENIED;
  1664. clsidBand = CLSID_FileSearchBand;
  1665. }
  1666. else
  1667. {
  1668. clsidBand = CLSID_SearchBand;
  1669. // we need to navigate to a search URL, grope the registry for that special URL
  1670. if( FAILED( (hr= GetSearchURLs( guidSearch, szUrl, ARRAYSIZE(szUrl),
  1671. szUrlNavNew, ARRAYSIZE(szUrlNavNew),
  1672. &fRunInProcess )) ) )
  1673. return hr;
  1674. }
  1675. // FEATURE [scotthan]: this function will fail unless invoked from within a browser.
  1676. // This sits fine for now since SearchAsst is designed as a browser band.
  1677. IWebBrowser2* pwb2;
  1678. hr = IUnknown_QueryServiceForWebBrowserApp(punkSite, IID_PPV_ARG(IWebBrowser2, &pwb2));
  1679. if (SUCCEEDED(hr))
  1680. {
  1681. SA_BSTRGUID bstrClsid;
  1682. InitFakeBSTR(&bstrClsid, clsidBand);
  1683. VARIANT var;
  1684. var.bstrVal = bstrClsid.wsz;
  1685. var.vt = VT_BSTR;
  1686. VARIANT varNil = {0};
  1687. // show a search bar
  1688. hr = pwb2->ShowBrowserBar(&var, &varNil, &varNil);
  1689. if( SUCCEEDED( hr ) )
  1690. {
  1691. VARIANT varFlags;
  1692. if( fShellSearchBand )
  1693. {
  1694. hr= _ShowShellSearchBand( pwb2, guidSearch );
  1695. }
  1696. else
  1697. {
  1698. varFlags.vt = VT_I4;
  1699. varFlags.lVal = navBrowserBar;
  1700. var.bstrVal = SysAllocString( T2W( szUrl ) ) ;
  1701. var.vt = VT_BSTR ;
  1702. // navigate the search bar to the correct url
  1703. hr = pwb2->Navigate2(&var, &varFlags, &varNil, &varNil, &varNil);
  1704. SysFreeString(var.bstrVal);
  1705. if( SUCCEEDED( hr ) )
  1706. {
  1707. hr = pwb2->put_Visible( TRUE ) ;
  1708. }
  1709. }
  1710. }
  1711. pwb2->Release();
  1712. }
  1713. return hr;
  1714. }
  1715. STDMETHODIMP CSearchAssistantOC::SetSite( IUnknown* punkSite )
  1716. {
  1717. ATOMICRELEASE(m_punkSite);
  1718. if ((m_punkSite = punkSite) != NULL)
  1719. m_punkSite->AddRef() ;
  1720. return S_OK ;
  1721. }
  1722. STDMETHODIMP CSearchAssistantOC::GetSite( REFIID riid, void** ppvSite )
  1723. {
  1724. if( !m_punkSite )
  1725. return E_FAIL ;
  1726. return m_punkSite->QueryInterface( riid, ppvSite ) ;
  1727. }