Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2365 lines
63 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: urlmon.cxx
  7. //
  8. // Contents: contains URL moniker implementation
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 12-11-95 JohannP (Johann Posch) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <trans.h>
  18. #ifndef unix
  19. #include "..\iapp\curl.hxx"
  20. #else
  21. #include "../iapp/curl.hxx"
  22. #endif /* unix */
  23. #include "urlmk.hxx"
  24. PerfDbgTag(tagCUrlMon, "Urlmon", "Log CUrlMon", DEB_URLMON);
  25. BOOL IsOInetProtocol(IBindCtx *pbc, LPCWSTR wzProtocol);
  26. // prototypes of helper functions (used by RelativePathTo)
  27. CUrlMon *CreateEmptyPathUrlMon();
  28. HRESULT HrCreateCUrlFromUrlStr(LPCWSTR pwzUrl, BOOL fParseUrl, CUrl **ppUrl);
  29. HRESULT HrCreateCUrlFromUrlMon(LPMONIKER pmkUrl, BOOL fParseUrl, CUrl **ppUrl);
  30. HRESULT HrGetRelativePath(LPSTR lpszBase, LPSTR lpszOther, DWORD dwProto, LPSTR lpszHost,LPSTR lpszRelPath);
  31. // #define URLMON_RELPATHTO_PARSE_QUERY_PARAMS
  32. #ifdef URLMON_RELPATHTO_PARSE_QUERY_PARAMS
  33. // These are helper routines used by RelativePathTo to deal with the Query
  34. // and Params sub-strings of a URL, according to rfc 1808.
  35. // These routines are not enabled because ComposeWith does not deal with
  36. // these sub-strings in any special way, and we want RelativePathTo to be
  37. // compatible with ComposeWith.
  38. void ParseUrlQuery(LPSTR pszURL, LPSTR *ppszQuery);
  39. void ParseUrlParams(LPSTR pszURL, LPSTR *ppszParams);
  40. void AddParamsAndQueryToRelPath(LPSTR szRelPath,
  41. LPSTR pszParamsBase, LPSTR pszParamsOther,
  42. LPSTR pszQueryBase, LPSTR pszQueryOther);
  43. #endif // URLMON_RELPATHTO_PARSE_QUERY_PARAMS
  44. // Macros for Double-Byte Character Support (DBCS)
  45. #if 1
  46. // Beware of double evaluation
  47. #define IncLpch(sz) ((sz)=CharNext((sz)))
  48. #define DecLpch(szStart, sz) ((sz)=CharPrev ((szStart),(sz)))
  49. #else
  50. #define IncLpch(sz) (++(sz))
  51. #define DecLpch(szStart,sz) (--(sz))
  52. #endif
  53. CUrlMon::CUrlMon(LPWSTR pszUrl) : _CRefs()
  54. {
  55. DEBUG_ENTER((DBG_MONIKER,
  56. None,
  57. "CUrlMon::CUrlMon",
  58. "this=%#x",
  59. this
  60. ));
  61. _pwzUrl = pszUrl;
  62. DllAddRef();
  63. DEBUG_LEAVE(0);
  64. }
  65. CUrlMon::~CUrlMon()
  66. {
  67. DEBUG_ENTER((DBG_MONIKER,
  68. None,
  69. "CUrlMon::~CUrlMon",
  70. "this=%#x",
  71. this
  72. ));
  73. if (_pwzUrl)
  74. {
  75. delete [] _pwzUrl;
  76. }
  77. DllRelease();
  78. DEBUG_LEAVE(0);
  79. }
  80. //+---------------------------------------------------------------------------
  81. //
  82. // Method: CUrlMon::QueryInterface
  83. //
  84. // Synopsis:
  85. //
  86. // Arguments: [riid] --
  87. // [ppvObj] --
  88. //
  89. // Returns:
  90. //
  91. // History: 1-19-96 JohannP (Johann Posch) Created
  92. //
  93. // Notes:
  94. //
  95. //----------------------------------------------------------------------------
  96. STDMETHODIMP CUrlMon::QueryInterface(REFIID riid, void **ppvObj)
  97. {
  98. DEBUG_ENTER((DBG_MONIKER,
  99. Hresult,
  100. "CUrlMon::IUnknown::QueryInterface",
  101. "this=%#x, %#x, %#x",
  102. this, &riid, ppvObj
  103. ));
  104. VDATEPTROUT(ppvObj, void *);
  105. HRESULT hr = NOERROR;
  106. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::QueryInterface");
  107. if ( riid == IID_IUnknown
  108. || riid == IID_IMoniker
  109. || riid == IID_IAsyncMoniker
  110. || riid == IID_IPersist
  111. || riid == IID_IPersistStream)
  112. {
  113. *ppvObj = this;
  114. }
  115. else if (riid == IID_IROTData)
  116. {
  117. *ppvObj = (void*)(IROTData *) this;
  118. }
  119. else if (riid == IID_IMarshal)
  120. {
  121. *ppvObj = (void*) (IMarshal *) this;
  122. }
  123. else
  124. {
  125. *ppvObj = NULL;
  126. hr = E_NOINTERFACE;
  127. }
  128. if (hr == NOERROR)
  129. {
  130. AddRef();
  131. }
  132. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::QueryInterface (hr:%lx)", hr);
  133. DEBUG_LEAVE(hr);
  134. return hr;
  135. }
  136. //+---------------------------------------------------------------------------
  137. //
  138. // Function: CUrlMon::AddRef
  139. //
  140. // Synopsis:
  141. //
  142. // Arguments: [ULONG] --
  143. //
  144. // Returns:
  145. //
  146. // History: 1-19-96 JohannP (Johann Posch) Created
  147. //
  148. // Notes:
  149. //
  150. //----------------------------------------------------------------------------
  151. STDMETHODIMP_(ULONG) CUrlMon::AddRef(void)
  152. {
  153. DEBUG_ENTER((DBG_MONIKER,
  154. Dword,
  155. "CUrlMon::IUnknown::AddRef",
  156. "this=%#x",
  157. this
  158. ));
  159. LONG lRet = ++_CRefs;
  160. PerfDbgLog1(tagCUrlMon, this, "CUrlMon::AddRef (cRefs:%ld)", lRet);
  161. DEBUG_LEAVE(lRet);
  162. return lRet;
  163. }
  164. //+---------------------------------------------------------------------------
  165. //
  166. // Function: CUrlMon::Release
  167. //
  168. // Synopsis:
  169. //
  170. // Arguments: [ULONG] --
  171. //
  172. // Returns:
  173. //
  174. // History: 1-19-96 JohannP (Johann Posch) Created
  175. //
  176. // Notes:
  177. //
  178. //----------------------------------------------------------------------------
  179. STDMETHODIMP_(ULONG) CUrlMon::Release(void)
  180. {
  181. DEBUG_ENTER((DBG_MONIKER,
  182. Dword,
  183. "CUrlMon::IUnknown::Release",
  184. "this=%#x",
  185. this
  186. ));
  187. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Release");
  188. LONG lRet = --_CRefs;
  189. if (_CRefs == 0)
  190. {
  191. delete this;
  192. }
  193. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Release (cRefs:%ld)", lRet);
  194. DEBUG_LEAVE(lRet);
  195. return lRet;
  196. }
  197. //+---------------------------------------------------------------------------
  198. //
  199. // Method: CUrlMon::GetClassID
  200. //
  201. // Synopsis:
  202. //
  203. // Arguments: [pClassID] --
  204. //
  205. // Returns:
  206. //
  207. // History: 1-19-96 JohannP (Johann Posch) Created
  208. //
  209. // Notes:
  210. //
  211. //----------------------------------------------------------------------------
  212. STDMETHODIMP CUrlMon::GetClassID(CLSID *pClassID)
  213. {
  214. DEBUG_ENTER((DBG_MONIKER,
  215. Hresult,
  216. "CUrlMon::IPersist::GetClassID",
  217. "this=%#x, %#x",
  218. this, pClassID
  219. ));
  220. VDATEPTRIN(pClassID, CLSID);
  221. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::GetClassID");
  222. *pClassID = CLSID_StdURLMoniker;
  223. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::GetClassID (hr:%lx)", NOERROR);
  224. DEBUG_LEAVE(NOERROR);
  225. return NOERROR;
  226. }
  227. //+---------------------------------------------------------------------------
  228. //
  229. // Method: CUrlMon::IsDirty
  230. //
  231. // Synopsis:
  232. //
  233. // Arguments: (none)
  234. //
  235. // Returns:
  236. //
  237. // History: 1-19-96 JohannP (Johann Posch) Created
  238. //
  239. // Notes:
  240. //
  241. //----------------------------------------------------------------------------
  242. STDMETHODIMP CUrlMon::IsDirty()
  243. {
  244. DEBUG_ENTER((DBG_MONIKER,
  245. Hresult,
  246. "CUrlMon::IPersistStream::IsDirty",
  247. "this=%#x",
  248. this
  249. ));
  250. DEBUG_LEAVE(NOERROR);
  251. return NOERROR;
  252. }
  253. //+---------------------------------------------------------------------------
  254. //
  255. // Method: CUrlMon::Load
  256. //
  257. // Synopsis:
  258. //
  259. // Arguments: [pistm] --
  260. //
  261. // Returns:
  262. //
  263. // History: 1-19-96 JohannP (Johann Posch) Created
  264. //
  265. // Notes:
  266. //
  267. //----------------------------------------------------------------------------
  268. STDMETHODIMP CUrlMon::Load(IStream *pistm)
  269. {
  270. DEBUG_ENTER((DBG_MONIKER,
  271. Hresult,
  272. "CUrlMon::IPersistStream::Load",
  273. "this=%#x, %#x",
  274. this, pistm
  275. ));
  276. VDATEIFACE(pistm);
  277. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Load");
  278. HRESULT hr = NOERROR;
  279. ULONG cbLen = 0;
  280. // Read in the new URL from the stream
  281. hr = pistm->Read(&cbLen, sizeof(ULONG), NULL);
  282. if ((hr == NOERROR) && (cbLen > 0))
  283. {
  284. LPWSTR wszUrlLocal = new WCHAR [cbLen / sizeof(WCHAR)];
  285. DbgLog2(tagCUrlMon, this, "=== CUrlMon::Load (cbBytes:%ld, cbLen:%ld)", cbLen, cbLen / sizeof(WCHAR));
  286. if (wszUrlLocal)
  287. {
  288. hr = pistm->Read(wszUrlLocal, cbLen, NULL);
  289. DbgLog2(tagCUrlMon, this, "=== CUrlMon::Load (cbLen:%ld, hr:%lx)", cbLen, hr);
  290. if (hr == NOERROR)
  291. {
  292. // If we already had a URL, delete it
  293. if (_pwzUrl)
  294. {
  295. delete [] _pwzUrl;
  296. }
  297. _pwzUrl = wszUrlLocal;
  298. }
  299. else
  300. {
  301. delete [] wszUrlLocal;
  302. }
  303. }
  304. }
  305. PerfDbgLog2(tagCUrlMon, this, "-CUrlMon::Load (hr:%lx, szUrl:%ws)", hr, _pwzUrl?_pwzUrl:L"");
  306. DEBUG_LEAVE(hr);
  307. return hr;
  308. }
  309. //+---------------------------------------------------------------------------
  310. //
  311. // Method: CUrlMon::Save
  312. //
  313. // Synopsis:
  314. //
  315. // Arguments: [pistm] --
  316. // [fClearDirty] --
  317. //
  318. // Returns:
  319. //
  320. // History: 1-19-96 JohannP (Johann Posch) Created
  321. //
  322. // Notes:
  323. //
  324. //----------------------------------------------------------------------------
  325. STDMETHODIMP CUrlMon::Save(IStream *pistm, BOOL fClearDirty)
  326. {
  327. DEBUG_ENTER((DBG_MONIKER,
  328. Hresult,
  329. "CUrlMon::IPersistStream::Save",
  330. "this=%#x, %#x, %B",
  331. this, pistm, fClearDirty
  332. ));
  333. VDATEIFACE(pistm);
  334. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Save");
  335. UrlMkAssert((_pwzUrl));
  336. HRESULT hr = E_FAIL;
  337. if (_pwzUrl)
  338. {
  339. ULONG cbLen = (wcslen(_pwzUrl) + 1) * sizeof(WCHAR);
  340. DbgLog2(tagCUrlMon, this, "=== CUrlMon::Save (cbLen:%ld, cbLen:%ld)", cbLen, cbLen / sizeof(WCHAR));
  341. // Write the URL to the stream
  342. hr = pistm->Write(&cbLen, sizeof(ULONG), NULL);
  343. if (hr == NOERROR)
  344. {
  345. hr = pistm->Write(_pwzUrl, cbLen, NULL);
  346. }
  347. }
  348. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Save (hr:%lx)", hr);
  349. DEBUG_LEAVE(hr);
  350. return hr;
  351. }
  352. //+---------------------------------------------------------------------------
  353. //
  354. // Method: CUrlMon::GetSizeMax
  355. //
  356. // Synopsis:
  357. //
  358. // Arguments: [pcbSize] --
  359. //
  360. // Returns:
  361. //
  362. // History: 1-19-96 JohannP (Johann Posch) Created
  363. //
  364. // Notes:
  365. //
  366. //----------------------------------------------------------------------------
  367. STDMETHODIMP CUrlMon::GetSizeMax(ULARGE_INTEGER *pcbSize)
  368. {
  369. DEBUG_ENTER((DBG_MONIKER,
  370. Hresult,
  371. "CUrlMon::IPersistStream::GetSizeMax",
  372. "this=%#x, %#x",
  373. this, pcbSize
  374. ));
  375. VDATEPTROUT (pcbSize, ULONG);
  376. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::GetSizeMax");
  377. UrlMkAssert((_pwzUrl));
  378. UrlMkAssert((pcbSize));
  379. // length of url
  380. ULISet32(*pcbSize, ((wcslen(_pwzUrl) + 1) * sizeof(WCHAR)) + sizeof(ULONG));
  381. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::GetSizeMax (hr:%lx)", NOERROR);
  382. DEBUG_LEAVE(NOERROR);
  383. return NOERROR;
  384. }
  385. //+---------------------------------------------------------------------------
  386. //
  387. // Method: CUrlMon::BindToObject
  388. //
  389. // Synopsis:
  390. //
  391. // Arguments: [pbc] --
  392. // [pmkToLeft] --
  393. // [riidRes] --
  394. // [ppvRes] --
  395. //
  396. // Returns:
  397. //
  398. // History: 1-19-96 JohannP (Johann Posch) Created
  399. //
  400. // Notes:
  401. //
  402. //----------------------------------------------------------------------------
  403. STDMETHODIMP CUrlMon::BindToObject(IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riidRes, void **ppvRes)
  404. {
  405. DEBUG_ENTER((DBG_MONIKER,
  406. Hresult,
  407. "CUrlMon::IMoniker::BindToObject",
  408. "this=%#x, %#x, %#x, %#x, %#x",
  409. this, pbc, pmkToLeft, &riidRes, ppvRes
  410. ));
  411. VDATEPTROUT(ppvRes, LPVOID);
  412. VDATEIFACE(pbc);
  413. PerfDbgLog2(tagCUrlMon, this, "+CUrlMon::BindToObject (IBindCtx:%lx, pmkToLeft:%lx)", pbc, pmkToLeft);
  414. *ppvRes = NULL;
  415. if (pmkToLeft)
  416. {
  417. VDATEIFACE(pmkToLeft);
  418. }
  419. HRESULT hr;
  420. CLSID clsid;
  421. BIND_OPTS bindopts;
  422. CBinding *pCBdg = NULL;
  423. CBSC *pBSC = NULL;
  424. WCHAR wzURL[MAX_URL_SIZE + 1];
  425. *ppvRes = NULL;
  426. // Step 1: check if the object is runining
  427. // if so QI for the requested interface
  428. //
  429. {
  430. IRunningObjectTable *pROT = NULL;
  431. // check if the object is already running
  432. hr = IsRunningROT(pbc, pmkToLeft, &pROT);
  433. if (hr == NOERROR)
  434. {
  435. // object is running
  436. IUnknown *pUnk = NULL;
  437. // object is running
  438. // get the object and Qi for the requested interface
  439. hr = pROT->GetObject(this, &pUnk);
  440. if (SUCCEEDED(hr))
  441. {
  442. hr = pUnk->QueryInterface(riidRes, ppvRes);
  443. pUnk->Release();
  444. }
  445. pROT->Release();
  446. goto End;
  447. }
  448. else
  449. {
  450. if (pROT)
  451. {
  452. pROT->Release();
  453. }
  454. if (FAILED(hr))
  455. {
  456. // did not get ROT!!
  457. goto End;
  458. }
  459. }
  460. }
  461. // Step 2: get the bind options from the bind context
  462. bindopts.cbStruct = sizeof(BIND_OPTS);
  463. hr = pbc->GetBindOptions(&bindopts);
  464. if (FAILED(hr))
  465. {
  466. goto End;
  467. }
  468. // Step 3: create a CBinding and releated objects and
  469. // start a transaction
  470. hr = StartBinding(TRUE, pbc, pmkToLeft, riidRes, ppvRes);
  471. End:
  472. PerfDbgLog2(tagCUrlMon, this, "-CUrlMon::BindToObject (hr:%lx, ppvobj:%lx)",
  473. hr, (hr == S_OK) ? *ppvRes : NULL);
  474. DEBUG_LEAVE(hr);
  475. return hr;
  476. }
  477. //+---------------------------------------------------------------------------
  478. //
  479. // Method: CUrlMon::BindToStorage
  480. //
  481. // Synopsis:
  482. //
  483. // Arguments: [pbc] --
  484. // [pmkToLeft] --
  485. // [riid] --
  486. // [ppvObj] --
  487. //
  488. // Returns:
  489. //
  490. // History: 1-19-96 JohannP (Johann Posch) Created
  491. //
  492. // Notes:
  493. //
  494. //----------------------------------------------------------------------------
  495. STDMETHODIMP CUrlMon::BindToStorage(IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, void **ppvObj)
  496. {
  497. DEBUG_ENTER((DBG_MONIKER,
  498. Hresult,
  499. "CUrlMon::IMoniker::BindToStorage",
  500. "this=%#x, %#x, %#x, %#x, %#x",
  501. this, pbc, pmkToLeft, &riid, ppvObj
  502. ));
  503. VDATEPTROUT(ppvObj, LPVOID);
  504. VDATEIFACE(pbc);
  505. PerfDbgLog2(tagCUrlMon, this, "+CUrlMon::BindToStorage (IBindCtx:%lx, pmkToLeft:%lx)", pbc, pmkToLeft);
  506. if (pmkToLeft)
  507. {
  508. VDATEIFACE(pmkToLeft);
  509. }
  510. CBSC *pBSC = NULL;
  511. HRESULT hr;
  512. BIND_OPTS bindopts;
  513. CBinding *pCBdg = NULL;
  514. FORMATETC fetc;
  515. WCHAR wzURL[MAX_URL_SIZE + 1];
  516. IID iidLocal = riid;
  517. *ppvObj = NULL;
  518. #if DBG==1
  519. {
  520. LPOLESTR pszStr;
  521. StringFromCLSID(riid, &pszStr);
  522. DbgLog2(tagCUrlMon, this, "CUrlMon::BindToStorage (szUrl:%ws)(iid:%ws)",
  523. GetUrl(), pszStr);
  524. delete pszStr;
  525. }
  526. #endif
  527. hr = StartBinding(FALSE, pbc, pmkToLeft, riid, ppvObj);
  528. PerfDbgLog2(tagCUrlMon, this, "-CUrlMon::BindToStorage (hr:%lx, ppvobj:%lx)",
  529. hr, (hr == S_OK) ? *ppvObj : NULL);
  530. DEBUG_LEAVE(hr);
  531. return hr;
  532. }
  533. //+---------------------------------------------------------------------------
  534. //
  535. // Method: CUrlMon::StartBinding
  536. //
  537. // Synopsis: sets up the cbinding and starts the transaction
  538. //
  539. // Arguments: [fBindToObject] --
  540. // [pbc] --
  541. // [pmkToLeft] --
  542. // [riid] --
  543. // [ppvObj] --
  544. //
  545. // Returns:
  546. //
  547. // History: 8-20-96 JohannP (Johann Posch) Created
  548. //
  549. // Notes:
  550. //
  551. //----------------------------------------------------------------------------
  552. STDMETHODIMP CUrlMon::StartBinding(BOOL fBindToObject, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, void **ppvObj)
  553. {
  554. DEBUG_ENTER((DBG_MONIKER,
  555. Hresult,
  556. "CUrlMon::StartBinding",
  557. "this=%#x, %B, %#x, %#x, %#x, %#x",
  558. this, fBindToObject, pbc, pmkToLeft, &riid, ppvObj
  559. ));
  560. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::StartBinding");
  561. HRESULT hr = NOERROR;
  562. WCHAR wzURL[MAX_URL_SIZE + 1];
  563. CBSC *pBSC = NULL;
  564. CBinding *pCBdg = NULL;
  565. BOOL fUnknown = FALSE;
  566. do
  567. {
  568. // No need to canonicalize URL here. This should have already been done
  569. // by CreateURLMoniker.
  570. hr = ConstructURL(pbc, NULL, pmkToLeft, GetUrl(), wzURL, sizeof(wzURL),CU_NO_CANONICALIZE);
  571. if (hr != NOERROR)
  572. {
  573. break;
  574. }
  575. // moved to CBinding::StartBinding
  576. // BUG-WORK
  577. //if (!IsOInetProtocol(pbc, wzURL))
  578. //{
  579. // hr = INET_E_UNKNOWN_PROTOCOL;
  580. // break;
  581. //}
  582. // check if a BSC is registerted if not register our own one - for Office!
  583. IUnknown *pUnk = NULL;
  584. hr = GetObjectParam(pbc, REG_BSCB_HOLDER, IID_IBindStatusCallback, (IUnknown**)&pUnk);
  585. if ((hr == NOERROR) && pUnk)
  586. {
  587. // release - nothing to do
  588. pUnk->Release();
  589. }
  590. else
  591. {
  592. hr = NOERROR;
  593. if (fBindToObject)
  594. {
  595. pBSC = new CBSC(Medium_Unknown);
  596. }
  597. else
  598. {
  599. Medium medium = (riid == IID_IStorage) ? Medium_Storage : Medium_Stream;
  600. pBSC = new CBSC(medium);
  601. if (medium == Medium_Storage)
  602. {
  603. fUnknown = TRUE;
  604. }
  605. }
  606. // no IBSC - create our own one and register
  607. if (pBSC)
  608. {
  609. hr = RegisterBindStatusCallback(pbc, pBSC, 0, 0);
  610. }
  611. else
  612. {
  613. hr = E_OUTOFMEMORY;
  614. }
  615. }
  616. if (hr != NOERROR)
  617. {
  618. break;
  619. }
  620. // Create a CBinding object
  621. hr = CBinding::Create(NULL, wzURL, pbc, (fUnknown) ? IID_IUnknown : riid, fBindToObject, &pCBdg);
  622. if (hr != NOERROR)
  623. {
  624. break;
  625. }
  626. UrlMkAssert((pCBdg != NULL));
  627. if (fBindToObject)
  628. {
  629. pCBdg->SetMoniker(this);
  630. }
  631. {
  632. LPWSTR pwzExtra = NULL;
  633. // start the transaction now
  634. hr = pCBdg->StartBinding(wzURL, pbc, (fUnknown) ? IID_IUnknown : riid, fBindToObject, &pwzExtra, ppvObj);
  635. if (pwzExtra)
  636. {
  637. SetUrl(GetUrl(), pwzExtra);
  638. }
  639. }
  640. if( hr == INET_E_USE_EXTEND_BINDING )
  641. {
  642. // rosebud
  643. hr = NOERROR;
  644. // there is no need to return IBinding to client, se should
  645. // free it here.
  646. pCBdg->Release();
  647. break;
  648. }
  649. if (SUCCEEDED(hr))
  650. {
  651. if (pCBdg->IsAsyncTransaction() == FALSE)
  652. {
  653. hr = pCBdg->CompleteTransaction();
  654. if (SUCCEEDED(hr))
  655. {
  656. // retrieve the requested object
  657. if (pBSC)
  658. {
  659. hr = pBSC->GetRequestedObject(pbc, ppvObj);
  660. }
  661. else
  662. {
  663. hr = pCBdg->GetRequestedObject(pbc, (IUnknown **)ppvObj);
  664. }
  665. }
  666. }
  667. else
  668. {
  669. hr = pCBdg->GetRequestedObject(pbc, (IUnknown **)ppvObj);
  670. }
  671. }
  672. // in case the transaction could not be started,
  673. // the following release we terminate all releated objects
  674. pCBdg->Release();
  675. break;
  676. } while (TRUE);
  677. if (pBSC)
  678. {
  679. RevokeBindStatusCallback(pbc, pBSC);
  680. pBSC->Release();
  681. }
  682. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::StartBinding (hr:%lx)", hr);
  683. DEBUG_LEAVE(hr);
  684. return hr;
  685. }
  686. //+---------------------------------------------------------------------------
  687. //
  688. // Method: CUrlMon::Reduce
  689. //
  690. // Synopsis:
  691. //
  692. // Arguments: [pbc] --
  693. // [dwReduceHowFar] --
  694. // [IMoniker] --
  695. // [ppmkReduced] --
  696. //
  697. // Returns:
  698. //
  699. // History: 1-19-96 JohannP (Johann Posch) Created
  700. //
  701. // Notes:
  702. //
  703. //----------------------------------------------------------------------------
  704. STDMETHODIMP CUrlMon::Reduce(IBindCtx *pbc, DWORD dwReduceHowFar,
  705. IMoniker **ppmkToLeft,IMoniker **ppmkReduced)
  706. {
  707. DEBUG_ENTER((DBG_MONIKER,
  708. Hresult,
  709. "CUrlMon::IMoniker::Reduce",
  710. "this=%#x, %#x, %#x, %#x, %#x",
  711. this, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced
  712. ));
  713. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Reduce");
  714. // There is nothing we can do to reduce our moniker
  715. *ppmkReduced = this;
  716. AddRef();
  717. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Reduce (hr:%lx)", MK_S_REDUCED_TO_SELF);
  718. DEBUG_LEAVE(MK_S_REDUCED_TO_SELF);
  719. return MK_S_REDUCED_TO_SELF;
  720. }
  721. //+---------------------------------------------------------------------------
  722. //
  723. // Method: CUrlMon::ComposeWith
  724. //
  725. // Synopsis:
  726. //
  727. // Arguments: [pmkRight] --
  728. // [fOnlyIfNotGeneric] --
  729. // [ppmkComposite] --
  730. //
  731. // Returns:
  732. //
  733. // History: 1-19-96 JohannP (Johann Posch) Created
  734. //
  735. // Notes:
  736. //
  737. //----------------------------------------------------------------------------
  738. STDMETHODIMP CUrlMon::ComposeWith(IMoniker *pmkRight, BOOL fOnlyIfNotGeneric, IMoniker **ppmkComposite)
  739. {
  740. DEBUG_ENTER((DBG_MONIKER,
  741. Hresult,
  742. "CUrlMon::IMoniker::ComposeWith",
  743. "this=%#x, %#x, %B, %#x",
  744. this, pmkRight, fOnlyIfNotGeneric, ppmkComposite
  745. ));
  746. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::ComposeWith");
  747. VDATEIFACE(pmkRight);
  748. VDATEPTROUT(ppmkComposite, LPMONIKER);
  749. HRESULT hr = NOERROR;
  750. DWORD dwMnk = 0;
  751. LPWSTR wzURLRelative = NULL;
  752. *ppmkComposite = NULL;
  753. pmkRight->IsSystemMoniker(&dwMnk);
  754. if (dwMnk == MKSYS_URLMONIKER)
  755. {
  756. hr = pmkRight->GetDisplayName(NULL, NULL, &wzURLRelative);
  757. if (hr == NOERROR)
  758. {
  759. hr = CreateURLMoniker(this, wzURLRelative, ppmkComposite);
  760. }
  761. }
  762. else if (fOnlyIfNotGeneric)
  763. {
  764. hr = MK_E_NEEDGENERIC;
  765. }
  766. else
  767. {
  768. hr = CreateGenericComposite(this, pmkRight, ppmkComposite);
  769. }
  770. if (wzURLRelative)
  771. {
  772. delete wzURLRelative;
  773. }
  774. PerfDbgLog(tagCUrlMon, this, "-CUrlMon::ComposeWith");
  775. DEBUG_LEAVE(hr);
  776. return hr;
  777. }
  778. //+---------------------------------------------------------------------------
  779. //
  780. // Method: CUrlMon::Enum
  781. //
  782. // Synopsis:
  783. //
  784. // Arguments: [fForward] --
  785. // [ppenumMoniker] --
  786. //
  787. // Returns:
  788. //
  789. // History: 1-19-96 JohannP (Johann Posch) Created
  790. //
  791. // Notes:
  792. //
  793. //----------------------------------------------------------------------------
  794. STDMETHODIMP CUrlMon::Enum(BOOL fForward, IEnumMoniker **ppenumMoniker)
  795. {
  796. DEBUG_ENTER((DBG_MONIKER,
  797. Hresult,
  798. "CUrlMon::IMoniker::Enum",
  799. "this=%#x, %B, %#x",
  800. this, fForward, ppenumMoniker
  801. ));
  802. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Enum");
  803. VDATEPTROUT(ppenumMoniker, LPENUMMONIKER);
  804. *ppenumMoniker = NULL;
  805. PerfDbgLog(tagCUrlMon, this, "-CUrlMon::Enum (hr:0)");
  806. DEBUG_LEAVE(NOERROR);
  807. return NOERROR;
  808. }
  809. //+---------------------------------------------------------------------------
  810. //
  811. // Method: CUrlMon::IsEqual
  812. //
  813. // Synopsis:
  814. //
  815. // Arguments: [pMnkOther] --
  816. //
  817. // Returns:
  818. //
  819. // History: 1-19-96 JohannP (Johann Posch) Created
  820. //
  821. // Notes:
  822. // REVIEW: this code will not work cross process. What is the
  823. // correct implementation?
  824. //
  825. //----------------------------------------------------------------------------
  826. STDMETHODIMP CUrlMon::IsEqual(IMoniker *pMnkOther)
  827. {
  828. DEBUG_ENTER((DBG_MONIKER,
  829. Hresult,
  830. "CUrlMon::IMoniker::IsEqual",
  831. "this=%#x, %#x",
  832. this, pMnkOther
  833. ));
  834. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::IsEqual");
  835. HRESULT hr = S_FALSE;
  836. VDATEIFACE(pMnkOther);
  837. // We only worry about URL monikers
  838. if (this == pMnkOther)
  839. {
  840. // same object
  841. hr = NOERROR;
  842. }
  843. else if (IsUrlMoniker(pMnkOther))
  844. {
  845. LPWSTR szDispName = NULL;
  846. // The other moniker is a URL moniker.
  847. // get and compare the display names
  848. hr = pMnkOther->GetDisplayName(NULL, NULL, &szDispName);
  849. // Compare the URL's
  850. if (hr == NOERROR)
  851. {
  852. UrlMkAssert((_pwzUrl));
  853. UrlMkAssert((szDispName));
  854. hr = wcscmp(_pwzUrl, szDispName) ? S_FALSE : NOERROR;
  855. }
  856. if (szDispName)
  857. {
  858. delete szDispName;
  859. }
  860. }
  861. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::IsEqual (hr:%lx)", hr);
  862. DEBUG_LEAVE(hr);
  863. return hr;
  864. }
  865. //+---------------------------------------------------------------------------
  866. //
  867. // Method: CUrlMon::Hash
  868. //
  869. // Synopsis:
  870. //
  871. // Arguments: [pdwHash] --
  872. //
  873. // Returns:
  874. //
  875. // History: 1-19-96 JohannP (Johann Posch) Created
  876. //
  877. // 9-02-95 AdriaanC (Adriaan Canter)
  878. // Modified to use Pearson's Method
  879. //
  880. // Notes:
  881. // 32 bit hashing operator for IMoniker::Hash(DWORD*)
  882. //
  883. // Method based upon "Fast Hashing of Variable Length Text Strings" ,
  884. // by Peter K. Pearson, Communications of the ACM,
  885. // June 1990 Vol. 33, Number 6. pp 677-680.
  886. //
  887. //----------------------------------------------------------------------------
  888. STDMETHODIMP CUrlMon::Hash(DWORD* pdwHash)
  889. {
  890. DEBUG_ENTER((DBG_MONIKER,
  891. Hresult,
  892. "CUrlMon::IMoniker::Hash",
  893. "this=%#x, %#x",
  894. this, pdwHash
  895. ));
  896. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Hash");
  897. UrlMkAssert((_pwzUrl != NULL));
  898. HRESULT hr = NOERROR;
  899. UCHAR c0, c1, c2, c3;
  900. UCHAR* idx = (UCHAR*) _pwzUrl;
  901. static UCHAR T[256] =
  902. {
  903. 1, 14,110, 25, 97,174,132,119,138,170,125,118, 27,233,140, 51,
  904. 87,197,177,107,234,169, 56, 68, 30, 7,173, 73,188, 40, 36, 65,
  905. 49,213,104,190, 57,211,148,223, 48,115, 15, 2, 67,186,210, 28,
  906. 12,181,103, 70, 22, 58, 75, 78,183,167,238,157,124,147,172,144,
  907. 176,161,141, 86, 60, 66,128, 83,156,241, 79, 46,168,198, 41,254,
  908. 178, 85,253,237,250,154,133, 88, 35,206, 95,116,252,192, 54,221,
  909. 102,218,255,240, 82,106,158,201, 61, 3, 89, 9, 42,155,159, 93,
  910. 166, 80, 50, 34,175,195,100, 99, 26,150, 16,145, 4, 33, 8,189,
  911. 121, 64, 77, 72,208,245,130,122,143, 55,105,134, 29,164,185,194,
  912. 193,239,101,242, 5,171,126, 11, 74, 59,137,228,108,191,232,139,
  913. 6, 24, 81, 20,127, 17, 91, 92,251,151,225,207, 21, 98,113,112,
  914. 84,226, 18,214,199,187, 13, 32, 94,220,224,212,247,204,196, 43,
  915. 249,236, 45,244,111,182,153,136,129, 90,217,202, 19,165,231, 71,
  916. 230,142, 96,227, 62,179,246,114,162, 53,160,215,205,180, 47,109,
  917. 44, 38, 31,149,135, 0,216, 52, 63, 23, 37, 69, 39,117,146,184,
  918. 163,200,222,235,248,243,219, 10,152,131,123,229,203, 76,120,209
  919. };
  920. c0 = T[*idx];
  921. c1 = T[*idx+1 % 256];
  922. c2 = T[*idx+2 % 256];
  923. c3 = T[*idx+3 % 256];
  924. #ifndef unix
  925. while ((WCHAR) *(WCHAR*) ++idx != L'\0')
  926. #else
  927. // We are trying to cast a UCHAR as a WCHAR in the windows code. We will need
  928. // to handle alignments correctly here, as we cant randomly cast
  929. // a UCHAR * to a WCHAR *.
  930. WCHAR wend = 0;
  931. while (memcmp(++idx,&wend,sizeof(WCHAR)))
  932. #endif /* unix */
  933. {
  934. c0 = T[c0^*idx]; c1 = T[c1^*idx];
  935. c2 = T[c2^*idx]; c3 = T[c3^*idx];
  936. }
  937. *(((UCHAR*) pdwHash)+0) = c0;
  938. *(((UCHAR*) pdwHash)+1) = c1;
  939. *(((UCHAR*) pdwHash)+2) = c2;
  940. *(((UCHAR*) pdwHash)+3) = c3;
  941. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Hash (hr:%lx)", hr);
  942. DEBUG_LEAVE(hr);
  943. return hr;
  944. }
  945. //+---------------------------------------------------------------------------
  946. //
  947. // Method: CUrlMon::IsRunning
  948. //
  949. // Synopsis:
  950. //
  951. // Arguments: [pbc] --
  952. // [pmkToLeft] --
  953. // [pmkNewlyRunning] --
  954. //
  955. // Returns:
  956. //
  957. // History: 1-19-96 JohannP (Johann Posch) Created
  958. //
  959. // Notes:
  960. //
  961. //----------------------------------------------------------------------------
  962. STDMETHODIMP CUrlMon::IsRunning(IBindCtx *pbc, IMoniker *pmkToLeft, IMoniker *pmkNewlyRunning)
  963. {
  964. DEBUG_ENTER((DBG_MONIKER,
  965. Hresult,
  966. "CUrlMon::IMoniker::IsRunning",
  967. "this=%#x, %#x, %#x, %#x",
  968. this, pbc, pmkToLeft, pmkNewlyRunning
  969. ));
  970. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::IsRunning");
  971. HRESULT hr = NOERROR;
  972. VDATEIFACE(pbc);
  973. if (pmkToLeft)
  974. VDATEIFACE(pmkToLeft);
  975. if (pmkNewlyRunning)
  976. VDATEIFACE(pmkNewlyRunning);
  977. // This implementation was shamelessly stolen from the OLE sources.
  978. if (pmkToLeft == NULL)
  979. {
  980. if (pmkNewlyRunning != NULL)
  981. {
  982. hr = pmkNewlyRunning->IsEqual(this);
  983. }
  984. else
  985. {
  986. hr = IsRunningROT(pbc, NULL, NULL);
  987. }
  988. }
  989. else
  990. {
  991. UrlMkAssert((FALSE));
  992. hr = S_FALSE;
  993. }
  994. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::IsRunning (hr:%lx)", hr);
  995. DEBUG_LEAVE(hr);
  996. return hr;
  997. }
  998. //+---------------------------------------------------------------------------
  999. //
  1000. // Method: CUrlMon::GetTimeOfLastChange
  1001. //
  1002. // Synopsis:
  1003. //
  1004. // Arguments: [pbc] --
  1005. // [pmkToLeft] --
  1006. // [pFileTime] --
  1007. //
  1008. // Returns:
  1009. //
  1010. // History: 1-19-96 JohannP (Johann Posch) Created
  1011. //
  1012. // Notes:
  1013. //
  1014. //----------------------------------------------------------------------------
  1015. STDMETHODIMP CUrlMon::GetTimeOfLastChange(IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pFileTime)
  1016. {
  1017. DEBUG_ENTER((DBG_MONIKER,
  1018. Hresult,
  1019. "CUrlMon::IMoniker::GetTimeOfLastChange",
  1020. "this=%#x, %#x, %#x, %#x",
  1021. this, pbc, pmkToLeft, pFileTime
  1022. ));
  1023. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::GetTimeOfLastChange");
  1024. VDATEIFACE(pbc);
  1025. if (pmkToLeft)
  1026. {
  1027. VDATEIFACE(pmkToLeft);
  1028. }
  1029. VDATEPTROUT(pFileTime, FILETIME);
  1030. HRESULT hr = MK_E_UNAVAILABLE;
  1031. IRunningObjectTable *pROT;
  1032. hr = pbc->GetRunningObjectTable(&pROT);
  1033. if (SUCCEEDED(hr))
  1034. {
  1035. hr = pROT->GetTimeOfLastChange(this, pFileTime);
  1036. pROT->Release();
  1037. }
  1038. else
  1039. {
  1040. hr = MK_E_UNAVAILABLE;
  1041. }
  1042. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::GetTimeOfLastChange (hr:%lx)", hr);
  1043. DEBUG_LEAVE(hr);
  1044. return hr;
  1045. }
  1046. //+---------------------------------------------------------------------------
  1047. //
  1048. // Method: CUrlMon::Inverse
  1049. //
  1050. // Synopsis:
  1051. //
  1052. // Arguments: [ppmk] --
  1053. //
  1054. // Returns:
  1055. //
  1056. // History: 1-16-96 JohannP (Johann Posch) Created
  1057. //
  1058. // Notes: urlmon does not have aninverse
  1059. //
  1060. //----------------------------------------------------------------------------
  1061. STDMETHODIMP CUrlMon::Inverse(IMoniker **ppmk)
  1062. {
  1063. DEBUG_ENTER((DBG_MONIKER,
  1064. Hresult,
  1065. "CUrlMon::IMoniker::Inverse",
  1066. "this=%#x, %#x",
  1067. this, ppmk
  1068. ));
  1069. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::Inverse");
  1070. VDATEPTROUT(ppmk, LPMONIKER);
  1071. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::Inverse (hr:%lx)", MK_E_NOINVERSE);
  1072. DEBUG_LEAVE(MK_E_NOINVERSE);
  1073. return MK_E_NOINVERSE;
  1074. }
  1075. //+---------------------------------------------------------------------------
  1076. //
  1077. // Method: CUrlMon::CommonPrefixWith
  1078. //
  1079. // Synopsis:
  1080. //
  1081. // Arguments: [pmkOther] --
  1082. // [ppmkPrefix] --
  1083. //
  1084. // Returns:
  1085. //
  1086. // History: 1-19-96 JohannP (Johann Posch) Created
  1087. //
  1088. // Notes:
  1089. //
  1090. //----------------------------------------------------------------------------
  1091. STDMETHODIMP CUrlMon::CommonPrefixWith(IMoniker *pmkOther, IMoniker **ppmkPrefix)
  1092. {
  1093. DEBUG_ENTER((DBG_MONIKER,
  1094. Hresult,
  1095. "CUrlMon::IMoniker::CommonPrefixWith",
  1096. "this=%#x, %#x, %#x",
  1097. this, pmkOther, ppmkPrefix
  1098. ));
  1099. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::CommonPrefixWith");
  1100. HRESULT hr = E_NOTIMPL;
  1101. VDATEPTROUT(ppmkPrefix, LPMONIKER);
  1102. *ppmkPrefix = NULL;
  1103. VDATEIFACE(pmkOther);
  1104. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::CommonPrefixWith (hr:%lx)", hr);
  1105. DEBUG_LEAVE(hr);
  1106. return hr;
  1107. }
  1108. //+---------------------------------------------------------------------------
  1109. //
  1110. // Method: CUrlMon::RelativePathTo
  1111. //
  1112. // Synopsis:
  1113. //
  1114. // Arguments: [pmkOther] --
  1115. // [ppmkRelPath] --
  1116. //
  1117. // Returns:
  1118. //
  1119. // History: 1-16-96 JohannP (Johann Posch) Created
  1120. // 8-20-96 ClarG (Clarence Glasse) Implemented
  1121. //
  1122. // Notes: Code is based on composition algorithm in rfc 1808 (this code does
  1123. // the reverse of that).
  1124. //
  1125. //----------------------------------------------------------------------------
  1126. STDMETHODIMP CUrlMon::RelativePathTo(IMoniker *pmkOther, IMoniker **ppmkRelPath)
  1127. {
  1128. DEBUG_ENTER((DBG_MONIKER,
  1129. Hresult,
  1130. "CUrlMon::IMoniker::RelativePathTo",
  1131. "this=%#x, %#x, %#x",
  1132. this, pmkOther, ppmkRelPath
  1133. ));
  1134. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::RelativePathTo");
  1135. HRESULT hr = NOERROR;
  1136. VDATEPTROUT(ppmkRelPath, LPMONIKER);
  1137. *ppmkRelPath = NULL;
  1138. VDATEIFACE(pmkOther);
  1139. CUrl *pUrlThis = NULL;
  1140. CUrl *pUrlOther = NULL;
  1141. LPSTR pch = NULL;
  1142. LPSTR pszQueryThis = NULL;
  1143. LPSTR pszQueryOther = NULL;
  1144. LPSTR pszParamsThis = NULL;
  1145. LPSTR pszParamsOther = NULL;
  1146. char szRelPath[MAX_URL_SIZE + 1];
  1147. if (!_pwzUrl)
  1148. {
  1149. hr = MK_E_NOTBINDABLE;
  1150. goto End;
  1151. }
  1152. if (IsEqual(pmkOther) == S_OK)
  1153. {
  1154. // we are equal to pmkOther, so create an empty path URL moniker.
  1155. if ((*ppmkRelPath = CreateEmptyPathUrlMon()) == NULL)
  1156. {
  1157. hr = E_OUTOFMEMORY;
  1158. goto End;
  1159. }
  1160. // CUrlmon has refcount of 1 now
  1161. }
  1162. else if (IsUrlMoniker(pmkOther))
  1163. {
  1164. if ((hr = HrCreateCUrlFromUrlMon(pmkOther, TRUE, &pUrlOther)) != NOERROR)
  1165. {
  1166. if (hr == MK_E_SYNTAX)
  1167. hr = MK_E_NOTBINDABLE;
  1168. goto End;
  1169. }
  1170. if ((hr = HrCreateCUrlFromUrlStr(_pwzUrl, TRUE, &pUrlThis)) != NOERROR)
  1171. {
  1172. if (hr == MK_E_SYNTAX)
  1173. hr = MK_E_NOTBINDABLE;
  1174. goto End;
  1175. }
  1176. // Each URL has been parsed into its separate components.
  1177. // Now compute the relative path.
  1178. if ((pUrlThis->_dwProto == DLD_PROTOCOL_NONE) ||
  1179. (pUrlOther->_dwProto == DLD_PROTOCOL_NONE))
  1180. {
  1181. // Unrecognized protocol; return MK_S_HIM or MK_E_NOTBINDABLE
  1182. if (pUrlThis->_pszProtocol[0] && pUrlOther->_pszProtocol[0])
  1183. {
  1184. *ppmkRelPath = pmkOther;
  1185. pmkOther->AddRef();
  1186. hr = MK_S_HIM;
  1187. }
  1188. else
  1189. {
  1190. hr = MK_E_NOTBINDABLE;
  1191. }
  1192. goto End;
  1193. }
  1194. // if the scheme and net_loc portion of the url are not equal,
  1195. // return MK_S_HIM
  1196. if ((pUrlThis->_dwProto != pUrlOther->_dwProto) ||
  1197. (lstrcmpi(pUrlThis->_pszServerName, pUrlOther->_pszServerName) != 0) ||
  1198. (pUrlThis->_ipPort != pUrlOther->_ipPort) ||
  1199. (lstrcmpi(pUrlThis->_pszUserName, pUrlOther->_pszUserName) != 0) ||
  1200. (lstrcmpi(pUrlThis->_pszPassword, pUrlOther->_pszPassword) != 0))
  1201. {
  1202. *ppmkRelPath = pmkOther;
  1203. pmkOther->AddRef();
  1204. hr = MK_S_HIM;
  1205. goto End;
  1206. }
  1207. #ifdef URLMON_RELPATHTO_PARSE_QUERY_PARAMS
  1208. // parse the query and params info
  1209. ParseUrlQuery(pUrlThis->_pszObject, &pszQueryThis);
  1210. ParseUrlQuery(pUrlOther->_pszObject, &pszQueryOther);
  1211. ParseUrlParams(pUrlThis->_pszObject, &pszParamsThis);
  1212. ParseUrlParams(pUrlOther->_pszObject, &pszParamsOther);
  1213. #endif // URLMON_RELPATHTO_PARSE_QUERY_PARAMS
  1214. // compute the relative path
  1215. hr = HrGetRelativePath(
  1216. pUrlThis->_pszObject, pUrlOther->_pszObject,
  1217. pUrlThis->_dwProto, pUrlThis->_pszServerName, szRelPath);
  1218. if (FAILED(hr))
  1219. goto End;
  1220. #ifdef URLMON_RELPATHTO_PARSE_QUERY_PARAMS
  1221. // append the appropriate query and params info
  1222. AddParamsAndQueryToRelPath(
  1223. szRelPath, pszParamsThis, pszParamsOther, pszQueryThis, pszQueryOther);
  1224. #endif // URLMON_RELPATHTO_PARSE_QUERY_PARAMS
  1225. if (szRelPath[0])
  1226. {
  1227. HRESULT hr2 = NOERROR;
  1228. WCHAR wzObjRel[MAX_URL_SIZE + 1];
  1229. A2W(szRelPath, wzObjRel, MAX_URL_SIZE);
  1230. hr2 = CreateURLMoniker(NULL, wzObjRel, ppmkRelPath);
  1231. if (FAILED(hr2))
  1232. hr = hr2;
  1233. }
  1234. else
  1235. {
  1236. *ppmkRelPath = CreateEmptyPathUrlMon();
  1237. if (!(*ppmkRelPath))
  1238. hr = E_OUTOFMEMORY;
  1239. }
  1240. }
  1241. else
  1242. {
  1243. hr = MonikerRelativePathTo(this, pmkOther, ppmkRelPath, TRUE);
  1244. }
  1245. End:
  1246. if (pUrlThis)
  1247. delete pUrlThis;
  1248. if (pUrlOther)
  1249. delete pUrlOther;
  1250. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::RelativePathTo (hr:%lx)", hr);
  1251. DEBUG_LEAVE(hr);
  1252. return hr;
  1253. }
  1254. //+---------------------------------------------------------------------------
  1255. //
  1256. // Method: CUrlMon::GetDisplayName
  1257. //
  1258. // Synopsis:
  1259. //
  1260. // Arguments: [pbc] --
  1261. // [pmkToLeft] --
  1262. // [ppszDisplayName] --
  1263. //
  1264. // Returns:
  1265. //
  1266. // History: 1-19-96 JohannP (Johann Posch) Created
  1267. //
  1268. // Notes:
  1269. //
  1270. //----------------------------------------------------------------------------
  1271. STDMETHODIMP CUrlMon::GetDisplayName(IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
  1272. {
  1273. DEBUG_ENTER((DBG_MONIKER,
  1274. Hresult,
  1275. "CUrlMon::IMoniker::GetDisplayName",
  1276. "this=%#x, %#x, %#x, %#x",
  1277. this, pbc, pmkToLeft, ppszDisplayName
  1278. ));
  1279. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::GetDisplayName");
  1280. HRESULT hr = NOERROR;
  1281. VDATEPTROUT(ppszDisplayName, LPSTR);
  1282. *ppszDisplayName = NULL;
  1283. if (pbc)
  1284. {
  1285. VDATEIFACE(pbc);
  1286. }
  1287. if (pmkToLeft)
  1288. {
  1289. VDATEIFACE(pmkToLeft);
  1290. }
  1291. *ppszDisplayName = OLESTRDuplicate(_pwzUrl);
  1292. if (*ppszDisplayName == NULL)
  1293. {
  1294. hr = E_OUTOFMEMORY;
  1295. }
  1296. PerfDbgLog2(tagCUrlMon, this, "-CUrlMon::GetDisplayName (hr:%lx) [%ws]", hr, *ppszDisplayName ? *ppszDisplayName : L"");
  1297. DEBUG_LEAVE(hr);
  1298. return hr;
  1299. }
  1300. //+---------------------------------------------------------------------------
  1301. //
  1302. // Method: CUrlMon::ParseDisplayName
  1303. //
  1304. // Synopsis:
  1305. //
  1306. // Arguments: [IMoniker] --
  1307. // [pmkToLeft] --
  1308. // [ULONG] --
  1309. // [IMoniker] --
  1310. // [ppmkOut] --
  1311. //
  1312. // Returns:
  1313. //
  1314. // History: 1-19-96 JohannP (Johann Posch) Created
  1315. //
  1316. // Notes:
  1317. //
  1318. //----------------------------------------------------------------------------
  1319. STDMETHODIMP CUrlMon::ParseDisplayName(IBindCtx *pbc,IMoniker *pmkToLeft,
  1320. LPOLESTR pozDisplayName,ULONG *pchEaten,IMoniker **ppmkOut)
  1321. {
  1322. DEBUG_ENTER((DBG_MONIKER,
  1323. Hresult,
  1324. "CUrlMon::IMoniker::ParseDisplayName",
  1325. "this=%#x, %#x, %#x, %#x, %#x, %#x",
  1326. this, pbc, pmkToLeft, pozDisplayName, pchEaten, ppmkOut
  1327. ));
  1328. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::ParseDisplayName");
  1329. HRESULT hr;
  1330. WCHAR wzURL[MAX_URL_SIZE + 1];
  1331. VDATEPTROUT(ppmkOut, LPMONIKER);
  1332. *ppmkOut = NULL;
  1333. VDATEIFACE(pbc);
  1334. if (pmkToLeft) VDATEIFACE(pmkToLeft);
  1335. VDATEPTRIN(pozDisplayName, char);
  1336. VDATEPTROUT(pchEaten, ULONG);
  1337. hr = ConstructURL(pbc, this, pmkToLeft, pozDisplayName, wzURL,
  1338. sizeof(wzURL), CU_CANONICALIZE);
  1339. if (hr != NOERROR)
  1340. {
  1341. goto End;
  1342. }
  1343. if (!wcscmp(_pwzUrl, wzURL))
  1344. {
  1345. // Return ourselves if new URL is the same.
  1346. *ppmkOut = this;
  1347. AddRef();
  1348. hr = NOERROR;
  1349. }
  1350. else
  1351. {
  1352. hr = CreateURLMoniker(NULL, wzURL, ppmkOut);
  1353. }
  1354. if (hr == NOERROR)
  1355. {
  1356. // We have eaten all the characters
  1357. *pchEaten = wcslen(pozDisplayName);
  1358. }
  1359. End:
  1360. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::ParseDisplayName (hr:%lx)", hr);
  1361. DEBUG_LEAVE(hr);
  1362. return hr;
  1363. }
  1364. //+---------------------------------------------------------------------------
  1365. //
  1366. // Method: CUrlMon::IsSystemMoniker
  1367. //
  1368. // Synopsis:
  1369. //
  1370. // Arguments: [pdwMksys] --
  1371. //
  1372. // Returns:
  1373. //
  1374. // History: 1-19-96 JohannP (Johann Posch) Created
  1375. //
  1376. // Notes:
  1377. //
  1378. //----------------------------------------------------------------------------
  1379. STDMETHODIMP CUrlMon::IsSystemMoniker(DWORD *pdwMksys)
  1380. {
  1381. DEBUG_ENTER((DBG_MONIKER,
  1382. Hresult,
  1383. "CUrlMon::IMoniker::IsSystemMoniker",
  1384. "this=%#x, %#x",
  1385. this, pdwMksys
  1386. ));
  1387. PerfDbgLog(tagCUrlMon, this, "CUrlMon::IsSystemMoniker");
  1388. VDATEPTROUT(pdwMksys, DWORD);
  1389. *pdwMksys = MKSYS_URLMONIKER;
  1390. DEBUG_LEAVE(NOERROR);
  1391. return NOERROR;
  1392. }
  1393. // Delete the URL string if we have one
  1394. void CUrlMon::DeleteUrl()
  1395. {
  1396. DEBUG_ENTER((DBG_MONIKER,
  1397. None,
  1398. "CUrlMon::DeleteUrl",
  1399. "this=%#x",
  1400. this
  1401. ));
  1402. if (_pwzUrl)
  1403. delete [] _pwzUrl;
  1404. _pwzUrl = NULL;
  1405. DEBUG_LEAVE(0);
  1406. }
  1407. HRESULT CUrlMon::SetUrl(LPWSTR pwzUrl, LPWSTR pwzExtra)
  1408. {
  1409. DEBUG_ENTER((DBG_MONIKER,
  1410. Hresult,
  1411. "CUrlMon::SetUrl",
  1412. "this=%#x, %.80wq, %.80wq",
  1413. this, pwzUrl, pwzExtra
  1414. ));
  1415. int clen;
  1416. HRESULT hr = NOERROR;
  1417. TransAssert((pwzUrl));
  1418. clen = wcslen(pwzUrl) + 1;
  1419. if (pwzExtra)
  1420. {
  1421. clen += wcslen(pwzExtra);
  1422. }
  1423. LPWSTR pwzStr = (LPWSTR) new WCHAR [clen];
  1424. if (pwzStr)
  1425. {
  1426. wcscpy(pwzStr, pwzUrl);
  1427. if (pwzExtra)
  1428. {
  1429. wcscat(pwzStr, pwzExtra);
  1430. }
  1431. if (_pwzUrl)
  1432. {
  1433. delete [] _pwzUrl;
  1434. }
  1435. _pwzUrl = pwzStr;
  1436. }
  1437. else
  1438. {
  1439. hr = E_OUTOFMEMORY;
  1440. }
  1441. DEBUG_LEAVE(hr);
  1442. return hr;
  1443. }
  1444. // Helper function for IMoniker::IsRunning and BindToObject.
  1445. // Return NOERROR if running, and S_FALSE if not.
  1446. //+---------------------------------------------------------------------------
  1447. //
  1448. // Method: CUrlMon::IsRunningROT
  1449. //
  1450. // Synopsis: Checks if the moniker is running
  1451. //
  1452. // Arguments: [pbc] --
  1453. // [pmkToLeft] --
  1454. // [ppROT] --
  1455. //
  1456. // Returns:
  1457. //
  1458. // History: 1-19-96 JohannP (Johann Posch) Created
  1459. //
  1460. // Notes:
  1461. //
  1462. //----------------------------------------------------------------------------
  1463. HRESULT CUrlMon::IsRunningROT(IBindCtx *pbc, IMoniker *pmkToLeft, IRunningObjectTable **ppROT)
  1464. {
  1465. DEBUG_ENTER((DBG_MONIKER,
  1466. Hresult,
  1467. "CUrlMon::IsRunningROT",
  1468. "this=%#x, %#x, %#x, %#x",
  1469. this, pbc, pmkToLeft, ppROT
  1470. ));
  1471. HRESULT hr;
  1472. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::IsRunningROT");
  1473. IRunningObjectTable *pROT;
  1474. hr = pbc->GetRunningObjectTable(&pROT);
  1475. if (SUCCEEDED(hr))
  1476. {
  1477. hr = pROT->IsRunning(this);
  1478. if (ppROT != NULL && SUCCEEDED(hr))
  1479. {
  1480. *ppROT = pROT;
  1481. }
  1482. else
  1483. {
  1484. pROT->Release();
  1485. }
  1486. }
  1487. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::IsRunningROT (hr:%lx)", hr);
  1488. DEBUG_LEAVE(hr);
  1489. return hr;
  1490. }
  1491. //+---------------------------------------------------------------------------
  1492. //
  1493. // Method: CUrlMon::IsUrlMoniker
  1494. //
  1495. // Synopsis: Checks if pMk is a URL moniker
  1496. //
  1497. // Arguments: [pMk] -- the moniker to be checked
  1498. //
  1499. // Returns: true if moniker is URL moniker
  1500. //
  1501. // History: 1-19-96 JohannP (Johann Posch) Created
  1502. //
  1503. // Notes:
  1504. //
  1505. //----------------------------------------------------------------------------
  1506. BOOL CUrlMon::IsUrlMoniker(IMoniker *pMk)
  1507. {
  1508. DEBUG_ENTER((DBG_MONIKER,
  1509. Bool,
  1510. "CUrlMon::IsUrlMoniker",
  1511. "this=%#x, %#x",
  1512. this, pMk
  1513. ));
  1514. PerfDbgLog(tagCUrlMon, this, "+CUrlMon::IsUrlMoniker");
  1515. BOOL fRet = FALSE;
  1516. if (pMk)
  1517. {
  1518. DWORD dwMnk = 0;
  1519. pMk->IsSystemMoniker(&dwMnk);
  1520. fRet = (dwMnk == MKSYS_URLMONIKER);
  1521. }
  1522. PerfDbgLog1(tagCUrlMon, this, "-CUrlMon::IsUrlMoniker (fRet:%d)", fRet);
  1523. DEBUG_LEAVE(fRet);
  1524. return fRet;
  1525. }
  1526. // ********** Helper Functions **********
  1527. // These functions are used by RelativePathTo
  1528. //+---------------------------------------------------------------------------
  1529. //
  1530. // Function: CreateEmptyPathUrlMon
  1531. //
  1532. // Synopsis: Create a UrlMon with empty path "", such that composing it onto
  1533. // a base UrlMon via IMoniker::ComposeWith will yield a moniker
  1534. // equal to the base UrlMon.
  1535. // We don't call CreateUrlMoniker(""), to do this because that will
  1536. // return a UrlMon with path "/". Composing such a moniker onto
  1537. // a base UrlMon out everything after the host name.
  1538. //
  1539. // Arguments: (none)
  1540. //
  1541. // Returns:
  1542. //
  1543. // History: 8-16-96 ClarG (Clarence Glasse) Created
  1544. //
  1545. // Notes:
  1546. //
  1547. //----------------------------------------------------------------------------
  1548. CUrlMon * CreateEmptyPathUrlMon()
  1549. {
  1550. DEBUG_ENTER((DBG_MONIKER,
  1551. Pointer,
  1552. "CreateEmptyPathUrlMon",
  1553. NULL
  1554. ));
  1555. PerfDbgLog(tagCUrlMon, NULL, "+CreateEmptyPathUrlMon");
  1556. CUrlMon * pUMk = NULL;
  1557. LPWSTR pwzUrlEmpty = NULL;
  1558. // allocate empty string
  1559. if ((pwzUrlEmpty = new WCHAR [1]) == NULL)
  1560. {
  1561. goto End;
  1562. }
  1563. pwzUrlEmpty[0] = 0;
  1564. if ((pUMk = new CUrlMon(pwzUrlEmpty)) == NULL)
  1565. {
  1566. delete pwzUrlEmpty;
  1567. goto End;
  1568. }
  1569. // pUMk has refcount of 1 now
  1570. End:
  1571. PerfDbgLog1(tagCUrlMon, NULL, "-CreateEmptyPathUrlMon, pUMk:%lx", pUMk);
  1572. DEBUG_LEAVE(pUMk);
  1573. return pUMk;
  1574. }
  1575. //+---------------------------------------------------------------------------
  1576. //
  1577. // Function: HrCreateCUrlFromUrlMon
  1578. //
  1579. // Synopsis: Given a Url moniker pmkUrl, create a CUrl object. Assumes that
  1580. // pmkUrl is indeed a Url moniker.
  1581. //
  1582. // Arguments: [pmkUrl] -- Url moniker
  1583. // [fParseUrl] -- if TRUE, parse the URL.
  1584. // [ppUrl] -- returns created CUrl obj, which caller must delete
  1585. // when finished with it.
  1586. //
  1587. // Returns: NOERROR is successful.
  1588. //
  1589. // History: 8-16-96 ClarG (Clarence Glasse) Created
  1590. //
  1591. // Notes:
  1592. //
  1593. //----------------------------------------------------------------------------
  1594. HRESULT HrCreateCUrlFromUrlMon(LPMONIKER pmkUrl, BOOL fParseUrl, CUrl **ppUrl)
  1595. {
  1596. DEBUG_ENTER((DBG_MONIKER,
  1597. Hresult,
  1598. "HrCreateCUrlFromUrlMon",
  1599. "%#x, %B, %#x",
  1600. pmkUrl, fParseUrl, ppUrl
  1601. ));
  1602. PerfDbgLog(tagCUrlMon, NULL, "+HrCreateCUrlFromUrlMon");
  1603. UrlMkAssert((pmkUrl));
  1604. UrlMkAssert((ppUrl));
  1605. HRESULT hr = NOERROR;
  1606. LPBC pbc = NULL;
  1607. LPWSTR pwzUrl = NULL;
  1608. if ((*ppUrl = new CUrl) == NULL)
  1609. {
  1610. hr = E_OUTOFMEMORY;
  1611. goto End;
  1612. }
  1613. if( !(*ppUrl)->CUrlInitAll() )
  1614. {
  1615. hr = E_OUTOFMEMORY;
  1616. goto End;
  1617. }
  1618. if ((hr = CreateBindCtx(0, &pbc)) != NOERROR)
  1619. {
  1620. goto End;
  1621. }
  1622. if ((hr = pmkUrl->GetDisplayName(pbc, NULL, &pwzUrl)) != NOERROR)
  1623. {
  1624. goto End;
  1625. }
  1626. W2A(pwzUrl, (*ppUrl)->_pszBaseURL, MAX_URL_SIZE);
  1627. if (fParseUrl)
  1628. {
  1629. if (!(*ppUrl)->ParseUrl())
  1630. {
  1631. hr = MK_E_SYNTAX;
  1632. goto End;
  1633. }
  1634. }
  1635. End:
  1636. if (pbc)
  1637. pbc->Release();
  1638. if (pwzUrl)
  1639. CoTaskMemFree(pwzUrl);
  1640. if ((hr != NOERROR) && (*ppUrl != NULL))
  1641. {
  1642. delete *ppUrl;
  1643. *ppUrl = NULL;
  1644. }
  1645. PerfDbgLog1(tagCUrlMon, NULL, "-HrCreateCUrlFromUrlMon (hr:%lx)", hr);
  1646. DEBUG_LEAVE(hr);
  1647. return hr;
  1648. }
  1649. //+---------------------------------------------------------------------------
  1650. //
  1651. // Function: HrCreateCUrlFromUrlStr
  1652. //
  1653. // Synopsis: Given a Url string pwzUrl, create a CUrl object.
  1654. //
  1655. // Arguments: [pwzUrl] -- Url string
  1656. // [fParseUrl] -- if TRUE, parse the URL.
  1657. // [ppUrl] -- returns created CUrl obj, which caller must delete
  1658. // when finished with it.
  1659. //
  1660. // Returns: NOERROR is successful.
  1661. //
  1662. // History: 8-16-96 ClarG (Clarence Glasse) Created
  1663. //
  1664. // Notes:
  1665. //
  1666. //----------------------------------------------------------------------------
  1667. HRESULT HrCreateCUrlFromUrlStr(LPCWSTR pwzUrl, BOOL fParseUrl, CUrl **ppUrl)
  1668. {
  1669. DEBUG_ENTER((DBG_MONIKER,
  1670. Hresult,
  1671. "HrCreateCUrlFromUrlStr",
  1672. "%.80wq, %B, %#x",
  1673. pwzUrl, fParseUrl, ppUrl
  1674. ));
  1675. PerfDbgLog(tagCUrlMon, NULL, "+HrCreateCUrlFromUrlStr");
  1676. UrlMkAssert((pwzUrl));
  1677. UrlMkAssert((ppUrl));
  1678. HRESULT hr = NOERROR;
  1679. if ((*ppUrl = new CUrl) == NULL)
  1680. {
  1681. hr = E_OUTOFMEMORY;
  1682. goto End;
  1683. }
  1684. if( !(*ppUrl)->CUrlInitAll() )
  1685. {
  1686. hr = E_OUTOFMEMORY;
  1687. goto End;
  1688. }
  1689. W2A(pwzUrl, (*ppUrl)->_pszBaseURL, MAX_URL_SIZE);
  1690. if (fParseUrl)
  1691. {
  1692. if (!(*ppUrl)->ParseUrl())
  1693. {
  1694. hr = MK_E_SYNTAX;
  1695. goto End;
  1696. }
  1697. }
  1698. End:
  1699. if ((hr != NOERROR) && (*ppUrl != NULL))
  1700. {
  1701. delete *ppUrl;
  1702. *ppUrl = NULL;
  1703. }
  1704. PerfDbgLog1(tagCUrlMon, NULL, "-HrCreateCUrlFromUrlStr (hr:%lx)", hr);
  1705. DEBUG_LEAVE(hr);
  1706. return hr;
  1707. }
  1708. //+---------------------------------------------------------------------------
  1709. //
  1710. // Function: IsSeparator
  1711. //
  1712. // Synopsis: Return TRUE if ch is a file path or url path separator char.
  1713. //
  1714. // Arguments: [ch] -- the char in question
  1715. // when finished with it.
  1716. //
  1717. // Returns: TRUE if ch is a separator char
  1718. //
  1719. // History: 8-20-96 ClarG (Clarence Glasse) Created
  1720. //
  1721. // Notes: This is taken from OLE2 file moniker code
  1722. //
  1723. //----------------------------------------------------------------------------
  1724. inline BOOL IsSeparator( char ch )
  1725. {
  1726. DEBUG_ENTER((DBG_MONIKER,
  1727. Bool,
  1728. "IsSeparator",
  1729. "%c",
  1730. ch
  1731. ));
  1732. BOOL fRet = (ch == '\\' || ch == '/' || ch == ':');
  1733. DEBUG_LEAVE(fRet);
  1734. return fRet;
  1735. }
  1736. //+---------------------------------------------------------------------------
  1737. //
  1738. // Function: CountSegments
  1739. //
  1740. // Synopsis: Return the number of segments in file or url path pch.
  1741. //
  1742. // Arguments: [pch] -- the string in question.
  1743. //
  1744. // Returns: number of segments in pch
  1745. //
  1746. // History: 8-20-96 ClarG (Clarence Glasse) Created
  1747. //
  1748. // Notes: This is taken from OLE2 file moniker code
  1749. //
  1750. //----------------------------------------------------------------------------
  1751. int CountSegments ( LPSTR pch )
  1752. {
  1753. DEBUG_ENTER((DBG_MONIKER,
  1754. Int,
  1755. "CountSegments",
  1756. "%.80q",
  1757. pch
  1758. ));
  1759. PerfDbgLog(tagCUrlMon, NULL, "+CountSegments");
  1760. // counts the number of pieces in a path, after the first colon, if
  1761. // there is one
  1762. int n = 0;
  1763. LPSTR pch1;
  1764. pch1 = pch;
  1765. while (*pch1 != '\0' && *pch1 != ':') IncLpch(pch1);
  1766. if (*pch1 == ':') pch = ++pch1;
  1767. while (*pch != '\0')
  1768. {
  1769. while (*pch && IsSeparator(*pch)) pch++;
  1770. if (*pch) n++;
  1771. while (*pch && (!IsSeparator(*pch))) IncLpch(pch);
  1772. }
  1773. PerfDbgLog1(tagCUrlMon, NULL, "-CountSegments (n:%ld)", n);
  1774. DEBUG_LEAVE(n);
  1775. return n;
  1776. }
  1777. //+---------------------------------------------------------------------------
  1778. //
  1779. // Function: HrGetRelativePath
  1780. //
  1781. // Synopsis: Compute and return relative path from url path
  1782. // lpszBase to url path lpszOther.
  1783. //
  1784. // Arguments: [lpszBase] -- the base path without the scheme and host info
  1785. // [lpszOther] -- the target path without the scheme and host
  1786. // [dwProto] -- DLD_PROTOCOL_XXX value, indicating the scheme
  1787. // of the urls.
  1788. // [lpszHost] -- the host name for the urls
  1789. // [lpszRelPath] -- buffer of size MAX_URL_SIZE that returns the
  1790. // relative path.
  1791. //
  1792. // Returns: NOERROR, MK_S_HIM, MK_E_NOTBINDABLE, or some other hresult.
  1793. //
  1794. // History: 8-20-96 ClarG (Clarence Glasse) Created
  1795. //
  1796. // Notes: This is based on OLE2 file moniker code
  1797. //
  1798. //----------------------------------------------------------------------------
  1799. HRESULT HrGetRelativePath(
  1800. LPSTR lpszBase, LPSTR lpszOther, DWORD dwProto, LPSTR lpszHost,
  1801. LPSTR lpszRelPath)
  1802. {
  1803. DEBUG_ENTER((DBG_MONIKER,
  1804. Hresult,
  1805. "HrGetRelativePath",
  1806. "%.80q, %.80q, %#x, %.80q, %.80q",
  1807. lpszBase, lpszOther, dwProto, lpszHost, lpszRelPath
  1808. ));
  1809. PerfDbgLog(tagCUrlMon, NULL, "+HrGetRelativePath");
  1810. HRESULT hr = NOERROR;
  1811. LPSTR lpszRover;
  1812. LPSTR lpszMarker;
  1813. LPSTR lpch;
  1814. LPSTR lpchStripBaseSav = NULL;
  1815. char ch1;
  1816. char ch2;
  1817. char chStripBaseSav;
  1818. char chNull = '\0';
  1819. int i;
  1820. int cAnti;
  1821. lpszRelPath[0] = 0;
  1822. // if neither lpszBase nor lpszRelPath look like absolute url or file
  1823. // paths, return MK_E_NOTBINDALBE
  1824. if (!lpszBase[0] || !lpszOther[0])
  1825. {
  1826. hr = MK_E_NOTBINDABLE;
  1827. goto End;
  1828. }
  1829. if ((lpszBase[0] != '\\') && (lpszBase[0] != '/') && (lpszBase[1] != ':'))
  1830. {
  1831. hr = MK_E_NOTBINDABLE;
  1832. goto End;
  1833. }
  1834. if ((lpszOther[0] != '\\') && (lpszOther[0] != '/') && (lpszOther[1] != ':'))
  1835. {
  1836. hr = MK_E_NOTBINDABLE;
  1837. goto End;
  1838. }
  1839. if (lstrcmpi(lpszBase, lpszOther) == 0)
  1840. {
  1841. // if paths are equal, relative path is empty string
  1842. lpszRelPath[0] = 0;
  1843. hr = NOERROR;
  1844. goto End;
  1845. }
  1846. // if base does not end in a separator, remove its last piece
  1847. lpch = lpszBase + lstrlen(lpszBase);
  1848. for( ; ((!(IsSeparator(*lpch))) && (lpch > lpszBase)); DecLpch(lpszBase, lpch) );
  1849. if (IsSeparator(*lpch))
  1850. {
  1851. IncLpch(lpch);
  1852. lpchStripBaseSav = lpch;
  1853. chStripBaseSav = *lpch;
  1854. *lpch = '\0';
  1855. }
  1856. lpszRover = lpszBase;
  1857. lpszMarker = lpszRover;
  1858. i = 0;
  1859. lpszOther = lpszOther;
  1860. while (*lpszRover != '\0')
  1861. {
  1862. while (*lpszRover && IsSeparator(*lpszRover)) lpszRover++;
  1863. while (*lpszRover && !IsSeparator(*lpszRover)) IncLpch(lpszRover);
  1864. // the first part of the path is between m_szPath and
  1865. // lpszRover
  1866. i = (int) (lpszRover - lpszBase);
  1867. ch1 = *lpszRover;
  1868. ch2 = *(lpszOther + i);
  1869. *lpszRover = '\0';
  1870. *(lpszOther + i) = '\0';
  1871. if (lstrcmpi(lpszBase, lpszOther) == 0)
  1872. lpszMarker = lpszRover;
  1873. else
  1874. lpszRover = &chNull;
  1875. *(lpszBase + i) = ch1;
  1876. *(lpszOther + i) = ch2;
  1877. }
  1878. // common portion is from lpszBase to lpszMarker
  1879. i = (int) (lpszMarker - lpszBase);
  1880. if ((!lpszHost || !lpszHost[0]) && (i == 0))
  1881. {
  1882. lstrcpy(lpszRelPath, lpszOther);
  1883. hr = MK_S_HIM;
  1884. goto End;
  1885. }
  1886. lpszRover = lpszRelPath;
  1887. while (IsSeparator(*(lpszOther+i))) i++;
  1888. cAnti = CountSegments(lpszMarker);
  1889. while (cAnti)
  1890. {
  1891. if (dwProto != DLD_PROTOCOL_FILE)
  1892. lstrcpy(lpszRover, "../");
  1893. else
  1894. lstrcpy(lpszRover, "..\\");
  1895. lpszRover += 3;
  1896. cAnti--;
  1897. }
  1898. lstrcpy(lpszRover, lpszOther + i);
  1899. End:
  1900. if (lpchStripBaseSav)
  1901. {
  1902. *lpchStripBaseSav = chStripBaseSav;
  1903. }
  1904. PerfDbgLog2(tagCUrlMon, NULL, "-HrGetRelativePath [%s], hr:%lx", lpszRelPath?lpszRelPath:"", hr);
  1905. DEBUG_LEAVE(hr);
  1906. return hr;
  1907. }
  1908. #ifdef URLMON_RELPATHTO_PARSE_QUERY_PARAMS
  1909. //+---------------------------------------------------------------------------
  1910. //
  1911. // Function: ParseUrlQuery
  1912. //
  1913. // Synopsis: Parse the Query portion of a url
  1914. //
  1915. // Arguments: [pszURL] -- url to parse; the query portion is "removed" from
  1916. // pszURL when function returns.
  1917. // [ppszQuery] -- returns pointer to query portion of URL
  1918. //
  1919. // Returns: nothing
  1920. //
  1921. // History: 8-20-96 ClarG (Clarence Glasse) Created
  1922. //
  1923. // Notes: This is based on OLE2 file moniker code
  1924. //
  1925. //----------------------------------------------------------------------------
  1926. void ParseUrlQuery(LPSTR pszURL, LPSTR *ppszQuery)
  1927. {
  1928. DEBUG_ENTER((DBG_MONIKER,
  1929. None,
  1930. "ParseUrlQuery",
  1931. "%.80q, %#x",
  1932. pszURL, ppszQuery
  1933. ));
  1934. PerfDbgLog(tagCUrlMon, NULL, "+ParseUrlQuery");
  1935. LPSTR pch = NULL;
  1936. *ppszQuery = NULL;
  1937. for (pch = pszURL; *pch; IncLpch(pch))
  1938. {
  1939. if (*pch == '?')
  1940. {
  1941. *pch = '\0';
  1942. pch++;
  1943. if (*pch)
  1944. *ppszQuery = pch;
  1945. break;
  1946. }
  1947. }
  1948. PerfDbgLog(tagCUrlMon, NULL, "-ParseUrlQuery");
  1949. DEBUG_LEAVE(0);
  1950. }
  1951. //+---------------------------------------------------------------------------
  1952. //
  1953. // Function: ParseUrlParams
  1954. //
  1955. // Synopsis: Parse the Params portion of a url
  1956. //
  1957. // Arguments: [pszURL] -- url to parse; the params portion is "removed" from
  1958. // pszURL when function returns.
  1959. // [ppszParams] -- returns pointer to params portion of URL
  1960. //
  1961. // Returns: nothing
  1962. //
  1963. // History: 8-20-96 ClarG (Clarence Glasse) Created
  1964. //
  1965. // Notes: This is based on OLE2 file moniker code
  1966. //
  1967. //----------------------------------------------------------------------------
  1968. void ParseUrlParams(LPSTR pszURL, LPSTR *ppszParams)
  1969. {
  1970. DEBUG_ENTER((DBG_MONIKER,
  1971. None,
  1972. "ParseUrlParams",
  1973. "%.80q, %#x",
  1974. pszURL, ppszParams
  1975. ));
  1976. PerfDbgLog(tagCUrlMon, NULL, "+ParseUrlParams");
  1977. LPSTR pch = NULL;
  1978. *ppszParams = NULL;
  1979. for (pch = pszURL; *pch; IncLpch(pch))
  1980. {
  1981. if (*pch == ';')
  1982. {
  1983. *pch = '\0';
  1984. pch++;
  1985. if (*pch)
  1986. *ppszParams = pch;
  1987. break;
  1988. }
  1989. }
  1990. PerfDbgLog(tagCUrlMon, NULL, "-ParseUrlParams");
  1991. DEBUG_LEAVE(0);
  1992. }
  1993. //+---------------------------------------------------------------------------
  1994. //
  1995. // Function: AddParamsAndQueryToRelPath
  1996. //
  1997. // Synopsis: Given a computed relative URL path from a base to a target,
  1998. // append the appropriate Params and Query info.
  1999. //
  2000. // Arguments: [szRelPath] -- computed relative path
  2001. // [pszParamsBase] -- Params info of base URL
  2002. // [pszParamsOther] -- Params info of target URL
  2003. // [pszQueryBase] -- Query info of base URL
  2004. // [pszQueryOther] -- Query info of target URL
  2005. //
  2006. // Returns: nothing
  2007. //
  2008. // History: 8-20-96 ClarG (Clarence Glasse) Created
  2009. //
  2010. // Notes: This is based on OLE2 file moniker code
  2011. //
  2012. //----------------------------------------------------------------------------
  2013. void AddParamsAndQueryToRelPath(
  2014. LPSTR szRelPath,
  2015. LPSTR pszParamsBase, LPSTR pszParamsOther,
  2016. LPSTR pszQueryBase, LPSTR pszQueryOther)
  2017. {
  2018. DEBUG_ENTER((DBG_MONIKER,
  2019. None,
  2020. "AddParamsAndQueryToRelPath",
  2021. "%.80q, %.80q, %.80q, %.80q, %.80q",
  2022. szRelPath, pszParamsBase, pszParamsOther, pszQueryBase, pszQueryOther
  2023. ));
  2024. PerfDbgLog(tagCUrlMon, NULL, "+AddParamsAndQueryToRelPath");
  2025. if (szRelPath[0])
  2026. {
  2027. if (pszParamsOther)
  2028. {
  2029. lstrcat(szRelPath, ";");
  2030. lstrcat(szRelPath, pszParamsOther);
  2031. }
  2032. if (pszQueryOther)
  2033. {
  2034. lstrcat(szRelPath, "?");
  2035. lstrcat(szRelPath, pszQueryOther);
  2036. }
  2037. }
  2038. else
  2039. {
  2040. if (pszParamsOther &&
  2041. (!pszParamsBase || (lstrcmpi(pszParamsOther, pszParamsBase) != 0)))
  2042. {
  2043. lstrcat(szRelPath, ";");
  2044. lstrcat(szRelPath, pszParamsOther);
  2045. if (pszQueryOther)
  2046. {
  2047. lstrcat(szRelPath, "?");
  2048. lstrcat(szRelPath, pszQueryOther);
  2049. }
  2050. }
  2051. else if (pszQueryOther &&
  2052. (!pszQueryBase || (lstrcmpi(pszQueryOther, pszQueryBase) != 0)))
  2053. {
  2054. lstrcat(szRelPath, "?");
  2055. lstrcat(szRelPath, pszQueryOther);
  2056. }
  2057. }
  2058. PerfDbgLog(tagCUrlMon, NULL, "-AddParamsAndQueryToRelPath");
  2059. DEBUG_LEAVE(0);
  2060. }
  2061. #endif // URLMON_RELPATHTO_PARSE_QUERY_PARAMS