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