You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5091 lines
118 KiB
5091 lines
118 KiB
// Copyright (c)1997-1999 Microsoft Corporation, All Rights Reserved
|
|
// Notes on m_bfModeSwitched and m_bfReloadAttempted.
|
|
// IE5 bug 52818 was punted; pages containing IFrames don't refresh when changing
|
|
// browse/edit modes, because the stream is seen as dirty (because the IFrame
|
|
// considers itself dirty.) In response, we set m_bfModeSwitched when changing mode,
|
|
// m_bfReloadAttempted when and ATTEMPT is made to reload the page, and check for BOTH
|
|
// in OnReadyStateChanged. If the mode was changed but the page wasn't reloaded,
|
|
// we have to reload it manually.
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "DHTMLEd.h"
|
|
#include "DHTMLEdit.h"
|
|
#include "site.h"
|
|
#include "proxyframe.h"
|
|
#include <TRIEDIID.h>
|
|
#include <mshtmdid.h>
|
|
#include "dispexa.h"
|
|
#include <wchar.h>
|
|
#include <string.h>
|
|
|
|
|
|
// HTML to initialize Trident with if the host didn't supply any
|
|
// The <P> </P> works around a nasty Trident bug.
|
|
// Change: now there is one with paragraphs, one with DIVs.
|
|
//
|
|
static WCHAR* g_initialHTMLwithP = \
|
|
L"<HTML>\r\n\
|
|
<HEAD>\r\n\
|
|
<META NAME=\"GENERATOR\" Content=\"Microsoft DHTML Editing Control\">\r\n\
|
|
<TITLE></TITLE>\r\n\
|
|
</HEAD>\r\n\
|
|
<BODY>\r\n\
|
|
<P> </P>\r\n\
|
|
</BODY>\r\n\
|
|
</HTML>\r\n";
|
|
|
|
static WCHAR* g_initialHTMLwithDIV = \
|
|
L"<HTML>\r\n\
|
|
<HEAD>\r\n\
|
|
<META NAME=\"GENERATOR\" Content=\"Microsoft DHTML Editing Control\">\r\n\
|
|
<TITLE></TITLE>\r\n\
|
|
</HEAD>\r\n\
|
|
<BODY>\r\n\
|
|
<DIV> </DIV>\r\n\
|
|
</BODY>\r\n\
|
|
</HTML>\r\n";
|
|
|
|
|
|
// Text, numbers and constants used to construct a unique-per-process protocol ID
|
|
//
|
|
static WCHAR* g_wszProtocolPrefix = L"DHTMLEd";
|
|
static int s_iProtocolSuffix = 0;
|
|
#define MAX_PROTOCOL_SUFFIX 999999
|
|
|
|
|
|
// Name of the Title property which we get from the IHtmlDocument2 interface.
|
|
static WCHAR* g_wszHTMLTitlePropName = L"title";
|
|
|
|
|
|
// Maps private DHTMLEdit command IDs to Triedit command IDs.
|
|
// The third field is true if the command includes an out parameter.
|
|
//
|
|
static CommandMap cmdMap[] =
|
|
{
|
|
{DECMD_BOLD, IDM_TRIED_BOLD, FALSE},
|
|
{DECMD_COPY, IDM_TRIED_COPY, FALSE},
|
|
{DECMD_CUT, IDM_TRIED_CUT, FALSE},
|
|
{DECMD_DELETE, IDM_TRIED_DELETE, FALSE},
|
|
{DECMD_DELETECELLS, IDM_TRIED_DELETECELLS, FALSE},
|
|
{DECMD_DELETECOLS, IDM_TRIED_DELETECOLS, FALSE},
|
|
{DECMD_DELETEROWS, IDM_TRIED_DELETEROWS, FALSE},
|
|
{DECMD_FINDTEXT, IDM_TRIED_FIND, FALSE},
|
|
{DECMD_FONT, IDM_TRIED_FONT, FALSE},
|
|
{DECMD_GETBACKCOLOR, IDM_TRIED_BACKCOLOR, TRUE},
|
|
{DECMD_GETBLOCKFMT, IDM_TRIED_BLOCKFMT, TRUE},
|
|
{DECMD_GETBLOCKFMTNAMES, IDM_TRIED_GETBLOCKFMTS, TRUE},
|
|
{DECMD_GETFONTNAME, IDM_TRIED_FONTNAME, TRUE},
|
|
{DECMD_GETFONTSIZE, IDM_TRIED_FONTSIZE, TRUE},
|
|
{DECMD_GETFORECOLOR, IDM_TRIED_FORECOLOR, TRUE},
|
|
{DECMD_HYPERLINK, IDM_TRIED_HYPERLINK, FALSE},
|
|
{DECMD_IMAGE, IDM_TRIED_IMAGE, FALSE},
|
|
{DECMD_INDENT, IDM_TRIED_INDENT, FALSE},
|
|
{DECMD_INSERTCELL, IDM_TRIED_INSERTCELL, FALSE},
|
|
{DECMD_INSERTCOL, IDM_TRIED_INSERTCOL, FALSE},
|
|
{DECMD_INSERTROW, IDM_TRIED_INSERTROW, FALSE},
|
|
{DECMD_INSERTTABLE, IDM_TRIED_INSERTTABLE, FALSE},
|
|
{DECMD_ITALIC, IDM_TRIED_ITALIC, FALSE},
|
|
{DECMD_JUSTIFYLEFT, IDM_TRIED_JUSTIFYLEFT, FALSE},
|
|
{DECMD_JUSTIFYRIGHT, IDM_TRIED_JUSTIFYRIGHT, FALSE},
|
|
{DECMD_JUSTIFYCENTER, IDM_TRIED_JUSTIFYCENTER, FALSE},
|
|
{DECMD_LOCK_ELEMENT, IDM_TRIED_LOCK_ELEMENT, FALSE},
|
|
{DECMD_MAKE_ABSOLUTE, IDM_TRIED_MAKE_ABSOLUTE, FALSE},
|
|
{DECMD_MERGECELLS, IDM_TRIED_MERGECELLS, FALSE},
|
|
{DECMD_ORDERLIST, IDM_TRIED_ORDERLIST, FALSE},
|
|
{DECMD_OUTDENT, IDM_TRIED_OUTDENT, FALSE},
|
|
{DECMD_PASTE, IDM_TRIED_PASTE, FALSE},
|
|
{DECMD_REDO, IDM_TRIED_REDO, FALSE},
|
|
{DECMD_REMOVEFORMAT, IDM_TRIED_REMOVEFORMAT, FALSE},
|
|
{DECMD_SELECTALL, IDM_TRIED_SELECTALL, FALSE},
|
|
{DECMD_SEND_BACKWARD, IDM_TRIED_SEND_BACKWARD, FALSE},
|
|
{DECMD_BRING_FORWARD, IDM_TRIED_SEND_FORWARD, FALSE},
|
|
{DECMD_SEND_BELOW_TEXT, IDM_TRIED_SEND_BEHIND_1D, FALSE},
|
|
{DECMD_BRING_ABOVE_TEXT, IDM_TRIED_SEND_FRONT_1D, FALSE},
|
|
{DECMD_SEND_TO_BACK, IDM_TRIED_SEND_TO_BACK, FALSE},
|
|
{DECMD_BRING_TO_FRONT, IDM_TRIED_SEND_TO_FRONT, FALSE},
|
|
{DECMD_SETBACKCOLOR, IDM_TRIED_BACKCOLOR, FALSE},
|
|
{DECMD_SETBLOCKFMT, IDM_TRIED_BLOCKFMT, FALSE},
|
|
{DECMD_SETFONTNAME, IDM_TRIED_FONTNAME, FALSE},
|
|
{DECMD_SETFONTSIZE, IDM_TRIED_FONTSIZE, FALSE},
|
|
{DECMD_SETFORECOLOR, IDM_TRIED_FORECOLOR, FALSE},
|
|
{DECMD_SPLITCELL, IDM_TRIED_SPLITCELL, FALSE},
|
|
{DECMD_UNDERLINE, IDM_TRIED_UNDERLINE, FALSE},
|
|
{DECMD_UNDO, IDM_TRIED_UNDO, FALSE},
|
|
{DECMD_UNLINK, IDM_TRIED_UNLINK, FALSE},
|
|
{DECMD_UNORDERLIST, IDM_TRIED_UNORDERLIST, FALSE},
|
|
{DECMD_PROPERTIES, IDM_TRIED_DOVERB, FALSE}
|
|
};
|
|
|
|
|
|
|
|
CProxyFrame::CProxyFrame(CDHTMLSafe* pCtl)
|
|
{
|
|
SAFEARRAYBOUND rgsabound[1] = {0};
|
|
|
|
_ASSERTE(pCtl);
|
|
|
|
m_cRef = 1;
|
|
|
|
m_pUnkTriEdit = NULL;
|
|
m_hWndObj = NULL;
|
|
m_pIOleIPActiveObject = NULL;
|
|
m_pSite = NULL;
|
|
m_pCtl = pCtl;
|
|
|
|
m_fCreated = FALSE;
|
|
m_fActivated = FALSE;
|
|
m_state = ESTATE_NOTCREATED;
|
|
m_readyState = READYSTATE_UNINITIALIZED;
|
|
m_dwFilterFlags = m_dwFilterOutFlags = filterAll;
|
|
|
|
m_fActivateApplets = FALSE;
|
|
m_fActivateControls = FALSE;
|
|
m_fActivateDTCs = TRUE;
|
|
m_fShowAllTags = FALSE;
|
|
m_fShowBorders = FALSE;
|
|
|
|
m_fDialogEditing = TRUE;
|
|
m_fDisplay3D = TRUE;
|
|
m_fScrollbars = TRUE;
|
|
m_fDisplayFlatScrollbars = FALSE;
|
|
m_fContextMenu = TRUE;
|
|
|
|
m_fPreserveSource = TRUE;
|
|
|
|
m_fAbsoluteDropMode = FALSE;
|
|
m_fSnapToGrid = FALSE;
|
|
m_ulSnapToGridX = 50;
|
|
m_ulSnapToGridY = 50;
|
|
|
|
rgsabound[0].lLbound = 0;
|
|
rgsabound[0].cElements = 0;
|
|
|
|
m_pMenuStrings = NULL;
|
|
m_pMenuStates = NULL;
|
|
|
|
m_vbBrowseMode = VARIANT_FALSE;
|
|
|
|
m_vbUseDivOnCr = VARIANT_FALSE;
|
|
m_bfIsLoading = FALSE;
|
|
m_bfBaseURLFromBASETag = FALSE;
|
|
m_bfPreserveDirtyFlagAcrossBrowseMode = FALSE;
|
|
m_bstrInitialDoc.Empty ();
|
|
|
|
m_bstrCurDocPath.Empty ();
|
|
|
|
wcscpy ( m_wszProtocol, g_wszProtocolPrefix );
|
|
WCHAR wszSuffix[8];
|
|
_itow ( s_iProtocolSuffix++, wszSuffix, 10 );
|
|
if ( MAX_PROTOCOL_SUFFIX <= s_iProtocolSuffix )
|
|
{
|
|
s_iProtocolSuffix = 0; // Roll over.
|
|
}
|
|
wcscat ( m_wszProtocol, wszSuffix );
|
|
wcscpy ( m_wszProtocolPrefix, m_wszProtocol );
|
|
wcscat ( m_wszProtocolPrefix, L":" );
|
|
|
|
m_pProtInfo = NULL;
|
|
m_bfIsURL = FALSE;
|
|
m_bstrBaseURL = L"";
|
|
m_hwndRestoreFocus = NULL;
|
|
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
m_hUlrMon = NULL;
|
|
m_hWinINet = NULL;
|
|
m_pfnCoInternetCombineUrl = NULL;
|
|
m_pfnCoInternetParseUrl = NULL;
|
|
m_pfnCreateURLMoniker = NULL;
|
|
m_pfnCoInternetGetSession = NULL;
|
|
m_pfnURLOpenBlockingStream = NULL;
|
|
|
|
m_pfnDeleteUrlCacheEntry = NULL;
|
|
m_pfnInternetCreateUrl = NULL;
|
|
m_pfnInternetCrackUrl = NULL;
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
m_bfModeSwitched = FALSE;
|
|
m_bfReloadAttempted = FALSE;
|
|
m_bfSFSRedirect = FALSE;
|
|
}
|
|
|
|
CProxyFrame::~CProxyFrame()
|
|
{
|
|
_ASSERTE(FALSE == m_fCreated);
|
|
_ASSERTE(FALSE == m_fActivated);
|
|
_ASSERTE( m_cRef == 0 );
|
|
|
|
if (m_pMenuStrings)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStrings);
|
|
m_pMenuStrings = NULL;
|
|
}
|
|
|
|
if (m_pMenuStates)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStates);
|
|
m_pMenuStates = NULL;
|
|
}
|
|
|
|
// This should never happen: SetActiveObject should take care of it.
|
|
_ASSERTE ( NULL == m_pIOleIPActiveObject );
|
|
if (m_pIOleIPActiveObject)
|
|
{
|
|
m_pIOleIPActiveObject->Release();
|
|
m_pIOleIPActiveObject = NULL;
|
|
}
|
|
|
|
UnRegisterPluggableProtocol ();
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
DynUnloadLibraries ();
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
}
|
|
|
|
|
|
// Create the TriEdit object and host it.
|
|
// Clean up and return an error if there was any problem.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::Init(IUnknown* pUnk, IUnknown** ppUnkTriEdit)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
if ( ! DynLoadLibraries () )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
hr = RegisterPluggableProtocol ();
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
_ASSERTE(NULL == m_pSite);
|
|
_ASSERTE(GetState() == ESTATE_NOTCREATED);
|
|
|
|
InitializeDocString ();
|
|
|
|
if (m_pSite)
|
|
return E_UNEXPECTED;
|
|
|
|
if (GetState() != ESTATE_NOTCREATED)
|
|
return E_UNEXPECTED;
|
|
|
|
// Create and initialize the site for TriEdit
|
|
m_pSite = new CSite(this);
|
|
|
|
if (NULL == m_pSite)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
m_pSite->AddRef(); // So we can free with Release
|
|
|
|
// Ask the site to create TriEdit
|
|
if (SUCCEEDED(hr = m_pSite->HrCreate(pUnk, &m_pUnkTriEdit)))
|
|
{
|
|
ChangeState(ESTATE_CREATED);
|
|
m_fCreated = TRUE;
|
|
if (ppUnkTriEdit)
|
|
{
|
|
m_pUnkTriEdit->AddRef();
|
|
*ppUnkTriEdit = m_pUnkTriEdit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pSite->Release();
|
|
m_pSite = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Destroy the site and the TriEdit object.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::Close()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERTE(m_pUnkTriEdit);
|
|
_ASSERTE(m_pSite);
|
|
_ASSERTE(GetState() != ESTATE_NOTCREATED);
|
|
|
|
m_bstrCurDocPath.Empty ();
|
|
|
|
// triedit must be created
|
|
// any state from created to activated is ok
|
|
if (GetState() == ESTATE_NOTCREATED)
|
|
return E_UNEXPECTED;
|
|
|
|
if (m_fActivated)
|
|
{
|
|
hr = HrExecCommand(&CGID_MSHTML, IDM_STOP, MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
}
|
|
|
|
ChangeState(ESTATE_NOTCREATED);
|
|
m_fCreated = FALSE;
|
|
m_fActivated = FALSE;
|
|
if (m_pSite != NULL)
|
|
{
|
|
CSite* pSite = m_pSite; // prevents reentry;
|
|
m_pSite = NULL;
|
|
|
|
pSite->Close(FALSE);
|
|
ReleaseInterface(pSite)
|
|
pSite = NULL;
|
|
}
|
|
|
|
if (m_pUnkTriEdit != NULL)
|
|
{
|
|
LPUNKNOWN pUnkTriEdit = m_pUnkTriEdit;
|
|
m_pUnkTriEdit = NULL;
|
|
|
|
ReleaseInterface(pUnkTriEdit);
|
|
pUnkTriEdit = NULL;
|
|
}
|
|
|
|
m_hwndRestoreFocus = NULL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Determine which string constant to use and return a pointer to it.
|
|
//
|
|
WCHAR* CProxyFrame::GetInitialHTML ()
|
|
{
|
|
if ( m_vbUseDivOnCr )
|
|
{
|
|
return g_initialHTMLwithDIV;
|
|
}
|
|
else
|
|
{
|
|
return g_initialHTMLwithP;
|
|
}
|
|
}
|
|
|
|
|
|
// Perform these steps before loading TriEdit's contents
|
|
//
|
|
HRESULT
|
|
CProxyFrame::PreActivate()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
_ASSERTE(m_pSite);
|
|
_ASSERTE(m_pCtl);
|
|
|
|
_ASSERTE(ESTATE_CREATED == GetState());
|
|
|
|
if (GetState() != ESTATE_CREATED)
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
if (FAILED(hr = m_pSite->HrObjectInitialize()))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
m_fActivated = TRUE;
|
|
ChangeState(ESTATE_PREACTIVATING);
|
|
|
|
if (FAILED(hr = HrSetRuntimeProperties()))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
ChangeState(ESTATE_ACTIVATING);
|
|
|
|
error:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
void
|
|
CProxyFrame::UIDeactivate()
|
|
{
|
|
// This was m_pSite->GetIPObject()->UIDeactivate(),
|
|
// but the QA teams VB app using this version of the control crashed
|
|
// with a NULL pointer dereference.
|
|
|
|
if ( NULL != m_pSite )
|
|
{
|
|
LPOLEINPLACEOBJECT pipObj = m_pSite->GetIPObject();
|
|
if ( NULL != pipObj )
|
|
{
|
|
pipObj->UIDeactivate();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Perform these steps after loading TriEdits contents to go UI active.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::Activate()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERTE(m_pSite);
|
|
_ASSERTE(m_pCtl);
|
|
_ASSERTE(m_pCtl->m_hWndCD);
|
|
|
|
_ASSERTE(GetState() == ESTATE_ACTIVATING);
|
|
|
|
if (GetState() != ESTATE_ACTIVATING)
|
|
return E_UNEXPECTED;
|
|
|
|
// UI-activate the control
|
|
if ( ! m_pCtl->m_bUIActive )
|
|
{
|
|
// Used to be UIActivate, until MohanB fixed OnSetFocus and activation/deactivation linkage.
|
|
m_pCtl->DoVerbInPlaceActivate ( NULL, NULL );
|
|
}
|
|
|
|
// activate Trident with "Show"
|
|
m_pSite->InitialActivate(OLEIVERB_SHOW, m_pCtl->m_hWndCD);
|
|
|
|
ChangeState(ESTATE_ACTIVATED);
|
|
|
|
// This may have been deferred, because the site's command target did not yet exist...
|
|
SetBrowseMode ( m_vbBrowseMode );
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Load and activate the control with a minimal, empty page.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::LoadInitialDoc()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERTE(GetState() == ESTATE_CREATED);
|
|
|
|
if (GetState() != ESTATE_CREATED)
|
|
return E_UNEXPECTED;
|
|
|
|
if (FAILED(hr = PreActivate()))
|
|
goto error;
|
|
|
|
if (FAILED(hr = LoadBSTRDeferred ( m_bstrInitialDoc )))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
if (FAILED(hr = Activate()))
|
|
goto error;
|
|
|
|
error:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Before getting or setting a property or calling a method on the docobject,
|
|
// assure that it's been properly activated.
|
|
//
|
|
void CProxyFrame::AssureActivated ()
|
|
{
|
|
if ( ! m_fActivated )
|
|
{
|
|
if ( m_pCtl->IsUserMode() )
|
|
{
|
|
if ( !m_pCtl->m_bInPlaceActive )
|
|
{
|
|
m_pCtl->DoVerbInPlaceActivate ( NULL, NULL );
|
|
}
|
|
LoadInitialDoc ();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Loading MSHTML shifts the focus to its document window.
|
|
// This is not desirable in a control. Experimentation has demonstrated
|
|
// that the focus shifts between various QIs from MSHTML (probably in response
|
|
// to posted messages.) There is no routine in DHTMLEdit which enters with the
|
|
// focus outside the control and exits with the focus within the control.
|
|
// Therefore, a member variable is used to preserve the appropriate focus
|
|
// across calls to OnReadyStateChanged, which are called in response to events
|
|
// fired by the control. m_hwndRestoreFocus is used to preserve the appropriate
|
|
// window to receive the focus. Note that NULL may be appropriate, but is not honored.
|
|
// If no window had focus, the document will gain focus.
|
|
//
|
|
void
|
|
CProxyFrame::OnReadyStateChanged(READYSTATE readyState)
|
|
{
|
|
_ASSERTE(m_pCtl);
|
|
|
|
m_readyState = readyState;
|
|
|
|
switch (m_readyState)
|
|
{
|
|
case READYSTATE_UNINITIALIZED:
|
|
{
|
|
m_hwndRestoreFocus = NULL;
|
|
}
|
|
break;
|
|
|
|
case READYSTATE_LOADING:
|
|
{
|
|
m_hwndRestoreFocus = ::GetFocus ();
|
|
}
|
|
break;
|
|
|
|
case READYSTATE_LOADED:
|
|
{
|
|
}
|
|
break;
|
|
|
|
case READYSTATE_INTERACTIVE:
|
|
{
|
|
if ( NULL != m_hwndRestoreFocus )
|
|
{
|
|
_ASSERTE ( ::IsWindow ( m_hwndRestoreFocus ) );
|
|
if ( ::IsWindow ( m_hwndRestoreFocus ) )
|
|
{
|
|
::SetFocus ( m_hwndRestoreFocus );
|
|
}
|
|
}
|
|
|
|
// See if we failed to get a refresh on a mode change. This happens if
|
|
// there are IFrames on the page, perhaps in other cases as well.
|
|
if ( m_bfModeSwitched && !m_bfReloadAttempted )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CComPtr<IMoniker> srpMoniker;
|
|
CComPtr<IBindCtx> srpBindCtx;
|
|
CComQIPtr<IPersistMoniker, &IID_IPersistMoniker> srpPM (m_pUnkTriEdit);
|
|
_ASSERTE ( srpPM );
|
|
|
|
if ( srpPM )
|
|
{
|
|
CComBSTR bstrProtocol = m_wszProtocolPrefix;
|
|
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
_ASSERTE ( m_pfnCreateURLMoniker );
|
|
hr = (*m_pfnCreateURLMoniker)( NULL, bstrProtocol, &srpMoniker );
|
|
#else
|
|
hr = CreateURLMoniker ( NULL, bstrProtocol, &srpMoniker );
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
_ASSERTE ( SUCCEEDED( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = ::CreateBindCtx(NULL, &srpBindCtx);
|
|
_ASSERTE ( SUCCEEDED( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = srpPM->Load(FALSE, srpMoniker, srpBindCtx, STGM_READ);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
m_bfModeSwitched = FALSE;
|
|
m_bfReloadAttempted = FALSE;
|
|
}
|
|
break;
|
|
|
|
case READYSTATE_COMPLETE:
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
m_hwndRestoreFocus = NULL;
|
|
if ( ! m_vbBrowseMode )
|
|
{
|
|
hr = HrSetDocLoadedProperties();
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
}
|
|
|
|
_ASSERTE ( m_pCtl->m_hWnd );
|
|
_ASSERTE ( ::IsWindow ( m_pCtl->m_hWnd ) );
|
|
|
|
if ( m_bfPreserveDirtyFlagAcrossBrowseMode && !m_vbBrowseMode )
|
|
{
|
|
m_bfPreserveDirtyFlagAcrossBrowseMode = FALSE;
|
|
SetDirtyFlag ( TRUE );
|
|
}
|
|
// Post a user message to fire the DocumentComplete event.
|
|
// Otherwise, calling things like LoadURL from DocumentComplete behaves strangely.
|
|
::PostMessage ( m_pCtl->m_hWnd, DOCUMENT_COMPETE_MESSAGE, DOCUMENT_COMPETE_SIGNATURE, 0L );
|
|
HrSetRuntimeProperties ();
|
|
//m_bfIsLoading = FALSE; // This has been moved the the DOCUMENT_COMPETE_MESSAGE handler.
|
|
SetBaseURLFromBaseHref (); // Must be called after clearing m_bfIsLoading
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* IUnknown implementation
|
|
*/
|
|
/*
|
|
* CProxyFrame::QueryInterface
|
|
* CProxyFrame::AddRef
|
|
* CProxyFrame::Release
|
|
*/
|
|
STDMETHODIMP CProxyFrame::QueryInterface( REFIID riid, void **ppv )
|
|
{
|
|
/*
|
|
* We provide IOleInPlaceFrame and IOleCommandTarget
|
|
* interfaces here for the ActiveX Document hosting
|
|
*/
|
|
*ppv = NULL;
|
|
|
|
if ( IID_IUnknown == riid || IID_IOleInPlaceUIWindow == riid
|
|
|| IID_IOleWindow == riid || IID_IOleInPlaceFrame == riid )
|
|
{
|
|
*ppv = static_cast<IOleInPlaceFrame *>(this);
|
|
}
|
|
|
|
else if ( IID_IOleCommandTarget == riid )
|
|
{
|
|
*ppv = static_cast<IOleCommandTarget *>(this);
|
|
}
|
|
else if ( IID_IBindStatusCallback == riid )
|
|
{
|
|
*ppv = static_cast<IBindStatusCallback *>(this);
|
|
}
|
|
else if ( IID_IAuthenticate == riid )
|
|
{
|
|
*ppv = static_cast<IAuthenticate *>(this);
|
|
}
|
|
else if ( IID_IServiceProvider == riid )
|
|
{
|
|
// Ask the control for a security manager IF in edit mode:
|
|
if ( ! m_vbBrowseMode )
|
|
{
|
|
return m_pCtl->GetUnknown()->QueryInterface ( riid, ppv );
|
|
}
|
|
}
|
|
|
|
if ( NULL != *ppv )
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CProxyFrame::AddRef( void )
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CProxyFrame::Release( void )
|
|
{
|
|
//Nothing special happening here-- life if user-controlled.
|
|
// Debug check to see we don't fall below 0
|
|
_ASSERTE( m_cRef != 0 );
|
|
|
|
ULONG ulRefCount = --m_cRef;
|
|
if ( 0 == ulRefCount )
|
|
{
|
|
delete this; // Do not refer to any member variables after this.
|
|
}
|
|
return ulRefCount;
|
|
}
|
|
|
|
|
|
/*
|
|
* IOleInPlaceFrame implementation
|
|
*/
|
|
/*
|
|
* CProxyFrame::GetWindow
|
|
*
|
|
* Purpose:
|
|
* Retrieves the handle of the window associated with the object
|
|
* on which this interface is implemented.
|
|
*
|
|
* Parameters:
|
|
* phWnd HWND * in which to store the window handle.
|
|
*
|
|
* Return Value:
|
|
* HRESULT S_OK if successful, E_FAIL if there is no
|
|
* window.
|
|
*/
|
|
STDMETHODIMP CProxyFrame::GetWindow( HWND* phWnd )
|
|
{
|
|
if ( m_pCtl != NULL )
|
|
{
|
|
*phWnd = m_pCtl->m_hWnd;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* CProxyFrame::ContextSensitiveHelp
|
|
*
|
|
* Purpose:
|
|
* Instructs the object on which this interface is implemented to
|
|
* enter or leave a context-sensitive help mode.
|
|
*
|
|
* Parameters:
|
|
* fEnterMode BOOL TRUE to enter the mode, FALSE otherwise.
|
|
*
|
|
* Return Value:
|
|
* HRESULT S_OK
|
|
*/
|
|
STDMETHODIMP CProxyFrame::ContextSensitiveHelp( BOOL /*fEnterMode*/ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* CProxyFrame::GetBorder
|
|
*
|
|
* Purpose:
|
|
* Returns the rectangle in which the container is willing to
|
|
* negotiate about an object's adornments.
|
|
*
|
|
* Parameters:
|
|
* prcBorder LPRECT in which to store the rectangle.
|
|
*
|
|
* Return Value:
|
|
* HRESULT S_OK if all is well, INPLACE_E_NOTOOLSPACE
|
|
* if there is no negotiable space.
|
|
*/
|
|
STDMETHODIMP CProxyFrame::GetBorder( LPRECT prcBorder )
|
|
{
|
|
if ( NULL == prcBorder )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//We return all the client area space
|
|
m_pCtl->GetClientRect( prcBorder );
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* CProxyFrame::RequestBorderSpace
|
|
*
|
|
* Purpose:
|
|
* Asks the container if it can surrender the amount of space
|
|
* in pBW that the object would like for it's adornments. The
|
|
* container does nothing but validate the spaces on this call.
|
|
*
|
|
* Parameters:
|
|
* pBW LPCBORDERWIDTHS containing the requested space.
|
|
* The values are the amount of space requested
|
|
* from each side of the relevant window.
|
|
*
|
|
* Return Value:
|
|
* HRESULT S_OK if we can give up space,
|
|
* INPLACE_E_NOTOOLSPACE otherwise.
|
|
*/
|
|
STDMETHODIMP CProxyFrame::RequestBorderSpace( LPCBORDERWIDTHS /*pBW*/ )
|
|
{
|
|
// We have no border space restrictions
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* CProxyFrame::SetBorderSpace
|
|
*
|
|
* Purpose:
|
|
* Called when the object now officially requests that the
|
|
* container surrender border space it previously allowed
|
|
* in RequestBorderSpace. The container should resize windows
|
|
* appropriately to surrender this space.
|
|
*
|
|
* Parameters:
|
|
* pBW LPCBORDERWIDTHS containing the amount of space
|
|
* from each side of the relevant window that the
|
|
* object is now reserving.
|
|
*
|
|
* Return Value:
|
|
* HRESULT S_OK
|
|
*/
|
|
STDMETHODIMP CProxyFrame::SetBorderSpace( LPCBORDERWIDTHS /*pBW*/ )
|
|
{
|
|
// We turn off the MSHTML.DLL UI so we ignore all of this.
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* CProxyFrame::SetActiveObject
|
|
*
|
|
* Purpose:
|
|
* Provides the container with the object's IOleInPlaceActiveObject
|
|
* pointer
|
|
*
|
|
* Parameters:
|
|
* pIIPActiveObj LPOLEINPLACEACTIVEOBJECT of interest.
|
|
* pszObj LPCOLESTR naming the object. Not used.
|
|
*
|
|
* Return Value:
|
|
* HRESULT S_OK
|
|
*/
|
|
STDMETHODIMP CProxyFrame::SetActiveObject( LPOLEINPLACEACTIVEOBJECT pIIPActiveObj,
|
|
LPCOLESTR /*pszObj*/)
|
|
{
|
|
// If we already have an active Object then release it.
|
|
if ( NULL != m_pIOleIPActiveObject )
|
|
{
|
|
m_pIOleIPActiveObject->Release();
|
|
}
|
|
|
|
//NULLs m_pIOleIPActiveObject if pIIPActiveObj is NULL
|
|
m_pIOleIPActiveObject = pIIPActiveObj;
|
|
|
|
if ( NULL != m_pIOleIPActiveObject )
|
|
{
|
|
m_pIOleIPActiveObject->AddRef();
|
|
m_pIOleIPActiveObject->GetWindow( &m_hWndObj );
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* CProxyFrame::InsertMenus
|
|
*
|
|
* Purpose:
|
|
* Instructs the container to place its in-place menu items where
|
|
* necessary in the given menu and to fill in elements 0, 2, and 4
|
|
* of the OLEMENUGROUPWIDTHS array to indicate how many top-level
|
|
* items are in each group.
|
|
*
|
|
* Parameters:
|
|
* hMenu HMENU in which to add popups.
|
|
* pMGW LPOLEMENUGROUPWIDTHS in which to store the
|
|
* width of each container menu group.
|
|
*
|
|
* Return Value:
|
|
* HRESULT E_NOTIMPL
|
|
*/
|
|
STDMETHODIMP CProxyFrame::InsertMenus( HMENU /*hMenu*/, LPOLEMENUGROUPWIDTHS /*pMGW*/ )
|
|
{
|
|
// We've turned off the MSHTML.DLL Menus so we don't expect any merging to go on!
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
/*
|
|
* CProxyFrame::SetMenu
|
|
*
|
|
* Purpose:
|
|
* Instructs the container to replace whatever menu it's currently
|
|
* using with the given menu and to call OleSetMenuDescritor so OLE
|
|
* knows to whom to dispatch messages.
|
|
*
|
|
* Parameters:
|
|
* hMenu HMENU to show.
|
|
* hOLEMenu HOLEMENU to the menu descriptor.
|
|
* hWndObj HWND of the active object to which messages are
|
|
* dispatched.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR
|
|
*/
|
|
STDMETHODIMP CProxyFrame::SetMenu( HMENU /*hMenu*/, HOLEMENU /*hOLEMenu*/, HWND /*hWndObj*/ )
|
|
{
|
|
// We've turned off the MSHTML.DLL Menus so we don't expect any merging to go on!
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* CProxyFrame::RemoveMenus
|
|
*
|
|
* Purpose:
|
|
* Asks the container to remove any menus it put into hMenu in
|
|
* InsertMenus.
|
|
*
|
|
* Parameters:
|
|
* hMenu HMENU from which to remove the container's
|
|
* items.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR
|
|
*/
|
|
STDMETHODIMP CProxyFrame::RemoveMenus( HMENU /*hMenu*/ )
|
|
{
|
|
// We've turned off the MSHTML.DLL Menus so we don't expect any merging to go on!
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
/*
|
|
* CProxyFrame::SetStatusText
|
|
*
|
|
* Purpose:
|
|
* Asks the container to place some text in a status line, if one
|
|
* exists. If the container does not have a status line it
|
|
* should return E_FAIL here in which case the object could
|
|
* display its own.
|
|
*
|
|
* Parameters:
|
|
* pszText LPCOLESTR to display.
|
|
*
|
|
* Return Value:
|
|
* HRESULT S_OK if successful, S_TRUNCATED if not all
|
|
* of the text could be displayed, or E_FAIL if
|
|
* the container has no status line.
|
|
*/
|
|
STDMETHODIMP CProxyFrame::SetStatusText( LPCOLESTR /*pszText*/ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* CProxyFrame::EnableModeless
|
|
*
|
|
* Purpose:
|
|
* Instructs the container to show or hide any modeless popup
|
|
* windows that it may be using.
|
|
*
|
|
* Parameters:
|
|
* fEnable BOOL indicating to enable/show the windows
|
|
* (TRUE) or to hide them (FALSE).
|
|
*
|
|
* Return Value:
|
|
* HRESULT S_OK
|
|
*/
|
|
|
|
STDMETHODIMP CProxyFrame::EnableModeless( BOOL /*fEnable*/ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
* CProxyFrame::TranslateAccelerator
|
|
*
|
|
* Purpose:
|
|
* When dealing with an in-place object from an EXE server, this
|
|
* is called to give the container a chance to process accelerators
|
|
* after the server has looked at the message.
|
|
*
|
|
* Parameters:
|
|
* pMSG LPMSG for the container to examine.
|
|
* wID WORD the identifier in the container's
|
|
* accelerator table (from IOleInPlaceSite
|
|
* ::GetWindowContext) for this message (OLE does
|
|
* some translation before calling).
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR if the keystroke was used,
|
|
* S_FALSE otherwise.
|
|
*/
|
|
STDMETHODIMP CProxyFrame::TranslateAccelerator( LPMSG /*pMSG*/, WORD /*wID*/ )
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* IOleCommandTarget::QueryStatus
|
|
*/
|
|
STDMETHODIMP CProxyFrame::QueryStatus( const GUID* pguidCmdGroup, ULONG cCmds,
|
|
OLECMD* prgCmds, OLECMDTEXT* pCmdText )
|
|
{
|
|
if ( pguidCmdGroup != NULL )
|
|
{
|
|
// It's a nonstandard group!!
|
|
return OLECMDERR_E_UNKNOWNGROUP;
|
|
}
|
|
|
|
MSOCMD* pCmd;
|
|
INT c;
|
|
HRESULT hr = S_OK;
|
|
|
|
// By default command text is NOT SUPPORTED.
|
|
if ( pCmdText && ( pCmdText->cmdtextf != OLECMDTEXTF_NONE ) )
|
|
{
|
|
pCmdText->cwActual = 0;
|
|
}
|
|
|
|
// Loop through each command in the array, setting the status of each.
|
|
for ( pCmd = prgCmds, c = cCmds; --c >= 0; pCmd++ )
|
|
{
|
|
// By default command status is NOT SUPPORTED.
|
|
pCmd->cmdf = 0;
|
|
|
|
switch ( pCmd->cmdID )
|
|
{
|
|
case OLECMDID_UPDATECOMMANDS:
|
|
pCmd->cmdf = OLECMDF_SUPPORTED;
|
|
break;
|
|
|
|
case OLECMDID_NEW:
|
|
case OLECMDID_OPEN:
|
|
case OLECMDID_SAVE:
|
|
pCmd->cmdf = (MSOCMDF_SUPPORTED | MSOCMDF_ENABLED);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
|
|
/*
|
|
* IOleCommandTarget::Exec
|
|
*/
|
|
|
|
STDMETHODIMP CProxyFrame::Exec( const GUID* pguidCmdGroup, DWORD nCmdID,
|
|
DWORD /*nCmdexecopt*/, VARIANTARG* /*pvaIn*/, VARIANTARG* /*pvaOut*/ )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( pguidCmdGroup == NULL )
|
|
{
|
|
switch (nCmdID)
|
|
{
|
|
|
|
case OLECMDID_UPDATECOMMANDS:
|
|
{
|
|
// Fires event to container.
|
|
m_pCtl->Fire_DisplayChanged();
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
hr = OLECMDERR_E_NOTSUPPORTED;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = OLECMDERR_E_UNKNOWNGROUP;
|
|
}
|
|
return (hr);
|
|
}
|
|
|
|
|
|
// Connector from control to site.
|
|
//
|
|
void
|
|
CProxyFrame::UpdateObjectRects()
|
|
{
|
|
_ASSERTE ( m_pSite );
|
|
if ( NULL != m_pSite )
|
|
{
|
|
m_pSite->UpdateObjectRects();
|
|
}
|
|
}
|
|
|
|
|
|
// Called from the control's TranslateAccelerator.
|
|
// Try our own (VID-like) acclerators first, and if not handled pass them along to TriEdit.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrTranslateAccelerator(LPMSG lpmsg)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (NULL != m_pIOleIPActiveObject)
|
|
{
|
|
_ASSERTE(lpmsg);
|
|
|
|
hr = HrHandleAccelerator(lpmsg);
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
hr = m_pIOleIPActiveObject->TranslateAccelerator(lpmsg);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// A lot of time was lost here in scenarios like clicking on/tabbing to a control
|
|
// embedded in a VB OCX, tabbing to a control on a page, etc.
|
|
// Exercise great caution and perform a lot of testing if this is changed.
|
|
//
|
|
LRESULT
|
|
CProxyFrame::OnSetFocus(UINT /*nMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
|
|
{
|
|
if ( ! m_pCtl->m_bUIActive )
|
|
{
|
|
m_pCtl->DoVerbUIActivate ( NULL, NULL );
|
|
}
|
|
|
|
// Give the focus to the ActiveX Document window
|
|
if ( m_hWndObj != NULL )
|
|
{
|
|
::SetFocus( m_hWndObj );
|
|
bHandled = TRUE;
|
|
}
|
|
|
|
// activate Trident with "Show"
|
|
m_pSite->Activate(OLEIVERB_SHOW);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Sets the Trident window's parent correctly when created and destroyed.
|
|
//
|
|
void
|
|
CProxyFrame::SetParent ( HWND hwndParent )
|
|
{
|
|
// This may be called before the control has been drawn.
|
|
if ( NULL != m_hWndObj )
|
|
{
|
|
if( hwndParent )
|
|
{
|
|
HWND hwndOldParent = ::SetParent ( m_hWndObj, hwndParent );
|
|
if ( NULL == hwndOldParent )
|
|
{
|
|
DWORD dwErr = 0;
|
|
dwErr = GetLastError ();
|
|
}
|
|
_ASSERTE ( m_pSite );
|
|
m_pSite->SetWindow ( hwndParent );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Handles WM_SHOWWINDOW messages directed to the control.
|
|
//
|
|
void
|
|
CProxyFrame::Show ( WPARAM nCmdShow )
|
|
{
|
|
// This may be called before the control has been drawn.
|
|
// Hide or show the hosted Trident
|
|
if ( NULL != m_hWndObj )
|
|
{
|
|
::ShowWindow ( m_hWndObj, (int)nCmdShow );
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ExecCommand mechanism
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Convert a command ID into a TriEdit command ID.
|
|
// Some commands used to represent other command groups as well, thus the ppguidCmdGroup parameter.
|
|
// While this does little now, it may be useful again in the future.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrMapCommand(DHTMLEDITCMDID typeLibCmdID,
|
|
ULONG* cmdID, const GUID** ppguidCmdGroup, BOOL* pbOutParam)
|
|
{
|
|
|
|
_ASSERTE(cmdID);
|
|
_ASSERTE(ppguidCmdGroup);
|
|
_ASSERTE(pbOutParam);
|
|
|
|
*cmdID = 0;
|
|
*ppguidCmdGroup = NULL;
|
|
*pbOutParam = FALSE;
|
|
|
|
for (UINT i=0; i < sizeof(cmdMap)/sizeof(CommandMap); ++i)
|
|
{
|
|
if (typeLibCmdID == cmdMap[i].typeLibCmdID)
|
|
{
|
|
*cmdID = cmdMap[i].cmdID;
|
|
*ppguidCmdGroup = &GUID_TriEditCommandGroup;
|
|
*pbOutParam = cmdMap[i].bOutParam;
|
|
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return OLECMDERR_E_NOTSUPPORTED ;
|
|
}
|
|
|
|
|
|
// Helper routine for calling Exec.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrExecCommand(const GUID* pguidCmdGroup, ULONG ucmdID,
|
|
OLECMDEXECOPT cmdexecopt, VARIANT* pVarIn, VARIANT* pVarOut)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
LPOLECOMMANDTARGET pCommandTarget = NULL;
|
|
|
|
// note that it is valid for pguidCmdGroup to be NULL
|
|
|
|
_ASSERTE(m_pSite);
|
|
|
|
if (NULL == m_pSite)
|
|
return E_UNEXPECTED;
|
|
|
|
pCommandTarget = m_pSite->GetCommandTarget();
|
|
|
|
_ASSERTE(pCommandTarget);
|
|
|
|
if (pCommandTarget != NULL)
|
|
{
|
|
hr = pCommandTarget->Exec(pguidCmdGroup, ucmdID, cmdexecopt, pVarIn, pVarOut);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Main command dispatcher; called from the control's ExecCommand method.
|
|
// Handle our unique commands here, pass the rest onto HrExecGenericCommands.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrMapExecCommand(DHTMLEDITCMDID deCommand, OLECMDEXECOPT cmdexecopt,
|
|
VARIANT* pVarInput, VARIANT* pVarOutput)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPOLECOMMANDTARGET pCmdTgt = NULL;
|
|
ULONG ulMappedCommand = 0;
|
|
const GUID* pguidCmdGroup = NULL;
|
|
BOOL bOutParam = FALSE;
|
|
|
|
if (FALSE == m_fActivated)
|
|
return E_UNEXPECTED;
|
|
|
|
_ASSERTE(m_pSite);
|
|
if (NULL == m_pSite)
|
|
return E_UNEXPECTED;
|
|
|
|
pCmdTgt = m_pSite->GetCommandTarget();
|
|
_ASSERTE(pCmdTgt);
|
|
|
|
if (NULL == pCmdTgt)
|
|
return E_UNEXPECTED;
|
|
|
|
// Its valid for pVarInput to be NULL
|
|
|
|
if (FAILED(hr = HrMapCommand(deCommand, &ulMappedCommand, &pguidCmdGroup, &bOutParam)))
|
|
return hr;
|
|
|
|
AssureActivated();
|
|
|
|
switch ( deCommand )
|
|
{
|
|
case DECMD_GETBLOCKFMTNAMES:
|
|
hr = HrExecGetBlockFmtNames(pVarInput);
|
|
break;
|
|
|
|
case DECMD_INSERTTABLE:
|
|
hr = HrExecInsertTable(pVarInput);
|
|
break;
|
|
|
|
case DECMD_GETFORECOLOR:
|
|
case DECMD_GETBACKCOLOR:
|
|
hr = HrExecGetColor(deCommand, ulMappedCommand, pVarOutput);
|
|
break;
|
|
|
|
case DECMD_SETFONTSIZE:
|
|
hr = HrExecSetFontSize(pVarInput);
|
|
break;
|
|
|
|
case DECMD_GETBLOCKFMT:
|
|
// Trident inconsistancy: GetBlockFmt fails if outparam isn't a BSTR. GetFontName is OK with VT_EMPTY
|
|
VariantChangeType ( pVarOutput, pVarOutput, 0, VT_BSTR );
|
|
// Fall through; do not break!
|
|
case DECMD_GETFONTNAME:
|
|
case DECMD_GETFONTSIZE:
|
|
hr = HrExecGenericCommands(pguidCmdGroup, ulMappedCommand, cmdexecopt, pVarOutput, TRUE );
|
|
break;
|
|
|
|
// Because our QueryStatus on DECMD_PROPERTIES returns TRUE for anything with IOleObject, executing the properties
|
|
// verb can return an unexpected error. Therefore, we ALWAYS return S_OK from this command to avoid causing VB and
|
|
// script to terminate.
|
|
case DECMD_PROPERTIES:
|
|
{
|
|
CComVariant varParam;
|
|
varParam.vt = VT_I4;
|
|
varParam.lVal = OLEIVERB_PROPERTIES;
|
|
hr = HrExecGenericCommands(pguidCmdGroup, ulMappedCommand, cmdexecopt, &varParam, FALSE );
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
hr = HrExecGenericCommands(pguidCmdGroup, ulMappedCommand, cmdexecopt, pVarInput, bOutParam);
|
|
break;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
if (DISP_E_BADVARTYPE == hr || DISP_E_MEMBERNOTFOUND == hr)
|
|
{
|
|
// Map these Trident errors to something more general.
|
|
// These errors can occur if Trident expected the element
|
|
// it was trying to operate on to support certain interfaces.
|
|
// The caller was trying to perform an operation not valid
|
|
// for the current selection. Probably didn't call QueryStatus
|
|
// first.
|
|
|
|
hr = OLECMDERR_E_NOTSUPPORTED;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ExecCommand handler implementations
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Helper routine for calling Exec and dealing with results.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrExecGenericCommands(const GUID* pguidCmdGroup, ULONG cmdID,
|
|
OLECMDEXECOPT cmdexecopt, LPVARIANT pVarInput, BOOL bOutParam)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPOLECOMMANDTARGET pCmdTgt = NULL;
|
|
LPVARIANT _pVar = NULL;
|
|
VARIANT varCopy;
|
|
|
|
pCmdTgt = m_pSite->GetCommandTarget();
|
|
|
|
if (pVarInput && V_VT(pVarInput) & VT_BYREF)
|
|
{
|
|
// convert VARIANTARGs to Variant for use by Trident
|
|
// this occurs in VB if the user specified a basic type
|
|
// as an arg, i.e., String or Long, instead of Variant
|
|
|
|
VariantInit(&varCopy);
|
|
if (FAILED(hr = VariantCopyInd(&varCopy, pVarInput)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
_pVar = &varCopy;
|
|
}
|
|
else if (pVarInput)
|
|
_pVar = pVarInput;
|
|
|
|
if (bOutParam)
|
|
{
|
|
hr = pCmdTgt->Exec(pguidCmdGroup, cmdID, cmdexecopt, NULL, _pVar);
|
|
}
|
|
else
|
|
{
|
|
hr = pCmdTgt->Exec(pguidCmdGroup, cmdID, cmdexecopt, _pVar, NULL);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
goto cleanup;
|
|
|
|
// if a VARIANTARG was passed in for a command with output then
|
|
// fill it in with the result from the Exec
|
|
if (bOutParam && pVarInput && (V_VT(pVarInput) & VT_BYREF))
|
|
{
|
|
_ASSERTE(_pVar); // _pVar should always be non NULL here
|
|
// if there was an input arg that was byref,
|
|
// then it should have been mapped to _pVar
|
|
|
|
if (NULL == _pVar)
|
|
return E_UNEXPECTED; // the catch all error return for "we are in a weird state"
|
|
|
|
// if the type of return is different that the type the caller
|
|
// passed in then do nothing and return
|
|
if (V_VT(_pVar) != (V_VT(pVarInput) ^ VT_BYREF))
|
|
return hr;
|
|
|
|
switch(V_VT(_pVar))
|
|
{
|
|
case VT_BSTR:
|
|
_ASSERTE(V_VT(pVarInput) == (VT_BSTR|VT_BYREF));
|
|
|
|
if (V_BSTRREF(pVarInput))
|
|
hr = SysReAllocString(V_BSTRREF(pVarInput), V_BSTR(_pVar));
|
|
break;
|
|
|
|
case VT_BOOL:
|
|
_ASSERTE(V_VT(pVarInput) == (VT_BOOL|VT_BYREF));
|
|
|
|
if (V_BOOLREF(pVarInput))
|
|
*(V_BOOLREF(pVarInput)) = V_BOOL(_pVar);
|
|
break;
|
|
|
|
case VT_I4:
|
|
_ASSERTE(V_VT(pVarInput) == (VT_I4|VT_BYREF));
|
|
|
|
if (V_I4REF(pVarInput))
|
|
*(V_I4REF(pVarInput)) = V_I4(_pVar);
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
// Our documentation replaces E_FAIL with DE_E_UNEXPECTED: different values.
|
|
if ( E_FAIL == hr )
|
|
{
|
|
hr = DE_E_UNEXPECTED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Handler for command DECMD_GETBLOCKFMTNAMES.
|
|
// There are plenty of possible types of arrays to be handled.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrExecGetBlockFmtNames(LPVARIANT pVarInput)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPOLECOMMANDTARGET pCmdTgt = NULL;
|
|
VARIANT varArray;
|
|
LPUNKNOWN pUnk = NULL;
|
|
CComPtr<IDEGetBlockFmtNamesParam> piNamesParam;
|
|
|
|
pCmdTgt = m_pSite->GetCommandTarget();
|
|
|
|
if (NULL == pVarInput)
|
|
return E_INVALIDARG;
|
|
|
|
if (V_VT(pVarInput) == (VT_BYREF|VT_DISPATCH))
|
|
{
|
|
if (V_DISPATCHREF(pVarInput))
|
|
pUnk = *(V_DISPATCHREF(pVarInput));
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else if (V_VT(pVarInput) == VT_DISPATCH)
|
|
{
|
|
if (V_DISPATCH(pVarInput))
|
|
pUnk = V_DISPATCH(pVarInput);
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else if (V_VT(pVarInput) == (VT_BYREF|VT_UNKNOWN))
|
|
{
|
|
if (V_UNKNOWNREF(pVarInput))
|
|
pUnk = *(V_UNKNOWNREF(pVarInput));
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else if (V_VT(pVarInput) == VT_UNKNOWN)
|
|
{
|
|
if (V_UNKNOWN(pVarInput))
|
|
pUnk = V_UNKNOWN(pVarInput);
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
|
|
// This can happen in VB if an object that has not
|
|
// been set with CreateObject has been passed in
|
|
if (NULL == pUnk)
|
|
return E_INVALIDARG;
|
|
|
|
// Try to get the names object before
|
|
// performing the command
|
|
|
|
if (FAILED(hr = pUnk->QueryInterface(IID_IDEGetBlockFmtNamesParam, (LPVOID*) &piNamesParam)))
|
|
return E_INVALIDARG;
|
|
|
|
_ASSERTE((!piNamesParam) == FALSE);
|
|
|
|
// Trident wants the vt to be specifically VT_ARRAY with
|
|
// no type qualifer -- if you give one it fails even though
|
|
// an array of BSTRs is returned
|
|
|
|
VariantInit(&varArray);
|
|
V_VT(&varArray) = VT_ARRAY;
|
|
|
|
hr = pCmdTgt->Exec(&GUID_TriEditCommandGroup, IDM_TRIED_GETBLOCKFMTS,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, NULL, &varArray);
|
|
|
|
if (FAILED(hr))
|
|
goto cleanup;
|
|
|
|
piNamesParam->put_Names(&varArray);
|
|
|
|
cleanup:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Handler for command DECMD_INSERTTABLE.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrExecInsertTable(LPVARIANT pVarInput)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPOLECOMMANDTARGET pCmdTgt = NULL;
|
|
VARIANT varTableArray;
|
|
LPUNKNOWN pUnk = NULL;
|
|
CComPtr<IDEInsertTableParam> piTableParam;
|
|
|
|
pCmdTgt = m_pSite->GetCommandTarget();
|
|
|
|
VariantInit(&varTableArray);
|
|
|
|
if (NULL == pVarInput)
|
|
return E_INVALIDARG;
|
|
|
|
if (V_VT(pVarInput) == (VT_BYREF|VT_DISPATCH))
|
|
{
|
|
if (V_DISPATCHREF(pVarInput))
|
|
pUnk = *(V_DISPATCHREF(pVarInput));
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else if (V_VT(pVarInput) == VT_DISPATCH)
|
|
{
|
|
if (V_DISPATCH(pVarInput))
|
|
pUnk = V_DISPATCH(pVarInput);
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else if (V_VT(pVarInput) == (VT_BYREF|VT_UNKNOWN))
|
|
{
|
|
if (V_UNKNOWNREF(pVarInput))
|
|
pUnk = *(V_UNKNOWNREF(pVarInput));
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else if (V_VT(pVarInput) == VT_UNKNOWN)
|
|
{
|
|
if (V_UNKNOWN(pVarInput))
|
|
pUnk = V_UNKNOWN(pVarInput);
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
|
|
// This can happen in VB if an object that has not
|
|
// been set with CreateObject has been passed in
|
|
if (NULL == pUnk)
|
|
return E_INVALIDARG;
|
|
|
|
if (FAILED(hr = pUnk->QueryInterface(IID_IDEInsertTableParam, (LPVOID*) &piTableParam)))
|
|
return E_INVALIDARG;
|
|
|
|
_ASSERTE((!piTableParam) == FALSE);
|
|
|
|
if (FAILED(hr = HrGetTableSafeArray(piTableParam, &varTableArray)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
hr = pCmdTgt->Exec(&GUID_TriEditCommandGroup, IDM_TRIED_INSERTTABLE,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, &varTableArray, NULL);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Hanlder for commands DECMD_GETFORECOLOR and DECMD_GETBACKCOLOR.
|
|
// Reply with a string in the format #RRGGBB or an empty string.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrExecGetColor(DHTMLEDITCMDID deCommand, ULONG ulMappedCommand, LPVARIANT pVarOutput)
|
|
{
|
|
USES_CONVERSION;
|
|
HRESULT hr = S_OK;
|
|
LPOLECOMMANDTARGET pCmdTgt = NULL;
|
|
VARIANT varColorOut;
|
|
TCHAR buf[32];
|
|
WCHAR* oleStr = NULL;
|
|
|
|
pCmdTgt = m_pSite->GetCommandTarget();
|
|
|
|
if (NULL == pVarOutput)
|
|
return E_INVALIDARG;
|
|
|
|
// validate the command
|
|
if (DECMD_GETFORECOLOR != deCommand && DECMD_GETBACKCOLOR != deCommand)
|
|
return E_INVALIDARG;
|
|
|
|
// validate the args
|
|
if (V_VT(pVarOutput) == (VT_BYREF|VT_BSTR))
|
|
{
|
|
if (NULL == V_BSTRREF(pVarOutput))
|
|
return E_INVALIDARG;
|
|
}
|
|
else if (V_VT(pVarOutput) == VT_BSTR)
|
|
{
|
|
if (NULL == V_BSTR(pVarOutput))
|
|
return E_INVALIDARG;
|
|
}
|
|
else if (V_VT(pVarOutput) != (VT_EMPTY) && V_VT(pVarOutput) != (VT_NULL))
|
|
return E_INVALIDARG;
|
|
|
|
VariantInit(&varColorOut);
|
|
V_VT(&varColorOut) = VT_I4;
|
|
|
|
hr = pCmdTgt->Exec(&GUID_TriEditCommandGroup, ulMappedCommand,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, NULL, &varColorOut);
|
|
|
|
// Trident will return VT_NULL if color selection
|
|
// was mixed or no text is selected, we return empty
|
|
// string ("") in that case.
|
|
|
|
buf[0] = 0;
|
|
|
|
if (VT_I4 == V_VT(&varColorOut))
|
|
{
|
|
ULONG ulColor = 0;
|
|
ULONG r=0;
|
|
ULONG g=0;
|
|
ULONG b=0;
|
|
|
|
ulColor = V_I4(&varColorOut);
|
|
r = 0x000000ff & ulColor;
|
|
g = (0x0000ff00 & ulColor) >> 8;
|
|
b = (0x00ff0000 & ulColor) >> 16;
|
|
|
|
wsprintf(buf, TEXT("#%02X%02X%02X"), r, g, b);
|
|
}
|
|
|
|
oleStr = T2OLE(buf);
|
|
|
|
if (V_VT(pVarOutput) == (VT_BSTR|VT_BYREF))
|
|
hr = SysReAllocString(V_BSTRREF(pVarOutput), oleStr);
|
|
else if (V_VT(pVarOutput) == (VT_BSTR))
|
|
hr = SysReAllocString(&(V_BSTR(pVarOutput)), oleStr);
|
|
else if (V_VT(pVarOutput) == (VT_EMPTY) || V_VT(pVarOutput) == (VT_NULL))
|
|
{
|
|
V_VT(pVarOutput) = VT_BSTR;
|
|
V_BSTR(pVarOutput) = SysAllocString(oleStr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Handler for command DECMD_SETFONTSIZE.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrExecSetFontSize(LPVARIANT pVarInput)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPOLECOMMANDTARGET pCmdTgt = NULL;
|
|
VARIANT varSizeIn;
|
|
|
|
|
|
pCmdTgt = m_pSite->GetCommandTarget();
|
|
|
|
if (NULL == pVarInput)
|
|
return E_INVALIDARG;
|
|
|
|
VariantInit(&varSizeIn);
|
|
|
|
if (FAILED(hr = VariantChangeType(&varSizeIn, pVarInput, 0, VT_I4)))
|
|
return E_INVALIDARG;
|
|
|
|
if (varSizeIn.lVal < 0 || varSizeIn.lVal > 7)
|
|
return E_INVALIDARG;
|
|
|
|
if (0 == varSizeIn.lVal)
|
|
varSizeIn.lVal = varSizeIn.lVal + 1;
|
|
|
|
|
|
hr = pCmdTgt->Exec(&GUID_TriEditCommandGroup, IDM_TRIED_FONTSIZE,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, &varSizeIn, NULL);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// QueryStatus mechanism
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Map the control specific command ID to a TriEdit command ID and call QueryStatus.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrMapQueryStatus( DHTMLEDITCMDID ucmdID, DHTMLEDITCMDF* cmdf)
|
|
{
|
|
LPOLECOMMANDTARGET pCommandTarget = NULL;
|
|
|
|
_ASSERTE(cmdf);
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (FALSE == m_fActivated)
|
|
return E_UNEXPECTED;
|
|
|
|
if (NULL == cmdf)
|
|
return E_INVALIDARG;
|
|
|
|
*cmdf = (DHTMLEDITCMDF) 0;
|
|
|
|
_ASSERTE(m_pSite);
|
|
|
|
if (NULL == m_pSite)
|
|
return E_UNEXPECTED;
|
|
|
|
pCommandTarget = m_pSite->GetCommandTarget();
|
|
_ASSERTE(pCommandTarget);
|
|
|
|
if ( pCommandTarget != NULL )
|
|
{
|
|
|
|
AssureActivated ();
|
|
|
|
ULONG cmdID = 0;
|
|
const GUID* pguidCmdGroup = NULL;
|
|
BOOL bOutParam = FALSE;
|
|
|
|
if (SUCCEEDED(hr = HrMapCommand(ucmdID, &cmdID, &pguidCmdGroup, &bOutParam)))
|
|
{
|
|
MSOCMD msocmd;
|
|
msocmd.cmdID = cmdID;
|
|
msocmd.cmdf = 0;
|
|
|
|
hr = pCommandTarget->QueryStatus(pguidCmdGroup, 1, &msocmd, NULL);
|
|
|
|
*cmdf = (DHTMLEDITCMDF) msocmd.cmdf;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// General routine for determining the status of a command.
|
|
// Should resolve to not supported, disabled, enabled, latched or ninched.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrQueryStatus(const GUID* pguidCmdGroup, ULONG ucmdID, OLECMDF* cmdf)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
_ASSERTE(cmdf);
|
|
|
|
// Note that it is valid for pguidCmdGroup to be NULL
|
|
|
|
if (NULL == cmdf)
|
|
return E_INVALIDARG;
|
|
|
|
*cmdf = (OLECMDF) 0;
|
|
|
|
_ASSERTE(m_pSite);
|
|
|
|
if ( m_pSite != NULL ) // m_pSite should always be set
|
|
{
|
|
LPOLECOMMANDTARGET pCommandTarget = m_pSite->GetCommandTarget();
|
|
|
|
if ( pCommandTarget != NULL )
|
|
{
|
|
MSOCMD msocmd;
|
|
msocmd.cmdID = ucmdID;
|
|
msocmd.cmdf = 0;
|
|
|
|
hr = pCommandTarget->QueryStatus(pguidCmdGroup, 1, &msocmd, NULL);
|
|
|
|
*cmdf = (OLECMDF) msocmd.cmdf;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// A tragic FAT16 compatibility problem: file names in the specific form:
|
|
// [a-zA-z]\:[^\\].+ cause various, severe problems. NTFS "forgives".
|
|
// We must detect these, both in file names and file:// URL and return an error.
|
|
//
|
|
BOOL
|
|
CProxyFrame::IsMissingBackSlash ( BSTR path, BOOL bfIsURL )
|
|
{
|
|
BOOL bfMissing = FALSE;
|
|
|
|
if ( bfIsURL )
|
|
{
|
|
WCHAR wszFileProtocol[] = L"file://";
|
|
int cchProtocol = wcslen ( wszFileProtocol );
|
|
|
|
if ( 0 == _wcsnicmp ( path, wszFileProtocol, cchProtocol ) )
|
|
{
|
|
if ( OLECHAR(':') == path[cchProtocol+1] )
|
|
{
|
|
if ( OLECHAR('\\') != path[cchProtocol+2] )
|
|
{
|
|
bfMissing = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Path name. chec for drive letter, colon, non-backslash.
|
|
if ( OLECHAR(':') == path[1] )
|
|
{
|
|
if ( OLECHAR('\\') != path[2] )
|
|
{
|
|
bfMissing = TRUE;
|
|
}
|
|
}
|
|
}
|
|
return bfMissing;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Control methods and properties
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Handles NewDocument, LoadURL and LoadDocument control methods.
|
|
// The document is loaded indirectly via the pluggable protocol handler.
|
|
// If "path" is NULL, do NewDocument. TestbfURL to see if it's a URL or UNC path.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::LoadDocument(BSTR path, BOOL bfIsURL )
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr = S_OK;
|
|
UINT pathLen = 0;
|
|
|
|
AssureActivated (); // This can set m_bstrLoadText as a side effect in unactivated controls! Be careful!
|
|
|
|
if (FALSE == m_fActivated)
|
|
return E_UNEXPECTED;
|
|
|
|
m_bstrLoadText.Empty (); // Clear the text to be added directly, or it will be used instead!
|
|
m_bstrCurDocPath = L"";
|
|
m_bstrBaseURL = L"";
|
|
|
|
if (path)
|
|
pathLen = ::SysStringLen(path);
|
|
else
|
|
pathLen = 0;
|
|
|
|
// We've resetting the contents of the control. Go back to default save mechanism.
|
|
// If we load Unicode it will be reset.
|
|
m_pSite->SetSaveAsUnicode ( FALSE );
|
|
|
|
if (path && pathLen)
|
|
{
|
|
_ASSERTE(path);
|
|
_ASSERTE(pathLen > 0);
|
|
|
|
// First, look out for a wicked error: X:FileName with no '\' is BAD on FAT16.
|
|
if ( IsMissingBackSlash ( path, bfIsURL ) )
|
|
{
|
|
hr = DE_E_PATH_NOT_FOUND;
|
|
LoadBSTRDeferred ( m_bstrInitialDoc );
|
|
goto error;
|
|
}
|
|
|
|
// Try to open the file -- stop the sequence
|
|
// if its bogus or we don't have access
|
|
if ( !bfIsURL )
|
|
{
|
|
if (FAILED(hr = m_pSite->HrTestFileOpen(path)))
|
|
{
|
|
LoadBSTRDeferred ( m_bstrInitialDoc );
|
|
goto error;
|
|
}
|
|
}
|
|
m_bfIsURL = bfIsURL;
|
|
|
|
m_bstrCurDocPath = path; // This needs to be set before loading, because base url is needed durring load.
|
|
SetBaseURLFromCurDocPath ( bfIsURL );
|
|
m_bfPreserveDirtyFlagAcrossBrowseMode = FALSE;
|
|
|
|
CComPtr<IMoniker> srpMoniker;
|
|
CComPtr<IBindCtx> srpBindCtx;
|
|
CComQIPtr<IPersistMoniker, &IID_IPersistMoniker> srpPM (m_pUnkTriEdit);
|
|
_ASSERTE ( srpPM );
|
|
|
|
if ( srpPM )
|
|
{
|
|
CComBSTR bstrProtocol = m_wszProtocolPrefix;
|
|
bstrProtocol += L"(";
|
|
bstrProtocol += path;
|
|
bstrProtocol += L")";
|
|
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
_ASSERTE ( m_pfnCreateURLMoniker );
|
|
hr = (*m_pfnCreateURLMoniker)( NULL, bstrProtocol, &srpMoniker );
|
|
#else
|
|
hr = CreateURLMoniker ( NULL, bstrProtocol, &srpMoniker );
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
_ASSERTE ( SUCCEEDED( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = ::CreateBindCtx(NULL, &srpBindCtx);
|
|
_ASSERTE ( SUCCEEDED( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
// Delete the cache entry before downloading.
|
|
// This assures that loading, posting, and reloading works.
|
|
// Bug 18544.
|
|
// NOTE: Inexact match fails! http://www.microsoft.com fails,
|
|
// because this actually loads/caches a specific default page.
|
|
if ( bfIsURL )
|
|
{
|
|
LPTSTR szURL = OLE2T ( m_bstrCurDocPath );
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
_ASSERTE ( m_pfnDeleteUrlCacheEntry );
|
|
(*m_pfnDeleteUrlCacheEntry)( szURL );
|
|
#else
|
|
DeleteUrlCacheEntry ( szURL );
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
}
|
|
m_bfIsLoading = TRUE;
|
|
m_hrDeferredLoadError = S_OK; // URLs: don't let Trident get the error!
|
|
|
|
hr = srpPM->Load(FALSE, srpMoniker, srpBindCtx, STGM_READ);
|
|
|
|
if ( SUCCEEDED ( hr ) && FAILED ( m_hrDeferredLoadError ) )
|
|
{
|
|
hr = m_hrDeferredLoadError; // In case we stashed a result
|
|
}
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
m_bfIsLoading = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (FAILED(hr = LoadBSTRDeferred ( m_bstrInitialDoc )))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
error:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements FilterSourceCode control method
|
|
// Used to restore filtered content extracted directly from DOM.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::FilterSourceCode ( BSTR bsSourceIn, BSTR* pbsSourceOut )
|
|
{
|
|
HRESULT hr;
|
|
CComPtr<IStream> spStreamIn;
|
|
IStream* piStreamOut;
|
|
|
|
hr = m_pSite->HrBstrToStream(bsSourceIn, &spStreamIn);
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
if ( m_vbBrowseMode )
|
|
{
|
|
spStreamIn.p->AddRef ();
|
|
piStreamOut = spStreamIn;
|
|
}
|
|
else
|
|
{
|
|
hr = m_pSite->HrFilter ( FALSE, spStreamIn, &piStreamOut, m_dwFilterOutFlags | dwFilterSourceCode);
|
|
}
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = m_pSite->HrStreamToBstr ( piStreamOut, pbsSourceOut );
|
|
piStreamOut->Release ();
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements the control's Print method
|
|
//
|
|
HRESULT
|
|
CProxyFrame::Print ( BOOL bfWithUI )
|
|
{
|
|
AssureActivated ();
|
|
|
|
if (FALSE == m_fActivated)
|
|
return E_UNEXPECTED;
|
|
return HrExecCommand ( &GUID_TriEditCommandGroup, IDM_TRIED_PRINT,
|
|
bfWithUI ? MSOCMDEXECOPT_PROMPTUSER : MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL );
|
|
}
|
|
|
|
|
|
// Implements the control's Refresh method
|
|
//
|
|
HRESULT
|
|
CProxyFrame::RefreshDoc ()
|
|
{
|
|
if ( NULL != m_hWndObj )
|
|
{
|
|
if ( ::IsWindow ( m_hWndObj ) )
|
|
{
|
|
::InvalidateRect ( m_hWndObj, NULL, TRUE );
|
|
return S_OK;
|
|
}
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
// Implements the control's SaveDocument method
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SaveDocument(BSTR path)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG pathLen = 0;
|
|
|
|
if (FALSE == m_fActivated)
|
|
return E_UNEXPECTED;
|
|
|
|
_ASSERTE(GetState() == ESTATE_ACTIVATED);
|
|
|
|
AssureActivated ();
|
|
|
|
if (GetState() != ESTATE_ACTIVATED)
|
|
return E_UNEXPECTED;
|
|
|
|
_ASSERTE(path);
|
|
|
|
if (path)
|
|
pathLen = ::SysStringLen(path);
|
|
else
|
|
pathLen = 0;
|
|
|
|
if (0 == pathLen)
|
|
return E_INVALIDARG;
|
|
|
|
_ASSERTE(pathLen);
|
|
|
|
// First, look out for a wicked error: X:FileName with no '\' is BAD on FAT16.
|
|
if ( IsMissingBackSlash ( path, FALSE ) )
|
|
{
|
|
return DE_E_PATH_NOT_FOUND;
|
|
}
|
|
|
|
hr = m_pSite->HrSaveToFile(path, m_dwFilterOutFlags);
|
|
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
m_bstrCurDocPath = path;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements the control's SetContextMenu method
|
|
// One routine handles javascript arrays, the other simple arrays.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetContextMenu(LPVARIANT pVarMenuStrings, LPVARIANT pVarMenuStates)
|
|
{
|
|
if (V_VT(pVarMenuStrings) == VT_DISPATCH || V_VT(pVarMenuStates) == VT_DISPATCH)
|
|
return SetContextMenuDispEx(pVarMenuStrings, pVarMenuStates);
|
|
else
|
|
return SetContextMenuSA(pVarMenuStrings, pVarMenuStates);
|
|
}
|
|
|
|
|
|
// Get menu strings from SafeArray
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetContextMenuSA(LPVARIANT pVarMenuStrings, LPVARIANT pVarMenuStates)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SAFEARRAY* psaStrings = NULL;
|
|
SAFEARRAY* psaStates = NULL;
|
|
LONG lLBound, lUBound, lLBoundState, lUBoundState;
|
|
|
|
if (NULL == pVarMenuStrings || NULL == pVarMenuStates)
|
|
return E_INVALIDARG;
|
|
|
|
if ((VT_ARRAY|VT_BSTR) != V_VT(pVarMenuStrings) &&
|
|
((VT_ARRAY|VT_BSTR)|VT_BYREF) != V_VT(pVarMenuStrings) &&
|
|
((VT_ARRAY|VT_VARIANT)|VT_BYREF) != V_VT(pVarMenuStrings) &&
|
|
(VT_ARRAY|VT_VARIANT) != V_VT(pVarMenuStrings))
|
|
return E_INVALIDARG;
|
|
|
|
if ((VT_ARRAY|VT_I4) != V_VT(pVarMenuStates) &&
|
|
((VT_ARRAY|VT_I4)|VT_BYREF) != V_VT(pVarMenuStates) &&
|
|
((VT_ARRAY|VT_VARIANT)|VT_BYREF) != V_VT(pVarMenuStates) &&
|
|
(VT_ARRAY|VT_VARIANT) != V_VT(pVarMenuStates))
|
|
return E_INVALIDARG;
|
|
|
|
if ((VT_ARRAY|VT_BSTR) == V_VT(pVarMenuStrings))
|
|
{
|
|
psaStrings = V_ARRAY(pVarMenuStrings);
|
|
}
|
|
if ((VT_ARRAY|VT_VARIANT) == V_VT(pVarMenuStrings))
|
|
{
|
|
psaStrings = V_ARRAY(pVarMenuStrings);
|
|
}
|
|
else if ((VT_ARRAY|VT_BSTR|VT_BYREF) == V_VT(pVarMenuStrings))
|
|
{
|
|
if (NULL == V_ARRAYREF(pVarMenuStrings))
|
|
return E_INVALIDARG;
|
|
|
|
psaStrings = *(V_ARRAYREF(pVarMenuStrings));
|
|
}
|
|
else if ((VT_ARRAY|VT_VARIANT|VT_BYREF) == V_VT(pVarMenuStrings))
|
|
{
|
|
if (NULL == V_ARRAYREF(pVarMenuStrings))
|
|
return E_INVALIDARG;
|
|
|
|
psaStrings = *(V_ARRAYREF(pVarMenuStrings));
|
|
}
|
|
|
|
if ((VT_ARRAY|VT_I4) == V_VT(pVarMenuStates))
|
|
{
|
|
psaStates = V_ARRAY(pVarMenuStates);
|
|
}
|
|
if ((VT_ARRAY|VT_VARIANT) == V_VT(pVarMenuStates))
|
|
{
|
|
psaStates = V_ARRAY(pVarMenuStates);
|
|
}
|
|
else if ((VT_ARRAY|VT_I4|VT_BYREF) == V_VT(pVarMenuStates))
|
|
{
|
|
if (NULL == V_ARRAYREF(pVarMenuStates))
|
|
return E_INVALIDARG;
|
|
|
|
psaStates = *(V_ARRAYREF(pVarMenuStates));
|
|
}
|
|
else if ((VT_ARRAY|VT_VARIANT|VT_BYREF) == V_VT(pVarMenuStates))
|
|
{
|
|
if (NULL == V_ARRAYREF(pVarMenuStates))
|
|
return E_INVALIDARG;
|
|
|
|
psaStates = *(V_ARRAYREF(pVarMenuStates));
|
|
}
|
|
|
|
|
|
if (NULL == psaStrings || NULL == psaStates)
|
|
return E_INVALIDARG;
|
|
|
|
SafeArrayGetLBound(psaStrings, 1, &lLBound);
|
|
SafeArrayGetUBound(psaStrings, 1, &lUBound);
|
|
|
|
SafeArrayGetLBound(psaStates, 1, &lLBoundState);
|
|
SafeArrayGetUBound(psaStates, 1, &lUBoundState);
|
|
|
|
if (lLBound != lLBoundState || lUBound != lUBoundState)
|
|
return E_INVALIDARG;
|
|
|
|
if (m_pMenuStrings)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStrings);
|
|
m_pMenuStrings = NULL;
|
|
}
|
|
|
|
if (m_pMenuStates)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStates);
|
|
m_pMenuStates = NULL;
|
|
}
|
|
|
|
// An empty array was passed in
|
|
// The context menu has been cleared
|
|
if (lLBound ==lUBound )
|
|
goto cleanup;
|
|
|
|
if (FAILED(hr = SafeArrayCopy(psaStrings, &m_pMenuStrings)))
|
|
goto cleanup;
|
|
|
|
if (FAILED(hr = SafeArrayCopy(psaStates, &m_pMenuStates)))
|
|
goto cleanup;
|
|
|
|
cleanup:
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
if (m_pMenuStrings)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStrings);
|
|
m_pMenuStrings = NULL;
|
|
}
|
|
|
|
if (m_pMenuStates)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStates);
|
|
m_pMenuStates = NULL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Get menu strings from JScript array, or object that supports IDispatchEx
|
|
// For iterating through JScript arrays, we expect the elements
|
|
// to be accessable by ordinals starting at 0, i.e., a 0 based array
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetContextMenuDispEx(LPVARIANT pVarMenuStrings, LPVARIANT pVarMenuStates)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG i=0;
|
|
ULONG ulStringsLen = 0;
|
|
ULONG ulStatesLen = 0;
|
|
IDispatch* pdStrings = NULL;
|
|
IDispatch* pdStates = NULL;
|
|
IDispatchEx* pdexStrings = NULL;
|
|
IDispatchEx* pdexStates = NULL;
|
|
CDispExArray dispStrings;
|
|
CDispExArray dispStates;
|
|
VARIANT varString;
|
|
VARIANT varState;
|
|
SAFEARRAYBOUND rgsabound[1] = {0};
|
|
LONG ix[1] = {0};
|
|
|
|
if (VT_DISPATCH != V_VT(pVarMenuStrings) || VT_DISPATCH != V_VT(pVarMenuStates))
|
|
return E_INVALIDARG;
|
|
|
|
VariantInit(&varString);
|
|
VariantInit(&varState);
|
|
|
|
pdStrings = V_DISPATCH(pVarMenuStrings);
|
|
pdStates = V_DISPATCH(pVarMenuStates);
|
|
|
|
_ASSERTE(pdStrings);
|
|
_ASSERTE(pdStates);
|
|
|
|
if (FAILED(hr = pdStrings->QueryInterface(IID_IDispatchEx, (LPVOID*) &pdexStrings)))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
dispStrings.Attach(pdexStrings);
|
|
|
|
if (FAILED(hr = pdStates->QueryInterface(IID_IDispatchEx, (LPVOID*) &pdexStates)))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
dispStates.Attach(pdexStates);
|
|
|
|
if (FAILED(dispStrings.HrGetLength(&ulStringsLen)))
|
|
goto cleanup;
|
|
|
|
if (FAILED(dispStates.HrGetLength(&ulStatesLen)))
|
|
goto cleanup;
|
|
|
|
// Make sure that arrays are equal length
|
|
if (ulStringsLen != ulStatesLen)
|
|
return E_INVALIDARG;
|
|
|
|
if (m_pMenuStrings)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStrings);
|
|
m_pMenuStrings = NULL;
|
|
}
|
|
|
|
if (m_pMenuStates)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStates);
|
|
m_pMenuStates = NULL;
|
|
}
|
|
|
|
// An empty array was passed in
|
|
// The context menu has been cleared
|
|
if (ulStringsLen <= 0)
|
|
goto cleanup;
|
|
|
|
rgsabound[0].lLbound = 0;
|
|
rgsabound[0].cElements = ulStringsLen;
|
|
|
|
m_pMenuStrings = SafeArrayCreate(VT_BSTR, 1, rgsabound);
|
|
_ASSERTE(m_pMenuStrings);
|
|
if (NULL == m_pMenuStrings)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
m_pMenuStates = SafeArrayCreate(VT_I4, 1, rgsabound);
|
|
_ASSERTE(m_pMenuStates);
|
|
if (NULL == m_pMenuStates)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
// For iterating through JScript arrays, we expect the elements
|
|
// to be accessable by ordinals starting at 0, i.e., a 0 based array
|
|
hr = S_OK;
|
|
for (i=0; i < ulStringsLen && hr != S_FALSE; i++)
|
|
{
|
|
if (FAILED(hr = dispStrings.HrGetElement(i, &varString)))
|
|
goto cleanup;
|
|
|
|
if (FAILED(hr = dispStates.HrGetElement(i, &varState)))
|
|
goto cleanup;
|
|
|
|
if (VT_BSTR != V_VT(&varString) || VT_I4 != V_VT(&varState))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto cleanup;
|
|
}
|
|
|
|
ix[0] = i;
|
|
if (FAILED(hr = SafeArrayPutElement(m_pMenuStrings, ix, (LPVOID) V_BSTR(&varString))))
|
|
goto cleanup;
|
|
|
|
if (FAILED(hr = SafeArrayPutElement(m_pMenuStates, ix, (LPVOID) &(V_I4(&varState)))))
|
|
goto cleanup;
|
|
|
|
VariantClear ( &varString );
|
|
VariantClear ( &varState );
|
|
}
|
|
|
|
cleanup:
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
if (m_pMenuStrings)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStrings);
|
|
m_pMenuStrings = NULL;
|
|
}
|
|
|
|
if (m_pMenuStates)
|
|
{
|
|
SafeArrayDestroy(m_pMenuStates);
|
|
m_pMenuStates = NULL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// DocumentTitle property implementation; read only.
|
|
// Get the property from the HTML document.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetDocumentTitle ( CComBSTR& bstrTitle )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DISPID dispid;
|
|
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
|
|
CComVariant varResult;
|
|
|
|
CComPtr<IHTMLDocument2> piHtmlDoc = NULL;
|
|
hr = HrGetDoc( &piHtmlDoc );
|
|
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
AssureActivated();
|
|
|
|
hr = piHtmlDoc->GetIDsOfNames ( IID_NULL, &g_wszHTMLTitlePropName, 1, LOCALE_SYSTEM_DEFAULT, &dispid );
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = piHtmlDoc->Invoke ( dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,
|
|
&dispparamsNoArgs, &varResult, NULL, NULL );
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = varResult.ChangeType ( VT_BSTR );
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
bstrTitle = varResult.bstrVal;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's BrowseMode property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetBrowseMode ( VARIANT_BOOL *pVal )
|
|
{
|
|
*pVal = m_vbBrowseMode;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements setting the control's BrowseMode property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetBrowseMode ( VARIANT_BOOL newVal )
|
|
{
|
|
HRESULT hr = S_FALSE; // Indicates value was set, but actual mode was not changed.
|
|
|
|
_ASSERTE ( m_pSite );
|
|
|
|
// If we're still reading the property bag, just set the value, don't change the text;
|
|
// it hasn't been loaded yet.
|
|
if ( NULL == m_pSite->GetCommandTarget() )
|
|
{
|
|
m_vbBrowseMode = newVal;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
if ( m_vbBrowseMode != newVal )
|
|
{
|
|
AssureActivated ();
|
|
|
|
m_bfModeSwitched = TRUE;
|
|
|
|
if ( newVal && m_pCtl->IsUserMode () ) // newVal means "switching to browse mode"
|
|
{
|
|
CComPtr<IStream> spStream = NULL;
|
|
|
|
HrGetIsDirty ( m_bfPreserveDirtyFlagAcrossBrowseMode );
|
|
hr = m_pSite->HrSaveToStreamAndFilter ( &spStream, m_dwFilterOutFlags );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
m_bstrLoadText.Empty ();
|
|
// Preserve the byte order mark, or else it will not be reloaded properly
|
|
hr = m_pSite->HrStreamToBstr ( spStream, &m_bstrLoadText, TRUE );
|
|
}
|
|
}
|
|
|
|
m_vbBrowseMode = newVal;
|
|
|
|
// Let Trident know the ambient property has changed.
|
|
CComQIPtr<IOleControl,&IID_IOleControl>spioc ( m_pSite->GetObjectUnknown() );
|
|
if ( spioc )
|
|
{
|
|
m_bfIsLoading = TRUE;
|
|
spioc->OnAmbientPropertyChange ( DISPID_AMBIENT_USERMODE );
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's UseDivOnCarriageReturn property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetDivOnCr ( VARIANT_BOOL *pVal )
|
|
{
|
|
*pVal = m_vbUseDivOnCr;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements setting the control's UseDivOnCarriageReturn property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetDivOnCr ( VARIANT_BOOL newVal )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComVariant varDefBlock;
|
|
|
|
m_vbUseDivOnCr = newVal;
|
|
|
|
// Reinitialize if we haven't loaded our properties before this point.
|
|
if ( READYSTATE_UNINITIALIZED == m_readyState )
|
|
{
|
|
// InitializeDocString takes m_vbUseDivOnCr into account
|
|
InitializeDocString ();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's read-only Busy property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetBusy ( VARIANT_BOOL *pVal )
|
|
{
|
|
#pragma warning(disable: 4310) // cast truncates constant value
|
|
*pVal = ( m_bfIsLoading ) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
#pragma warning(default: 4310) // cast truncates constant value
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements setting the control's ActivateActiveXControls property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetPropActivateControls(BOOL activateControls)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_fActivated)
|
|
{
|
|
if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_NOACTIVATENORMALOLECONTROLS, !activateControls)))
|
|
m_fActivateControls = activateControls;
|
|
}
|
|
else
|
|
m_fActivateControls = activateControls;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's ActivateActiveXControls property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetPropActivateControls(BOOL& activateControls)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
activateControls = m_fActivateControls;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements setting the control's ActivateApplets property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetPropActivateApplets(BOOL activateApplets)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_fActivated)
|
|
{
|
|
if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_NOACTIVATEJAVAAPPLETS, !activateApplets)))
|
|
m_fActivateApplets = activateApplets;
|
|
}
|
|
else
|
|
m_fActivateApplets = activateApplets;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's ActivateApplets property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetPropActivateApplets(BOOL& activateApplets)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
activateApplets = m_fActivateApplets;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements setting the control's ActivateDTCs property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetPropActivateDTCs(BOOL activateDTCs)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_fActivated)
|
|
{
|
|
if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_NOACTIVATEDESIGNTIMECONTROLS, !activateDTCs)))
|
|
m_fActivateDTCs = activateDTCs;
|
|
}
|
|
else
|
|
m_fActivateDTCs = activateDTCs;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's ActivateDTCs property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetPropActivateDTCs(BOOL& activateDTCs)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
activateDTCs = m_fActivateDTCs;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
// Implements setting the control's ShowDetails property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetPropShowAllTags(BOOL showAllTags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_fActivated)
|
|
{
|
|
if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_SHOWALLTAGS, showAllTags)))
|
|
m_fShowAllTags = showAllTags;
|
|
}
|
|
else
|
|
m_fShowAllTags = showAllTags;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's ShowDetails property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetPropShowAllTags(BOOL& showAllTags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
showAllTags = m_fShowAllTags;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements setting the control's ShowBorders property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetPropShowBorders(BOOL showBorders)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_fActivated)
|
|
{
|
|
if (SUCCEEDED(hr = HrTridentSetPropBool(IDM_SHOWZEROBORDERATDESIGNTIME, showBorders)))
|
|
m_fShowBorders = showBorders;
|
|
}
|
|
else
|
|
m_fShowBorders = showBorders;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's ShowBorders property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetPropShowBorders(BOOL& showBorders)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
showBorders = m_fShowBorders;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements setting the control's Appearance property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetDisplay3D(BOOL bVal)
|
|
{
|
|
m_fDisplay3D = bVal;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements getting the control's Appearance property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetDisplay3D(BOOL& bVal)
|
|
{
|
|
bVal = m_fDisplay3D;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements setting the control's Scrollbars property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetScrollbars(BOOL bVal)
|
|
{
|
|
m_fScrollbars = bVal;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements getting the control's Scrollbars property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetScrollbars(BOOL& bVal)
|
|
{
|
|
bVal = m_fScrollbars;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements setting the control's ScrollbarAppearance property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetDisplayFlatScrollbars(BOOL bVal)
|
|
{
|
|
m_fDisplayFlatScrollbars = bVal;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements getting the control's ScrollbarAppearance property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetDisplayFlatScrollbars(BOOL& bVal)
|
|
{
|
|
bVal = m_fDisplayFlatScrollbars;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements setting the control's AbsoluteDropMode property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetAbsoluteDropMode(BOOL dropMode)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_fActivated)
|
|
{
|
|
VARIANT var;
|
|
|
|
VariantInit(&var);
|
|
|
|
V_VT(&var) = VT_BOOL;
|
|
#pragma warning(disable: 4310) // cast truncates constant value
|
|
V_BOOL(&var) = (dropMode) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
#pragma warning(default: 4310) // cast truncates constant value
|
|
|
|
if (SUCCEEDED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_SET_2D_DROP_MODE,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, &var, NULL)))
|
|
m_fAbsoluteDropMode = dropMode;
|
|
}
|
|
else
|
|
m_fAbsoluteDropMode = dropMode;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's AbsoluteDropMode property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetAbsoluteDropMode(BOOL& dropMode)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
dropMode = m_fAbsoluteDropMode;
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements setting the control's SnapToGrid property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetSnapToGrid(BOOL snapToGrid)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_fActivated)
|
|
{
|
|
VARIANT var;
|
|
POINT pt = {0};
|
|
|
|
VariantInit(&var);
|
|
if ( snapToGrid )
|
|
{
|
|
pt.y = m_ulSnapToGridY;
|
|
pt.x = m_ulSnapToGridX;
|
|
}
|
|
else
|
|
{
|
|
pt.y = 0;
|
|
pt.x = 0;
|
|
}
|
|
|
|
V_VT(&var) = VT_BYREF;
|
|
V_BYREF(&var) = &pt;
|
|
|
|
if (SUCCEEDED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_SET_ALIGNMENT,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, &var, NULL)))
|
|
m_fSnapToGrid = snapToGrid;
|
|
|
|
}
|
|
else
|
|
m_fSnapToGrid = snapToGrid;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's SnapToGrid property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetSnapToGrid(BOOL& snapToGrid)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
snapToGrid = m_fSnapToGrid;
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements setting the control's SnapToGridX property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetSnapToGridX(LONG snapToGridX)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( 0 >= snapToGridX )
|
|
{
|
|
return DE_E_INVALIDARG;
|
|
}
|
|
|
|
if (m_fActivated)
|
|
{
|
|
VARIANT var;
|
|
POINT pt = {0};
|
|
|
|
VariantInit(&var);
|
|
|
|
pt.x = snapToGridX;
|
|
pt.y = m_ulSnapToGridY;
|
|
|
|
V_VT(&var) = VT_BYREF;
|
|
V_BYREF(&var) = &pt;
|
|
|
|
if (SUCCEEDED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_SET_ALIGNMENT,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, &var, NULL)))
|
|
m_ulSnapToGridX = snapToGridX;
|
|
}
|
|
else
|
|
m_ulSnapToGridX = snapToGridX;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's SnapToGridX property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetSnapToGridX(LONG& snapToGridX)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
snapToGridX = m_ulSnapToGridX;
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements setting the control's SnapToGridY property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetSnapToGridY(LONG snapToGridY)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( 0 >= snapToGridY )
|
|
{
|
|
return DE_E_INVALIDARG;
|
|
}
|
|
|
|
if (m_fActivated)
|
|
{
|
|
VARIANT var;
|
|
POINT pt = {0};
|
|
|
|
VariantInit(&var);
|
|
pt.y = snapToGridY;
|
|
pt.x = m_ulSnapToGridX;
|
|
|
|
V_VT(&var) = VT_BYREF;
|
|
V_BYREF(&var) = &pt;
|
|
|
|
if (SUCCEEDED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_SET_ALIGNMENT,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, &var, NULL)))
|
|
m_ulSnapToGridY = snapToGridY;
|
|
}
|
|
else
|
|
m_ulSnapToGridY = snapToGridY;
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's SnapToGridY property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetSnapToGridY(LONG& snapToGridY)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
snapToGridY = m_ulSnapToGridY;
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements setting the control's DocumentHTML property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetDocumentHTML(BSTR bVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERTE(bVal);
|
|
|
|
if (NULL == bVal)
|
|
return E_INVALIDARG;
|
|
|
|
if (m_pCtl->IsUserMode ())
|
|
{
|
|
hr = DE_E_UNEXPECTED;
|
|
|
|
AssureActivated ();
|
|
if ( m_fActivated )
|
|
{
|
|
m_bstrBaseURL = L"";
|
|
m_bfPreserveDirtyFlagAcrossBrowseMode = FALSE;
|
|
if ( 0 == SysStringLen ( bVal ) )
|
|
{
|
|
CComBSTR bstrMT = GetInitialHTML ();
|
|
hr = LoadBSTRDeferred ( bstrMT );
|
|
}
|
|
else
|
|
{
|
|
hr = LoadBSTRDeferred ( bVal );
|
|
}
|
|
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
goto error;
|
|
}
|
|
|
|
// We've reset the contents of the control. Go back to default save mechanism.
|
|
m_pSite->SetSaveAsUnicode ( FALSE );
|
|
}
|
|
}
|
|
|
|
error:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the control's DocumentHTML property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetDocumentHTML(BSTR* bVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bfWasDirty = FALSE;
|
|
|
|
_ASSERTE(bVal);
|
|
|
|
if (NULL == bVal)
|
|
return E_INVALIDARG;
|
|
|
|
if ( m_bfIsLoading )
|
|
return DE_E_UNEXPECTED; // This is invalid while document is still loading.
|
|
|
|
if ( FAILED ( hr = m_pSite->HrIsDirtyIPersistStreamInit(bfWasDirty) ) )
|
|
{
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
bfWasDirty = FALSE; // what else can we do in a situation like this?
|
|
}
|
|
|
|
AssureActivated ();
|
|
|
|
if (m_fActivated)
|
|
{
|
|
_ASSERTE(m_pSite);
|
|
|
|
hr = m_pSite->HrSaveToBstr(bVal, m_dwFilterOutFlags );
|
|
|
|
// Preserve original dirty state.
|
|
if ( bfWasDirty )
|
|
{
|
|
SetDirtyFlag ( TRUE );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements setting the control's SourceCodePreservation property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrSetPreserveSource(BOOL bVal)
|
|
{
|
|
m_fPreserveSource = bVal;
|
|
if (m_fPreserveSource)
|
|
m_dwFilterFlags = filterAll;
|
|
else
|
|
m_dwFilterFlags = filterDTCs | filterASP;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements getting the control's SourceCodePreservation property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetPreserveSource(BOOL& bVal)
|
|
{
|
|
bVal = m_fPreserveSource;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements getting the control's read-only IsDirty property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetIsDirty(BOOL& bVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
bVal = FALSE;
|
|
|
|
AssureActivated ();
|
|
|
|
if (m_fActivated)
|
|
{
|
|
hr = m_pSite->HrIsDirtyIPersistStreamInit(bVal);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Implements getting the BaseURL property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetBaseURL ( CComBSTR& bstrBaseURL )
|
|
{
|
|
AssureActivated ();
|
|
|
|
if ( NULL == m_bstrBaseURL.m_str )
|
|
{
|
|
bstrBaseURL = L"";
|
|
}
|
|
else
|
|
{
|
|
bstrBaseURL = m_bstrBaseURL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Implements setting the BaseURL property.
|
|
// NOTE:
|
|
// The BaseURL can't be (effectively) changed if there's a <BASE HREF=XXX> tag in
|
|
// the document. Our pluggable Protocol's CombineURL is never called in this case,
|
|
// so don't misguide the user by changing the property.
|
|
//
|
|
// Pay attention to m_bfBaseURLFromBASETag before calling to set the value from
|
|
// the routine parsing the <BASE> tag!
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetBaseURL ( CComBSTR& bstrBaseURL )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERTE ( bstrBaseURL );
|
|
|
|
// Non-persisted property. Ignore if not in UserMode.
|
|
if ( m_pCtl->IsUserMode () )
|
|
{
|
|
if ( m_bfBaseURLFromBASETag )
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ( NULL == m_bstrBaseURL.m_str )
|
|
{
|
|
m_bstrBaseURL = L"";
|
|
}
|
|
|
|
// If this test succeedes, the user has done something like x.BaseURL = x.DOM.url or
|
|
// x.BaseURL = y.DOM.url.
|
|
// Response: bstrBaseURL may be the bare protocol prefix, or a prefix with a URL attached
|
|
// for example: dhtmled0:(http://www.microsoft.com).
|
|
// Strip off the prefix and parens (if they exist) and use the interior URL.
|
|
if ( 0 == _wcsnicmp ( bstrBaseURL.m_str, g_wszProtocolPrefix, wcslen ( g_wszProtocolPrefix ) ) )
|
|
{
|
|
CComBSTR bstrNew = bstrBaseURL.m_str;
|
|
|
|
// There must be a colon; it would be possibe to have a legitimate base url beginning with g_wszProtocolPrefix
|
|
WCHAR* pwcURL = wcschr ( bstrNew, (WCHAR)':' );
|
|
if ( NULL != pwcURL )
|
|
{
|
|
// Find the first open paren:
|
|
pwcURL = wcschr ( pwcURL, (WCHAR)'(' );
|
|
|
|
if ( NULL == pwcURL )
|
|
{
|
|
bstrBaseURL = L""; // No (...)? Set the Base to empty. Input must have been bare protocol ID.
|
|
}
|
|
else
|
|
{
|
|
pwcURL++; // Step past the paren.
|
|
|
|
// Strip of dhtmledXXX:( ...to... ) and set the BaseURL to what remains.
|
|
_ASSERTE ( (WCHAR)')' == pwcURL[wcslen(pwcURL)-1] );
|
|
if ( (WCHAR)')' == pwcURL[wcslen(pwcURL)-1] )
|
|
{
|
|
pwcURL[wcslen(pwcURL)-1] = (WCHAR)'\0';
|
|
bstrBaseURL = pwcURL;
|
|
}
|
|
else
|
|
{
|
|
// Unexpected: ill formed pluggable protocol id:
|
|
// starts with dhtml[n[n]]:( but does not end with ).
|
|
// If we skipped it, we would crash. Best to use an empty base URL.
|
|
bstrBaseURL = L"";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( 0 != wcscmp ( m_bstrBaseURL.m_str, bstrBaseURL.m_str ) )
|
|
{
|
|
m_bstrBaseURL = bstrBaseURL;
|
|
m_bfIsLoading = TRUE;
|
|
|
|
// Can't Exec without a command target:
|
|
if ( NULL != m_pSite->GetCommandTarget() )
|
|
{
|
|
// Reload the page, revaluating relative links.
|
|
hr = HrExecCommand(&CGID_MSHTML, IDM_REFRESH, MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Accelerator handler implementations
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Nudge accelerator handler
|
|
// Nudge the selection in the given direction by one pixle if SnaptoGrid is off, or by
|
|
// the SnaptoGridX/Y quantity if SnapToGrid is on.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrNudge(DENudgeDirection dir)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
OLECMDF cmdf = (OLECMDF) 0;
|
|
VARIANT var;
|
|
LPVARIANT pVarIn = &var;
|
|
LONG lXDelta = m_fSnapToGrid ? m_ulSnapToGridX : 1;
|
|
LONG lYDelta = m_fSnapToGrid ? m_ulSnapToGridY : 1;
|
|
|
|
if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_NUDGE_ELEMENT, &cmdf)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
|
|
{
|
|
LPPOINT lpPoint = new POINT;
|
|
|
|
if (NULL == lpPoint)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
_ASSERTE(lpPoint);
|
|
|
|
lpPoint->x = 0;
|
|
lpPoint->y = 0;
|
|
|
|
// Set increment to snap to absolute grid, not relative grid.
|
|
// Find the selections current position and set increment modulo that position.
|
|
// This assures the first nudge snaps to a grid corner.
|
|
if ( m_fSnapToGrid )
|
|
{
|
|
POINT ptSelPos;
|
|
if ( SUCCEEDED ( GetSelectionPos ( &ptSelPos ) ) )
|
|
{
|
|
LONG lXNorm = ptSelPos.x % lXDelta;
|
|
LONG lYNorm = ptSelPos.y % lYDelta;
|
|
lXDelta = lXNorm ? lXNorm : lXDelta;
|
|
lYDelta = lYNorm ? lYNorm : lYDelta;
|
|
}
|
|
}
|
|
|
|
switch(dir)
|
|
{
|
|
case deNudgeUp:
|
|
{
|
|
lpPoint->x = 0;
|
|
lpPoint->y = -lYDelta;
|
|
}
|
|
break;
|
|
|
|
case deNudgeDown:
|
|
{
|
|
lpPoint->x = 0;
|
|
lpPoint->y = lYDelta;
|
|
}
|
|
break;
|
|
|
|
case deNudgeLeft:
|
|
{
|
|
lpPoint->x = -lXDelta;
|
|
lpPoint->y = 0;
|
|
}
|
|
break;
|
|
|
|
case deNudgeRight:
|
|
{
|
|
lpPoint->x = lXDelta;
|
|
lpPoint->y = 0;
|
|
}
|
|
break;
|
|
|
|
default: // move right by default
|
|
{
|
|
lpPoint->x = lXDelta;
|
|
lpPoint->y = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
VariantInit(pVarIn);
|
|
V_VT(pVarIn) = VT_BYREF;
|
|
V_BYREF(pVarIn) = lpPoint;
|
|
|
|
if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_NUDGE_ELEMENT, MSOCMDEXECOPT_DONTPROMPTUSER, pVarIn, NULL)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
hr = S_FALSE;
|
|
|
|
cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Accelerator handler
|
|
// Toggle the absolute positioned property of the selected object
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrToggleAbsolutePositioned()
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
OLECMDF cmdf = (OLECMDF) 0;
|
|
|
|
if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_MAKE_ABSOLUTE, &cmdf)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
|
|
{
|
|
if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_MAKE_ABSOLUTE,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Accelerator handler
|
|
// Make a link out of the current selection (with UI.)
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrHyperLink()
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
OLECMDF cmdf = (OLECMDF) 0;
|
|
|
|
if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_HYPERLINK, &cmdf)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
|
|
{
|
|
if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_HYPERLINK,
|
|
MSOCMDEXECOPT_PROMPTUSER, NULL, NULL)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Accelerator handler
|
|
// Increase the indent of the current selection.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrIncreaseIndent()
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
OLECMDF cmdf = (OLECMDF) 0;
|
|
|
|
if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_INDENT, &cmdf)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
|
|
{
|
|
if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_INDENT,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Accelerator handler
|
|
// Decrease the indent of the current selection.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrDecreaseIndent()
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
OLECMDF cmdf = (OLECMDF) 0;
|
|
|
|
if (FAILED(hr = HrQueryStatus(&GUID_TriEditCommandGroup, IDM_TRIED_OUTDENT, &cmdf)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (cmdf & OLECMDF_SUPPORTED && cmdf & OLECMDF_ENABLED)
|
|
{
|
|
if (FAILED(hr = HrExecCommand(&GUID_TriEditCommandGroup, IDM_TRIED_OUTDENT,
|
|
MSOCMDEXECOPT_DONTPROMPTUSER, NULL, NULL)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Check for and handle control-specific accelerators. If none is found, call TriEdit to handle it.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrHandleAccelerator(LPMSG lpmsg)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
BOOL fControl = (0x8000 & GetKeyState(VK_CONTROL));
|
|
BOOL fShift = (0x8000 & GetKeyState(VK_SHIFT));
|
|
BOOL fAlt = (0x8000 & GetKeyState(VK_MENU));
|
|
|
|
if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_UP)
|
|
{
|
|
hr = HrNudge(deNudgeUp);
|
|
}
|
|
else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_DOWN)
|
|
{
|
|
hr = HrNudge(deNudgeDown);
|
|
}
|
|
else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_LEFT)
|
|
{
|
|
hr = HrNudge(deNudgeLeft);
|
|
}
|
|
else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_RIGHT)
|
|
{
|
|
hr = HrNudge(deNudgeRight);
|
|
}
|
|
else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == 'K' && fControl)
|
|
{
|
|
hr = HrToggleAbsolutePositioned();
|
|
}
|
|
else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == 'L' && fControl && !fAlt)
|
|
{
|
|
hr = HrHyperLink();
|
|
}
|
|
else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == 'T' && !fShift && fControl)
|
|
{
|
|
hr = HrIncreaseIndent();
|
|
}
|
|
else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == 'T' && fShift && fControl)
|
|
{
|
|
hr = HrDecreaseIndent();
|
|
}
|
|
else if (lpmsg->message == WM_KEYDOWN && lpmsg->wParam == VK_TAB && fControl)
|
|
{
|
|
// Process control-tab keys as belonging to the container; this allows the user
|
|
// to tab out of the control in non-MDI apps. MDI uses control-tab to switch
|
|
// windows, thus these apps (like VID) do not pass them to us.
|
|
IOleControlSite* piControlSite = m_pCtl->GetControlSite ();
|
|
_ASSERTE ( piControlSite );
|
|
if ( NULL != piControlSite )
|
|
{
|
|
// Eat the control key, but preserve shift to perform reverse tabbing.
|
|
// KEYMOD_SHIFT = 0x00000001, but isn't defined in any header...
|
|
DWORD dwModifiers = fShift ? 1 : 0;
|
|
|
|
hr = piControlSite->TranslateAccelerator ( lpmsg, dwModifiers );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BaseURL helper routines
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Override the default BaseURL if there is one or more <BASE HREF=...> tags
|
|
// in the document. If successful, set m_bfBaseURLFromBASETag to TRUE
|
|
// If multiple BASE tags exist, simply use the last one.
|
|
// Equivilent script: baseurl = document.all.tags("BASE")[<LAST>].href,
|
|
// where <LAST> is derived.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetBaseURLFromBaseHref ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComBSTR bstrBase;
|
|
|
|
if ( !m_bfBaseURLFromBASETag )
|
|
{
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
CComPtr<IHTMLDocument2> spHtmlDoc = NULL;
|
|
hr = HrGetDoc( &spHtmlDoc );
|
|
if ( spHtmlDoc && SUCCEEDED ( hr ) )
|
|
{
|
|
CComPtr<IHTMLElementCollection> spAll = NULL;
|
|
hr = spHtmlDoc->get_all ( &spAll );
|
|
if ( spAll && SUCCEEDED ( hr ) )
|
|
{
|
|
CComVariant varTag = L"BASE";
|
|
IDispatch* piDispTags = NULL;
|
|
|
|
hr = spAll->tags ( varTag, &piDispTags );
|
|
if ( piDispTags && SUCCEEDED ( hr ) )
|
|
{
|
|
CComQIPtr<IHTMLElementCollection, &IID_IHTMLElementCollection> spBases (piDispTags);
|
|
piDispTags->Release ();
|
|
piDispTags = NULL;
|
|
if ( spBases )
|
|
{
|
|
long cBases = 0;
|
|
hr = spBases->get_length ( &cBases );
|
|
if ( SUCCEEDED ( hr ) && ( 0 != cBases ) )
|
|
{
|
|
CComVariant varName;
|
|
varName.vt = VT_I2;
|
|
|
|
for ( varName.iVal = 0; varName.iVal < cBases; varName.iVal++ )
|
|
{
|
|
IDispatch* piDispBase = NULL;
|
|
CComVariant varValue;
|
|
|
|
hr = spBases->item ( varName, varName, &piDispBase );
|
|
if ( piDispBase && SUCCEEDED ( hr ) )
|
|
{
|
|
CComQIPtr<IHTMLElement, &IID_IHTMLElement> spElem ( piDispBase );
|
|
piDispBase->Release ();
|
|
piDispBase = NULL;
|
|
|
|
if ( spElem )
|
|
{
|
|
varValue.Clear ();
|
|
hr = spElem->getAttribute ( L"HREF", FALSE, &varValue );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = varValue.ChangeType ( VT_BSTR );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
if ( 0 != SysStringLen ( varValue.bstrVal ) )
|
|
{
|
|
bstrBase = varValue.bstrVal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( 0 != bstrBase.Length () )
|
|
{
|
|
hr = SetBaseURL ( bstrBase ); // This clears m_bfBaseURLIsDefault
|
|
m_bfBaseURLFromBASETag = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Set the m_bstrBaseURL value using m_bstrCurDocPath.
|
|
// With URLs, it may be impossible to be certain about the correct BaseURL,
|
|
// so make an intellegent guess. With files, it should be deterministic.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetBaseURLFromCurDocPath ( BOOL bfIsURL )
|
|
{
|
|
m_bfBaseURLFromBASETag = FALSE; // We're reloading: whipe this out.
|
|
if ( bfIsURL )
|
|
{
|
|
return SetBaseURLFromURL ( m_bstrCurDocPath );
|
|
}
|
|
else
|
|
{
|
|
return SetBaseURLFromFileName ( m_bstrCurDocPath );
|
|
}
|
|
}
|
|
|
|
|
|
// Given a URL_COMPONENTS with nScheme set to INTERNET_SCHEME_FILE,
|
|
// modify the path part to reflect the base path, reconstruct the URL,
|
|
// and set m_bstrBaseURL.
|
|
// Separators may be \ or /.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetBaseUrlFromFileUrlComponents ( URL_COMPONENTS & urlc )
|
|
{
|
|
TCHAR* pszPath;
|
|
BOOL bfBackSlash = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERTE ( INTERNET_SCHEME_FILE == urlc.nScheme );
|
|
_ASSERTE ( urlc.dwUrlPathLength );
|
|
if ( urlc.dwUrlPathLength <= 0)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
pszPath = new TCHAR [urlc.dwUrlPathLength + 3]; // Extra room for \0, dot, and /.
|
|
if ( NULL != pszPath )
|
|
{
|
|
TCHAR c = 0;
|
|
int iPos = 0;
|
|
|
|
// Scan backwards and modify in copy (never in BSTR, please) for beginning, '/' or '\'
|
|
memcpy ( pszPath, urlc.lpszUrlPath, ( urlc.dwUrlPathLength + 1 ) * sizeof(TCHAR) );
|
|
for ( iPos = urlc.dwUrlPathLength - 1; iPos >= 0; iPos-- )
|
|
{
|
|
c = pszPath[iPos];
|
|
pszPath[iPos] = '\0'; // Delete first, ask questions later. '\' must go.
|
|
if ( '\\' == c )
|
|
{
|
|
break;
|
|
}
|
|
if ( '/' == c )
|
|
{
|
|
bfBackSlash = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Space was reserved for an additional two characters, if needed.
|
|
// If empty, add a dot.
|
|
if ( 0 == _tcslen ( pszPath ) )
|
|
{
|
|
_tcscat ( pszPath, TEXT(".") );
|
|
}
|
|
// Add a / or \.
|
|
if ( bfBackSlash )
|
|
{
|
|
_tcscat ( pszPath, TEXT("\\") );
|
|
}
|
|
else
|
|
{
|
|
_tcscat ( pszPath, TEXT("/") );
|
|
}
|
|
|
|
urlc.lpszUrlPath = pszPath;
|
|
urlc.dwUrlPathLength = _tcslen ( pszPath );
|
|
|
|
DWORD dwLen = 0;
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
_ASSERTE ( m_pfnInternetCreateUrl );
|
|
(*m_pfnInternetCreateUrl)( &urlc, 0, NULL, &dwLen ); // Get the size required.
|
|
#else
|
|
InternetCreateUrl ( &urlc, 0, NULL, &dwLen ); // Get the size required.
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
_ASSERTE ( 0 != dwLen );
|
|
TCHAR* pszURL = new TCHAR [ dwLen + 1 ];
|
|
_ASSERTE ( pszURL );
|
|
if ( NULL != pszURL )
|
|
{
|
|
// Incredibly, on Win98, the URL is terminated with a single byte \0.
|
|
// Intializing this buffer to zero assures full termination of the string.
|
|
dwLen += 1;
|
|
memset ( pszURL, 0, sizeof(TCHAR) * dwLen );
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
if ( (*m_pfnInternetCreateUrl)( &urlc, 0, pszURL, &dwLen ) )
|
|
#else
|
|
if ( InternetCreateUrl ( &urlc, 0, pszURL, &dwLen ) )
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
{
|
|
m_bstrBaseURL = pszURL;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32 ( GetLastError () );
|
|
}
|
|
delete [] pszURL;
|
|
}
|
|
|
|
delete [] pszPath;
|
|
}
|
|
else
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// The most complicated scenario for "guessing" at the base URL.
|
|
// URLs like http://www.x.com/stuff could be either a file or a directory;
|
|
// a default page might actually be loaded. We guess based on whether or
|
|
// not the last item in the path contains a period. If so, we eliminate it.
|
|
// We make sure the path ends with a '/'.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetBaseUrlFromUrlComponents ( URL_COMPONENTS & urlc )
|
|
{
|
|
_ASSERTE ( INTERNET_SCHEME_FILE != urlc.nScheme );
|
|
|
|
BOOL bfPeriodIncluded = FALSE;
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( 0 == urlc.dwSchemeLength )
|
|
{
|
|
m_bstrBaseURL = L"";
|
|
return S_FALSE;
|
|
}
|
|
|
|
// Scan backwards over path for beginning, '/'
|
|
TCHAR c = 0;
|
|
int iPos = 0;
|
|
|
|
for ( iPos = urlc.dwUrlPathLength - 1; iPos >= 0; iPos-- )
|
|
{
|
|
c = urlc.lpszUrlPath[iPos];
|
|
if ( '/' == c )
|
|
{
|
|
break;
|
|
}
|
|
if ( '.' == c )
|
|
{
|
|
bfPeriodIncluded = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( bfPeriodIncluded )
|
|
{
|
|
if ( 0 > iPos ) iPos = 0;
|
|
urlc.lpszUrlPath[iPos] = '\0'; // Truncate at the '/', or beginning
|
|
urlc.dwUrlPathLength = _tcslen ( urlc.lpszUrlPath );
|
|
}
|
|
|
|
// Recreate the URL:
|
|
DWORD dwLen = 0;
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
_ASSERTE ( m_pfnInternetCreateUrl );
|
|
(*m_pfnInternetCreateUrl)( &urlc, 0, NULL, &dwLen ); // Get the size required.
|
|
#else
|
|
InternetCreateUrl ( &urlc, 0, NULL, &dwLen ); // Get the size required.
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
_ASSERTE ( 0 != dwLen );
|
|
TCHAR* pszURL = new TCHAR [ dwLen + 1 ];
|
|
_ASSERTE ( pszURL );
|
|
if ( NULL != pszURL )
|
|
{
|
|
dwLen += 1;
|
|
memset ( pszURL, 0, sizeof(TCHAR) * dwLen );
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
if ( (*m_pfnInternetCreateUrl)( &urlc, 0, pszURL, &dwLen ) )
|
|
#else
|
|
if ( InternetCreateUrl ( &urlc, 0, pszURL, &dwLen ) )
|
|
#endif
|
|
{
|
|
m_bstrBaseURL = pszURL;
|
|
|
|
// Append a '/' if needed.
|
|
WCHAR wc = m_bstrBaseURL.m_str[m_bstrBaseURL.Length () - 1];
|
|
if ( ( WCHAR('/') != wc ) && ( NULL != urlc.lpszHostName ) ) // hostname: special case for user pluggable protocols
|
|
{
|
|
m_bstrBaseURL += L"/";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32 ( GetLastError () );
|
|
}
|
|
delete [] pszURL;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Crack the URL, determine if it's a file scheme or other, and call the appropriate handler.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetBaseURLFromURL ( const CComBSTR& bstrURL )
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr = S_OK;
|
|
URL_COMPONENTS urlc;
|
|
TCHAR *ptszScheme = NULL;
|
|
TCHAR *ptszHostName = NULL;
|
|
TCHAR *ptszUrlPath = NULL;
|
|
BOOL fSuccess = FALSE;
|
|
TCHAR* tszURL = NULL;
|
|
|
|
_ASSERTE ( 0 != bstrURL.Length () );
|
|
|
|
tszURL = OLE2T ( bstrURL );
|
|
_ASSERTE ( tszURL );
|
|
if ( NULL == tszURL )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
memset ( &urlc, 0, sizeof ( urlc ) );
|
|
urlc.dwStructSize = sizeof ( urlc );
|
|
urlc.dwSchemeLength = 1;
|
|
urlc.dwHostNameLength = 1;
|
|
urlc.dwUrlPathLength = 1;
|
|
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
_ASSERTE ( m_pfnInternetCrackUrl );
|
|
fSuccess = (*m_pfnInternetCrackUrl)( tszURL, 0, 0, &urlc );
|
|
#else
|
|
fSuccess = InternetCrackUrl ( tszURL, 0, 0, &urlc );
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
if ( !fSuccess )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if ( 0 != urlc.dwSchemeLength )
|
|
{
|
|
urlc.dwSchemeLength++;
|
|
ptszScheme = new TCHAR[urlc.dwSchemeLength];
|
|
urlc.lpszScheme = ptszScheme;
|
|
if ( NULL == ptszScheme )
|
|
goto ONERROR;
|
|
}
|
|
if ( 0 != urlc.dwHostNameLength )
|
|
{
|
|
urlc.dwHostNameLength++;
|
|
ptszHostName = new TCHAR[urlc.dwHostNameLength];
|
|
urlc.lpszHostName = ptszHostName;
|
|
if ( NULL == ptszHostName )
|
|
goto ONERROR;
|
|
}
|
|
if ( 0 != urlc.dwUrlPathLength )
|
|
{
|
|
urlc.dwUrlPathLength++;
|
|
ptszUrlPath = new TCHAR[urlc.dwUrlPathLength];
|
|
urlc.lpszUrlPath = ptszUrlPath;
|
|
if ( NULL == ptszUrlPath )
|
|
goto ONERROR;
|
|
}
|
|
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
fSuccess = (*m_pfnInternetCrackUrl)( tszURL, 0, 0, &urlc );
|
|
#else
|
|
fSuccess = InternetCrackUrl ( tszURL, 0, 0, &urlc );
|
|
#endif
|
|
|
|
if ( fSuccess )
|
|
{
|
|
if ( INTERNET_SCHEME_FILE == urlc.nScheme )
|
|
{
|
|
hr = SetBaseUrlFromFileUrlComponents ( urlc );
|
|
}
|
|
else
|
|
{
|
|
hr = SetBaseUrlFromUrlComponents ( urlc );
|
|
}
|
|
}
|
|
|
|
ONERROR:
|
|
if ( ptszScheme )
|
|
delete [] ptszScheme;
|
|
if ( ptszHostName )
|
|
delete [] ptszHostName;
|
|
if ( ptszUrlPath )
|
|
delete [] ptszUrlPath;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Given a UNC file name, set the m_bstrBaseURL member variable.
|
|
// if bstrFName is empty, set m_bstrBaseURL to empty.
|
|
// Else, scan backward to the first "\" or the beginning of the string.
|
|
// Truncate the string at this point. If the resultant string is empty,
|
|
// add ".". Then, add "\".
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetBaseURLFromFileName ( const CComBSTR& bstrFName )
|
|
{
|
|
if ( 0 == bstrFName.Length () )
|
|
{
|
|
m_bstrBaseURL = L"";
|
|
}
|
|
else
|
|
{
|
|
WCHAR* pwzstr = new WCHAR[bstrFName.Length () + 1];
|
|
_ASSERTE ( pwzstr );
|
|
if ( NULL != pwzstr )
|
|
{
|
|
WCHAR wc = 0;
|
|
int iPos = 0;
|
|
|
|
// Scan backwards and modify in copy (never in BSTR, please) for beginning or '\'
|
|
memcpy ( pwzstr, bstrFName.m_str, sizeof(WCHAR) * (bstrFName.Length () + 1) );
|
|
for ( iPos = wcslen ( pwzstr ) - 1; iPos >= 0; iPos-- )
|
|
{
|
|
wc = pwzstr[iPos];
|
|
pwzstr[iPos] = WCHAR('\0'); // Delete first, ask questions later. '\' must go.
|
|
if ( WCHAR('\\') == wc )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
m_bstrBaseURL = pwzstr;
|
|
delete [] pwzstr;
|
|
|
|
// If empty, add a '.'
|
|
if ( 0 == m_bstrBaseURL.Length () )
|
|
{
|
|
m_bstrBaseURL += L".";
|
|
}
|
|
m_bstrBaseURL += L"\\";
|
|
}
|
|
else
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Security oriented routines
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// This is a critical security issue:
|
|
// The pluggable protocol's ParseURL is called with PARSE_SECURITY_URL in the SFS control.
|
|
// If the BaseURL is empty, and if we're hosted in Trident, we should return the
|
|
// URL of the hosting page.
|
|
// If there is no Trident host, say we're hosted in VB, return the bootdrive + : + /.
|
|
// Bootdrive is not always C.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetSecurityURL (CComBSTR& bstrSecurityURL )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IOleClientSite *piClientSiteUnreffed = NULL;
|
|
|
|
bstrSecurityURL = L"";
|
|
|
|
piClientSiteUnreffed = m_pCtl->m_spClientSite;
|
|
if ( NULL != piClientSiteUnreffed )
|
|
{
|
|
CComPtr<IOleContainer> spContainer = NULL;
|
|
hr = piClientSiteUnreffed->GetContainer ( &spContainer );
|
|
if ( SUCCEEDED ( hr ) && spContainer )
|
|
{
|
|
CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spHostDoc ( spContainer );
|
|
if ( spHostDoc )
|
|
{
|
|
CComPtr<IHTMLLocation> spHostLoc = NULL;
|
|
|
|
|
|
spHostDoc->get_location ( &spHostLoc );
|
|
if ( spHostLoc )
|
|
{
|
|
BSTR bsOut;
|
|
hr = spHostLoc->get_href ( &bsOut );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
bstrSecurityURL.Empty ();
|
|
bstrSecurityURL.Attach ( bsOut );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If we are not hosted in Trident, use local machine access:
|
|
TCHAR tszDrive[4];
|
|
GetModuleFileName ( _Module.m_hInst, tszDrive, 3 ); // Get X:\.
|
|
_ASSERTE ( TCHAR(':') == tszDrive[1] );
|
|
_ASSERTE ( TCHAR('\\') == tszDrive[2] );
|
|
bstrSecurityURL = tszDrive;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Pluggable protocol oriented routines
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Register our pluggable protocol handler so dhtmledN[N...] is loaded by our code.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::RegisterPluggableProtocol()
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Get InternetSession
|
|
|
|
CComPtr<IInternetSession> srpSession;
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
_ASSERTE ( m_pfnCoInternetGetSession );
|
|
hr = (*m_pfnCoInternetGetSession)(0, &srpSession, 0);
|
|
#else
|
|
hr = CoInternetGetSession (0, &srpSession, 0);
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if(m_pProtInfo == NULL)
|
|
{
|
|
hr = CComObject<CDHTMLEdProtocolInfo>::CreateInstance(&m_pProtInfo);
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// CreateInstance - doesnt AddRef
|
|
m_pProtInfo->GetUnknown()->AddRef();
|
|
}
|
|
|
|
hr = srpSession->RegisterNameSpace(
|
|
static_cast<IClassFactory*>(m_pProtInfo),
|
|
CLSID_DHTMLEdProtocol,
|
|
m_wszProtocol,
|
|
0,
|
|
NULL,
|
|
0);
|
|
|
|
if ( FAILED ( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
CComQIPtr <IProtocolInfoConnector, &IID_IProtocolInfoConnector> piPic ( m_pProtInfo );
|
|
_ASSERTE ( piPic );
|
|
piPic->SetProxyFrame ( (SIZE_T*)this );
|
|
|
|
ATLTRACE( _T("CProxyFrame::Registered ProtocolInfo\n"));
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
// Unregister the pluggable protocol handler installed in RegisterPluggableProtocol
|
|
//
|
|
HRESULT
|
|
CProxyFrame::UnRegisterPluggableProtocol()
|
|
{
|
|
if(m_pProtInfo == NULL)
|
|
return E_UNEXPECTED;
|
|
|
|
// Get InternetSession
|
|
|
|
HRESULT hr;
|
|
CComPtr<IInternetSession> srpSession;
|
|
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
_ASSERTE ( m_pfnCoInternetGetSession );
|
|
hr = (*m_pfnCoInternetGetSession)(0, &srpSession, 0);
|
|
#else
|
|
hr = CoInternetGetSession (0, &srpSession, 0);
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// UnRegister Protocol
|
|
|
|
srpSession->UnregisterNameSpace(
|
|
static_cast<IClassFactory*>(m_pProtInfo),
|
|
m_wszProtocol);
|
|
|
|
}
|
|
|
|
m_pProtInfo->GetUnknown()->Release();
|
|
m_pProtInfo = NULL;
|
|
|
|
ATLTRACE(_T("CProxyFrame::UnRegistered ProtocolInfo\n"));
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
// Workhorse routine that actually performs the loading of the control, including filtering.
|
|
// ParseAndBind calls this to retrieve the data to be displayed in the control.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetFilteredStream ( IStream** ppStream )
|
|
{
|
|
USES_CONVERSION;
|
|
HRESULT hr = S_OK;
|
|
LPTSTR pFileName = NULL;
|
|
CComPtr<IStream> piStream;
|
|
BOOL bfLoadingFromBSTR = ( 0 != m_bstrLoadText.Length () );
|
|
|
|
*ppStream = NULL;
|
|
m_bfReloadAttempted = TRUE;
|
|
|
|
if ( !bfLoadingFromBSTR )
|
|
{
|
|
_ASSERTE(m_bstrCurDocPath);
|
|
|
|
pFileName = OLE2T(m_bstrCurDocPath);
|
|
|
|
_ASSERTE(pFileName);
|
|
|
|
if (NULL == pFileName)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if ( bfLoadingFromBSTR )
|
|
{
|
|
hr = m_pSite->HrBstrToStream(m_bstrLoadText, &piStream);
|
|
}
|
|
else if ( m_bfIsURL )
|
|
{
|
|
hr = m_pSite->HrURLToStream(pFileName, &piStream);
|
|
}
|
|
else
|
|
{
|
|
hr = m_pSite->HrFileToStream(pFileName, &piStream);
|
|
}
|
|
|
|
if (FAILED( hr ))
|
|
{
|
|
m_bstrCurDocPath.Empty ();
|
|
m_bstrBaseURL.Empty ();
|
|
|
|
// Get TriEdit into a reasonable state by loading an empty document
|
|
// If we reinstanced successfully, this should never fail
|
|
// Also, this will make ignoring the above assert benign
|
|
if (FAILED(m_pSite->HrBstrToStream(m_bstrInitialDoc, ppStream)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if ( m_vbBrowseMode )
|
|
{
|
|
piStream.p->AddRef ();
|
|
*ppStream = piStream;
|
|
}
|
|
else
|
|
{
|
|
hr = m_pSite->HrFilter(TRUE, piStream, ppStream, m_dwFilterFlags);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
m_pSite->HrBstrToStream(m_bstrInitialDoc, ppStream);
|
|
}
|
|
else
|
|
{
|
|
m_dwFilterOutFlags = m_dwFilterFlags;
|
|
}
|
|
}
|
|
|
|
// Store the result to return from the (indirectly) called routine,
|
|
// but don't return an error to ParseAndBind!
|
|
if ( FAILED(hr) && ( ! bfLoadingFromBSTR ) )
|
|
{
|
|
m_hrDeferredLoadError = hr; // Stash this away, we'll pic it up in LoadDocument
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Document event handling routines
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
HRESULT
|
|
CProxyFrame::OnTriEditEvent ( const GUID& iidEventInterface, DISPID dispid )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( DIID_HTMLDocumentEvents == iidEventInterface )
|
|
{
|
|
switch ( dispid )
|
|
{
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS:
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN:
|
|
if ( DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN == dispid )
|
|
{
|
|
m_pCtl->Fire_onmousedown();
|
|
}
|
|
else if ( DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS == dispid )
|
|
{
|
|
m_pCtl->Fire_onkeypress();
|
|
}
|
|
|
|
// Make the control UIActive if it was clicked in. Since the DocObject swallows the clicks,
|
|
// the control isn't activated automatically.
|
|
// Not needed in browse mode.
|
|
if ( !m_pCtl->m_bUIActive && ! m_vbBrowseMode )
|
|
{
|
|
m_pCtl->DoVerbUIActivate ( NULL, NULL );
|
|
if ( m_hWndObj != NULL )
|
|
{
|
|
::SetFocus( m_hWndObj );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE:
|
|
m_pCtl->Fire_onmousemove();
|
|
break;
|
|
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP:
|
|
m_pCtl->Fire_onmouseup();
|
|
// onclick is not delivered in edit mode. First one lost in broswe mode.
|
|
m_pCtl->Fire_onclick();
|
|
break;
|
|
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT:
|
|
m_pCtl->Fire_onmouseout();
|
|
break;
|
|
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER:
|
|
m_pCtl->Fire_onmouseover();
|
|
break;
|
|
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONCLICK:
|
|
// We do not fire the onclick event in response.
|
|
// It is only delivered in browse mode, and in addition,
|
|
// the first onclick is lost. We fire on onmouseup.
|
|
//m_pCtl->Fire_onclick();
|
|
|
|
// The addition of the DesignMode property, in addition to <BASE TARGET="_top">
|
|
// makes links exploitable for cross-zone access in the SFS control.
|
|
// We must disable clicks (user and script) in the SFS control to prevent this.
|
|
if ( m_pCtl->IsSafeForScripting ())
|
|
{
|
|
CComPtr<IHTMLDocument2> spHtmlDoc;
|
|
hr = HrGetDoc ( &spHtmlDoc );
|
|
if ( SUCCEEDED ( hr ) && spHtmlDoc )
|
|
{
|
|
CComPtr<IHTMLWindow2> spWindow;
|
|
|
|
hr = spHtmlDoc->get_parentWindow ( &spWindow );
|
|
if ( SUCCEEDED ( hr ) && spWindow )
|
|
{
|
|
CComPtr<IHTMLEventObj> spEvt;
|
|
hr = spWindow->get_event ( &spEvt );
|
|
if ( SUCCEEDED ( hr ) && spEvt )
|
|
{
|
|
CComVariant varFalse(VARIANT_FALSE);
|
|
|
|
spEvt->put_cancelBubble ( VARIANT_TRUE );
|
|
spEvt->put_returnValue ( varFalse );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK:
|
|
m_pCtl->Fire_ondblclick();
|
|
break;
|
|
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN:
|
|
m_pCtl->Fire_onkeydown();
|
|
break;
|
|
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONKEYUP:
|
|
m_pCtl->Fire_onkeyup();
|
|
break;
|
|
|
|
case DISPID_HTMLDOCUMENTEVENTS_ONREADYSTATECHANGE:
|
|
m_pCtl->Fire_onreadystatechange();
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE ( TRUE );
|
|
break;
|
|
}
|
|
}
|
|
else if ( DIID_HTMLWindowEvents == iidEventInterface )
|
|
{
|
|
// I expected to get these, but I'm not...
|
|
switch ( dispid )
|
|
{
|
|
case DISPID_HTMLWINDOWEVENTS_ONLOAD:
|
|
case DISPID_HTMLWINDOWEVENTS_ONUNLOAD:
|
|
case DISPID_HTMLWINDOWEVENTS_ONHELP:
|
|
case DISPID_HTMLWINDOWEVENTS_ONFOCUS:
|
|
case DISPID_HTMLWINDOWEVENTS_ONBLUR:
|
|
case DISPID_HTMLWINDOWEVENTS_ONERROR:
|
|
case DISPID_HTMLWINDOWEVENTS_ONRESIZE:
|
|
case DISPID_HTMLWINDOWEVENTS_ONSCROLL:
|
|
case DISPID_HTMLWINDOWEVENTS_ONBEFOREUNLOAD:
|
|
hr = S_OK;
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE ( TRUE );
|
|
break;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Dynamic loading routines, used in 4.0 versions
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
// Load Urlmon and Wininet and get the proc addresses of every routine we use.
|
|
// We must be able to register the control, even if these libraries are not installed.
|
|
// NOTE:
|
|
// This routine loads ANSI versions. Needs addaptation for UNICODE.
|
|
//
|
|
BOOL CProxyFrame::DynLoadLibraries ()
|
|
{
|
|
m_hUlrMon = LoadLibrary ( TEXT("URLMON.DLL") );
|
|
m_hWinINet = LoadLibrary ( TEXT("WININET.DLL") );
|
|
if ( ( NULL == m_hUlrMon ) || ( NULL == m_hWinINet ) )
|
|
{
|
|
DynUnloadLibraries ();
|
|
return FALSE;
|
|
}
|
|
|
|
m_pfnCoInternetCombineUrl = (PFNCoInternetCombineUrl)GetProcAddress (
|
|
m_hUlrMon, "CoInternetCombineUrl" );
|
|
_ASSERTE ( m_pfnCoInternetCombineUrl );
|
|
m_pfnCoInternetParseUrl = (PFNCoInternetParseUrl)GetProcAddress (
|
|
m_hUlrMon, "CoInternetParseUrl" );
|
|
_ASSERTE ( m_pfnCoInternetParseUrl );
|
|
m_pfnCreateURLMoniker = (PFNCreateURLMoniker)GetProcAddress (
|
|
m_hUlrMon, "CreateURLMoniker" );
|
|
_ASSERTE ( m_pfnCreateURLMoniker );
|
|
m_pfnCoInternetGetSession = (PFNCoInternetGetSession)GetProcAddress (
|
|
m_hUlrMon, "CoInternetGetSession" );
|
|
_ASSERTE ( m_pfnCoInternetGetSession );
|
|
m_pfnURLOpenBlockingStream = (PFNURLOpenBlockingStream)GetProcAddress (
|
|
m_hUlrMon, "URLOpenBlockingStreamA" );
|
|
_ASSERTE ( m_pfnURLOpenBlockingStream );
|
|
|
|
m_pfnDeleteUrlCacheEntry = (PFNDeleteUrlCacheEntry)GetProcAddress (
|
|
m_hWinINet, "DeleteUrlCacheEntry" );
|
|
_ASSERTE ( m_pfnDeleteUrlCacheEntry );
|
|
m_pfnInternetCreateUrl = (PFNInternetCreateUrl)GetProcAddress (
|
|
m_hWinINet, "InternetCreateUrlA" );
|
|
_ASSERTE ( m_pfnInternetCreateUrl );
|
|
m_pfnInternetCrackUrl = (PFNInternetCrackURL)GetProcAddress (
|
|
m_hWinINet, "InternetCrackUrlA" );
|
|
_ASSERTE ( m_pfnInternetCrackUrl );
|
|
|
|
return ( m_pfnCoInternetCombineUrl && m_pfnCoInternetParseUrl && m_pfnCreateURLMoniker &&
|
|
m_pfnCoInternetGetSession && m_pfnURLOpenBlockingStream && m_pfnDeleteUrlCacheEntry &&
|
|
m_pfnInternetCreateUrl && m_pfnInternetCrackUrl );
|
|
}
|
|
|
|
|
|
// Release the libraries loaded by DynLoadLibraries
|
|
//
|
|
void CProxyFrame::DynUnloadLibraries ()
|
|
{
|
|
if ( NULL != m_hUlrMon )
|
|
{
|
|
FreeLibrary ( m_hUlrMon );
|
|
m_hUlrMon = NULL;
|
|
}
|
|
if ( NULL != m_hWinINet )
|
|
{
|
|
FreeLibrary ( m_hWinINet );
|
|
m_hWinINet = NULL;
|
|
}
|
|
|
|
m_pfnCoInternetCombineUrl = NULL;
|
|
m_pfnCoInternetParseUrl = NULL;
|
|
m_pfnCreateURLMoniker = NULL;
|
|
m_pfnCoInternetGetSession = NULL;
|
|
m_pfnURLOpenBlockingStream = NULL;
|
|
|
|
m_pfnDeleteUrlCacheEntry = NULL;
|
|
m_pfnInternetCreateUrl = NULL;
|
|
m_pfnInternetCrackUrl = NULL;
|
|
}
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Utility routines
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Return the IHTMLDocument2 pointer from the hosted doc.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetDoc(IHTMLDocument2 **ppDoc)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IUnknown* lpUnk = m_pSite->GetObjectUnknown();
|
|
|
|
if (FALSE == m_fActivated)
|
|
return DE_E_UNEXPECTED;
|
|
|
|
_ASSERTE(ppDoc);
|
|
|
|
if (NULL == ppDoc)
|
|
return DE_E_INVALIDARG;
|
|
|
|
_ASSERTE(lpUnk);
|
|
|
|
if ( m_bfIsLoading )
|
|
return DE_E_UNEXPECTED; // This is invalid while document is still loading.
|
|
|
|
if (lpUnk != NULL)
|
|
{
|
|
// Request the "document" object from the MSHTML
|
|
*ppDoc = NULL;
|
|
hr = lpUnk->QueryInterface(IID_IHTMLDocument2, (void **)ppDoc);
|
|
}
|
|
|
|
_ASSERTE(SUCCEEDED(hr)); // this should always succeed
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Helper routine to set any Boolean Trident property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrTridentSetPropBool(ULONG cmd, BOOL bVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
VARIANT varIn;
|
|
|
|
VariantInit(&varIn);
|
|
V_VT(&varIn) = VT_BOOL;
|
|
|
|
#pragma warning(disable: 4310) // cast truncates constant value
|
|
bVal ? V_BOOL(&varIn) = VARIANT_TRUE : V_BOOL(&varIn) = VARIANT_FALSE;
|
|
#pragma warning(default: 4310) // cast truncates constant value
|
|
|
|
hr = HrExecCommand(&CGID_MSHTML, cmd, MSOCMDEXECOPT_DONTPROMPTUSER, &varIn, NULL);
|
|
|
|
// this should always succeed since all props
|
|
// should be set in correct phases of Trident creation
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Helper routine to get any Boolean Trident property
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrTridentGetPropBool(ULONG cmd, BOOL& bVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
OLECMDF cmdf = (OLECMDF) 0;
|
|
|
|
if (SUCCEEDED(HrQueryStatus(&CGID_MSHTML, cmd, &cmdf)))
|
|
{
|
|
bVal = (cmdf & OLECMDF_ENABLED) == OLECMDF_ENABLED ? TRUE : FALSE;
|
|
}
|
|
|
|
// this should always succeed since all props
|
|
// should be set in correct phases of Trident creation
|
|
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Store the BSTR so LoadFilteredStream can access it, and load a URL with our protocol
|
|
// to kick off the load/resolve/display through the pluggable protocol handler.
|
|
//
|
|
// Clear the BaseURL, and mark the control "Loading..."
|
|
//
|
|
HRESULT
|
|
CProxyFrame::LoadBSTRDeferred ( BSTR bVal )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
_ASSERTE ( m_pUnkTriEdit );
|
|
|
|
m_bstrLoadText = bVal;
|
|
|
|
CComPtr<IMoniker> srpMoniker;
|
|
CComPtr<IBindCtx> srpBindCtx;
|
|
CComQIPtr<IPersistMoniker, &IID_IPersistMoniker> srpPM (m_pUnkTriEdit);
|
|
_ASSERTE ( srpPM );
|
|
|
|
if ( srpPM )
|
|
{
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
_ASSERTE ( m_pfnCreateURLMoniker );
|
|
hr = (*m_pfnCreateURLMoniker)( NULL, m_wszProtocolPrefix, &srpMoniker );
|
|
#else
|
|
hr = CreateURLMoniker ( NULL, m_wszProtocolPrefix, &srpMoniker );
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
|
|
_ASSERTE ( SUCCEEDED( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = ::CreateBindCtx(NULL, &srpBindCtx);
|
|
_ASSERTE ( SUCCEEDED( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
m_bfIsLoading = TRUE;
|
|
m_bfBaseURLFromBASETag = FALSE;
|
|
|
|
hr = srpPM->Load(FALSE, srpMoniker, srpBindCtx, STGM_READ);
|
|
|
|
_ASSERTE ( SUCCEEDED( hr ) );
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Set the document stream's dirty flag
|
|
//
|
|
HRESULT
|
|
CProxyFrame::SetDirtyFlag ( BOOL bfMakeDirty )
|
|
{
|
|
CComVariant varDirty;
|
|
|
|
varDirty = bfMakeDirty ? true : false;
|
|
|
|
return HrExecCommand(&CGID_MSHTML, IDM_SETDIRTY, MSOCMDEXECOPT_DONTPROMPTUSER, &varDirty, NULL);
|
|
}
|
|
|
|
|
|
// properties that can be set only after TriEdit is in running state
|
|
HRESULT
|
|
CProxyFrame::HrSetRuntimeProperties()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (FAILED(hr = HrSetPropActivateControls(m_fActivateControls)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
if (FAILED(hr = HrSetPropActivateApplets(m_fActivateApplets)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
if (FAILED(hr = HrSetPropActivateDTCs(m_fActivateDTCs)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
// toggle properties
|
|
|
|
if (FAILED(hr = HrSetPropShowAllTags(m_fShowAllTags)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
|
|
if (FAILED(hr = HrSetPropShowBorders(m_fShowBorders)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CProxyFrame::HrGetCurrentDocumentPath(BSTR* bVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_ASSERTE(bVal);
|
|
|
|
if (NULL == bVal)
|
|
return E_INVALIDARG;
|
|
|
|
*bVal = m_bstrCurDocPath.Copy ();
|
|
return hr;
|
|
}
|
|
|
|
|
|
// properties that can only be set after UIActivation
|
|
HRESULT
|
|
CProxyFrame::HrSetDocLoadedProperties()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bGoodUndoBehavior = TRUE;
|
|
|
|
bGoodUndoBehavior = TRUE;
|
|
if (FAILED(HrTridentGetPropBool(IDM_GOOD_UNDO_BEHAVIOR, bGoodUndoBehavior)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
if (FAILED(hr = HrSetAbsoluteDropMode(m_fAbsoluteDropMode)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
if (FAILED(hr = HrSetSnapToGridX(m_ulSnapToGridX)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
if (FAILED(hr = HrSetSnapToGridY(m_ulSnapToGridY)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
if (FAILED(hr = HrSetSnapToGrid(m_fSnapToGrid)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// HrExecInsertTable helper. Extract the safearrys
|
|
//
|
|
HRESULT
|
|
CProxyFrame::HrGetTableSafeArray(IDEInsertTableParam* pTable, LPVARIANT pVarIn)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
UINT i = 0;
|
|
SAFEARRAY FAR* psa = NULL;
|
|
SAFEARRAYBOUND rgsabound[1] = {0};
|
|
LONG ix[1] = {0};
|
|
VARIANT varElem;
|
|
LONG nNumRows = 0;
|
|
LONG nNumCols = 0;
|
|
BSTR bstrTableAttrs = NULL;
|
|
BSTR bstrCellAttrs = NULL;
|
|
BSTR bstrCaption = NULL;
|
|
|
|
_ASSERTE(pTable);
|
|
|
|
if (FAILED(hr = pTable->get_NumRows(&nNumRows)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
if (FAILED(hr = pTable->get_NumCols(&nNumCols)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
|
|
if (FAILED(hr = pTable->get_TableAttrs(&bstrTableAttrs)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
_ASSERTE(bstrTableAttrs);
|
|
|
|
if (FAILED(hr = pTable->get_CellAttrs(&bstrCellAttrs)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
_ASSERTE(bstrCellAttrs);
|
|
|
|
if (FAILED(hr = pTable->get_Caption(&bstrCaption)))
|
|
{
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
return hr;
|
|
}
|
|
_ASSERTE(bstrCaption);
|
|
|
|
rgsabound[0].lLbound = 0;
|
|
rgsabound[0].cElements = 5;
|
|
|
|
psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
|
|
_ASSERTE(psa);
|
|
|
|
if(NULL == psa)
|
|
return E_OUTOFMEMORY;
|
|
|
|
VariantInit(pVarIn);
|
|
V_VT(pVarIn) = VT_ARRAY;
|
|
V_ARRAY(pVarIn) = psa;
|
|
|
|
i=0;
|
|
|
|
// elmement 1: number of rows
|
|
ix[0] = i;
|
|
VariantInit(&varElem);
|
|
V_VT(&varElem) = VT_I4;
|
|
V_I4(&varElem) = nNumRows;
|
|
hr = SafeArrayPutElement(psa, ix, &varElem);
|
|
VariantClear(&varElem);
|
|
++i;
|
|
|
|
// elmement 2: number of columns
|
|
ix[0] = i;
|
|
VariantInit(&varElem);
|
|
V_VT(&varElem) = VT_I4;
|
|
V_I4(&varElem) = nNumCols;
|
|
hr = SafeArrayPutElement(psa, ix, &varElem);
|
|
VariantClear(&varElem);
|
|
++i;
|
|
|
|
// elmement 3: table tag attributes
|
|
ix[0] = i;
|
|
VariantInit(&varElem);
|
|
V_VT(&varElem) = VT_BSTR;
|
|
V_BSTR(&varElem) = bstrTableAttrs;
|
|
hr = SafeArrayPutElement(psa, ix, &varElem);
|
|
VariantClear(&varElem);
|
|
++i;
|
|
|
|
// elmement 4: cell attributes
|
|
ix[0] = i;
|
|
VariantInit(&varElem);
|
|
V_VT(&varElem) = VT_BSTR;
|
|
V_BSTR(&varElem) = bstrCellAttrs;
|
|
hr = SafeArrayPutElement(psa, ix, &varElem);
|
|
VariantClear(&varElem);
|
|
++i;
|
|
|
|
// elmement 5: table caption
|
|
// VK bug 15857: don't include caption if it's empty.
|
|
if ( 0 != SysStringLen ( bstrCaption ) )
|
|
{
|
|
ix[0] = i;
|
|
VariantInit(&varElem);
|
|
V_VT(&varElem) = VT_BSTR;
|
|
V_BSTR(&varElem) = bstrCaption;
|
|
hr = SafeArrayPutElement(psa, ix, &varElem);
|
|
VariantClear(&varElem);
|
|
++i;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Determine which object is selected, and return its position
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetSelectionPos ( LPPOINT lpWhere )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
CComPtr<IHTMLDocument2> spHtmlDoc = NULL;
|
|
CComPtr<IHTMLSelectionObject> spSelectionObj = NULL;
|
|
CComPtr<IDispatch> spRangeDisp = NULL;
|
|
CComPtr<IHTMLElement> spElement = NULL;
|
|
|
|
lpWhere->x = 0;
|
|
lpWhere->y = 0;
|
|
|
|
hr = HrGetDoc ( &spHtmlDoc );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = spHtmlDoc->get_selection ( &spSelectionObj );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = spSelectionObj->createRange ( &spRangeDisp );
|
|
if (SUCCEEDED ( hr ) )
|
|
{
|
|
CComQIPtr<IHTMLTxtRange, &IID_IHTMLTxtRange> spTextRange ( spRangeDisp );
|
|
if ( spTextRange )
|
|
{
|
|
hr = spTextRange->parentElement(&spElement);
|
|
}
|
|
else
|
|
{
|
|
CComQIPtr<IHTMLControlRange, &IID_IHTMLControlRange> spControlRange ( spRangeDisp );
|
|
if ( spControlRange )
|
|
{
|
|
hr = spControlRange->commonParentElement(&spElement);
|
|
}
|
|
}
|
|
if ( spElement )
|
|
{
|
|
CComPtr<IHTMLStyle> spStyle = NULL;
|
|
hr = spElement->get_style ( &spStyle );
|
|
if ( spStyle )
|
|
{
|
|
spStyle->get_pixelTop ( &( lpWhere->y ) );
|
|
spStyle->get_pixelLeft ( &( lpWhere->x ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// If the current document is loaded from a URL, return the empty string.
|
|
// If it's loaded from a file, strip the path part off and return just the file name.
|
|
// Return S_FALSE for a URL or no file name. S_OK if a file name is supplied.
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetCurDocNameWOPath ( CComBSTR& bstrDocName )
|
|
{
|
|
bstrDocName = L"";
|
|
|
|
if ( m_bfIsURL )
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
if ( 0 == m_bstrCurDocPath.Length () )
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
bstrDocName = m_bstrCurDocPath;
|
|
|
|
// Truncate at first backslash:
|
|
_wcsrev ( bstrDocName );
|
|
wcstok ( bstrDocName, OLESTR( "\\" ) );
|
|
_wcsrev ( bstrDocName );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Used by ShowContextMenu to properly offset the position of the click
|
|
//
|
|
HRESULT
|
|
CProxyFrame::GetScrollPos ( LPPOINT lpPos )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
CComPtr<IHTMLDocument2> spHtmlDoc = NULL;
|
|
CComPtr<IHTMLElement> spBodyElem = NULL;
|
|
|
|
_ASSERTE ( lpPos );
|
|
|
|
hr = HrGetDoc ( &spHtmlDoc );
|
|
|
|
// It's possible that the user clicked while the doc was still loading.
|
|
// If so, just return 0, 0.
|
|
if ( DE_E_UNEXPECTED == hr )
|
|
{
|
|
lpPos->x = lpPos->y = 0;
|
|
return S_FALSE;
|
|
}
|
|
|
|
_ASSERTE ( spHtmlDoc );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = spHtmlDoc->get_body ( &spBodyElem );
|
|
_ASSERTE ( spBodyElem );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
CComQIPtr<IHTMLTextContainer, &IID_IHTMLTextContainer> spHtmlTextCont ( spBodyElem );
|
|
if ( spHtmlTextCont )
|
|
{
|
|
LONG lxPos = 0;
|
|
LONG lyPos = 0;
|
|
|
|
hr = spHtmlTextCont->get_scrollLeft ( &lxPos );
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = spHtmlTextCont->get_scrollTop ( &lyPos );
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
lpPos->x = lxPos;
|
|
lpPos->y = lyPos;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CProxyFrame::GetContainer ( LPOLECONTAINER* ppContainer )
|
|
{
|
|
_ASSERTE ( m_pCtl );
|
|
_ASSERTE ( m_pCtl->m_spClientSite );
|
|
if ( m_pCtl->m_spClientSite )
|
|
{
|
|
return m_pCtl->m_spClientSite->GetContainer ( ppContainer );
|
|
}
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
// For the Safe for Scripting control, make sure the URL specified comes from
|
|
// the same host as the SecurityURL, the URL of the hosting container..
|
|
// Note that this makes the SFS control virtually useless in VB, which returns
|
|
// the Boot Drive Root Folder as the Security URL.
|
|
//
|
|
HRESULT CProxyFrame::CheckCrossZoneSecurity ( BSTR urlToLoad )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CComPtr<IInternetSecurityManager> srpSec;
|
|
CComBSTR bstrSecURL;
|
|
|
|
hr = GetSecurityURL ( bstrSecURL );
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
#ifdef LATE_BIND_URLMON_WININET
|
|
hr = (m_pfnCoInternetCreateSecurityManager)( NULL, &srpSec, 0 );
|
|
#else
|
|
hr = CoInternetCreateSecurityManager( NULL, &srpSec, 0 );
|
|
#endif // LATE_BIND_URLMON_WININET
|
|
if ( SUCCEEDED ( hr ) && srpSec )
|
|
{
|
|
BYTE* pbSidToLoad = NULL;
|
|
BYTE* pbDSidSecURL = NULL;
|
|
DWORD dwSizeToLoad = INTERNET_MAX_URL_LENGTH;
|
|
DWORD dwSizeSecURL = INTERNET_MAX_URL_LENGTH;
|
|
|
|
pbSidToLoad = new BYTE [INTERNET_MAX_URL_LENGTH];
|
|
pbDSidSecURL = new BYTE [INTERNET_MAX_URL_LENGTH];
|
|
|
|
hr = srpSec->GetSecurityId ( urlToLoad, pbSidToLoad, &dwSizeToLoad, 0 );
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = srpSec->GetSecurityId ( bstrSecURL, pbDSidSecURL, &dwSizeSecURL, 0 );
|
|
_ASSERTE ( SUCCEEDED ( hr ) );
|
|
if ( SUCCEEDED ( hr ) )
|
|
{
|
|
hr = DE_E_ACCESS_DENIED;
|
|
|
|
if ( ( dwSizeToLoad == dwSizeSecURL ) &&
|
|
( 0 == memcmp ( pbSidToLoad, pbDSidSecURL, dwSizeToLoad ) ) )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
delete [] pbSidToLoad;
|
|
delete [] pbDSidSecURL;
|
|
}
|
|
else
|
|
{
|
|
// BUG 597887: If CoInternetCreateSecurityManager returns NULL and success, return error:
|
|
if ( !srpSec )
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// A specialization of CheckCrossZoneSecurity which works on the current selection.
|
|
// Bug 547802 indicated a regression in execCommand, so we will assure safety ourselves.
|
|
//
|
|
HRESULT CProxyFrame::CheckCrossZoneSecurityOfSelection ()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IHTMLDocument2> spDOM;
|
|
CComPtr<IServiceProvider> srpSP;
|
|
CComPtr<IHTMLEditServices> srpEditor;
|
|
CComPtr<ISelectionServices> srpSelSvc;
|
|
CComPtr<IMarkupContainer> sprMarkupCont;
|
|
CComPtr<IHTMLDocument2> spSelDoc;
|
|
CComPtr<IHTMLLocation> spHostLoc;
|
|
CComBSTR bstrHref;
|
|
|
|
hr = HrGetDoc( &spDOM );
|
|
if ( FAILED(hr) ) goto ONERROR;
|
|
|
|
hr = spDOM->QueryInterface(IID_IServiceProvider, (LPVOID *)&srpSP);
|
|
if ( FAILED(hr) ) goto ONERROR;
|
|
hr = srpSP->QueryService(SID_SHTMLEditServices, IID_IHTMLEditServices, (void **)&srpEditor);
|
|
if ( FAILED(hr) ) goto ONERROR;
|
|
hr = srpEditor->GetSelectionServices(NULL, &srpSelSvc);
|
|
if ( FAILED(hr) ) goto ONERROR;
|
|
if ( !srpSelSvc ) goto ONERROR;
|
|
hr = srpSelSvc->GetMarkupContainer(&sprMarkupCont);
|
|
if ( FAILED(hr) ) goto ONERROR;
|
|
if ( !sprMarkupCont ) goto ONERROR;
|
|
hr = sprMarkupCont->QueryInterface(&spSelDoc);
|
|
if ( FAILED(hr) ) goto ONERROR;
|
|
|
|
hr = spSelDoc->get_location ( &spHostLoc );
|
|
if ( FAILED(hr) ) goto ONERROR;
|
|
if ( !spHostLoc ) goto ONERROR;
|
|
hr = spHostLoc->get_href ( &bstrHref );
|
|
if ( FAILED(hr) ) goto ONERROR;
|
|
if ( !bstrHref ) goto ONERROR;
|
|
|
|
hr = CheckCrossZoneSecurity ( bstrHref );
|
|
|
|
return hr;
|
|
|
|
ONERROR:
|
|
return DE_E_ACCESS_DENIED;
|
|
}
|
|
|
|
|
|
HRESULT CProxyFrame::OnProgress(ULONG, ULONG, ULONG ulStatusCode, LPCWSTR)
|
|
{
|
|
if ( BINDSTATUS_REDIRECTING == ulStatusCode )
|
|
{
|
|
// If we're the SFS control, cancel on Redirect. Otherwise, ignore it.
|
|
if ( m_pCtl->IsSafeForScripting ())
|
|
{
|
|
m_bfSFSRedirect = TRUE;
|
|
}
|
|
}
|
|
return E_NOTIMPL;
|
|
}
|
|
|