1832 lines
55 KiB
C++
1832 lines
55 KiB
C++
//
|
|
// 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_IServiceProvider, (void**)&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;
|
|
}
|
|
|
|
STDAPI GetHTMLDoc2(IUnknown *punk, IHTMLDocument2 **ppHtmlDoc)
|
|
{
|
|
*ppHtmlDoc = NULL;
|
|
|
|
if (!punk)
|
|
return E_FAIL;
|
|
|
|
*ppHtmlDoc = NULL;
|
|
// The window.external, jscript "new ActiveXObject" and the <OBJECT> tag
|
|
// don't take us down the same road.
|
|
|
|
IOleClientSite *pClientSite;
|
|
HRESULT hr = punk->QueryInterface(IID_PPV_ARG(IOleClientSite, &pClientSite));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// <OBJECT> tag path
|
|
|
|
IOleContainer *pContainer;
|
|
hr = pClientSite->GetContainer(&pContainer);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pContainer->QueryInterface(IID_PPV_ARG(IHTMLDocument2, ppHtmlDoc));
|
|
pContainer->Release();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
// window.external path
|
|
IWebBrowser2 *pWebBrowser2;
|
|
hr = IUnknown_QueryService(pClientSite, SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, &pWebBrowser2));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IDispatch *pDispatch;
|
|
hr = pWebBrowser2->get_Document(&pDispatch);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pDispatch->QueryInterface(IID_PPV_ARG(IHTMLDocument2, ppHtmlDoc));
|
|
pDispatch->Release();
|
|
}
|
|
pWebBrowser2->Release();
|
|
}
|
|
}
|
|
pClientSite->Release();
|
|
}
|
|
else
|
|
{
|
|
// jscript path
|
|
hr = IUnknown_QueryService(punk, SID_SContainerDispatch, IID_PPV_ARG(IHTMLDocument2, ppHtmlDoc));
|
|
}
|
|
|
|
ASSERT(FAILED(hr) || (*ppHtmlDoc));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// 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;
|
|
|
|
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;
|
|
}
|
|
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_ISubscriptionMgr, (void**)&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.wszSource));
|
|
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_IActiveDesktop, (LPVOID*)&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_IActiveDesktopP, (LPVOID*)&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_IADesktopP2, (LPVOID*)&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_IActiveDesktop, (LPVOID*)&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)
|
|
{
|
|
// 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);
|
|
|
|
BSTR bstrTemp = NULL;
|
|
if (!IsSpecialUrl(URL))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
bstrTemp = SysAllocString(URL);
|
|
if (bstrTemp)
|
|
{
|
|
hr = WrapSpecialUrl(&bstrTemp);
|
|
if (SUCCEEDED(hr))
|
|
URL = bstrTemp;
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Security: Don't allow javascript on one web page
|
|
// to automatically execute in the zone
|
|
// of the target frame URL.
|
|
if (SUCCEEDED(hr) && varTargetFrame)
|
|
{
|
|
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(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();
|
|
}
|
|
|
|
if (bstrTemp)
|
|
SysFreeString(bstrTemp);
|
|
|
|
//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
|
|
BSTR bstrTemp = NULL;
|
|
if (IsSpecialUrl(strFailureUrl))
|
|
{
|
|
bstrTemp = SysAllocString(strFailureUrl);
|
|
if (bstrTemp)
|
|
{
|
|
hr = WrapSpecialUrl(&bstrTemp);
|
|
if (SUCCEEDED(hr))
|
|
strFailureUrl = bstrTemp;
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
hr = 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(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();
|
|
}
|
|
}
|
|
if (bstrTemp)
|
|
SysFreeString(bstrTemp);
|
|
}
|
|
|
|
//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_IWebBrowser2, (void**)&pwb2);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pwb2->get_Document(&pdispDocument);
|
|
|
|
if (SUCCEEDED(hr) && (NULL != pdispDocument))
|
|
{
|
|
hr = pdispDocument->QueryInterface(IID_IHTMLDocument2, (void**)&pDocument);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pDocument->get_body(&pBody);
|
|
|
|
if (SUCCEEDED(hr) && (NULL != pBody))
|
|
{
|
|
hr = pBody->QueryInterface(IID_IHTMLBodyElement, (void**)&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;
|
|
}
|