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.

2064 lines
58 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. return InterlockedIncrement(&_cRef);
  180. }
  181. STDMETHODIMP_(ULONG) CSearch::Release()
  182. {
  183. ASSERT( 0 != _cRef );
  184. ULONG cRef = InterlockedDecrement(&_cRef);
  185. if ( 0 == cRef )
  186. {
  187. delete this;
  188. }
  189. return cRef;
  190. }
  191. HRESULT CSearch::get_Title(BSTR *pbstrTitle)
  192. {
  193. HRESULT hres = NOERROR;
  194. *pbstrTitle = SysAllocString(_bstrTitle);
  195. if (!*pbstrTitle)
  196. hres = E_OUTOFMEMORY;
  197. return hres;
  198. }
  199. HRESULT CSearch::get_Id(BSTR *pbstrId)
  200. {
  201. HRESULT hres = NOERROR;
  202. *pbstrId = SysAllocString(_szId);
  203. if (!*pbstrId)
  204. hres = E_OUTOFMEMORY;
  205. return hres;
  206. }
  207. HRESULT CSearch::get_Url(BSTR *pbstrUrl)
  208. {
  209. HRESULT hres = NOERROR;
  210. *pbstrUrl = SysAllocString(_bstrUrl);
  211. if (!*pbstrUrl)
  212. hres = E_OUTOFMEMORY;
  213. return hres;
  214. }
  215. HRESULT CSearchCollection_Create(IFolderSearches *pfs, ISearches **ppSearches)
  216. {
  217. HRESULT hres = E_INVALIDARG;
  218. ASSERT(ppSearches);
  219. *ppSearches = NULL;
  220. if (pfs)
  221. {
  222. CSearchCollection *psc = new CSearchCollection(pfs);
  223. if (psc)
  224. {
  225. hres = psc->QueryInterface(IID_ISearches, (void **)ppSearches);
  226. psc->Release();
  227. }
  228. else
  229. hres = E_OUTOFMEMORY;
  230. }
  231. return hres;
  232. }
  233. CSearchCollection::CSearchCollection(IFolderSearches *pfs) :
  234. _cRef(1), CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_ISearches)
  235. {
  236. GUID guid;
  237. if (SUCCEEDED(pfs->DefaultSearch(&guid)))
  238. SHStringFromGUID(guid, _szDefault, ARRAYSIZE(_szDefault));
  239. _hdsaItems = DSA_Create(SIZEOF(URLSEARCH), 4);
  240. if (_hdsaItems)
  241. {
  242. IEnumUrlSearch *penum;
  243. if (SUCCEEDED(pfs->EnumSearches(&penum)))
  244. {
  245. URLSEARCH us;
  246. ULONG cElt;
  247. penum->Reset();
  248. while (S_OK == penum->Next(1, &us, &cElt) && 1 == cElt)
  249. DSA_AppendItem(_hdsaItems, &us);
  250. penum->Release();
  251. }
  252. }
  253. }
  254. CSearchCollection::~CSearchCollection()
  255. {
  256. DSA_Destroy(_hdsaItems);
  257. _hdsaItems = NULL;
  258. }
  259. STDMETHODIMP CSearchCollection::QueryInterface(REFIID riid, void** ppv)
  260. {
  261. static const QITAB qit[] = {
  262. QITABENT(CSearchCollection, ISearches),
  263. QITABENTMULTI(CSearchCollection, IDispatch, ISearches),
  264. { 0 },
  265. };
  266. return QISearch(this, qit, riid, ppv);
  267. }
  268. STDMETHODIMP_(ULONG) CSearchCollection::AddRef()
  269. {
  270. return InterlockedIncrement(&_cRef);
  271. }
  272. STDMETHODIMP_(ULONG) CSearchCollection::Release()
  273. {
  274. ASSERT( 0 != _cRef );
  275. ULONG cRef = InterlockedDecrement(&_cRef);
  276. if ( 0 == cRef )
  277. {
  278. delete this;
  279. }
  280. return cRef;
  281. }
  282. STDMETHODIMP CSearchCollection::get_Count(long *plCount)
  283. {
  284. *plCount = 0;
  285. if (_hdsaItems)
  286. {
  287. *plCount = DSA_GetItemCount(_hdsaItems);
  288. }
  289. return S_OK;
  290. }
  291. STDMETHODIMP CSearchCollection::get_Default(BSTR *pbstrDefault)
  292. {
  293. HRESULT hres = E_OUTOFMEMORY;
  294. *pbstrDefault = SysAllocString(_szDefault);
  295. if (*pbstrDefault)
  296. hres = S_OK;
  297. return hres;
  298. }
  299. STDMETHODIMP CSearchCollection::Item(VARIANT index, ISearch **ppid)
  300. {
  301. HRESULT hres = E_NOTIMPL;
  302. *ppid = NULL;
  303. switch (index.vt)
  304. {
  305. case VT_I2:
  306. index.lVal = (long)index.iVal;
  307. // And fall through...
  308. case VT_I4:
  309. if ((index.lVal >= 0) && (index.lVal < DSA_GetItemCount(_hdsaItems)))
  310. {
  311. LPURLSEARCH pus;
  312. pus = (LPURLSEARCH)DSA_GetItemPtr(_hdsaItems, index.lVal);
  313. ASSERT(pus);
  314. hres = CSearch_Create(&pus->guid, pus->wszName, pus->wszUrl, ppid);
  315. }
  316. break;
  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_PPV_ARG(IServiceProvider, &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. HRESULT GetPerLocalePath(WCHAR *pwszKeyName, int cchKeyName)
  678. {
  679. HRESULT hr;
  680. ASSERT(cchKeyName >= (ARRAYSIZE(c_wszSearchProps) + 1));
  681. hr = StringCchCopy(pwszKeyName, cchKeyName, c_wszSearchProps);
  682. if (SUCCEEDED(hr))
  683. {
  684. *(pwszKeyName + (ARRAYSIZE(c_wszSearchProps) - 1)) = L'\\';
  685. GetWebLocaleAsRFC1766(pwszKeyName + ARRAYSIZE(c_wszSearchProps),
  686. cchKeyName - (ARRAYSIZE(c_wszSearchProps)));
  687. }
  688. return hr;
  689. }
  690. STDMETHODIMP CSearchAssistantOC::PutProperty(VARIANT_BOOL bPerLocale, BSTR bstrName, BSTR bstrValue)
  691. {
  692. HRESULT hr = E_ACCESSDENIED;
  693. if (IsTrustedSite())
  694. {
  695. HKEY hkey;
  696. LPCWSTR pwszKeyName;
  697. WCHAR wszKeyName[MAX_PATH];
  698. DWORD dwDisposition;
  699. if (bPerLocale)
  700. {
  701. hr = GetPerLocalePath(wszKeyName, ARRAYSIZE(wszKeyName));
  702. pwszKeyName = wszKeyName;
  703. }
  704. else
  705. {
  706. hr = S_OK;
  707. pwszKeyName = c_wszSearchProps;
  708. }
  709. if (SUCCEEDED(hr))
  710. {
  711. if (RegCreateKeyExW(HKEY_CURRENT_USER, pwszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE,
  712. KEY_SET_VALUE, NULL, &hkey, &dwDisposition) == ERROR_SUCCESS)
  713. {
  714. if ((NULL != bstrValue) && (bstrValue[0] != 0))
  715. {
  716. RegSetValueExW(hkey, bstrName, 0, REG_BINARY, (LPBYTE)bstrValue,
  717. SysStringByteLen(bstrValue));
  718. }
  719. else
  720. {
  721. // Empty or NULL string means remove the property
  722. RegDeleteValue(hkey, bstrName);
  723. }
  724. RegCloseKey(hkey);
  725. }
  726. }
  727. }
  728. return hr;
  729. }
  730. STDMETHODIMP CSearchAssistantOC::GetProperty(VARIANT_BOOL bPerLocale, BSTR bstrName, BSTR *pbstrValue)
  731. {
  732. HRESULT hr = E_INVALIDARG;
  733. if (NULL != pbstrValue)
  734. {
  735. hr = E_ACCESSDENIED;
  736. *pbstrValue = NULL;
  737. if (IsTrustedSite())
  738. {
  739. HKEY hkey;
  740. LPCWSTR pwszKeyName;
  741. WCHAR wszKeyName[MAX_PATH];
  742. if (bPerLocale)
  743. {
  744. hr = GetPerLocalePath(wszKeyName, ARRAYSIZE(wszKeyName));
  745. pwszKeyName = wszKeyName;
  746. }
  747. else
  748. {
  749. hr = S_OK;
  750. pwszKeyName = c_wszSearchProps;
  751. }
  752. if (SUCCEEDED(hr))
  753. {
  754. if (RegOpenKeyExW(HKEY_CURRENT_USER, pwszKeyName, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)
  755. {
  756. DWORD dwType;
  757. DWORD cbSize;
  758. if ((RegQueryValueExW(hkey, bstrName, NULL, &dwType, NULL, &cbSize) == ERROR_SUCCESS) &&
  759. (dwType == REG_BINARY))
  760. {
  761. BSTR bstrValue = SysAllocStringByteLen(NULL, cbSize);
  762. if (NULL != bstrValue)
  763. {
  764. if (RegQueryValueExW(hkey, bstrName, NULL, &dwType, (LPBYTE)bstrValue, &cbSize) == ERROR_SUCCESS)
  765. {
  766. *pbstrValue = bstrValue;
  767. }
  768. else
  769. {
  770. SysFreeString(bstrValue);
  771. }
  772. }
  773. }
  774. RegCloseKey(hkey);
  775. }
  776. }
  777. }
  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_QUERY_VALUE, &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_QUERY_VALUE, &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_PPV_ARG(IShellDispatch2, &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) Check if doc URL zone is local, if so everything's S_OK
  1075. // 4) Otherwise, get and compare doc URL SID to requested URL SID
  1076. IHTMLDocument2 *pHtmlDoc;
  1077. if (SUCCEEDED(GetHTMLDoc2(m_spClientSite, &pHtmlDoc)))
  1078. {
  1079. ASSERT(pHtmlDoc);
  1080. BSTR bstrDocUrl;
  1081. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl)))
  1082. {
  1083. ASSERT(bstrDocUrl);
  1084. DWORD dwZoneID = URLZONE_UNTRUSTED;
  1085. if (SUCCEEDED(GetZoneFromUrl(bstrDocUrl, m_spClientSite, &dwZoneID)))
  1086. {
  1087. if (dwZoneID == URLZONE_LOCAL_MACHINE)
  1088. hr = S_OK;
  1089. }
  1090. SysFreeString(bstrDocUrl);
  1091. }
  1092. pHtmlDoc->Release();
  1093. }
  1094. else
  1095. {
  1096. // If we don't have an IHTMLDocument2 we aren't running in a browser that supports
  1097. // our OM. We shouldn't block in this case since we could potentially
  1098. // get here from other hosts (VB, WHS, etc.).
  1099. hr = S_FALSE;
  1100. }
  1101. return hr;
  1102. }
  1103. // set flags so that the next navigate will cause
  1104. // a proxy autodetection cycle
  1105. // used in dnserr.htm along with location.reload.
  1106. // added by joshco
  1107. //
  1108. STDMETHODIMP CSearchAssistantOC::NETDetectNextNavigate()
  1109. {
  1110. HRESULT hr = S_FALSE;
  1111. CHAR szConnectionName[100];
  1112. DWORD dwBufLen;
  1113. DWORD dwFlags;
  1114. BOOL fResult;
  1115. if ( LocalZoneCheck() != S_OK ) {
  1116. // some security problem.. time to bail.
  1117. hr=E_ACCESSDENIED;
  1118. goto error;
  1119. }
  1120. dwBufLen = sizeof(szConnectionName);
  1121. // find the connection name via internetconnected state
  1122. fResult = InternetGetConnectedStateExA(&dwFlags, szConnectionName,dwBufLen, 0 );
  1123. INTERNET_PER_CONN_OPTION_LISTA list;
  1124. INTERNET_PER_CONN_OPTIONA option;
  1125. list.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LISTA);
  1126. if(!fResult || (dwFlags & INTERNET_CONNECTION_LAN))
  1127. {
  1128. list.pszConnection = NULL;
  1129. }
  1130. else
  1131. {
  1132. list.pszConnection = szConnectionName;
  1133. }
  1134. list.dwOptionCount = 1;
  1135. list.pOptions = &option;
  1136. option.dwOption = INTERNET_PER_CONN_FLAGS;
  1137. dwBufLen= sizeof(list);
  1138. // now call internetsetoption to do it..
  1139. // first set this connectoid to enable autodetect
  1140. if ( ! InternetQueryOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION ,
  1141. &list,&dwBufLen) )
  1142. {
  1143. goto error;
  1144. }
  1145. option.Value.dwValue |= PROXY_TYPE_AUTO_DETECT ;
  1146. if ( ! InternetSetOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION ,
  1147. &list,sizeof(list)))
  1148. {
  1149. goto error;
  1150. }
  1151. if ( ! InternetInitializeAutoProxyDll(0) ) {
  1152. goto error;
  1153. }
  1154. // Now set the autodetect flags for this connectoid to
  1155. // do a passive detect and shut itself off if it doesnt work
  1156. option.dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS;
  1157. if ( ! InternetQueryOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION ,
  1158. &list,&dwBufLen) )
  1159. {
  1160. goto error;
  1161. }
  1162. option.Value.dwValue &= ~(AUTO_PROXY_FLAG_DETECTION_RUN) ;
  1163. if ( ! InternetSetOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION ,
  1164. &list,sizeof(list)))
  1165. {
  1166. goto error;
  1167. }
  1168. if ( ! InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED,NULL, 0) ) {
  1169. goto error;
  1170. }
  1171. hr=S_OK;
  1172. error: ;
  1173. return hr;
  1174. }
  1175. STDMETHODIMP CSearchAssistantOC::PutFindText(BSTR FindText)
  1176. {
  1177. HRESULT hr;
  1178. if (IsTrustedSite())
  1179. {
  1180. IServiceProvider *pServiceProvider;
  1181. hr = IUnknown_QueryService(m_pSearchBandTBHelper,
  1182. SID_SProxyBrowser,
  1183. IID_IServiceProvider,
  1184. (void **)&pServiceProvider);
  1185. if (SUCCEEDED(hr))
  1186. {
  1187. IWebBrowser2 *pWebBrowser2;
  1188. hr = pServiceProvider->QueryService(SID_SWebBrowserApp,
  1189. IID_IWebBrowser2,
  1190. (void **)&pWebBrowser2);
  1191. if (SUCCEEDED(hr))
  1192. {
  1193. ::PutFindText(pWebBrowser2, FindText);
  1194. pWebBrowser2->Release();
  1195. }
  1196. pServiceProvider->Release();
  1197. }
  1198. hr = S_OK;
  1199. }
  1200. else
  1201. {
  1202. hr = E_ACCESSDENIED;
  1203. }
  1204. return hr;
  1205. }
  1206. STDMETHODIMP CSearchAssistantOC::get_Version(int *pVersion)
  1207. {
  1208. if (NULL != pVersion)
  1209. {
  1210. *pVersion = SAOC_VERSION;
  1211. }
  1212. return S_OK;
  1213. }
  1214. // x_hex_digit and URLEncode were stolen from trident
  1215. inline int x_hex_digit(int c)
  1216. {
  1217. if (c >= 0 && c <= 9)
  1218. {
  1219. return c + '0';
  1220. }
  1221. if (c >= 10 && c <= 15)
  1222. {
  1223. return c - 10 + 'A';
  1224. }
  1225. return '0';
  1226. }
  1227. /*
  1228. The following array was copied directly from NCSA Mosaic 2.2
  1229. */
  1230. static const unsigned char isAcceptable[96] =
  1231. /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
  1232. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, /* 2x !"#$%&'()*+,-./ */
  1233. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x 0123456789:;<=>? */
  1234. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x @ABCDEFGHIJKLMNO */
  1235. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x PQRSTUVWXYZ[\]^_ */
  1236. 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x `abcdefghijklmno */
  1237. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}; /* 7x pqrstuvwxyz{\}~
  1238. DEL */
  1239. // Performs URL-encoding of null-terminated strings. Pass NULL in pbOut
  1240. // to find buffer length required. Note that '\0' is not written out.
  1241. int URLEncode(char * pbOut, const char * pchIn)
  1242. {
  1243. int lenOut = 0;
  1244. char * pchOut = pbOut;
  1245. ASSERT(pchIn);
  1246. for (; *pchIn; pchIn++, lenOut++)
  1247. {
  1248. if (*pchIn == ' ')
  1249. {
  1250. if (pchOut)
  1251. *pchOut++ = '+';
  1252. }
  1253. else if (*pchIn >= 32 && *pchIn <= 127 && isAcceptable[*pchIn - 32])
  1254. {
  1255. if (pchOut)
  1256. *pchOut++ = *pchIn;
  1257. }
  1258. else
  1259. {
  1260. if (pchOut)
  1261. *pchOut++ = '%';
  1262. lenOut++;
  1263. if (pchOut)
  1264. *pchOut++ = (char)x_hex_digit((*pchIn >> 4) & 0xf);
  1265. lenOut++;
  1266. if (pchOut)
  1267. *pchOut++ = (char)x_hex_digit(*pchIn & 0xf);
  1268. }
  1269. }
  1270. return lenOut;
  1271. }
  1272. STDMETHODIMP CSearchAssistantOC::EncodeString(BSTR bstrValue, BSTR bstrCharSet, VARIANT_BOOL bUseUTF8, BSTR *pbstrResult)
  1273. {
  1274. if ((NULL != bstrValue) && (NULL != pbstrResult))
  1275. {
  1276. HRESULT hr;
  1277. IMultiLanguage2 *pMultiLanguage2;
  1278. *pbstrResult = NULL;
  1279. hr = CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
  1280. IID_PPV_ARG(IMultiLanguage2, &pMultiLanguage2));
  1281. if (SUCCEEDED(hr))
  1282. {
  1283. UINT uiCodePage = CP_BOGUS;
  1284. UINT cchVal = SysStringLen(bstrValue);
  1285. DWORD dwMode = 0;
  1286. if (!bUseUTF8)
  1287. {
  1288. // We're not using UTF so try and get the code page from the
  1289. // charset.
  1290. MIMECSETINFO info;
  1291. hr = pMultiLanguage2->GetCharsetInfo(bstrCharSet, &info);
  1292. if (SUCCEEDED(hr))
  1293. {
  1294. hr = pMultiLanguage2->ConvertStringFromUnicodeEx(&dwMode,
  1295. info.uiCodePage,
  1296. bstrValue,
  1297. &cchVal,
  1298. NULL,
  1299. NULL,
  1300. MLCONVCHARF_NOBESTFITCHARS,
  1301. NULL);
  1302. if (S_OK == hr)
  1303. {
  1304. uiCodePage = info.uiCodePage;
  1305. }
  1306. }
  1307. }
  1308. else
  1309. {
  1310. uiCodePage = CP_UTF_8;
  1311. }
  1312. if (uiCodePage == CP_BOGUS)
  1313. {
  1314. // we have characters which don't work in the charset or the charset
  1315. // is unknown to MLang, maybe MLang can figure out a code page to use.
  1316. IMLangCodePages *pMLangCodePages;
  1317. // When all else fails...
  1318. uiCodePage = CP_ACP;
  1319. hr = pMultiLanguage2->QueryInterface(IID_IMLangCodePages,
  1320. (void **)&pMLangCodePages);
  1321. if (SUCCEEDED(hr))
  1322. {
  1323. DWORD dwCodePages = 0;
  1324. long cchProcessed = 0;
  1325. UINT uiTmpCP = 0;
  1326. if (SUCCEEDED(pMLangCodePages->GetStrCodePages(bstrValue, cchVal,
  1327. 0, &dwCodePages,
  1328. &cchProcessed))
  1329. &&
  1330. SUCCEEDED(pMLangCodePages->CodePagesToCodePage(dwCodePages,
  1331. 0,
  1332. &uiTmpCP)))
  1333. {
  1334. uiCodePage = uiTmpCP;
  1335. }
  1336. pMLangCodePages->Release();
  1337. }
  1338. }
  1339. dwMode = 0;
  1340. UINT cbVal = 0;
  1341. // Ask MLang how big of a buffer we need
  1342. hr = pMultiLanguage2->ConvertStringFromUnicode(&dwMode,
  1343. uiCodePage,
  1344. bstrValue,
  1345. &cchVal,
  1346. NULL,
  1347. &cbVal);
  1348. if (SUCCEEDED(hr))
  1349. {
  1350. CHAR *pszValue = new CHAR[cbVal + 1];
  1351. if (NULL != pszValue)
  1352. {
  1353. // Really convert the string
  1354. hr = pMultiLanguage2->ConvertStringFromUnicode(&dwMode,
  1355. uiCodePage,
  1356. bstrValue,
  1357. &cchVal,
  1358. pszValue,
  1359. &cbVal);
  1360. if (SUCCEEDED(hr))
  1361. {
  1362. pszValue[cbVal] = 0;
  1363. int cbEncVal = URLEncode(NULL, pszValue);
  1364. CHAR *pszEncVal = new CHAR[cbEncVal];
  1365. if (NULL != pszEncVal)
  1366. {
  1367. URLEncode(pszEncVal, pszValue);
  1368. int cchResult = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  1369. pszEncVal, cbEncVal,
  1370. NULL, 0);
  1371. *pbstrResult = SysAllocStringLen(NULL, cchResult);
  1372. if (NULL != *pbstrResult)
  1373. {
  1374. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
  1375. pszEncVal, cbEncVal,
  1376. *pbstrResult, cchResult);
  1377. }
  1378. delete [] pszEncVal;
  1379. }
  1380. }
  1381. delete [] pszValue;
  1382. }
  1383. }
  1384. pMultiLanguage2->Release();
  1385. }
  1386. }
  1387. return S_OK;
  1388. }
  1389. STDMETHODIMP CSearchAssistantOC::get_ShowFindPrinter(VARIANT_BOOL *pbShowFindPrinter)
  1390. {
  1391. HRESULT hr;
  1392. if (IsTrustedSite())
  1393. {
  1394. if (NULL != pbShowFindPrinter)
  1395. {
  1396. IShellDispatch2* psd;
  1397. *pbShowFindPrinter = VARIANT_FALSE;
  1398. if (SUCCEEDED(CoCreateInstance(CLSID_Shell, 0, CLSCTX_INPROC_SERVER,
  1399. IID_PPV_ARG(IShellDispatch2, &psd))))
  1400. {
  1401. BSTR bstrName = SysAllocString( L"DirectoryServiceAvailable");
  1402. if (bstrName)
  1403. {
  1404. VARIANT varRet = {0};
  1405. if (SUCCEEDED(psd->GetSystemInformation(bstrName, &varRet)))
  1406. {
  1407. ASSERT(VT_BOOL == varRet.vt);
  1408. *pbShowFindPrinter = varRet.boolVal;
  1409. }
  1410. SysFreeString(bstrName);
  1411. }
  1412. psd->Release();
  1413. }
  1414. hr = S_OK;
  1415. }
  1416. else
  1417. {
  1418. hr = E_INVALIDARG;
  1419. }
  1420. }
  1421. else
  1422. {
  1423. hr = E_ACCESSDENIED;
  1424. }
  1425. return hr;
  1426. }
  1427. STDMETHODIMP CSearchAssistantOC::get_SearchCompanionAvailable(VARIANT_BOOL *pbAvailable)
  1428. {
  1429. HRESULT hr = E_ACCESSDENIED;
  1430. if (IsTrustedSite())
  1431. {
  1432. if (pbAvailable != NULL)
  1433. {
  1434. BOOL fSCAvailable = FALSE;
  1435. // need to determine if search companion is available on system and supports user locale
  1436. ISearchCompanionInfo* psci;
  1437. hr = CoCreateInstance(CLSID_SearchCompanionInfo, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ISearchCompanionInfo, &psci));
  1438. if (SUCCEEDED(hr))
  1439. {
  1440. hr = psci->IsSearchCompanionInetAvailable(&fSCAvailable);
  1441. psci->Release();
  1442. }
  1443. *pbAvailable = fSCAvailable ? VARIANT_TRUE : VARIANT_FALSE;
  1444. hr = S_OK;
  1445. }
  1446. else
  1447. {
  1448. hr = E_INVALIDARG;
  1449. }
  1450. }
  1451. return hr;
  1452. }
  1453. STDMETHODIMP CSearchAssistantOC::put_UseSearchCompanion(VARIANT_BOOL bUseSC)
  1454. {
  1455. HRESULT hr = E_ACCESSDENIED;
  1456. if (IsTrustedSite())
  1457. {
  1458. LPCTSTR pszUseSC = bUseSC ? TEXT("yes") : TEXT("no");
  1459. SHSetValue(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_USE_SEARCH_COMP, REG_SZ, pszUseSC, CbFromCch(lstrlen(pszUseSC) + 1));
  1460. if (bUseSC)
  1461. {
  1462. // disable "Use Custom Search URL" as SC won't launch if custom search URL is defined
  1463. DWORD dwUseCustom = FALSE;
  1464. SHSetValue(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_USECUSTOM, REG_DWORD, &dwUseCustom, sizeof(dwUseCustom));
  1465. }
  1466. hr = S_OK;
  1467. }
  1468. return hr;
  1469. }
  1470. STDMETHODIMP CSearchAssistantOC::get_UseSearchCompanion(VARIANT_BOOL *pbUseSC)
  1471. {
  1472. HRESULT hr = E_ACCESSDENIED;
  1473. if (IsTrustedSite())
  1474. {
  1475. if (pbUseSC != NULL)
  1476. {
  1477. BOOL fUseSC = SHRegGetBoolUSValue(REG_SZ_IE_MAIN, REG_SZ_USE_SEARCH_COMP, FALSE, FALSE);
  1478. *pbUseSC = fUseSC ? VARIANT_TRUE : VARIANT_FALSE;
  1479. hr = S_OK;
  1480. }
  1481. else
  1482. {
  1483. hr = E_INVALIDARG;
  1484. }
  1485. }
  1486. return hr;
  1487. }
  1488. #ifdef ENABLE_THIS_FOR_IE5X
  1489. STDMETHODIMP CSearchAssistantOC::RefreshLocation(IDispatch *pLocation)
  1490. {
  1491. HRESULT hr;
  1492. if (IsTrustedSite())
  1493. {
  1494. if (NULL != pLocation)
  1495. {
  1496. IHTMLLocation *pHTMLLocation;
  1497. IUnknown_QueryService(pLocation, IID_IHTMLLocation, IID_IHTMLLocation, (void **)&pHTMLLocation);
  1498. if (pHTMLLocation)
  1499. {
  1500. pHTMLLocation->reload(VARIANT_TRUE);
  1501. pHTMLLocation->Release();
  1502. }
  1503. }
  1504. hr = S_OK;
  1505. }
  1506. else
  1507. {
  1508. hr = E_ACCESSDENIED;
  1509. }
  1510. return hr;
  1511. }
  1512. #endif
  1513. //-------------------------------------------------------------------------//
  1514. #define REG_SZ_SHELL_SEARCH TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\") \
  1515. TEXT("Explorer\\FindExtensions\\Static\\ShellSearch")
  1516. //-------------------------------------------------------------------------//
  1517. HRESULT GetSearchURLs(
  1518. IN REFGUID guidSearch,
  1519. OUT LPTSTR pszUrl,
  1520. IN DWORD cch,
  1521. OUT OPTIONAL LPTSTR pszUrlNavNew,
  1522. OUT DWORD cchNavNew,
  1523. OUT BOOL *pfRunInProcess )
  1524. {
  1525. HRESULT hr = E_FAIL ;
  1526. DWORD cb ;
  1527. DWORD dwType ;
  1528. DWORD dwErr ;
  1529. *pfRunInProcess = FALSE ;
  1530. if( pszUrlNavNew && cchNavNew )
  1531. *pszUrlNavNew = 0 ;
  1532. if( IsEqualGUID( guidSearch, SRCID_SWebSearch ) )
  1533. {
  1534. if( GetDefaultInternetSearchUrlW( pszUrl, cch, TRUE ) )
  1535. hr = S_OK ;
  1536. }
  1537. else
  1538. {
  1539. // The shell search URL-eating stuff was adapted from
  1540. // CShellSearchExt::_GetSearchUrls() in browseui\searchext.cpp,
  1541. // and should be kept in sync.
  1542. TCHAR szSubKey[32];
  1543. HKEY hkey, hkeySub;
  1544. if( (dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_SZ_SHELL_SEARCH,
  1545. 0, KEY_QUERY_VALUE, &hkey )) != ERROR_SUCCESS )
  1546. return HRESULT_FROM_WIN32( dwErr ) ;
  1547. hr = E_FAIL ;
  1548. for (int i = 0; SUCCEEDED(StringCchPrintf(szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), i)) && (RegOpenKeyEx(hkey, szSubKey, NULL, KEY_QUERY_VALUE, &hkeySub) == ERROR_SUCCESS); i++)
  1549. {
  1550. TCHAR szSearchGuid[MAX_PATH];
  1551. cb = SIZEOF(szSearchGuid);
  1552. if( SHGetValue( hkeySub, TEXT("SearchGUID"), NULL, &dwType, (BYTE*)szSearchGuid, &cb ) == ERROR_SUCCESS )
  1553. {
  1554. GUID guid;
  1555. SHCLSIDFromString(szSearchGuid, &guid);
  1556. if( IsEqualGUID( guid, guidSearch ) )
  1557. {
  1558. cb = cch * sizeof(TCHAR);
  1559. if( SHGetValue( hkeySub, TEXT("SearchGUID\\Url"), NULL,
  1560. &dwType, (BYTE*)pszUrl, &cb ) == ERROR_SUCCESS )
  1561. {
  1562. if( pszUrlNavNew && cchNavNew )
  1563. {
  1564. // See if there is a secondary URL that we should navigate to
  1565. cb = cchNavNew * sizeof(TCHAR);
  1566. SHGetValue(hkeySub, TEXT("SearchGUID\\UrlNavNew"), NULL, &dwType, (BYTE*)pszUrlNavNew, &cb);
  1567. }
  1568. // try to grab the RunInProcess flag
  1569. *pfRunInProcess = (BOOL)SHRegGetIntW( hkeySub, L"RunInProcess", 0 );
  1570. RegCloseKey(hkeySub);
  1571. hr = S_OK ;
  1572. break;
  1573. }
  1574. }
  1575. }
  1576. RegCloseKey(hkeySub);
  1577. }
  1578. RegCloseKey( hkey ) ;
  1579. }
  1580. return hr ;
  1581. }
  1582. STDMETHODIMP _IsShellSearchBand( REFGUID guidSearch )
  1583. {
  1584. if (IsEqualGUID( guidSearch, SRCID_SFileSearch ) ||
  1585. IsEqualGUID( guidSearch, SRCID_SFindComputer ) ||
  1586. IsEqualGUID( guidSearch, SRCID_SFindPrinter ) )
  1587. return S_OK;
  1588. return S_FALSE;
  1589. }
  1590. //-------------------------------------------------------------------------//
  1591. // Establishes the correct shell search dialog, etc.
  1592. STDMETHODIMP _ShowShellSearchBand( IWebBrowser2* pwb2, REFGUID guidSearch )
  1593. {
  1594. ASSERT( pwb2 );
  1595. ASSERT( S_OK == _IsShellSearchBand( guidSearch ) );
  1596. HRESULT hr;
  1597. VARIANT varBand;
  1598. if (SUCCEEDED( (hr = InitBSTRVariantFromGUID(&varBand, CLSID_FileSearchBand)) ))
  1599. {
  1600. // Retrieve the FileSearchBand's unknown from the browser frame as a VT_UNKNOWN property;
  1601. // (FileSearchBand initialized and this when he was created and hosted.)
  1602. VARIANT varFsb;
  1603. if (SUCCEEDED( (hr = pwb2->GetProperty( varBand.bstrVal, &varFsb )) ))
  1604. {
  1605. if (VT_UNKNOWN == varFsb.vt && varFsb.punkVal != NULL )
  1606. {
  1607. // Retrieve the IFileSearchBand interface
  1608. IFileSearchBand* pfsb;
  1609. if (SUCCEEDED( (hr = varFsb.punkVal->QueryInterface( IID_PPV_ARG(IFileSearchBand, &pfsb) )) ))
  1610. {
  1611. // Assign the correct search type to the band
  1612. VARIANT varSearchID;
  1613. if (SUCCEEDED( (hr = InitBSTRVariantFromGUID(&varSearchID, guidSearch)) ))
  1614. {
  1615. VARIANT varNil = {0};
  1616. VARIANT_BOOL bNavToResults = VARIANT_FALSE ;
  1617. // Note [scotthan]: we only navigate to results when we create a
  1618. // new frame for the search, which we never do from srchasst.
  1619. pfsb->SetSearchParameters( &varSearchID.bstrVal, bNavToResults, &varNil, &varNil );
  1620. VariantClear( &varSearchID );
  1621. }
  1622. pfsb->Release();
  1623. }
  1624. }
  1625. VariantClear( &varFsb );
  1626. }
  1627. VariantClear( &varBand );
  1628. }
  1629. return hr;
  1630. }
  1631. //-------------------------------------------------------------------------//
  1632. // The goop to show a search band in the current browser frame.
  1633. // 6/1
  1634. HRESULT CSearchAssistantOC::ShowSearchBand( REFGUID guidSearch )
  1635. {
  1636. HRESULT hr = E_FAIL;
  1637. TCHAR szUrl[MAX_URL_STRING];
  1638. TCHAR szUrlNavNew[MAX_URL_STRING];
  1639. CLSID clsidBand;
  1640. BOOL fShellSearchBand = FALSE;
  1641. BOOL fRunInProcess = FALSE;
  1642. IUnknown* punkSite = m_punkSite ? m_punkSite : (IUnknown*)m_spClientSite;
  1643. if( !punkSite )
  1644. return E_UNEXPECTED ;
  1645. // Determine band class and whether the band supports navigation
  1646. if( (fShellSearchBand = (S_OK == _IsShellSearchBand( guidSearch ))) )
  1647. {
  1648. if (SHRestricted(REST_NOFIND) && IsEqualGUID(guidSearch, SRCID_SFileSearch))
  1649. return E_ACCESSDENIED;
  1650. clsidBand = CLSID_FileSearchBand;
  1651. }
  1652. else
  1653. {
  1654. clsidBand = CLSID_SearchBand;
  1655. // we need to navigate to a search URL, grope the registry for that special URL
  1656. if( FAILED( (hr= GetSearchURLs( guidSearch, szUrl, ARRAYSIZE(szUrl),
  1657. szUrlNavNew, ARRAYSIZE(szUrlNavNew),
  1658. &fRunInProcess )) ) )
  1659. return hr;
  1660. }
  1661. // FEATURE [scotthan]: this function will fail unless invoked from within a browser.
  1662. // This sits fine for now since SearchAsst is designed as a browser band.
  1663. IWebBrowser2* pwb2;
  1664. hr = IUnknown_QueryServiceForWebBrowserApp(punkSite, IID_PPV_ARG(IWebBrowser2, &pwb2));
  1665. if (SUCCEEDED(hr))
  1666. {
  1667. SA_BSTRGUID bstrClsid;
  1668. InitFakeBSTR(&bstrClsid, clsidBand);
  1669. VARIANT var;
  1670. var.bstrVal = bstrClsid.wsz;
  1671. var.vt = VT_BSTR;
  1672. VARIANT varNil = {0};
  1673. // show a search bar
  1674. hr = pwb2->ShowBrowserBar(&var, &varNil, &varNil);
  1675. if( SUCCEEDED( hr ) )
  1676. {
  1677. VARIANT varFlags;
  1678. if( fShellSearchBand )
  1679. {
  1680. hr= _ShowShellSearchBand( pwb2, guidSearch );
  1681. }
  1682. else
  1683. {
  1684. varFlags.vt = VT_I4;
  1685. varFlags.lVal = navBrowserBar;
  1686. var.bstrVal = SysAllocString( szUrl );
  1687. var.vt = VT_BSTR ;
  1688. // navigate the search bar to the correct url
  1689. hr = pwb2->Navigate2(&var, &varFlags, &varNil, &varNil, &varNil);
  1690. SysFreeString(var.bstrVal);
  1691. if( SUCCEEDED( hr ) )
  1692. {
  1693. hr = pwb2->put_Visible( TRUE ) ;
  1694. }
  1695. }
  1696. }
  1697. pwb2->Release();
  1698. }
  1699. return hr;
  1700. }
  1701. STDMETHODIMP CSearchAssistantOC::SetSite( IUnknown* punkSite )
  1702. {
  1703. ATOMICRELEASE(m_punkSite);
  1704. if ((m_punkSite = punkSite) != NULL)
  1705. m_punkSite->AddRef() ;
  1706. return S_OK ;
  1707. }
  1708. STDMETHODIMP CSearchAssistantOC::GetSite( REFIID riid, void** ppvSite )
  1709. {
  1710. if( !m_punkSite )
  1711. return E_FAIL ;
  1712. return m_punkSite->QueryInterface( riid, ppvSite ) ;
  1713. }