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.

1106 lines
30 KiB

  1. /*
  2. * t r i u t i l . c p p
  3. *
  4. * Purpose:
  5. * Trident utilities
  6. *
  7. * History
  8. *
  9. * Copyright (C) Microsoft Corp. 1995, 1996.
  10. */
  11. #include <pch.hxx>
  12. #include "dllmain.h"
  13. #include "urlmon.h"
  14. #include "wininet.h"
  15. #include "winineti.h"
  16. #include "mshtml.h"
  17. #include "mshtmcid.h"
  18. #include "mshtmhst.h"
  19. #include "oleutil.h"
  20. #include "triutil.h"
  21. #include "htmlstr.h"
  22. #include "demand.h"
  23. #include "mhtml.h"
  24. #include "mshtmdid.h"
  25. #include "tags.h"
  26. ASSERTDATA
  27. class CDummySite :
  28. public IOleClientSite,
  29. public IDispatch
  30. {
  31. private:
  32. LONG m_cRef;
  33. public:
  34. // *** ctor/dtor methods ***
  35. CDummySite() : m_cRef(1) {}
  36. ~CDummySite() {}
  37. // *** IUnknown methods ***
  38. virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID FAR *);
  39. virtual ULONG STDMETHODCALLTYPE AddRef();
  40. virtual ULONG STDMETHODCALLTYPE Release();
  41. // IOleClientSite methods.
  42. virtual HRESULT STDMETHODCALLTYPE SaveObject() { return E_NOTIMPL; }
  43. virtual HRESULT STDMETHODCALLTYPE GetMoniker(DWORD, DWORD, LPMONIKER *) { return E_NOTIMPL; }
  44. virtual HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER *) { return E_NOTIMPL; }
  45. virtual HRESULT STDMETHODCALLTYPE ShowObject() { return E_NOTIMPL; }
  46. virtual HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL) { return E_NOTIMPL; }
  47. virtual HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() { return E_NOTIMPL; }
  48. // *** IDispatch ***
  49. virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo) { return E_NOTIMPL; }
  50. virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo) { return E_NOTIMPL; }
  51. virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid) { return E_NOTIMPL; }
  52. virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr);
  53. };
  54. /*
  55. * t y p e d e f s
  56. */
  57. /*
  58. * m a c r o s
  59. */
  60. /*
  61. * c o n s t a n t s
  62. */
  63. /*
  64. * g l o b a l s
  65. */
  66. /*
  67. * p r o t o t y p e s
  68. */
  69. HRESULT ClearStyleSheetBackground(IHTMLDocument2 *pDoc);
  70. STDMETHODIMP_(ULONG) CDummySite::AddRef()
  71. {
  72. return ::InterlockedIncrement(&m_cRef);
  73. }
  74. STDMETHODIMP_(ULONG) CDummySite::Release()
  75. {
  76. LONG cRef = 0;
  77. cRef = ::InterlockedDecrement(&m_cRef);
  78. if (0 == cRef)
  79. {
  80. delete this;
  81. return cRef;
  82. }
  83. return cRef;
  84. }
  85. STDMETHODIMP CDummySite::QueryInterface(REFIID riid, void ** ppvObject)
  86. {
  87. HRESULT hr = S_OK;
  88. // Check the incoming params
  89. if (NULL == ppvObject)
  90. {
  91. hr = E_INVALIDARG;
  92. goto exit;
  93. }
  94. // Initialize outgoing param
  95. *ppvObject = NULL;
  96. if ((riid == IID_IUnknown) || (riid == IID_IOleClientSite))
  97. {
  98. *ppvObject = static_cast<IOleClientSite *>(this);
  99. }
  100. else if (riid == IID_IDispatch)
  101. {
  102. *ppvObject = static_cast<IDispatch *>(this);
  103. }
  104. else
  105. {
  106. hr = E_NOINTERFACE;
  107. goto exit;
  108. }
  109. reinterpret_cast<IUnknown *>(*ppvObject)->AddRef();
  110. hr = S_OK;
  111. exit:
  112. return hr;
  113. }
  114. STDMETHODIMP CDummySite::Invoke(
  115. DISPID dispIdMember,
  116. REFIID /*riid*/,
  117. LCID /*lcid*/,
  118. WORD /*wFlags*/,
  119. DISPPARAMS FAR* /*pDispParams*/,
  120. VARIANT * pVarResult,
  121. EXCEPINFO * /*pExcepInfo*/,
  122. UINT * /*puArgErr*/)
  123. {
  124. HRESULT hr = S_OK;
  125. if (dispIdMember != DISPID_AMBIENT_DLCONTROL)
  126. {
  127. hr = E_NOTIMPL;
  128. goto exit;
  129. }
  130. if (NULL == pVarResult)
  131. {
  132. hr = E_INVALIDARG;
  133. goto exit;
  134. }
  135. // Set the return value
  136. pVarResult->vt = VT_I4;
  137. pVarResult->lVal = DLCTL_NO_SCRIPTS | DLCTL_NO_JAVA | DLCTL_NO_RUNACTIVEXCTLS | DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_FRAMEDOWNLOAD | DLCTL_FORCEOFFLINE;
  138. exit:
  139. return hr;
  140. }
  141. HRESULT HrCreateSyncTridentFromStream(LPSTREAM pstm, REFIID riid, LPVOID *ppv)
  142. {
  143. HRESULT hr;
  144. IOleCommandTarget *pCmdTarget = NULL;
  145. CDummySite *pDummy = NULL;
  146. IOleClientSite *pISite = NULL;
  147. IOleObject *pIObj = NULL;
  148. // BUGBUG: this cocreate should also go thro' the same code path as the DocHost one
  149. // so that if this is the first trident in the process, we keep it's CF around
  150. hr = CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
  151. IID_IOleCommandTarget, (LPVOID *)&pCmdTarget);
  152. if (FAILED(hr))
  153. goto exit;
  154. // Create a dummy site
  155. pDummy = new CDummySite;
  156. if (NULL == pDummy)
  157. {
  158. hr = E_OUTOFMEMORY;
  159. goto exit;
  160. }
  161. // Get the client site interface
  162. hr = pDummy->QueryInterface(IID_IOleClientSite, (VOID **) &pISite);
  163. if (FAILED(hr))
  164. {
  165. goto exit;
  166. }
  167. // Get the OLE object interface from trident
  168. hr = pCmdTarget->QueryInterface(IID_IOleObject, (VOID **) &pIObj);
  169. if (FAILED(hr))
  170. {
  171. goto exit;
  172. }
  173. // Set the client site
  174. hr = pIObj->SetClientSite(pISite);
  175. if (FAILED(hr))
  176. {
  177. goto exit;
  178. }
  179. // force trident to load sync
  180. pCmdTarget->Exec(&CMDSETID_Forms3, IDM_PERSISTSTREAMSYNC, NULL, NULL, NULL);
  181. hr = HrIPersistStreamInitLoad(pCmdTarget, pstm);
  182. if (FAILED(hr))
  183. goto exit;
  184. // success let's return the desired interface
  185. hr = pCmdTarget->QueryInterface(riid, ppv);
  186. exit:
  187. ReleaseObj(pIObj);
  188. ReleaseObj(pISite);
  189. ReleaseObj(pDummy);
  190. ReleaseObj(pCmdTarget);
  191. return hr;
  192. }
  193. HRESULT HrGetMember(LPUNKNOWN pUnk, BSTR bstrMember,LONG lFlags, BSTR *pbstr)
  194. {
  195. IHTMLElement *pObj;
  196. HRESULT hr=E_FAIL;
  197. VARIANT rVar;
  198. if (pUnk->QueryInterface(IID_IHTMLElement, (LPVOID *)&pObj)==S_OK)
  199. {
  200. Assert (pObj);
  201. rVar.vt = VT_BSTR;
  202. if (!FAILED(pObj->getAttribute(bstrMember, lFlags, &rVar))
  203. && rVar.vt == VT_BSTR
  204. && rVar.bstrVal != NULL)
  205. {
  206. hr = S_OK;
  207. *pbstr = rVar.bstrVal;
  208. }
  209. pObj->Release();
  210. }
  211. return hr;
  212. }
  213. ULONG UlGetCollectionCount(IHTMLElementCollection *pCollect)
  214. {
  215. ULONG ulCount=0;
  216. if (pCollect)
  217. pCollect->get_length((LONG *)&ulCount);
  218. return ulCount;
  219. }
  220. HRESULT HrGetCollectionItem(IHTMLElementCollection *pCollect, ULONG uIndex, REFIID riid, LPVOID *ppvObj)
  221. {
  222. HRESULT hr=E_FAIL;
  223. IDispatch *pDisp=0;
  224. VARIANTARG va1,
  225. va2;
  226. va1.vt = VT_I4;
  227. va2.vt = VT_EMPTY;
  228. va1.lVal = (LONG)uIndex;
  229. pCollect->item(va1, va2, &pDisp);
  230. if (pDisp)
  231. {
  232. hr = pDisp->QueryInterface(riid, ppvObj);
  233. pDisp->Release();
  234. }
  235. return hr;
  236. }
  237. HRESULT HrGetCollectionOf(IHTMLDocument2 *pDoc, BSTR bstrTagName, IHTMLElementCollection **ppCollect)
  238. {
  239. VARIANT v;
  240. IDispatch *pDisp=0;
  241. IHTMLElementCollection *pCollect=0;
  242. HRESULT hr;
  243. Assert(ppCollect);
  244. Assert(bstrTagName);
  245. Assert(pDoc);
  246. *ppCollect = NULL;
  247. hr = pDoc->get_all(&pCollect);
  248. if (pCollect)
  249. {
  250. v.vt = VT_BSTR;
  251. v.bstrVal = bstrTagName;
  252. pCollect->tags(v, &pDisp);
  253. if (pDisp)
  254. {
  255. hr = pDisp->QueryInterface(IID_IHTMLElementCollection, (LPVOID *)ppCollect);
  256. pDisp->Release();
  257. }
  258. pCollect->Release();
  259. }
  260. else if (S_OK == hr)
  261. hr = E_FAIL;
  262. return hr;
  263. }
  264. HRESULT HrSetMember(LPUNKNOWN pUnk, BSTR bstrMember, BSTR bstrValue)
  265. {
  266. IHTMLElement *pObj;
  267. HRESULT hr;
  268. VARIANT rVar;
  269. hr = pUnk->QueryInterface(IID_IHTMLElement, (LPVOID *)&pObj);
  270. if (!FAILED(hr))
  271. {
  272. Assert (pObj);
  273. rVar.vt = VT_BSTR;
  274. rVar.bstrVal = bstrValue;
  275. // if bstrVal is NULL then kill the member
  276. if (bstrValue)
  277. hr = pObj->setAttribute(bstrMember, rVar, FALSE);
  278. else
  279. hr = pObj->removeAttribute(bstrMember, 0, NULL);
  280. pObj->Release();
  281. }
  282. return hr;
  283. }
  284. HRESULT GetBodyStream(IUnknown *pUnkTrident, BOOL fHtml, LPSTREAM *ppstm)
  285. {
  286. LPPERSISTSTREAMINIT pStreamInit;
  287. LPSTREAM pstm;
  288. HRESULT hr;
  289. Assert(ppstm);
  290. Assert(pUnkTrident);
  291. *ppstm=NULL;
  292. if (fHtml)
  293. {
  294. // get the HTML from Trident
  295. hr = pUnkTrident->QueryInterface(IID_IPersistStreamInit, (LPVOID*)&pStreamInit);
  296. if (!FAILED(hr))
  297. {
  298. hr = MimeOleCreateVirtualStream(&pstm);
  299. if (!FAILED(hr))
  300. {
  301. hr=pStreamInit->Save(pstm, FALSE);
  302. if (!FAILED(hr))
  303. {
  304. *ppstm=pstm;
  305. pstm->AddRef();
  306. }
  307. pstm->Release();
  308. }
  309. pStreamInit->Release();
  310. }
  311. }
  312. else
  313. {
  314. hr = HrGetDataStream(pUnkTrident,
  315. #ifndef WIN16
  316. CF_UNICODETEXT,
  317. #else
  318. CF_TEXT,
  319. #endif
  320. ppstm);
  321. }
  322. return hr;
  323. }
  324. HRESULT HrBindToUrl(LPCSTR pszUrl, LPSTREAM *ppstm)
  325. {
  326. BYTE buf[MAX_CACHE_ENTRY_INFO_SIZE];
  327. INTERNET_CACHE_ENTRY_INFO *pCacheInfo = (INTERNET_CACHE_ENTRY_INFO *) buf;
  328. DWORD cInfo = sizeof(buf);
  329. HRESULT hr;
  330. pCacheInfo->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFO);
  331. // try to get from the cache
  332. if (RetrieveUrlCacheEntryFileA(pszUrl, pCacheInfo, &cInfo, 0))
  333. {
  334. UnlockUrlCacheEntryFile(pszUrl, 0);
  335. if (OpenFileStream(pCacheInfo->lpszLocalFileName, OPEN_EXISTING, GENERIC_READ, ppstm)==S_OK)
  336. return S_OK;
  337. }
  338. if (URLOpenBlockingStreamA(NULL, pszUrl, ppstm, 0, NULL)!=S_OK)
  339. return MIME_E_URL_NOTFOUND;
  340. return S_OK;
  341. }
  342. HRESULT HrGetStyleTag(IHTMLDocument2 *pDoc, BSTR *pbstr)
  343. {
  344. IHTMLStyleSheet *pStyle;
  345. VARIANTARG va1, va2;
  346. if (pDoc == NULL || pbstr == NULL)
  347. return E_INVALIDARG;
  348. *pbstr=NULL;
  349. if (HrGetStyleSheet(pDoc, &pStyle)==S_OK)
  350. {
  351. pStyle->get_cssText(pbstr);
  352. pStyle->Release();
  353. }
  354. return *pbstr ? S_OK : E_FAIL;
  355. }
  356. HRESULT HrFindUrlInMsg(LPMIMEMESSAGE pMsg, LPSTR lpszUrl, DWORD dwFlags, LPSTREAM *ppstm)
  357. {
  358. HBODY hBody=HBODY_ROOT;
  359. HRESULT hr = E_FAIL;
  360. LPSTR lpszFree=0;
  361. if (pMsg && lpszUrl)
  362. {
  363. // if it's an MHTML: url then we have to fixup to get the cid:
  364. if (StrCmpNIA(lpszUrl, "mhtml:", 6)==0 &&
  365. !FAILED(MimeOleParseMhtmlUrl(lpszUrl, NULL, &lpszFree)))
  366. lpszUrl = lpszFree;
  367. if (!(dwFlags & FINDURL_SEARCH_RELATED_ONLY) || MimeOleGetRelatedSection(pMsg, FALSE, &hBody, NULL)==S_OK)
  368. {
  369. if (!FAILED(hr = pMsg->ResolveURL(hBody, NULL, lpszUrl, 0, &hBody)) && ppstm)
  370. hr = pMsg->BindToObject(hBody, IID_IStream, (LPVOID *)ppstm);
  371. }
  372. }
  373. SafeMemFree(lpszFree);
  374. return hr;
  375. }
  376. HRESULT HrSniffStreamFileExt(LPSTREAM pstm, LPSTR *lplpszExt)
  377. {
  378. BYTE pb[4096];
  379. LPWSTR lpszW;
  380. TCHAR rgch[MAX_PATH];
  381. if (!FAILED(pstm->Read(&pb, 4096, NULL)))
  382. {
  383. if (!FAILED(FindMimeFromData(NULL, NULL, pb, 4096, NULL, NULL, &lpszW, 0)))
  384. {
  385. WideCharToMultiByte(CP_ACP, 0, lpszW, -1, rgch, MAX_PATH, NULL, NULL);
  386. return MimeOleGetContentTypeExt(rgch, lplpszExt);
  387. }
  388. }
  389. return S_FALSE;
  390. }
  391. HRESULT UnWrapStyleSheetUrl(BSTR bstrStyleUrl, BSTR *pbstrUrl)
  392. {
  393. LPWSTR lpszLeftParaW=0,
  394. lpszRightParaW=0;
  395. LPWSTR pszUrlW;
  396. // remove 'url()' wrapping from url
  397. *pbstrUrl = NULL;
  398. if (!bstrStyleUrl)
  399. return E_FAIL;
  400. if (StrCmpIW(bstrStyleUrl, L"none")==0) // 'none' means there isn't one!!!
  401. return E_FAIL;
  402. pszUrlW = PszDupW(bstrStyleUrl);
  403. if (!pszUrlW)
  404. return TraceResult(E_OUTOFMEMORY);
  405. if (*pszUrlW != 0)
  406. {
  407. DWORD cchSize = (lstrlenW(pszUrlW) + 1);
  408. lpszLeftParaW = StrChrW(pszUrlW, '(');
  409. if (lpszLeftParaW)
  410. {
  411. lpszRightParaW = StrChrW(lpszLeftParaW, ')');
  412. if(lpszRightParaW)
  413. {
  414. *lpszRightParaW = 0;
  415. // strcpy same block is ok, as it's a shift down.
  416. StrCpyNW(pszUrlW, ++lpszLeftParaW, cchSize);
  417. }
  418. }
  419. }
  420. *pbstrUrl = SysAllocString(pszUrlW);
  421. MemFree(pszUrlW);
  422. return *pbstrUrl ? S_OK : E_OUTOFMEMORY;
  423. }
  424. HRESULT WrapStyleSheetUrl(BSTR bstrUrl, BSTR *pbstrStyleUrl)
  425. {
  426. // simply put 'url()' around the url
  427. DWORD cchSize = (SysStringLen(bstrUrl) + 6);
  428. *pbstrStyleUrl = SysAllocStringLen(NULL, cchSize);
  429. if (*pbstrStyleUrl == NULL)
  430. return E_OUTOFMEMORY;
  431. StrCpyNW(*pbstrStyleUrl, L"url(", cchSize);
  432. StrCatBuffW(*pbstrStyleUrl, bstrUrl, cchSize);
  433. StrCatBuffW(*pbstrStyleUrl, L")", cchSize);
  434. StrCpyW(*pbstrStyleUrl, L"url(");
  435. StrCatW(*pbstrStyleUrl, bstrUrl);
  436. StrCatW(*pbstrStyleUrl, L")");
  437. return S_OK;
  438. }
  439. /*
  440. * GetBackgroundImage
  441. *
  442. * Trident does not have a very clean OM for getting a background image. You get get the BACKGROUND property on
  443. * the <body> tag and/or the background-url propetry in the body's sytle sheet, but neither of these OM methods will
  444. * combine with any <BASE> url's. So, if the Url is not absolute we have to hunt around for the <BASE> ourselves
  445. // ugh. This is really disgusting. Trident has no object model for getting a fixed up URL to the background image.
  446. // it doesn't comine with the base, so the URL is relative and useless to us. We have to do all this work manually.
  447. // We get a collection of <BASE> tags and find the sourceIndex of the <BODY> tag. We look for the <BASE> tag with the
  448. // highest sourceIndex below the body's sourceIndex and comine this guy.
  449. */
  450. HRESULT GetBackgroundImage(IHTMLDocument2 *pDoc, BSTR *pbstrUrl)
  451. {
  452. HRESULT hr;
  453. IMimeEditTagCollection *pCollect;
  454. IMimeEditTag *pTag;
  455. ULONG cFetched;
  456. BSTR bstrSrc;
  457. if (pDoc == NULL || pbstrUrl == NULL)
  458. return E_INVALIDARG;
  459. *pbstrUrl = NULL;
  460. // use the background image collection to get the first background in the precedence order
  461. if (CreateBGImageCollection(pDoc, &pCollect)==S_OK)
  462. {
  463. pCollect->Reset();
  464. if (pCollect->Next(1, &pTag, &cFetched)==S_OK && cFetched==1)
  465. {
  466. pTag->GetSrc(pbstrUrl);
  467. pTag->Release();
  468. }
  469. pCollect->Release();
  470. }
  471. return (*pbstrUrl == NULL ? E_FAIL : S_OK);
  472. }
  473. HRESULT SetBackgroundImage(IHTMLDocument2 *pDoc, BSTR bstrUrl)
  474. {
  475. IMimeEditTagCollection *pCollect;
  476. IMimeEditTag *pTag;
  477. IHTMLBodyElement *pBody;
  478. ULONG cFetched;
  479. BSTR bstrSrc;
  480. HRESULT hr = E_FAIL;
  481. if (pDoc == NULL)
  482. return E_INVALIDARG;
  483. // first we use the background image collection to get the
  484. // first background in the precedence order if one is present then
  485. // we use whatever tag this is. If not then we use the body background as that
  486. // is our prefered client-interop method
  487. if (CreateBGImageCollection(pDoc, &pCollect)==S_OK)
  488. {
  489. pCollect->Reset();
  490. if (pCollect->Next(1, &pTag, &cFetched)==S_OK && cFetched==1)
  491. {
  492. hr = pTag->SetSrc(bstrUrl);
  493. pTag->Release();
  494. }
  495. pCollect->Release();
  496. }
  497. if (hr == S_OK) // if we found one already
  498. return S_OK;
  499. hr = HrGetBodyElement(pDoc, &pBody);
  500. if (!FAILED(hr))
  501. {
  502. hr = pBody->put_background(bstrUrl);
  503. pBody->Release();
  504. }
  505. return hr;
  506. }
  507. HRESULT HrCopyStyleSheets(IHTMLDocument2 *pDocSrc, IHTMLDocument2 *pDocDest)
  508. {
  509. IHTMLStyleSheet *pStyleSrc=0,
  510. *pStyleDest=0;
  511. LONG lRule=0,
  512. lRules=0;
  513. IHTMLStyleSheetRulesCollection *pCollectRules=0;
  514. IHTMLStyleSheetRule *pRule=0;
  515. IHTMLRuleStyle *pRuleStyle=0;
  516. BSTR bstrSelector=0,
  517. bstrRule=0;
  518. if (pDocSrc == NULL || pDocDest == NULL)
  519. return E_INVALIDARG;
  520. if (HrGetStyleSheet(pDocDest, &pStyleDest)==S_OK)
  521. {
  522. // remove all the rules on the destination style sheet
  523. while (!FAILED(pStyleDest->removeRule(0)));
  524. if (HrGetStyleSheet(pDocSrc, &pStyleSrc)==S_OK)
  525. {
  526. // walk rules collection on source adding to dest
  527. if (pStyleSrc->get_rules(&pCollectRules)==S_OK)
  528. {
  529. lRules=0;
  530. pCollectRules->get_length(&lRules);
  531. for (lRule = 0; lRule < lRules; lRule++)
  532. {
  533. if (pCollectRules->item(lRule, &pRule)==S_OK)
  534. {
  535. if (pRule->get_selectorText(&bstrSelector)==S_OK)
  536. {
  537. if (pRule->get_style(&pRuleStyle)==S_OK)
  538. {
  539. if (pRuleStyle->get_cssText(&bstrRule)==S_OK)
  540. {
  541. LONG l;
  542. l=0;
  543. pStyleDest->addRule(bstrSelector, bstrRule, -1, &l);
  544. SysFreeString(bstrRule);
  545. }
  546. pRuleStyle->Release();
  547. }
  548. SysFreeString(bstrSelector);
  549. }
  550. pRule->Release();
  551. }
  552. }
  553. pCollectRules->Release();
  554. }
  555. pStyleSrc->Release();
  556. }
  557. pStyleDest->Release();
  558. }
  559. return S_OK;
  560. }
  561. HRESULT HrCopyBackground(IHTMLDocument2 *pDocSrc, IHTMLDocument2 *pDocDest)
  562. {
  563. HRESULT hr;
  564. IHTMLBodyElement *pBodySrc=0;
  565. IHTMLBodyElement *pBodyDest=0;
  566. BSTR bstrUrl=0;
  567. VARIANT var;
  568. var.vt = VT_BSTR;
  569. var.bstrVal = NULL;
  570. hr = HrGetBodyElement(pDocSrc, &pBodySrc);
  571. if(FAILED(hr))
  572. goto error;
  573. hr = HrGetBodyElement(pDocDest, &pBodyDest);
  574. if(FAILED(hr))
  575. goto error;
  576. GetBackgroundImage(pDocSrc, &bstrUrl);
  577. hr = pBodyDest->put_background(bstrUrl);
  578. if(FAILED(hr))
  579. goto error;
  580. hr=pBodySrc->get_bgColor(&var);
  581. if(FAILED(hr))
  582. goto error;
  583. hr=pBodyDest->put_bgColor(var);
  584. if(FAILED(hr))
  585. goto error;
  586. error:
  587. ReleaseObj(pBodySrc);
  588. ReleaseObj(pBodyDest);
  589. SysFreeString(bstrUrl);
  590. SysFreeString(var.bstrVal);
  591. return hr;
  592. }
  593. HRESULT HrRemoveStyleSheets(IHTMLDocument2 *pDoc)
  594. {
  595. IHTMLStyleSheet *pStyle=0;
  596. IHTMLBodyElement *pBody=0;
  597. if(pDoc == NULL)
  598. return E_INVALIDARG;
  599. if (HrGetBodyElement(pDoc, &pBody)==S_OK)
  600. {
  601. HrSetMember(pBody, (BSTR)c_bstr_STYLE, NULL);
  602. HrSetMember(pBody, (BSTR)c_bstr_LEFTMARGIN, NULL);
  603. HrSetMember(pBody, (BSTR)c_bstr_TOPMARGIN, NULL);
  604. pBody->Release();
  605. }
  606. if(HrGetStyleSheet(pDoc, &pStyle)==S_OK)
  607. {
  608. while (!FAILED(pStyle->removeRule(0)));
  609. pStyle->Release();
  610. }
  611. return S_OK;
  612. }
  613. HRESULT HrRemoveBackground(IHTMLDocument2 *pDoc)
  614. {
  615. HRESULT hr;
  616. IHTMLBodyElement *pBody=0;
  617. VARIANT var;
  618. var.vt = VT_BSTR;
  619. var.bstrVal = NULL;
  620. hr = HrGetBodyElement(pDoc, &pBody);
  621. if(FAILED(hr))
  622. goto error;
  623. hr = pBody->put_background(NULL);
  624. if(FAILED(hr))
  625. goto error;
  626. hr = pBody->put_bgColor(var);
  627. if(FAILED(hr))
  628. goto error;
  629. error:
  630. ReleaseObj(pBody);
  631. return hr;
  632. }
  633. HRESULT FindStyleRule(IHTMLDocument2 *pDoc, LPCWSTR pszSelectorW, IHTMLRuleStyle **ppRuleStyle)
  634. {
  635. IHTMLBodyElement *pBody;
  636. IHTMLElement *pElem;
  637. IHTMLStyle *pStyleAttrib=0;
  638. IHTMLStyleSheet *pStyleTag=0;
  639. IHTMLStyleSheetRulesCollection *pCollectRules=0;
  640. IHTMLStyleSheetRule *pRule=0;
  641. LONG lRule=0,
  642. lRules=0;
  643. BSTR bstrSelector=0;
  644. Assert (pDoc);
  645. *ppRuleStyle = NULL;
  646. if (HrGetStyleSheet(pDoc, &pStyleTag)==S_OK)
  647. {
  648. pStyleTag->get_rules(&pCollectRules);
  649. if (pCollectRules)
  650. {
  651. pCollectRules->get_length(&lRules);
  652. for (lRule = 0; lRule < lRules; lRule++)
  653. {
  654. pCollectRules->item(lRule, &pRule);
  655. if (pRule)
  656. {
  657. pRule->get_selectorText(&bstrSelector);
  658. if (bstrSelector)
  659. {
  660. if (StrCmpIW(bstrSelector, pszSelectorW)==0)
  661. pRule->get_style(ppRuleStyle);
  662. SysFreeString(bstrSelector);
  663. bstrSelector=0;
  664. }
  665. SafeRelease(pRule);
  666. }
  667. }
  668. pCollectRules->Release();
  669. }
  670. pStyleTag->Release();
  671. }
  672. return *ppRuleStyle ? S_OK : E_FAIL;
  673. }
  674. HRESULT ClearStyleSheetBackground(IHTMLDocument2 *pDoc)
  675. {
  676. IHTMLBodyElement *pBody;
  677. IHTMLElement *pElem;
  678. IHTMLStyle *pStyleAttrib=0;
  679. IHTMLRuleStyle *pRuleStyle=0;
  680. Assert (pDoc);
  681. if (HrGetBodyElement(pDoc, &pBody)==S_OK)
  682. {
  683. if (pBody->QueryInterface(IID_IHTMLElement, (LPVOID *)&pElem)==S_OK)
  684. {
  685. // NULL out the style sheet property.
  686. pElem->get_style(&pStyleAttrib);
  687. if (pStyleAttrib)
  688. {
  689. pStyleAttrib->put_backgroundImage(NULL);
  690. pStyleAttrib->Release();
  691. }
  692. pElem->Release();
  693. }
  694. pBody->Release();
  695. }
  696. if (FindStyleRule(pDoc, L"BODY", &pRuleStyle)==S_OK)
  697. {
  698. pRuleStyle->put_backgroundImage(NULL);
  699. pRuleStyle->Release();
  700. }
  701. return S_OK;
  702. }
  703. HRESULT GetBackgroundSound(IHTMLDocument2 *pDoc, int *pcRepeat, BSTR *pbstrUrl)
  704. {
  705. IHTMLElementCollection *pCollect;
  706. IHTMLBGsound *pBGSnd;
  707. VARIANT v;
  708. HRESULT hr = E_FAIL;
  709. TraceCall ("GetBackgroundSound");
  710. if (pDoc == NULL || pbstrUrl == NULL || pcRepeat == NULL)
  711. return TraceResult(E_INVALIDARG);
  712. *pbstrUrl = NULL;
  713. *pcRepeat=1;
  714. if (!FAILED(HrGetCollectionOf(pDoc, (BSTR)c_bstr_BGSOUND, &pCollect)))
  715. {
  716. // get the first BGSOUND in the document
  717. if (HrGetCollectionItem(pCollect, 0, IID_IHTMLBGsound, (LPVOID *)&pBGSnd)==S_OK)
  718. {
  719. pBGSnd->get_src(pbstrUrl);
  720. if (*pbstrUrl)
  721. {
  722. // valid bstr, make sure it's non null
  723. if (**pbstrUrl)
  724. {
  725. hr = S_OK;
  726. if (pBGSnd->get_loop(&v)==S_OK)
  727. {
  728. if (v.vt == VT_I4)
  729. *pcRepeat = v.lVal;
  730. else
  731. if (v.vt == VT_BSTR)
  732. {
  733. // returns a string with "INFINITE"
  734. *pcRepeat = -1;
  735. SysFreeString(v.bstrVal);
  736. }
  737. else
  738. AssertSz(FALSE, "bad-type from BGSOUND");
  739. }
  740. }
  741. else
  742. {
  743. SysFreeString(*pbstrUrl);
  744. *pbstrUrl = NULL;
  745. }
  746. }
  747. pBGSnd->Release();
  748. }
  749. pCollect->Release();
  750. }
  751. return hr;
  752. }
  753. HRESULT SetBackgroundSound(IHTMLDocument2 *pDoc, int cRepeat, BSTR bstrUrl)
  754. {
  755. IHTMLElementCollection *pCollect;
  756. IHTMLElement *pElem;
  757. IHTMLElement2 *pElem2;
  758. IHTMLBodyElement *pBody;
  759. IHTMLBGsound *pBGSnd;
  760. VARIANT v;
  761. int count,
  762. i;
  763. TraceCall ("GetBackgroundSound");
  764. if (pDoc == NULL)
  765. return TraceResult(E_INVALIDARG);
  766. // remove an existing background sounds
  767. if (!FAILED(HrGetCollectionOf(pDoc, (BSTR)c_bstr_BGSOUND, &pCollect)))
  768. {
  769. count = (int)UlGetCollectionCount(pCollect);
  770. for (i=0; i<count; i++)
  771. {
  772. if (HrGetCollectionItem(pCollect, i, IID_IHTMLElement, (LPVOID *)&pElem)==S_OK)
  773. {
  774. pElem->put_outerHTML(NULL);
  775. pElem->Release();
  776. }
  777. }
  778. pCollect->Release();
  779. }
  780. // if we're setting a new one, then insert after the body tag
  781. if (bstrUrl && *bstrUrl)
  782. {
  783. pElem = NULL; // trident' OM (returns S_OK with pElem==NULL)
  784. pDoc->createElement((BSTR)c_bstr_BGSOUND, &pElem);
  785. if (pElem)
  786. {
  787. if (pElem->QueryInterface(IID_IHTMLBGsound, (LPVOID *)&pBGSnd)==S_OK)
  788. {
  789. // set the source attribute
  790. pBGSnd->put_src(bstrUrl);
  791. // set the loop count
  792. v.vt = VT_I4;
  793. v.lVal = cRepeat;
  794. pBGSnd->put_loop(v);
  795. // insert the tag into the document
  796. if (HrGetBodyElement(pDoc, &pBody)==S_OK)
  797. {
  798. if (!FAILED(pBody->QueryInterface(IID_IHTMLElement2, (LPVOID *)&pElem2)))
  799. {
  800. pElem2->insertAdjacentElement((BSTR)c_bstr_AfterBegin, pElem, NULL);
  801. pElem2->Release();
  802. }
  803. pBody->Release();
  804. }
  805. pBGSnd->Release();
  806. }
  807. pElem->Release();
  808. }
  809. }
  810. return S_OK;
  811. }
  812. HRESULT FindNearestBaseUrl(IHTMLDocument2 *pDoc, IHTMLElement *pElemTag, BSTR *pbstrBaseUrl)
  813. {
  814. IHTMLElementCollection *pCollect;
  815. IHTMLElement *pElem;
  816. IHTMLBaseElement *pBase;
  817. LONG lBasePos=0,
  818. lBasePosSoFar=0,
  819. lIndex=0;
  820. BSTR bstr=NULL,
  821. bstrBase=NULL;
  822. int count;
  823. TraceCall ("FindNearestBaseUrl");
  824. if (pDoc == NULL || pbstrBaseUrl == NULL || pElemTag == NULL)
  825. return TraceResult(E_INVALIDARG);
  826. *pbstrBaseUrl = NULL;
  827. pElemTag->get_sourceIndex(&lIndex);
  828. if (!FAILED(HrGetCollectionOf(pDoc, (BSTR)c_bstr_BASE, &pCollect)))
  829. {
  830. count = (int)UlGetCollectionCount(pCollect);
  831. for (int i=0; i<count; i++)
  832. {
  833. if (!FAILED(HrGetCollectionItem(pCollect, i, IID_IHTMLElement, (LPVOID *)&pElem)))
  834. {
  835. pElem->get_sourceIndex(&lBasePos);
  836. if (lBasePos < lIndex &&
  837. lBasePos >= lBasePosSoFar)
  838. {
  839. if (!FAILED(pElem->QueryInterface(IID_IHTMLBaseElement, (LPVOID *)&pBase)))
  840. {
  841. SysFreeString(bstr);
  842. if (pBase->get_href(&bstr)==S_OK && bstr)
  843. {
  844. SysFreeString(bstrBase);
  845. bstrBase = bstr;
  846. lBasePosSoFar = lBasePos;
  847. }
  848. pBase->Release();
  849. }
  850. }
  851. pElem->Release();
  852. }
  853. }
  854. pCollect->Release();
  855. }
  856. *pbstrBaseUrl = bstrBase;
  857. return bstrBase ? S_OK : TraceResult(E_FAIL);
  858. }
  859. #define CCHMAX_SNIFF_BUFFER 4096
  860. HRESULT SniffStreamForMimeType(LPSTREAM pstm, LPWSTR *ppszType)
  861. {
  862. BYTE pb[CCHMAX_SNIFF_BUFFER];
  863. HRESULT hr = E_FAIL;
  864. *ppszType = NULL;
  865. if (!FAILED(pstm->Read(&pb, CCHMAX_SNIFF_BUFFER, NULL)))
  866. hr = FindMimeFromData(NULL, NULL, pb, CCHMAX_SNIFF_BUFFER, NULL, NULL, ppszType, 0);
  867. return hr;
  868. }
  869. HRESULT CreateCacheFileFromStream(LPSTR pszUrl, LPSTREAM pstm)
  870. {
  871. TCHAR rgchFileName[MAX_PATH];
  872. HRESULT hr;
  873. FILETIME ft;
  874. rgchFileName[0] = 0;
  875. if (pstm == NULL || pszUrl == NULL)
  876. return TraceResult(E_INVALIDARG);
  877. if (!CreateUrlCacheEntryA(pszUrl, 0, NULL, rgchFileName, 0))
  878. {
  879. hr = TraceResult(E_FAIL);
  880. goto error;
  881. }
  882. hr = WriteStreamToFile(pstm, rgchFileName, CREATE_ALWAYS, GENERIC_WRITE);
  883. if (FAILED(hr))
  884. {
  885. TraceResult(hr);
  886. goto error;
  887. }
  888. ft.dwLowDateTime = 0;
  889. ft.dwHighDateTime = 0;
  890. if (!CommitUrlCacheEntryA( pszUrl, rgchFileName,
  891. ft, ft,
  892. NORMAL_CACHE_ENTRY,
  893. NULL, 0, NULL, 0))
  894. {
  895. hr = TraceResult(E_FAIL);
  896. goto error;
  897. }
  898. error:
  899. return hr;
  900. };