Windows2003-3790/inetcore/urlmon/urlhlink/hlinkez.cxx
2020-09-30 16:53:55 +02:00

1006 lines
28 KiB
C++

//+---------------------------------------------------------------------------
//
// 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);
}