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

1251 lines
36 KiB
C++

//===============================================================
//
// rectpeer.cxx : Implementation of the CLayoutRect Peer
//
// Synposis : this class is repsponsible for handling the "generic"
// containership for view templates. It is the XML-ish tag <layout:Rect>
//
//===============================================================
#include "headers.h"
#pragma MARK_DATA(__FILE__)
#pragma MARK_CODE(__FILE__)
#pragma MARK_CONST(__FILE__)
#ifndef __X_IEXTAG_H_
#define __X_IEXTAG_H_
#include "iextag.h"
#endif
#ifndef __X_RECTPEER_HXX_
#define __X_RECTPEER_HXX_
#include "rectpeer.hxx"
#endif
#ifndef __X_UTILS_HXX_
#define __X_UTILS_HXX_
#include "utils.hxx"
#endif
#ifndef X_SHLGUID_H_
#define X_SHLGUID_H_
#include <shlguid.h>
#endif
#ifndef MSHTMHST_H_
#define MSHTMHST_H_
#include <mshtmhst.h>
#endif
#ifndef MSHTMCID_H_
#define MSHTMCID_H_
#include <mshtmcid.h>
#endif
#define CheckResult(x) { hr = x; if (FAILED(hr)) goto Cleanup; }
//+----------------------------------------------------------------------------
//
// DTOR
//
//-----------------------------------------------------------------------------
CLayoutRect::~CLayoutRect()
{
Detach();
}
//+----------------------------------------------------------------------------
//
// Member : Detach - IElementBehavior method impl
//
// Synopsis : when the peer is detatched, we will take this oppurtunity
// to release our various cached pointers.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::Detach()
{
CDataObject * pDO = NULL;
long i=0;
ClearInterface( &_pPeerSite );
for (pDO = &_aryAttributes[0], i=0;
pDO && i< eAttrTotal;
pDO++, i++)
{
pDO->ClearContents();
}
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Member : Init - IElementBehavior method impl
//
// Synopsis : this method is called by MSHTML.dll to initialize peer object.
// this is where we do all the connection and peer management work.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::Init(IElementBehaviorSite * pPeerSite)
{
HRESULT hr = S_OK;
VARIANT varParam;
CContextAccess ca(pPeerSite);
if (!pPeerSite)
{
hr = E_INVALIDARG;
goto Cleanup;
}
// some of our attributes have default values
V_BOOL(&_aryAttributes[eHonorPageBreaks]._varValue) = VB_TRUE;
V_VT(&_aryAttributes[eHonorPageBreaks]._varValue) = VT_BOOL;
V_BOOL(&_aryAttributes[eHonorPageRules]._varValue) = VB_TRUE;
V_VT(&_aryAttributes[eHonorPageRules]._varValue) = VT_BOOL;
// cache our peer element
_pPeerSite = pPeerSite;
_pPeerSite->AddRef();
// set up our default style sheet
ca.Open(CA_SITEOM | CA_DEFAULTS | CA_DEFSTYLE);
// The contents of layout rects shouldn't inherit styles from outside;
// we're like frames.
CheckResult( ca.Defaults()->put_viewInheritStyle( VB_FALSE ) );
CheckResult( ca.DefStyle()->put_overflow(CComBSTR("hidden")));
V_VT(&varParam) = VT_BSTR;
V_BSTR(&varParam) = SysAllocString(_T("300px"));
if (!V_BSTR(&varParam))
goto Cleanup;
CheckResult( ca.DefStyle()->put_width(varParam));
VariantClear(&varParam);
V_VT(&varParam) = VT_BSTR;
V_BSTR(&varParam) = SysAllocString(_T("150px"));
if (!V_BSTR(&varParam))
goto Cleanup;
CheckResult( ca.DefStyle()->put_height(varParam));
VariantClear(&varParam);
Cleanup:
return hr;
}
//+----------------------------------------------------------------------------
//
// Member : Notify - IElementBehavior method impl
//
// Synopsis : peer Interface, called for notification of document events.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::Notify(LONG lEvent, VARIANT *)
{
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Member : get_nextRect - ILayoutRect property impl
// : put_nextRect - ILayoutRect property impl
//
// Synopsis : property get'er. returns the next element in the container chain
// : property put'er. sets the next element in the container chain
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::get_nextRect(BSTR * pbstrNextId)
{
TEMPLATESECURITYCHECK()
if ( !pbstrNextId )
return E_POINTER;
return _aryAttributes[eNextRect].GetAsBSTR( pbstrNextId );
}
STDMETHODIMP
CLayoutRect::put_nextRect(BSTR bstrNextId )
{
TEMPLATESECURITYCHECK()
return _aryAttributes[eNextRect].Set(bstrNextId);
}
STDMETHODIMP
CLayoutRect::get_media(BSTR * pbstrMedia)
{
TEMPLATESECURITYCHECK()
// (greglett) This won't ever be used. Don't confuse the caller. Let them know.
return E_NOTIMPL;
}
STDMETHODIMP
CLayoutRect::put_media(BSTR bstrMedia )
{
TEMPLATESECURITYCHECK()
// (greglett) This won't ever be used. Don't confuse the caller. Let them know.
return E_NOTIMPL;
}
//+----------------------------------------------------------------------------
//
// Member : get_contentSrc - ILayoutRect property impl
// : put_contentSrc - ILayoutRect property impl
//
// Synopsis : property get'er. returns the String of the content ULR
// : property put'er. sets the string of the content URL
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::get_contentSrc(VARIANT * pvarSrc)
{
TEMPLATESECURITYCHECK()
if (!pvarSrc)
return E_POINTER;
return VariantCopy(pvarSrc, &(_aryAttributes[eContentSrc]._varValue));
}
STDMETHODIMP
CLayoutRect::put_contentSrc(VARIANT varSrc)
{
HRESULT hr;
if (!TemplateAccessAllowed(_pPeerSite))
{
PutBlankViewLink();
return E_ACCESSDENIED;
}
hr = VariantCopy(&(_aryAttributes[eContentSrc]._varValue), &varSrc);
if (hr)
goto Cleanup;
if (V_VT(&varSrc) == VT_BSTR)
{
hr = PutViewLink(V_BSTR(&varSrc));
}
else if ( V_VT(&varSrc) == VT_UNKNOWN
|| V_VT(&varSrc) == VT_DISPATCH)
{
hr = PutViewLink(V_UNKNOWN(&varSrc));
}
else
{
hr = E_INVALIDARG;
}
if (hr)
goto Cleanup;
Cleanup:
return hr;
}
//+----------------------------------------------------------------------
//
// Helper : PutViewLink
//
// Handles an IUnknown and routes it to the relevant PutViewLink function
//
//-----------------------------------------------------------------------
HRESULT
CLayoutRect::PutViewLink(IUnknown * pUnk )
{
HRESULT hr = E_FAIL;
IHTMLDocument2 * pISlaveDoc = NULL; // Slave document
IStream * pIStream = NULL; // OE Express header stream
if (!pUnk)
{
hr = E_INVALIDARG;
goto Cleanup;
}
// Are we an HTML document?
if ( !pUnk->QueryInterface(IID_IHTMLDocument2, (void**)&pISlaveDoc)
&& pISlaveDoc)
{
hr = PutViewLink(pISlaveDoc);
}
// Are we a stream from which to load an HTML document?
else if ( !pUnk->QueryInterface(IID_IStream, (void **)&pIStream)
&& pIStream)
{
hr = PutViewLink(pIStream);
}
Cleanup:
ReleaseInterface(pISlaveDoc);
ReleaseInterface(pIStream);
return hr;
}
//+----------------------------------------------------------------------
//
// Helper : PutViewLink
//
// Handles a IHTMLDocument2 input so that we can set up table-of-links.
// The second one handles strings, so that
// we can connect to "document" or to a specific URL
//
//-----------------------------------------------------------------------
HRESULT
CLayoutRect::PutViewLink(IHTMLDocument2 * pISlaveDoc )
{
HRESULT hr = S_OK;
IHTMLElement * pIBody = NULL; // From input document
IHTMLElement * pIBodyNew = NULL; // From (slave) document copy.
IHTMLDocument * pINewSlaveDoc = NULL;
IHTMLDocument4 * pINewSlaveDoc4= NULL; // Copied document.
IDispatch * pIDDocNewSlave= NULL; // Copied Document
IElementBehaviorSiteOM2 * pIBS = NULL;
IHTMLElementDefaults * pIPThis = NULL;
IOleCommandTarget * pioctNewSlave = NULL;
IHTMLElement * pIElement = NULL;
IDispatch * pIDDoc = NULL;
IHTMLDocument2 * pIThisDoc2 = NULL;
BSTR bstrTagName = NULL;
BSTR bstrHTML = NULL;
BSTR bstrMedia = NULL;
VARIANT var;
VariantInit(&var);
if (!pISlaveDoc)
{
hr = E_POINTER;
goto Cleanup;
}
// Get the body and save its innerHTML
hr = pISlaveDoc->get_body(&pIBody);
if (FAILED(hr))
goto Cleanup;
if (!pIBody)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIBody->get_innerHTML(&bstrHTML);
if (FAILED(hr))
goto Cleanup;
if (!bstrHTML)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIBody->get_tagName(&bstrTagName);
if (FAILED(hr))
goto Cleanup;
if (!bstrTagName)
{
hr = E_FAIL;
goto Cleanup;
}
// Set the media to print on the BODY markup before we parse in the stream string.
bstrMedia = SysAllocString(_T("print"));
if (!bstrMedia)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
// Create an element to act as the viewlinked document.
Assert(_pPeerSite);
hr = _pPeerSite->GetElement(&pIElement);
if (FAILED(hr))
goto Cleanup;
if (!pIElement)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIElement->get_document(&pIDDoc);
if (FAILED(hr))
goto Cleanup;
if (!pIDDoc)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIDDoc->QueryInterface(IID_IHTMLDocument2, (void **)&pIThisDoc2);
if (FAILED(hr))
goto Cleanup;
if (!pIThisDoc2)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIThisDoc2->createElement(bstrTagName, &pIBodyNew);
if (FAILED(hr))
goto Cleanup;
if (!pIBodyNew)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIBodyNew->get_document(&pIDDocNewSlave);
if (FAILED(hr))
goto Cleanup;
if (!pIDDocNewSlave)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIDDocNewSlave->QueryInterface(IID_IHTMLDocument4, (void **)&pINewSlaveDoc4);
if (FAILED(hr))
goto Cleanup;
if (!pINewSlaveDoc4)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIDDocNewSlave->QueryInterface(IID_IOleCommandTarget, (void **)&pioctNewSlave);
if (FAILED(hr))
goto Cleanup;
if (!pioctNewSlave)
{
hr = E_FAIL;
goto Cleanup;
}
//
// (greglett) 11/27/2000
// There are two types of Print Media
// 1. (per element) WYSIWYG mesurement. Set by the DeviceRect.
// 2. (per markup) A combination of "is paginated media", "is a print content document", and "should apply printing rules like no bg, media styles..."
// It is crucial to set the first two here right now.
// We only allowed print media to be set on a print template in 5.5 for a few reasons:
// 1. The combination of the above three properties is arbitrary and confusing enough that it would be impossible to explain.
// 2. Why would someone who is not a print template be interetsted in displaying as if printing?
// 3. Incorrect worries about security issues in setting print media (URL spoofing, metafile running, &c...)
// The first two reasons are still valid, so Trident still blocks this for anything other than print templates in 6.0.
// This used to not be an issue, since print-templateness was a CDoc level thing. Now that it is per markup...
// This is nonsensical. In fact, *no* paginated/print content documents should be print templates, and vice-versa.
// For Blackcomb, we really need to refactor what "Print Media" means.
//
V_VT(&var) = VT_BOOL;
V_BOOL(&var) = VB_TRUE;
hr = pioctNewSlave->Exec( &CGID_MSHTML,
IDM_SETPRINTTEMPLATE,
NULL,
&var,
NULL);
if (FAILED(hr))
goto Cleanup;
hr = pINewSlaveDoc4->put_media(bstrMedia);
if (FAILED(hr))
goto Cleanup;
V_BOOL(&var) = VB_FALSE;
hr = pioctNewSlave->Exec( &CGID_MSHTML,
IDM_SETPRINTTEMPLATE,
NULL,
&var,
NULL);
if (FAILED(hr))
goto Cleanup;
// Reparse in the innerHTML, so that all media properties will get picked up
hr = pIBodyNew->put_innerHTML(bstrHTML);
if (FAILED(hr))
goto Cleanup;
// Viewlink the slave doc.
Assert(_pPeerSite);
hr = _pPeerSite->QueryInterface(IID_IElementBehaviorSiteOM2, (void**)&pIBS);
if (FAILED(hr))
goto Cleanup;
if (!pIBS)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIBS->GetDefaults(&pIPThis);
if (FAILED(hr))
goto Cleanup;
if (!pIPThis)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pINewSlaveDoc4->QueryInterface(IID_IHTMLDocument, (void**)&pINewSlaveDoc);
if (FAILED(hr))
goto Cleanup;
if (!pINewSlaveDoc)
{
hr = E_FAIL;
goto Cleanup;
}
hr = pIPThis->putref_viewLink(pINewSlaveDoc);
if (FAILED(hr))
goto Cleanup;
Cleanup:
ReleaseInterface(pIBody);
ReleaseInterface(pIBodyNew);
ReleaseInterface(pIDDocNewSlave);
ReleaseInterface(pINewSlaveDoc);
ReleaseInterface(pINewSlaveDoc4);
ReleaseInterface(pIPThis);
ReleaseInterface(pIBS);
ReleaseInterface(pioctNewSlave);
ReleaseInterface(pIElement);
ReleaseInterface(pIDDoc);
ReleaseInterface(pIThisDoc2);
SysFreeString(bstrHTML);
SysFreeString(bstrTagName);
SysFreeString(bstrMedia);
return hr;
}
//+----------------------------------------------------------------------
//
// Helper : PutViewLink
//
// Handles a IHTMLDocument2 input so that we can set up table-of-links.
// The second one handles strings, so that
// we can connect to "document" or to a specific URL
//
//-----------------------------------------------------------------------
#define UNICODE_MARKER 0xfeff
HRESULT
CLayoutRect::PutViewLink(IStream * pIStream)
{
HRESULT hr = S_OK;
IHTMLElement * pIElement = NULL;
IDispatch * pIDDoc = NULL;
IHTMLDocument2 * pIThisDoc2 = NULL;
IHTMLDocument2 * pISlaveDoc2 = NULL;
IHTMLDocument4 * pISlaveDoc4 = NULL;
IDispatch * pIDDocSlave = NULL;
IHTMLElement * pBodyNew = NULL;
IElementBehaviorSiteOM2 * pIBS = NULL;
IHTMLElementDefaults * pIPThis = NULL;
IOleCommandTarget * pioctSlave = NULL;
BSTR bstrBody = NULL;
BSTR bstrHTML = NULL;
BSTR bstrMedia = NULL;
VARIANT var;
CBufferedStr strContent;
LARGE_INTEGER lnOffset;
VariantInit(&var);
if (!pIStream)
{
hr = E_POINTER;
goto Cleanup;
}
lnOffset.HighPart = 0;
lnOffset.LowPart = 0;
pIStream->Seek(lnOffset, STREAM_SEEK_SET, NULL);
// Read the OE header. We need the *whole* thing to pass in as an innerHTML.
{
BOOL fUnicode;
WCHAR chUnicodeMarker = UNICODE_MARKER;
WCHAR achBufWC[1024];
CHAR achBufMB[1024];
ULONG cRead;
hr = pIStream->Read(achBufWC, sizeof(WCHAR), &cRead);
if (!hr)
{
fUnicode = (memcmp(achBufWC, &chUnicodeMarker, sizeof(WCHAR)) == 0);
if (!fUnicode)
pIStream->Seek(lnOffset, STREAM_SEEK_SET, NULL); // Put it back! We took off two real MB characters
while ( hr == S_OK
&& cRead > 0 )
{
if (fUnicode)
{
hr = pIStream->Read(achBufWC, 1023 * sizeof(WCHAR), &cRead);
cRead /= sizeof(WCHAR);
}
else
{
hr = pIStream->Read(achBufMB, 1023 * sizeof(CHAR), &cRead);
cRead = MultiByteToWideChar(CP_ACP, 0, achBufMB, cRead, achBufWC, 1023);
}
if (cRead > 0)
{
achBufWC[cRead] = _T('\0');
strContent.QuickAppend(achBufWC);
}
}
}
}
// Create a BODY to act as the viewlinked document.
hr = _pPeerSite->GetElement(&pIElement);
if (FAILED(hr))
goto Cleanup;
Assert(pIElement);
hr = pIElement->get_document(&pIDDoc);
if (FAILED(hr))
goto Cleanup;
Assert(pIDDoc);
bstrBody = SysAllocString(_T("BODY"));
if (!bstrBody)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
hr = pIDDoc->QueryInterface(IID_IHTMLDocument2, (void **)&pIThisDoc2);
if (FAILED(hr))
goto Cleanup;
Assert(pIThisDoc2);
hr = pIThisDoc2->createElement(bstrBody, &pBodyNew);
if (FAILED(hr))
goto Cleanup;
Assert(pBodyNew);
bstrHTML = SysAllocString(strContent);
if (!bstrHTML)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
// Set the media to print on the BODY markup before we parse in the stream string.
bstrMedia = SysAllocString(_T("print"));
if (!bstrMedia)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
hr = pBodyNew->get_document(&pIDDocSlave);
if (FAILED(hr))
goto Cleanup;
Assert(pIDDocSlave);
hr = pIDDocSlave->QueryInterface(IID_IHTMLDocument4, (void **)&pISlaveDoc4);
if (FAILED(hr))
goto Cleanup;
Assert(pISlaveDoc4);
hr = pIDDocSlave->QueryInterface(IID_IOleCommandTarget, (void **)&pioctSlave);
if (FAILED(hr))
goto Cleanup;
Assert(pioctSlave);
//
// (greglett) 11/27/2000
// There are two types of Print Media
// 1. (per element) WYSIWYG mesurement. Set by the DeviceRect.
// 2. (per markup) A combination of "is paginated media", "is a print content document", and "should apply printing rules like no bg, media styles..."
// It is crucial to set the first two here right now.
// We only allowed print media to be set on a print template in 5.5 for a few reasons:
// 1. The combination of the above three properties is arbitrary and confusing enough that it would be impossible to explain.
// 2. Why would someone who is not a print template be interetsted in displaying as if printing?
// 3. Incorrect worries about security issues in setting print media (URL spoofing, metafile running, &c...)
// The first two reasons are still valid, so Trident still blocks this for anything other than print templates in 6.0.
// This used to not be an issue, since print-templateness was a CDoc level thing. Now that it is per markup...
// This is nonsensical. In fact, *no* paginated/print content documents should be print templates, and vice-versa.
// For Blackcomb, we really need to refactor what "Print Media" means.
//
V_VT(&var) = VT_BOOL;
V_BOOL(&var) = VB_TRUE;
hr = pioctSlave->Exec( &CGID_MSHTML,
IDM_SETPRINTTEMPLATE,
NULL,
&var,
NULL);
if (FAILED(hr))
goto Cleanup;
hr = pISlaveDoc4->put_media(bstrMedia);
if (FAILED(hr))
goto Cleanup;
V_BOOL(&var) = VB_FALSE;
hr = pioctSlave->Exec( &CGID_MSHTML,
IDM_SETPRINTTEMPLATE,
NULL,
&var,
NULL);
if (FAILED(hr))
goto Cleanup;
// innerHTML in the contents of the stream as the new document...
hr = pBodyNew->put_innerHTML(bstrHTML);
if (FAILED(hr))
goto Cleanup;
// ...and viewlink the document.
hr = pIDDocSlave->QueryInterface(IID_IHTMLDocument2, (void **)&pISlaveDoc2);
if (FAILED(hr))
goto Cleanup;
Assert(pISlaveDoc2);
Assert(_pPeerSite);
hr = _pPeerSite->QueryInterface(IID_IElementBehaviorSiteOM2, (void**)&pIBS);
if (FAILED(hr))
goto Cleanup;
Assert(pIBS);
hr = pIBS->GetDefaults(&pIPThis);
if (FAILED(hr))
goto Cleanup;
Assert(pIPThis);
hr = pIPThis->putref_viewLink(pISlaveDoc2);
if (FAILED(hr))
goto Cleanup;
Cleanup:
ReleaseInterface(pIElement);
ReleaseInterface(pIDDoc);
ReleaseInterface(pISlaveDoc2);
ReleaseInterface(pISlaveDoc4);
ReleaseInterface(pIDDocSlave);
ReleaseInterface(pIThisDoc2);
ReleaseInterface(pBodyNew);
ReleaseInterface(pIPThis);
ReleaseInterface(pIBS);
ReleaseInterface(pioctSlave);
SysFreeString(bstrBody);
SysFreeString(bstrHTML);
SysFreeString(bstrMedia);
return hr;
}
//+----------------------------------------------------------------------
//
// Helper : PutViewLink
//
// Handles a BSTR input to connect to "document" or a specific URL.
//
//-----------------------------------------------------------------------
HRESULT
CLayoutRect::PutViewLink(BSTR bstrSrc)
{
HRESULT hr;
IElementBehaviorSite * pIPeerSite = _pPeerSite; // interface to our peer
IHTMLElement * pIThis = NULL; // Interface to this element
IHTMLElementDefaults * pIPThis = NULL; // Interface to this's element defaults
IDispatch * pIThisDocDispatch = NULL; // The doc we're in
IHTMLDocument4 * pIThisDoc4 = NULL; // Same, so we can get to contentFromUrl
IHTMLDocument2 * pISlaveDoc = NULL; // Slave document
IElementBehaviorSiteOM2 * pIBS = NULL;
IHTMLDialog * pIDialog = NULL;
IServiceProvider * pIDocSrvProv = NULL;
IHTMLEventObj2 * pIEventObj = NULL;
BSTR bstrOptions = NULL;
BSTR bstrURL = NULL;
VARIANT vunkDialogArg;
VARIANT vbstrContentDoc;
VARIANT vbIsXML;
VariantInit(&vunkDialogArg);
VariantInit(&vbstrContentDoc);
VariantInit(&vbIsXML);
Assert(bstrSrc);
if (!bstrSrc)
{
hr = E_INVALIDARG;
goto Cleanup;
}
hr = pIPeerSite->GetElement(&pIThis);
if (FAILED(hr))
goto Cleanup;
hr = pIThis->get_document(&pIThisDocDispatch);
if (FAILED(hr))
goto Cleanup;
hr = pIThisDocDispatch->QueryInterface(IID_IHTMLDocument4, (void**)&pIThisDoc4);
if (FAILED(hr))
goto Cleanup;
// Get the dialog arguments, if they exist
hr = pIThisDocDispatch->QueryInterface(IID_IServiceProvider, (void **)&pIDocSrvProv);
if (!FAILED(hr))
{
// The keyword "document" maps to the dialog argument __IE_ContentDocumentUrl. Go after it.
hr = pIDocSrvProv->QueryService(IID_IHTMLDialog, IID_IHTMLDialog, (void**)&pIDialog);
if (!FAILED(hr))
{
hr = pIDialog->get_dialogArguments(&vunkDialogArg);
if (FAILED(hr) || V_VT(&vunkDialogArg) != VT_UNKNOWN)
goto Cleanup;
hr = V_UNKNOWN(&vunkDialogArg)->QueryInterface(IID_IHTMLEventObj2, (void**)&pIEventObj);
if (FAILED(hr))
goto Cleanup;
}
}
if (V_VT(&vunkDialogArg) != VT_UNKNOWN)
{
bstrOptions = SysAllocString( _T("print") );
bstrURL = bstrSrc;
}
else
{
BSTR bstrTarget=NULL;
bstrTarget = SysAllocString(_T("__IE_ContentDocumentUrl"));
if (!bstrTarget)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
hr = pIEventObj->getAttribute(bstrTarget, 0, &vbstrContentDoc);
SysFreeString(bstrTarget);
if (FAILED(hr) || V_VT(&vbstrContentDoc) != VT_BSTR)
goto Cleanup;
// We now have the content document URL in vbstrContentDoc. Either
if ( !_tcsicmp(bstrSrc, _T("document"))
|| !_tcsicmp(bstrSrc, V_BSTR(&vbstrContentDoc)) )
{
bstrTarget = SysAllocString(_T("__IE_ParsedXML"));
if (!bstrTarget)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
hr = pIEventObj->getAttribute(bstrTarget, 0, &vbIsXML);
SysFreeString(bstrTarget);
// Are we an already parsed XML document (with HTML:xxx tags)?
if ( !FAILED(hr)
&& V_VT(&vbIsXML) == VT_BOOL
&& V_BOOL(&vbIsXML) == VB_TRUE )
{
bstrOptions = SysAllocString( _T("print xml") );
}
else
{
bstrOptions = SysAllocString( _T("print") );
}
bstrURL = V_BSTR(&vbstrContentDoc);
}
else
{
bstrOptions = SysAllocString( _T("print") );
bstrURL = bstrSrc;
}
}
if ( !bstrOptions )
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
Assert(bstrURL);
hr = pIThisDoc4->createDocumentFromUrl(bstrURL, bstrOptions, &pISlaveDoc);
if (FAILED(hr))
goto Cleanup;
hr = pIPeerSite->QueryInterface(IID_IElementBehaviorSiteOM2, (void**)&pIBS);
if (FAILED(hr))
goto Cleanup;
hr = pIBS->GetDefaults(&pIPThis);
if (FAILED(hr))
goto Cleanup;
hr = pIPThis->putref_viewLink(pISlaveDoc);
if (FAILED(hr))
goto Cleanup;
Cleanup:
SysFreeString( bstrOptions );
ReleaseInterface(pIThis);
ReleaseInterface(pIPThis);
ReleaseInterface(pIThisDocDispatch);
ReleaseInterface(pIThisDoc4);
ReleaseInterface(pISlaveDoc);
ReleaseInterface(pIBS);
ReleaseInterface(pIDialog);
ReleaseInterface(pIDocSrvProv);
ReleaseInterface(pIEventObj);
VariantClear(&vunkDialogArg);
VariantClear(&vbstrContentDoc);
return hr;
}
//+----------------------------------------------------------------------
//
// Helper : PutBlankViewLink
//
// Does a PutViewLink for "about:blank"
//
//-----------------------------------------------------------------------
HRESULT CLayoutRect::PutBlankViewLink()
{
HRESULT hr;
BSTR bstrBlank = SysAllocString(_T("about:blank"));
if (!bstrBlank)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
hr = PutViewLink(bstrBlank);
Cleanup:
if (bstrBlank)
SysFreeString(bstrBlank);
return hr;
}
//+----------------------------------------------------------------------------
//
// Member : get_honorPageBreaks - ILayoutRect property imple
// : put_honorPageBreaks - ILayoutRect property imple
//
// Synopsis : Get'r and put'r for the boolean property on whether to honorPageBreaks
// within this tag. By default this is true.
//
//+----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::get_honorPageBreaks (VARIANT_BOOL * pVB)
{
TEMPLATESECURITYCHECK()
return _aryAttributes[eHonorPageBreaks].GetAsBOOL(pVB);
}
STDMETHODIMP
CLayoutRect::put_honorPageBreaks (VARIANT_BOOL v)
{
TEMPLATESECURITYCHECK()
return _aryAttributes[eHonorPageBreaks].Set(v);
}
//+----------------------------------------------------------------------------
//
// Member : get_honorPageRules - ILayoutRect property imple
// : put_honorPageRules - ILayoutRect property imple
//
// Synopsis : Get'r and put'r for the boolean property on whether to honorPageRules
// within this tag. By default this is true.
//
//+----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::get_honorPageRules (VARIANT_BOOL * pVB)
{
TEMPLATESECURITYCHECK()
return _aryAttributes[eHonorPageRules].GetAsBOOL(pVB);
}
STDMETHODIMP
CLayoutRect::put_honorPageRules (VARIANT_BOOL v)
{
TEMPLATESECURITYCHECK()
return _aryAttributes[eHonorPageRules].Set(v);
}
//+----------------------------------------------------------------------------
//
// Member : get_nextRectElement - ILayoutRect property imple
// : put_nextRectElement - ILayoutRect property imple
//
// Synopsis : Get'r and put'r for the IDispatch property for the nextRect.
//
//+----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::get_nextRectElement (IDispatch ** ppElem)
{
TEMPLATESECURITYCHECK()
// (greglett) This is not currently used, and we don't want to do the work to get this
// working in the Whistler timeframe.
return E_NOTIMPL;
//return _aryAttributes[eNextRectElement].GetAsDispatch( ppElem );
}
STDMETHODIMP
CLayoutRect::put_nextRectElement (IDispatch * pElem)
{
TEMPLATESECURITYCHECK()
// (greglett) This is not currently used, and we don't want to do the work to get this
// working in the Whistler timeframe.
return E_NOTIMPL;
//return _aryAttributes[eNextRectElement].Set( pElem );
}
//+----------------------------------------------------------------------------
//
// Member : get_contentDocument - ILayoutRect property imple
// : put_contentDocument - ILayoutRect property imple
//
// Synopsis : Get'r and put'r for the IDispatch property for the contentDocument.
//
//+----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::get_contentDocument(IDispatch ** ppDoc)
{
TEMPLATESECURITYCHECK()
// get peer, get IHTMLElement, get ViewLink, get document
HRESULT hr = S_OK;
IElementBehaviorSite * pPeerSite = _pPeerSite;
IElementBehaviorSiteOM2 * pIBS = NULL;
IHTMLElementDefaults * pIPThis = NULL;
if (!ppDoc)
return E_POINTER;
*ppDoc = NULL;
hr = pPeerSite->QueryInterface(IID_IElementBehaviorSiteOM2, (void**)&pIBS);
if (hr)
goto Cleanup;
hr = pIBS->GetDefaults(&pIPThis);
if (hr)
goto Cleanup;
hr = pIPThis->get_viewLink((IHTMLDocument **)ppDoc);
hr = S_OK;
Cleanup:
ReleaseInterface(pIBS);
ReleaseInterface(pIPThis);
return hr;
}
//+----------------------------------------------------------------------------
//
// Member : Load - IPersistPropertyBag2 property impl
//
// Synopsis : This gives us a chance to pull properties from the property bag
// created when the element's attributes were parsed in. Since we handle
// all the getter/putter logic, our copy of the value will always be the
// current one. This gives this behavior full control over the attribures
// that it is interested in.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::Load ( IPropertyBag2 *pPropBag, IErrorLog *pErrLog)
{
HRESULT hr = S_OK;
IPropertyBag * pBag = NULL;
CDataObject * pDO = NULL;
long i=0;
if (!pPropBag)
{
hr = E_POINTER;
goto Cleanup;
}
hr = pPropBag->QueryInterface(IID_IPropertyBag, (void**) &pBag);
if (hr || !pBag)
goto Cleanup;
// loop through all the attributes and load them
for (pDO = &_aryAttributes[0], i=0;
pDO && i< eAttrTotal;
pDO++, i++)
{
pBag->Read(pDO->_pstrPropertyName, &pDO->_varValue, pErrLog);
}
BSTR bstr;
_aryAttributes[eContentSrc].GetAsBSTR(&bstr);
if (bstr)
{
if (TemplateAccessAllowed(_pPeerSite))
PutViewLink(bstr);
else
PutBlankViewLink();
}
Cleanup:
ReleaseInterface(pBag);
return hr;
}
//+----------------------------------------------------------------------------
//
// Member : Save - IPersistPropertyBag2 property impl
//
// Synopsis : Like the load, above, this allows us to save the attributes which
// we control. This is all part of fully owning our element's behavior, OM
// and attributes.
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::Save ( IPropertyBag2 *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
{
HRESULT hr = S_OK;
IPropertyBag * pBag = NULL;
CDataObject * pDO = NULL;
long i=0;
// verify parameters
if (!pPropBag)
{
hr = E_POINTER;
goto Cleanup;
}
// now go through our properties and save them if they are dirty, or if
// a save-All is required.
//---------------------------------------------------------------------
hr = pPropBag->QueryInterface(IID_IPropertyBag, (void**) &pBag);
if (hr || !pBag)
goto Cleanup;
for (pDO = &_aryAttributes[0], i=0;
pDO && i< eAttrTotal;
pDO++, i++)
{
if (pDO->IsDirty() || fSaveAllProperties)
{
if (V_VT(&pDO->_varValue) != VT_DISPATCH)
{
pBag->Write(pDO->_pstrPropertyName, &(pDO->_varValue));
if (fClearDirty)
pDO->_fDirty = FALSE;
}
}
}
Cleanup:
ReleaseInterface(pBag);
return hr;
}
//+-----------------------------------------------------------------------------
//
// Method: Draw, IHTMLPainter
//
//------------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::Draw(RECT rcBounds, RECT rcUpdate, LONG lDrawFlags, HDC hdc,
LPVOID pvDrawObject)
{
return E_NOTIMPL;
}
//+-----------------------------------------------------------------------------
//
// Method: GetRenderInfo, IHTMLPainter
//
//------------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::GetPainterInfo(HTML_PAINTER_INFO * pInfo)
{
Assert(pInfo != NULL);
*pInfo = _hpi;
return S_OK;
}
//+-----------------------------------------------------------------------------
//
// Method: HitTestPoint, IHTMLPainter
//
//------------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::HitTestPoint(POINT pt, BOOL * pbHit, LONG *plPartID)
{
Assert(pbHit != NULL);
*pbHit = TRUE;
return S_OK;
}
//+-----------------------------------------------------------------------------
//
// Method: OnResize, IHTMLPainter
//
//------------------------------------------------------------------------------
STDMETHODIMP
CLayoutRect::OnResize(SIZE size)
{
return S_OK;
}