Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

241 lines
5.5 KiB

/******************************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name:
Behav_A.cpp
Abstract:
This file contains the implementation of the CPCHBehavior_A class,
that dictates how hyperlinks work in the help center.
Revision History:
Davide Massarenti (dmassare) 06/06/2000
created
******************************************************************************/
#include "stdafx.h"
#include <ShellApi.h>
////////////////////////////////////////////////////////////////////////////////
static const WCHAR s_APPprefix [] = L"APP:";
static const WCHAR s_HCPprefix [] = L"HCP:";
static const WCHAR s_HTTPprefix[] = L"HTTP:";
////////////////////////////////////////////////////////////////////////////////
HRESULT Local_ShellRun( LPCWSTR szCommandOrig ,
LPCWSTR szArgs )
{
__HCP_FUNC_ENTRY( "Local_ShellRun" );
HRESULT hr;
MPC::wstring szCommand( szCommandOrig );
SHELLEXECUTEINFOW oExecInfo;
::ZeroMemory( &oExecInfo, sizeof(oExecInfo) ); oExecInfo.cbSize = sizeof(oExecInfo);
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SubstituteEnvVariables( szCommand ));
oExecInfo.fMask = SEE_MASK_FLAG_NO_UI;
oExecInfo.hwnd = NULL;
oExecInfo.lpVerb = L"Open";
oExecInfo.lpFile = szCommand.c_str();
oExecInfo.lpParameters = (szArgs && szArgs[0]) ? szArgs : NULL;
oExecInfo.lpDirectory = NULL;
oExecInfo.nShow = SW_SHOWNORMAL;
__MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ShellExecuteExW( &oExecInfo ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(oExecInfo.hProcess) ::CloseHandle( oExecInfo.hProcess );
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
CPCHBehavior_A::CPCHBehavior_A()
{
__HCP_FUNC_ENTRY( "CPCHBehavior_A::CPCHBehavior_A" );
}
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPCHBehavior_A::Init( /*[in]*/ IElementBehaviorSite* pBehaviorSite )
{
__HCP_FUNC_ENTRY( "CPCHBehavior_A::Init" );
HRESULT hr;
__MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior::Init( pBehaviorSite ));
__MPC_EXIT_IF_METHOD_FAILS(hr, AttachToEvent( L"onclick", (CLASS_METHOD)onClick ));
////////////////////
{
CComQIPtr<IHTMLAnchorElement> elemHyperLink;
if((elemHyperLink = m_elem))
{
CComBSTR bstrHref;
MPC_SCRIPTHELPER_GET__DIRECT(bstrHref, elemHyperLink, href);
if(STRINGISPRESENT(bstrHref)) (void)HyperLinks::Lookup::s_GLOBAL->Queue( bstrHref );
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHBehavior_A::onClick( DISPID, DISPPARAMS*, VARIANT* )
{
__HCP_FUNC_ENTRY( "CPCHBehavior_A::onClick" );
HRESULT hr;
if(!m_parent) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
//
// If we are navigating, abort the click.
//
{
VARIANT_BOOL fCancel;
CPCHHelpSession* hs = m_parent->HelpSession();
if(hs)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, hs->IsNavigating( &fCancel ));
if(fCancel)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, CancelEvent());
__MPC_SET_ERROR_AND_EXIT(hr, S_OK);
}
hs->CancelThreshold();
}
}
//
// If the URL is an APP: one, process the redirect.
//
if(m_fTrusted)
{
CComPtr<IHTMLElement> elemSrc;
CComPtr<IHTMLElement> elemParent;
CComQIPtr<IHTMLAnchorElement> elemHyperLink;
__MPC_EXIT_IF_METHOD_FAILS(hr, GetEvent_SrcElement( elemSrc ));
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::HTML::FindFirstParentWithThisTag( elemParent, elemSrc, L"A" ));
if((elemHyperLink = elemParent))
{
CComBSTR bstrHref;
CComBSTR bstrTarget;
MPC_SCRIPTHELPER_GET__DIRECT(bstrHref , elemHyperLink, href );
MPC_SCRIPTHELPER_GET__DIRECT(bstrTarget, elemHyperLink, target);
if(bstrHref && !_wcsnicmp( bstrHref, s_APPprefix, MAXSTRLEN( s_APPprefix ) ))
{
LPCWSTR szRealHRef = bstrHref + MAXSTRLEN( s_APPprefix );
//
// The URL starts with "app:", so let's cancel the event.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, CancelEvent());
//
// Is it for hcp:// ?
//
if(!_wcsnicmp( szRealHRef, s_HCPprefix, MAXSTRLEN( s_HCPprefix ) ))
{
//
// Then navigate from the top level window.
//
CComPtr<IHTMLWindow2> win;
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::HTML::LocateFrame( win, elemSrc, L"_top" ));
__MPC_EXIT_IF_METHOD_FAILS(hr, win->navigate( CComBSTR( szRealHRef ) ));
}
else
//
// Launch an external program.
//
{
MPC::wstring szFile;
MPC::wstring szArgs;
MPC::WStringLookup mapQuery;
//
// Parse the query string.
//
MPC::HTML::ParseHREF( szRealHRef, szFile, mapQuery );
//
// Is it for http:// ? Then assume the url is properly escape and pass it directly to the shell.
//
if(!_wcsnicmp( szFile.c_str(), s_HTTPprefix, MAXSTRLEN( s_HTTPprefix ) ))
{
szFile = szRealHRef;
}
else
{
szArgs = mapQuery[ L"arg" ];
}
(void)Local_ShellRun( szFile.c_str(), szArgs.c_str() );
//
// If we have a "topic" argument from the query string, navigate the original target to it.
//
szFile = mapQuery[ L"topic" ];
if(szFile.size())
{
//
// Then navigate from the top level window.
//
CComPtr<IHTMLWindow2> win;
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::HTML::LocateFrame( win, elemSrc, bstrTarget ));
__MPC_EXIT_IF_METHOD_FAILS(hr, win->navigate( CComBSTR( szFile.c_str() ) ));
}
}
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}