Windows2003-3790/inetcore/mshtml/iextag/utils.cxx
2020-09-30 16:53:55 +02:00

1719 lines
42 KiB
C++

//+------------------------------------------------------------------------
//
// File : Utils.cxx
//
// purpose : implementation of helpful stuff
//
//-------------------------------------------------------------------------
#include "headers.h"
#pragma MARK_DATA(__FILE__)
#pragma MARK_CODE(__FILE__)
#pragma MARK_CONST(__FILE__)
#include "utils.hxx"
#include <docobj.h>
#include <mshtmcid.h>
#include <mshtmhst.h>
#define BUFFEREDSTR_SIZE 1024
// VARIANT conversion interface exposed by script engines (VBScript/JScript).
EXTERN_C const GUID SID_VariantConversion =
{ 0x1f101481, 0xbccd, 0x11d0, { 0x93, 0x36, 0x0, 0xa0, 0xc9, 0xd, 0xca, 0xa9 } };
//+------------------------------------------------------------------------
//
// Function: GetHTMLDocument
//
// Synopsis: Gets the IHTMLDocument2 interface from the client site.
//
//-------------------------------------------------------------------------
STDMETHODIMP
GetHTMLDocument(IElementBehaviorSite * pSite, IHTMLDocument2 **ppDoc)
{
HRESULT hr = E_FAIL;
if (!ppDoc)
return E_POINTER;
if (pSite != NULL)
{
IHTMLElement *pElement = NULL;
hr = pSite->GetElement(&pElement);
if (SUCCEEDED(hr))
{
IDispatch * pDispDoc = NULL;
hr = pElement->get_document(&pDispDoc);
if (SUCCEEDED(hr))
{
hr = pDispDoc->QueryInterface(IID_IHTMLDocument2, (void **)ppDoc);
pDispDoc->Release();
}
pElement->Release();
}
}
return hr;
}
//+------------------------------------------------------------------------
//
// Function: GetHTMLWindow
//
// Synopsis: Gets the IHTMLWindow2 interface from the client site.
//
//-------------------------------------------------------------------------
STDMETHODIMP
GetHTMLWindow(IElementBehaviorSite * pSite, IHTMLWindow2 **ppWindow)
{
HRESULT hr = E_FAIL;
IHTMLDocument2 *pDoc = NULL;
hr = GetHTMLDocument(pSite, &pDoc);
if (SUCCEEDED(hr))
{
hr = pDoc->get_parentWindow(ppWindow);
pDoc->Release();
}
return hr;
}
//+------------------------------------------------------------------------
//
// Function: GetClientSiteWindow
//
// Synopsis: Gets the window handle of the client site passed in.
//
//-------------------------------------------------------------------------
STDMETHODIMP
GetClientSiteWindow(IElementBehaviorSite *pSite, HWND *phWnd)
{
HRESULT hr = E_FAIL;
IWindowForBindingUI *pWindowForBindingUI = NULL;
if (pSite != NULL) {
// Get IWindowForBindingUI ptr
hr = pSite->QueryInterface(IID_IWindowForBindingUI,
(LPVOID *)&pWindowForBindingUI);
if (FAILED(hr)) {
IServiceProvider *pServProv;
hr = pSite->QueryInterface(IID_IServiceProvider, (LPVOID *)&pServProv);
if (hr == NOERROR) {
pServProv->QueryService(IID_IWindowForBindingUI,IID_IWindowForBindingUI,
(LPVOID *)&pWindowForBindingUI);
pServProv->Release();
}
}
if (pWindowForBindingUI) {
pWindowForBindingUI->GetWindow(IID_IWindowForBindingUI, phWnd);
pWindowForBindingUI->Release();
}
}
return hr;
}
//+------------------------------------------------------------------------
//
// Function: AppendElement
//
// Synopsis: Appends a child to an owner
//
//-------------------------------------------------------------------------
STDMETHODIMP
AppendChild(IHTMLElement *pOwner, IHTMLElement *pChild)
{
HRESULT hr;
CComPtr<IHTMLDOMNode> pOwnerNode, pChildNode;
hr = pOwner->QueryInterface(IID_IHTMLDOMNode, (void **) &pOwnerNode);
if (FAILED(hr))
goto Cleanup;
hr = pChild->QueryInterface(IID_IHTMLDOMNode, (void **) &pChildNode);
if (FAILED(hr))
goto Cleanup;
hr = pOwnerNode->appendChild(pChildNode, NULL);
if (FAILED(hr))
goto Cleanup;
Cleanup:
return hr;
}
//+---------------------------------------------------------------
//
// Function: IsSameObject
//
// Synopsis: Checks for COM identity
//
// Arguments: pUnkLeft, pUnkRight
//
//+---------------------------------------------------------------
BOOL
IsSameObject(IUnknown *pUnkLeft, IUnknown *pUnkRight)
{
IUnknown *pUnk1, *pUnk2;
if (pUnkLeft == pUnkRight)
return TRUE;
if (pUnkLeft == NULL || pUnkRight == NULL)
return FALSE;
if (SUCCEEDED(pUnkLeft->QueryInterface(IID_IUnknown, (LPVOID *)&pUnk1)))
{
pUnk1->Release();
if (pUnk1 == pUnkRight)
return TRUE;
if (SUCCEEDED(pUnkRight->QueryInterface(IID_IUnknown, (LPVOID *)&pUnk2)))
{
pUnk2->Release();
return pUnk1 == pUnk2;
}
}
return FALSE;
}
//+------------------------------------------------------------------------
//
// Function: ClearInterfaceFn
//
// Synopsis: Sets an interface pointer to NULL, after first calling
// Release if the pointer was not NULL initially
//
// Arguments: [ppUnk] *ppUnk is cleared
//
//-------------------------------------------------------------------------
void
ClearInterfaceFn(IUnknown ** ppUnk)
{
IUnknown * pUnk;
pUnk = *ppUnk;
*ppUnk = NULL;
if (pUnk)
pUnk->Release();
}
//+------------------------------------------------------------------------
//
// Function: ReplaceInterfaceFn
//
// Synopsis: Replaces an interface pointer with a new interface,
// following proper ref counting rules:
//
// = *ppUnk is set to pUnk
// = if *ppUnk was not NULL initially, it is Release'd
// = if pUnk is not NULL, it is AddRef'd
//
// Effectively, this allows pointer assignment for ref-counted
// pointers.
//
// Arguments: [ppUnk]
// [pUnk]
//
//-------------------------------------------------------------------------
void
ReplaceInterfaceFn(IUnknown ** ppUnk, IUnknown * pUnk)
{
IUnknown * pUnkOld = *ppUnk;
*ppUnk = pUnk;
// Note that we do AddRef before Release; this avoids
// accidentally destroying an object if this function
// is passed two aliases to it
if (pUnk)
pUnk->AddRef();
if (pUnkOld)
pUnkOld->Release();
}
//+------------------------------------------------------------------------
//
// Function: ReleaseInterface
//
// Synopsis: Releases an interface pointer if it is non-NULL
//
// Arguments: [pUnk]
//
//-------------------------------------------------------------------------
void
ReleaseInterface(IUnknown * pUnk)
{
if (pUnk)
pUnk->Release();
}
//+------------------------------------------------------------------------
//
// Member: CBufferedStr::Set
//
// Synopsis: Initilizes a CBufferedStr
//
//-------------------------------------------------------------------------
HRESULT
CBufferedStr::Set (LPCTSTR pch, UINT uiCch)
{
HRESULT hr = S_OK;
Free();
if (!uiCch)
_cchIndex = pch ? _tcslen (pch) : 0;
else
_cchIndex = uiCch;
_cchBufSize = _cchIndex > BUFFEREDSTR_SIZE ? _cchIndex : BUFFEREDSTR_SIZE;
_pchBuf = new TCHAR [ _cchBufSize ];
if (!_pchBuf)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
if (pch)
{
_tcsncpy (_pchBuf, pch, _cchIndex);
}
_pchBuf[_cchIndex] = '\0';
Cleanup:
return (hr);
}
//+------------------------------------------------------------------------
//
// Member: CBufferedStr::QuickAppend
//
// Parameters: pchNewStr string to be added to _pchBuf
//
// Synopsis: Appends pNewStr into _pchBuf starting at
// _pchBuf[uIndex]. Increments index to reference
// new end of string. If _pchBuf is not large enough,
// reallocs _pchBuf and updates _cchBufSize.
//
//-------------------------------------------------------------------------
HRESULT
CBufferedStr::QuickAppend (const TCHAR* pchNewStr, ULONG newLen)
{
HRESULT hr = S_OK;
if (!_pchBuf)
{
hr = Set();
if (hr)
goto Cleanup;
}
if (_cchIndex + newLen >= _cchBufSize) // we can't fit the new string in the current buffer
{ // so allocate a new buffer, and copy the old string
_cchBufSize += (newLen > BUFFEREDSTR_SIZE) ? newLen : BUFFEREDSTR_SIZE;
TCHAR * pchTemp = new TCHAR [ _cchBufSize ];
if (!pchTemp)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
_tcsncpy (pchTemp, _pchBuf, _cchIndex);
Free();
_pchBuf = pchTemp;
}
// append the new string
_tcsncpy (_pchBuf + _cchIndex, pchNewStr, newLen);
_cchIndex += newLen;
_pchBuf[_cchIndex] = '\0';
Cleanup:
return (hr);
}
HRESULT
CBufferedStr::QuickAppend(long lValue)
{
TCHAR strValue[40];
#ifdef UNICODE
return QuickAppend( _ltow(lValue, strValue, 10) );
#else
return QuickAppend( _ltoa(lValue, strValue, 10) );
#endif
}
//+---------------------------------------------------------------------------
//
// method : ConvertGmtTimeToString
//
// Synopsis: This function produces a standard(?) format date, of the form
// Tue, 02 Apr 1996 02:04:57 UTC The date format *will not* be tailored
// for the locale. This is for cookie use and Netscape compatibility
//
//----------------------------------------------------------------------------
static const TCHAR* achMonth[] = {
_T("Jan"),_T("Feb"),_T("Mar"),_T("Apr"),_T("May"),_T("Jun"),
_T("Jul"),_T("Aug"),_T("Sep"),_T("Oct"),_T("Nov"),_T("Dec")
};
static const TCHAR* achDay[] = {
_T("Sun"), _T("Mon"),_T("Tue"),_T("Wed"),_T("Thu"),_T("Fri"),_T("Sat")
};
HRESULT
ConvertGmtTimeToString(FILETIME Time, TCHAR * pchDateStr, DWORD cchDateStr)
{
SYSTEMTIME SystemTime;
CBufferedStr strBuf;
if (cchDateStr < DATE_STR_LENGTH)
return E_INVALIDARG;
FileTimeToSystemTime(&Time, &SystemTime);
strBuf.QuickAppend(achDay[SystemTime.wDayOfWeek]);
strBuf.QuickAppend(_T(", "));
strBuf.QuickAppend(SystemTime.wDay);
strBuf.QuickAppend(_T(" ") );
strBuf.QuickAppend(achMonth[SystemTime.wMonth - 1] );
strBuf.QuickAppend(_T(" ") );
strBuf.QuickAppend(SystemTime.wYear );
strBuf.QuickAppend(_T(" ") );
strBuf.QuickAppend(SystemTime.wHour );
strBuf.QuickAppend(_T(":") );
strBuf.QuickAppend(SystemTime.wMinute );
strBuf.QuickAppend(_T(":") );
strBuf.QuickAppend(SystemTime.wSecond );
strBuf.QuickAppend(_T(" UTC") );
if (strBuf.Length() >cchDateStr)
return E_FAIL;
_tcscpy(pchDateStr, strBuf);
return S_OK;
}
HRESULT
ParseDate(BSTR strDate, FILETIME * pftTime)
{
HRESULT hr = S_FALSE;
SYSTEMTIME stTime ={0};
LPCTSTR pszToken = NULL;
BOOL fFound;
int idx, cch;
CDataListEnumerator dle(strDate, _T(':'));
if (!pftTime)
{
hr = E_POINTER;
goto Cleanup;
}
// get the dayOfTheWeek: 3 digits max plus comma
//--------------------------------------------------
if (! dle.GetNext(&pszToken, &cch) || cch > 4)
goto Cleanup;
else
{
for (idx=0; idx < ARRAY_SIZE(achDay); idx++)
{
fFound = !_tcsnicmp( pszToken, achDay[idx], 3);
if (fFound)
{
stTime.wDayOfWeek = (WORD)idx;
break;
}
}
if (!fFound)
{
hr = E_FAIL;
goto Cleanup;
}
}
// get the Day 2 digits max
//--------------------------------------------------
if (! dle.GetNext(&pszToken, &cch) || cch > 2)
goto Cleanup;
stTime.wDay = (WORD)_ttoi(pszToken);
// get the Month: 3 characters
//--------------------------------------------------
if (! dle.GetNext(&pszToken, &cch) || cch > 3)
goto Cleanup;
else
{
for (idx=0; idx < ARRAY_SIZE(achMonth); idx++)
{
fFound = !_tcsnicmp( pszToken, achMonth[idx], 3);
if (fFound)
{
stTime.wMonth = (WORD)idx + 1;
break;
}
}
if (!fFound)
{
hr = E_FAIL;
goto Cleanup;
}
}
// get the Year 4 digits max
//--------------------------------------------------
if (! dle.GetNext(&pszToken, &cch) || cch > 4)
goto Cleanup;
stTime.wYear = (WORD)_ttoi(pszToken);
// get the Hour 2 digits max
//--------------------------------------------------
if (! dle.GetNext(&pszToken, &cch) || cch > 2)
goto Cleanup;
stTime.wHour = (WORD)_ttoi(pszToken);
// get the Minute 2 digits max
//--------------------------------------------------
if (! dle.GetNext(&pszToken, &cch) || cch > 2)
goto Cleanup;
stTime.wMinute = (WORD)_ttoi(pszToken);
// get the Second 2 digits max
//--------------------------------------------------
if (! dle.GetNext(&pszToken, &cch) || cch > 2)
goto Cleanup;
stTime.wSecond = (WORD)_ttoi(pszToken);
// now we have SYSTEMTIME, lets return the FILETIME
if (!SystemTimeToFileTime(&stTime, pftTime))
hr = GetLastError();
else
hr = S_OK;
Cleanup:
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: MbcsFromUnicode
//
// Synopsis: Converts a string to MBCS from Unicode.
//
// Arguments: [pstr] -- The buffer for the MBCS string.
// [cch] -- The size of the MBCS buffer, including space for
// NULL terminator.
//
// [pwstr] -- The Unicode string to convert.
// [cwch] -- The number of characters in the Unicode string to
// convert, including NULL terminator. If this
// number is -1, the string is assumed to be
// NULL terminated. -1 is supplied as a
// default argument.
//
// Returns: If [pstr] is NULL or [cch] is 0, 0 is returned. Otherwise,
// the number of characters converted, including the terminating
// NULL, is returned (note that converting the empty string will
// return 1). If the conversion fails, 0 is returned.
//
// Modifies: [pstr].
//
//----------------------------------------------------------------------------
int
MbcsFromUnicode(LPSTR pstr, int cch, LPCWSTR pwstr, int cwch)
{
int ret;
#if DBG == 1 /* { */
int errcode;
#endif /* } */
if (!pstr || cch <= 0 || !pwstr || cwch<-1)
return 0;
ret = WideCharToMultiByte(CP_ACP, 0, pwstr, cwch, pstr, cch, NULL, NULL);
#if DBG == 1 /* { */
if (ret <= 0)
{
errcode = GetLastError();
}
#endif /* } */
return ret;
}
//+---------------------------------------------------------------------------
//
// Function: UnicodeFromMbcs
//
// Synopsis: Converts a string to Unicode from MBCS.
//
// Arguments: [pwstr] -- The buffer for the Unicode string.
// [cwch] -- The size of the Unicode buffer, including space for
// NULL terminator.
//
// [pstr] -- The MBCS string to convert.
// [cch] -- The number of characters in the MBCS string to
// convert, including NULL terminator. If this
// number is -1, the string is assumed to be
// NULL terminated. -1 is supplied as a
// default argument.
//
// Returns: If [pwstr] is NULL or [cwch] is 0, 0 is returned. Otherwise,
// the number of characters converted, including the terminating
// NULL, is returned (note that converting the empty string will
// return 1). If the conversion fails, 0 is returned.
//
// Modifies: [pwstr].
//
//----------------------------------------------------------------------------
int
UnicodeFromMbcs(LPWSTR pwstr, int cwch, LPCSTR pstr, int cch)
{
int ret;
#if DBG == 1 /* { */
int errcode;
#endif /* } */
if (!pstr || cwch <= 0 || !pwstr || cch<-1)
return 0;
ret = MultiByteToWideChar(CP_ACP, 0, pstr, cch, pwstr, cwch);
#if DBG == 1 /* { */
if (ret <= 0)
{
errcode = GetLastError();
}
#endif /* } */
return ret;
}
//+--------------------------------------------------------------------
//
// Function: _tcsistr
//
//---------------------------------------------------------------------
const TCHAR * __cdecl _tcsistr (const TCHAR * tcs1,const TCHAR * tcs2)
{
const TCHAR *cp;
int cc,count;
int n2Len = _tcslen ( tcs2 );
int n1Len = _tcslen ( tcs1 );
if ( n1Len >= n2Len )
{
for ( cp = tcs1, count = n1Len - n2Len; count>=0 ; cp++,count-- )
{
cc = CompareString(LCID_SCRIPTING,
NORM_IGNORECASE | NORM_IGNOREWIDTH | NORM_IGNOREKANATYPE,
cp, n2Len,tcs2, n2Len);
if ( cc > 0 )
cc-=2;
if ( !cc )
return cp;
}
}
return NULL;
}
//+--------------------------------------------------------------------
//
// Function: AccessAllowed
//
//---------------------------------------------------------------------
BOOL
AccessAllowed(BSTR bstrUrl, IUnknown * pUnkSite)
{
BOOL fAccessAllowed = FALSE;
HRESULT hr;
CComPtr<IBindHost> pBindHost;
CComPtr<IMoniker> pMoniker;
LPTSTR pchUrl = NULL;
BYTE abSID1[MAX_SIZE_SECURITY_ID];
BYTE abSID2[MAX_SIZE_SECURITY_ID];
DWORD cbSID1 = ARRAY_SIZE(abSID1);
DWORD cbSID2 = ARRAY_SIZE(abSID2);
CComPtr<IInternetSecurityManager> pSecurityManager;
CComPtr<IInternetHostSecurityManager> pHostSecurityManager;
CComQIPtr<IServiceProvider, &IID_IServiceProvider> pServiceProvider(pUnkSite);
if (!pServiceProvider)
goto Cleanup;
//
// expand url
//
hr = pServiceProvider->QueryService(SID_IBindHost, IID_IBindHost, (void**)&pBindHost);
if (hr)
goto Cleanup;
hr = pBindHost->CreateMoniker(bstrUrl, NULL, &pMoniker, NULL);
if (hr)
goto Cleanup;
hr = pMoniker->GetDisplayName(NULL, NULL, &pchUrl);
if (hr)
goto Cleanup;
//
// get security id of the url
//
hr = CoInternetCreateSecurityManager(NULL, &pSecurityManager, 0);
if (hr)
goto Cleanup;
hr = pSecurityManager->GetSecurityId(pchUrl, abSID1, &cbSID1, NULL);
if (hr)
goto Cleanup;
//
// get security id of the document
//
hr = pServiceProvider->QueryService(
IID_IInternetHostSecurityManager, IID_IInternetHostSecurityManager, (void**)&pHostSecurityManager);
if (hr)
goto Cleanup;
hr = pHostSecurityManager->GetSecurityId(abSID2, &cbSID2, NULL);
//
// the security check itself
//
fAccessAllowed = (cbSID1 == cbSID2 && (0 == memcmp(abSID1, abSID2, cbSID1)));
Cleanup:
if (pchUrl)
CoTaskMemFree(pchUrl);
return fAccessAllowed;
}
//+------------------------------------------------------------------------
//
// CDataObject : Member function implmentations
//
//-------------------------------------------------------------------------
HRESULT
CDataObject::Set (BSTR bstrValue)
{
VariantClear(&_varValue);
_fDirty = TRUE;
V_VT(&_varValue) = VT_BSTR;
if (!bstrValue)
{
V_BSTR(&_varValue) = NULL;
return S_OK;
}
else
{
V_BSTR(&_varValue) = SysAllocStringLen(bstrValue, SysStringLen(bstrValue));
return (V_BSTR(&_varValue)) ? S_OK : E_OUTOFMEMORY;
}
}
HRESULT
CDataObject::Set (VARIANT_BOOL vBool)
{
VariantClear(&_varValue);
_fDirty = TRUE;
V_VT(&_varValue) = VT_BOOL;
V_BOOL(&_varValue) = vBool;
return S_OK;
}
HRESULT
CDataObject::Set(IDispatch * pDisp)
{
VariantClear(&_varValue);
_fDirty = TRUE;
V_VT(&_varValue) = VT_DISPATCH;
V_DISPATCH(&_varValue) = pDisp;
if (pDisp)
pDisp->AddRef();
return S_OK;
}
HRESULT
CDataObject::GetAsBSTR (BSTR * pbstr)
{
HRESULT hr = S_OK;
if (!pbstr)
{
hr = E_POINTER;
goto Cleanup;
}
*pbstr = NULL;
if (V_VT(&_varValue) == VT_BSTR)
{
*pbstr = SysAllocStringLen(V_BSTR(&_varValue),
SysStringLen(V_BSTR(&_varValue)));
if (!*pbstr)
hr = E_OUTOFMEMORY;
}
Cleanup:
return hr;
};
HRESULT
CDataObject::GetAsBOOL (VARIANT_BOOL * pVB)
{
HRESULT hr = S_OK;
if (!pVB)
{
hr = E_POINTER;
goto Cleanup;
}
if (V_VT(&_varValue) != VT_BOOL)
{
*pVB = VB_FALSE;
hr = S_FALSE;
}
else
{
*pVB = V_BOOL(&_varValue);
}
Cleanup:
return hr;
};
HRESULT
CDataObject::GetAsDispatch(IDispatch ** ppDisp)
{
HRESULT hr = S_OK;
if (!ppDisp)
{
hr = E_POINTER;
goto Cleanup;
}
*ppDisp = NULL;
if (V_VT(&_varValue)!= VT_DISPATCH)
{
hr = S_FALSE;
}
else
{
*ppDisp = V_DISPATCH(&_varValue);
if (*ppDisp)
(*ppDisp)->AddRef();
}
Cleanup:
return hr;
}
/////////////////////////////////////////////////////////////////////////////
//
// Helper Class: CContextAccess
// access to behavior site, element and style
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
CContextAccess::CContextAccess(IElementBehaviorSite * pSite)
{
memset (this, 0, sizeof(*this));
_pSite = pSite;
_pSite->AddRef();
}
CContextAccess::CContextAccess(IHTMLElement * pElement)
{
memset (this, 0, sizeof(*this));
_dwAccess = CA_ELEM;
_pElem = pElement;
_pElem->AddRef();
}
/////////////////////////////////////////////////////////////////////////////
CContextAccess::~CContextAccess()
{
DWORD dw;
ReleaseInterface (_pSite);
// the point of this loop is to avoid doing as many ReleaseInterface-s as we have possible values in CONTEXT_ACCESS enum.
// instead, we do as many ReleaseInterface-s as number of bits actually set in dwAccess.
while (_dwAccess)
{
dw = (_dwAccess - 1) & _dwAccess;
switch (_dwAccess - dw)
{
case CA_SITEOM: _pSiteOM->Release(); break;
case CA_SITERENDER: _pSiteRender->Release(); break;
case CA_ELEM: _pElem->Release(); break;
case CA_ELEM2: _pElem2->Release(); break;
case CA_ELEM3: _pElem3->Release(); break;
case CA_STYLE: _pStyle->Release(); break;
case CA_STYLE2: _pStyle2->Release(); break;
case CA_STYLE3: _pStyle3->Release(); break;
case CA_DEFAULTS: _pDefaults->Release(); break;
case CA_DEFSTYLE: _pDefStyle->Release(); break;
case CA_DEFSTYLE2: _pDefStyle2->Release(); break;
case CA_DEFSTYLE3: _pDefStyle3->Release(); break;
default: Assert (FALSE && "invalid _dwAccess"); break;
}
_dwAccess = dw;
}
}
/////////////////////////////////////////////////////////////////////////////
HRESULT
CContextAccess::Open(DWORD dwAccess)
{
HRESULT hr = S_OK;
DWORD dw, dw2, dw3;
// NOTE order of these ifs is important
// STYLE2 or STYLE3 require us to get STYLE
if (dwAccess & (CA_STYLE2 | CA_STYLE3))
dwAccess |= CA_STYLE;
// ELEM2, ELEM3, or CA_STYLE require us to get ELEM
if (dwAccess & (CA_ELEM2 | CA_ELEM3 | CA_STYLE))
dwAccess |= CA_ELEM;
// DEFSTYLE2 or DEFSTYLE3 require us to get STYLE
if (dwAccess & (CA_DEFSTYLE2 | CA_DEFSTYLE3))
dwAccess |= CA_DEFSTYLE;
// any DEFSTYLE require us to get PELEM
if (dwAccess & (CA_DEFSTYLE))
dwAccess |= CA_DEFAULTS;
// PELEM requires us to get SITEOM
if (dwAccess & (CA_DEFAULTS))
dwAccess |= CA_SITEOM;
// the point of this loop is to avoid doing as many ifs as we have possible values in CONTEXT_ACCESS enum.
// instead, we do as many ifs as number of bits actually set in dwAccess.
dw = dwAccess;
while (dw)
{
dw2 = (dw - 1) & dw;
dw3 = dw - dw2;
if (0 == (dw3 & _dwAccess))
{
switch (dw3)
{
case CA_SITEOM:
Assert (_pSite && !_pSiteOM);
hr = _pSite->QueryInterface(IID_IElementBehaviorSiteOM2, (void**)&_pSiteOM);
if (hr)
goto Cleanup;
break;
case CA_SITERENDER:
Assert (_pSite && !_pSiteRender);
hr = _pSite->QueryInterface(IID_IElementBehaviorSiteRender, (void**)&_pSiteRender);
if (hr)
goto Cleanup;
break;
case CA_ELEM:
Assert (_pSite && !_pElem);
hr = _pSite->GetElement(&_pElem);
if (hr)
goto Cleanup;
break;
case CA_ELEM2:
Assert (_pElem && !_pElem2);
hr = _pElem->QueryInterface(IID_IHTMLElement2, (void**)&_pElem2);
if (hr)
goto Cleanup;
break;
case CA_ELEM3:
Assert (_pElem && !_pElem3);
hr = _pElem->QueryInterface(IID_IHTMLElement3, (void**)&_pElem3);
if (hr)
goto Cleanup;
break;
case CA_STYLE:
Assert (_pElem && !_pStyle);
hr = _pElem->get_style(&_pStyle);
if (hr)
goto Cleanup;
break;
case CA_STYLE2:
Assert (_pStyle && !_pStyle2);
hr = _pStyle->QueryInterface(IID_IHTMLStyle2, (void**)&_pStyle2);
if (hr)
goto Cleanup;
break;
case CA_STYLE3:
Assert (_pStyle && !_pStyle3);
hr = _pStyle->QueryInterface(IID_IHTMLStyle3, (void**)&_pStyle3);
if (hr)
goto Cleanup;
break;
case CA_DEFAULTS:
Assert (_pSiteOM && !_pDefaults);
hr = _pSiteOM->GetDefaults(&_pDefaults);
if (hr)
goto Cleanup;
break;
case CA_DEFSTYLE:
Assert (_pDefaults && !_pDefStyle);
hr = _pDefaults->get_style(&_pDefStyle);
if (hr)
goto Cleanup;
break;
case CA_DEFSTYLE2:
Assert (_pDefStyle && !_pDefStyle2);
hr = _pDefStyle->QueryInterface(IID_IHTMLStyle2, (void**)&_pDefStyle2);
if (hr)
goto Cleanup;
break;
case CA_DEFSTYLE3:
Assert (_pDefStyle && !_pDefStyle3);
hr = _pDefStyle->QueryInterface(IID_IHTMLStyle3, (void**)&_pDefStyle3);
if (hr)
goto Cleanup;
break;
default:
Assert (FALSE && "invalid dwAccess");
break;
}
}
dw = dw2;
}
_dwAccess |= dwAccess;
Cleanup:
return hr;
}
/////////////////////////////////////////////////////////////////////////////
#if DBG == 1
HRESULT
CContextAccess::DbgTest(IElementBehaviorSite * pSite)
{
HRESULT hr;
// CA_NONE
{
CContextAccess a(pSite);
hr = a.Open(CA_NONE);
if (hr)
goto Cleanup;
}
// CA_ELEM
{
CContextAccess a(pSite);
hr = a.Open(CA_ELEM);
if (hr)
goto Cleanup;
a.Elem()->AddRef();
a.Elem()->Release();
}
// CA_ELEM2
{
CContextAccess a(pSite);
hr = a.Open(CA_ELEM2);
if (hr)
goto Cleanup;
a.Elem2()->AddRef();
a.Elem2()->Release();
}
// CA_ELEM3
{
CContextAccess a(pSite);
hr = a.Open(CA_ELEM3);
if (hr)
goto Cleanup;
a.Elem3()->AddRef();
a.Elem3()->Release();
}
// CA_STYLE
{
CContextAccess a(pSite);
hr = a.Open(CA_STYLE);
if (hr)
goto Cleanup;
a.Style()->AddRef();
a.Style()->Release();
}
// CA_STYLE2
{
CContextAccess a(pSite);
hr = a.Open(CA_STYLE2);
if (hr)
goto Cleanup;
a.Style2()->AddRef();
a.Style2()->Release();
}
// CA_STYLE3
{
CContextAccess a(pSite);
hr = a.Open(CA_STYLE3);
if (hr)
goto Cleanup;
a.Style3()->AddRef();
a.Style3()->Release();
}
// CA_DEFSTYLE
{
CContextAccess a(pSite);
hr = a.Open(CA_DEFSTYLE);
if (hr)
goto Cleanup;
a.DefStyle()->AddRef();
a.DefStyle()->Release();
}
// CA_DEFSTYLE2
{
CContextAccess a(pSite);
hr = a.Open(CA_DEFSTYLE2);
if (hr)
goto Cleanup;
a.DefStyle2()->AddRef();
a.DefStyle2()->Release();
}
// CA_DEFSTYLE3
{
CContextAccess a(pSite);
hr = a.Open(CA_DEFSTYLE3);
if (hr)
goto Cleanup;
a.DefStyle3()->AddRef();
a.DefStyle3()->Release();
}
// CA_SITEOM
{
CContextAccess a(pSite);
hr = a.Open(CA_SITEOM);
if (hr)
goto Cleanup;
a.SiteOM()->AddRef();
a.SiteOM()->Release();
}
// sequencing of Opens
{
CContextAccess a(pSite);
hr = a.Open(CA_SITEOM);
if (hr)
goto Cleanup;
a.SiteOM()->AddRef();
a.SiteOM()->Release();
hr = a.Open(CA_ELEM);
if (hr)
goto Cleanup;
a.Elem()->AddRef();
a.Elem()->Release();
hr = a.Open(CA_DEFSTYLE3);
if (hr)
goto Cleanup;
a.DefStyle3()->AddRef();
a.DefStyle3()->Release();
}
Cleanup:
return hr;
}
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Helper Class: CEventObjectAccess
// access to event object
//
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
CEventObjectAccess::CEventObjectAccess(DISPPARAMS * pDispParams)
{
memset (this, 0, sizeof(*this));
_pDispParams = pDispParams;
}
///////////////////////////////////////////////////////////////////////////////
CEventObjectAccess::~CEventObjectAccess()
{
ReleaseInterface (_pEventObj);
ReleaseInterface (_pEventObj2);
}
///////////////////////////////////////////////////////////////////////////////
HRESULT
CEventObjectAccess::Open(DWORD dwAccess)
{
HRESULT hr = S_OK;
VARIANT * pvarArg;
Assert (_pDispParams);
if (!_pDispParams ||
!_pDispParams->rgvarg ||
_pDispParams->cArgs != 1)
{
hr = E_INVALIDARG;
goto Cleanup;
}
pvarArg = &_pDispParams->rgvarg[0];
if (!V_UNKNOWN(pvarArg) ||
(VT_DISPATCH != V_VT(pvarArg) &&
VT_UNKNOWN != V_VT(pvarArg)))
{
hr = E_INVALIDARG;
goto Cleanup;
}
if (0 != (dwAccess & EOA_EVENTOBJ) &&
!_pEventObj)
{
hr = V_UNKNOWN(pvarArg)->QueryInterface(IID_IHTMLEventObj, (void **)&_pEventObj);
if (hr)
goto Cleanup;
}
if (dwAccess & EOA_EVENTOBJ2 &&
!_pEventObj2)
{
hr = V_UNKNOWN(pvarArg)->QueryInterface(IID_IHTMLEventObj2, (void **)&_pEventObj2);
if (hr)
goto Cleanup;
}
Cleanup:
return hr;
}
HRESULT
CEventObjectAccess::GetScreenCoordinates(POINT * ppt)
{
HRESULT hr = S_OK;
if (!_fEventPropertiesInitialized)
{
hr = InitializeEventProperties();
if (hr)
goto Cleanup;
}
*ppt = _EventProperties.ptScreen;
Cleanup:
return hr;
}
HRESULT
CEventObjectAccess::GetWindowCoordinates(POINT * ppt)
{
HRESULT hr = S_OK;
if (!_fEventPropertiesInitialized)
{
hr = InitializeEventProperties();
if (hr)
goto Cleanup;
}
*ppt = _EventProperties.ptClient;
Cleanup:
return hr;
}
HRESULT
CEventObjectAccess::GetParentCoordinates(POINT * ppt)
{
HRESULT hr = S_OK;
if (!_fEventPropertiesInitialized)
{
hr = InitializeEventProperties();
if (hr)
goto Cleanup;
}
*ppt = _EventProperties.ptElem;
Cleanup:
return hr;
}
HRESULT
CEventObjectAccess::GetKeyCode(long * pl)
{
HRESULT hr = S_OK;
if (!_fEventPropertiesInitialized)
{
hr = InitializeEventProperties();
if (hr)
goto Cleanup;
}
*pl = _EventProperties.lKey;
Cleanup:
return hr;
}
HRESULT
CEventObjectAccess::GetMouseButtons(long * pl)
{
HRESULT hr = S_OK;
if (!_fEventPropertiesInitialized)
{
hr = InitializeEventProperties();
if (hr)
goto Cleanup;
}
*pl = _EventProperties.lMouseButtons;
Cleanup:
return hr;
}
HRESULT
CEventObjectAccess::GetKeyboardStatus(long * pl)
{
HRESULT hr = S_OK;
if (!_fEventPropertiesInitialized)
{
hr = InitializeEventProperties();
if (hr)
goto Cleanup;
}
*pl = _EventProperties.lKeys;
Cleanup:
return hr;
}
HRESULT
CEventObjectAccess::InitializeEventProperties()
{
HRESULT hr = S_OK;
VARIANT_BOOL b;
BOOL fAltKey = FALSE;
BOOL fCtrlKey = FALSE;
BOOL fShiftKey = FALSE;
BOOL fLeft = FALSE;
BOOL fRight = FALSE;
BOOL fMiddle = FALSE;
long lMouseButtons;
if (!_pEventObj)
{
hr = Open(EOA_EVENTOBJ);
if (hr)
goto Cleanup;
}
// KeyboardStatus
hr = _pEventObj->get_altKey(&b);
if (hr)
goto Cleanup;
fAltKey = (b == VARIANT_TRUE);
hr = _pEventObj->get_ctrlKey(&b);
if (hr)
goto Cleanup;
fCtrlKey = (b == VARIANT_TRUE);
hr = _pEventObj->get_shiftKey(&b);
if (hr)
goto Cleanup;
fShiftKey = (b == VARIANT_TRUE);
_EventProperties.lKeys = (fAltKey ? EVENT_ALTKEY : 0) | (fCtrlKey ? EVENT_CTRLKEY : 0) | (fShiftKey ? EVENT_SHIFTKEY : 0);
// MouseButtons
hr = _pEventObj->get_button(&lMouseButtons);
if (hr)
goto Cleanup;
fLeft = (lMouseButtons == 1) || (lMouseButtons == 3) || (lMouseButtons == 5) || (lMouseButtons == 7);
fRight = (lMouseButtons == 2) || (lMouseButtons == 3) || (lMouseButtons == 6) || (lMouseButtons == 7);
fMiddle = (lMouseButtons == 4) || (lMouseButtons == 5) || (lMouseButtons == 6) || (lMouseButtons == 7);
_EventProperties.lMouseButtons = ( fLeft ? EVENT_LEFTBUTTON : 0)
| (fRight ? EVENT_RIGHTBUTTON : 0)
| (fMiddle ? EVENT_MIDDLEBUTTON : 0);
// KeyCode
hr = _pEventObj->get_keyCode(&_EventProperties.lKey);
if (hr)
goto Cleanup;
// ParentCoordinates
hr = _pEventObj->get_x(&_EventProperties.ptElem.x);
if (hr)
goto Cleanup;
hr = _pEventObj->get_y(&_EventProperties.ptElem.y);
if (hr)
goto Cleanup;
// WindowCoordinates
hr = _pEventObj->get_clientX(&_EventProperties.ptClient.x);
if (hr)
goto Cleanup;
hr = _pEventObj->get_clientY(&_EventProperties.ptClient.y);
if (hr)
goto Cleanup;
// ScreenCoordinates
hr = _pEventObj->get_screenX(&_EventProperties.ptScreen.x);
if (hr)
goto Cleanup;
hr = _pEventObj->get_screenY(&_EventProperties.ptScreen.y);
if (hr)
goto Cleanup;
_fEventPropertiesInitialized = TRUE;
Cleanup:
return hr;
}
/////////////////////////////////////////////////////////////////////////////
//
// Misc helpers
//
/////////////////////////////////////////////////////////////////////////////
void *
MemAllocClear(size_t cb)
{
void * pv = malloc(cb);
if (pv)
{
memset (pv, 0, cb);
}
return pv;
}
HRESULT
LoadLibrary(char *achLibraryName, HINSTANCE *hInst)
{
DWORD dwError;
Assert(achLibraryName);
Assert(hInst);
*hInst = NULL;
// Try to load the library using the normal mechanism.
*hInst = ::LoadLibraryA(achLibraryName);
#ifdef WIN16
if ( (UINT) *hInst < 32 )
goto Error;
#endif
#if !defined(WIN16) && !defined(WINCE)
// If that failed because the module was not be found,
// then try to find the module in the directory we were
// loaded from.
if (!*hInst)
{
dwError = ::GetLastError();
if ( dwError == ERROR_MOD_NOT_FOUND
|| dwError == ERROR_DLL_NOT_FOUND)
{
char achBuf1[MAX_PATH];
char achBuf2[MAX_PATH];
char *pch;
// Get path name of this module.
if (::GetModuleFileNameA(NULL, achBuf1, ARRAY_SIZE(achBuf1)) == 0)
goto Error;
// Find where the file name starts in the module path.
if (::GetFullPathNameA(achBuf1, ARRAY_SIZE(achBuf2), achBuf2, &pch) == 0)
goto Error;
// Chop off the file name to get a directory name.
*pch = 0;
// See if there's a dll with the given name in the directory.
if (::SearchPathA(
achBuf2,
achLibraryName,
NULL,
ARRAY_SIZE(achBuf1),
achBuf1,
NULL) != 0)
{
// Yes, there's a dll. Load it.
*hInst = ::LoadLibraryExA(
achBuf1,
NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
}
}
}
#endif // !defined(WIN16) && !defined(WINCE)
if (!*hInst)
{
goto Error;
}
return S_OK;
Error:
dwError = GetLastError();
return dwError ? HRESULT_FROM_WIN32(dwError) : E_FAIL;
}
//+----------------------------------------------------------------------------
//
// Member : AccessAllowed
//
// Synopsis : Internal helper. this function is part of the behavior security
// model for this tag. We only allow layout rects to be trusted if they're
// within a trusted dialog.
//
//-----------------------------------------------------------------------------
BOOL
TemplateAccessAllowed(IElementBehaviorSite *pISite)
{
#ifdef TEMPLATE_TESTING
return TRUE;
#else
HRESULT hr;
IHTMLElement * pElem = NULL;
IDispatch * pDoc = NULL;
IOleCommandTarget * pioct = NULL;
VARIANT varRet;
MSOCMD msocmd;
if (!pISite)
return FALSE;
VariantInit(&varRet);
msocmd.cmdID = IDM_ISTRUSTEDDLG;
msocmd.cmdf = 0;
hr = pISite->GetElement(&pElem);
if (FAILED(hr))
goto Cleanup;
hr = pElem->get_document(&pDoc);
if (FAILED(hr))
goto Cleanup;
hr = pDoc->QueryInterface(IID_IOleCommandTarget, (void**)&pioct);
if (hr)
goto Cleanup;
hr = pioct->Exec(&CGID_MSHTML, IDM_GETPRINTTEMPLATE, NULL, NULL, &varRet);
Cleanup:
ReleaseInterface(pElem);
ReleaseInterface(pDoc);
ReleaseInterface(pioct);
return (hr || V_VT(&varRet) != VT_BOOL || V_BOOL(&varRet) != VB_TRUE) ? FALSE : TRUE;
#endif
}
//------------------------------------------------------------------------------
//---------------------------------- Wrappers ----------------------------------
//------------------------------------------------------------------------------
STDAPI
SHGetFolderPathA(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pchPath)
{
HMODULE hDLL = NULL;
void * pfnSHGetFolderPath = NULL ;
if (g_fUseShell32InsteadOfSHFolder)
{
hDLL = LoadLibraryA("shell32.dll");
if (hDLL)
{
pfnSHGetFolderPath = GetProcAddress(hDLL, "SHGetFolderPathA");
if(!pfnSHGetFolderPath)
{
FreeLibrary(hDLL);
hDLL = NULL;
}
}
}
if (!hDLL)
{
hDLL = LoadLibraryA("shfolder.dll");
if (hDLL)
{
pfnSHGetFolderPath = GetProcAddress(hDLL, "SHGetFolderPathA");
if(!pfnSHGetFolderPath)
{
FreeLibrary(hDLL);
hDLL = NULL;
}
}
}
if (pfnSHGetFolderPath)
{
HRESULT hr = (*(HRESULT (STDAPICALLTYPE *)(HWND, int, HANDLE, DWORD, LPSTR))pfnSHGetFolderPath)
(hwnd, csidl, hToken, dwFlags, pchPath);
FreeLibrary(hDLL);
return hr;
}
return E_FAIL;
}