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.
1005 lines
28 KiB
1005 lines
28 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1996.
|
|
//
|
|
// File: hlinkez.cxx
|
|
//
|
|
// Contents:
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History:
|
|
// 5-15-96 Ramesh G - Major modifications
|
|
// 5-17-96 Ramesh G - Added Frames support
|
|
// Ramesh G - Modified variable names to Hungarian Notation
|
|
// 6-19-96 Ramesh G - Modifications
|
|
// 7-25-96 Ramesh G - Modifications
|
|
// 8-05-96 Ramesh G - Merged HlinkSimple...String() and Moniker()
|
|
// HlinkSimpleNavigateToString() creates the moniker
|
|
// and calls HlinkSimpleNavigateToMoniker()
|
|
//----------------------------------------------------------------------------
|
|
#define USE_SYSTEM_URL_MONIKER
|
|
#define INITGUID
|
|
#define STR_SIZE 20
|
|
|
|
#include "hlink.h"
|
|
#include "ocidl.h"
|
|
#include "docobj.h"
|
|
#include "exdisp.h"
|
|
#include "shellapi.h"
|
|
#include "servprov.h"
|
|
#include "urlhlink.h"
|
|
#include "htiface.h"
|
|
#include "wininet.h"
|
|
#include <shlwapi.h>
|
|
#include <shlwapip.h>
|
|
#include <mshtml.h>
|
|
#include "mshtmdid.h"
|
|
#include <delaydll.h>
|
|
#include "sdll.hxx"
|
|
|
|
#ifndef GUID_NULL
|
|
struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) GUID_NULL;
|
|
#define GUID_NULL __uuidof(struct GUID_NULL)
|
|
#endif
|
|
|
|
class HLinkDll
|
|
{
|
|
public:
|
|
HLinkDll();
|
|
HRESULT HlinkCreateFromMoniker(
|
|
IMoniker* pmkSource,
|
|
LPCWSTR szLocation,
|
|
LPCWSTR szFriendlyName,
|
|
IHlinkSite* phlSite,
|
|
DWORD dwSiteData,
|
|
IUnknown* punkOuter,
|
|
REFIID riid,
|
|
void** ppv);
|
|
private:
|
|
|
|
BOOL LoadFunc( LPCSTR lpProcName, FARPROC & fp );
|
|
typedef HRESULT (STDAPICALLTYPE * LPFNHlinkCreateFromMoniker)(
|
|
IMoniker* pmkSource,
|
|
LPCWSTR szLocation,
|
|
LPCWSTR szFriendlyName,
|
|
IHlinkSite* phlSite,
|
|
DWORD dwSiteData,
|
|
IUnknown* punkOuter,
|
|
REFIID riid,
|
|
void** ppv);
|
|
LPFNHlinkCreateFromMoniker m_lpfnHlinkCreateFromMoniker;
|
|
|
|
HMODULE m_hmodule;
|
|
BOOL m_error;
|
|
|
|
};
|
|
|
|
inline HRESULT HLinkDll::HlinkCreateFromMoniker(
|
|
IMoniker* pmkSource,
|
|
LPCWSTR szLocation,
|
|
LPCWSTR szFriendlyName,
|
|
IHlinkSite* phlSite,
|
|
DWORD dwSiteData,
|
|
IUnknown* punkOuter,
|
|
REFIID riid,
|
|
void** ppv)
|
|
{
|
|
|
|
if( !LoadFunc("HlinkCreateFromMoniker",*(FARPROC*)&m_lpfnHlinkCreateFromMoniker) )
|
|
return(E_FAIL);
|
|
|
|
return m_lpfnHlinkCreateFromMoniker(
|
|
pmkSource,
|
|
szLocation,
|
|
szFriendlyName,
|
|
phlSite,
|
|
dwSiteData,
|
|
punkOuter,
|
|
riid,
|
|
ppv);
|
|
}
|
|
|
|
|
|
HLinkDll::HLinkDll()
|
|
{
|
|
m_hmodule = 0;
|
|
m_error = 0;
|
|
m_lpfnHlinkCreateFromMoniker = 0;
|
|
}
|
|
|
|
#if 0
|
|
HLinkDll::~HLinkDll()
|
|
{
|
|
if( m_hmodule )
|
|
::FreeLibrary( m_hmodule );
|
|
}
|
|
#endif
|
|
|
|
BOOL HLinkDll::LoadFunc( LPCSTR lpProcName, FARPROC & fp )
|
|
{
|
|
if( m_error )
|
|
return(0);
|
|
|
|
if( fp )
|
|
return(1);
|
|
|
|
if( !m_hmodule )
|
|
{
|
|
m_hmodule = ::LoadLibrary( "HLINK.DLL" );
|
|
|
|
if( !m_hmodule )
|
|
{
|
|
m_error = 1;
|
|
return(0);
|
|
}
|
|
|
|
}
|
|
|
|
fp = ::GetProcAddress( m_hmodule, lpProcName );
|
|
|
|
return( fp != 0 );
|
|
}
|
|
|
|
static HLinkDll hlink;
|
|
|
|
|
|
//////////////////
|
|
static int wclen(LPCWSTR szStr)
|
|
{
|
|
int cbStr=0;
|
|
if(szStr!=NULL)
|
|
while(szStr[cbStr]!=NULL)
|
|
++cbStr;
|
|
|
|
return cbStr;
|
|
}
|
|
|
|
////////////////////////////
|
|
|
|
static HRESULT GetAnInterface
|
|
(
|
|
IUnknown * punk,
|
|
const IID & riid,
|
|
void ** pout,
|
|
|
|
BOOL bCheckServiceProvider,
|
|
const IID & siid,
|
|
const IID & siid_riid,
|
|
void ** sout
|
|
)
|
|
{
|
|
IOleObject * oleObj = 0;
|
|
IOleClientSite * oleSite = 0;
|
|
IOleContainer * container = 0;
|
|
IUnknown * service = 0;
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
// Initialize passed in interface pointers: calling code assumes NULL for failure
|
|
if(pout)
|
|
*pout = NULL;
|
|
if(sout)
|
|
*sout = NULL;
|
|
|
|
if(punk)
|
|
hr = punk->QueryInterface( IID_IOleObject, (void **)&oleObj );
|
|
|
|
// BUBUG: I think this returns a wrong hr if QS fails but the QI passes - jp
|
|
while( SUCCEEDED(hr) && oleObj )
|
|
{
|
|
if( oleSite )
|
|
{
|
|
//oleSite->Release();
|
|
oleSite = 0;
|
|
}
|
|
|
|
hr = oleObj->GetClientSite(&oleSite);
|
|
|
|
if( FAILED(hr) || !oleSite)
|
|
break;
|
|
|
|
if( bCheckServiceProvider)
|
|
{
|
|
IServiceProvider * servProv;
|
|
|
|
hr = oleSite->QueryInterface( IID_IServiceProvider, (void**)&servProv);
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
hr = servProv->QueryService
|
|
(
|
|
siid,
|
|
siid_riid,
|
|
(void **)&service
|
|
);
|
|
|
|
servProv->Release();
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
bCheckServiceProvider = FALSE;
|
|
|
|
hr = service->QueryInterface( riid, pout );
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
break;
|
|
|
|
}
|
|
|
|
if( container )
|
|
{
|
|
container->Release();
|
|
container = 0;
|
|
}
|
|
|
|
hr = oleSite->GetContainer( &container );
|
|
|
|
if( FAILED(hr) )
|
|
break;
|
|
|
|
hr = container->QueryInterface( riid, pout );
|
|
|
|
if( SUCCEEDED(hr) )
|
|
break;
|
|
|
|
oleObj->Release();
|
|
oleObj = 0;
|
|
|
|
hr = container->QueryInterface( IID_IOleObject, (void**)&oleObj );
|
|
|
|
}
|
|
|
|
if( oleSite )
|
|
{
|
|
oleSite->Release();
|
|
oleSite = 0;
|
|
}
|
|
|
|
if( oleObj )
|
|
oleObj->Release();
|
|
|
|
if( container )
|
|
container->Release();
|
|
|
|
if( service )
|
|
{
|
|
if (sout)
|
|
*sout = service;
|
|
else
|
|
service->Release();
|
|
}
|
|
|
|
return( hr );
|
|
}
|
|
|
|
//
|
|
// GetUrlScheme() returns one of the URL_SCHEME_* constants as
|
|
// defined in shlwapip.h
|
|
// example "http://foo" returns URL_SCHEME_HTTP
|
|
//
|
|
static DWORD GetUrlSchemeW(IN LPCWSTR pcszUrl)
|
|
{
|
|
if(pcszUrl)
|
|
{
|
|
PARSEDURLW pu;
|
|
pu.cbSize = sizeof(pu);
|
|
if(SUCCEEDED(ParseURLW(pcszUrl, &pu)))
|
|
return pu.nScheme;
|
|
}
|
|
return URL_SCHEME_INVALID;
|
|
}
|
|
|
|
//
|
|
// GetUrlScheme() returns one of the URL_SCHEME_* constants as
|
|
// defined in shlwapip.h
|
|
// example "http://foo" returns URL_SCHEME_HTTP
|
|
//
|
|
static DWORD GetUrlSchemeA(IN LPCSTR pcszUrl)
|
|
{
|
|
if(pcszUrl)
|
|
{
|
|
PARSEDURLA pu;
|
|
pu.cbSize = sizeof(pu);
|
|
if(SUCCEEDED(ParseURLA(pcszUrl, &pu)))
|
|
return pu.nScheme;
|
|
}
|
|
return URL_SCHEME_INVALID;
|
|
}
|
|
|
|
HRESULT DoUrlShellExecuteA(LPCSTR pszUrl)
|
|
{
|
|
CShellDll sdll;
|
|
HINSTANCE hInst = NULL;
|
|
|
|
if(S_OK == sdll.Init())
|
|
{
|
|
UINT uProt = GetUrlSchemeA(pszUrl);
|
|
|
|
switch (uProt)
|
|
{
|
|
case URL_SCHEME_HTTP:
|
|
case URL_SCHEME_HTTPS:
|
|
case URL_SCHEME_FTP:
|
|
case URL_SCHEME_FILE:
|
|
hInst = sdll.ShellExecute(
|
|
NULL, NULL, pszUrl,
|
|
NULL, NULL, SW_SHOWNORMAL );
|
|
break;
|
|
|
|
// Non-standard protocols go here:
|
|
default:
|
|
hInst = sdll.ShellExecute(
|
|
NULL, "open", "iexplore.exe",
|
|
pszUrl, NULL, SW_SHOWNORMAL );
|
|
}
|
|
}
|
|
|
|
return ((ULONG_PTR)hInst > 32) ? S_OK : E_FAIL;
|
|
}
|
|
|
|
|
|
|
|
BOOL IsSpecialUrl(WCHAR *pchURL)
|
|
{
|
|
UINT uProt;
|
|
uProt = GetUrlSchemeW(pchURL);
|
|
return (URL_SCHEME_JAVASCRIPT == uProt ||
|
|
URL_SCHEME_VBSCRIPT == uProt ||
|
|
URL_SCHEME_ABOUT == uProt);
|
|
}
|
|
|
|
HRESULT WrapSpecialUrlFlat(LPWSTR pszUrl, DWORD cchUrl)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (IsSpecialUrl(pszUrl))
|
|
{
|
|
//
|
|
// If this is javascript:, vbscript: or about:, append the
|
|
// url of this document so that on the other side we can
|
|
// decide whether or not to allow script execution.
|
|
//
|
|
|
|
// QFE 2735 (Georgi XDomain): [alanau]
|
|
//
|
|
// If the special URL contains an %00 sequence, then it will be converted to a Null char when
|
|
// encoded. This will effectively truncate the Security ID. For now, simply disallow this
|
|
// sequence, and display a "Permission Denied" script error.
|
|
//
|
|
if (StrStrW(pszUrl, L"%00"))
|
|
{
|
|
hr = E_ACCESSDENIED;
|
|
}
|
|
else
|
|
{
|
|
// munge the url in place
|
|
//
|
|
|
|
// someone could put in a string like this:
|
|
// %2501 OR %252501 OR %25252501
|
|
// which, depending on the number of decoding steps, will bypass security
|
|
// so, just keep decoding while there are %s and the string is getting shorter
|
|
int nPreviousLen = 0;
|
|
while ( (nPreviousLen != lstrlenW(pszUrl)) && (StrChrW(pszUrl, L'%')))
|
|
{
|
|
nPreviousLen = lstrlenW(pszUrl);
|
|
int nNumPercents;
|
|
int nNumPrevPercents = 0;
|
|
|
|
// Reduce the URL
|
|
//
|
|
for (;;)
|
|
{
|
|
// Count the % signs.
|
|
//
|
|
nNumPercents = 0;
|
|
|
|
WCHAR *pch = pszUrl;
|
|
while (pch = StrChrW(pch, L'%'))
|
|
{
|
|
pch++;
|
|
nNumPercents++;
|
|
}
|
|
|
|
// If the number of % signs has changed, we've reduced the URL one iteration.
|
|
//
|
|
if (nNumPercents != nNumPrevPercents)
|
|
{
|
|
WCHAR szBuf[INTERNET_MAX_URL_LENGTH];
|
|
DWORD dwSize;
|
|
|
|
// Encode the URL
|
|
hr = CoInternetParseUrl(pszUrl,
|
|
PARSE_ENCODE,
|
|
0,
|
|
szBuf,
|
|
INTERNET_MAX_URL_LENGTH,
|
|
&dwSize,
|
|
0);
|
|
|
|
StrCpyNW(pszUrl, szBuf, cchUrl);
|
|
|
|
nNumPrevPercents = nNumPercents;
|
|
}
|
|
else
|
|
{
|
|
// The URL is fully reduced. Break out of loop.
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Now scan for '\1' characters.
|
|
//
|
|
if (StrChrW(pszUrl, L'\1'))
|
|
{
|
|
// If there are '\1' characters, we can't guarantee the safety. Put up "Permission Denied".
|
|
//
|
|
hr = E_ACCESSDENIED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
static HRESULT GetAMoniker
|
|
(
|
|
IUnknown * pUnk,
|
|
LPCWSTR szTarget,
|
|
IMoniker * * ppMoniker
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IBindHost * pBindHost = 0;
|
|
|
|
hr = GetAnInterface
|
|
(
|
|
pUnk,
|
|
IID_IBindHost,
|
|
(void**)&pBindHost,
|
|
TRUE,
|
|
IID_IBindHost,
|
|
IID_IBindHost,
|
|
NULL
|
|
);
|
|
|
|
if( pBindHost )
|
|
{
|
|
hr = pBindHost->CreateMoniker((LPWSTR)szTarget,NULL,ppMoniker,0);
|
|
pBindHost->Release();
|
|
}
|
|
else
|
|
hr = ::CreateURLMoniker(0,szTarget,ppMoniker);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
STDAPI HlinkSimpleNavigateToString
|
|
(
|
|
/* [in] */ LPCWSTR szTarget, // required - target document - null if local jump w/in doc
|
|
/* [in] */ LPCWSTR szLocation, // optional, for navigation into middle of a doc
|
|
/* [in] */ LPCWSTR szTargetFrame, // optional, for targeting frame-sets
|
|
/* [in] */ IUnknown *pUnk, // required - we'll search this for other necessary interfaces
|
|
/* [in] */ IBindCtx *pBndctx, // optional. caller may register an IBSC in this
|
|
/* [in] */ IBindStatusCallback * pBscb,
|
|
/* [in] */ DWORD grfHLNF, // flags (TBD - HadiP needs to define this correctly?)
|
|
/* [in] */ DWORD dwReserved // for future use, must be NULL
|
|
)
|
|
{
|
|
IWebBrowserApp *pExplorer = 0;
|
|
IHlinkFrame *pHlframe = 0;
|
|
ITargetFrame *pTargetFrame = 0;
|
|
IMoniker *pMoniker = 0;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( szTarget && *szTarget )
|
|
hr = GetAMoniker( pUnk, szTarget, &pMoniker );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
hr = HlinkSimpleNavigateToMoniker (
|
|
pMoniker,
|
|
szLocation,
|
|
szTargetFrame,
|
|
pUnk,
|
|
pBndctx,
|
|
pBscb,
|
|
grfHLNF,
|
|
dwReserved );
|
|
|
|
if ( pMoniker )
|
|
pMoniker->Release();
|
|
|
|
return( hr );
|
|
|
|
}
|
|
|
|
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
BOOL AccessAllowed(LPCWSTR pwszURL1, LPCWSTR pwszURL2)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
IInternetSecurityManager *pSecMgr = NULL;
|
|
|
|
if (pwszURL1 && pwszURL2)
|
|
{
|
|
if (StrCmpW(pwszURL1, pwszURL2) == 0)
|
|
{
|
|
// No need to check if URLs are the same
|
|
fRet = TRUE;
|
|
}
|
|
else if (SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IInternetSecurityManager,
|
|
(void **)&pSecMgr)))
|
|
{
|
|
BYTE reqSid[MAX_SIZE_SECURITY_ID], docSid[MAX_SIZE_SECURITY_ID];
|
|
DWORD cbReqSid = ARRAYSIZE(reqSid);
|
|
DWORD cbDocSid = ARRAYSIZE(docSid);
|
|
|
|
if ( SUCCEEDED(pSecMgr->GetSecurityId(pwszURL1, reqSid, &cbReqSid, 0))
|
|
&& SUCCEEDED(pSecMgr->GetSecurityId(pwszURL2, docSid, &cbDocSid, 0))
|
|
&& (cbReqSid == cbDocSid)
|
|
&& (memcmp(reqSid, docSid, cbReqSid) == 0))
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
pSecMgr->Release();
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
BOOL AccessAllowed(ITargetFrame* pSrcFrame, IHlinkFrame* pTargetFrame)
|
|
{
|
|
IDispatch* pdisp[2] = {0};
|
|
IServiceProvider* pIsp[2] = {0};
|
|
DISPPARAMS dp;
|
|
VARIANT VarUrl[2];
|
|
UINT uiErr;
|
|
BOOL fRet = FALSE;
|
|
HRESULT hr;
|
|
int idx;
|
|
|
|
if(!pTargetFrame || !pSrcFrame)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
hr = pTargetFrame->QueryInterface(IID_IServiceProvider, (LPVOID *)&pIsp[0]);
|
|
|
|
if(hr)
|
|
goto cleanup;
|
|
|
|
hr = pSrcFrame->QueryInterface(IID_IServiceProvider, (LPVOID *)&pIsp[1]);
|
|
|
|
if(hr)
|
|
goto cleanup;
|
|
|
|
VariantInit(&VarUrl[0]);
|
|
VariantInit(&VarUrl[1]);
|
|
|
|
for (idx = 0; idx < 2; idx++)
|
|
{
|
|
hr = pIsp[idx]->QueryService(IID_IHTMLWindow2, IID_IDispatch, (LPVOID *)&pdisp[idx]);
|
|
|
|
if(hr)
|
|
{
|
|
hr = pIsp[idx]->QueryService(IID_IWebBrowserApp, IID_IDispatch, (LPVOID *)&pdisp[idx]);
|
|
}
|
|
|
|
if(hr)
|
|
goto cleanup;
|
|
|
|
ZeroMemory((PVOID)&dp, sizeof(dp));
|
|
|
|
hr = pdisp[idx]->Invoke(
|
|
DISPID_SECURITYCTX,
|
|
IID_NULL,
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
DISPATCH_PROPERTYGET,
|
|
&dp,
|
|
&VarUrl[idx],
|
|
NULL,
|
|
&uiErr);
|
|
|
|
if(hr)
|
|
goto cleanup;
|
|
|
|
if (V_VT(&VarUrl[idx]) != VT_BSTR || !V_BSTR(&VarUrl[idx]))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
if (hr)
|
|
goto cleanup;
|
|
}
|
|
|
|
fRet = AccessAllowed(V_BSTR(&VarUrl[0]), V_BSTR(&VarUrl[1]));
|
|
|
|
cleanup:
|
|
for (idx = 0; idx < 2; idx++)
|
|
{
|
|
if(pdisp[idx])
|
|
pdisp[idx]->Release();
|
|
if(pIsp[idx])
|
|
pIsp[idx]->Release();
|
|
|
|
VariantClear(&VarUrl[idx]);
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
|
|
STDAPI HlinkSimpleNavigateToMoniker
|
|
(
|
|
/* [in] */ IMoniker *pmkTarget, // required - target document - (may be null if local jump w/in doc)
|
|
/* [in] */ LPCWSTR szLocation, // optional, for navigation into middle of a doc
|
|
/* [in] */ LPCWSTR szTargetFrame, // optional, for targeting frame-sets
|
|
/* [in] */ IUnknown *pUnk, // required - we'll search this for other necessary interfaces
|
|
/* [in] */ IBindCtx *pBndctx, // optional. caller may register an IBSC in this
|
|
/* [in] */ IBindStatusCallback * pBscb,
|
|
/* [in] */ DWORD grfHLNF, // flags
|
|
/* [in] */ DWORD dwReserved // for future use, must be NULL
|
|
)
|
|
{
|
|
IWebBrowserApp * pExplorer = 0;
|
|
IHlinkFrame * pHlframe = 0;
|
|
ITargetFrame * pTargetFrameSrc = 0;
|
|
CShellDll sdll;
|
|
LPWSTR pszUrl = NULL;
|
|
|
|
HRESULT hr, htemp;
|
|
|
|
if (pmkTarget == NULL)
|
|
{
|
|
if (szLocation && *szLocation)
|
|
{
|
|
grfHLNF |= HLNF_INTERNALJUMP;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
return E_INVALIDARG; //no location specified for internal jump
|
|
}
|
|
else
|
|
{
|
|
DWORD dwId;
|
|
|
|
if (SUCCEEDED(pmkTarget->IsSystemMoniker(&dwId)) &&
|
|
MKSYS_URLMONIKER == dwId)
|
|
{
|
|
|
|
if (SUCCEEDED(pmkTarget->GetDisplayName(NULL, NULL, &pszUrl)))
|
|
{
|
|
HRESULT hrSecure = WrapSpecialUrlFlat(pszUrl, lstrlenW(pszUrl) + 1);
|
|
|
|
|
|
if (FAILED(hrSecure))
|
|
{
|
|
CoTaskMemFree(pszUrl);
|
|
return hrSecure;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pUnk)
|
|
hr = GetAnInterface
|
|
(
|
|
pUnk,
|
|
IID_IWebBrowserApp,
|
|
(void**)&pExplorer,
|
|
TRUE,
|
|
IID_IHlinkFrame,
|
|
IID_IHlinkFrame,
|
|
(void**)&pHlframe
|
|
);
|
|
|
|
IHlink * pLink = 0;
|
|
|
|
hr = hlink.HlinkCreateFromMoniker
|
|
(
|
|
pmkTarget,
|
|
szLocation,
|
|
L"TheName",
|
|
0, // hlsite,
|
|
0, NULL,
|
|
IID_IHlink,
|
|
(void**)&pLink
|
|
);
|
|
|
|
if (SUCCEEDED(hr) && pHlframe)
|
|
{
|
|
BOOL fAccessAllowed = TRUE;
|
|
|
|
if (szTargetFrame && *szTargetFrame)
|
|
{
|
|
long len = (lstrlenW(szTargetFrame) + 1) * sizeof(char);
|
|
char szTargetFrameName[STR_SIZE+1];
|
|
len = (len > STR_SIZE) ? STR_SIZE : len;
|
|
WideCharToMultiByte(CP_ACP, 0, szTargetFrame, -1, (LPSTR)szTargetFrameName, len, NULL, NULL);
|
|
if (lstrcmpi(szTargetFrameName,"_blank") == 0)
|
|
grfHLNF |= HLNF_OPENINNEWWINDOW;
|
|
else
|
|
{
|
|
htemp = GetAnInterface
|
|
(
|
|
pUnk,
|
|
IID_ITargetFrame,
|
|
(void**)&pTargetFrameSrc,
|
|
TRUE,
|
|
IID_ITargetFrame,
|
|
IID_ITargetFrame,
|
|
NULL
|
|
);
|
|
IUnknown *punkTargetFrame = 0;
|
|
if (SUCCEEDED(htemp))
|
|
htemp = pTargetFrameSrc->FindFrame(szTargetFrame,
|
|
pHlframe,
|
|
FINDFRAME_JUSTTESTEXISTENCE,
|
|
&punkTargetFrame);
|
|
IHlinkFrame *pTargetHlinkFrame = 0;
|
|
if (punkTargetFrame)
|
|
{
|
|
IServiceProvider *pIsp = 0;
|
|
|
|
// Get the IHlinkFrame for the target'ed frame and the source.
|
|
htemp = punkTargetFrame->QueryInterface(IID_IServiceProvider, (LPVOID *)&pIsp);
|
|
if (pIsp != NULL)
|
|
{
|
|
// NOTE: SID_SHLinkFrame should be the guidService
|
|
htemp = pIsp->QueryService(IID_IWebBrowserApp, IID_IHlinkFrame, (LPVOID*) &pTargetHlinkFrame);
|
|
pIsp->Release();
|
|
}
|
|
|
|
fAccessAllowed = (!IsSpecialUrl(pszUrl) ||
|
|
AccessAllowed(pTargetFrameSrc, pTargetHlinkFrame));
|
|
}
|
|
else
|
|
{
|
|
grfHLNF |= HLNF_OPENINNEWWINDOW;
|
|
}
|
|
if (punkTargetFrame)
|
|
punkTargetFrame->Release();
|
|
|
|
if (pTargetFrameSrc)
|
|
pTargetFrameSrc->Release();
|
|
|
|
|
|
if (pTargetHlinkFrame)
|
|
{
|
|
pHlframe->Release();
|
|
pHlframe = pTargetHlinkFrame;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!fAccessAllowed)
|
|
{
|
|
hr = E_ACCESSDENIED;
|
|
goto exit;
|
|
}
|
|
|
|
hr = pHlframe->Navigate(grfHLNF,
|
|
pBndctx,
|
|
pBscb,
|
|
pLink);
|
|
}
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
|
|
if ( FAILED(hr) && pHlframe)
|
|
{ // Navigation through pHlframe failed, we will retrieve the
|
|
// corresponding IWebBrowserApp interface and try navigation.
|
|
if (pExplorer)
|
|
{
|
|
pExplorer->Release();
|
|
pExplorer = 0;
|
|
}
|
|
pHlframe->QueryInterface(IID_IWebBrowserApp, (void **)&pExplorer);
|
|
}
|
|
|
|
if (FAILED(hr) && pExplorer && pmkTarget)
|
|
{
|
|
LPOLESTR szTarget;
|
|
hr = pmkTarget->GetDisplayName(pBndctx,NULL,&szTarget);
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = pExplorer->Navigate(
|
|
szTarget,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
CoTaskMemFree(szTarget);
|
|
}
|
|
|
|
// pExplorer->Navigate ShellExecute's
|
|
// We need not ShellExecute when pExplorer is not NULL
|
|
|
|
if (FAILED(hr) && !pExplorer && pmkTarget)
|
|
{
|
|
// Our container does not support hyperlinking. We need to shell execute
|
|
// explorer and go to the link.
|
|
|
|
// We need to translate the string to ANSI
|
|
CHAR szPath[MAX_PATH];
|
|
DWORD cchPath = MAX_PATH;
|
|
LPOLESTR szTarget;
|
|
pmkTarget->GetDisplayName(pBndctx,NULL,&szTarget);
|
|
int cbStr = 2 * wclen(szTarget + 1);
|
|
|
|
char *pszAnsiTarget = new char[cbStr];
|
|
if( !pszAnsiTarget )
|
|
goto cleanup;
|
|
|
|
// ASSERT(pszAnsiTarget)
|
|
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, szTarget, -1, pszAnsiTarget, cbStr, 0, 0);
|
|
pszAnsiTarget[cbStr-1] = '\0';
|
|
|
|
|
|
if(SUCCEEDED(PathCreateFromUrl(pszAnsiTarget, szPath, &cchPath, 0)))
|
|
{
|
|
HANDLE hFile = CreateFile(szPath,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (INVALID_HANDLE_VALUE != hFile)
|
|
{
|
|
CloseHandle(hFile);
|
|
hr = DoUrlShellExecuteA(szPath);
|
|
}
|
|
else
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
hr = DoUrlShellExecuteA((LPCTSTR)pszAnsiTarget);
|
|
}
|
|
cleanup:
|
|
if( pszAnsiTarget )
|
|
delete[] pszAnsiTarget;
|
|
|
|
CoTaskMemFree(szTarget);
|
|
}
|
|
|
|
exit:
|
|
|
|
if (pExplorer)
|
|
pExplorer->Release();
|
|
if (pHlframe)
|
|
pHlframe->Release();
|
|
if (pLink)
|
|
pLink->Release();
|
|
if(pszUrl)
|
|
CoTaskMemFree(pszUrl);
|
|
|
|
|
|
return( hr );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HlinkGoBack
|
|
//
|
|
STDAPI HlinkGoBack(IUnknown *pUnk)
|
|
{
|
|
IWebBrowserApp * pExplorer = 0;
|
|
IHlinkFrame * pHlframe = 0;
|
|
HRESULT hr;
|
|
|
|
|
|
hr = GetAnInterface
|
|
(
|
|
pUnk,
|
|
IID_IWebBrowserApp,
|
|
(void**)&pExplorer,
|
|
TRUE,
|
|
IID_IHlinkFrame,
|
|
IID_IHlinkFrame,
|
|
(void**)&pHlframe
|
|
);
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
hr = pHlframe->Navigate(HLNF_NAVIGATINGBACK, 0, 0, 0);
|
|
|
|
if ( FAILED(hr) && pExplorer )
|
|
hr = pExplorer->GoBack();
|
|
|
|
if ( pExplorer )
|
|
pExplorer->Release();
|
|
|
|
if ( pHlframe )
|
|
pHlframe->Release();
|
|
|
|
return (hr);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HlinkGoForward
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
STDAPI HlinkGoForward(IUnknown *pUnk)
|
|
{
|
|
IWebBrowserApp * pExplorer = 0;
|
|
IHlinkFrame * pHlframe = 0;
|
|
HRESULT hr;
|
|
|
|
hr = GetAnInterface
|
|
(
|
|
pUnk,
|
|
IID_IWebBrowserApp,
|
|
(void**)&pExplorer,
|
|
TRUE,
|
|
IID_IHlinkFrame,
|
|
IID_IHlinkFrame,
|
|
(void**)&pHlframe
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = pHlframe->Navigate(HLNF_NAVIGATINGFORWARD, 0, 0, 0);
|
|
|
|
if ( FAILED(hr) && pExplorer )
|
|
hr = pExplorer->GoForward();
|
|
|
|
if ( pExplorer )
|
|
pExplorer->Release();
|
|
|
|
if ( pHlframe )
|
|
pHlframe->Release();
|
|
|
|
return (hr);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HlinkNavigateString
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
STDAPI HlinkNavigateString(IUnknown *pUnk, LPCWSTR szTarget)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = HlinkSimpleNavigateToString(szTarget, NULL, NULL, pUnk, NULL, 0, 0, 0);
|
|
|
|
return (hr);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HlinkNavigateMoniker
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
STDAPI HlinkNavigateMoniker(IUnknown *pUnk, IMoniker *pmkTarget)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = HlinkSimpleNavigateToMoniker(pmkTarget, NULL, NULL, pUnk, NULL,NULL, 0, 0);
|
|
|
|
return (hr);
|
|
}
|
|
|