|
|
//+---------------------------------------------------------------------------
//
// 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
|