// DHTMLEdit.cpp : Implementation of CDHTMLEdit and CDHTMLSafe
// Copyright (c)1997-1999 Microsoft Corporation, All Rights Reserved
#include "stdafx.h"
#include "DHTMLEd.h"
#include "DHTMLEdit.h"
#include "proxyframe.h"
#include "site.h"
/////////////////////////////////////////////////////////////////////////////
// CDHTMLSafe
CDHTMLSafe::CDHTMLSafe()
{
m_bWindowOnly = TRUE; // A window is needed when we activate Trident.
m_pFrame = NULL;
m_piControlSite = NULL;
m_fJustCreated = TRUE;
m_piOuterEditCtl = (IDHTMLEdit*)-1; // Crash if we use this without properly initializing it.
m_bfOuterEditUnknownTested = NULL;
}
CDHTMLSafe::~CDHTMLSafe()
{
}
HRESULT CDHTMLSafe::FinalConstruct()
{
HRESULT hr E_FAIL;
m_pFrame = new CProxyFrame(this);
_ASSERTE(m_pFrame);
if (NULL == m_pFrame)
return E_OUTOFMEMORY;
// not aggregating TriEdit -- don't get
// reference to its pUnk;
hr = m_pFrame->Init(NULL, NULL);
_ASSERTE(SUCCEEDED(hr));
if (FAILED(hr))
{
m_pFrame->Release ();
m_pFrame = NULL;
}
return hr;
}
void CDHTMLSafe::FinalRelease()
{
if ( NULL != m_piControlSite )
{
m_piControlSite->Release ();
m_piControlSite = NULL;
}
if (NULL != m_pFrame)
{
if (m_pFrame->IsCreated())
{
_ASSERTE(FALSE == m_pFrame->IsActivated());
m_pFrame->Close();
}
m_pFrame->Release ();
m_pFrame = NULL;
}
}
HRESULT CDHTMLSafe::OnDraw(ATL_DRAWINFO& di)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
if (NULL == m_pFrame)
return E_UNEXPECTED;
if (IsUserMode() == FALSE)
{
HBRUSH hgreyBrush = NULL;
hgreyBrush = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
RECT& rc = *(RECT*)di.prcBounds;
Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
FillRect(di.hdcDraw, &rc, hgreyBrush);
return S_OK;
}
else if (IsUserMode() && m_pFrame->IsCreated() == TRUE && m_pFrame->IsActivated() == FALSE)
{
_ASSERTE(m_bInPlaceActive == TRUE);
hr = m_pFrame->LoadInitialDoc();
}
return hr;
}
LRESULT
CDHTMLSafe::OnSize(UINT /*nMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& lResult)
{
m_pFrame->UpdateObjectRects();
lResult = TRUE;
return 0;
}
STDMETHODIMP CDHTMLSafe::TranslateAccelerator(LPMSG lpmsg)
{
HRESULT hr = S_OK;
hr = m_pFrame->HrTranslateAccelerator(lpmsg);
return hr;
}
STDMETHODIMP CDHTMLSafe::OnMnemonic(LPMSG /*pMsg*/)
{
return S_FALSE;
}
STDMETHODIMP CDHTMLSafe::SetClientSite(IOleClientSite *pClientSite)
{
HRESULT hr = S_OK;
if ( NULL == pClientSite )
{
_ASSERTE ( m_pFrame );
if ( NULL != m_pFrame )
{
_ASSERTE(m_pFrame->IsCreated());
hr = m_pFrame->Close();
_ASSERTE(SUCCEEDED(hr));
}
}
return IOleObject_SetClientSite ( pClientSite );
}
LRESULT
CDHTMLSafe::OnDestroy(UINT /*nMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*lResult*/)
{
HRESULT hr = S_OK;
// This would, in turn, destroy the hosted Trident's window.
if ( NULL != m_pFrame )
{
_ASSERTE(m_pFrame->IsCreated());
_ASSERTE ( m_hWndCD );
m_pFrame->SetParent ( NULL );
}
return hr;
}
LRESULT
CDHTMLSafe::OnCreate(UINT /*nMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*lResult*/)
{
if ( NULL != m_pFrame )
{
_ASSERTE(m_pFrame->IsCreated());
_ASSERTE ( m_hWndCD );
m_pFrame->SetParent ( m_hWndCD );
}
return 0;
}
LRESULT
CDHTMLSafe::OnShow(UINT /*nMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*lResult*/)
{
if ( NULL != m_pFrame )
{
_ASSERTE(m_pFrame->IsCreated());
m_pFrame->Show ( wParam );
}
return 0;
}
// Do our best to set the focus on the ControlSite.
// m_piControlSite is obtained on demand, and released in FinalRelease.
//
void
CDHTMLSafe::FocusSite ( BOOL bfGetFocus )
{
if ( NULL == m_piControlSite )
{
_ASSERTE ( m_spClientSite );
if ( m_spClientSite )
{
m_spClientSite->QueryInterface ( IID_IOleControlSite, (void**)&m_piControlSite );
}
}
if ( m_piControlSite )
{
m_piControlSite->OnFocus ( bfGetFocus );
}
}
LRESULT
CDHTMLSafe::OnSetFocus(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& lResult)
{
lResult = FALSE; // Pass it on to the default event handler if not handled by Frame.
_ASSERTE ( m_pFrame );
if ( NULL != m_pFrame )
{
// If its the Trident instance loosing the focus, let's not set it right back again!
// Also, if it has not yet been UIActivated, don't risk inplace deactivationg with this:
if ( m_pFrame->GetDocWindow() != (HWND)wParam )
{
FocusSite ( TRUE );
return m_pFrame->OnSetFocus ( nMsg, wParam, lParam, lResult );
}
}
return 0;
}
// This message is posted in OnReadyStateChanged.
// This postpones firing DocumentComplete until MSHTML is actually complete.
//
LRESULT
CDHTMLSafe::OnDocumentComplete(UINT /*nMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& lResult)
{
_ASSERTE ( DOCUMENT_COMPETE_SIGNATURE == wParam );
if ( DOCUMENT_COMPETE_SIGNATURE == wParam )
{
lResult = TRUE;
m_pFrame->ClearLoadingFlag ();
Fire_DocumentComplete();
}
return 0;
}
STDMETHODIMP CDHTMLSafe::OnAmbientPropertyChange(DISPID /*dispID*/)
{
HRESULT hr = S_OK;
// There may be some VB ambients we may want to handle here
// in the future for VB debugging.
return hr;
}
// IE5 security settings for Paste, and possibly for Copy and Cut, require that we call
// ITHMLDocument2->execCommand for testing.
//
HRESULT CDHTMLSafe::SpecialEdit ( DHTMLEDITCMDID cmdID, OLECMDEXECOPT cmdexecopt )
{
HRESULT hr = S_OK;
CComPtr spDOM = NULL;
VARIANT_BOOL vbResult = VARIANT_FALSE;
CComBSTR bstrCommand;
CComVariant varValue;
// Regression: The point of SpecialEdit was to call execCommand rather than Exec for the
// editing commands and allow Trident to do the corss-zone security checks, but this has
// broken. (Bug 547802.) In response, we now check the cross-zone security of the current
// selection ourselves. We stick with execCommand to minimize impact on behavior.
hr = m_pFrame->CheckCrossZoneSecurityOfSelection ();
if ( SUCCEEDED ( hr ) )
{
hr = get_DOM ( &spDOM );
if ( SUCCEEDED ( hr ) )
{
switch ( cmdID )
{
case DECMD_CUT:
bstrCommand = L"Cut";
break;
case DECMD_COPY:
bstrCommand = L"Copy";
break;
case DECMD_PASTE:
bstrCommand = L"Paste";
break;
default:
return E_UNEXPECTED;
}
hr = spDOM->execCommand ( bstrCommand, cmdexecopt == OLECMDEXECOPT_PROMPTUSER, varValue, &vbResult );
}
}
return hr;
}
// To be Safe for Scripting, restrict the range of cmdIDs to a known set.
// Handle edit commands specially to utilize IE5's security settings.
//
STDMETHODIMP CDHTMLSafe::ExecCommand(DHTMLEDITCMDID cmdID, OLECMDEXECOPT cmdexecopt, LPVARIANT pInVar, LPVARIANT pOutVar)
{
HRESULT hr = S_OK;
LPVARIANT _pVarIn = NULL;
LPVARIANT _pVarOut = NULL;
// It is valid for pVar to be VT_EMPTY (on a DECMD_GETXXX op) but not VT_ERROR
if (pInVar && (V_VT(pInVar) != VT_ERROR))
_pVarIn = pInVar;
if (pOutVar && (V_VT(pOutVar) != VT_ERROR))
_pVarOut = pOutVar;
if ( ( cmdexecopt < OLECMDEXECOPT_DODEFAULT ) ||
( cmdexecopt > OLECMDEXECOPT_DONTPROMPTUSER ) )
{
return E_INVALIDARG;
}
// Special case for editing commands in Safe for Scripting version:
if ( ( DECMD_CUT == cmdID ) || ( DECMD_COPY == cmdID ) || ( DECMD_PASTE == cmdID ) )
{
return SpecialEdit ( cmdID, cmdexecopt );
}
hr = m_pFrame->HrMapExecCommand(cmdID, cmdexecopt, _pVarIn, _pVarOut);
return hr;
}
STDMETHODIMP CDHTMLSafe::QueryStatus(DHTMLEDITCMDID cmdID, DHTMLEDITCMDF* retval)
{
HRESULT hr = S_OK;
hr = m_pFrame->HrMapQueryStatus(cmdID, retval);
return hr;
}
// Get Document Object Model
//
STDMETHODIMP CDHTMLSafe::get_DOM(IHTMLDocument2 ** pVal)
{
HRESULT hr = S_OK;
_ASSERTE(pVal);
if (NULL == pVal)
return E_INVALIDARG;
*pVal = NULL;
hr = m_pFrame->HrGetDoc(pVal);
return hr;
}
STDMETHODIMP CDHTMLSafe::get_DocumentHTML(BSTR * pVal)
{
HRESULT hr = S_OK;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetDocumentHTML(pVal);
return hr;
}
STDMETHODIMP CDHTMLSafe::put_DocumentHTML(BSTR newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetDocumentHTML(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_DOCUMENTHTML );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_ActivateApplets(VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetPropActivateApplets(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::put_ActivateApplets(VARIANT_BOOL newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetPropActivateApplets(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_ACTIVATEAPPLETS );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_ActivateActiveXControls(VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetPropActivateControls(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::put_ActivateActiveXControls(VARIANT_BOOL newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetPropActivateControls(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_ACTIVATEACTIVEXCONTROLS );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_ActivateDTCs(VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetPropActivateDTCs(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::put_ActivateDTCs(VARIANT_BOOL newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetPropActivateDTCs(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_ACTIVATEDTCS );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_ShowDetails(VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetPropShowAllTags(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::put_ShowDetails(VARIANT_BOOL newVal)
{
_ASSERTE(m_pFrame);
SetDirty ( TRUE );
FireOnChanged ( DISPID_SHOWDETAILS );
return m_pFrame->HrSetPropShowAllTags(newVal);
}
STDMETHODIMP CDHTMLSafe::get_ShowBorders(VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetPropShowBorders(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::put_ShowBorders(VARIANT_BOOL newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetPropShowBorders(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_SHOWBORDERS );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_Appearance(DHTMLEDITAPPEARANCE * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetDisplay3D(bVal);
*pVal = (bVal) ? DEAPPEARANCE_3D : DEAPPEARANCE_FLAT;
return hr;
}
STDMETHODIMP CDHTMLSafe::put_Appearance(DHTMLEDITAPPEARANCE newVal)
{
HRESULT hr = S_OK;
BOOL bVal = (newVal == DEAPPEARANCE_3D) ? TRUE : FALSE;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetDisplay3D(bVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_DHTMLEDITAPPEARANCE );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_Scrollbars(VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetScrollbars(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::put_Scrollbars(VARIANT_BOOL newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetScrollbars(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_DHTMLEDITSCROLLBARS );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_ScrollbarAppearance(DHTMLEDITAPPEARANCE * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetDisplayFlatScrollbars(bVal);
*pVal = (bVal) ? DEAPPEARANCE_FLAT : DEAPPEARANCE_3D;
return hr;
}
STDMETHODIMP CDHTMLSafe::put_ScrollbarAppearance(DHTMLEDITAPPEARANCE newVal)
{
HRESULT hr = S_OK;
BOOL bVal = (newVal == DEAPPEARANCE_3D) ? FALSE : TRUE;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetDisplayFlatScrollbars(bVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_SCROLLBARAPPEARANCE );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_SourceCodePreservation(VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetPreserveSource(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::put_SourceCodePreservation(VARIANT_BOOL newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetPreserveSource(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_SOURCECODEPRESERVATION );
}
return hr;
}
///////////////////////////////////////
STDMETHODIMP CDHTMLSafe::get_AbsoluteDropMode(VARIANT_BOOL* pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetAbsoluteDropMode(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::put_AbsoluteDropMode(VARIANT_BOOL newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetAbsoluteDropMode(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_ABSOLUTEDROPMODE );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_SnapToGrid(VARIANT_BOOL* pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetSnapToGrid(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::put_SnapToGrid(VARIANT_BOOL newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetSnapToGrid(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_SNAPTOGRID );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_SnapToGridX(LONG* pVal)
{
HRESULT hr = S_OK;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetSnapToGridX(*pVal);
return hr;
}
STDMETHODIMP CDHTMLSafe::put_SnapToGridX(LONG newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetSnapToGridX(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_SNAPTOGRIDX );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_SnapToGridY(LONG* pVal)
{
HRESULT hr = S_OK;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetSnapToGridY(*pVal);
return hr;
}
STDMETHODIMP CDHTMLSafe::put_SnapToGridY(LONG newVal)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
hr = m_pFrame->HrSetSnapToGridY(newVal);
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_SNAPTOGRIDY );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_CurrentDocumentPath(BSTR * pVal)
{
HRESULT hr = S_OK;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (!pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetCurrentDocumentPath(pVal);
return hr;
}
STDMETHODIMP CDHTMLSafe::get_IsDirty(VARIANT_BOOL * pVal)
{
HRESULT hr = S_OK;
BOOL bVal = FALSE;
_ASSERTE(pVal);
_ASSERTE(m_pFrame);
if (NULL == pVal)
return E_INVALIDARG;
hr = m_pFrame->HrGetIsDirty(bVal);
#pragma warning(disable: 4310) // cast truncates constant value
*pVal = (TRUE == bVal) ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
STDMETHODIMP CDHTMLSafe::get_BaseURL(/* [retval][out] */ BSTR *baseURL)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
_ASSERTE ( baseURL );
if ( NULL == baseURL )
{
return E_INVALIDARG;
}
CComBSTR bstr;
hr = m_pFrame->GetBaseURL ( bstr );
if ( SUCCEEDED ( hr ) )
{
SysReAllocString ( baseURL, bstr );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::put_BaseURL(/* [in] */ BSTR baseURL)
{
HRESULT hr = S_OK;
_ASSERTE(m_pFrame);
_ASSERTE ( baseURL );
if ( NULL == baseURL )
{
return E_INVALIDARG;
}
CComBSTR bstr = baseURL;
hr = m_pFrame->SetBaseURL ( bstr );
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_BASEURL );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_DocumentTitle(/* [retval][out] */ BSTR *docTitle)
{
HRESULT hr = S_OK;
_ASSERTE ( docTitle );
_ASSERTE ( m_pFrame );
if ( NULL == docTitle )
{
return E_INVALIDARG;
}
CComBSTR bstr;
hr = m_pFrame->GetDocumentTitle ( bstr );
if ( SUCCEEDED ( hr ) )
{
SysReAllocString ( docTitle, bstr );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::get_UseDivOnCarriageReturn ( VARIANT_BOOL *pVal )
{
_ASSERTE ( pVal );
if ( NULL == pVal )
{
return E_INVALIDARG;
}
return m_pFrame->GetDivOnCr ( pVal );
}
STDMETHODIMP CDHTMLSafe::get_Busy ( VARIANT_BOOL *pVal )
{
_ASSERTE ( pVal );
if ( NULL == pVal )
{
return E_INVALIDARG;
}
return m_pFrame->GetBusy ( pVal );
}
STDMETHODIMP CDHTMLSafe::put_UseDivOnCarriageReturn ( VARIANT_BOOL newVal )
{
HRESULT hr = S_OK;
hr = m_pFrame->SetDivOnCr( newVal );
if ( SUCCEEDED ( hr ) )
{
SetDirty ( TRUE );
FireOnChanged ( DISPID_USEDIVONCR );
}
return hr;
}
STDMETHODIMP CDHTMLSafe::SetContextMenu(/*[in]*/LPVARIANT menuStrings, /*[in]*/ LPVARIANT menuStates)
{
HRESULT hr = S_OK;
hr = m_pFrame->SetContextMenu(menuStrings, menuStates);
return hr;
}
STDMETHODIMP CDHTMLSafe::NewDocument ()
{
HRESULT hr = E_FAIL;
_ASSERTE ( m_pFrame );
if ( NULL == m_pFrame )
{
return E_UNEXPECTED;
}
hr = m_pFrame->LoadDocument( NULL );
return hr;
}
STDMETHODIMP CDHTMLSafe::Refresh ()
{
HRESULT hr = E_FAIL;
_ASSERTE ( m_pFrame );
if ( NULL == m_pFrame )
{
return E_UNEXPECTED;
}
hr = m_pFrame->RefreshDoc ();
return hr;
}
// In the safe for scripting version, only the http: protocol is permitted.
//
STDMETHODIMP CDHTMLSafe::LoadURL ( BSTR url )
{
HRESULT hr = S_OK;
CComBSTR rbstrSafeProtocols[] = { L"http://", L"https://", L"ftp://" };
_ASSERTE(url);
_ASSERTE ( m_pFrame );
if ( NULL == m_pFrame )
{
return E_UNEXPECTED;
}
if ( ( NULL == url ) || ( 0 == SysStringLen ( url ) ) )
return E_INVALIDARG;
// Check for the protocol:
CComBSTR bstrURL = url;
_wcslwr ( bstrURL.m_str );
BOOL bfSafe = FALSE;
for ( int iProtocol = 0;
iProtocol < ( sizeof ( rbstrSafeProtocols ) / sizeof ( CComBSTR ) );
iProtocol++ )
{
if ( 0 == wcsncmp ( bstrURL.m_str, rbstrSafeProtocols[iProtocol],
rbstrSafeProtocols[iProtocol].Length () ) )
{
bfSafe = TRUE;
break;
}
}
hr = m_pFrame->CheckCrossZoneSecurity ( url );
if ( SUCCEEDED ( hr ) )
{
hr = DE_E_UNKNOWN_PROTOCOL;
if ( bfSafe )
{
hr = m_pFrame->LoadDocument( url, TRUE );
}
}
return hr;
}
STDMETHODIMP CDHTMLSafe::FilterSourceCode(BSTR sourceCodeIn, BSTR* sourceCodeOut)
{
HRESULT hr;
_ASSERTE ( sourceCodeIn );
_ASSERTE ( sourceCodeOut );
if ( ( NULL == sourceCodeIn ) || ( NULL == sourceCodeOut ) )
{
return E_INVALIDARG;
}
*sourceCodeOut = NULL;
hr = m_pFrame->FilterSourceCode ( sourceCodeIn, sourceCodeOut );
return hr;
}
// Override handler for IOleInPlaceObject->UIDeactivate to fire the blur event.
//
HRESULT CDHTMLSafe::IOleInPlaceObject_UIDeactivate ( void )
{
Fire_onblur();
m_pFrame->UIDeactivate();
return CComControlBase::IOleInPlaceObject_UIDeactivate ();
}
// Override IOleObjectImpl methods
// We must set the object as dirty when resized
//
HRESULT CDHTMLSafe::IOleObject_SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
{
if ((m_sizeExtent.cx != psizel->cx || m_sizeExtent.cy != psizel->cy) && !m_fJustCreated)
SetDirty(TRUE);
m_fJustCreated = FALSE;
return CComControlBase::IOleObject_SetExtent(dwDrawAspect, psizel);
}
HRESULT CDHTMLSafe::IPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, ATL_PROPMAP_ENTRY*)
{
return CComControlBase::IPersistStreamInit_Save ( pStm, fClearDirty, ProperPropMap() );
}
HRESULT CDHTMLSafe::IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY*)
{
return CComControlBase::IPersistStreamInit_Load ( pStm, ProperPropMap() );
}
HRESULT CDHTMLSafe::IPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties, ATL_PROPMAP_ENTRY* )
{
return CComControlBase::IPersistPropertyBag_Save(pPropBag, fClearDirty, fSaveAllProperties, ProperPropMap());
}
HRESULT CDHTMLSafe::IPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY*)
{
return CComControlBase::IPersistPropertyBag_Load(pPropBag, pErrorLog, ProperPropMap());
}
// We cannot QI for the OuterEditControl in the FinalConstruct, or we crash whenever
// we're aggregated. So, we QI on demand.
// Call this routine to get the outer control's unknown, never use m_piOuterEditCtl
// directly.
// NOTE:
// This routine DOES NOT addref the interface returned! Do not release it!
//
IDHTMLEdit * CDHTMLSafe::GetOuterEditControl ()
{
if ( ! m_bfOuterEditUnknownTested )
{
m_bfOuterEditUnknownTested = TRUE;
// Keep an un-addreffed pointer to the aggregating DHTMLEdit control, if it exists.
if ( SUCCEEDED ( GetControllingUnknown()->QueryInterface ( IID_IDHTMLEdit, (void**)&m_piOuterEditCtl ) ) )
{
_ASSERTE ( m_piOuterEditCtl );
m_piOuterEditCtl->Release ();
}
}
_ASSERTE ( (IDHTMLEdit*)-1 != m_piOuterEditCtl );
return m_piOuterEditCtl;
}
// There are two property maps to choose from.
// Return the one for the DHTMLEdit control if it's aggregating us,
// else return our own.
//
ATL_PROPMAP_ENTRY* CDHTMLSafe::ProperPropMap ()
{
IDHTMLEdit *piOuterEditControl = GetOuterEditControl ();
if ( NULL == piOuterEditControl )
{
return CDHTMLSafe::GetPropertyMap();
}
else
{
return CDHTMLEdit::GetPropertyMap();
}
}
// Return the appropriate CLSID, depending on whether we're the safe or unsafe control.
//
HRESULT CDHTMLSafe::GetClassID( CLSID *pClassID )
{
IDHTMLEdit *piOuterEditControl = GetOuterEditControl ();
if ( NULL == piOuterEditControl )
{
*pClassID = CLSID_DHTMLSafe;
}
else
{
*pClassID = CLSID_DHTMLEdit;
}
return S_OK;
}
// The above redirecting of the PropertyMap doesn't work unless we override this method,
// We keep an un-addref'd pointer to the aggregating DHTMLEdit control if available.
// Addreffing it would cause a circular reference.
//
HRESULT CDHTMLSafe::ControlQueryInterface(const IID& iid, void** ppv)
{
HRESULT hr = S_OK;
IDHTMLEdit *piOuterEditControl = GetOuterEditControl ();
if ( NULL == piOuterEditControl )
{
hr = GetUnknown()->QueryInterface ( iid, ppv );
}
else
{
hr = piOuterEditControl->QueryInterface ( iid, ppv );
}
return hr;
}
////////////////////////////////////////////////////
//
// Event sink
//
class ATL_NO_VTABLE CEventXferSink :
public CComObjectRootEx,
public _DHTMLSafeEvents
{
public:
BEGIN_COM_MAP(CEventXferSink)
COM_INTERFACE_ENTRY_IID(DIID__DHTMLSafeEvents, _DHTMLSafeEvents)
END_COM_MAP()
CEventXferSink ()
{
m_pCtl = NULL;
}
void SetOwner ( CDHTMLEdit* pCtl )
{
_ASSERTE ( pCtl );
_ASSERTE ( NULL == m_pCtl );
if ( NULL == m_pCtl )
{
m_pCtl = pCtl;
}
}
STDMETHOD(GetTypeInfoCount) ( UINT * )
{
_ASSERTE ( FALSE );
return E_NOTIMPL;
}
STDMETHOD(GetTypeInfo) ( UINT, LCID, ITypeInfo ** )
{
_ASSERTE ( FALSE );
return E_NOTIMPL;
}
STDMETHOD(GetIDsOfNames) ( REFIID, OLECHAR **, UINT, LCID, DISPID * )
{
_ASSERTE ( FALSE );
return E_NOTIMPL;
}
STDMETHOD(Invoke) ( DISPID dispid, REFIID, LCID, USHORT, DISPPARAMS *pDispParams, VARIANT* /*pVarResult*/, EXCEPINFO *, UINT * )
{
HRESULT hr = E_UNEXPECTED;
_ASSERTE ( m_pCtl );
if ( NULL != m_pCtl )
{
switch ( dispid )
{
case DISPID_DOCUMENTCOMPLETE:
m_pCtl->Fire_DocumentComplete();
break;
case DISPID_DISPLAYCHANGED:
m_pCtl->Fire_DisplayChanged ();
break;
case DISPID_SHOWCONTEXTMENU:
{
CComVariant varParam;
long xPos = 0;
long yPos = 0;
unsigned int uiErr;
// There should be exactly two parameters.
_ASSERTE ( 2 == pDispParams->cArgs );
if (2 == pDispParams->cArgs )
{
hr = DispGetParam( pDispParams, 1, VT_I4, &varParam, &uiErr );
_ASSERTE ( SUCCEEDED ( hr ) );
if ( SUCCEEDED ( hr ) )
{
yPos = varParam.lVal;
hr = DispGetParam( pDispParams, 0, VT_I4, &varParam, &uiErr );
_ASSERTE ( SUCCEEDED ( hr ) );
if ( SUCCEEDED ( hr ) )
{
xPos = varParam.lVal;
m_pCtl->Fire_ShowContextMenu ( xPos, yPos );
}
}
}
break;
}
case DISPID_CONTEXTMENUACTION:
{
CComVariant varMenuIndex;
unsigned int uiErr;
// There should be exactly one parameter.
_ASSERTE ( 1 == pDispParams->cArgs );
if (1 == pDispParams->cArgs )
{
hr = DispGetParam( pDispParams, 0, VT_I4, &varMenuIndex, &uiErr );
_ASSERTE ( SUCCEEDED ( hr ) );
if ( SUCCEEDED ( hr ) )
{
long lMenuIndex = varMenuIndex.lVal;
m_pCtl->Fire_ContextMenuAction ( lMenuIndex );
}
}
break;
}
case DISPID_ONMOUSEDOWN:
m_pCtl->Fire_onmousedown ();
break;
case DISPID_ONMOUSEMOVE:
m_pCtl->Fire_onmousemove ();
break;
case DISPID_ONMOUSEUP:
m_pCtl->Fire_onmouseup ();
break;
case DISPID_ONMOUSEOUT:
m_pCtl->Fire_onmouseout ();
break;
case DISPID_ONMOUSEOVER:
m_pCtl->Fire_onmouseover ();
break;
case DISPID_ONCLICK:
m_pCtl->Fire_onclick ();
break;
case DISPID_ONDBLCLICK:
m_pCtl->Fire_ondblclick ();
break;
case DISPID_ONKEYDOWN:
m_pCtl->Fire_onkeydown ();
break;
case DISPID_ONKEYPRESS:
{
m_pCtl->Fire_onkeypress ();
#if 0
VARIANT_BOOL vbCancel;
vbCancel = m_pCtl->Fire_onkeypress ();
if ( NULL != pVarResult )
{
VariantClear ( pVarResult );
pVarResult->vt = VT_BOOL;
pVarResult->boolVal = vbCancel;
}
#endif
}
break;
case DISPID_ONKEYUP:
m_pCtl->Fire_onkeyup ();
break;
case DISPID_ONBLUR:
m_pCtl->Fire_onblur ();
break;
case DISPID_ONREADYSTATECHANGE:
m_pCtl->Fire_onreadystatechange ();
break;
default:
break;
}
}
return S_OK;
}
private:
CDHTMLEdit* m_pCtl;
};
////////////////////////////////////////////////////
//
// CDHTMLEdit implementation
//
CDHTMLEdit::CDHTMLEdit()
{
m_punkInnerCtl = NULL; // Aggregated control's IUnknown
m_pInnerCtl = NULL; // Aggregated control's custome interface
m_pInnerIOleObj = NULL; // Aggregated control's IOleObject
m_pXferSink = NULL; // Event sink for aggregated control
m_piInnerCtlConPt = NULL; // Connection point to aggregated control
m_pInterconnect = NULL; // Interface on inner control for communication
m_dwXferCookie = 0; // Cookie for aggregated control's connection point.
}
CDHTMLEdit::~CDHTMLEdit()
{
}
HRESULT CDHTMLEdit::FinalConstruct()
{
// Aggregate DHTMLSafe control:
HRESULT hr = E_FAIL;
IUnknown* punkContUnk = NULL;
punkContUnk = GetControllingUnknown ();
_ASSERTE ( punkContUnk );
hr = CoCreateInstance ( CLSID_DHTMLSafe, punkContUnk, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&m_punkInnerCtl );
if ( SUCCEEDED ( hr ) )
{
_ASSERTE ( m_punkInnerCtl );
hr = m_punkInnerCtl->QueryInterface ( IID_IOleObject, (void**)&m_pInnerIOleObj);
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( m_pInnerIOleObj );
punkContUnk->Release ();
hr = m_punkInnerCtl->QueryInterface ( IID_IDHTMLSafe, (void**)&m_pInnerCtl ); // This addrefs my unknown
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( m_pInnerCtl );
punkContUnk->Release ();
hr = m_punkInnerCtl->QueryInterface ( IID_IInterconnector, (void**)&m_pInterconnect ); // This addrefs my unknown
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( m_pInterconnect );
punkContUnk->Release ();
// Sink events from the aggregated control:
m_pXferSink = new CComObject;
// Check if the new worked
if(!m_pXferSink)
return E_OUTOFMEMORY;
m_pXferSink->AddRef ();
m_pXferSink->SetOwner ( this );
// Hook the sink up to the aggregated control:
CComQIPtrpicpc ( m_punkInnerCtl );
if ( picpc )
{
punkContUnk->Release ();
hr = picpc->FindConnectionPoint ( DIID__DHTMLSafeEvents, &m_piInnerCtlConPt );
if ( SUCCEEDED ( hr ) )
{
hr = m_piInnerCtlConPt->Advise ( static_cast(m_pXferSink), &m_dwXferCookie);
_ASSERTE ( SUCCEEDED ( hr ) );
}
}
}
_ASSERTE ( SUCCEEDED ( hr ) );
return hr;
}
void CDHTMLEdit::FinalRelease()
{
IUnknown* punkContUnk = NULL;
punkContUnk = GetControllingUnknown ();
_ASSERTE ( punkContUnk );
// Unadvise the event sink:
_ASSERTE ( m_pXferSink );
_ASSERTE ( m_piInnerCtlConPt );
if ( NULL != m_piInnerCtlConPt )
{
punkContUnk->AddRef ();
m_piInnerCtlConPt->Unadvise ( m_dwXferCookie );
m_piInnerCtlConPt->Release ();
m_piInnerCtlConPt = NULL;
}
if ( NULL != m_pXferSink )
{
m_pXferSink->Release ();
m_pXferSink = NULL;
}
if ( m_pInnerCtl )
{
// Releasing the cached interface will release my unknown, which has already been ballanced.
punkContUnk->AddRef ();
m_pInnerCtl->Release ();
}
if ( m_pInnerIOleObj )
{
punkContUnk->AddRef ();
m_pInnerIOleObj->Release ();
}
if ( m_pInterconnect )
{
punkContUnk->AddRef ();
m_pInterconnect->Release ();
}
if ( m_punkInnerCtl )
{
punkContUnk->AddRef ();
m_punkInnerCtl->Release ();
}
}
HRESULT
CDHTMLEdit::PromptOpenFile(LPTSTR pPath, ULONG ulPathLen)
{
HRESULT hr = S_OK;
OPENFILENAME ofn = {0};
BOOL bResult = FALSE;
HWND hWndCD = NULL;
_ASSERTE(pPath);
if (NULL == pPath)
return E_INVALIDARG;
hr = m_pInterconnect->GetCtlWnd ( (SIZE_T*)&hWndCD );
_ASSERTE ( SUCCEEDED ( hr ) );
if ( FAILED ( hr ) )
{
return ( SUCCEEDED ( hr ) ) ? E_UNEXPECTED : hr;
}
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.hwndOwner = hWndCD;
ofn.lpstrTitle = NULL;
ofn.lpstrFilter = TEXT("HTML Documents (*.htm, *.html)\0*.htm;*.html\0");
ofn.lpstrFile = pPath;
ofn.lpstrInitialDir = NULL;
ofn.lpstrDefExt = TEXT("htm");
ofn.nMaxFile = ulPathLen;
ofn.Flags = OFN_EXPLORER |
OFN_FILEMUSTEXIST |
OFN_PATHMUSTEXIST |
OFN_OVERWRITEPROMPT |
OFN_HIDEREADONLY;
bResult = GetOpenFileName(&ofn);
if (!bResult)
return S_FALSE;
return S_OK;
}
HRESULT
CDHTMLEdit::PromptSaveAsFile(LPTSTR pPath, ULONG ulPathLen)
{
HRESULT hr = S_OK;
OPENFILENAME ofn = {0};
BOOL bResult = FALSE;
HWND hWndCD = NULL;
_ASSERTE(pPath);
if (NULL == pPath)
return E_INVALIDARG;
hr = m_pInterconnect->GetCtlWnd ( (SIZE_T*)&hWndCD );
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( hWndCD );
if ( FAILED ( hr ) || ( NULL == hWndCD ) )
{
return ( SUCCEEDED ( hr ) ) ? E_UNEXPECTED : hr;
}
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.hwndOwner = hWndCD;
ofn.lpstrTitle = NULL;
ofn.lpstrFilter = TEXT("HTML Documents (*.htm, *.html)\0*.htm;*.html\0");
ofn.lpstrFile = pPath;
ofn.lpstrInitialDir = NULL;
ofn.lpstrDefExt = TEXT("htm");
ofn.nMaxFile = ulPathLen;
ofn.Flags = OFN_OVERWRITEPROMPT |
OFN_CREATEPROMPT |
OFN_HIDEREADONLY |
OFN_EXPLORER;
bResult = GetSaveFileName(&ofn);
if (!bResult)
return S_FALSE;
return S_OK;
}
STDMETHODIMP CDHTMLEdit::LoadDocument(LPVARIANT path, LPVARIANT promptUser)
{
USES_CONVERSION;
HRESULT hr = S_OK;
BOOL bPromptUser = NULL;
TCHAR promptPath[MAX_PATH] = {0};
CComBSTR bstrPath;
BSTR _path = NULL;
_ASSERTE(path);
CProxyFrame* pFrame = NULL;
hr = m_pInterconnect->GetInterconnector ( (SIZE_T*)&pFrame );
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( pFrame );
if ( FAILED ( hr ) || ( NULL == pFrame ) )
{
return ( SUCCEEDED ( hr ) ) ? E_UNEXPECTED : hr;
}
if (NULL == path || !(V_VT(path) == VT_BSTR || V_VT(path) == (VT_BSTR|VT_BYREF)))
return E_INVALIDARG;
// Note that it is valid for path to be NULL,
// In automation an empty string (BSTR) is a NULL pointer
// Passing in an emtpy string here allows for initializing TriEdit with
// an empty document (IPersistStreamInit->InitNew)
if (promptUser && (V_VT(promptUser) != VT_EMPTY && V_VT(promptUser) != VT_ERROR))
{
// note that if promptUser is not type VT_BOOL or VT_BOOL|VT_BYREF
// then user is not prompted
#pragma warning(disable: 4310) // cast truncates constant value
if (VT_BOOL == V_VT(promptUser))
bPromptUser = (VARIANT_TRUE == V_BOOL(promptUser)) ? TRUE : FALSE;
else if ((VT_BOOL|VT_BYREF) == V_VT(promptUser))
{
_ASSERTE(V_BOOLREF(promptUser));
if (V_BOOLREF(promptUser))
bPromptUser = (BOOL) (*(V_BOOLREF(promptUser)) == VARIANT_TRUE) ? TRUE : FALSE;
}
#pragma warning(default: 4310) // cast truncates constant value
}
// prompt user overrides any doc name that is specified
// Change VK:
// ...but the provided doc name is used as the default.
if (bPromptUser)
{
if ( NULL != path->bstrVal )
{
_tcsncpy ( promptPath, OLE2T(path->bstrVal), MAX_PATH );
}
hr = PromptOpenFile(promptPath, MAX_PATH);
if (S_FALSE == hr)
return S_OK;
bstrPath = promptPath;
_path = bstrPath;
}
else
{
if ((VT_BSTR|VT_BYREF) == V_VT(path) && V_BSTRREF(path))
_path = *(V_BSTRREF(path));
else if (VT_BSTR == V_VT(path) && V_BSTR(path))
_path = V_BSTR(path);
}
if ( 0 == SysStringLen ( _path ) )
{
return DE_E_INVALIDARG;
}
hr = pFrame->LoadDocument(_path);
return hr;
}
STDMETHODIMP CDHTMLEdit::SaveDocument(LPVARIANT path, LPVARIANT promptUser)
{
USES_CONVERSION;
HRESULT hr= S_OK;
TCHAR promptPath[MAX_PATH] = {0};
CComBSTR bstrPath;
BOOL bPromptUser = FALSE;
BSTR _path = NULL;
_ASSERTE(path);
CProxyFrame* pFrame = NULL;
hr = m_pInterconnect->GetInterconnector ( (SIZE_T*)&pFrame );
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( pFrame );
if ( FAILED ( hr ) || ( NULL == pFrame ) )
{
return ( SUCCEEDED ( hr ) ) ? E_UNEXPECTED : hr;
}
if (NULL == path || !(V_VT(path) == VT_BSTR || V_VT(path) == (VT_BSTR|VT_BYREF)))
return E_INVALIDARG;
// prompt user overrides any doc name that is specified
if (promptUser && (V_VT(promptUser) != VT_EMPTY && V_VT(promptUser) != VT_ERROR))
{
// note that if promptUser is not type VT_BOOL or VT_BOOL|VT_BYREF
// then user is not prompted
#pragma warning(disable: 4310) // cast truncates constant value
if (VT_BOOL == V_VT(promptUser))
bPromptUser = (VARIANT_TRUE == V_BOOL(promptUser)) ? TRUE : FALSE;
else if ((VT_BOOL|VT_BYREF) == V_VT(promptUser))
{
_ASSERTE(V_BOOLREF(promptUser));
if (V_BOOLREF(promptUser))
bPromptUser = (BOOL) (*(V_BOOLREF(promptUser)) == VARIANT_TRUE) ? TRUE : FALSE;
}
#pragma warning(default: 4310) // cast truncates constant value
}
// prompt user overrides any doc name that is specified
// Change VK:
// ...but the provided doc name is used as the default. If doc name is empty,
// and the doc was opened from a file, the original file name is provided as a default.
if (bPromptUser)
{
if ( NULL != path->bstrVal )
{
_tcsncpy ( promptPath, OLE2T(path->bstrVal), MAX_PATH );
if ( 0 == _tcslen ( promptPath ) )
{
CComBSTR bstrFileName;
if ( SUCCEEDED ( pFrame->GetCurDocNameWOPath ( bstrFileName ) ) )
{
_tcsncpy ( promptPath, OLE2T(bstrFileName), MAX_PATH );
}
}
}
hr = PromptSaveAsFile(promptPath, MAX_PATH);
if (S_FALSE == hr)
return S_OK;
bstrPath = promptPath;
_path = bstrPath;
}
else
{
if ((VT_BSTR|VT_BYREF) == V_VT(path) && V_BSTRREF(path))
_path = *(V_BSTRREF(path));
else if (VT_BSTR == V_VT(path) && V_BSTR(path))
_path = V_BSTR(path);
}
hr = pFrame->SaveDocument(_path);
return hr;
}
STDMETHODIMP CDHTMLEdit::LoadURL ( BSTR url )
{
HRESULT hr = E_FAIL;
CProxyFrame* pFrame = NULL;
hr = m_pInterconnect->GetInterconnector ( (SIZE_T*)&pFrame );
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( pFrame );
if ( FAILED ( hr ) || ( NULL == pFrame ) )
{
return ( SUCCEEDED ( hr ) ) ? E_UNEXPECTED : hr;
}
if ( ( NULL == url ) || ( 0 == SysStringLen ( url ) ) )
return E_INVALIDARG;
hr = pFrame->LoadDocument( url, TRUE );
return hr;
}
STDMETHODIMP CDHTMLEdit::PrintDocument ( VARIANT* pvarWithUI )
{
BOOL bfWithUI = FALSE;
HRESULT hr = E_FAIL;
CProxyFrame* pFrame = NULL;
hr = m_pInterconnect->GetInterconnector ( (SIZE_T*)&pFrame );
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( pFrame );
if ( FAILED ( hr ) || ( NULL == pFrame ) )
{
return ( SUCCEEDED ( hr ) ) ? E_UNEXPECTED : hr;
}
if ( NULL != pvarWithUI )
{
CComVariant varLocal = *pvarWithUI;
hr = varLocal.ChangeType ( VT_BOOL );
if ( SUCCEEDED ( hr ) )
{
bfWithUI = varLocal.boolVal; // VariantBool to Bool is safe, not the reverse.
}
}
hr = pFrame->Print ( bfWithUI );
return S_OK; // We can't return anything meaningful, because w/UI, Cancel returns E_FAIL.
}
STDMETHODIMP CDHTMLEdit::get_BrowseMode(/* [retval][out] */ VARIANT_BOOL *pVal)
{
HRESULT hr = S_OK;
CProxyFrame* pFrame = NULL;
hr = m_pInterconnect->GetInterconnector ( (SIZE_T*)&pFrame );
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( pFrame );
if ( FAILED ( hr ) || ( NULL == pFrame ) )
{
return ( SUCCEEDED ( hr ) ) ? E_UNEXPECTED : hr;
}
_ASSERTE ( pVal );
if ( NULL == pVal )
{
return E_INVALIDARG;
}
return pFrame->GetBrowseMode ( pVal );
}
STDMETHODIMP CDHTMLEdit::put_BrowseMode(/* [in] */ VARIANT_BOOL newVal)
{
HRESULT hr = S_OK;
CProxyFrame* pFrame = NULL;
hr = m_pInterconnect->GetInterconnector ( (SIZE_T*)&pFrame );
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( pFrame );
if ( FAILED ( hr ) || ( NULL == pFrame ) )
{
return ( SUCCEEDED ( hr ) ) ? E_UNEXPECTED : hr;
}
hr = pFrame->SetBrowseMode ( newVal );
if ( SUCCEEDED ( hr ) )
{
m_pInterconnect->MakeDirty ( DISPID_BROWSEMODE );
}
return hr;
}
// To be safe, restrict the range of cmdIDs to a known set.
//
STDMETHODIMP CDHTMLEdit::ExecCommand(DHTMLEDITCMDID cmdID, OLECMDEXECOPT cmdexecopt, LPVARIANT pInVar, LPVARIANT pOutVar)
{
HRESULT hr = S_OK;
LPVARIANT _pVarIn = NULL;
LPVARIANT _pVarOut = NULL;
CProxyFrame* pFrame = NULL;
hr = m_pInterconnect->GetInterconnector ( (SIZE_T*)&pFrame );
_ASSERTE ( SUCCEEDED ( hr ) );
_ASSERTE ( pFrame );
if ( FAILED ( hr ) || ( NULL == pFrame ) )
{
return ( SUCCEEDED ( hr ) ) ? E_UNEXPECTED : hr;
}
// It is valid for pVar to be VT_EMPTY (on a DECMD_GETXXX op) but not VT_ERROR
if (pInVar && (V_VT(pInVar) != VT_ERROR))
_pVarIn = pInVar;
if (pOutVar && (V_VT(pOutVar) != VT_ERROR))
_pVarOut = pOutVar;
if ( ( cmdexecopt < OLECMDEXECOPT_DODEFAULT ) ||
( cmdexecopt > OLECMDEXECOPT_DONTPROMPTUSER ) )
{
return E_INVALIDARG;
}
hr = pFrame->HrMapExecCommand(cmdID, cmdexecopt, _pVarIn, _pVarOut);
return hr;
}
/*
* IServiceProvider implementation
*/
STDMETHODIMP CDHTMLEdit::QueryService( REFGUID guidService, REFIID riid, void** ppvService )
{
*ppvService = NULL;
if ( SID_SInternetSecurityManager == guidService )
{
return GetUnknown()->QueryInterface ( riid, ppvService );
}
return E_NOINTERFACE;
}
/*
* IInternetSecurityManager implementation
*
* The purpose of this implementation is to OVERRIDE security and reduce it to the minimum.
* This should only be provided in Edit mode, not in browse mode. (Browse mode edits scripts.)
* This prevents warnings about unsafe for scripting DTCs, etc.
*
* From HTMED/TriSite, by Carlos Gomes.
*
*/
STDMETHODIMP CDHTMLEdit::GetSecurityId ( LPCWSTR /*pwszUrl*/, BYTE* /*pbSecurityId*/,
DWORD* /*pcbSecurityId*/, DWORD_PTR /*dwReserved*/ )
{
return INET_E_DEFAULT_ACTION;
}
STDMETHODIMP CDHTMLEdit::GetSecuritySite ( IInternetSecurityMgrSite** /*ppSite*/ )
{
return INET_E_DEFAULT_ACTION;
}
STDMETHODIMP CDHTMLEdit::GetZoneMappings ( DWORD /*dwZone*/, IEnumString** /*ppenumString*/, DWORD /*dwFlags*/ )
{
return INET_E_DEFAULT_ACTION;
}
STDMETHODIMP CDHTMLEdit::MapUrlToZone ( LPCWSTR /*pwszUrl*/, DWORD *pdwZone, DWORD /*dwFlags*/ )
{
if ( pdwZone != NULL )
{
*pdwZone = URLZONE_LOCAL_MACHINE;
return NOERROR;
}
return INET_E_DEFAULT_ACTION;
}
STDMETHODIMP CDHTMLEdit::ProcessUrlAction ( LPCWSTR /*pwszUrl*/, DWORD dwAction, BYTE* pPolicy, DWORD cbPolicy,
BYTE* /*pContext*/, DWORD /*cbContext*/, DWORD /*dwFlags*/, DWORD /*dwReserved*/ )
{
_ASSERTE ( pPolicy );
if ( NULL == pPolicy )
{
return E_INVALIDARG;
}
// Handle
// URLACTION_DOWNLOAD_SIGNED_ACTIVEX
// URLACTION_ACTIVEX_OVERRIDE_OBJECT_SAFETY
// URLACTION_ACTIVEX_OVERRIDE_DATA_SAFETY
// URLACTION_ACTIVEX_OVERRIDE_SCRIPT_SAFETY
// URLACTION_SCRIPT_OVERRIDE_SAFETY
// URLACTION_ACTIVEX_RUN
// URLACTION_ACTIVEX_CONFIRM_NOOBJECTSAFETY
// URLACTION_SCRIPT_SAFE_ACTIVEX
//
if(dwAction >= URLACTION_ACTIVEX_MIN && dwAction <= URLACTION_ACTIVEX_MAX)
{
if (cbPolicy >= sizeof(DWORD))
{
*(DWORD *)pPolicy = URLPOLICY_ALLOW;
return S_OK;
}
return S_FALSE;
}
//
// Handle
// URLACTION_DOWNLOAD_SIGNED_ACTIVEX
// URLACTION_DOWNLOAD_UNSIGNED_ACTIVEX
//
// BUG 597859: Disable download overrides; use default action instead.
//else if(dwAction >= URLACTION_DOWNLOAD_MIN && dwAction <= URLACTION_DOWNLOAD_MAX)
//{
// if (cbPolicy >= sizeof(DWORD))
// {
// *(DWORD *)pPolicy = URLPOLICY_ALLOW;
// return S_OK;
// }
// return S_FALSE;
//}
//
// Handle
// URLACTION_SCRIPT_RUN
// URLACTION_SCRIPT_JAVA_USE
// URLACTION_SCRIPT_SAFE_ACTIVEX
//
else if(dwAction >= URLACTION_SCRIPT_MIN && dwAction <= URLACTION_SCRIPT_MAX)
{
if (cbPolicy >= sizeof(DWORD))
{
*(DWORD *)pPolicy = URLPOLICY_ALLOW;
return S_OK;
}
return S_FALSE;
}
//
// Allow applets to do anything they want.
// Provide the java permissions.
//
else if(dwAction == URLACTION_JAVA_PERMISSIONS)
{
if (cbPolicy >= sizeof(DWORD))
{
//
// URLPOLICY_JAVA_LOW
// Set low Java security. Java applets will be allowed to
// do high-capability operations, such as file I/O.
//
*(DWORD *)pPolicy = URLPOLICY_JAVA_LOW;
return S_OK;
}
return S_FALSE;
}
return INET_E_DEFAULT_ACTION;
}
STDMETHODIMP CDHTMLEdit::QueryCustomPolicy ( LPCWSTR /*pwszUrl*/, REFGUID /*guidKey*/,
BYTE** /*ppPolicy*/, DWORD* /*pcbPolicy*/, BYTE* /*pContext*/, DWORD /*cbContext*/, DWORD /*dwReserved*/ )
{
return INET_E_DEFAULT_ACTION;
}
STDMETHODIMP CDHTMLEdit::SetSecuritySite ( IInternetSecurityMgrSite* /*pSite*/ )
{
return INET_E_DEFAULT_ACTION;
}
STDMETHODIMP CDHTMLEdit::SetZoneMapping ( DWORD /*dwZone*/, LPCWSTR /*lpszPattern*/, DWORD /*dwFlags*/ )
{
return INET_E_DEFAULT_ACTION;
}
// Map to aggregated control's methods:
//
STDMETHODIMP CDHTMLEdit::get_IsDirty(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_IsDirty ( pVal );}
STDMETHODIMP CDHTMLEdit::get_SourceCodePreservation(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_SourceCodePreservation ( pVal );}
STDMETHODIMP CDHTMLEdit::put_SourceCodePreservation(VARIANT_BOOL newVal) {return m_pInnerCtl->put_SourceCodePreservation ( newVal );}
STDMETHODIMP CDHTMLEdit::get_ScrollbarAppearance(DHTMLEDITAPPEARANCE *pVal) {return m_pInnerCtl->get_ScrollbarAppearance ( pVal );}
STDMETHODIMP CDHTMLEdit::put_ScrollbarAppearance(DHTMLEDITAPPEARANCE newVal) {return m_pInnerCtl->put_ScrollbarAppearance ( newVal );}
STDMETHODIMP CDHTMLEdit::get_Scrollbars(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_Scrollbars ( pVal );}
STDMETHODIMP CDHTMLEdit::put_Scrollbars(VARIANT_BOOL newVal) {return m_pInnerCtl->put_Scrollbars ( newVal );}
STDMETHODIMP CDHTMLEdit::get_Appearance(DHTMLEDITAPPEARANCE *pVal) {return m_pInnerCtl->get_Appearance ( pVal );}
STDMETHODIMP CDHTMLEdit::put_Appearance(DHTMLEDITAPPEARANCE newVal) {return m_pInnerCtl->put_Appearance ( newVal );}
STDMETHODIMP CDHTMLEdit::get_ShowBorders(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_ShowBorders ( pVal );}
STDMETHODIMP CDHTMLEdit::put_ShowBorders(VARIANT_BOOL newVal) {return m_pInnerCtl->put_ShowBorders ( newVal );}
STDMETHODIMP CDHTMLEdit::get_ShowDetails(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_ShowDetails ( pVal );}
STDMETHODIMP CDHTMLEdit::put_ShowDetails(VARIANT_BOOL newVal) {return m_pInnerCtl->put_ShowDetails ( newVal );}
STDMETHODIMP CDHTMLEdit::get_ActivateDTCs(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_ActivateDTCs ( pVal );}
STDMETHODIMP CDHTMLEdit::put_ActivateDTCs(VARIANT_BOOL newVal) {return m_pInnerCtl->put_ActivateDTCs ( newVal );}
STDMETHODIMP CDHTMLEdit::get_ActivateActiveXControls(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_ActivateActiveXControls ( pVal );}
STDMETHODIMP CDHTMLEdit::put_ActivateActiveXControls(VARIANT_BOOL newVal) {return m_pInnerCtl->put_ActivateActiveXControls ( newVal );}
STDMETHODIMP CDHTMLEdit::get_ActivateApplets(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_ActivateApplets ( pVal );}
STDMETHODIMP CDHTMLEdit::put_ActivateApplets(VARIANT_BOOL newVal) {return m_pInnerCtl->put_ActivateApplets ( newVal );}
STDMETHODIMP CDHTMLEdit::get_DOM(IHTMLDocument2 **pVal) {return m_pInnerCtl->get_DOM ( pVal );}
STDMETHODIMP CDHTMLEdit::get_DocumentHTML(BSTR *pVal) {return m_pInnerCtl->get_DocumentHTML ( pVal );}
STDMETHODIMP CDHTMLEdit::put_DocumentHTML(BSTR newVal) {return m_pInnerCtl->put_DocumentHTML ( newVal );}
STDMETHODIMP CDHTMLEdit::get_AbsoluteDropMode(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_AbsoluteDropMode ( pVal );}
STDMETHODIMP CDHTMLEdit::put_AbsoluteDropMode(VARIANT_BOOL newVal) {return m_pInnerCtl->put_AbsoluteDropMode ( newVal );}
STDMETHODIMP CDHTMLEdit::get_SnapToGridX(LONG *pVal) {return m_pInnerCtl->get_SnapToGridX ( pVal );}
STDMETHODIMP CDHTMLEdit::put_SnapToGridX(LONG newVal) {return m_pInnerCtl->put_SnapToGridX ( newVal );}
STDMETHODIMP CDHTMLEdit::get_SnapToGridY(LONG *pVal) {return m_pInnerCtl->get_SnapToGridY ( pVal );}
STDMETHODIMP CDHTMLEdit::put_SnapToGridY(LONG newVal) {return m_pInnerCtl->put_SnapToGridY ( newVal );}
STDMETHODIMP CDHTMLEdit::get_SnapToGrid(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_SnapToGrid ( pVal );}
STDMETHODIMP CDHTMLEdit::put_SnapToGrid(VARIANT_BOOL newVal) {return m_pInnerCtl->put_SnapToGrid ( newVal );}
STDMETHODIMP CDHTMLEdit::get_CurrentDocumentPath(BSTR *pVal) {return m_pInnerCtl->get_CurrentDocumentPath ( pVal );}
STDMETHODIMP CDHTMLEdit::QueryStatus(DHTMLEDITCMDID cmdID, DHTMLEDITCMDF* retval) {return m_pInnerCtl->QueryStatus ( cmdID, retval );}
STDMETHODIMP CDHTMLEdit::SetContextMenu(LPVARIANT menuStrings,LPVARIANT menuStates) {return m_pInnerCtl->SetContextMenu ( menuStrings, menuStates );}
STDMETHODIMP CDHTMLEdit::get_BaseURL(BSTR *baseURL) {return m_pInnerCtl->get_BaseURL(baseURL);}
STDMETHODIMP CDHTMLEdit::put_BaseURL(BSTR baseURL) {return m_pInnerCtl->put_BaseURL(baseURL);}
STDMETHODIMP CDHTMLEdit::get_DocumentTitle(BSTR *docTitle) {return m_pInnerCtl->get_DocumentTitle(docTitle);}
STDMETHODIMP CDHTMLEdit::NewDocument() {return m_pInnerCtl->NewDocument();}
STDMETHODIMP CDHTMLEdit::get_UseDivOnCarriageReturn(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_UseDivOnCarriageReturn(pVal);}
STDMETHODIMP CDHTMLEdit::put_UseDivOnCarriageReturn(VARIANT_BOOL newVal) {return m_pInnerCtl->put_UseDivOnCarriageReturn(newVal);}
STDMETHODIMP CDHTMLEdit::FilterSourceCode(BSTR sourceCodeIn, BSTR* sourceCodeOut) {return m_pInnerCtl->FilterSourceCode(sourceCodeIn, sourceCodeOut);}
STDMETHODIMP CDHTMLEdit::Refresh() {return m_pInnerCtl->Refresh();}
STDMETHODIMP CDHTMLEdit::get_Busy(VARIANT_BOOL *pVal) {return m_pInnerCtl->get_Busy(pVal);}
// End of DHTMLEdit.cpp