|
|
//
// Shell UI Control Class (CShellUIHelper)
//
// Sample code : shell\docs\shuiod.htm
//
// This is the source code of the ShellUI control class. You can put an instance
// of ShellUI control on any HTML pages then
//
// The key thing is it always bring up some UI and never alter the system
// silently (without the User's interaction). By doing this, we can expose
// shell features as much as we want without worrying about the security
// problem (which automation interface has).
//
// This control also allow us to provide many configuration type UI (such as
// "Customize your IE page") as well as rich web-view on some folders
// (especially control panel ;-) without paying the cost of data-binding.
//
#include "priv.h"
#include "sccls.h"
#ifndef UNIX
#include <webcheck.h>
#else
#include <subsmgr.h>
#endif
#include "favorite.h"
#include "caggunk.h"
#include "resource.h"
#include "channel.h"
#include "chanmgr.h"
#include "chanmgrp.h"
#include "iforms.h"
#include "dspsprt.h"
#include "impexp.h" // needed for RunImportExportWizard()
#include "iforms.h"
//#include "cobjsafe.h" // CObjectSafety
#include "shvocx.h" // WrapSpecialUrl()
#include <mluisupp.h>
#define REG_DESKCOMP_SCHEME TEXT("Software\\Microsoft\\Internet Explorer\\Desktop\\Scheme")
#define REG_VAL_SCHEME_DISPLAY TEXT("Display")
#define REG_VAL_GENERAL_WALLPAPER TEXT("Wallpaper")
#define REG_VAL_GENERAL_TILEWALLPAPER TEXT("TileWallpaper")
#define REG_DESKCOMP_GENERAL TEXT("Software\\Microsoft\\Internet Explorer\\Desktop%sGeneral")
STDAPI SHAddSubscribeFavorite (HWND hwnd, LPCWSTR pwszURL, LPCWSTR pwszName, DWORD dwFlags, SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO* pInfo);
// move it to shdocvw.h
UINT IE_ErrorMsgBox(IShellBrowser* psb, HWND hwndOwner, HRESULT hrError, LPCWSTR szError, LPCTSTR pszURLparam, UINT idResource, UINT wFlags);
#define DM_SHUIOC DM_TRACE
LONG GetSearchFormatString(DWORD dwIndex, LPTSTR psz, DWORD cbpsz);
HRESULT TargetQueryService(IUnknown *punk, REFIID riid, void **ppvObj);
EXTERN_C const SA_BSTRGUID s_sstrSearch; EXTERN_C const SA_BSTRGUID s_sstrFailureUrl;
class CShellUIHelper : public CAggregatedUnknown, public IObjectWithSite, public IObjectSafety, public IShellUIHelper, // dual, IDispatch
public IDispatchEx, protected CImpIDispatch { // IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj) { return CAggregatedUnknown::QueryInterface(riid, ppvObj);}; STDMETHODIMP_(ULONG) AddRef(void) { return CAggregatedUnknown::AddRef();}; STDMETHODIMP_(ULONG) Release(void) { return CAggregatedUnknown::Release();};
// IObjectWithSite
STDMETHODIMP SetSite(IUnknown *pUnkSite); STDMETHODIMP GetSite(REFIID riid, void **ppvSite);
// IObjectSafety
STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions); STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions);
// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT * pctinfo); STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo); STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid); STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr);
// IDispatchEx
STDMETHODIMP GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid); STDMETHODIMP InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller); STDMETHODIMP DeleteMemberByName(BSTR bstr, DWORD grfdex); STDMETHODIMP DeleteMemberByDispID(DISPID id); STDMETHODIMP GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex); STDMETHODIMP GetMemberName(DISPID id, BSTR *pbstrName); STDMETHODIMP GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid); STDMETHODIMP GetNameSpaceParent(IUnknown **ppunk);
// IShellUIHelper
STDMETHODIMP Execute(); STDMETHODIMP ResetSafeMode(); STDMETHODIMP ResetFirstBootMode(); STDMETHODIMP RefreshOfflineDesktop(); STDMETHODIMP AddFavorite(BSTR strURL, VARIANT *Title); STDMETHODIMP AddChannel(BSTR bstrURL); STDMETHODIMP AddDesktopComponent(BSTR strURL, BSTR strType, VARIANT *Left, VARIANT *Top, VARIANT *Width, VARIANT *Height); STDMETHODIMP IsSubscribed(BSTR bstrURL, VARIANT_BOOL* pBool); STDMETHODIMP NavigateAndFind(BSTR URL, BSTR strQuery, VARIANT* varTargetFrame); STDMETHODIMP ImportExportFavorites(VARIANT_BOOL fImport, BSTR strImpExpPath); STDMETHODIMP AutoCompleteSaveForm(VARIANT *Form); STDMETHODIMP AutoScan(BSTR strSearch, BSTR strFailureUrl, VARIANT* pvarTargetFrame); STDMETHODIMP AutoCompleteAttach(VARIANT *Form); STDMETHODIMP ShowBrowserUI(BSTR bstrName, VARIANT *pvarIn, VARIANT *pvarOut);
HRESULT v_InternalQueryInterface(REFIID riid, void ** ppvObj);
CShellUIHelper(IUnknown* punkAgg); ~CShellUIHelper();
inline IDispatch *GetExternalDispatch() { return _pExternalDispEx ? _pExternalDispEx : _pExternalDisp; }
void SetExternalDispatch(IDispatch *pExternalDisp) { ATOMICRELEASE(_pExternalDisp); ATOMICRELEASE(_pExternalDispEx);
// If we were passed an IDispatch to delegate to then we need to
// see if it can do IDispatchEx so we can support it as well,
// otherwise we just fall back to good ole IDispatch.
if (pExternalDisp) { if (FAILED(pExternalDisp->QueryInterface(IID_IDispatchEx, (void **)&_pExternalDispEx))) { _pExternalDisp = pExternalDisp; _pExternalDisp->AddRef(); } } }
STDMETHODIMP ShowChannel(IChannelMgrPriv *pChMgrPriv, LPWSTR pwszURL, HWND hwnd); HWND _GetOwnerWindow(); HRESULT _ConnectToTopLevelConnectionPoint(BOOL fConnect, IUnknown* punk); STDMETHODIMP _DoFindOnPage(IDispatch* pdisp);
friend HRESULT CShellUIHelper_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi); friend HRESULT CShellUIHelper_CreateInstance2(IUnknown** ppunk, REFIID riid, IUnknown *pSite, IDispatch *pExternalDisp);
DWORD _dwSafety; // Cached pointers, hwnd
IUnknown* _punkSite; // site pointer
IDispatchEx* _pExternalDispEx; IDispatch* _pExternalDisp; DWORD _dwcpCookie; BOOL _fWaitingToFindText; BSTR _bstrQuery; VOID * _pvIntelliForms; };
STDAPI CShellUIHelper_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi) { HRESULT hres = E_OUTOFMEMORY; CShellUIHelper* psuo = new CShellUIHelper(punkOuter); if (psuo) { *ppunk = psuo->_GetInner(); hres = S_OK; } return hres; }
HRESULT CShellUIHelper_CreateInstance2(IUnknown** ppunk, REFIID riid, IUnknown *pSite, IDispatch *pExternalDisp) { HRESULT hres = E_OUTOFMEMORY; CShellUIHelper* psuo = new CShellUIHelper(NULL); if (psuo) { hres = psuo->QueryInterface(riid, (void **)ppunk); psuo->Release();
if (SUCCEEDED(hres)) { psuo->SetSite(pSite); psuo->SetExternalDispatch(pExternalDisp); } }
return hres; }
CShellUIHelper::CShellUIHelper(IUnknown* punkAgg) : CAggregatedUnknown(punkAgg), CImpIDispatch(LIBID_SHDocVw, 1, 1, IID_IShellUIHelper) { DllAddRef(); _fWaitingToFindText = FALSE; _bstrQuery = NULL; }
CShellUIHelper::~CShellUIHelper() {
ReleaseIntelliForms(_pvIntelliForms);
if (_punkSite) SetSite(NULL); // In case the parent did not clean it up.
if (_bstrQuery) SysFreeString(_bstrQuery); ATOMICRELEASE(_pExternalDisp); ATOMICRELEASE(_pExternalDispEx);
DllRelease(); }
HRESULT CShellUIHelper::v_InternalQueryInterface(REFIID riid, void ** ppvObj) { if (IsEqualIID(riid, IID_IDispatch) || IsEqualIID(riid, IID_IShellUIHelper)) { *ppvObj = SAFECAST(this, IShellUIHelper *); } else if (IsEqualIID(riid, IID_IObjectWithSite)) { *ppvObj = SAFECAST(this, IObjectWithSite *); } else if (IsEqualIID(riid, IID_IObjectSafety)) { *ppvObj = SAFECAST(this, IObjectSafety *); } else if (IsEqualIID(riid, IID_IDispatchEx)) { *ppvObj = SAFECAST(this, IDispatchEx *); } else { *ppvObj = NULL; return E_NOINTERFACE; }
AddRef(); return S_OK; }
HWND CShellUIHelper::_GetOwnerWindow() { HWND hwnd; HRESULT hres;
// this deals with NULL _punkSite and zeros hwnd on failure
IUnknown_GetWindow(_punkSite, &hwnd);
if (!hwnd) { //
// We get to this point if we are instantiated like this
// in jscript:
// foo = new ActiveXObject("Shell.UIControl");
// or vbscript:
// set foo = CreateObject("Shell.UIControl");
//
if (_punkSite) { IServiceProvider *pSP = NULL; IOleWindow *pOleWindow = NULL; hres = _punkSite->QueryInterface(IID_IServiceProvider, (void **)&pSP);
if (SUCCEEDED(hres)) { ASSERT(pSP);
hres = pSP->QueryService(SID_SContainerDispatch, IID_IOleWindow, (void **)&pOleWindow); if (SUCCEEDED(hres)) { pOleWindow->GetWindow(&hwnd); pOleWindow->Release(); } pSP->Release(); } } else { // It's either this or the functions we call should take NULL for HWNDs.
hwnd = GetDesktopWindow(); } }
return hwnd; }
HRESULT CShellUIHelper::_ConnectToTopLevelConnectionPoint(BOOL fConnect, IUnknown* punk) { HRESULT hr = E_INVALIDARG; IConnectionPointContainer* pcpContainer; IServiceProvider* psp; IServiceProvider* psp2;
ASSERT(punk); if (punk) { hr = punk->QueryInterface(IID_PPV_ARG(IServiceProvider, &psp));
if (SUCCEEDED(hr)) { hr = psp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void**) &psp2);
if (SUCCEEDED(hr)) { hr = psp2->QueryService(SID_SWebBrowserApp, IID_IConnectionPointContainer, (void **)&pcpContainer);
if (SUCCEEDED(hr)) { //to avoid ambiguous reference
IDispatch* pdispThis; this->QueryInterface(IID_IDispatch, (void **)&pdispThis); ASSERT(pdispThis); hr = ConnectToConnectionPoint(pdispThis, DIID_DWebBrowserEvents2, fConnect, pcpContainer, &_dwcpCookie, NULL); pcpContainer->Release(); pdispThis->Release(); } psp2->Release(); } psp->Release(); } } return hr; }
HRESULT CShellUIHelper::SetSite(IUnknown *punkSite) { if (!_punkSite) { _ConnectToTopLevelConnectionPoint(TRUE, punkSite); } else { ASSERT(punkSite == NULL); //if we've already got _punkSite, we'd better be releasing the site
_ConnectToTopLevelConnectionPoint(FALSE, _punkSite); ATOMICRELEASE(_punkSite); } _punkSite = punkSite;
if (_punkSite) _punkSite->AddRef();
return S_OK; }
HRESULT CShellUIHelper::GetSite(REFIID riid, void **ppvSite) { TraceMsg(DM_SHUIOC, "SHUO::GetSite called");
if (_punkSite) return _punkSite->QueryInterface(riid, ppvSite);
*ppvSite = NULL; return E_FAIL; }
STDMETHODIMP CShellUIHelper::GetInterfaceSafetyOptions(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions) { HRESULT hr = S_OK;
if (!pdwSupportedOptions || !pdwEnabledOptions) return E_POINTER;
if (IID_IDispatch == riid) { *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER; *pdwEnabledOptions = _dwSafety & INTERFACESAFE_FOR_UNTRUSTED_CALLER; } else { *pdwSupportedOptions = 0; *pdwEnabledOptions = 0; hr = E_NOINTERFACE; }
return hr; }
STDMETHODIMP CShellUIHelper::SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions) { HRESULT hr = S_OK; if (IID_IDispatch == riid) _dwSafety = dwOptionSetMask & dwEnabledOptions; else hr = E_NOINTERFACE;
return hr; }
struct SHUI_STRMAP { LPCTSTR psz; int id; };
int _MapStringToId(LPCTSTR pszStr, const SHUI_STRMAP* const psmap, int cel, int idDefault) { if (pszStr) { for (int i=0; i<cel ; i++) { if (StrCmpI(psmap[i].psz, pszStr) == 0) { return psmap[i].id; } } } return idDefault; }
LPCTSTR OptionalVariantToStr(VARIANT *pvar, LPTSTR pszBuf, UINT cchBuf) { if (pvar->vt == VT_BSTR && pvar->bstrVal) { SHUnicodeToTChar(pvar->bstrVal, pszBuf, cchBuf); return pszBuf; } *pszBuf = 0; return NULL; }
int OptionalVariantToInt(VARIANT *pvar, int iDefault) { VARIANT v; VariantInit(&v); if (SUCCEEDED(VariantChangeType(&v, pvar, 0, VT_I4))) { iDefault = v.lVal; // VariantClear(&v); // not needed, VT_I4 has no allocs
} return iDefault; }
BOOL OptionalVariantToBool(VARIANT *pvar, BOOL fDefault) { VARIANT v; VariantInit(&v); if (SUCCEEDED(VariantChangeType(&v, pvar, 0, VT_BOOL))) { fDefault = v.boolVal; } return fDefault; }
//------------------------------------------------------------------------
STDMETHODIMP CShellUIHelper::AddFavorite(/* [in] */ BSTR strURL, /* [in][optional] */ VARIANT *Title) { HRESULT hres = S_OK; LPITEMIDLIST pidl; BSTR bstrTemp = NULL;
if (IsSpecialUrl(strURL)) { bstrTemp = SysAllocString(strURL); if (bstrTemp) { hres = WrapSpecialUrl(&bstrTemp); if (SUCCEEDED(hres)) strURL = bstrTemp; } else hres = E_OUTOFMEMORY; }
if (SUCCEEDED(hres)) hres = IECreateFromPath(strURL, &pidl); if (SUCCEEDED(hres)) { TCHAR szTitle[MAX_PATH]; hres = ::AddToFavorites(_GetOwnerWindow(), pidl, OptionalVariantToStr(Title, szTitle, ARRAYSIZE(szTitle)), TRUE, NULL, NULL); ILFree(pidl); } if (bstrTemp) SysFreeString(bstrTemp); return hres; }
//------------------------------------------------------------------------
STDMETHODIMP CShellUIHelper::ShowChannel(IChannelMgrPriv *pChMgrPriv, LPWSTR pwszURL, HWND hwnd) { HRESULT hres = E_FAIL; IServiceProvider *pSP1 = NULL, *pSP2 = NULL; IWebBrowser2 *pWebBrowser2 = NULL;
if (_punkSite) { hres = _punkSite->QueryInterface(IID_IServiceProvider, (void **)&pSP1); if (SUCCEEDED(hres)) { ASSERT(pSP1); hres = pSP1->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void**)&pSP2); if (SUCCEEDED(hres)) { ASSERT(pSP2); hres = pSP2->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void**)&pWebBrowser2); ASSERT((SUCCEEDED(hres) && pWebBrowser2) || FAILED(hres)); pSP2->Release(); } pSP1->Release(); } }
if (FAILED(hres)) { hres = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IWebBrowser2, &pWebBrowser2)); }
if (SUCCEEDED(hres)) { ASSERT(pWebBrowser2); hres = pChMgrPriv->ShowChannel(pWebBrowser2, pwszURL, hwnd); pWebBrowser2->Release(); } return hres; }
STDMETHODIMP CShellUIHelper::AddChannel(BSTR bstrURL) { HRESULT hres; IChannelMgrPriv *pChMgrPriv;
TCHAR szURL[MAX_URL_STRING]; HWND hwnd;
if (!bstrURL) { return E_INVALIDARG; } hwnd = _GetOwnerWindow();
//
// As long as the underlying functions choke on NULL HWNDs then we may as well
// bail early.
//
if (hwnd) { if (!SHIsRestricted2W(hwnd, REST_NoChannelUI, NULL, 0) && !SHIsRestricted2W(hwnd, REST_NoAddingChannels, NULL, 0)) { StrCpyNW(szURL, bstrURL, ARRAYSIZE(szURL));
hres = JITCoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER, IID_IChannelMgrPriv, (void **)&pChMgrPriv, hwnd, FIEF_FLAG_FORCE_JITUI);
if (S_OK == hres) { ASSERT(pChMgrPriv); hres = pChMgrPriv->AddAndSubscribe(hwnd, bstrURL, NULL); if (hres == S_OK) { hres = ShowChannel(pChMgrPriv, bstrURL, hwnd); } else if (FAILED(hres)) { IE_ErrorMsgBox(NULL, hwnd, hres, NULL, szURL, IDS_CHANNEL_UNAVAILABLE, MB_OK| MB_ICONSTOP); hres = S_FALSE; } pChMgrPriv->Release(); } else if (SUCCEEDED(hres)) { hres = S_FALSE; // FAIL silently for now - throw dialog for indicating that reboot required if needed
} else { IE_ErrorMsgBox(NULL, hwnd, hres, NULL, szURL, IDS_FAV_UNABLETOCREATE, MB_OK| MB_ICONSTOP); hres = S_FALSE; } } else { hres = S_FALSE; // Failure code results in a script error.
} } else // !hwnd
{ hres = E_FAIL; } return hres; }
// A lot like GetHTMLDoc2, but only cares about window.external
STDMETHODIMP GetTopLevelBrowser(IUnknown *punk, IWebBrowser2 **ppwb2) { return IUnknown_QueryService(punk, SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, ppwb2)); }
STDMETHODIMP ZoneCheck(IUnknown *punkSite, BSTR bstrReqUrl) { 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 (!punkSite) 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(punkSite, &pHtmlDoc))) { ASSERT(pHtmlDoc); BSTR bstrDocUrl; if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl))) { ASSERT(bstrDocUrl); IInternetSecurityManager *pSecMgr;
HRESULT hrTmp = IUnknown_QueryService(punkSite, SID_SInternetSecurityManager, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr)); if (FAILED(hrTmp)) { hrTmp = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr)); } if (SUCCEEDED(hrTmp)) { ASSERT(pSecMgr); DWORD dwZoneID = URLZONE_UNTRUSTED; if (SUCCEEDED(pSecMgr->MapUrlToZone(bstrDocUrl, &dwZoneID, 0))) { if (dwZoneID == URLZONE_LOCAL_MACHINE) hr = S_OK; } if (hr != S_OK && bstrReqUrl) { BYTE reqSid[MAX_SIZE_SECURITY_ID], docSid[MAX_SIZE_SECURITY_ID]; DWORD cbReqSid = ARRAYSIZE(reqSid); DWORD cbDocSid = ARRAYSIZE(docSid);
if ( SUCCEEDED(pSecMgr->GetSecurityId(bstrReqUrl, reqSid, &cbReqSid, 0)) && SUCCEEDED(pSecMgr->GetSecurityId(bstrDocUrl, docSid, &cbDocSid, 0)) && (cbReqSid == cbDocSid) && (memcmp(reqSid, docSid, cbReqSid) == 0)) {
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; }
// This function checks to see if a navigation is happening from either internet
// or restricted url to LOCAL_MACHINE.
BOOL CanNavigateToUrlWithLocalMachineCheck(IUnknown *punkSite, BSTR pchurltarget) { BOOL bCanNavigate = FALSE;
// Get the DochostUI flags for the site.
IDocHostUIHandler *pIDocHostUI; if (SUCCEEDED(punkSite->QueryInterface(IID_PPV_ARG(IDocHostUIHandler, &pIDocHostUI)))) { DOCHOSTUIINFO dhInfo; if (SUCCEEDED(pIDocHostUI->GetHostInfo(&dhInfo))) { if (!(dhInfo.dwFlags & DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK)) bCanNavigate = TRUE; } pIDocHostUI->Release(); }
// If the DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK is set or if we failed to
// get the flags, do a check to see if the zone is elevated to local machine.
if (!bCanNavigate) { // Get the site's url.
IHTMLDocument2 *pHtmlDoc; if (SUCCEEDED(GetHTMLDoc2(punkSite, &pHtmlDoc))) { BSTR pchurlsource; if (SUCCEEDED(pHtmlDoc->get_URL(&pchurlsource))) { IInternetSecurityManager *pSecMgr; if (SUCCEEDED(IUnknown_QueryService(punkSite, SID_SInternetSecurityManager, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr))) || SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr)))) { DWORD dwZoneIDSource = URLZONE_UNTRUSTED; DWORD dwZoneIDTarget = URLZONE_LOCAL_MACHINE; DWORD dwFlags = PUAF_DEFAULT;
// Get zone of the source url.
if (!pchurlsource || IsSpecialUrl(pchurlsource)) { // Treat special Urls as restricted.
dwZoneIDSource = URLZONE_UNTRUSTED; } else if (!SUCCEEDED(pSecMgr->MapUrlToZone(pchurlsource, &dwZoneIDSource, 0))) { // If MapUrlToZone fails, treat the url as restricted.
dwZoneIDSource = URLZONE_UNTRUSTED; }
// Get zone of the target url
if (!SUCCEEDED(pSecMgr->MapUrlToZone(pchurltarget, &dwZoneIDTarget, 0))) { // If MapUrlToZone fails, treat the url as MyComputer. This is safe.
dwZoneIDTarget = URLZONE_LOCAL_MACHINE; }
// Check if there is a zone elevation.
if ((dwZoneIDSource != URLZONE_INTERNET && dwZoneIDSource != URLZONE_UNTRUSTED) || dwZoneIDTarget != URLZONE_LOCAL_MACHINE) { // There is no zone elevation.
bCanNavigate = TRUE; } pSecMgr->Release(); } SysFreeString(pchurlsource); } pHtmlDoc->Release(); } } return bCanNavigate; }
STDMETHODIMP CShellUIHelper::IsSubscribed(BSTR bstrURL, VARIANT_BOOL* pBool) { HRESULT hr;
if (!bstrURL || !pBool) { return E_INVALIDARG; }
hr = ZoneCheck(_punkSite, bstrURL);
if (SUCCEEDED(hr)) { ISubscriptionMgr *pSubscriptionMgr;
hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ISubscriptionMgr, &pSubscriptionMgr)); if (SUCCEEDED(hr)) { ASSERT(pSubscriptionMgr);
BOOL tmpBool; hr = pSubscriptionMgr->IsSubscribed(bstrURL, &tmpBool); *pBool = tmpBool ? VARIANT_TRUE : VARIANT_FALSE; pSubscriptionMgr->Release(); } }
return hr; }
/****************************************************************************
* * AddDesktopComponentA - Adds a component to the desktop * * ENTRY: * hwnd - the parent for all UI * pszUrlA - the URL of the component * iCompType - one of COMP_TYPE_* * iLeft, iTop, iWidth, iHeight - dimensions of the component * dwFlags - additional flags * * RETURNS: * TRUE on success * ****************************************************************************/ BOOL AddDesktopComponentW(HWND hwnd, LPCWSTR pszUrl, int iCompType, int iLeft, int iTop, int iWidth, int iHeight, DWORD dwFlags) { COMPONENT Comp; BOOL fRet = FALSE; HRESULT hres;
Comp.dwSize = sizeof(Comp);
//
// Build the pcomp structure.
//
Comp.dwID = -1; Comp.iComponentType = iCompType; Comp.fChecked = TRUE; Comp.fDirty = FALSE; Comp.fNoScroll = FALSE; Comp.dwSize = SIZEOF(Comp); Comp.cpPos.dwSize = SIZEOF(COMPPOS); Comp.cpPos.iLeft = iLeft; Comp.cpPos.iTop = iTop; Comp.cpPos.dwWidth = iWidth; Comp.cpPos.dwHeight = iHeight; Comp.cpPos.izIndex = COMPONENT_TOP; Comp.cpPos.fCanResize = TRUE; Comp.cpPos.fCanResizeX = TRUE; Comp.cpPos.fCanResizeY = TRUE; Comp.cpPos.iPreferredLeftPercent = 0; Comp.cpPos.iPreferredTopPercent = 0; StrCpyNW(Comp.wszSource, pszUrl, ARRAYSIZE(Comp.wszSource)); StrCpyNW(Comp.wszSubscribedURL, pszUrl, ARRAYSIZE(Comp.wszSubscribedURL)); StrCpyNW(Comp.wszFriendlyName, pszUrl, ARRAYSIZE(Comp.wszFriendlyName)); Comp.dwCurItemState = IS_NORMAL;
IActiveDesktop * piad;
//
// Add it to the system.
//
hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IActiveDesktop, &piad)); if (SUCCEEDED(hres)) { dwFlags |= DTI_ADDUI_POSITIONITEM; piad->AddDesktopItemWithUI(hwnd, &Comp, dwFlags); piad->Release(); fRet = TRUE; }
return fRet; }
//------------------------------------------------------------------------
STDMETHODIMP CShellUIHelper::AddDesktopComponent(BSTR strURL, BSTR strType, /* [optional, in] */ VARIANT *Left, /* [optional, in] */ VARIANT *Top, /* [optional, in] */ VARIANT *Width, /* [optional, in] */ VARIANT *Height) { #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
HRESULT hres; int iType;
if (StrCmpIW(strType, L"image")==0) { iType = COMP_TYPE_PICTURE; } else if (StrCmpIW(strType, L"website")==0) { iType = COMP_TYPE_WEBSITE; } else { iType = 0; }
if (iType) { AddDesktopComponentW(_GetOwnerWindow(), strURL, iType, OptionalVariantToInt(Left, -1), OptionalVariantToInt(Top, -1), OptionalVariantToInt(Width, -1), OptionalVariantToInt(Height, -1), DTI_ADDUI_DISPSUBWIZARD); hres = S_OK; } else { hres = E_INVALIDARG; } return hres; #else // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
return E_INVALIDARG;
#endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
} void RemoveDefaultWallpaper(); STDMETHODIMP CShellUIHelper::ResetFirstBootMode() { #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
if (MLShellMessageBox( _GetOwnerWindow(), MAKEINTRESOURCE(IDS_CONFIRM_RESETFLAG), MAKEINTRESOURCE(IDS_TITLE), MB_YESNO | MB_ICONQUESTION) == IDYES) { RemoveDefaultWallpaper(); return S_OK; }
#endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
return S_FALSE; }
// Little helper function used to change the safemode state
void SetSafeMode(DWORD dwFlags) { IActiveDesktopP * piadp;
HRESULT hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IActiveDesktopP, &piadp)); if (SUCCEEDED(hres)) { piadp->SetSafeMode(dwFlags); piadp->Release(); } }
STDMETHODIMP CShellUIHelper::ResetSafeMode() { #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
if ((ZoneCheck(_punkSite, NULL) == S_OK) || (MLShellMessageBox( _GetOwnerWindow(), MAKEINTRESOURCE(IDS_CONFIRM_RESET_SAFEMODE), MAKEINTRESOURCE(IDS_TITLE), MB_YESNO | MB_ICONQUESTION) == IDYES)) { SetSafeMode(SSM_CLEAR | SSM_REFRESH); return S_OK; }
#endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
return S_FALSE; }
STDMETHODIMP CShellUIHelper::RefreshOfflineDesktop() { #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
IADesktopP2 * piad;
HRESULT hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IADesktopP2, &piad)); if (SUCCEEDED(hres)) { piad->UpdateAllDesktopSubscriptions(); piad->Release(); } #endif // #ifndef DISABLE_ACTIVEDESKTOP_FOR_UNIX
return S_OK; }
STDMETHODIMP CShellUIHelper::GetTypeInfoCount(UINT * pctinfo) { return E_NOTIMPL; }
STDMETHODIMP CShellUIHelper::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo) { return E_NOTIMPL; }
STDMETHODIMP CShellUIHelper::GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid) { HRESULT hr = E_FAIL;
// First let our host get a crack at this method
IDispatch *pDisp = GetExternalDispatch();
if (pDisp) { hr = pDisp->GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); if (SUCCEEDED(hr)) { if (rgdispid[0] > 0) { // Offset there dispid
rgdispid[0] += DISPID_SHELLUIHELPERLAST; } } }
if (FAILED(hr)) { // Our host didn't support it so we'll see if it's one of ours.
hr = CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); }
return hr; }
HRESULT CShellUIHelper::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT * pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr) { HRESULT hr = DISP_E_MEMBERNOTFOUND; if ((dispidMember > 0) && (dispidMember <= DISPID_SHELLUIHELPERLAST)) { hr = CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); } else if (_fWaitingToFindText && (dispidMember == DISPID_DOCUMENTCOMPLETE)) { ASSERT(pdispparams->rgvarg[1].vt == VT_DISPATCH);
_fWaitingToFindText = FALSE; hr = _DoFindOnPage(pdispparams->rgvarg[1].pdispVal); } else { IDispatch *pDisp = GetExternalDispatch(); if (pDisp) { if (dispidMember > 0) { // Fixup the offset we added in GetIDsOfNames
dispidMember -= DISPID_SHELLUIHELPERLAST; } hr = pDisp->Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); } }
return hr; }
STDMETHODIMP CShellUIHelper::GetDispID(BSTR bstrName, DWORD grfdex, DISPID *pid) { HRESULT hr = E_FAIL; LCID lcid = GetSystemDefaultLCID();
// First let our host get a crack at this method via IDispatchEx or IDispatch
if (_pExternalDispEx) { hr = _pExternalDispEx->GetDispID(bstrName, grfdex, pid); } else if (_pExternalDisp) { hr = _pExternalDisp->GetIDsOfNames(IID_NULL, &bstrName, 1, lcid, pid); }
if (SUCCEEDED(hr)) { if (*pid > 0) { *pid += DISPID_SHELLUIHELPERLAST; } } else { // Our host didn't support it so we'll see if it's one of ours.
hr = CImpIDispatch::GetIDsOfNames(IID_NULL, &bstrName, 1, lcid, pid); }
return hr; }
STDMETHODIMP CShellUIHelper::InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { HRESULT hr = DISP_E_MEMBERNOTFOUND; UINT ArgErr; // inetsdk says this isn't used here
// First see if it's ours
if ((id > 0) && (id <= DISPID_SHELLUIHELPERLAST)) { hr = CImpIDispatch::Invoke(id, IID_NULL, lcid, wFlags, pdp, pvarRes, pei, &ArgErr); } else { if (id > 0) { id -= DISPID_SHELLUIHELPERLAST; } // otherwise try external IDispatchEx
if (_pExternalDispEx) { hr = _pExternalDispEx->InvokeEx(id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); } // finally try the external IDispatch
else if (_pExternalDisp) { hr = _pExternalDisp->Invoke(id, IID_NULL, lcid, wFlags, pdp, pvarRes, pei, &ArgErr); } } return hr; }
STDMETHODIMP CShellUIHelper::DeleteMemberByName(BSTR bstr, DWORD grfdex) { HRESULT hr = E_NOTIMPL; if (_pExternalDispEx) { hr = _pExternalDispEx->DeleteMemberByName(bstr, grfdex); }
return hr; } STDMETHODIMP CShellUIHelper::DeleteMemberByDispID(DISPID id) { HRESULT hr = E_NOTIMPL; if (_pExternalDispEx) { hr = _pExternalDispEx->DeleteMemberByDispID(id); }
return hr; } STDMETHODIMP CShellUIHelper::GetMemberProperties(DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) { HRESULT hr = E_NOTIMPL; if (_pExternalDispEx) { hr = _pExternalDispEx->GetMemberProperties(id, grfdexFetch, pgrfdex); }
return hr; } STDMETHODIMP CShellUIHelper::GetMemberName(DISPID id, BSTR *pbstrName) { HRESULT hr = E_NOTIMPL; if (_pExternalDispEx) { hr = _pExternalDispEx->GetMemberName(id, pbstrName); }
return hr; }
STDMETHODIMP CShellUIHelper::GetNextDispID(DWORD grfdex, DISPID id, DISPID *pid) { HRESULT hr = E_NOTIMPL; if (_pExternalDispEx) { hr = _pExternalDispEx->GetNextDispID(grfdex, id, pid); }
return hr; } STDMETHODIMP CShellUIHelper::GetNameSpaceParent(IUnknown **ppunk) { HRESULT hr = E_NOTIMPL; if (_pExternalDispEx) { hr = _pExternalDispEx->GetNameSpaceParent(ppunk); }
return hr; }
int GetIntFromReg(HKEY hKey, LPCTSTR lpszSubkey, LPCTSTR lpszNameValue, int iDefault) { TCHAR szValue[20]; DWORD dwSizeofValueBuff = SIZEOF(szValue); int iRetValue = iDefault; DWORD dwType;
if ((SHGetValue(hKey, lpszSubkey, lpszNameValue, &dwType,(LPBYTE)szValue, &dwSizeofValueBuff) == ERROR_SUCCESS) && dwSizeofValueBuff) { if (dwType == REG_SZ) { iRetValue = (int)StrToInt(szValue); } }
return iRetValue; }
void GetRegLocation(LPTSTR lpszResult, DWORD cchResult, LPCTSTR lpszKey, LPCTSTR lpszScheme) { TCHAR szSubkey[MAX_PATH]; DWORD dwDataLength = sizeof(szSubkey) - 2 * sizeof(TCHAR); DWORD dwType;
StrCpyN(szSubkey, TEXT("\\"), ARRAYSIZE(szSubkey)); if (lpszScheme) StrCatBuff(szSubkey, lpszScheme, ARRAYSIZE(szSubkey)); else SHGetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_DISPLAY, &dwType, (LPBYTE)(szSubkey) + sizeof(TCHAR), &dwDataLength); if (szSubkey[1]) StrCatBuff(szSubkey, TEXT("\\"), ARRAYSIZE(szSubkey));
wnsprintf(lpszResult, cchResult, lpszKey, szSubkey); }
#define c_szWallpaper REG_VAL_GENERAL_WALLPAPER
void RemoveDefaultWallpaper() { // Read the Wallpaper from the Old location.
TCHAR szOldWallpaper[MAX_PATH]; DWORD dwType; DWORD dwSize = SIZEOF(szOldWallpaper); if (SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP, c_szWallpaper, &dwType, szOldWallpaper, &dwSize) != ERROR_SUCCESS) szOldWallpaper[0] = TEXT('\0');
// Read the wallpaper style
DWORD dwWallpaperStyle = GetIntFromReg(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP, REG_VAL_GENERAL_TILEWALLPAPER, WPSTYLE_TILE);
TCHAR szDeskcomp[MAX_PATH]; GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_GENERAL, NULL);
// Set the old wallpaper into the new location.
SHSetValue(HKEY_CURRENT_USER, szDeskcomp, c_szWallpaper, REG_SZ, (LPBYTE)szOldWallpaper, SIZEOF(szOldWallpaper));
// 98/08/14 vtan: This used to write out a REG_DWORD. It should've
// written out a REG_SZ.
TCHAR szWallpaperStyle[2];
(TCHAR*)StrCpyN(szWallpaperStyle, TEXT("0"), ARRAYSIZE(szWallpaperStyle)); szWallpaperStyle[0] += static_cast<TCHAR>(dwWallpaperStyle & WPSTYLE_MAX);
// Set the old wallpaper style into the new location.
SHSetValue(HKEY_CURRENT_USER, szDeskcomp, REG_VAL_GENERAL_TILEWALLPAPER, REG_SZ, (LPBYTE)szWallpaperStyle, SIZEOF(szWallpaperStyle));
// 98/08/14 vtan #196226: Moved the create instance of IActiveDesktop
// to here from entry of the function. When the instance is created the
// registry information is cached in the member variable data. The
// registry information for the wallpaper is then changed behind the
// object instance and ApplyChanges() is called on STALE information.
// By deferring the object instantiation to after the registry changes
// the changes are applied correctly.
IActiveDesktop * piad; HRESULT hres = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IActiveDesktop, &piad)); if (SUCCEEDED(hres)) { piad->ApplyChanges(AD_APPLY_FORCE | AD_APPLY_HTMLGEN | AD_APPLY_REFRESH); piad->Release(); } }
HRESULT GetTargetFrame(IUnknown* _punkSite, BSTR bstrFrame, IWebBrowser2** ppunkTargetFrame) { IWebBrowser2 * pwb2; HRESULT hr = GetTopLevelBrowser(_punkSite, &pwb2);
*ppunkTargetFrame = NULL;
if (SUCCEEDED(hr)) { ITargetFrame2 * pOurTargetFrame; IUnknown * punkTargetFrame = NULL;
// See if there is an existing frame with the specified target name
hr = TargetQueryService(pwb2, IID_PPV_ARG(ITargetFrame2, &pOurTargetFrame)); if (SUCCEEDED(hr)) { hr = pOurTargetFrame->FindFrame(bstrFrame, FINDFRAME_JUSTTESTEXISTENCE, &punkTargetFrame); if (SUCCEEDED(hr) && punkTargetFrame) // SUCCEEDED with NULL punkTargetFrame implies bstrFrame is "_blank" (since we specified FINDFRAME_JUSTTESTEXISTENCE)
{ // yes, we found a frame with that name. QI for the automation
// interface on that frame.
hr = punkTargetFrame->QueryInterface(IID_PPV_ARG(IWebBrowser2, ppunkTargetFrame)); punkTargetFrame->Release(); } pOurTargetFrame->Release(); } pwb2->Release(); } return hr; }
// NavigateAndFind
// 1. navigate the specified target frame to the specified url
// 2. set _fWaitingToFindText so that on DocumentComplete,
// mimic the find dialog and select/highlight the specified text
STDMETHODIMP CShellUIHelper::NavigateAndFind(BSTR URL, BSTR strQuery, VARIANT* varTargetFrame) { HRESULT hr; IWebBrowser2 * pwb2 = NULL; BSTR bstrFrameSrc = NULL;
if (_bstrQuery) SysFreeString(_bstrQuery); _bstrQuery = SysAllocString(strQuery); hr = IsSpecialUrl(URL) ? E_FAIL: S_OK; // Security: Don't allow javascript on one web page
// to automatically execute in the zone
// of the target frame URL.
if (SUCCEEDED(hr) && varTargetFrame && (varTargetFrame->vt == VT_BSTR) && varTargetFrame->bstrVal) { hr = GetTargetFrame(_punkSite, varTargetFrame->bstrVal, &pwb2); // GetTargetFrame can return NULL pwb2 on S_OK (when bstrVal is "_blank")
if (SUCCEEDED(hr) && pwb2) { hr = pwb2->get_LocationURL(&bstrFrameSrc); if (SUCCEEDED(hr)) { IHTMLDocument2 *pHtmlDoc; if (SUCCEEDED(GetHTMLDoc2(_punkSite, &pHtmlDoc))) { BSTR bstrDocUrl; if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl))) { hr = AccessAllowed(_punkSite, bstrDocUrl, bstrFrameSrc) ? S_OK : E_ACCESSDENIED;
if(!IsSpecialUrl(URL) && hr == E_ACCESSDENIED) { // For non-script navigates check policy
DWORD dwPolicy = 0; DWORD dwContext = 0; if( SUCCEEDED(ZoneCheckUrlEx(bstrDocUrl, &dwPolicy, sizeof(dwPolicy), &dwContext, sizeof(dwContext), URLACTION_HTML_SUBFRAME_NAVIGATE, 0, NULL)) && GetUrlPolicyPermissions(dwPolicy) == URLPOLICY_ALLOW) { hr = S_OK; } } SysFreeString(bstrDocUrl); } pHtmlDoc->Release(); } SysFreeString(bstrFrameSrc); } pwb2->Release(); pwb2 = NULL; } }
// Don't allow access to MyComputer zone from non-MyComputer zone.
if (SUCCEEDED(hr) && !CanNavigateToUrlWithLocalMachineCheck(_punkSite, URL)) hr = E_ACCESSDENIED;
if (SUCCEEDED(hr)) hr = GetTopLevelBrowser(_punkSite, &pwb2);
if (SUCCEEDED(hr)) { _fWaitingToFindText = TRUE; pwb2->Navigate(URL, PVAREMPTY, varTargetFrame, PVAREMPTY, PVAREMPTY); pwb2->Release(); }
//script runtime error protection
return SUCCEEDED(hr) ? S_OK : S_FALSE; }
// AutoScan
//
// Takes the search string and tries to navigate to www.%s.com, www.%s.org etc. If all of
// these fail then we navigate to pvarTargetFrame.
//
STDMETHODIMP CShellUIHelper::AutoScan ( BSTR strSearch, // String to autoscan
BSTR strFailureUrl, // url to display is search fails
VARIANT* pvarTargetFrame // [optional] target frame
) { HRESULT hr = E_FAIL; IWebBrowser2* pwb2;
// Don't bother autoscanning if there are extended characters in the search string
if (!HasExtendedChar(strSearch)) { //first, check to see if the url is trying to spoof /1 security
hr = IsSpecialUrl(strFailureUrl) ? E_FAIL : S_OK;
if (SUCCEEDED(hr)) { LPWSTR pszTarget = (pvarTargetFrame && pvarTargetFrame->vt == VT_BSTR && pvarTargetFrame->bstrVal) ? pvarTargetFrame->bstrVal : L"_main";
hr = GetTargetFrame(_punkSite, pszTarget, &pwb2); // GetTargetFrame can return NULL pwb2 on S_OK (when bstrVal is "_blank")
if (!pwb2) hr = E_FAIL; if (SUCCEEDED(hr)) { BSTR bstrFrameSrc = NULL; hr = pwb2->get_LocationURL(&bstrFrameSrc); if (SUCCEEDED(hr)) { IHTMLDocument2 *pHtmlDoc; if (SUCCEEDED(GetHTMLDoc2(_punkSite, &pHtmlDoc))) { BSTR bstrDocUrl; if (SUCCEEDED(pHtmlDoc->get_URL(&bstrDocUrl))) { hr = AccessAllowed(_punkSite, bstrDocUrl, bstrFrameSrc) ? S_OK : E_ACCESSDENIED; SysFreeString(bstrDocUrl); } pHtmlDoc->Release(); } SysFreeString(bstrFrameSrc); }
// Don't allow access to MyComputer zone from non-MyComputer zone.
if (SUCCEEDED(hr) && !CanNavigateToUrlWithLocalMachineCheck(_punkSite, strFailureUrl)) hr = E_ACCESSDENIED;
if (SUCCEEDED(hr)) { // We don't want to navigate to strSearch. Start searching using the
// first autoscan substitution.
WCHAR szFormat[MAX_PATH]; WCHAR szUrl[MAX_URL_STRING]; if (GetSearchFormatString(1, szFormat, sizeof(szFormat)) != ERROR_SUCCESS) { hr = E_FAIL; } else { wnsprintf(szUrl, ARRAYSIZE(szUrl), szFormat, strSearch); BSTRBLOB bstrBlob; bstrBlob.cbSize = lstrlenW(szUrl) * sizeof(WCHAR); bstrBlob.pData = (BYTE*)szUrl; BSTR bstrUrl = (BSTR)bstrBlob.pData; // Save the original search string for autoscanning. Normally
// this come from the addressbar, but in our case we store it as
// a property
VARIANT v; VariantInit (&v); v.vt = VT_BSTR; v.bstrVal = strSearch; pwb2->PutProperty((BSTR)s_sstrSearch.wsz, v); // Save the error page in case the scan fails
v.vt = VT_BSTR; v.bstrVal = strFailureUrl; pwb2->PutProperty((BSTR)s_sstrFailureUrl.wsz, v); // Navigate with autosearch enabled
VARIANT vFlags; vFlags.vt = VT_I4; vFlags.lVal = navAllowAutosearch; pwb2->Navigate(bstrUrl, &vFlags, pvarTargetFrame, PVAREMPTY, PVAREMPTY); } } pwb2->Release(); } } }
//script runtime error protection
return SUCCEEDED(hr) ? S_OK : S_FALSE; }
typedef HRESULT (*PFNSHOWBROWSERUI)(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut);
typedef void (*PFNOPENLANGUAGEDIALOG)(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
HRESULT ShowLanguageDialog(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut) { HRESULT hr = E_FAIL; HINSTANCE hInstInetcpl = LoadLibrary(TEXT("inetcpl.cpl"));
if (hInstInetcpl) { PFNOPENLANGUAGEDIALOG pfnOpenLanguageDialog = (PFNOPENLANGUAGEDIALOG)GetProcAddress( hInstInetcpl, "OpenLanguageDialog" );
if (pfnOpenLanguageDialog) { pfnOpenLanguageDialog(hwnd, NULL, NULL, SW_SHOW); hr = S_OK; }
FreeLibrary(hInstInetcpl); }
return hr; }
HRESULT ShowOrganizeFavorites(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut) { return DoOrganizeFavDlgW(hwnd, NULL) ? S_OK : E_FAIL; }
HRESULT ShowPrivacySettings(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut) { LaunchPrivacySettings(hwnd);
return S_OK; }
HRESULT ShowProgramAccessAndDefaults(IUnknown *punkSite, HWND hwnd, VARIANT *pvarIn, VARIANT *pvarOut) { HRESULT hr;
const WCHAR c_szControlExe[] = L"control.exe"; WCHAR szControlPath[MAX_PATH];
UINT nLen = GetSystemDirectory(szControlPath, ARRAYSIZE(szControlPath));
// This accounts for needing a backslash after the sysdir
if ((nLen + ARRAYSIZE(c_szControlExe)) < ARRAYSIZE(szControlPath)) { PathAppend(szControlPath, c_szControlExe);
HINSTANCE hInst = ShellExecute(NULL, NULL, szControlPath, L"appwiz.cpl,,3", NULL, SW_SHOWNORMAL);
if (hInst > (HINSTANCE)HINSTANCE_ERROR) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32(PtrToInt(hInst)); } } else { hr = E_OUTOFMEMORY; }
return hr; }
struct BROWSERUI_MAP { LPWSTR pwszName; PFNSHOWBROWSERUI pfnShowBrowserUI; };
const BROWSERUI_MAP s_browserUIMap[] = { { L"LanguageDialog", ShowLanguageDialog }, { L"OrganizeFavorites", ShowOrganizeFavorites }, { L"PrivacySettings", ShowPrivacySettings }, { L"ProgramAccessAndDefaults", ShowProgramAccessAndDefaults } };
STDMETHODIMP CShellUIHelper::ShowBrowserUI(BSTR bstrName, VARIANT *pvarIn, VARIANT *pvarOut) { HRESULT hr = E_FAIL;
for (int i = 0; i < ARRAYSIZE(s_browserUIMap); i++) { if (pvarOut) { VariantInit(pvarOut); } if (0 == StrCmpIW(s_browserUIMap[i].pwszName, bstrName)) { hr = s_browserUIMap[i].pfnShowBrowserUI(_punkSite, _GetOwnerWindow(), pvarIn, pvarOut); } }
return S_OK == hr ? S_OK : S_FALSE; }
// the find dialog does the following:
//
// rng = document.body.createTextRange();
// if (rng.findText("Find this text"))
// rng.select();
STDMETHODIMP CShellUIHelper::_DoFindOnPage(IDispatch* pdisp) { HRESULT hr; IWebBrowser2* pwb2; IDispatch* pdispDocument; IHTMLDocument2* pDocument; IHTMLElement* pBody; IHTMLBodyElement* pBodyElement; IHTMLTxtRange* pRange;
ASSERT(pdisp); if (!pdisp) return E_FAIL;
hr = pdisp->QueryInterface(IID_PPV_ARG(IWebBrowser2, &pwb2));
if (SUCCEEDED(hr)) { hr = pwb2->get_Document(&pdispDocument);
if (SUCCEEDED(hr) && (NULL != pdispDocument)) { hr = pdispDocument->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pDocument)); if (SUCCEEDED(hr)) { hr = pDocument->get_body(&pBody); if (SUCCEEDED(hr) && (NULL != pBody)) { hr = pBody->QueryInterface(IID_PPV_ARG(IHTMLBodyElement, &pBodyElement));
if (SUCCEEDED(hr)) { hr = pBodyElement->createTextRange(&pRange);
if (SUCCEEDED(hr) && (NULL != pRange)) { VARIANT_BOOL vbfFoundText; hr = pRange->findText(_bstrQuery, 1000000, 0, &vbfFoundText);
if (SUCCEEDED(hr) && (vbfFoundText == VARIANT_TRUE)) { hr = pRange->select(); } pRange->Release(); } pBodyElement->Release(); } pBody->Release(); } pDocument->Release(); } pdispDocument->Release(); } pwb2->Release(); } return hr; }
//
// Launch the favorites import/export wizard
//
STDMETHODIMP CShellUIHelper::ImportExportFavorites(VARIANT_BOOL fImport, BSTR strImpExpPath) { //don't allow to import/export to folders other than Favorites from OM
DoImportOrExport(fImport==VARIANT_TRUE, NULL, (LPCWSTR)strImpExpPath, TRUE); return S_OK; }
//
// Save the form data via intelliforms
//
STDMETHODIMP CShellUIHelper::AutoCompleteSaveForm(VARIANT *Form) { HRESULT hrRet = S_FALSE;
IHTMLDocument2 *pDoc2=NULL;
GetHTMLDoc2(_punkSite, &pDoc2); if (pDoc2) { hrRet = IntelliFormsSaveForm(pDoc2, Form); pDoc2->Release(); }
return hrRet; }
//
// Attach intelliforms to this document
//
STDMETHODIMP CShellUIHelper::AutoCompleteAttach(VARIANT *Reserved) { HRESULT hr=E_FAIL;
if (_pvIntelliForms == NULL) { IHTMLDocument2 *pDoc2=NULL;
GetHTMLDoc2(_punkSite, &pDoc2);
if (pDoc2) { hr = S_OK; AttachIntelliForms(NULL, _GetOwnerWindow(), pDoc2, &_pvIntelliForms); pDoc2->Release(); } }
return SUCCEEDED(hr) ? S_OK : S_FALSE; }
|