#include "priv.h" #include "caggunk.h" #include "srchasst.h" #include "dhuihand.h" #include "mlang.h" // fo char conversion #include "..\browseui\legacy.h" // for CITIDM_GETFOLDERSEARCHES #include "varutil.h" #include ///////////////////////////////////////////////////////////////////////////// // CSearchAssistantOC // If you change this, change browseui also. const WCHAR c_wszThisBandIsYourBand[] = L"$$SearchBand$$"; // HKLM values #define REG_SZ_SEARCH L"Software\\Microsoft\\Internet Explorer\\Search" #define REG_SZ_SEARCHASSIST L"SearchAssistant" #define REG_SZ_SEARCHCFG L"CustomizeSearch" // HKCU values #define REG_SZ_IE_MAIN L"Software\\Microsoft\\Internet Explorer\\Main" #define REG_SZ_IE_SEARCURL L"Software\\Microsoft\\Internet Explorer\\SearchURL" #define REG_SZ_SEARCHBAR L"Search Bar" #define REG_SZ_USECUSTOM L"Use Custom Search URL" #define REG_SZ_AUTOSEARCH L"AutoSearch" #define REG_SZ_PROVIDER L"Provider" #define REG_SZ_USE_SEARCH_COMP L"Use Search Asst" #define SAOC_VERSION 2 const WCHAR c_wszSearchProps[] = REG_SZ_SEARCH L"\\SearchProperties"; STDAPI_(VARIANT_BOOL) UseCustomInternetSearch() { VARIANT_BOOL bRet; DWORD dwVal; DWORD cbVal = sizeof(dwVal); if ((SHGetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_USECUSTOM, NULL, &dwVal, &cbVal) == ERROR_SUCCESS) && (FALSE != dwVal)) { bRet = VARIANT_TRUE; } else { bRet = VARIANT_FALSE; } return bRet; } STDAPI_(BOOL) GetSearchAssistantUrlW(LPWSTR pwszUrl, int cchUrl, BOOL bSubstitute, BOOL bCustomize) { BOOL bResult; WCHAR wszUrlTmp[MAX_URL_STRING]; WCHAR *pwszUrlRead; DWORD cb; ASSERT(pwszUrl); *pwszUrl = 0; if (bSubstitute) { cb = sizeof(wszUrlTmp); pwszUrlRead = wszUrlTmp; } else { cb = cchUrl * sizeof(WCHAR); pwszUrlRead = pwszUrl; } bResult = SHGetValueW(HKEY_LOCAL_MACHINE, REG_SZ_SEARCH, bCustomize ? REG_SZ_SEARCHCFG : REG_SZ_SEARCHASSIST, NULL, (BYTE *)pwszUrlRead, &cb) == ERROR_SUCCESS; if (bResult && bSubstitute) { bResult = SUCCEEDED(URLSubstitution(wszUrlTmp, pwszUrl, cchUrl, URLSUB_ALL)); } return bResult; } STDAPI_(BOOL) GetDefaultInternetSearchUrlW(LPWSTR pwszUrl, int cchUrl, BOOL bSubstitute) { BOOL bResult = FALSE; DWORD cb; ASSERT(pwszUrl); *pwszUrl = 0; if (UseCustomInternetSearch()) { // First try the user specific value cb = cchUrl * sizeof(TCHAR); bResult = SHGetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_SEARCHBAR, NULL, (BYTE *)pwszUrl, &cb) == ERROR_SUCCESS; } if (!bResult) { bResult = GetSearchAssistantUrlW(pwszUrl, cchUrl, bSubstitute, FALSE); } return bResult; } STDAPI_(BOOL) GetSearchAssistantUrlA(LPSTR pszUrl, int cchUrl, BOOL bSubstitute, BOOL bCustomize) { WCHAR wszUrl[INTERNET_MAX_URL_LENGTH]; BOOL bResult = GetSearchAssistantUrlW(wszUrl, ARRAYSIZE(wszUrl), bSubstitute, bCustomize); SHUnicodeToAnsi(wszUrl, pszUrl, cchUrl); return bResult; } STDAPI_(BOOL) GetDefaultInternetSearchUrlA(LPSTR pszUrl, int cchUrl, BOOL bSubstitute) { WCHAR wszUrl[INTERNET_MAX_URL_LENGTH]; BOOL bResult = GetDefaultInternetSearchUrlW(wszUrl, ARRAYSIZE(wszUrl), bSubstitute); SHUnicodeToAnsi(wszUrl, pszUrl, cchUrl); return bResult; } void SetDefaultInternetSearchUrlW(LPCWSTR pwszUrl) { DWORD dwUseCustom = FALSE; DWORD cb; if ((NULL != pwszUrl) && (0 != *pwszUrl)) { cb = (lstrlenW(pwszUrl) + 1) * sizeof(WCHAR); if (SHSetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_SEARCHBAR, REG_SZ, pwszUrl, cb) == ERROR_SUCCESS) { dwUseCustom = TRUE; } } cb = sizeof(dwUseCustom); SHSetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_USECUSTOM, REG_DWORD, &dwUseCustom, cb); } HRESULT CSearch_Create(GUID *pguid, BSTR bstrTitle, BSTR bstrUrl, ISearch **ppSearch) { HRESULT hres = E_INVALIDARG; ASSERT(ppSearch); *ppSearch = NULL; if (bstrTitle && bstrUrl && pguid) { BSTR _bstrTitle = SysAllocString(bstrTitle); BSTR _bstrUrl = SysAllocString(bstrUrl); if (_bstrTitle && _bstrUrl) { CSearch *ps = new CSearch(pguid, _bstrTitle, _bstrUrl); if (ps) { hres = ps->QueryInterface(IID_ISearch, (void **)ppSearch); ps->Release(); } } else { if (_bstrTitle) SysFreeString(_bstrTitle); if (_bstrUrl) SysFreeString(_bstrUrl); hres = E_OUTOFMEMORY; } } return hres; } CSearch::CSearch(GUID *pguid, BSTR bstrTitle, BSTR bstrUrl) : _cRef(1), _bstrTitle(bstrTitle), _bstrUrl(bstrUrl), CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_ISearch) { SHStringFromGUID(*pguid, _szId, ARRAYSIZE(_szId)); } CSearch::~CSearch() { if (_bstrTitle) SysFreeString(_bstrTitle); if (_bstrUrl) SysFreeString(_bstrUrl); } STDMETHODIMP CSearch::QueryInterface(REFIID riid, void** ppv) { static const QITAB qit[] = { QITABENT(CSearch, ISearch), QITABENTMULTI(CSearch, IDispatch, ISearch), { 0 }, }; return QISearch(this, qit, riid, ppv); } STDMETHODIMP_(ULONG) CSearch::AddRef() { return InterlockedIncrement(&_cRef); } STDMETHODIMP_(ULONG) CSearch::Release() { ASSERT( 0 != _cRef ); ULONG cRef = InterlockedDecrement(&_cRef); if ( 0 == cRef ) { delete this; } return cRef; } HRESULT CSearch::get_Title(BSTR *pbstrTitle) { HRESULT hres = NOERROR; *pbstrTitle = SysAllocString(_bstrTitle); if (!*pbstrTitle) hres = E_OUTOFMEMORY; return hres; } HRESULT CSearch::get_Id(BSTR *pbstrId) { HRESULT hres = NOERROR; *pbstrId = SysAllocString(_szId); if (!*pbstrId) hres = E_OUTOFMEMORY; return hres; } HRESULT CSearch::get_Url(BSTR *pbstrUrl) { HRESULT hres = NOERROR; *pbstrUrl = SysAllocString(_bstrUrl); if (!*pbstrUrl) hres = E_OUTOFMEMORY; return hres; } HRESULT CSearchCollection_Create(IFolderSearches *pfs, ISearches **ppSearches) { HRESULT hres = E_INVALIDARG; ASSERT(ppSearches); *ppSearches = NULL; if (pfs) { CSearchCollection *psc = new CSearchCollection(pfs); if (psc) { hres = psc->QueryInterface(IID_ISearches, (void **)ppSearches); psc->Release(); } else hres = E_OUTOFMEMORY; } return hres; } CSearchCollection::CSearchCollection(IFolderSearches *pfs) : _cRef(1), CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_ISearches) { GUID guid; if (SUCCEEDED(pfs->DefaultSearch(&guid))) SHStringFromGUID(guid, _szDefault, ARRAYSIZE(_szDefault)); _hdsaItems = DSA_Create(SIZEOF(URLSEARCH), 4); if (_hdsaItems) { IEnumUrlSearch *penum; if (SUCCEEDED(pfs->EnumSearches(&penum))) { URLSEARCH us; ULONG cElt; penum->Reset(); while (S_OK == penum->Next(1, &us, &cElt) && 1 == cElt) DSA_AppendItem(_hdsaItems, &us); penum->Release(); } } } CSearchCollection::~CSearchCollection() { DSA_Destroy(_hdsaItems); _hdsaItems = NULL; } STDMETHODIMP CSearchCollection::QueryInterface(REFIID riid, void** ppv) { static const QITAB qit[] = { QITABENT(CSearchCollection, ISearches), QITABENTMULTI(CSearchCollection, IDispatch, ISearches), { 0 }, }; return QISearch(this, qit, riid, ppv); } STDMETHODIMP_(ULONG) CSearchCollection::AddRef() { return InterlockedIncrement(&_cRef); } STDMETHODIMP_(ULONG) CSearchCollection::Release() { ASSERT( 0 != _cRef ); ULONG cRef = InterlockedDecrement(&_cRef); if ( 0 == cRef ) { delete this; } return cRef; } STDMETHODIMP CSearchCollection::get_Count(long *plCount) { *plCount = 0; if (_hdsaItems) { *plCount = DSA_GetItemCount(_hdsaItems); } return S_OK; } STDMETHODIMP CSearchCollection::get_Default(BSTR *pbstrDefault) { HRESULT hres = E_OUTOFMEMORY; *pbstrDefault = SysAllocString(_szDefault); if (*pbstrDefault) hres = S_OK; return hres; } STDMETHODIMP CSearchCollection::Item(VARIANT index, ISearch **ppid) { HRESULT hres = E_NOTIMPL; *ppid = NULL; switch (index.vt) { case VT_I2: index.lVal = (long)index.iVal; // And fall through... case VT_I4: if ((index.lVal >= 0) && (index.lVal < DSA_GetItemCount(_hdsaItems))) { LPURLSEARCH pus; pus = (LPURLSEARCH)DSA_GetItemPtr(_hdsaItems, index.lVal); ASSERT(pus); hres = CSearch_Create(&pus->guid, pus->wszName, pus->wszUrl, ppid); } break; } return hres; } STDMETHODIMP CSearchCollection::_NewEnum(IUnknown **ppunk) { *ppunk = NULL; return E_NOTIMPL; } CSearchAssistantOC::CSearchAssistantOC() : m_punkSite(NULL) { #ifdef UNIX m_dwSafety = 0; #endif } CSearchAssistantOC::~CSearchAssistantOC() { ATOMICRELEASE(m_pSearchBandTBHelper); ATOMICRELEASE(m_punkSite); } HRESULT CSearchAssistantOC::OnDraw(ATL_DRAWINFO& di) { return S_OK; } STDMETHODIMP CSearchAssistantOC::SetClientSite(IOleClientSite *pClientSite) { if (NULL != pClientSite) { HRESULT hr; IWebBrowser2 *pWebBrowser2; hr = IUnknown_QueryService(pClientSite, SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&pWebBrowser2); if (SUCCEEDED(hr)) { BSTR bstrProp = SysAllocString(c_wszThisBandIsYourBand); if (bstrProp) { VARIANT var; hr = pWebBrowser2->GetProperty(bstrProp, &var); if (SUCCEEDED(hr)) { if (var.vt == VT_UNKNOWN) { ATOMICRELEASE(m_pSearchBandTBHelper); hr = var.punkVal->QueryInterface(IID_ISearchBandTBHelper, (void **)&m_pSearchBandTBHelper); ASSERT(SUCCEEDED(hr)); if (m_pSearchBandTBHelper) m_pSearchBandTBHelper->SetOCCallback(this); } VariantClear(&var); } SysFreeString(bstrProp); } pWebBrowser2->Release(); } } else { if (NULL != m_pSearchBandTBHelper) { m_pSearchBandTBHelper->SetOCCallback(NULL); ATOMICRELEASE(m_pSearchBandTBHelper); } } return IOleObjectImpl::SetClientSite(pClientSite); } STDMETHODIMP CSearchAssistantOC::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText) { return E_NOTIMPL; } STDMETHODIMP CSearchAssistantOC::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) { HRESULT hr = E_UNEXPECTED; if (NULL == pguidCmdGroup) { switch (nCmdID) { case SBID_SEARCH_NEXT: if ((NULL != pvaIn) && (pvaIn->vt == VT_I4)) { Fire_OnNextMenuSelect(pvaIn->lVal); hr = S_OK; } else { hr = E_INVALIDARG; } break; case SBID_SEARCH_NEW: if (NULL != pvaOut) { m_bEventHandled = VARIANT_FALSE; Fire_OnNewSearch(); pvaOut->vt = VT_BOOL; pvaOut->boolVal = m_bEventHandled; hr = S_OK; } else { hr = E_INVALIDARG; } break; } } return hr; } STDMETHODIMP CSearchAssistantOC::AddNextMenuItem(BSTR bstrText, long idItem) { HRESULT hr; if (IsTrustedSite()) { if (NULL != m_pSearchBandTBHelper) { hr = m_pSearchBandTBHelper->AddNextMenuItem(bstrText, idItem); ASSERT(SUCCEEDED(hr)); } hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::ResetNextMenu() { HRESULT hr; if (IsTrustedSite()) { if (NULL != m_pSearchBandTBHelper) { hr = m_pSearchBandTBHelper->ResetNextMenu(); ASSERT(SUCCEEDED(hr)); } hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::SetDefaultSearchUrl(BSTR bstrUrl) { HRESULT hr; if (IsTrustedSite()) { SetDefaultInternetSearchUrlW(bstrUrl); hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::NavigateToDefaultSearch() { HRESULT hr; IWebBrowser2 *pWebBrowser2; hr = IUnknown_QueryService(m_spClientSite, SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&pWebBrowser2); if (SUCCEEDED(hr)) { WCHAR wszUrl[INTERNET_MAX_URL_LENGTH]; if (GetDefaultInternetSearchUrlW(wszUrl, ARRAYSIZE(wszUrl), TRUE)) { BSTR bstrUrl = SysAllocString(wszUrl); if (NULL != bstrUrl) { VARIANT varFrame; varFrame.vt = VT_BSTR; varFrame.bstrVal = SysAllocString(L"_search"); if (NULL != varFrame.bstrVal) { hr = pWebBrowser2->Navigate(bstrUrl, NULL, &varFrame, NULL, NULL); ASSERT(SUCCEEDED(hr)); SysFreeString(varFrame.bstrVal); } SysFreeString(bstrUrl); } } pWebBrowser2->Release(); } return S_OK; } typedef struct _GUIDREST { const GUID * pguid; RESTRICTIONS rest; } GUIDREST; HRESULT CSearchAssistantOC::IsRestricted(BSTR bstrGuid, VARIANT_BOOL *pVal) { HRESULT hr; GUID guid; if (IsTrustedSite()) { *pVal = VARIANT_FALSE; // default to not restricted if (SUCCEEDED(SHCLSIDFromString(bstrGuid, &guid))) { // find computer is special because if it restricted then we show // it else don't show it (restriction name is HASFINDCOMPUTER if (IsEqualGUID(guid, SRCID_SFindComputer)) { if (!SHRestricted(REST_HASFINDCOMPUTERS)) *pVal = VARIANT_TRUE; } else { static GUIDREST agr[] = { {&SRCID_SFileSearch, REST_NOFIND}, // rest_nofindprinter does not exist yet //{&SRCID_SFindPrinter, REST_NOFINDPRINTER}, }; for (int i=0; i < ARRAYSIZE(agr); i++) { if (IsEqualGUID(guid, *agr[i].pguid)) { if (SHRestricted(agr[i].rest)) *pVal = VARIANT_TRUE; break; } } } } hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } HRESULT CSearchAssistantOC::get_ShellFeaturesEnabled(VARIANT_BOOL *pVal) { HRESULT hr; if (IsTrustedSite()) { if (pVal) { *pVal = (GetUIVersion() >= 5) ? VARIANT_TRUE : VARIANT_FALSE; hr = S_OK; } else { hr = E_INVALIDARG; } } else { hr = E_ACCESSDENIED; } return hr; } HRESULT CSearchAssistantOC::get_SearchAssistantDefault(VARIANT_BOOL *pVal) { HRESULT hr; if (IsTrustedSite()) { if (pVal) { *pVal = !UseCustomInternetSearch(); hr = S_OK; } else { hr = E_INVALIDARG; } } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::get_Searches(ISearches **ppid) { HRESULT hr; *ppid = NULL; if (IsTrustedSite()) { IServiceProvider *psp; hr = IUnknown_QueryService(m_spClientSite, SID_STopLevelBrowser, IID_PPV_ARG(IServiceProvider, &psp)); if (SUCCEEDED(hr)) { IOleCommandTarget *pct; hr = psp->QueryService(SID_SExplorerToolbar, IID_IOleCommandTarget, (void **)&pct); if (SUCCEEDED(hr)) { VARIANTARG var = {0}; hr = pct->Exec(&CGID_PrivCITCommands, CITIDM_GETFOLDERSEARCHES, 0, NULL, &var); if (SUCCEEDED(hr)) { IFolderSearches *pfs; ASSERT(var.vt == VT_UNKNOWN && var.punkVal); hr = var.punkVal->QueryInterface(IID_IFolderSearches, (void **)&pfs); if (SUCCEEDED(hr)) { hr = CSearchCollection_Create(pfs, ppid); pfs->Release(); } var.punkVal->Release(); } pct->Release(); hr = S_OK; } psp->Release(); } } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::get_InWebFolder(VARIANT_BOOL *pVal) { HRESULT hr; if (IsTrustedSite()) { ASSERT(pVal); *pVal = VARIANT_FALSE; IBrowserService2 *pbs; hr = IUnknown_QueryService(m_spClientSite, SID_STopLevelBrowser, IID_IBrowserService2, (void **)&pbs); if (SUCCEEDED(hr)) { ITEMIDLIST *pidl; hr = pbs->GetPidl(&pidl); if (SUCCEEDED(hr)) { // REARCHITECT: Don't use ILIsWeb(). We should use IShellFolder2::GetDefaultSearchGUID() and // test for SRCID_SWebSearch vs. SRCID_SFileSearch/SRCID_SFindComputer/SRCID_SFindPrinter. // This is because Shell Extensions need a way to indicate what kind of search they want // and ILIsWeb() doesn't provide that. An example of this is "Web Folders" won't return // TRUE from ILIsWeb(). The use of ILIsWeb() should be limited. if (ILIsWeb(pidl)) { *pVal = VARIANT_TRUE; } ILFree(pidl); } pbs->Release(); } hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } HRESULT GetPerLocalePath(WCHAR *pwszKeyName, int cchKeyName) { HRESULT hr; ASSERT(cchKeyName >= (ARRAYSIZE(c_wszSearchProps) + 1)); hr = StringCchCopy(pwszKeyName, cchKeyName, c_wszSearchProps); if (SUCCEEDED(hr)) { *(pwszKeyName + (ARRAYSIZE(c_wszSearchProps) - 1)) = L'\\'; GetWebLocaleAsRFC1766(pwszKeyName + ARRAYSIZE(c_wszSearchProps), cchKeyName - (ARRAYSIZE(c_wszSearchProps))); } return hr; } STDMETHODIMP CSearchAssistantOC::PutProperty(VARIANT_BOOL bPerLocale, BSTR bstrName, BSTR bstrValue) { HRESULT hr = E_ACCESSDENIED; if (IsTrustedSite()) { HKEY hkey; LPCWSTR pwszKeyName; WCHAR wszKeyName[MAX_PATH]; DWORD dwDisposition; if (bPerLocale) { hr = GetPerLocalePath(wszKeyName, ARRAYSIZE(wszKeyName)); pwszKeyName = wszKeyName; } else { hr = S_OK; pwszKeyName = c_wszSearchProps; } if (SUCCEEDED(hr)) { if (RegCreateKeyExW(HKEY_CURRENT_USER, pwszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwDisposition) == ERROR_SUCCESS) { if ((NULL != bstrValue) && (bstrValue[0] != 0)) { RegSetValueExW(hkey, bstrName, 0, REG_BINARY, (LPBYTE)bstrValue, SysStringByteLen(bstrValue)); } else { // Empty or NULL string means remove the property RegDeleteValue(hkey, bstrName); } RegCloseKey(hkey); } } } return hr; } STDMETHODIMP CSearchAssistantOC::GetProperty(VARIANT_BOOL bPerLocale, BSTR bstrName, BSTR *pbstrValue) { HRESULT hr = E_INVALIDARG; if (NULL != pbstrValue) { hr = E_ACCESSDENIED; *pbstrValue = NULL; if (IsTrustedSite()) { HKEY hkey; LPCWSTR pwszKeyName; WCHAR wszKeyName[MAX_PATH]; if (bPerLocale) { hr = GetPerLocalePath(wszKeyName, ARRAYSIZE(wszKeyName)); pwszKeyName = wszKeyName; } else { hr = S_OK; pwszKeyName = c_wszSearchProps; } if (SUCCEEDED(hr)) { if (RegOpenKeyExW(HKEY_CURRENT_USER, pwszKeyName, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { DWORD dwType; DWORD cbSize; if ((RegQueryValueExW(hkey, bstrName, NULL, &dwType, NULL, &cbSize) == ERROR_SUCCESS) && (dwType == REG_BINARY)) { BSTR bstrValue = SysAllocStringByteLen(NULL, cbSize); if (NULL != bstrValue) { if (RegQueryValueExW(hkey, bstrName, NULL, &dwType, (LPBYTE)bstrValue, &cbSize) == ERROR_SUCCESS) { *pbstrValue = bstrValue; } else { SysFreeString(bstrValue); } } } RegCloseKey(hkey); } } } } return hr; } STDMETHODIMP CSearchAssistantOC::put_EventHandled(VARIANT_BOOL bHandled) { HRESULT hr; if (IsTrustedSite()) { m_bEventHandled = bHandled; hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::GetSearchAssistantURL(VARIANT_BOOL bSubstitute, VARIANT_BOOL bCustomize, BSTR *pbstrValue) { HRESULT hr; if (IsTrustedSite()) { if (NULL != pbstrValue) { WCHAR wszUrl[INTERNET_MAX_URL_LENGTH]; if (GetSearchAssistantUrlW(wszUrl, ARRAYSIZE(wszUrl), bSubstitute, bCustomize)) { *pbstrValue = SysAllocString(wszUrl); } hr = S_OK; } else { hr = E_INVALIDARG; } } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::NotifySearchSettingsChanged() { HRESULT hr; if (IsTrustedSite()) { SendShellIEBroadcastMessage(WM_WININICHANGE, 0, (LPARAM)SEARCH_SETTINGS_CHANGED, 3000); hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::put_ASProvider(BSTR Provider) { HRESULT hr; if (IsTrustedSite()) { if (Provider) { DWORD dwRet = SHSetValueW(HKEY_CURRENT_USER, REG_SZ_IE_SEARCURL, REG_SZ_PROVIDER, REG_SZ, Provider, (lstrlenW(Provider) + 1) * sizeof(WCHAR)); ASSERT(ERROR_SUCCESS == dwRet); } hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::get_ASProvider(BSTR *pProvider) { HRESULT hr; if (IsTrustedSite()) { if (NULL != pProvider) { HKEY hkey; if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CURRENT_USER, REG_SZ_IE_SEARCURL, 0, KEY_QUERY_VALUE, &hkey)) { DWORD dwType; DWORD dwSize; if ((ERROR_SUCCESS == RegQueryValueExW(hkey, REG_SZ_PROVIDER, NULL, &dwType, NULL, &dwSize)) && (REG_SZ == dwType)) { *pProvider = SysAllocStringByteLen(NULL, dwSize); if (NULL != *pProvider) { if (ERROR_SUCCESS != RegQueryValueExW(hkey, REG_SZ_PROVIDER, NULL, &dwType, (LPBYTE)*pProvider, &dwSize)) { *pProvider = 0; } } } RegCloseKey(hkey); } hr = S_OK; } else { hr = E_INVALIDARG; } } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::put_ASSetting(int Setting) { HRESULT hr; if (IsTrustedSite()) { DWORD dwRet = SHSetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_AUTOSEARCH, REG_DWORD, &Setting, sizeof(DWORD)); ASSERT(ERROR_SUCCESS == dwRet); hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::get_ASSetting(int *pSetting) { HRESULT hr; if (IsTrustedSite()) { if (NULL != pSetting) { DWORD dwSize = sizeof(int); *pSetting = -1; DWORD dwRet = SHGetValueW(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_AUTOSEARCH, NULL, pSetting, &dwSize); hr = S_OK; } else { hr = E_INVALIDARG; } } else { hr = E_ACCESSDENIED; } return hr; } BOOL CSearchAssistantOC::IsTrustedSite() { if (!m_bSafetyInited && m_spClientSite) { m_bSafetyInited = TRUE; IHTMLDocument2 *pHTMLDocument2; HRESULT hr = GetHTMLDoc2(m_spClientSite, &pHTMLDocument2); if (SUCCEEDED(hr)) { ASSERT(NULL != pHTMLDocument2); IHTMLLocation *pHTMLLocation; hr = pHTMLDocument2->get_location(&pHTMLLocation); if (SUCCEEDED(hr) && (NULL != pHTMLLocation)) { BSTR bstrUrl; pHTMLLocation->get_href(&bstrUrl); if (SUCCEEDED(hr) && (NULL != bstrUrl)) { HKEY hkey; // FEATURE (tnoonan) // This code is duped with CSearchBand::_IsSafeUrl in browseui if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\SafeSites", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { WCHAR wszValue[MAX_PATH]; WCHAR wszData[MAX_URL_STRING]; WCHAR wszExpandedUrl[MAX_URL_STRING]; DWORD cbData = SIZEOF(wszData); DWORD cchValue = ARRAYSIZE(wszValue); for (int i=0; RegEnumValueW(hkey, i, wszValue, &cchValue, NULL, NULL, (LPBYTE)wszData, &cbData) == ERROR_SUCCESS; i++) { if (SHExpandEnvironmentStringsW(wszData, wszExpandedUrl, ARRAYSIZE(wszExpandedUrl)) > 0) { cchValue = ARRAYSIZE(wszExpandedUrl); if (SUCCEEDED(UrlCanonicalizeW(wszExpandedUrl, wszExpandedUrl, &cchValue, 0))) { if (cchValue > 0) { BOOL bRet; if (wszExpandedUrl[cchValue-1] == L'*') { bRet = StrCmpNIW(bstrUrl, wszExpandedUrl, cchValue - 1) == 0; } else { bRet = StrCmpIW(bstrUrl, wszExpandedUrl) == 0; } m_bIsTrustedSite = bRet ? TRUE : FALSE; if (m_bIsTrustedSite) break; } } cbData = SIZEOF(wszData); cchValue = ARRAYSIZE(wszValue); } } RegCloseKey(hkey); } SysFreeString(bstrUrl); } pHTMLLocation->Release(); } pHTMLDocument2->Release(); } } return m_bIsTrustedSite; } HRESULT CSearchAssistantOC::UpdateRegistry(BOOL bRegister) { //this control uses selfreg.inx, not the ATL registry goo return S_OK; } STDMETHODIMP CSearchAssistantOC::FindOnWeb() { if (!IsTrustedSite() && m_punkSite==NULL) return E_ACCESSDENIED ; return ShowSearchBand( SRCID_SWebSearch ) ; } STDMETHODIMP CSearchAssistantOC::FindFilesOrFolders() { if (!IsTrustedSite() && m_punkSite==NULL) return E_ACCESSDENIED ; return ShowSearchBand( SRCID_SFileSearch ) ; } STDMETHODIMP CSearchAssistantOC::FindComputer() { if (!IsTrustedSite() && m_punkSite==NULL) return E_ACCESSDENIED ; return ShowSearchBand( SRCID_SFindComputer ) ; } STDMETHODIMP CSearchAssistantOC::FindPrinter() { if (!IsTrustedSite() && m_punkSite==NULL) return E_ACCESSDENIED ; HRESULT hr = E_FAIL; IShellDispatch2* psd2; if( SUCCEEDED( (hr = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellDispatch2, &psd2) )) ) ) { hr = psd2->FindPrinter( NULL, NULL, NULL ) ; psd2->Release(); } return hr ; } STDMETHODIMP CSearchAssistantOC::FindPeople() { if (!IsTrustedSite() && m_punkSite==NULL) { return E_ACCESSDENIED; } SHELLEXECUTEINFO sei = {0}; sei.cbSize = sizeof(SHELLEXECUTEINFO); sei.hwnd = HWND_DESKTOP; sei.lpVerb = TEXT("open"); sei.lpFile = TEXT("wab.exe"); sei.lpParameters = TEXT("/find"); sei.lpDirectory = NULL; sei.nShow = SW_SHOWNORMAL; if (!ShellExecuteEx(&sei)) { return HRESULT_FROM_WIN32(GetLastError()); } else { return S_OK; } } // Wininet helper method to retry autodetection // check to make sure that the hosting page is on // the local computer. // stolen from the zones code by joshco // STDMETHODIMP CSearchAssistantOC::LocalZoneCheck( ) { HRESULT hr = E_ACCESSDENIED; // Return S_FALSE if we don't have a host site since we have no way of doing a // security check. This is as far as VB 5.0 apps get. if (!m_spClientSite) return S_FALSE; // 1) Get an IHTMLDocument2 pointer // 2) Get URL from doc // 3) Check if doc URL zone is local, if so everything's S_OK // 4) Otherwise, get and compare doc URL SID to requested URL SID IHTMLDocument2 *pHtmlDoc; if (SUCCEEDED(GetHTMLDoc2(m_spClientSite, &pHtmlDoc))) { ASSERT(pHtmlDoc); BSTR bstrDocUrl; if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl))) { ASSERT(bstrDocUrl); DWORD dwZoneID = URLZONE_UNTRUSTED; if (SUCCEEDED(GetZoneFromUrl(bstrDocUrl, m_spClientSite, &dwZoneID))) { if (dwZoneID == URLZONE_LOCAL_MACHINE) hr = S_OK; } SysFreeString(bstrDocUrl); } pHtmlDoc->Release(); } else { // If we don't have an IHTMLDocument2 we aren't running in a browser that supports // our OM. We shouldn't block in this case since we could potentially // get here from other hosts (VB, WHS, etc.). hr = S_FALSE; } return hr; } // set flags so that the next navigate will cause // a proxy autodetection cycle // used in dnserr.htm along with location.reload. // added by joshco // STDMETHODIMP CSearchAssistantOC::NETDetectNextNavigate() { HRESULT hr = S_FALSE; CHAR szConnectionName[100]; DWORD dwBufLen; DWORD dwFlags; BOOL fResult; if ( LocalZoneCheck() != S_OK ) { // some security problem.. time to bail. hr=E_ACCESSDENIED; goto error; } dwBufLen = sizeof(szConnectionName); // find the connection name via internetconnected state fResult = InternetGetConnectedStateExA(&dwFlags, szConnectionName,dwBufLen, 0 ); INTERNET_PER_CONN_OPTION_LISTA list; INTERNET_PER_CONN_OPTIONA option; list.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LISTA); if(!fResult || (dwFlags & INTERNET_CONNECTION_LAN)) { list.pszConnection = NULL; } else { list.pszConnection = szConnectionName; } list.dwOptionCount = 1; list.pOptions = &option; option.dwOption = INTERNET_PER_CONN_FLAGS; dwBufLen= sizeof(list); // now call internetsetoption to do it.. // first set this connectoid to enable autodetect if ( ! InternetQueryOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION , &list,&dwBufLen) ) { goto error; } option.Value.dwValue |= PROXY_TYPE_AUTO_DETECT ; if ( ! InternetSetOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION , &list,sizeof(list))) { goto error; } if ( ! InternetInitializeAutoProxyDll(0) ) { goto error; } // Now set the autodetect flags for this connectoid to // do a passive detect and shut itself off if it doesnt work option.dwOption = INTERNET_PER_CONN_AUTODISCOVERY_FLAGS; if ( ! InternetQueryOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION , &list,&dwBufLen) ) { goto error; } option.Value.dwValue &= ~(AUTO_PROXY_FLAG_DETECTION_RUN) ; if ( ! InternetSetOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION , &list,sizeof(list))) { goto error; } if ( ! InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED,NULL, 0) ) { goto error; } hr=S_OK; error: ; return hr; } STDMETHODIMP CSearchAssistantOC::PutFindText(BSTR FindText) { HRESULT hr; if (IsTrustedSite()) { IServiceProvider *pServiceProvider; hr = IUnknown_QueryService(m_pSearchBandTBHelper, SID_SProxyBrowser, IID_IServiceProvider, (void **)&pServiceProvider); if (SUCCEEDED(hr)) { IWebBrowser2 *pWebBrowser2; hr = pServiceProvider->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&pWebBrowser2); if (SUCCEEDED(hr)) { ::PutFindText(pWebBrowser2, FindText); pWebBrowser2->Release(); } pServiceProvider->Release(); } hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::get_Version(int *pVersion) { if (NULL != pVersion) { *pVersion = SAOC_VERSION; } return S_OK; } // x_hex_digit and URLEncode were stolen from trident inline int x_hex_digit(int c) { if (c >= 0 && c <= 9) { return c + '0'; } if (c >= 10 && c <= 15) { return c - 10 + 'A'; } return '0'; } /* The following array was copied directly from NCSA Mosaic 2.2 */ static const unsigned char isAcceptable[96] = /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, /* 2x !"#$%&'()*+,-./ */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x 0123456789:;<=>? */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x @ABCDEFGHIJKLMNO */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x PQRSTUVWXYZ[\]^_ */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x `abcdefghijklmno */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}; /* 7x pqrstuvwxyz{\}~ DEL */ // Performs URL-encoding of null-terminated strings. Pass NULL in pbOut // to find buffer length required. Note that '\0' is not written out. int URLEncode(char * pbOut, const char * pchIn) { int lenOut = 0; char * pchOut = pbOut; ASSERT(pchIn); for (; *pchIn; pchIn++, lenOut++) { if (*pchIn == ' ') { if (pchOut) *pchOut++ = '+'; } else if (*pchIn >= 32 && *pchIn <= 127 && isAcceptable[*pchIn - 32]) { if (pchOut) *pchOut++ = *pchIn; } else { if (pchOut) *pchOut++ = '%'; lenOut++; if (pchOut) *pchOut++ = (char)x_hex_digit((*pchIn >> 4) & 0xf); lenOut++; if (pchOut) *pchOut++ = (char)x_hex_digit(*pchIn & 0xf); } } return lenOut; } STDMETHODIMP CSearchAssistantOC::EncodeString(BSTR bstrValue, BSTR bstrCharSet, VARIANT_BOOL bUseUTF8, BSTR *pbstrResult) { if ((NULL != bstrValue) && (NULL != pbstrResult)) { HRESULT hr; IMultiLanguage2 *pMultiLanguage2; *pbstrResult = NULL; hr = CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IMultiLanguage2, &pMultiLanguage2)); if (SUCCEEDED(hr)) { UINT uiCodePage = CP_BOGUS; UINT cchVal = SysStringLen(bstrValue); DWORD dwMode = 0; if (!bUseUTF8) { // We're not using UTF so try and get the code page from the // charset. MIMECSETINFO info; hr = pMultiLanguage2->GetCharsetInfo(bstrCharSet, &info); if (SUCCEEDED(hr)) { hr = pMultiLanguage2->ConvertStringFromUnicodeEx(&dwMode, info.uiCodePage, bstrValue, &cchVal, NULL, NULL, MLCONVCHARF_NOBESTFITCHARS, NULL); if (S_OK == hr) { uiCodePage = info.uiCodePage; } } } else { uiCodePage = CP_UTF_8; } if (uiCodePage == CP_BOGUS) { // we have characters which don't work in the charset or the charset // is unknown to MLang, maybe MLang can figure out a code page to use. IMLangCodePages *pMLangCodePages; // When all else fails... uiCodePage = CP_ACP; hr = pMultiLanguage2->QueryInterface(IID_IMLangCodePages, (void **)&pMLangCodePages); if (SUCCEEDED(hr)) { DWORD dwCodePages = 0; long cchProcessed = 0; UINT uiTmpCP = 0; if (SUCCEEDED(pMLangCodePages->GetStrCodePages(bstrValue, cchVal, 0, &dwCodePages, &cchProcessed)) && SUCCEEDED(pMLangCodePages->CodePagesToCodePage(dwCodePages, 0, &uiTmpCP))) { uiCodePage = uiTmpCP; } pMLangCodePages->Release(); } } dwMode = 0; UINT cbVal = 0; // Ask MLang how big of a buffer we need hr = pMultiLanguage2->ConvertStringFromUnicode(&dwMode, uiCodePage, bstrValue, &cchVal, NULL, &cbVal); if (SUCCEEDED(hr)) { CHAR *pszValue = new CHAR[cbVal + 1]; if (NULL != pszValue) { // Really convert the string hr = pMultiLanguage2->ConvertStringFromUnicode(&dwMode, uiCodePage, bstrValue, &cchVal, pszValue, &cbVal); if (SUCCEEDED(hr)) { pszValue[cbVal] = 0; int cbEncVal = URLEncode(NULL, pszValue); CHAR *pszEncVal = new CHAR[cbEncVal]; if (NULL != pszEncVal) { URLEncode(pszEncVal, pszValue); int cchResult = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszEncVal, cbEncVal, NULL, 0); *pbstrResult = SysAllocStringLen(NULL, cchResult); if (NULL != *pbstrResult) { MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszEncVal, cbEncVal, *pbstrResult, cchResult); } delete [] pszEncVal; } } delete [] pszValue; } } pMultiLanguage2->Release(); } } return S_OK; } STDMETHODIMP CSearchAssistantOC::get_ShowFindPrinter(VARIANT_BOOL *pbShowFindPrinter) { HRESULT hr; if (IsTrustedSite()) { if (NULL != pbShowFindPrinter) { IShellDispatch2* psd; *pbShowFindPrinter = VARIANT_FALSE; if (SUCCEEDED(CoCreateInstance(CLSID_Shell, 0, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellDispatch2, &psd)))) { BSTR bstrName = SysAllocString( L"DirectoryServiceAvailable"); if (bstrName) { VARIANT varRet = {0}; if (SUCCEEDED(psd->GetSystemInformation(bstrName, &varRet))) { ASSERT(VT_BOOL == varRet.vt); *pbShowFindPrinter = varRet.boolVal; } SysFreeString(bstrName); } psd->Release(); } hr = S_OK; } else { hr = E_INVALIDARG; } } else { hr = E_ACCESSDENIED; } return hr; } STDMETHODIMP CSearchAssistantOC::get_SearchCompanionAvailable(VARIANT_BOOL *pbAvailable) { HRESULT hr = E_ACCESSDENIED; if (IsTrustedSite()) { if (pbAvailable != NULL) { BOOL fSCAvailable = FALSE; // need to determine if search companion is available on system and supports user locale ISearchCompanionInfo* psci; hr = CoCreateInstance(CLSID_SearchCompanionInfo, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ISearchCompanionInfo, &psci)); if (SUCCEEDED(hr)) { hr = psci->IsSearchCompanionInetAvailable(&fSCAvailable); psci->Release(); } *pbAvailable = fSCAvailable ? VARIANT_TRUE : VARIANT_FALSE; hr = S_OK; } else { hr = E_INVALIDARG; } } return hr; } STDMETHODIMP CSearchAssistantOC::put_UseSearchCompanion(VARIANT_BOOL bUseSC) { HRESULT hr = E_ACCESSDENIED; if (IsTrustedSite()) { LPCTSTR pszUseSC = bUseSC ? TEXT("yes") : TEXT("no"); SHSetValue(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_USE_SEARCH_COMP, REG_SZ, pszUseSC, CbFromCch(lstrlen(pszUseSC) + 1)); if (bUseSC) { // disable "Use Custom Search URL" as SC won't launch if custom search URL is defined DWORD dwUseCustom = FALSE; SHSetValue(HKEY_CURRENT_USER, REG_SZ_IE_MAIN, REG_SZ_USECUSTOM, REG_DWORD, &dwUseCustom, sizeof(dwUseCustom)); } hr = S_OK; } return hr; } STDMETHODIMP CSearchAssistantOC::get_UseSearchCompanion(VARIANT_BOOL *pbUseSC) { HRESULT hr = E_ACCESSDENIED; if (IsTrustedSite()) { if (pbUseSC != NULL) { BOOL fUseSC = SHRegGetBoolUSValue(REG_SZ_IE_MAIN, REG_SZ_USE_SEARCH_COMP, FALSE, FALSE); *pbUseSC = fUseSC ? VARIANT_TRUE : VARIANT_FALSE; hr = S_OK; } else { hr = E_INVALIDARG; } } return hr; } #ifdef ENABLE_THIS_FOR_IE5X STDMETHODIMP CSearchAssistantOC::RefreshLocation(IDispatch *pLocation) { HRESULT hr; if (IsTrustedSite()) { if (NULL != pLocation) { IHTMLLocation *pHTMLLocation; IUnknown_QueryService(pLocation, IID_IHTMLLocation, IID_IHTMLLocation, (void **)&pHTMLLocation); if (pHTMLLocation) { pHTMLLocation->reload(VARIANT_TRUE); pHTMLLocation->Release(); } } hr = S_OK; } else { hr = E_ACCESSDENIED; } return hr; } #endif //-------------------------------------------------------------------------// #define REG_SZ_SHELL_SEARCH TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\") \ TEXT("Explorer\\FindExtensions\\Static\\ShellSearch") //-------------------------------------------------------------------------// HRESULT GetSearchURLs( IN REFGUID guidSearch, OUT LPTSTR pszUrl, IN DWORD cch, OUT OPTIONAL LPTSTR pszUrlNavNew, OUT DWORD cchNavNew, OUT BOOL *pfRunInProcess ) { HRESULT hr = E_FAIL ; DWORD cb ; DWORD dwType ; DWORD dwErr ; *pfRunInProcess = FALSE ; if( pszUrlNavNew && cchNavNew ) *pszUrlNavNew = 0 ; if( IsEqualGUID( guidSearch, SRCID_SWebSearch ) ) { if( GetDefaultInternetSearchUrlW( pszUrl, cch, TRUE ) ) hr = S_OK ; } else { // The shell search URL-eating stuff was adapted from // CShellSearchExt::_GetSearchUrls() in browseui\searchext.cpp, // and should be kept in sync. TCHAR szSubKey[32]; HKEY hkey, hkeySub; if( (dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_SZ_SHELL_SEARCH, 0, KEY_QUERY_VALUE, &hkey )) != ERROR_SUCCESS ) return HRESULT_FROM_WIN32( dwErr ) ; hr = E_FAIL ; for (int i = 0; SUCCEEDED(StringCchPrintf(szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), i)) && (RegOpenKeyEx(hkey, szSubKey, NULL, KEY_QUERY_VALUE, &hkeySub) == ERROR_SUCCESS); i++) { TCHAR szSearchGuid[MAX_PATH]; cb = SIZEOF(szSearchGuid); if( SHGetValue( hkeySub, TEXT("SearchGUID"), NULL, &dwType, (BYTE*)szSearchGuid, &cb ) == ERROR_SUCCESS ) { GUID guid; SHCLSIDFromString(szSearchGuid, &guid); if( IsEqualGUID( guid, guidSearch ) ) { cb = cch * sizeof(TCHAR); if( SHGetValue( hkeySub, TEXT("SearchGUID\\Url"), NULL, &dwType, (BYTE*)pszUrl, &cb ) == ERROR_SUCCESS ) { if( pszUrlNavNew && cchNavNew ) { // See if there is a secondary URL that we should navigate to cb = cchNavNew * sizeof(TCHAR); SHGetValue(hkeySub, TEXT("SearchGUID\\UrlNavNew"), NULL, &dwType, (BYTE*)pszUrlNavNew, &cb); } // try to grab the RunInProcess flag *pfRunInProcess = (BOOL)SHRegGetIntW( hkeySub, L"RunInProcess", 0 ); RegCloseKey(hkeySub); hr = S_OK ; break; } } } RegCloseKey(hkeySub); } RegCloseKey( hkey ) ; } return hr ; } STDMETHODIMP _IsShellSearchBand( REFGUID guidSearch ) { if (IsEqualGUID( guidSearch, SRCID_SFileSearch ) || IsEqualGUID( guidSearch, SRCID_SFindComputer ) || IsEqualGUID( guidSearch, SRCID_SFindPrinter ) ) return S_OK; return S_FALSE; } //-------------------------------------------------------------------------// // Establishes the correct shell search dialog, etc. STDMETHODIMP _ShowShellSearchBand( IWebBrowser2* pwb2, REFGUID guidSearch ) { ASSERT( pwb2 ); ASSERT( S_OK == _IsShellSearchBand( guidSearch ) ); HRESULT hr; VARIANT varBand; if (SUCCEEDED( (hr = InitBSTRVariantFromGUID(&varBand, CLSID_FileSearchBand)) )) { // Retrieve the FileSearchBand's unknown from the browser frame as a VT_UNKNOWN property; // (FileSearchBand initialized and this when he was created and hosted.) VARIANT varFsb; if (SUCCEEDED( (hr = pwb2->GetProperty( varBand.bstrVal, &varFsb )) )) { if (VT_UNKNOWN == varFsb.vt && varFsb.punkVal != NULL ) { // Retrieve the IFileSearchBand interface IFileSearchBand* pfsb; if (SUCCEEDED( (hr = varFsb.punkVal->QueryInterface( IID_PPV_ARG(IFileSearchBand, &pfsb) )) )) { // Assign the correct search type to the band VARIANT varSearchID; if (SUCCEEDED( (hr = InitBSTRVariantFromGUID(&varSearchID, guidSearch)) )) { VARIANT varNil = {0}; VARIANT_BOOL bNavToResults = VARIANT_FALSE ; // Note [scotthan]: we only navigate to results when we create a // new frame for the search, which we never do from srchasst. pfsb->SetSearchParameters( &varSearchID.bstrVal, bNavToResults, &varNil, &varNil ); VariantClear( &varSearchID ); } pfsb->Release(); } } VariantClear( &varFsb ); } VariantClear( &varBand ); } return hr; } //-------------------------------------------------------------------------// // The goop to show a search band in the current browser frame. // 6/1 HRESULT CSearchAssistantOC::ShowSearchBand( REFGUID guidSearch ) { HRESULT hr = E_FAIL; TCHAR szUrl[MAX_URL_STRING]; TCHAR szUrlNavNew[MAX_URL_STRING]; CLSID clsidBand; BOOL fShellSearchBand = FALSE; BOOL fRunInProcess = FALSE; IUnknown* punkSite = m_punkSite ? m_punkSite : (IUnknown*)m_spClientSite; if( !punkSite ) return E_UNEXPECTED ; // Determine band class and whether the band supports navigation if( (fShellSearchBand = (S_OK == _IsShellSearchBand( guidSearch ))) ) { if (SHRestricted(REST_NOFIND) && IsEqualGUID(guidSearch, SRCID_SFileSearch)) return E_ACCESSDENIED; clsidBand = CLSID_FileSearchBand; } else { clsidBand = CLSID_SearchBand; // we need to navigate to a search URL, grope the registry for that special URL if( FAILED( (hr= GetSearchURLs( guidSearch, szUrl, ARRAYSIZE(szUrl), szUrlNavNew, ARRAYSIZE(szUrlNavNew), &fRunInProcess )) ) ) return hr; } // FEATURE [scotthan]: this function will fail unless invoked from within a browser. // This sits fine for now since SearchAsst is designed as a browser band. IWebBrowser2* pwb2; hr = IUnknown_QueryServiceForWebBrowserApp(punkSite, IID_PPV_ARG(IWebBrowser2, &pwb2)); if (SUCCEEDED(hr)) { SA_BSTRGUID bstrClsid; InitFakeBSTR(&bstrClsid, clsidBand); VARIANT var; var.bstrVal = bstrClsid.wsz; var.vt = VT_BSTR; VARIANT varNil = {0}; // show a search bar hr = pwb2->ShowBrowserBar(&var, &varNil, &varNil); if( SUCCEEDED( hr ) ) { VARIANT varFlags; if( fShellSearchBand ) { hr= _ShowShellSearchBand( pwb2, guidSearch ); } else { varFlags.vt = VT_I4; varFlags.lVal = navBrowserBar; var.bstrVal = SysAllocString( szUrl ); var.vt = VT_BSTR ; // navigate the search bar to the correct url hr = pwb2->Navigate2(&var, &varFlags, &varNil, &varNil, &varNil); SysFreeString(var.bstrVal); if( SUCCEEDED( hr ) ) { hr = pwb2->put_Visible( TRUE ) ; } } } pwb2->Release(); } return hr; } STDMETHODIMP CSearchAssistantOC::SetSite( IUnknown* punkSite ) { ATOMICRELEASE(m_punkSite); if ((m_punkSite = punkSite) != NULL) m_punkSite->AddRef() ; return S_OK ; } STDMETHODIMP CSearchAssistantOC::GetSite( REFIID riid, void** ppvSite ) { if( !m_punkSite ) return E_FAIL ; return m_punkSite->QueryInterface( riid, ppvSite ) ; }