windows-nt/Source/XPSP1/NT/shell/shdocvw/srchasst.cpp
2020-09-26 16:20:57 +08:00

2082 lines
56 KiB
C++

#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 <wininet.h>
/////////////////////////////////////////////////////////////////////////////
// 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()
{
InterlockedIncrement(&_cRef);
return _cRef;
}
STDMETHODIMP_(ULONG) CSearch::Release()
{
if (InterlockedDecrement(&_cRef) > 0)
return _cRef;
delete this;
return 0;
}
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()
{
InterlockedIncrement(&_cRef);
return _cRef;
}
STDMETHODIMP_(ULONG) CSearchCollection::Release()
{
if (InterlockedDecrement(&_cRef) > 0)
return _cRef;
delete this;
return 0;
}
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;
#if 0
// should we worry about this one?
case VT_BSTR:
#endif
}
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<CSearchAssistantOC>::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_IServiceProvider, (void**)&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;
}
void GetPerLocalePath(WCHAR *pwszKeyName, int cchKeyName)
{
ASSERT(cchKeyName >= (ARRAYSIZE(c_wszSearchProps) + 1));
StrCpyNW(pwszKeyName, c_wszSearchProps, cchKeyName);
*(pwszKeyName + (ARRAYSIZE(c_wszSearchProps) - 1)) = L'\\';
GetWebLocaleAsRFC1766(pwszKeyName + ARRAYSIZE(c_wszSearchProps),
cchKeyName - (ARRAYSIZE(c_wszSearchProps)));
}
STDMETHODIMP CSearchAssistantOC::PutProperty(VARIANT_BOOL bPerLocale, BSTR bstrName, BSTR bstrValue)
{
HRESULT hr;
if (IsTrustedSite())
{
HKEY hkey;
LPCWSTR pwszKeyName;
WCHAR wszKeyName[MAX_PATH];
DWORD dwDisposition;
if (bPerLocale)
{
GetPerLocalePath(wszKeyName, ARRAYSIZE(wszKeyName));
pwszKeyName = wszKeyName;
}
else
{
pwszKeyName = c_wszSearchProps;
}
if (RegCreateKeyExW(HKEY_CURRENT_USER, pwszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_WRITE, 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);
}
hr = S_OK;
}
else
{
hr = E_ACCESSDENIED;
}
return hr;
}
STDMETHODIMP CSearchAssistantOC::GetProperty(VARIANT_BOOL bPerLocale, BSTR bstrName, BSTR *pbstrValue)
{
HRESULT hr;
if (NULL != pbstrValue)
{
*pbstrValue = NULL;
if (IsTrustedSite())
{
HKEY hkey;
LPCWSTR pwszKeyName;
WCHAR wszKeyName[MAX_PATH];
if (bPerLocale)
{
GetPerLocalePath(wszKeyName, ARRAYSIZE(wszKeyName));
pwszKeyName = wszKeyName;
}
else
{
pwszKeyName = c_wszSearchProps;
}
if (RegOpenKeyExW(HKEY_CURRENT_USER, pwszKeyName, 0, KEY_READ, &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);
}
hr = S_OK;
}
else
{
hr = E_ACCESSDENIED;
}
}
else
{
hr = E_INVALIDARG;
}
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_READ, &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_READ, &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_IShellDispatch2, (void**)&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) Create security manager
// 4) Check if doc URL zone is local, if so everything's S_OK
// 5) 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);
IInternetSecurityManager *pSecMgr;
if (SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager,
NULL,
CLSCTX_INPROC_SERVER,
IID_IInternetSecurityManager,
(void **)&pSecMgr)))
{
ASSERT(pSecMgr);
DWORD dwZoneID = URLZONE_UNTRUSTED;
if (SUCCEEDED(pSecMgr->MapUrlToZone(bstrDocUrl, &dwZoneID, 0)))
{
if (dwZoneID == URLZONE_LOCAL_MACHINE)
hr = S_OK;
}
pSecMgr->Release();
}
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_IMultiLanguage2, (void**)&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_IShellDispatch2, (void**)&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\browband.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_READ, &hkey )) != ERROR_SUCCESS )
return HRESULT_FROM_WIN32( dwErr ) ;
hr = E_FAIL ;
for( int i = 0;
wnsprintf( szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), i ),
RegOpenKey(hkey, szSubKey, &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_IFileSearchBand, (LPVOID*)&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( T2W( 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 ) ;
}