2366 lines
60 KiB
C++
2366 lines
60 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1994.
|
|
//
|
|
// File: urlmon.cxx
|
|
//
|
|
// Contents: contains URL moniker implementation
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 12-11-95 JohannP (Johann Posch) Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#include <trans.h>
|
|
#ifndef unix
|
|
#include "..\iapp\curl.hxx"
|
|
#else
|
|
#include "../iapp/curl.hxx"
|
|
#endif /* unix */
|
|
#include "urlmk.hxx"
|
|
|
|
PerfDbgTag(tagCUrlMon, "Urlmon", "Log CUrlMon", DEB_URLMON);
|
|
|
|
BOOL IsOInetProtocol(IBindCtx *pbc, LPCWSTR wzProtocol);
|
|
|
|
// prototypes of helper functions (used by RelativePathTo)
|
|
CUrlMon *CreateEmptyPathUrlMon();
|
|
HRESULT HrCreateCUrlFromUrlStr(LPCWSTR pwzUrl, BOOL fParseUrl, CUrl **ppUrl);
|
|
HRESULT HrCreateCUrlFromUrlMon(LPMONIKER pmkUrl, BOOL fParseUrl, CUrl **ppUrl);
|
|
HRESULT HrGetRelativePath(LPSTR lpszBase, LPSTR lpszOther, DWORD dwProto, LPSTR lpszHost,LPSTR lpszRelPath);
|
|
|
|
// #define URLMON_RELPATHTO_PARSE_QUERY_PARAMS
|
|
#ifdef URLMON_RELPATHTO_PARSE_QUERY_PARAMS
|
|
// These are helper routines used by RelativePathTo to deal with the Query
|
|
// and Params sub-strings of a URL, according to rfc 1808.
|
|
// These routines are not enabled because ComposeWith does not deal with
|
|
// these sub-strings in any special way, and we want RelativePathTo to be
|
|
// compatible with ComposeWith.
|
|
void ParseUrlQuery(LPSTR pszURL, LPSTR *ppszQuery);
|
|
void ParseUrlParams(LPSTR pszURL, LPSTR *ppszParams);
|
|
void AddParamsAndQueryToRelPath(LPSTR szRelPath,
|
|
LPSTR pszParamsBase, LPSTR pszParamsOther,
|
|
LPSTR pszQueryBase, LPSTR pszQueryOther);
|
|
#endif // URLMON_RELPATHTO_PARSE_QUERY_PARAMS
|
|
|
|
|
|
// Macros for Double-Byte Character Support (DBCS)
|
|
#if 1
|
|
// Beware of double evaluation
|
|
#define IncLpch(sz) ((sz)=CharNext((sz)))
|
|
#define DecLpch(szStart, sz) ((sz)=CharPrev ((szStart),(sz)))
|
|
#else
|
|
#define IncLpch(sz) (++(sz))
|
|
#define DecLpch(szStart,sz) (--(sz))
|
|
#endif
|
|
|
|
|
|
CUrlMon::CUrlMon(LPWSTR pszUrl) : _CRefs()
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
None,
|
|
"CUrlMon::CUrlMon",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
_pwzUrl = pszUrl;
|
|
DllAddRef();
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
CUrlMon::~CUrlMon()
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
None,
|
|
"CUrlMon::~CUrlMon",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
if (_pwzUrl)
|
|
{
|
|
delete [] _pwzUrl;
|
|
}
|
|
DllRelease();
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::QueryInterface
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [riid] --
|
|
// [ppvObj] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IUnknown::QueryInterface",
|
|
"this=%#x, %#x, %#x",
|
|
this, &riid, ppvObj
|
|
));
|
|
|
|
VDATEPTROUT(ppvObj, void *);
|
|
HRESULT hr = NOERROR;
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::QueryInterface");
|
|
|
|
if ( riid == IID_IUnknown
|
|
|| riid == IID_IMoniker
|
|
|| riid == IID_IAsyncMoniker
|
|
|| riid == IID_IPersist
|
|
|| riid == IID_IPersistStream)
|
|
{
|
|
*ppvObj = this;
|
|
}
|
|
else if (riid == IID_IROTData)
|
|
{
|
|
*ppvObj = (void*)(IROTData *) this;
|
|
}
|
|
else if (riid == IID_IMarshal)
|
|
{
|
|
*ppvObj = (void*) (IMarshal *) this;
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
if (hr == NOERROR)
|
|
{
|
|
AddRef();
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::QueryInterface (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CUrlMon::AddRef
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [ULONG] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CUrlMon::AddRef(void)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Dword,
|
|
"CUrlMon::IUnknown::AddRef",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
LONG lRet = ++_CRefs;
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "CUrlMon::AddRef (cRefs:%ld)", lRet);
|
|
|
|
DEBUG_LEAVE(lRet);
|
|
return lRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CUrlMon::Release
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [ULONG] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CUrlMon::Release(void)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Dword,
|
|
"CUrlMon::IUnknown::Release",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Release");
|
|
|
|
LONG lRet = --_CRefs;
|
|
|
|
if (_CRefs == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Release (cRefs:%ld)", lRet);
|
|
|
|
DEBUG_LEAVE(lRet);
|
|
return lRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::GetClassID
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pClassID] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::GetClassID(CLSID *pClassID)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IPersist::GetClassID",
|
|
"this=%#x, %#x",
|
|
this, pClassID
|
|
));
|
|
|
|
VDATEPTRIN(pClassID, CLSID);
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::GetClassID");
|
|
|
|
*pClassID = CLSID_StdURLMoniker;
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::GetClassID (hr:%lx)", NOERROR);
|
|
|
|
DEBUG_LEAVE(NOERROR);
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::IsDirty
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::IsDirty()
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IPersistStream::IsDirty",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
|
|
DEBUG_LEAVE(NOERROR);
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::Load
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pistm] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::Load(IStream *pistm)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IPersistStream::Load",
|
|
"this=%#x, %#x",
|
|
this, pistm
|
|
));
|
|
|
|
VDATEIFACE(pistm);
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Load");
|
|
HRESULT hr = NOERROR;
|
|
ULONG cbLen = 0;
|
|
|
|
// Read in the new URL from the stream
|
|
hr = pistm->Read(&cbLen, sizeof(ULONG), NULL);
|
|
|
|
if ((hr == NOERROR) && (cbLen > 0))
|
|
{
|
|
LPWSTR wszUrlLocal = new WCHAR [cbLen / sizeof(WCHAR)];
|
|
DbgLog2(tagCUrlMon, this, "=== CUrlMon::Load (cbBytes:%ld, cbLen:%ld)", cbLen, cbLen / sizeof(WCHAR));
|
|
|
|
if (wszUrlLocal)
|
|
{
|
|
hr = pistm->Read(wszUrlLocal, cbLen, NULL);
|
|
DbgLog2(tagCUrlMon, this, "=== CUrlMon::Load (cbLen:%ld, hr:%lx)", cbLen, hr);
|
|
|
|
if (hr == NOERROR)
|
|
{
|
|
// If we already had a URL, delete it
|
|
if (_pwzUrl)
|
|
{
|
|
delete [] _pwzUrl;
|
|
}
|
|
|
|
_pwzUrl = wszUrlLocal;
|
|
}
|
|
else
|
|
{
|
|
delete [] wszUrlLocal;
|
|
}
|
|
}
|
|
}
|
|
|
|
PerfDbgLog2(tagCUrlMon, this, "-CUrlMon::Load (hr:%lx, szUrl:%ws)", hr, _pwzUrl?_pwzUrl:L"");
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::Save
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pistm] --
|
|
// [fClearDirty] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::Save(IStream *pistm, BOOL fClearDirty)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IPersistStream::Save",
|
|
"this=%#x, %#x, %B",
|
|
this, pistm, fClearDirty
|
|
));
|
|
|
|
VDATEIFACE(pistm);
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Save");
|
|
UrlMkAssert((_pwzUrl));
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (_pwzUrl)
|
|
{
|
|
ULONG cbLen = (wcslen(_pwzUrl) + 1) * sizeof(WCHAR);
|
|
DbgLog2(tagCUrlMon, this, "=== CUrlMon::Save (cbLen:%ld, cbLen:%ld)", cbLen, cbLen / sizeof(WCHAR));
|
|
|
|
// Write the URL to the stream
|
|
hr = pistm->Write(&cbLen, sizeof(ULONG), NULL);
|
|
if (hr == NOERROR)
|
|
{
|
|
hr = pistm->Write(_pwzUrl, cbLen, NULL);
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Save (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::GetSizeMax
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pcbSize] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::GetSizeMax(ULARGE_INTEGER *pcbSize)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IPersistStream::GetSizeMax",
|
|
"this=%#x, %#x",
|
|
this, pcbSize
|
|
));
|
|
|
|
VDATEPTROUT (pcbSize, ULONG);
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::GetSizeMax");
|
|
|
|
UrlMkAssert((_pwzUrl));
|
|
UrlMkAssert((pcbSize));
|
|
|
|
// length of url
|
|
ULISet32(*pcbSize, ((wcslen(_pwzUrl) + 1) * sizeof(WCHAR)) + sizeof(ULONG));
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::GetSizeMax (hr:%lx)", NOERROR);
|
|
|
|
DEBUG_LEAVE(NOERROR);
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::BindToObject
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pbc] --
|
|
// [pmkToLeft] --
|
|
// [riidRes] --
|
|
// [ppvRes] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::BindToObject(IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riidRes, void **ppvRes)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::BindToObject",
|
|
"this=%#x, %#x, %#x, %#x, %#x",
|
|
this, pbc, pmkToLeft, &riidRes, ppvRes
|
|
));
|
|
|
|
VDATEPTROUT(ppvRes, LPVOID);
|
|
VDATEIFACE(pbc);
|
|
PerfDbgLog2(tagCUrlMon, this, "+CUrlMon::BindToObject (IBindCtx:%lx, pmkToLeft:%lx)", pbc, pmkToLeft);
|
|
|
|
*ppvRes = NULL;
|
|
if (pmkToLeft)
|
|
{
|
|
VDATEIFACE(pmkToLeft);
|
|
}
|
|
|
|
HRESULT hr;
|
|
CLSID clsid;
|
|
BIND_OPTS bindopts;
|
|
CBinding *pCBdg = NULL;
|
|
CBSC *pBSC = NULL;
|
|
WCHAR wzURL[MAX_URL_SIZE + 1];
|
|
|
|
*ppvRes = NULL;
|
|
|
|
// Step 1: check if the object is runining
|
|
// if so QI for the requested interface
|
|
//
|
|
{
|
|
IRunningObjectTable *pROT = NULL;
|
|
// check if the object is already running
|
|
hr = IsRunningROT(pbc, pmkToLeft, &pROT);
|
|
if (hr == NOERROR)
|
|
{
|
|
// object is running
|
|
IUnknown *pUnk = NULL;
|
|
|
|
// object is running
|
|
// get the object and Qi for the requested interface
|
|
hr = pROT->GetObject(this, &pUnk);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pUnk->QueryInterface(riidRes, ppvRes);
|
|
pUnk->Release();
|
|
}
|
|
|
|
pROT->Release();
|
|
goto End;
|
|
}
|
|
else
|
|
{
|
|
if (pROT)
|
|
{
|
|
pROT->Release();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
// did not get ROT!!
|
|
goto End;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Step 2: get the bind options from the bind context
|
|
bindopts.cbStruct = sizeof(BIND_OPTS);
|
|
hr = pbc->GetBindOptions(&bindopts);
|
|
if (FAILED(hr))
|
|
{
|
|
goto End;
|
|
}
|
|
|
|
// Step 3: create a CBinding and releated objects and
|
|
// start a transaction
|
|
|
|
|
|
hr = StartBinding(TRUE, pbc, pmkToLeft, riidRes, ppvRes);
|
|
|
|
End:
|
|
|
|
PerfDbgLog2(tagCUrlMon, this, "-CUrlMon::BindToObject (hr:%lx, ppvobj:%lx)",
|
|
hr, (hr == S_OK) ? *ppvRes : NULL);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::BindToStorage
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pbc] --
|
|
// [pmkToLeft] --
|
|
// [riid] --
|
|
// [ppvObj] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::BindToStorage(IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, void **ppvObj)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::BindToStorage",
|
|
"this=%#x, %#x, %#x, %#x, %#x",
|
|
this, pbc, pmkToLeft, &riid, ppvObj
|
|
));
|
|
|
|
VDATEPTROUT(ppvObj, LPVOID);
|
|
VDATEIFACE(pbc);
|
|
PerfDbgLog2(tagCUrlMon, this, "+CUrlMon::BindToStorage (IBindCtx:%lx, pmkToLeft:%lx)", pbc, pmkToLeft);
|
|
|
|
if (pmkToLeft)
|
|
{
|
|
VDATEIFACE(pmkToLeft);
|
|
}
|
|
CBSC *pBSC = NULL;
|
|
HRESULT hr;
|
|
BIND_OPTS bindopts;
|
|
CBinding *pCBdg = NULL;
|
|
FORMATETC fetc;
|
|
WCHAR wzURL[MAX_URL_SIZE + 1];
|
|
|
|
IID iidLocal = riid;
|
|
|
|
*ppvObj = NULL;
|
|
|
|
#if DBG==1
|
|
{
|
|
LPOLESTR pszStr;
|
|
StringFromCLSID(riid, &pszStr);
|
|
DbgLog2(tagCUrlMon, this, "CUrlMon::BindToStorage (szUrl:%ws)(iid:%ws)",
|
|
GetUrl(), pszStr);
|
|
delete pszStr;
|
|
}
|
|
#endif
|
|
|
|
hr = StartBinding(FALSE, pbc, pmkToLeft, riid, ppvObj);
|
|
|
|
PerfDbgLog2(tagCUrlMon, this, "-CUrlMon::BindToStorage (hr:%lx, ppvobj:%lx)",
|
|
hr, (hr == S_OK) ? *ppvObj : NULL);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::StartBinding
|
|
//
|
|
// Synopsis: sets up the cbinding and starts the transaction
|
|
//
|
|
// Arguments: [fBindToObject] --
|
|
// [pbc] --
|
|
// [pmkToLeft] --
|
|
// [riid] --
|
|
// [ppvObj] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 8-20-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::StartBinding(BOOL fBindToObject, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, void **ppvObj)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::StartBinding",
|
|
"this=%#x, %B, %#x, %#x, %#x, %#x",
|
|
this, fBindToObject, pbc, pmkToLeft, &riid, ppvObj
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::StartBinding");
|
|
|
|
HRESULT hr = NOERROR;
|
|
WCHAR wzURL[MAX_URL_SIZE + 1];
|
|
CBSC *pBSC = NULL;
|
|
CBinding *pCBdg = NULL;
|
|
BOOL fUnknown = FALSE;
|
|
|
|
do
|
|
{
|
|
// No need to canonicalize URL here. This should have already been done
|
|
// by CreateURLMoniker.
|
|
|
|
hr = ConstructURL(pbc, NULL, pmkToLeft, GetUrl(), wzURL, sizeof(wzURL),CU_NO_CANONICALIZE);
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// moved to CBinding::StartBinding
|
|
// BUG-WORK
|
|
//if (!IsOInetProtocol(pbc, wzURL))
|
|
//{
|
|
// hr = INET_E_UNKNOWN_PROTOCOL;
|
|
// break;
|
|
//}
|
|
|
|
// check if a BSC is registerted if not register our own one - for Office!
|
|
IUnknown *pUnk = NULL;
|
|
hr = GetObjectParam(pbc, REG_BSCB_HOLDER, IID_IBindStatusCallback, (IUnknown**)&pUnk);
|
|
if ((hr == NOERROR) && pUnk)
|
|
{
|
|
// release - nothing to do
|
|
pUnk->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = NOERROR;
|
|
if (fBindToObject)
|
|
{
|
|
pBSC = new CBSC(Medium_Unknown);
|
|
}
|
|
else
|
|
{
|
|
Medium medium = (riid == IID_IStorage) ? Medium_Storage : Medium_Stream;
|
|
pBSC = new CBSC(medium);
|
|
if (medium == Medium_Storage)
|
|
{
|
|
fUnknown = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
// no IBSC - create our own one and register
|
|
if (pBSC)
|
|
{
|
|
hr = RegisterBindStatusCallback(pbc, pBSC, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
}
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
break;
|
|
}
|
|
// Create a CBinding object
|
|
hr = CBinding::Create(NULL, wzURL, pbc, (fUnknown) ? IID_IUnknown : riid, fBindToObject, &pCBdg);
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
UrlMkAssert((pCBdg != NULL));
|
|
|
|
if (fBindToObject)
|
|
{
|
|
pCBdg->SetMoniker(this);
|
|
}
|
|
|
|
{
|
|
LPWSTR pwzExtra = NULL;
|
|
// start the transaction now
|
|
hr = pCBdg->StartBinding(wzURL, pbc, (fUnknown) ? IID_IUnknown : riid, fBindToObject, &pwzExtra, ppvObj);
|
|
|
|
if (pwzExtra)
|
|
{
|
|
SetUrl(GetUrl(), pwzExtra);
|
|
}
|
|
}
|
|
|
|
if( hr == INET_E_USE_EXTEND_BINDING )
|
|
{
|
|
// rosebud
|
|
hr = NOERROR;
|
|
|
|
// there is no need to return IBinding to client, se should
|
|
// free it here.
|
|
pCBdg->Release();
|
|
break;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (pCBdg->IsAsyncTransaction() == FALSE)
|
|
{
|
|
hr = pCBdg->CompleteTransaction();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// retrieve the requested object
|
|
if (pBSC)
|
|
{
|
|
hr = pBSC->GetRequestedObject(pbc, ppvObj);
|
|
}
|
|
else
|
|
{
|
|
hr = pCBdg->GetRequestedObject(pbc, (IUnknown **)ppvObj);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = pCBdg->GetRequestedObject(pbc, (IUnknown **)ppvObj);
|
|
}
|
|
}
|
|
|
|
// in case the transaction could not be started,
|
|
// the following release we terminate all releated objects
|
|
pCBdg->Release();
|
|
|
|
break;
|
|
} while (TRUE);
|
|
|
|
if (pBSC)
|
|
{
|
|
RevokeBindStatusCallback(pbc, pBSC);
|
|
pBSC->Release();
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::StartBinding (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::Reduce
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pbc] --
|
|
// [dwReduceHowFar] --
|
|
// [IMoniker] --
|
|
// [ppmkReduced] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::Reduce(IBindCtx *pbc, DWORD dwReduceHowFar,
|
|
IMoniker **ppmkToLeft,IMoniker **ppmkReduced)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::Reduce",
|
|
"this=%#x, %#x, %#x, %#x, %#x",
|
|
this, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Reduce");
|
|
|
|
// There is nothing we can do to reduce our moniker
|
|
*ppmkReduced = this;
|
|
AddRef();
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Reduce (hr:%lx)", MK_S_REDUCED_TO_SELF);
|
|
|
|
DEBUG_LEAVE(MK_S_REDUCED_TO_SELF);
|
|
return MK_S_REDUCED_TO_SELF;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::ComposeWith
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pmkRight] --
|
|
// [fOnlyIfNotGeneric] --
|
|
// [ppmkComposite] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::ComposeWith(IMoniker *pmkRight, BOOL fOnlyIfNotGeneric, IMoniker **ppmkComposite)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::ComposeWith",
|
|
"this=%#x, %#x, %B, %#x",
|
|
this, pmkRight, fOnlyIfNotGeneric, ppmkComposite
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::ComposeWith");
|
|
VDATEIFACE(pmkRight);
|
|
VDATEPTROUT(ppmkComposite, LPMONIKER);
|
|
HRESULT hr = NOERROR;
|
|
DWORD dwMnk = 0;
|
|
LPWSTR wzURLRelative = NULL;
|
|
|
|
*ppmkComposite = NULL;
|
|
|
|
pmkRight->IsSystemMoniker(&dwMnk);
|
|
if (dwMnk == MKSYS_URLMONIKER)
|
|
{
|
|
hr = pmkRight->GetDisplayName(NULL, NULL, &wzURLRelative);
|
|
if (hr == NOERROR)
|
|
{
|
|
hr = CreateURLMoniker(this, wzURLRelative, ppmkComposite);
|
|
}
|
|
}
|
|
else if (fOnlyIfNotGeneric)
|
|
{
|
|
hr = MK_E_NEEDGENERIC;
|
|
}
|
|
else
|
|
{
|
|
hr = CreateGenericComposite(this, pmkRight, ppmkComposite);
|
|
}
|
|
if (wzURLRelative)
|
|
{
|
|
delete wzURLRelative;
|
|
}
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "-CUrlMon::ComposeWith");
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::Enum
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [fForward] --
|
|
// [ppenumMoniker] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::Enum(BOOL fForward, IEnumMoniker **ppenumMoniker)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::Enum",
|
|
"this=%#x, %B, %#x",
|
|
this, fForward, ppenumMoniker
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Enum");
|
|
VDATEPTROUT(ppenumMoniker, LPENUMMONIKER);
|
|
*ppenumMoniker = NULL;
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "-CUrlMon::Enum (hr:0)");
|
|
|
|
DEBUG_LEAVE(NOERROR);
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::IsEqual
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pMnkOther] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
// REVIEW: this code will not work cross process. What is the
|
|
// correct implementation?
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::IsEqual(IMoniker *pMnkOther)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::IsEqual",
|
|
"this=%#x, %#x",
|
|
this, pMnkOther
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::IsEqual");
|
|
HRESULT hr = S_FALSE;
|
|
VDATEIFACE(pMnkOther);
|
|
|
|
// We only worry about URL monikers
|
|
if (this == pMnkOther)
|
|
{
|
|
// same object
|
|
hr = NOERROR;
|
|
}
|
|
else if (IsUrlMoniker(pMnkOther))
|
|
{
|
|
LPWSTR szDispName = NULL;
|
|
// The other moniker is a URL moniker.
|
|
// get and compare the display names
|
|
hr = pMnkOther->GetDisplayName(NULL, NULL, &szDispName);
|
|
// Compare the URL's
|
|
if (hr == NOERROR)
|
|
{
|
|
UrlMkAssert((_pwzUrl));
|
|
UrlMkAssert((szDispName));
|
|
|
|
hr = wcscmp(_pwzUrl, szDispName) ? S_FALSE : NOERROR;
|
|
}
|
|
|
|
if (szDispName)
|
|
{
|
|
delete szDispName;
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::IsEqual (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::Hash
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pdwHash] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// 9-02-95 AdriaanC (Adriaan Canter)
|
|
// Modified to use Pearson's Method
|
|
//
|
|
// Notes:
|
|
// 32 bit hashing operator for IMoniker::Hash(DWORD*)
|
|
//
|
|
// Method based upon "Fast Hashing of Variable Length Text Strings" ,
|
|
// by Peter K. Pearson, Communications of the ACM,
|
|
// June 1990 Vol. 33, Number 6. pp 677-680.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::Hash(DWORD* pdwHash)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::Hash",
|
|
"this=%#x, %#x",
|
|
this, pdwHash
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Hash");
|
|
UrlMkAssert((_pwzUrl != NULL));
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
UCHAR c0, c1, c2, c3;
|
|
UCHAR* idx = (UCHAR*) _pwzUrl;
|
|
|
|
static UCHAR T[256] =
|
|
{
|
|
1, 14,110, 25, 97,174,132,119,138,170,125,118, 27,233,140, 51,
|
|
87,197,177,107,234,169, 56, 68, 30, 7,173, 73,188, 40, 36, 65,
|
|
49,213,104,190, 57,211,148,223, 48,115, 15, 2, 67,186,210, 28,
|
|
12,181,103, 70, 22, 58, 75, 78,183,167,238,157,124,147,172,144,
|
|
176,161,141, 86, 60, 66,128, 83,156,241, 79, 46,168,198, 41,254,
|
|
178, 85,253,237,250,154,133, 88, 35,206, 95,116,252,192, 54,221,
|
|
102,218,255,240, 82,106,158,201, 61, 3, 89, 9, 42,155,159, 93,
|
|
166, 80, 50, 34,175,195,100, 99, 26,150, 16,145, 4, 33, 8,189,
|
|
121, 64, 77, 72,208,245,130,122,143, 55,105,134, 29,164,185,194,
|
|
193,239,101,242, 5,171,126, 11, 74, 59,137,228,108,191,232,139,
|
|
6, 24, 81, 20,127, 17, 91, 92,251,151,225,207, 21, 98,113,112,
|
|
84,226, 18,214,199,187, 13, 32, 94,220,224,212,247,204,196, 43,
|
|
249,236, 45,244,111,182,153,136,129, 90,217,202, 19,165,231, 71,
|
|
230,142, 96,227, 62,179,246,114,162, 53,160,215,205,180, 47,109,
|
|
44, 38, 31,149,135, 0,216, 52, 63, 23, 37, 69, 39,117,146,184,
|
|
163,200,222,235,248,243,219, 10,152,131,123,229,203, 76,120,209
|
|
};
|
|
|
|
c0 = T[*idx];
|
|
c1 = T[*idx+1 % 256];
|
|
c2 = T[*idx+2 % 256];
|
|
c3 = T[*idx+3 % 256];
|
|
|
|
#ifndef unix
|
|
while ((WCHAR) *(WCHAR*) ++idx != L'\0')
|
|
#else
|
|
// We are trying to cast a UCHAR as a WCHAR in the windows code. We will need
|
|
// to handle alignments correctly here, as we cant randomly cast
|
|
// a UCHAR * to a WCHAR *.
|
|
WCHAR wend = 0;
|
|
while (memcmp(++idx,&wend,sizeof(WCHAR)))
|
|
#endif /* unix */
|
|
{
|
|
c0 = T[c0^*idx]; c1 = T[c1^*idx];
|
|
c2 = T[c2^*idx]; c3 = T[c3^*idx];
|
|
}
|
|
|
|
*(((UCHAR*) pdwHash)+0) = c0;
|
|
*(((UCHAR*) pdwHash)+1) = c1;
|
|
*(((UCHAR*) pdwHash)+2) = c2;
|
|
*(((UCHAR*) pdwHash)+3) = c3;
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Hash (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::IsRunning
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pbc] --
|
|
// [pmkToLeft] --
|
|
// [pmkNewlyRunning] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::IsRunning(IBindCtx *pbc, IMoniker *pmkToLeft, IMoniker *pmkNewlyRunning)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::IsRunning",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, pbc, pmkToLeft, pmkNewlyRunning
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::IsRunning");
|
|
HRESULT hr = NOERROR;
|
|
VDATEIFACE(pbc);
|
|
|
|
if (pmkToLeft)
|
|
VDATEIFACE(pmkToLeft);
|
|
if (pmkNewlyRunning)
|
|
VDATEIFACE(pmkNewlyRunning);
|
|
|
|
// This implementation was shamelessly stolen from the OLE sources.
|
|
|
|
if (pmkToLeft == NULL)
|
|
{
|
|
if (pmkNewlyRunning != NULL)
|
|
{
|
|
hr = pmkNewlyRunning->IsEqual(this);
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = IsRunningROT(pbc, NULL, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UrlMkAssert((FALSE));
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::IsRunning (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::GetTimeOfLastChange
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pbc] --
|
|
// [pmkToLeft] --
|
|
// [pFileTime] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::GetTimeOfLastChange(IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pFileTime)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::GetTimeOfLastChange",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, pbc, pmkToLeft, pFileTime
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::GetTimeOfLastChange");
|
|
VDATEIFACE(pbc);
|
|
if (pmkToLeft)
|
|
{
|
|
VDATEIFACE(pmkToLeft);
|
|
}
|
|
VDATEPTROUT(pFileTime, FILETIME);
|
|
|
|
HRESULT hr = MK_E_UNAVAILABLE;
|
|
IRunningObjectTable *pROT;
|
|
|
|
hr = pbc->GetRunningObjectTable(&pROT);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pROT->GetTimeOfLastChange(this, pFileTime);
|
|
pROT->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = MK_E_UNAVAILABLE;
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::GetTimeOfLastChange (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::Inverse
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [ppmk] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-16-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes: urlmon does not have aninverse
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::Inverse(IMoniker **ppmk)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::Inverse",
|
|
"this=%#x, %#x",
|
|
this, ppmk
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Inverse");
|
|
VDATEPTROUT(ppmk, LPMONIKER);
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Inverse (hr:%lx)", MK_E_NOINVERSE);
|
|
|
|
DEBUG_LEAVE(MK_E_NOINVERSE);
|
|
return MK_E_NOINVERSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::CommonPrefixWith
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pmkOther] --
|
|
// [ppmkPrefix] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::CommonPrefixWith(IMoniker *pmkOther, IMoniker **ppmkPrefix)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::CommonPrefixWith",
|
|
"this=%#x, %#x, %#x",
|
|
this, pmkOther, ppmkPrefix
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::CommonPrefixWith");
|
|
HRESULT hr = E_NOTIMPL;
|
|
VDATEPTROUT(ppmkPrefix, LPMONIKER);
|
|
*ppmkPrefix = NULL;
|
|
VDATEIFACE(pmkOther);
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::CommonPrefixWith (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::RelativePathTo
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pmkOther] --
|
|
// [ppmkRelPath] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-16-96 JohannP (Johann Posch) Created
|
|
// 8-20-96 ClarG (Clarence Glasse) Implemented
|
|
//
|
|
// Notes: Code is based on composition algorithm in rfc 1808 (this code does
|
|
// the reverse of that).
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::RelativePathTo(IMoniker *pmkOther, IMoniker **ppmkRelPath)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::RelativePathTo",
|
|
"this=%#x, %#x, %#x",
|
|
this, pmkOther, ppmkRelPath
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::RelativePathTo");
|
|
HRESULT hr = NOERROR;
|
|
VDATEPTROUT(ppmkRelPath, LPMONIKER);
|
|
*ppmkRelPath = NULL;
|
|
VDATEIFACE(pmkOther);
|
|
|
|
CUrl *pUrlThis = NULL;
|
|
CUrl *pUrlOther = NULL;
|
|
LPSTR pch = NULL;
|
|
LPSTR pszQueryThis = NULL;
|
|
LPSTR pszQueryOther = NULL;
|
|
LPSTR pszParamsThis = NULL;
|
|
LPSTR pszParamsOther = NULL;
|
|
|
|
char szRelPath[MAX_URL_SIZE + 1];
|
|
|
|
if (!_pwzUrl)
|
|
{
|
|
hr = MK_E_NOTBINDABLE;
|
|
goto End;
|
|
}
|
|
|
|
if (IsEqual(pmkOther) == S_OK)
|
|
{
|
|
// we are equal to pmkOther, so create an empty path URL moniker.
|
|
if ((*ppmkRelPath = CreateEmptyPathUrlMon()) == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto End;
|
|
}
|
|
// CUrlmon has refcount of 1 now
|
|
}
|
|
else if (IsUrlMoniker(pmkOther))
|
|
{
|
|
if ((hr = HrCreateCUrlFromUrlMon(pmkOther, TRUE, &pUrlOther)) != NOERROR)
|
|
{
|
|
if (hr == MK_E_SYNTAX)
|
|
hr = MK_E_NOTBINDABLE;
|
|
goto End;
|
|
}
|
|
|
|
if ((hr = HrCreateCUrlFromUrlStr(_pwzUrl, TRUE, &pUrlThis)) != NOERROR)
|
|
{
|
|
if (hr == MK_E_SYNTAX)
|
|
hr = MK_E_NOTBINDABLE;
|
|
goto End;
|
|
}
|
|
|
|
// Each URL has been parsed into its separate components.
|
|
// Now compute the relative path.
|
|
if ((pUrlThis->_dwProto == DLD_PROTOCOL_NONE) ||
|
|
(pUrlOther->_dwProto == DLD_PROTOCOL_NONE))
|
|
{
|
|
// Unrecognized protocol; return MK_S_HIM or MK_E_NOTBINDABLE
|
|
if (pUrlThis->_pszProtocol[0] && pUrlOther->_pszProtocol[0])
|
|
{
|
|
*ppmkRelPath = pmkOther;
|
|
pmkOther->AddRef();
|
|
hr = MK_S_HIM;
|
|
}
|
|
else
|
|
{
|
|
hr = MK_E_NOTBINDABLE;
|
|
}
|
|
goto End;
|
|
}
|
|
|
|
// if the scheme and net_loc portion of the url are not equal,
|
|
// return MK_S_HIM
|
|
if ((pUrlThis->_dwProto != pUrlOther->_dwProto) ||
|
|
(lstrcmpi(pUrlThis->_pszServerName, pUrlOther->_pszServerName) != 0) ||
|
|
(pUrlThis->_ipPort != pUrlOther->_ipPort) ||
|
|
(lstrcmpi(pUrlThis->_pszUserName, pUrlOther->_pszUserName) != 0) ||
|
|
(lstrcmpi(pUrlThis->_pszPassword, pUrlOther->_pszPassword) != 0))
|
|
{
|
|
*ppmkRelPath = pmkOther;
|
|
pmkOther->AddRef();
|
|
hr = MK_S_HIM;
|
|
goto End;
|
|
}
|
|
|
|
#ifdef URLMON_RELPATHTO_PARSE_QUERY_PARAMS
|
|
// parse the query and params info
|
|
ParseUrlQuery(pUrlThis->_pszObject, &pszQueryThis);
|
|
ParseUrlQuery(pUrlOther->_pszObject, &pszQueryOther);
|
|
ParseUrlParams(pUrlThis->_pszObject, &pszParamsThis);
|
|
ParseUrlParams(pUrlOther->_pszObject, &pszParamsOther);
|
|
#endif // URLMON_RELPATHTO_PARSE_QUERY_PARAMS
|
|
|
|
// compute the relative path
|
|
hr = HrGetRelativePath(
|
|
pUrlThis->_pszObject, pUrlOther->_pszObject,
|
|
pUrlThis->_dwProto, pUrlThis->_pszServerName, szRelPath);
|
|
if (FAILED(hr))
|
|
goto End;
|
|
|
|
#ifdef URLMON_RELPATHTO_PARSE_QUERY_PARAMS
|
|
// append the appropriate query and params info
|
|
AddParamsAndQueryToRelPath(
|
|
szRelPath, pszParamsThis, pszParamsOther, pszQueryThis, pszQueryOther);
|
|
#endif // URLMON_RELPATHTO_PARSE_QUERY_PARAMS
|
|
|
|
if (szRelPath[0])
|
|
{
|
|
HRESULT hr2 = NOERROR;
|
|
WCHAR wzObjRel[MAX_URL_SIZE + 1];
|
|
|
|
A2W(szRelPath, wzObjRel, MAX_URL_SIZE);
|
|
hr2 = CreateURLMoniker(NULL, wzObjRel, ppmkRelPath);
|
|
if (FAILED(hr2))
|
|
hr = hr2;
|
|
}
|
|
else
|
|
{
|
|
*ppmkRelPath = CreateEmptyPathUrlMon();
|
|
if (!(*ppmkRelPath))
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = MonikerRelativePathTo(this, pmkOther, ppmkRelPath, TRUE);
|
|
}
|
|
|
|
End:
|
|
if (pUrlThis)
|
|
delete pUrlThis;
|
|
if (pUrlOther)
|
|
delete pUrlOther;
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::RelativePathTo (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::GetDisplayName
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pbc] --
|
|
// [pmkToLeft] --
|
|
// [ppszDisplayName] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::GetDisplayName(IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::GetDisplayName",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, pbc, pmkToLeft, ppszDisplayName
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::GetDisplayName");
|
|
HRESULT hr = NOERROR;
|
|
VDATEPTROUT(ppszDisplayName, LPSTR);
|
|
*ppszDisplayName = NULL;
|
|
if (pbc)
|
|
{
|
|
VDATEIFACE(pbc);
|
|
}
|
|
if (pmkToLeft)
|
|
{
|
|
VDATEIFACE(pmkToLeft);
|
|
}
|
|
|
|
*ppszDisplayName = OLESTRDuplicate(_pwzUrl);
|
|
|
|
if (*ppszDisplayName == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
PerfDbgLog2(tagCUrlMon, this, "-CUrlMon::GetDisplayName (hr:%lx) [%ws]", hr, *ppszDisplayName ? *ppszDisplayName : L"");
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::ParseDisplayName
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [IMoniker] --
|
|
// [pmkToLeft] --
|
|
// [ULONG] --
|
|
// [IMoniker] --
|
|
// [ppmkOut] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::ParseDisplayName(IBindCtx *pbc,IMoniker *pmkToLeft,
|
|
LPOLESTR pozDisplayName,ULONG *pchEaten,IMoniker **ppmkOut)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::ParseDisplayName",
|
|
"this=%#x, %#x, %#x, %#x, %#x, %#x",
|
|
this, pbc, pmkToLeft, pozDisplayName, pchEaten, ppmkOut
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::ParseDisplayName");
|
|
|
|
HRESULT hr;
|
|
WCHAR wzURL[MAX_URL_SIZE + 1];
|
|
VDATEPTROUT(ppmkOut, LPMONIKER);
|
|
*ppmkOut = NULL;
|
|
VDATEIFACE(pbc);
|
|
if (pmkToLeft) VDATEIFACE(pmkToLeft);
|
|
VDATEPTRIN(pozDisplayName, char);
|
|
VDATEPTROUT(pchEaten, ULONG);
|
|
|
|
hr = ConstructURL(pbc, this, pmkToLeft, pozDisplayName, wzURL,
|
|
sizeof(wzURL), CU_CANONICALIZE);
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
goto End;
|
|
}
|
|
|
|
if (!wcscmp(_pwzUrl, wzURL))
|
|
{
|
|
// Return ourselves if new URL is the same.
|
|
|
|
*ppmkOut = this;
|
|
AddRef();
|
|
|
|
hr = NOERROR;
|
|
}
|
|
else
|
|
{
|
|
hr = CreateURLMoniker(NULL, wzURL, ppmkOut);
|
|
}
|
|
|
|
if (hr == NOERROR)
|
|
{
|
|
// We have eaten all the characters
|
|
*pchEaten = wcslen(pozDisplayName);
|
|
}
|
|
|
|
End:
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::ParseDisplayName (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::IsSystemMoniker
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pdwMksys] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CUrlMon::IsSystemMoniker(DWORD *pdwMksys)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IMoniker::IsSystemMoniker",
|
|
"this=%#x, %#x",
|
|
this, pdwMksys
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "CUrlMon::IsSystemMoniker");
|
|
VDATEPTROUT(pdwMksys, DWORD);
|
|
*pdwMksys = MKSYS_URLMONIKER;
|
|
|
|
DEBUG_LEAVE(NOERROR);
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
// Delete the URL string if we have one
|
|
void CUrlMon::DeleteUrl()
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
None,
|
|
"CUrlMon::DeleteUrl",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
if (_pwzUrl)
|
|
delete [] _pwzUrl;
|
|
|
|
_pwzUrl = NULL;
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
HRESULT CUrlMon::SetUrl(LPWSTR pwzUrl, LPWSTR pwzExtra)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::SetUrl",
|
|
"this=%#x, %.80wq, %.80wq",
|
|
this, pwzUrl, pwzExtra
|
|
));
|
|
|
|
int clen;
|
|
HRESULT hr = NOERROR;
|
|
|
|
TransAssert((pwzUrl));
|
|
|
|
clen = wcslen(pwzUrl) + 1;
|
|
if (pwzExtra)
|
|
{
|
|
clen += wcslen(pwzExtra);
|
|
}
|
|
LPWSTR pwzStr = (LPWSTR) new WCHAR [clen];
|
|
if (pwzStr)
|
|
{
|
|
wcscpy(pwzStr, pwzUrl);
|
|
if (pwzExtra)
|
|
{
|
|
wcscat(pwzStr, pwzExtra);
|
|
}
|
|
if (_pwzUrl)
|
|
{
|
|
delete [] _pwzUrl;
|
|
}
|
|
_pwzUrl = pwzStr;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Helper function for IMoniker::IsRunning and BindToObject.
|
|
// Return NOERROR if running, and S_FALSE if not.
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::IsRunningROT
|
|
//
|
|
// Synopsis: Checks if the moniker is running
|
|
//
|
|
// Arguments: [pbc] --
|
|
// [pmkToLeft] --
|
|
// [ppROT] --
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CUrlMon::IsRunningROT(IBindCtx *pbc, IMoniker *pmkToLeft, IRunningObjectTable **ppROT)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"CUrlMon::IsRunningROT",
|
|
"this=%#x, %#x, %#x, %#x",
|
|
this, pbc, pmkToLeft, ppROT
|
|
));
|
|
|
|
HRESULT hr;
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::IsRunningROT");
|
|
IRunningObjectTable *pROT;
|
|
|
|
hr = pbc->GetRunningObjectTable(&pROT);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pROT->IsRunning(this);
|
|
|
|
if (ppROT != NULL && SUCCEEDED(hr))
|
|
{
|
|
*ppROT = pROT;
|
|
}
|
|
else
|
|
{
|
|
pROT->Release();
|
|
}
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::IsRunningROT (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CUrlMon::IsUrlMoniker
|
|
//
|
|
// Synopsis: Checks if pMk is a URL moniker
|
|
//
|
|
// Arguments: [pMk] -- the moniker to be checked
|
|
//
|
|
// Returns: true if moniker is URL moniker
|
|
//
|
|
// History: 1-19-96 JohannP (Johann Posch) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL CUrlMon::IsUrlMoniker(IMoniker *pMk)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Bool,
|
|
"CUrlMon::IsUrlMoniker",
|
|
"this=%#x, %#x",
|
|
this, pMk
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, this, "+CUrlMon::IsUrlMoniker");
|
|
BOOL fRet = FALSE;
|
|
|
|
if (pMk)
|
|
{
|
|
DWORD dwMnk = 0;
|
|
pMk->IsSystemMoniker(&dwMnk);
|
|
fRet = (dwMnk == MKSYS_URLMONIKER);
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::IsUrlMoniker (fRet:%d)", fRet);
|
|
|
|
DEBUG_LEAVE(fRet);
|
|
return fRet;
|
|
}
|
|
|
|
|
|
// ********** Helper Functions **********
|
|
// These functions are used by RelativePathTo
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateEmptyPathUrlMon
|
|
//
|
|
// Synopsis: Create a UrlMon with empty path "", such that composing it onto
|
|
// a base UrlMon via IMoniker::ComposeWith will yield a moniker
|
|
// equal to the base UrlMon.
|
|
// We don't call CreateUrlMoniker(""), to do this because that will
|
|
// return a UrlMon with path "/". Composing such a moniker onto
|
|
// a base UrlMon out everything after the host name.
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 8-16-96 ClarG (Clarence Glasse) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CUrlMon * CreateEmptyPathUrlMon()
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Pointer,
|
|
"CreateEmptyPathUrlMon",
|
|
NULL
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "+CreateEmptyPathUrlMon");
|
|
CUrlMon * pUMk = NULL;
|
|
LPWSTR pwzUrlEmpty = NULL;
|
|
|
|
// allocate empty string
|
|
if ((pwzUrlEmpty = new WCHAR [1]) == NULL)
|
|
{
|
|
goto End;
|
|
}
|
|
pwzUrlEmpty[0] = 0;
|
|
|
|
if ((pUMk = new CUrlMon(pwzUrlEmpty)) == NULL)
|
|
{
|
|
delete pwzUrlEmpty;
|
|
goto End;
|
|
}
|
|
// pUMk has refcount of 1 now
|
|
|
|
End:
|
|
PerfDbgLog1(tagCUrlMon, NULL, "-CreateEmptyPathUrlMon, pUMk:%lx", pUMk);
|
|
|
|
DEBUG_LEAVE(pUMk);
|
|
return pUMk;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrCreateCUrlFromUrlMon
|
|
//
|
|
// Synopsis: Given a Url moniker pmkUrl, create a CUrl object. Assumes that
|
|
// pmkUrl is indeed a Url moniker.
|
|
//
|
|
// Arguments: [pmkUrl] -- Url moniker
|
|
// [fParseUrl] -- if TRUE, parse the URL.
|
|
// [ppUrl] -- returns created CUrl obj, which caller must delete
|
|
// when finished with it.
|
|
//
|
|
// Returns: NOERROR is successful.
|
|
//
|
|
// History: 8-16-96 ClarG (Clarence Glasse) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT HrCreateCUrlFromUrlMon(LPMONIKER pmkUrl, BOOL fParseUrl, CUrl **ppUrl)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"HrCreateCUrlFromUrlMon",
|
|
"%#x, %B, %#x",
|
|
pmkUrl, fParseUrl, ppUrl
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "+HrCreateCUrlFromUrlMon");
|
|
UrlMkAssert((pmkUrl));
|
|
UrlMkAssert((ppUrl));
|
|
HRESULT hr = NOERROR;
|
|
LPBC pbc = NULL;
|
|
LPWSTR pwzUrl = NULL;
|
|
|
|
if ((*ppUrl = new CUrl) == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto End;
|
|
}
|
|
|
|
if( !(*ppUrl)->CUrlInitAll() )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto End;
|
|
}
|
|
|
|
if ((hr = CreateBindCtx(0, &pbc)) != NOERROR)
|
|
{
|
|
goto End;
|
|
}
|
|
|
|
if ((hr = pmkUrl->GetDisplayName(pbc, NULL, &pwzUrl)) != NOERROR)
|
|
{
|
|
goto End;
|
|
}
|
|
|
|
|
|
W2A(pwzUrl, (*ppUrl)->_pszBaseURL, MAX_URL_SIZE);
|
|
|
|
if (fParseUrl)
|
|
{
|
|
if (!(*ppUrl)->ParseUrl())
|
|
{
|
|
hr = MK_E_SYNTAX;
|
|
goto End;
|
|
}
|
|
}
|
|
|
|
End:
|
|
if (pbc)
|
|
pbc->Release();
|
|
if (pwzUrl)
|
|
CoTaskMemFree(pwzUrl);
|
|
|
|
if ((hr != NOERROR) && (*ppUrl != NULL))
|
|
{
|
|
delete *ppUrl;
|
|
*ppUrl = NULL;
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, NULL, "-HrCreateCUrlFromUrlMon (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrCreateCUrlFromUrlStr
|
|
//
|
|
// Synopsis: Given a Url string pwzUrl, create a CUrl object.
|
|
//
|
|
// Arguments: [pwzUrl] -- Url string
|
|
// [fParseUrl] -- if TRUE, parse the URL.
|
|
// [ppUrl] -- returns created CUrl obj, which caller must delete
|
|
// when finished with it.
|
|
//
|
|
// Returns: NOERROR is successful.
|
|
//
|
|
// History: 8-16-96 ClarG (Clarence Glasse) Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT HrCreateCUrlFromUrlStr(LPCWSTR pwzUrl, BOOL fParseUrl, CUrl **ppUrl)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"HrCreateCUrlFromUrlStr",
|
|
"%.80wq, %B, %#x",
|
|
pwzUrl, fParseUrl, ppUrl
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "+HrCreateCUrlFromUrlStr");
|
|
UrlMkAssert((pwzUrl));
|
|
UrlMkAssert((ppUrl));
|
|
HRESULT hr = NOERROR;
|
|
|
|
if ((*ppUrl = new CUrl) == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto End;
|
|
}
|
|
|
|
if( !(*ppUrl)->CUrlInitAll() )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto End;
|
|
}
|
|
|
|
W2A(pwzUrl, (*ppUrl)->_pszBaseURL, MAX_URL_SIZE);
|
|
|
|
if (fParseUrl)
|
|
{
|
|
if (!(*ppUrl)->ParseUrl())
|
|
{
|
|
hr = MK_E_SYNTAX;
|
|
goto End;
|
|
}
|
|
}
|
|
|
|
End:
|
|
if ((hr != NOERROR) && (*ppUrl != NULL))
|
|
{
|
|
delete *ppUrl;
|
|
*ppUrl = NULL;
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, NULL, "-HrCreateCUrlFromUrlStr (hr:%lx)", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: IsSeparator
|
|
//
|
|
// Synopsis: Return TRUE if ch is a file path or url path separator char.
|
|
//
|
|
// Arguments: [ch] -- the char in question
|
|
// when finished with it.
|
|
//
|
|
// Returns: TRUE if ch is a separator char
|
|
//
|
|
// History: 8-20-96 ClarG (Clarence Glasse) Created
|
|
//
|
|
// Notes: This is taken from OLE2 file moniker code
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline BOOL IsSeparator( char ch )
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Bool,
|
|
"IsSeparator",
|
|
"%c",
|
|
ch
|
|
));
|
|
|
|
BOOL fRet = (ch == '\\' || ch == '/' || ch == ':');
|
|
|
|
DEBUG_LEAVE(fRet);
|
|
return fRet;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CountSegments
|
|
//
|
|
// Synopsis: Return the number of segments in file or url path pch.
|
|
//
|
|
// Arguments: [pch] -- the string in question.
|
|
//
|
|
// Returns: number of segments in pch
|
|
//
|
|
// History: 8-20-96 ClarG (Clarence Glasse) Created
|
|
//
|
|
// Notes: This is taken from OLE2 file moniker code
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
int CountSegments ( LPSTR pch )
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Int,
|
|
"CountSegments",
|
|
"%.80q",
|
|
pch
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "+CountSegments");
|
|
// counts the number of pieces in a path, after the first colon, if
|
|
// there is one
|
|
|
|
int n = 0;
|
|
LPSTR pch1;
|
|
pch1 = pch;
|
|
while (*pch1 != '\0' && *pch1 != ':') IncLpch(pch1);
|
|
if (*pch1 == ':') pch = ++pch1;
|
|
while (*pch != '\0')
|
|
{
|
|
while (*pch && IsSeparator(*pch)) pch++;
|
|
if (*pch) n++;
|
|
while (*pch && (!IsSeparator(*pch))) IncLpch(pch);
|
|
}
|
|
|
|
PerfDbgLog1(tagCUrlMon, NULL, "-CountSegments (n:%ld)", n);
|
|
|
|
DEBUG_LEAVE(n);
|
|
return n;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrGetRelativePath
|
|
//
|
|
// Synopsis: Compute and return relative path from url path
|
|
// lpszBase to url path lpszOther.
|
|
//
|
|
// Arguments: [lpszBase] -- the base path without the scheme and host info
|
|
// [lpszOther] -- the target path without the scheme and host
|
|
// [dwProto] -- DLD_PROTOCOL_XXX value, indicating the scheme
|
|
// of the urls.
|
|
// [lpszHost] -- the host name for the urls
|
|
// [lpszRelPath] -- buffer of size MAX_URL_SIZE that returns the
|
|
// relative path.
|
|
//
|
|
// Returns: NOERROR, MK_S_HIM, MK_E_NOTBINDABLE, or some other hresult.
|
|
//
|
|
// History: 8-20-96 ClarG (Clarence Glasse) Created
|
|
//
|
|
// Notes: This is based on OLE2 file moniker code
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT HrGetRelativePath(
|
|
LPSTR lpszBase, LPSTR lpszOther, DWORD dwProto, LPSTR lpszHost,
|
|
LPSTR lpszRelPath)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
Hresult,
|
|
"HrGetRelativePath",
|
|
"%.80q, %.80q, %#x, %.80q, %.80q",
|
|
lpszBase, lpszOther, dwProto, lpszHost, lpszRelPath
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "+HrGetRelativePath");
|
|
HRESULT hr = NOERROR;
|
|
LPSTR lpszRover;
|
|
LPSTR lpszMarker;
|
|
LPSTR lpch;
|
|
LPSTR lpchStripBaseSav = NULL;
|
|
char ch1;
|
|
char ch2;
|
|
char chStripBaseSav;
|
|
char chNull = '\0';
|
|
int i;
|
|
int cAnti;
|
|
|
|
lpszRelPath[0] = 0;
|
|
|
|
// if neither lpszBase nor lpszRelPath look like absolute url or file
|
|
// paths, return MK_E_NOTBINDALBE
|
|
if (!lpszBase[0] || !lpszOther[0])
|
|
{
|
|
hr = MK_E_NOTBINDABLE;
|
|
goto End;
|
|
}
|
|
|
|
if ((lpszBase[0] != '\\') && (lpszBase[0] != '/') && (lpszBase[1] != ':'))
|
|
{
|
|
hr = MK_E_NOTBINDABLE;
|
|
goto End;
|
|
}
|
|
|
|
if ((lpszOther[0] != '\\') && (lpszOther[0] != '/') && (lpszOther[1] != ':'))
|
|
{
|
|
hr = MK_E_NOTBINDABLE;
|
|
goto End;
|
|
}
|
|
|
|
if (lstrcmpi(lpszBase, lpszOther) == 0)
|
|
{
|
|
// if paths are equal, relative path is empty string
|
|
lpszRelPath[0] = 0;
|
|
hr = NOERROR;
|
|
goto End;
|
|
}
|
|
|
|
// if base does not end in a separator, remove its last piece
|
|
lpch = lpszBase + lstrlen(lpszBase);
|
|
for( ; ((!(IsSeparator(*lpch))) && (lpch > lpszBase)); DecLpch(lpszBase, lpch) );
|
|
if (IsSeparator(*lpch))
|
|
{
|
|
IncLpch(lpch);
|
|
lpchStripBaseSav = lpch;
|
|
chStripBaseSav = *lpch;
|
|
*lpch = '\0';
|
|
}
|
|
|
|
lpszRover = lpszBase;
|
|
lpszMarker = lpszRover;
|
|
i = 0;
|
|
lpszOther = lpszOther;
|
|
|
|
while (*lpszRover != '\0')
|
|
{
|
|
while (*lpszRover && IsSeparator(*lpszRover)) lpszRover++;
|
|
while (*lpszRover && !IsSeparator(*lpszRover)) IncLpch(lpszRover);
|
|
// the first part of the path is between m_szPath and
|
|
// lpszRover
|
|
i = (int) (lpszRover - lpszBase);
|
|
ch1 = *lpszRover;
|
|
ch2 = *(lpszOther + i);
|
|
*lpszRover = '\0';
|
|
*(lpszOther + i) = '\0';
|
|
|
|
if (lstrcmpi(lpszBase, lpszOther) == 0)
|
|
lpszMarker = lpszRover;
|
|
else
|
|
lpszRover = &chNull;
|
|
|
|
*(lpszBase + i) = ch1;
|
|
*(lpszOther + i) = ch2;
|
|
}
|
|
|
|
// common portion is from lpszBase to lpszMarker
|
|
i = (int) (lpszMarker - lpszBase);
|
|
if ((!lpszHost || !lpszHost[0]) && (i == 0))
|
|
{
|
|
lstrcpy(lpszRelPath, lpszOther);
|
|
hr = MK_S_HIM;
|
|
goto End;
|
|
}
|
|
|
|
lpszRover = lpszRelPath;
|
|
while (IsSeparator(*(lpszOther+i))) i++;
|
|
cAnti = CountSegments(lpszMarker);
|
|
|
|
while (cAnti)
|
|
{
|
|
if (dwProto != DLD_PROTOCOL_FILE)
|
|
lstrcpy(lpszRover, "../");
|
|
else
|
|
lstrcpy(lpszRover, "..\\");
|
|
lpszRover += 3;
|
|
cAnti--;
|
|
}
|
|
|
|
lstrcpy(lpszRover, lpszOther + i);
|
|
|
|
End:
|
|
if (lpchStripBaseSav)
|
|
{
|
|
*lpchStripBaseSav = chStripBaseSav;
|
|
}
|
|
|
|
PerfDbgLog2(tagCUrlMon, NULL, "-HrGetRelativePath [%s], hr:%lx", lpszRelPath?lpszRelPath:"", hr);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
#ifdef URLMON_RELPATHTO_PARSE_QUERY_PARAMS
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ParseUrlQuery
|
|
//
|
|
// Synopsis: Parse the Query portion of a url
|
|
//
|
|
// Arguments: [pszURL] -- url to parse; the query portion is "removed" from
|
|
// pszURL when function returns.
|
|
// [ppszQuery] -- returns pointer to query portion of URL
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
// History: 8-20-96 ClarG (Clarence Glasse) Created
|
|
//
|
|
// Notes: This is based on OLE2 file moniker code
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void ParseUrlQuery(LPSTR pszURL, LPSTR *ppszQuery)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
None,
|
|
"ParseUrlQuery",
|
|
"%.80q, %#x",
|
|
pszURL, ppszQuery
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "+ParseUrlQuery");
|
|
LPSTR pch = NULL;
|
|
|
|
*ppszQuery = NULL;
|
|
|
|
for (pch = pszURL; *pch; IncLpch(pch))
|
|
{
|
|
if (*pch == '?')
|
|
{
|
|
*pch = '\0';
|
|
pch++;
|
|
if (*pch)
|
|
*ppszQuery = pch;
|
|
break;
|
|
}
|
|
}
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "-ParseUrlQuery");
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ParseUrlParams
|
|
//
|
|
// Synopsis: Parse the Params portion of a url
|
|
//
|
|
// Arguments: [pszURL] -- url to parse; the params portion is "removed" from
|
|
// pszURL when function returns.
|
|
// [ppszParams] -- returns pointer to params portion of URL
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
// History: 8-20-96 ClarG (Clarence Glasse) Created
|
|
//
|
|
// Notes: This is based on OLE2 file moniker code
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void ParseUrlParams(LPSTR pszURL, LPSTR *ppszParams)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
None,
|
|
"ParseUrlParams",
|
|
"%.80q, %#x",
|
|
pszURL, ppszParams
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "+ParseUrlParams");
|
|
LPSTR pch = NULL;
|
|
|
|
*ppszParams = NULL;
|
|
|
|
for (pch = pszURL; *pch; IncLpch(pch))
|
|
{
|
|
if (*pch == ';')
|
|
{
|
|
*pch = '\0';
|
|
pch++;
|
|
if (*pch)
|
|
*ppszParams = pch;
|
|
break;
|
|
}
|
|
}
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "-ParseUrlParams");
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddParamsAndQueryToRelPath
|
|
//
|
|
// Synopsis: Given a computed relative URL path from a base to a target,
|
|
// append the appropriate Params and Query info.
|
|
//
|
|
// Arguments: [szRelPath] -- computed relative path
|
|
// [pszParamsBase] -- Params info of base URL
|
|
// [pszParamsOther] -- Params info of target URL
|
|
// [pszQueryBase] -- Query info of base URL
|
|
// [pszQueryOther] -- Query info of target URL
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
// History: 8-20-96 ClarG (Clarence Glasse) Created
|
|
//
|
|
// Notes: This is based on OLE2 file moniker code
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void AddParamsAndQueryToRelPath(
|
|
LPSTR szRelPath,
|
|
LPSTR pszParamsBase, LPSTR pszParamsOther,
|
|
LPSTR pszQueryBase, LPSTR pszQueryOther)
|
|
{
|
|
DEBUG_ENTER((DBG_MONIKER,
|
|
None,
|
|
"AddParamsAndQueryToRelPath",
|
|
"%.80q, %.80q, %.80q, %.80q, %.80q",
|
|
szRelPath, pszParamsBase, pszParamsOther, pszQueryBase, pszQueryOther
|
|
));
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "+AddParamsAndQueryToRelPath");
|
|
|
|
if (szRelPath[0])
|
|
{
|
|
if (pszParamsOther)
|
|
{
|
|
lstrcat(szRelPath, ";");
|
|
lstrcat(szRelPath, pszParamsOther);
|
|
}
|
|
if (pszQueryOther)
|
|
{
|
|
lstrcat(szRelPath, "?");
|
|
lstrcat(szRelPath, pszQueryOther);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pszParamsOther &&
|
|
(!pszParamsBase || (lstrcmpi(pszParamsOther, pszParamsBase) != 0)))
|
|
{
|
|
lstrcat(szRelPath, ";");
|
|
lstrcat(szRelPath, pszParamsOther);
|
|
|
|
if (pszQueryOther)
|
|
{
|
|
lstrcat(szRelPath, "?");
|
|
lstrcat(szRelPath, pszQueryOther);
|
|
}
|
|
}
|
|
else if (pszQueryOther &&
|
|
(!pszQueryBase || (lstrcmpi(pszQueryOther, pszQueryBase) != 0)))
|
|
{
|
|
lstrcat(szRelPath, "?");
|
|
lstrcat(szRelPath, pszQueryOther);
|
|
}
|
|
}
|
|
|
|
PerfDbgLog(tagCUrlMon, NULL, "-AddParamsAndQueryToRelPath");
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
#endif // URLMON_RELPATHTO_PARSE_QUERY_PARAMS
|