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.

1005 lines
28 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: hlinkez.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History:
  15. // 5-15-96 Ramesh G - Major modifications
  16. // 5-17-96 Ramesh G - Added Frames support
  17. // Ramesh G - Modified variable names to Hungarian Notation
  18. // 6-19-96 Ramesh G - Modifications
  19. // 7-25-96 Ramesh G - Modifications
  20. // 8-05-96 Ramesh G - Merged HlinkSimple...String() and Moniker()
  21. // HlinkSimpleNavigateToString() creates the moniker
  22. // and calls HlinkSimpleNavigateToMoniker()
  23. //----------------------------------------------------------------------------
  24. #define USE_SYSTEM_URL_MONIKER
  25. #define INITGUID
  26. #define STR_SIZE 20
  27. #include "hlink.h"
  28. #include "ocidl.h"
  29. #include "docobj.h"
  30. #include "exdisp.h"
  31. #include "shellapi.h"
  32. #include "servprov.h"
  33. #include "urlhlink.h"
  34. #include "htiface.h"
  35. #include "wininet.h"
  36. #include <shlwapi.h>
  37. #include <shlwapip.h>
  38. #include <mshtml.h>
  39. #include "mshtmdid.h"
  40. #include <delaydll.h>
  41. #include "sdll.hxx"
  42. #ifndef GUID_NULL
  43. struct __declspec(uuid("00000000-0000-0000-0000-000000000000")) GUID_NULL;
  44. #define GUID_NULL __uuidof(struct GUID_NULL)
  45. #endif
  46. class HLinkDll
  47. {
  48. public:
  49. HLinkDll();
  50. HRESULT HlinkCreateFromMoniker(
  51. IMoniker* pmkSource,
  52. LPCWSTR szLocation,
  53. LPCWSTR szFriendlyName,
  54. IHlinkSite* phlSite,
  55. DWORD dwSiteData,
  56. IUnknown* punkOuter,
  57. REFIID riid,
  58. void** ppv);
  59. private:
  60. BOOL LoadFunc( LPCSTR lpProcName, FARPROC & fp );
  61. typedef HRESULT (STDAPICALLTYPE * LPFNHlinkCreateFromMoniker)(
  62. IMoniker* pmkSource,
  63. LPCWSTR szLocation,
  64. LPCWSTR szFriendlyName,
  65. IHlinkSite* phlSite,
  66. DWORD dwSiteData,
  67. IUnknown* punkOuter,
  68. REFIID riid,
  69. void** ppv);
  70. LPFNHlinkCreateFromMoniker m_lpfnHlinkCreateFromMoniker;
  71. HMODULE m_hmodule;
  72. BOOL m_error;
  73. };
  74. inline HRESULT HLinkDll::HlinkCreateFromMoniker(
  75. IMoniker* pmkSource,
  76. LPCWSTR szLocation,
  77. LPCWSTR szFriendlyName,
  78. IHlinkSite* phlSite,
  79. DWORD dwSiteData,
  80. IUnknown* punkOuter,
  81. REFIID riid,
  82. void** ppv)
  83. {
  84. if( !LoadFunc("HlinkCreateFromMoniker",*(FARPROC*)&m_lpfnHlinkCreateFromMoniker) )
  85. return(E_FAIL);
  86. return m_lpfnHlinkCreateFromMoniker(
  87. pmkSource,
  88. szLocation,
  89. szFriendlyName,
  90. phlSite,
  91. dwSiteData,
  92. punkOuter,
  93. riid,
  94. ppv);
  95. }
  96. HLinkDll::HLinkDll()
  97. {
  98. m_hmodule = 0;
  99. m_error = 0;
  100. m_lpfnHlinkCreateFromMoniker = 0;
  101. }
  102. #if 0
  103. HLinkDll::~HLinkDll()
  104. {
  105. if( m_hmodule )
  106. ::FreeLibrary( m_hmodule );
  107. }
  108. #endif
  109. BOOL HLinkDll::LoadFunc( LPCSTR lpProcName, FARPROC & fp )
  110. {
  111. if( m_error )
  112. return(0);
  113. if( fp )
  114. return(1);
  115. if( !m_hmodule )
  116. {
  117. m_hmodule = ::LoadLibrary( "HLINK.DLL" );
  118. if( !m_hmodule )
  119. {
  120. m_error = 1;
  121. return(0);
  122. }
  123. }
  124. fp = ::GetProcAddress( m_hmodule, lpProcName );
  125. return( fp != 0 );
  126. }
  127. static HLinkDll hlink;
  128. //////////////////
  129. static int wclen(LPCWSTR szStr)
  130. {
  131. int cbStr=0;
  132. if(szStr!=NULL)
  133. while(szStr[cbStr]!=NULL)
  134. ++cbStr;
  135. return cbStr;
  136. }
  137. ////////////////////////////
  138. static HRESULT GetAnInterface
  139. (
  140. IUnknown * punk,
  141. const IID & riid,
  142. void ** pout,
  143. BOOL bCheckServiceProvider,
  144. const IID & siid,
  145. const IID & siid_riid,
  146. void ** sout
  147. )
  148. {
  149. IOleObject * oleObj = 0;
  150. IOleClientSite * oleSite = 0;
  151. IOleContainer * container = 0;
  152. IUnknown * service = 0;
  153. HRESULT hr = E_FAIL;
  154. // Initialize passed in interface pointers: calling code assumes NULL for failure
  155. if(pout)
  156. *pout = NULL;
  157. if(sout)
  158. *sout = NULL;
  159. if(punk)
  160. hr = punk->QueryInterface( IID_IOleObject, (void **)&oleObj );
  161. // BUBUG: I think this returns a wrong hr if QS fails but the QI passes - jp
  162. while( SUCCEEDED(hr) && oleObj )
  163. {
  164. if( oleSite )
  165. {
  166. //oleSite->Release();
  167. oleSite = 0;
  168. }
  169. hr = oleObj->GetClientSite(&oleSite);
  170. if( FAILED(hr) || !oleSite)
  171. break;
  172. if( bCheckServiceProvider)
  173. {
  174. IServiceProvider * servProv;
  175. hr = oleSite->QueryInterface( IID_IServiceProvider, (void**)&servProv);
  176. if( SUCCEEDED(hr) )
  177. {
  178. hr = servProv->QueryService
  179. (
  180. siid,
  181. siid_riid,
  182. (void **)&service
  183. );
  184. servProv->Release();
  185. }
  186. if( SUCCEEDED(hr) )
  187. {
  188. bCheckServiceProvider = FALSE;
  189. hr = service->QueryInterface( riid, pout );
  190. }
  191. if( SUCCEEDED(hr) )
  192. break;
  193. }
  194. if( container )
  195. {
  196. container->Release();
  197. container = 0;
  198. }
  199. hr = oleSite->GetContainer( &container );
  200. if( FAILED(hr) )
  201. break;
  202. hr = container->QueryInterface( riid, pout );
  203. if( SUCCEEDED(hr) )
  204. break;
  205. oleObj->Release();
  206. oleObj = 0;
  207. hr = container->QueryInterface( IID_IOleObject, (void**)&oleObj );
  208. }
  209. if( oleSite )
  210. {
  211. oleSite->Release();
  212. oleSite = 0;
  213. }
  214. if( oleObj )
  215. oleObj->Release();
  216. if( container )
  217. container->Release();
  218. if( service )
  219. {
  220. if (sout)
  221. *sout = service;
  222. else
  223. service->Release();
  224. }
  225. return( hr );
  226. }
  227. //
  228. // GetUrlScheme() returns one of the URL_SCHEME_* constants as
  229. // defined in shlwapip.h
  230. // example "http://foo" returns URL_SCHEME_HTTP
  231. //
  232. static DWORD GetUrlSchemeW(IN LPCWSTR pcszUrl)
  233. {
  234. if(pcszUrl)
  235. {
  236. PARSEDURLW pu;
  237. pu.cbSize = sizeof(pu);
  238. if(SUCCEEDED(ParseURLW(pcszUrl, &pu)))
  239. return pu.nScheme;
  240. }
  241. return URL_SCHEME_INVALID;
  242. }
  243. //
  244. // GetUrlScheme() returns one of the URL_SCHEME_* constants as
  245. // defined in shlwapip.h
  246. // example "http://foo" returns URL_SCHEME_HTTP
  247. //
  248. static DWORD GetUrlSchemeA(IN LPCSTR pcszUrl)
  249. {
  250. if(pcszUrl)
  251. {
  252. PARSEDURLA pu;
  253. pu.cbSize = sizeof(pu);
  254. if(SUCCEEDED(ParseURLA(pcszUrl, &pu)))
  255. return pu.nScheme;
  256. }
  257. return URL_SCHEME_INVALID;
  258. }
  259. HRESULT DoUrlShellExecuteA(LPCSTR pszUrl)
  260. {
  261. CShellDll sdll;
  262. HINSTANCE hInst = NULL;
  263. if(S_OK == sdll.Init())
  264. {
  265. UINT uProt = GetUrlSchemeA(pszUrl);
  266. switch (uProt)
  267. {
  268. case URL_SCHEME_HTTP:
  269. case URL_SCHEME_HTTPS:
  270. case URL_SCHEME_FTP:
  271. case URL_SCHEME_FILE:
  272. hInst = sdll.ShellExecute(
  273. NULL, NULL, pszUrl,
  274. NULL, NULL, SW_SHOWNORMAL );
  275. break;
  276. // Non-standard protocols go here:
  277. default:
  278. hInst = sdll.ShellExecute(
  279. NULL, "open", "iexplore.exe",
  280. pszUrl, NULL, SW_SHOWNORMAL );
  281. }
  282. }
  283. return ((ULONG_PTR)hInst > 32) ? S_OK : E_FAIL;
  284. }
  285. BOOL IsSpecialUrl(WCHAR *pchURL)
  286. {
  287. UINT uProt;
  288. uProt = GetUrlSchemeW(pchURL);
  289. return (URL_SCHEME_JAVASCRIPT == uProt ||
  290. URL_SCHEME_VBSCRIPT == uProt ||
  291. URL_SCHEME_ABOUT == uProt);
  292. }
  293. HRESULT WrapSpecialUrlFlat(LPWSTR pszUrl, DWORD cchUrl)
  294. {
  295. HRESULT hr = S_OK;
  296. if (IsSpecialUrl(pszUrl))
  297. {
  298. //
  299. // If this is javascript:, vbscript: or about:, append the
  300. // url of this document so that on the other side we can
  301. // decide whether or not to allow script execution.
  302. //
  303. // QFE 2735 (Georgi XDomain): [alanau]
  304. //
  305. // If the special URL contains an %00 sequence, then it will be converted to a Null char when
  306. // encoded. This will effectively truncate the Security ID. For now, simply disallow this
  307. // sequence, and display a "Permission Denied" script error.
  308. //
  309. if (StrStrW(pszUrl, L"%00"))
  310. {
  311. hr = E_ACCESSDENIED;
  312. }
  313. else
  314. {
  315. // munge the url in place
  316. //
  317. // someone could put in a string like this:
  318. // %2501 OR %252501 OR %25252501
  319. // which, depending on the number of decoding steps, will bypass security
  320. // so, just keep decoding while there are %s and the string is getting shorter
  321. int nPreviousLen = 0;
  322. while ( (nPreviousLen != lstrlenW(pszUrl)) && (StrChrW(pszUrl, L'%')))
  323. {
  324. nPreviousLen = lstrlenW(pszUrl);
  325. int nNumPercents;
  326. int nNumPrevPercents = 0;
  327. // Reduce the URL
  328. //
  329. for (;;)
  330. {
  331. // Count the % signs.
  332. //
  333. nNumPercents = 0;
  334. WCHAR *pch = pszUrl;
  335. while (pch = StrChrW(pch, L'%'))
  336. {
  337. pch++;
  338. nNumPercents++;
  339. }
  340. // If the number of % signs has changed, we've reduced the URL one iteration.
  341. //
  342. if (nNumPercents != nNumPrevPercents)
  343. {
  344. WCHAR szBuf[INTERNET_MAX_URL_LENGTH];
  345. DWORD dwSize;
  346. // Encode the URL
  347. hr = CoInternetParseUrl(pszUrl,
  348. PARSE_ENCODE,
  349. 0,
  350. szBuf,
  351. INTERNET_MAX_URL_LENGTH,
  352. &dwSize,
  353. 0);
  354. StrCpyNW(pszUrl, szBuf, cchUrl);
  355. nNumPrevPercents = nNumPercents;
  356. }
  357. else
  358. {
  359. // The URL is fully reduced. Break out of loop.
  360. //
  361. break;
  362. }
  363. }
  364. }
  365. // Now scan for '\1' characters.
  366. //
  367. if (StrChrW(pszUrl, L'\1'))
  368. {
  369. // If there are '\1' characters, we can't guarantee the safety. Put up "Permission Denied".
  370. //
  371. hr = E_ACCESSDENIED;
  372. }
  373. }
  374. }
  375. return hr;
  376. }
  377. static HRESULT GetAMoniker
  378. (
  379. IUnknown * pUnk,
  380. LPCWSTR szTarget,
  381. IMoniker * * ppMoniker
  382. )
  383. {
  384. HRESULT hr;
  385. IBindHost * pBindHost = 0;
  386. hr = GetAnInterface
  387. (
  388. pUnk,
  389. IID_IBindHost,
  390. (void**)&pBindHost,
  391. TRUE,
  392. IID_IBindHost,
  393. IID_IBindHost,
  394. NULL
  395. );
  396. if( pBindHost )
  397. {
  398. hr = pBindHost->CreateMoniker((LPWSTR)szTarget,NULL,ppMoniker,0);
  399. pBindHost->Release();
  400. }
  401. else
  402. hr = ::CreateURLMoniker(0,szTarget,ppMoniker);
  403. return(hr);
  404. }
  405. STDAPI HlinkSimpleNavigateToString
  406. (
  407. /* [in] */ LPCWSTR szTarget, // required - target document - null if local jump w/in doc
  408. /* [in] */ LPCWSTR szLocation, // optional, for navigation into middle of a doc
  409. /* [in] */ LPCWSTR szTargetFrame, // optional, for targeting frame-sets
  410. /* [in] */ IUnknown *pUnk, // required - we'll search this for other necessary interfaces
  411. /* [in] */ IBindCtx *pBndctx, // optional. caller may register an IBSC in this
  412. /* [in] */ IBindStatusCallback * pBscb,
  413. /* [in] */ DWORD grfHLNF, // flags (TBD - HadiP needs to define this correctly?)
  414. /* [in] */ DWORD dwReserved // for future use, must be NULL
  415. )
  416. {
  417. IWebBrowserApp *pExplorer = 0;
  418. IHlinkFrame *pHlframe = 0;
  419. ITargetFrame *pTargetFrame = 0;
  420. IMoniker *pMoniker = 0;
  421. HRESULT hr = S_OK;
  422. if ( szTarget && *szTarget )
  423. hr = GetAMoniker( pUnk, szTarget, &pMoniker );
  424. if ( SUCCEEDED(hr) )
  425. hr = HlinkSimpleNavigateToMoniker (
  426. pMoniker,
  427. szLocation,
  428. szTargetFrame,
  429. pUnk,
  430. pBndctx,
  431. pBscb,
  432. grfHLNF,
  433. dwReserved );
  434. if ( pMoniker )
  435. pMoniker->Release();
  436. return( hr );
  437. }
  438. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  439. BOOL AccessAllowed(LPCWSTR pwszURL1, LPCWSTR pwszURL2)
  440. {
  441. BOOL fRet = FALSE;
  442. IInternetSecurityManager *pSecMgr = NULL;
  443. if (pwszURL1 && pwszURL2)
  444. {
  445. if (StrCmpW(pwszURL1, pwszURL2) == 0)
  446. {
  447. // No need to check if URLs are the same
  448. fRet = TRUE;
  449. }
  450. else if (SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager,
  451. NULL,
  452. CLSCTX_INPROC_SERVER,
  453. IID_IInternetSecurityManager,
  454. (void **)&pSecMgr)))
  455. {
  456. BYTE reqSid[MAX_SIZE_SECURITY_ID], docSid[MAX_SIZE_SECURITY_ID];
  457. DWORD cbReqSid = ARRAYSIZE(reqSid);
  458. DWORD cbDocSid = ARRAYSIZE(docSid);
  459. if ( SUCCEEDED(pSecMgr->GetSecurityId(pwszURL1, reqSid, &cbReqSid, 0))
  460. && SUCCEEDED(pSecMgr->GetSecurityId(pwszURL2, docSid, &cbDocSid, 0))
  461. && (cbReqSid == cbDocSid)
  462. && (memcmp(reqSid, docSid, cbReqSid) == 0))
  463. {
  464. fRet = TRUE;
  465. }
  466. pSecMgr->Release();
  467. }
  468. }
  469. return fRet;
  470. }
  471. BOOL AccessAllowed(ITargetFrame* pSrcFrame, IHlinkFrame* pTargetFrame)
  472. {
  473. IDispatch* pdisp[2] = {0};
  474. IServiceProvider* pIsp[2] = {0};
  475. DISPPARAMS dp;
  476. VARIANT VarUrl[2];
  477. UINT uiErr;
  478. BOOL fRet = FALSE;
  479. HRESULT hr;
  480. int idx;
  481. if(!pTargetFrame || !pSrcFrame)
  482. {
  483. goto cleanup;
  484. }
  485. hr = pTargetFrame->QueryInterface(IID_IServiceProvider, (LPVOID *)&pIsp[0]);
  486. if(hr)
  487. goto cleanup;
  488. hr = pSrcFrame->QueryInterface(IID_IServiceProvider, (LPVOID *)&pIsp[1]);
  489. if(hr)
  490. goto cleanup;
  491. VariantInit(&VarUrl[0]);
  492. VariantInit(&VarUrl[1]);
  493. for (idx = 0; idx < 2; idx++)
  494. {
  495. hr = pIsp[idx]->QueryService(IID_IHTMLWindow2, IID_IDispatch, (LPVOID *)&pdisp[idx]);
  496. if(hr)
  497. {
  498. hr = pIsp[idx]->QueryService(IID_IWebBrowserApp, IID_IDispatch, (LPVOID *)&pdisp[idx]);
  499. }
  500. if(hr)
  501. goto cleanup;
  502. ZeroMemory((PVOID)&dp, sizeof(dp));
  503. hr = pdisp[idx]->Invoke(
  504. DISPID_SECURITYCTX,
  505. IID_NULL,
  506. LOCALE_SYSTEM_DEFAULT,
  507. DISPATCH_PROPERTYGET,
  508. &dp,
  509. &VarUrl[idx],
  510. NULL,
  511. &uiErr);
  512. if(hr)
  513. goto cleanup;
  514. if (V_VT(&VarUrl[idx]) != VT_BSTR || !V_BSTR(&VarUrl[idx]))
  515. {
  516. goto cleanup;
  517. }
  518. if (hr)
  519. goto cleanup;
  520. }
  521. fRet = AccessAllowed(V_BSTR(&VarUrl[0]), V_BSTR(&VarUrl[1]));
  522. cleanup:
  523. for (idx = 0; idx < 2; idx++)
  524. {
  525. if(pdisp[idx])
  526. pdisp[idx]->Release();
  527. if(pIsp[idx])
  528. pIsp[idx]->Release();
  529. VariantClear(&VarUrl[idx]);
  530. }
  531. return fRet;
  532. }
  533. STDAPI HlinkSimpleNavigateToMoniker
  534. (
  535. /* [in] */ IMoniker *pmkTarget, // required - target document - (may be null if local jump w/in doc)
  536. /* [in] */ LPCWSTR szLocation, // optional, for navigation into middle of a doc
  537. /* [in] */ LPCWSTR szTargetFrame, // optional, for targeting frame-sets
  538. /* [in] */ IUnknown *pUnk, // required - we'll search this for other necessary interfaces
  539. /* [in] */ IBindCtx *pBndctx, // optional. caller may register an IBSC in this
  540. /* [in] */ IBindStatusCallback * pBscb,
  541. /* [in] */ DWORD grfHLNF, // flags
  542. /* [in] */ DWORD dwReserved // for future use, must be NULL
  543. )
  544. {
  545. IWebBrowserApp * pExplorer = 0;
  546. IHlinkFrame * pHlframe = 0;
  547. ITargetFrame * pTargetFrameSrc = 0;
  548. CShellDll sdll;
  549. LPWSTR pszUrl = NULL;
  550. HRESULT hr, htemp;
  551. if (pmkTarget == NULL)
  552. {
  553. if (szLocation && *szLocation)
  554. {
  555. grfHLNF |= HLNF_INTERNALJUMP;
  556. hr = S_OK;
  557. }
  558. else
  559. return E_INVALIDARG; //no location specified for internal jump
  560. }
  561. else
  562. {
  563. DWORD dwId;
  564. if (SUCCEEDED(pmkTarget->IsSystemMoniker(&dwId)) &&
  565. MKSYS_URLMONIKER == dwId)
  566. {
  567. if (SUCCEEDED(pmkTarget->GetDisplayName(NULL, NULL, &pszUrl)))
  568. {
  569. HRESULT hrSecure = WrapSpecialUrlFlat(pszUrl, lstrlenW(pszUrl) + 1);
  570. if (FAILED(hrSecure))
  571. {
  572. CoTaskMemFree(pszUrl);
  573. return hrSecure;
  574. }
  575. }
  576. }
  577. }
  578. if (pUnk)
  579. hr = GetAnInterface
  580. (
  581. pUnk,
  582. IID_IWebBrowserApp,
  583. (void**)&pExplorer,
  584. TRUE,
  585. IID_IHlinkFrame,
  586. IID_IHlinkFrame,
  587. (void**)&pHlframe
  588. );
  589. IHlink * pLink = 0;
  590. hr = hlink.HlinkCreateFromMoniker
  591. (
  592. pmkTarget,
  593. szLocation,
  594. L"TheName",
  595. 0, // hlsite,
  596. 0, NULL,
  597. IID_IHlink,
  598. (void**)&pLink
  599. );
  600. if (SUCCEEDED(hr) && pHlframe)
  601. {
  602. BOOL fAccessAllowed = TRUE;
  603. if (szTargetFrame && *szTargetFrame)
  604. {
  605. long len = (lstrlenW(szTargetFrame) + 1) * sizeof(char);
  606. char szTargetFrameName[STR_SIZE+1];
  607. len = (len > STR_SIZE) ? STR_SIZE : len;
  608. WideCharToMultiByte(CP_ACP, 0, szTargetFrame, -1, (LPSTR)szTargetFrameName, len, NULL, NULL);
  609. if (lstrcmpi(szTargetFrameName,"_blank") == 0)
  610. grfHLNF |= HLNF_OPENINNEWWINDOW;
  611. else
  612. {
  613. htemp = GetAnInterface
  614. (
  615. pUnk,
  616. IID_ITargetFrame,
  617. (void**)&pTargetFrameSrc,
  618. TRUE,
  619. IID_ITargetFrame,
  620. IID_ITargetFrame,
  621. NULL
  622. );
  623. IUnknown *punkTargetFrame = 0;
  624. if (SUCCEEDED(htemp))
  625. htemp = pTargetFrameSrc->FindFrame(szTargetFrame,
  626. pHlframe,
  627. FINDFRAME_JUSTTESTEXISTENCE,
  628. &punkTargetFrame);
  629. IHlinkFrame *pTargetHlinkFrame = 0;
  630. if (punkTargetFrame)
  631. {
  632. IServiceProvider *pIsp = 0;
  633. // Get the IHlinkFrame for the target'ed frame and the source.
  634. htemp = punkTargetFrame->QueryInterface(IID_IServiceProvider, (LPVOID *)&pIsp);
  635. if (pIsp != NULL)
  636. {
  637. // NOTE: SID_SHLinkFrame should be the guidService
  638. htemp = pIsp->QueryService(IID_IWebBrowserApp, IID_IHlinkFrame, (LPVOID*) &pTargetHlinkFrame);
  639. pIsp->Release();
  640. }
  641. fAccessAllowed = (!IsSpecialUrl(pszUrl) ||
  642. AccessAllowed(pTargetFrameSrc, pTargetHlinkFrame));
  643. }
  644. else
  645. {
  646. grfHLNF |= HLNF_OPENINNEWWINDOW;
  647. }
  648. if (punkTargetFrame)
  649. punkTargetFrame->Release();
  650. if (pTargetFrameSrc)
  651. pTargetFrameSrc->Release();
  652. if (pTargetHlinkFrame)
  653. {
  654. pHlframe->Release();
  655. pHlframe = pTargetHlinkFrame;
  656. }
  657. }
  658. }
  659. if(!fAccessAllowed)
  660. {
  661. hr = E_ACCESSDENIED;
  662. goto exit;
  663. }
  664. hr = pHlframe->Navigate(grfHLNF,
  665. pBndctx,
  666. pBscb,
  667. pLink);
  668. }
  669. else
  670. hr = E_FAIL;
  671. if ( FAILED(hr) && pHlframe)
  672. { // Navigation through pHlframe failed, we will retrieve the
  673. // corresponding IWebBrowserApp interface and try navigation.
  674. if (pExplorer)
  675. {
  676. pExplorer->Release();
  677. pExplorer = 0;
  678. }
  679. pHlframe->QueryInterface(IID_IWebBrowserApp, (void **)&pExplorer);
  680. }
  681. if (FAILED(hr) && pExplorer && pmkTarget)
  682. {
  683. LPOLESTR szTarget;
  684. hr = pmkTarget->GetDisplayName(pBndctx,NULL,&szTarget);
  685. if (SUCCEEDED(hr))
  686. hr = pExplorer->Navigate(
  687. szTarget,
  688. 0,
  689. 0,
  690. 0,
  691. 0);
  692. CoTaskMemFree(szTarget);
  693. }
  694. // pExplorer->Navigate ShellExecute's
  695. // We need not ShellExecute when pExplorer is not NULL
  696. if (FAILED(hr) && !pExplorer && pmkTarget)
  697. {
  698. // Our container does not support hyperlinking. We need to shell execute
  699. // explorer and go to the link.
  700. // We need to translate the string to ANSI
  701. CHAR szPath[MAX_PATH];
  702. DWORD cchPath = MAX_PATH;
  703. LPOLESTR szTarget;
  704. pmkTarget->GetDisplayName(pBndctx,NULL,&szTarget);
  705. int cbStr = 2 * wclen(szTarget + 1);
  706. char *pszAnsiTarget = new char[cbStr];
  707. if( !pszAnsiTarget )
  708. goto cleanup;
  709. // ASSERT(pszAnsiTarget)
  710. WideCharToMultiByte(CP_ACP, 0, szTarget, -1, pszAnsiTarget, cbStr, 0, 0);
  711. pszAnsiTarget[cbStr-1] = '\0';
  712. if(SUCCEEDED(PathCreateFromUrl(pszAnsiTarget, szPath, &cchPath, 0)))
  713. {
  714. HANDLE hFile = CreateFile(szPath,
  715. GENERIC_READ,
  716. FILE_SHARE_READ,
  717. NULL,
  718. OPEN_EXISTING,
  719. FILE_ATTRIBUTE_NORMAL,
  720. NULL);
  721. if (INVALID_HANDLE_VALUE != hFile)
  722. {
  723. CloseHandle(hFile);
  724. hr = DoUrlShellExecuteA(szPath);
  725. }
  726. else
  727. hr = E_FAIL;
  728. }
  729. else
  730. {
  731. hr = DoUrlShellExecuteA((LPCTSTR)pszAnsiTarget);
  732. }
  733. cleanup:
  734. if( pszAnsiTarget )
  735. delete[] pszAnsiTarget;
  736. CoTaskMemFree(szTarget);
  737. }
  738. exit:
  739. if (pExplorer)
  740. pExplorer->Release();
  741. if (pHlframe)
  742. pHlframe->Release();
  743. if (pLink)
  744. pLink->Release();
  745. if(pszUrl)
  746. CoTaskMemFree(pszUrl);
  747. return( hr );
  748. }
  749. //////////////////////////////////////////////////////////////////////////
  750. //
  751. // HlinkGoBack
  752. //
  753. STDAPI HlinkGoBack(IUnknown *pUnk)
  754. {
  755. IWebBrowserApp * pExplorer = 0;
  756. IHlinkFrame * pHlframe = 0;
  757. HRESULT hr;
  758. hr = GetAnInterface
  759. (
  760. pUnk,
  761. IID_IWebBrowserApp,
  762. (void**)&pExplorer,
  763. TRUE,
  764. IID_IHlinkFrame,
  765. IID_IHlinkFrame,
  766. (void**)&pHlframe
  767. );
  768. if ( SUCCEEDED(hr) )
  769. hr = pHlframe->Navigate(HLNF_NAVIGATINGBACK, 0, 0, 0);
  770. if ( FAILED(hr) && pExplorer )
  771. hr = pExplorer->GoBack();
  772. if ( pExplorer )
  773. pExplorer->Release();
  774. if ( pHlframe )
  775. pHlframe->Release();
  776. return (hr);
  777. }
  778. //////////////////////////////////////////////////////////////////////////
  779. //
  780. // HlinkGoForward
  781. //
  782. //////////////////////////////////////////////////////////////////////////
  783. STDAPI HlinkGoForward(IUnknown *pUnk)
  784. {
  785. IWebBrowserApp * pExplorer = 0;
  786. IHlinkFrame * pHlframe = 0;
  787. HRESULT hr;
  788. hr = GetAnInterface
  789. (
  790. pUnk,
  791. IID_IWebBrowserApp,
  792. (void**)&pExplorer,
  793. TRUE,
  794. IID_IHlinkFrame,
  795. IID_IHlinkFrame,
  796. (void**)&pHlframe
  797. );
  798. if (SUCCEEDED(hr))
  799. hr = pHlframe->Navigate(HLNF_NAVIGATINGFORWARD, 0, 0, 0);
  800. if ( FAILED(hr) && pExplorer )
  801. hr = pExplorer->GoForward();
  802. if ( pExplorer )
  803. pExplorer->Release();
  804. if ( pHlframe )
  805. pHlframe->Release();
  806. return (hr);
  807. }
  808. //////////////////////////////////////////////////////////////////////////
  809. //
  810. // HlinkNavigateString
  811. //
  812. //////////////////////////////////////////////////////////////////////////
  813. STDAPI HlinkNavigateString(IUnknown *pUnk, LPCWSTR szTarget)
  814. {
  815. HRESULT hr;
  816. hr = HlinkSimpleNavigateToString(szTarget, NULL, NULL, pUnk, NULL, 0, 0, 0);
  817. return (hr);
  818. }
  819. //////////////////////////////////////////////////////////////////////////
  820. //
  821. // HlinkNavigateMoniker
  822. //
  823. //////////////////////////////////////////////////////////////////////////
  824. STDAPI HlinkNavigateMoniker(IUnknown *pUnk, IMoniker *pmkTarget)
  825. {
  826. HRESULT hr;
  827. hr = HlinkSimpleNavigateToMoniker(pmkTarget, NULL, NULL, pUnk, NULL,NULL, 0, 0);
  828. return (hr);
  829. }