text: // 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<IHTMLDocument2>	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<CComSingleThreadModel>,
  	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<CEventXferSink>;
  
  		// 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:
  		CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer>picpc ( m_punkInnerCtl );
  		if ( picpc )
  		{
  			punkContUnk->Release ();
  			hr = picpc->FindConnectionPoint ( DIID__DHTMLSafeEvents, &m_piInnerCtlConPt );
  			if ( SUCCEEDED ( hr ) )
  			{
  				hr = m_piInnerCtlConPt->Advise ( static_cast<IDispatch *>(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
  