Source code of Windows XP (NT5)
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.

2774 lines
71 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // xmlutil.cpp
  4. //
  5. // XML item helper functions.
  6. //
  7. // History:
  8. //
  9. // 4/1/97 edwardp Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "cdfidl.h"
  17. #include "xmlutil.h"
  18. #include "winineti.h"
  19. #include <ocidl.h> // IPersistStreamInit.
  20. //
  21. // Function prototypes.
  22. //
  23. //
  24. // XML helper functions.
  25. //
  26. ////////////////////////////////////////////////////////////////////////////////
  27. //
  28. // *** XML_MarkCacheEntrySticky ***
  29. //
  30. // Description:
  31. // Marks the cache entry for the given URL as sticky by setting its
  32. // expiration delta to be very high
  33. //
  34. // Parameters:
  35. // [In] lpszUrl - url for cache entry to make sticky
  36. //
  37. // Return:
  38. // S_OK if the url entry was successfully marked sticky
  39. // E_FAIL otherwise.
  40. //
  41. ////////////////////////////////////////////////////////////////////////////////
  42. HRESULT XML_MarkCacheEntrySticky(LPTSTR lpszURL)
  43. {
  44. char chBuf[MAX_CACHE_ENTRY_INFO_SIZE];
  45. LPINTERNET_CACHE_ENTRY_INFO lpInfo = (LPINTERNET_CACHE_ENTRY_INFO) chBuf;
  46. DWORD dwSize = sizeof(chBuf);
  47. lpInfo->dwStructSize = dwSize;
  48. if (GetUrlCacheEntryInfo(lpszURL, lpInfo, &dwSize))
  49. {
  50. lpInfo->dwExemptDelta = 0xFFFFFFFF; // make VERY sticky
  51. if (SetUrlCacheEntryInfo(lpszURL, lpInfo, CACHE_ENTRY_EXEMPT_DELTA_FC))
  52. {
  53. return S_OK;
  54. }
  55. }
  56. return E_FAIL;
  57. }
  58. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  59. //
  60. // *** XML_SynchronousParse ***
  61. //
  62. //
  63. // Description:
  64. // Synchronously parses the given URL.
  65. //
  66. // Parameters:
  67. // [In] pIXMLDocument - An interface pointer to an XML document object.
  68. // [In] pidl - The pidl of the cdf file (contains the full path).
  69. //
  70. // Return:
  71. // S_OK if the object was parsed successfully.
  72. // E_FAIL otherwise.
  73. //
  74. // Comments:
  75. //
  76. //
  77. ////////////////////////////////////////////////////////////////////////////////
  78. HRESULT
  79. XML_SynchronousParse(
  80. IXMLDocument* pIXMLDocument,
  81. LPTSTR szPath
  82. )
  83. {
  84. ASSERT(pIXMLDocument);
  85. ASSERT(szPath);
  86. HRESULT hr;
  87. IPersistStreamInit* pIPersistStreamInit;
  88. hr = pIXMLDocument->QueryInterface(IID_IPersistStreamInit,
  89. (void**)&pIPersistStreamInit);
  90. if (SUCCEEDED(hr))
  91. {
  92. ASSERT(pIPersistStreamInit);
  93. IStream* pIStream;
  94. //
  95. // URLOpenBlockingStream pumps window messages! Don't use it!
  96. //
  97. //hr = URLOpenBlockingStream(NULL, szPath, &pIStream, 0, NULL);
  98. hr = SHCreateStreamOnFile(szPath, STGM_READ, &pIStream);
  99. TraceMsg(TF_CDFPARSE, "[%s SHCreateStreamOnFileW %s %s %s]",
  100. PathIsURL(szPath) ? TEXT("*** ") : TEXT(""), szPath,
  101. SUCCEEDED(hr) ? TEXT("SUCCEEDED") : TEXT("FAILED"),
  102. PathIsURL(szPath) ? TEXT("***") : TEXT(""));
  103. if (SUCCEEDED(hr))
  104. {
  105. ASSERT(pIStream);
  106. //
  107. // Load loads and parses the file. If this call succeeds the cdf
  108. // will be displayed. If it fails none of the cdf is displayed.
  109. //
  110. hr = pIPersistStreamInit->Load(pIStream);
  111. TraceMsg(TF_CDFPARSE, "[XML Parser %s]",
  112. SUCCEEDED(hr) ? TEXT("SUCCEEDED") : TEXT("FAILED"));
  113. pIStream->Release();
  114. //
  115. // If CDFVIEW is downloading a CDF from the net mark it as sticky
  116. // in the cache
  117. //
  118. if (PathIsURL(szPath))
  119. {
  120. XML_MarkCacheEntrySticky(szPath);
  121. }
  122. }
  123. pIPersistStreamInit->Release();
  124. }
  125. return hr;
  126. }
  127. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  128. //
  129. // *** XML_DownloadImages ***
  130. //
  131. //
  132. // Description:
  133. //
  134. //
  135. // Parameters:
  136. //
  137. //
  138. // Return:
  139. //
  140. //
  141. // Comments:
  142. //
  143. //
  144. ////////////////////////////////////////////////////////////////////////////////
  145. HRESULT
  146. XML_DownloadLogo(
  147. IXMLDocument *pIXMLDocument
  148. )
  149. {
  150. ASSERT(pIXMLDocument);
  151. HRESULT hr;
  152. IXMLElement* pIXMLElement;
  153. LONG nIndex;
  154. hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
  155. if (SUCCEEDED(hr))
  156. {
  157. ASSERT(pIXMLElement);
  158. BSTR bstrURL = XML_GetAttribute(pIXMLElement, XML_LOGO);
  159. if (bstrURL)
  160. {
  161. hr = XML_DownloadImage(bstrURL);
  162. SysFreeString(bstrURL);
  163. }
  164. //
  165. // Download the wide logo also.
  166. //
  167. bstrURL = XML_GetAttribute(pIXMLElement, XML_LOGO_WIDE);
  168. if (bstrURL)
  169. {
  170. hr = XML_DownloadImage(bstrURL);
  171. SysFreeString(bstrURL);
  172. }
  173. pIXMLElement->Release();
  174. }
  175. return hr;
  176. }
  177. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  178. //
  179. // *** XML_DownloadImages ***
  180. //
  181. //
  182. // Description:
  183. //
  184. //
  185. // Parameters:
  186. //
  187. //
  188. // Return:
  189. //
  190. //
  191. // Comments:
  192. //
  193. //
  194. ////////////////////////////////////////////////////////////////////////////////
  195. HRESULT
  196. XML_DownloadImages(
  197. IXMLDocument *pIXMLDocument
  198. )
  199. {
  200. ASSERT(pIXMLDocument);
  201. HRESULT hr;
  202. IXMLElement* pIXMLElement;
  203. LONG nIndex;
  204. hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
  205. if (SUCCEEDED(hr))
  206. {
  207. ASSERT(pIXMLElement);
  208. hr = XML_RecursiveImageDownload(pIXMLElement);
  209. pIXMLElement->Release();
  210. }
  211. return hr;
  212. }
  213. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  214. //
  215. // *** XML_RecuriveImageDownload ***
  216. //
  217. //
  218. // Description:
  219. //
  220. //
  221. // Parameters:
  222. //
  223. //
  224. // Return:
  225. //
  226. //
  227. // Comments:
  228. //
  229. //
  230. ////////////////////////////////////////////////////////////////////////////////
  231. HRESULT
  232. XML_RecursiveImageDownload(
  233. IXMLElement* pIXMLElement
  234. )
  235. {
  236. ASSERT(pIXMLElement);
  237. HRESULT hr = S_OK;
  238. BSTR bstrTagName;
  239. HRESULT hr2 = pIXMLElement->get_tagName(&bstrTagName);
  240. if (SUCCEEDED(hr2) && bstrTagName)
  241. {
  242. if (StrEqlW(bstrTagName, WSTR_LOGO))
  243. {
  244. BSTR bstrURL = XML_GetAttribute(pIXMLElement, XML_HREF);
  245. if (bstrURL && *bstrURL != 0)
  246. {
  247. hr = XML_DownloadImage(bstrURL);
  248. SysFreeString(bstrURL);
  249. }
  250. }
  251. else if (XML_IsCdfDisplayable(pIXMLElement))
  252. {
  253. IXMLElementCollection* pIXMLElementCollection;
  254. hr2 = pIXMLElement->get_children(&pIXMLElementCollection);
  255. if (SUCCEEDED(hr2) && pIXMLElementCollection)
  256. {
  257. ASSERT(pIXMLElementCollection);
  258. LONG nCount;
  259. hr2 = pIXMLElementCollection->get_length(&nCount);
  260. ASSERT(SUCCEEDED(hr2) || (FAILED(hr2) && 0 == nCount));
  261. for (int i = 0; i < nCount; i++)
  262. {
  263. IXMLElement* pIXMLElementChild;
  264. hr2 = XML_GetElementByIndex(pIXMLElementCollection, i,
  265. &pIXMLElementChild);
  266. if (SUCCEEDED(hr2))
  267. {
  268. ASSERT (pIXMLElementChild);
  269. XML_RecursiveImageDownload(pIXMLElementChild);
  270. pIXMLElementChild->Release();
  271. }
  272. }
  273. pIXMLElementCollection->Release();
  274. }
  275. }
  276. SysFreeString(bstrTagName);
  277. }
  278. return hr;
  279. }
  280. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  281. //
  282. // *** XML_DownloadImage ***
  283. //
  284. //
  285. // Description:
  286. //
  287. //
  288. // Parameters:
  289. //
  290. //
  291. // Return:
  292. //
  293. //
  294. // Comments:
  295. //
  296. //
  297. ////////////////////////////////////////////////////////////////////////////////
  298. HRESULT
  299. XML_DownloadImage(
  300. LPCWSTR pwszURL
  301. )
  302. {
  303. ASSERT (pwszURL);
  304. HRESULT hr;
  305. WCHAR szFileW[MAX_PATH];
  306. hr = URLDownloadToCacheFileW(NULL, pwszURL, szFileW,
  307. ARRAYSIZE(szFileW), 0, NULL);
  308. //
  309. // Mark the logo in the cache as sticky
  310. //
  311. if (SUCCEEDED(hr))
  312. {
  313. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  314. SHUnicodeToTChar(pwszURL, szURL, ARRAYSIZE(szURL));
  315. XML_MarkCacheEntrySticky(szURL);
  316. }
  317. #ifdef DEBUG
  318. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  319. SHUnicodeToTChar(pwszURL, szURL, ARRAYSIZE(szURL));
  320. TraceMsg(TF_CDFPARSE,
  321. "[*** Image URLDownloadToCacheFileW %s %s ***]",
  322. szURL, SUCCEEDED(hr) ? TEXT("SUCCEEDED") :
  323. TEXT("FAILED"));
  324. #endif // DEBUG
  325. return hr;
  326. }
  327. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  328. //
  329. // *** XML_GetDocType ***
  330. //
  331. //
  332. // Description:
  333. // Returns the type of the given xml document.
  334. //
  335. // Parameters:
  336. // [In] pIXMLDocument - A pointer to the xml document.
  337. //
  338. // Return:
  339. // DOC_CHANNEL, DOC_DESKTOPCOMPONENT, DOC_SOFTWAREUPDATE, or DOC_UNKNOWN.
  340. //
  341. // Comments:
  342. // If at the root level of a channel an ITEM contains a USAGE type of
  343. // DesktopComponent then the document is a Desktop Component otherwise
  344. // it is a channel.
  345. //
  346. ////////////////////////////////////////////////////////////////////////////////
  347. XMLDOCTYPE
  348. XML_GetDocType(IXMLDocument* pIXMLDocument)
  349. {
  350. ASSERT(pIXMLDocument);
  351. XMLDOCTYPE xdtRet;
  352. IXMLElement* pIXMLElement;
  353. LONG nIndex;
  354. HRESULT hr = XML_GetFirstDesktopComponentElement(pIXMLDocument,
  355. &pIXMLElement,
  356. &nIndex);
  357. if (SUCCEEDED(hr))
  358. {
  359. ASSERT(pIXMLElement);
  360. xdtRet = DOC_DESKTOPCOMPONENT;
  361. pIXMLElement->Release();
  362. }
  363. else
  364. {
  365. hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement,
  366. &nIndex);
  367. if (SUCCEEDED(hr))
  368. {
  369. ASSERT(pIXMLElement);
  370. BSTR bstr = XML_GetAttribute( pIXMLElement, XML_USAGE_SOFTWAREUPDATE );
  371. if (bstr)
  372. {
  373. SysFreeString(bstr);
  374. xdtRet = DOC_SOFTWAREUPDATE;
  375. }
  376. else
  377. {
  378. xdtRet = DOC_CHANNEL;
  379. }
  380. pIXMLElement->Release();
  381. }
  382. else
  383. {
  384. xdtRet = DOC_UNKNOWN;
  385. }
  386. }
  387. return xdtRet;
  388. }
  389. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  390. //
  391. // *** XML_GetChildElementCollection ***
  392. //
  393. //
  394. // Description:
  395. // Returns an element collection given the parent collection and an index.
  396. //
  397. // Parameters:
  398. // [In] pParentIXMLElementCollection - The parent collection.
  399. // [In] nIndex - Index to the requested collection.
  400. // [Out] ppIXMLElementCollection - A pointer that receives the
  401. // requested collection.
  402. //
  403. // Return:
  404. // S_OK if the collection is returned.
  405. // E_FAIL otherwise.
  406. //
  407. // Comments:
  408. // The caller is responsible for calling Release() on the returned interface
  409. // pointer.
  410. //
  411. ////////////////////////////////////////////////////////////////////////////////
  412. HRESULT
  413. XML_GetChildElementCollection(
  414. IXMLElementCollection *pParentIXMLElementCollection,
  415. LONG nIndex,
  416. IXMLElementCollection** ppIXMLElementCollection
  417. )
  418. {
  419. ASSERT(pParentIXMLElementCollection);
  420. ASSERT(ppIXMLElementCollection);
  421. HRESULT hr;
  422. IXMLElement* pIXMLElement;
  423. hr = XML_GetElementByIndex(pParentIXMLElementCollection, nIndex,
  424. &pIXMLElement);
  425. if (SUCCEEDED(hr))
  426. {
  427. ASSERT(pIXMLElement);
  428. hr = pIXMLElement->get_children(ppIXMLElementCollection);
  429. if(SUCCEEDED(hr) && !(*ppIXMLElementCollection))
  430. hr = E_FAIL;
  431. pIXMLElement->Release();
  432. }
  433. ASSERT((SUCCEEDED(hr) && (*ppIXMLElementCollection)) || FAILED(hr));
  434. return hr;
  435. }
  436. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  437. //
  438. // *** XML_GetElementByIndex ***
  439. //
  440. //
  441. // Description:
  442. // Returns the nIndex'th element of the given collection.
  443. //
  444. // Parameters:
  445. // [In] pIXMLElementCollection - A pointer to the collection.
  446. // [In] nIndex - The index of the item to retrieve.
  447. // [Out] ppIXMLElement - A pointer that receives the item.
  448. //
  449. // Return:
  450. // S_OK if the item was retrieved.
  451. // E_FAIL otherwise.
  452. //
  453. // Comments:
  454. // The caller is responsible for calling Release() on the returned interface
  455. // pointer.
  456. //
  457. ////////////////////////////////////////////////////////////////////////////////
  458. HRESULT
  459. XML_GetElementByIndex(
  460. IXMLElementCollection* pIXMLElementCollection,
  461. LONG nIndex,
  462. IXMLElement** ppIXMLElement
  463. )
  464. {
  465. ASSERT(pIXMLElementCollection);
  466. ASSERT(ppIXMLElement);
  467. HRESULT hr;
  468. VARIANT var1, var2;
  469. VariantInit(&var1);
  470. VariantInit(&var2);
  471. var1.vt = VT_I4;
  472. var1.lVal = nIndex;
  473. IDispatch* pIDispatch;
  474. hr = pIXMLElementCollection->item(var1, var2, &pIDispatch);
  475. if (SUCCEEDED(hr))
  476. {
  477. ASSERT(pIDispatch);
  478. hr = pIDispatch->QueryInterface(IID_IXMLElement, (void**)ppIXMLElement);
  479. pIDispatch->Release();
  480. }
  481. else
  482. {
  483. *ppIXMLElement = NULL;
  484. }
  485. ASSERT((SUCCEEDED(hr) && *ppIXMLElement) ||
  486. (FAILED(hr) && NULL == *ppIXMLElement));
  487. return hr;
  488. }
  489. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  490. //
  491. // *** XML_GetElementByName ***
  492. //
  493. //
  494. // Description:
  495. // Returns the first element with the given tag name.
  496. //
  497. // Parameters:
  498. // [In] pIXMLElementCollection - A pointer to the collection.
  499. // [In] nszNameW - The tag name of the item to retrieve.
  500. // [Out] ppIXMLElement - A pointer that receives the item.
  501. //
  502. // Return:
  503. // S_OK if the item was retrieved.
  504. // E_OUTOFMEMORY if a sys string could not be allocated.
  505. // E_FAIL otherwise.
  506. //
  507. // Comments:
  508. // The caller is responsible for calling Release() on the returned interface
  509. // pointer.
  510. //
  511. ////////////////////////////////////////////////////////////////////////////////
  512. HRESULT
  513. XML_GetElementByName(
  514. IXMLElementCollection* pIXMLElementCollection,
  515. LPWSTR szNameW,
  516. IXMLElement** ppIXMLElement
  517. )
  518. {
  519. ASSERT(pIXMLElementCollection);
  520. ASSERT(ppIXMLElement);
  521. HRESULT hr = E_FAIL;
  522. LONG nCount;
  523. HRESULT hr2 = pIXMLElementCollection->get_length(&nCount);
  524. ASSERT(SUCCEEDED(hr2) || (FAILED(hr2) && 0 == nCount));
  525. for (int i = 0, bElement = FALSE; (i < nCount) && !bElement; i++)
  526. {
  527. IXMLElement* pIXMLElement;
  528. hr2 = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElement);
  529. if (SUCCEEDED(hr2))
  530. {
  531. ASSERT(pIXMLElement);
  532. BSTR pStr;
  533. hr2 = pIXMLElement->get_tagName(&pStr);
  534. if (SUCCEEDED(hr2) && pStr)
  535. {
  536. ASSERT(pStr);
  537. if (bElement = StrEqlW(pStr, szNameW))
  538. {
  539. pIXMLElement->AddRef();
  540. *ppIXMLElement = pIXMLElement;
  541. hr = S_OK;
  542. }
  543. SysFreeString(pStr);
  544. }
  545. pIXMLElement->Release();
  546. }
  547. }
  548. hr = FAILED(hr2) ? hr2 : hr;
  549. /* Enable this when pIXMLElementCollection->item works with VT_BSTR
  550. VARIANT var1, var2;
  551. VariantInit(&var1);
  552. VariantInit(&var2);
  553. var1.vt = VT_BSTR;
  554. var1.bstrVal = SysAllocString(szNameW);
  555. var2.vt = VT_I4
  556. var2.lVal = 1;
  557. if (var1.bstrVal)
  558. {
  559. IDispatch* pIDispatch;
  560. hr = pIXMLElementCollection->item(var1, var2, &pIDispatch);
  561. if (SUCCEEDED(hr))
  562. {
  563. ASSERT(pIDispatch);
  564. hr = pIDispatch->QueryInterface(IID_IXMLElement,
  565. (void**)ppIXMLElement);
  566. pIDispatch->Release();
  567. }
  568. SysFreeString(var1.bstrVal);
  569. }
  570. else
  571. {
  572. hr = E_OUTOFMEMORY;
  573. }
  574. */
  575. ASSERT((SUCCEEDED(hr) && ppIXMLElement) || FAILED(hr));
  576. return hr;
  577. }
  578. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  579. //
  580. // *** XML_GetFirstChannelElement ***
  581. //
  582. //
  583. // Description:
  584. // Returns the IXMLElement of the first channel in the XML document.
  585. //
  586. // Parameters:
  587. // [In] pIXMLDocument - A pointer to the XML document object.
  588. // [Out] ppIXMLElement - The pointer that receives the element.
  589. // [Out] pnIndex - The index of the element.
  590. //
  591. // Return:
  592. // S_OK if the first channel element was returned.
  593. // E_FAIL if the element couldn't be returned.
  594. //
  595. // Comments:
  596. // This function can't call XML_GetElementByName to find the first channel.
  597. // XML channels can have a tag name of "Channel" or "CHAN".
  598. // XML_GetElementByName wouldn't be able to determine which of the items
  599. // came first if both where present in the XML doc.
  600. //
  601. // The caller is responsible for calling Release() on the returned interface
  602. // pointer. The return pointer is not NULL'ed out on error.
  603. //
  604. ////////////////////////////////////////////////////////////////////////////////
  605. HRESULT
  606. XML_GetFirstChannelElement(
  607. IXMLDocument* pIXMLDocument,
  608. IXMLElement** ppIXMLElement,
  609. PLONG pnIndex)
  610. {
  611. ASSERT(pIXMLDocument);
  612. ASSERT(ppIXMLElement);
  613. ASSERT(pnIndex);
  614. IXMLElement *pRootElem = NULL;
  615. HRESULT hr = E_FAIL;
  616. *pnIndex = 0;
  617. hr = pIXMLDocument->get_root(&pRootElem);
  618. if (SUCCEEDED(hr) && pRootElem)
  619. {
  620. ASSERT(pRootElem);
  621. if (XML_IsChannel(pRootElem))
  622. {
  623. *ppIXMLElement = pRootElem;
  624. hr = S_OK;
  625. }
  626. else
  627. {
  628. pRootElem->Release();
  629. hr = E_FAIL;
  630. }
  631. }
  632. else
  633. {
  634. hr = E_FAIL;
  635. }
  636. ASSERT((SUCCEEDED(hr) && (*ppIXMLElement)) || FAILED(hr));
  637. return hr;
  638. }
  639. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  640. //
  641. // *** XML_GetDesktopElementFromChannelElement ***
  642. //
  643. //
  644. // Description:
  645. // Returns the IXMLElement of the first dekstop component in the channel.
  646. //
  647. // Parameters:
  648. // [In] pChannelIXMLElement - A pointer to the XML channel element.
  649. // [Out] ppIXMLElement - The pointer that receives the element.
  650. // [Out] pnIndex - The index of the element.
  651. //
  652. // Return:
  653. // S_OK if the first desktop element was returned.
  654. // E_FAIL if the element couldn't be returned.
  655. //
  656. // Comments:
  657. // This looks for the first ITEM with a usage of DesktopComponent.
  658. //
  659. ////////////////////////////////////////////////////////////////////////////////
  660. HRESULT
  661. XML_GetDesktopElementFromChannelElement(
  662. IXMLElement* pChannelIXMLElement,
  663. IXMLElement** ppIXMLElement,
  664. PLONG pnIndex)
  665. {
  666. ASSERT(pChannelIXMLElement);
  667. ASSERT(ppIXMLElement);
  668. ASSERT(pnIndex);
  669. HRESULT hr;
  670. IXMLElementCollection* pIXMLElementCollection;
  671. hr = pChannelIXMLElement->get_children(&pIXMLElementCollection);
  672. if (SUCCEEDED(hr) && pIXMLElementCollection)
  673. {
  674. ASSERT(pIXMLElementCollection);
  675. LONG nCount;
  676. hr = pIXMLElementCollection->get_length(&nCount);
  677. ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount));
  678. hr = E_FAIL;
  679. for (int i = 0, bComponent = FALSE; (i < nCount) && !bComponent;
  680. i++)
  681. {
  682. IXMLElement* pIXMLElement;
  683. HRESULT hr2 = XML_GetElementByIndex(pIXMLElementCollection, i,
  684. &pIXMLElement);
  685. if (SUCCEEDED(hr2))
  686. {
  687. ASSERT(pIXMLElement);
  688. if (bComponent = XML_IsDesktopComponent(pIXMLElement))
  689. {
  690. pIXMLElement->AddRef();
  691. *ppIXMLElement = pIXMLElement;
  692. *pnIndex = i;
  693. hr = S_OK;
  694. }
  695. pIXMLElement->Release();
  696. }
  697. hr = FAILED(hr2) ? hr2 : hr;
  698. }
  699. pIXMLElementCollection->Release();
  700. }
  701. else
  702. {
  703. hr = E_FAIL;
  704. }
  705. return hr;
  706. }
  707. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  708. //
  709. // *** XML_GetFirstDesktopComponentElement ***
  710. //
  711. //
  712. // Description:
  713. // Returns the IXMLElement of the first dekstop component in the channel.
  714. //
  715. // Parameters:
  716. // [In] pIXMLDocument - A pointer to the XML document object.
  717. // [Out] ppIXMLElement - The pointer that receives the element.
  718. // [Out] pnIndex - The index of the element.
  719. //
  720. // Return:
  721. // S_OK if the first channel element was returned.
  722. // E_FAIL if the element couldn't be returned.
  723. //
  724. // Comments:
  725. // This function gets the first channel and then looks for the first
  726. // top-level ITEM with a usage of DesktopComponent.
  727. //
  728. ////////////////////////////////////////////////////////////////////////////////
  729. HRESULT
  730. XML_GetFirstDesktopComponentElement(
  731. IXMLDocument* pIXMLDocument,
  732. IXMLElement** ppIXMLElement,
  733. PLONG pnIndex)
  734. {
  735. ASSERT(pIXMLDocument);
  736. ASSERT(ppIXMLElement);
  737. ASSERT(pnIndex);
  738. HRESULT hr;
  739. IXMLElement* pChannelIXMLElement;
  740. LONG nIndex;
  741. hr = XML_GetFirstChannelElement(pIXMLDocument, &pChannelIXMLElement,
  742. &nIndex);
  743. if (SUCCEEDED(hr))
  744. {
  745. ASSERT(pChannelIXMLElement);
  746. hr = XML_GetDesktopElementFromChannelElement(pChannelIXMLElement,
  747. ppIXMLElement,
  748. pnIndex);
  749. pChannelIXMLElement->Release();
  750. }
  751. ASSERT((SUCCEEDED(hr) && *ppIXMLElement) || FAILED(hr));
  752. return hr;
  753. }
  754. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  755. //
  756. // *** XML_GetFirstDesktopComponentUsageElement ***
  757. //
  758. //
  759. // Description:
  760. // Returns the first USAGE VALUE="DesktopComponent" element of the first
  761. // desktop component.
  762. //
  763. // Parameters:
  764. // [In] pIXMLDocument - A pointer to the the document.
  765. // [Out] pIXMLElement - A pointer the receives the element.
  766. //
  767. // Return:
  768. // S_OK if the element was found.
  769. // E_FAIL if the element wasn't found.
  770. //
  771. // Comments:
  772. //
  773. //
  774. ////////////////////////////////////////////////////////////////////////////////
  775. HRESULT
  776. XML_GetFirstDesktopComponentUsageElement(
  777. IXMLDocument* pIXMLDocument,
  778. IXMLElement** ppIXMLElement
  779. )
  780. {
  781. ASSERT(pIXMLDocument);
  782. ASSERT(ppIXMLElement);
  783. HRESULT hr;
  784. IXMLElement* pParentIXMLElement;
  785. LONG nIndex;
  786. hr = XML_GetFirstDesktopComponentElement(pIXMLDocument, &pParentIXMLElement,
  787. &nIndex);
  788. if (SUCCEEDED(hr))
  789. {
  790. IXMLElementCollection* pIXMLElementCollection;
  791. hr = pParentIXMLElement->get_children(&pIXMLElementCollection);
  792. if (SUCCEEDED(hr) && pIXMLElementCollection)
  793. {
  794. ASSERT(pIXMLElementCollection);
  795. LONG nCount;
  796. hr = pIXMLElementCollection->get_length(&nCount);
  797. ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount));
  798. hr = E_FAIL;
  799. for (int i = 0, bUsage = FALSE; (i < nCount) && !bUsage; i++)
  800. {
  801. IXMLElement* pIXMLElement;
  802. HRESULT hr2 = XML_GetElementByIndex(pIXMLElementCollection, i,
  803. &pIXMLElement);
  804. if (SUCCEEDED(hr2))
  805. {
  806. ASSERT(pIXMLElement);
  807. if (bUsage = XML_IsDesktopComponentUsage(pIXMLElement))
  808. {
  809. pIXMLElement->AddRef();
  810. *ppIXMLElement = pIXMLElement;
  811. //*pnIndex = i;
  812. hr = S_OK;
  813. }
  814. pIXMLElement->Release();
  815. }
  816. hr = FAILED(hr2) ? hr2 : hr;
  817. }
  818. pIXMLElementCollection->Release();
  819. }
  820. else
  821. {
  822. hr = E_FAIL;
  823. }
  824. pParentIXMLElement->Release();
  825. }
  826. return hr;
  827. }
  828. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  829. //
  830. // *** XML_GetDesktopComponentInfo ***
  831. //
  832. //
  833. // Description:
  834. // Fills in the desktop component information structure.
  835. //
  836. // Parameters:
  837. // [In] pIXMLDocument - A ponter to the document.
  838. // [Out] pInfo - A desktop component information structure.
  839. //
  840. // Return:
  841. // S_OK if the given document is desktop component document.
  842. // E_FAIL otherwise.
  843. //
  844. // Comments:
  845. //
  846. //
  847. ////////////////////////////////////////////////////////////////////////////////
  848. HRESULT
  849. XML_GetDesktopComponentInfo(
  850. IXMLDocument* pIXMLDocument,
  851. COMPONENT* pInfo
  852. )
  853. {
  854. ASSERT(pIXMLDocument);
  855. ASSERT(pInfo);
  856. HRESULT hr;
  857. IXMLElement* pIXMLElement;
  858. hr = XML_GetFirstDesktopComponentUsageElement(pIXMLDocument, &pIXMLElement);
  859. if (SUCCEEDED(hr))
  860. {
  861. ASSERT(pIXMLElement);
  862. memset(pInfo, 0, sizeof(COMPONENT));
  863. pInfo->dwSize = sizeof(COMPONENT);
  864. pInfo->fChecked = TRUE;
  865. pInfo->fDirty = TRUE;
  866. pInfo->fNoScroll = FALSE;
  867. pInfo->cpPos.dwSize = sizeof(COMPPOS);
  868. pInfo->cpPos.izIndex = COMPONENT_TOP;
  869. pInfo->dwCurItemState = IS_NORMAL;
  870. BSTR bstrValue;
  871. if (bstrValue = XML_GetAttribute(pIXMLElement, XML_OPENAS))
  872. {
  873. if (!(0 == StrCmpIW(bstrValue, WSTR_IMAGE)))
  874. {
  875. pInfo->iComponentType = COMP_TYPE_WEBSITE;
  876. }
  877. else
  878. {
  879. pInfo->iComponentType = COMP_TYPE_PICTURE;
  880. }
  881. SysFreeString(bstrValue);
  882. }
  883. if (bstrValue = XML_GetAttribute(pIXMLElement, XML_WIDTH))
  884. {
  885. pInfo->cpPos.dwWidth = StrToIntW(bstrValue);
  886. SysFreeString(bstrValue);
  887. }
  888. if (bstrValue = XML_GetAttribute(pIXMLElement, XML_HEIGHT))
  889. {
  890. pInfo->cpPos.dwHeight = StrToIntW(bstrValue);
  891. SysFreeString(bstrValue);
  892. }
  893. if (bstrValue = XML_GetAttribute(pIXMLElement, XML_ITEMSTATE))
  894. {
  895. if(!StrCmpIW(bstrValue, WSTR_NORMAL))
  896. pInfo->dwCurItemState = IS_NORMAL;
  897. else
  898. {
  899. if(!StrCmpIW(bstrValue, WSTR_FULLSCREEN))
  900. pInfo->dwCurItemState = IS_FULLSCREEN;
  901. else
  902. pInfo->dwCurItemState = IS_SPLIT;
  903. }
  904. SysFreeString(bstrValue);
  905. }
  906. if (bstrValue = XML_GetAttribute(pIXMLElement, XML_CANRESIZE))
  907. {
  908. pInfo->cpPos.fCanResize = StrEqlW(bstrValue, WSTR_YES);
  909. SysFreeString(bstrValue);
  910. }
  911. else
  912. {
  913. if (bstrValue = XML_GetAttribute(pIXMLElement, XML_CANRESIZEX))
  914. {
  915. pInfo->cpPos.fCanResizeX = StrEqlW(bstrValue, WSTR_YES);
  916. SysFreeString(bstrValue);
  917. }
  918. if (bstrValue = XML_GetAttribute(pIXMLElement, XML_CANRESIZEY))
  919. {
  920. pInfo->cpPos.fCanResizeY = StrEqlW(bstrValue, WSTR_YES);
  921. SysFreeString(bstrValue);
  922. }
  923. }
  924. if (bstrValue = XML_GetAttribute(pIXMLElement, XML_PREFERREDLEFT))
  925. {
  926. if (StrChrW(bstrValue, L'%'))
  927. {
  928. pInfo->cpPos.iPreferredLeftPercent = StrToIntW(bstrValue);
  929. }
  930. else
  931. {
  932. pInfo->cpPos.iLeft = StrToIntW(bstrValue);
  933. }
  934. SysFreeString(bstrValue);
  935. }
  936. if (bstrValue = XML_GetAttribute(pIXMLElement, XML_PREFERREDTOP))
  937. {
  938. if (StrChrW(bstrValue, L'%'))
  939. {
  940. pInfo->cpPos.iPreferredTopPercent = StrToIntW(bstrValue);
  941. }
  942. else
  943. {
  944. pInfo->cpPos.iTop = StrToIntW(bstrValue);
  945. }
  946. SysFreeString(bstrValue);
  947. }
  948. IXMLElement *pIXMLElementParent;
  949. hr = pIXMLElement->get_parent(&pIXMLElementParent);
  950. if(!pIXMLElementParent)
  951. hr = E_FAIL;
  952. if (SUCCEEDED(hr))
  953. {
  954. ASSERT(pIXMLElementParent);
  955. if (bstrValue = XML_GetAttribute(pIXMLElementParent, XML_TITLE))
  956. {
  957. StrCpyNW(pInfo->wszFriendlyName, bstrValue,
  958. ARRAYSIZE(pInfo->wszFriendlyName));
  959. SysFreeString(bstrValue);
  960. }
  961. if (bstrValue = XML_GetAttribute(pIXMLElementParent, XML_HREF))
  962. {
  963. if (*bstrValue)
  964. {
  965. StrCpyNW(pInfo->wszSource, bstrValue,
  966. ARRAYSIZE(pInfo->wszSource));
  967. SysFreeString(bstrValue);
  968. }
  969. else
  970. {
  971. hr = E_FAIL;
  972. }
  973. }
  974. if (SUCCEEDED(hr))
  975. {
  976. IXMLElement *pIXMLChannel;
  977. LONG nIndex;
  978. hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLChannel,
  979. &nIndex);
  980. if (SUCCEEDED(hr))
  981. {
  982. ASSERT(pIXMLChannel);
  983. if (bstrValue = XML_GetAttribute(pIXMLChannel, XML_SELF))
  984. {
  985. StrCpyNW(pInfo->wszSubscribedURL, bstrValue,
  986. ARRAYSIZE(pInfo->wszSubscribedURL));
  987. SysFreeString(bstrValue);
  988. }
  989. pIXMLChannel->Release();
  990. }
  991. }
  992. pIXMLElementParent->Release();
  993. }
  994. pIXMLElement->Release();
  995. }
  996. return hr;
  997. }
  998. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  999. //
  1000. // *** XML_GetAttribute ***
  1001. //
  1002. //
  1003. // Description:
  1004. // Returns a bstr representing the requested attribute of the given element.
  1005. //
  1006. // Parameters:
  1007. // [In] pIXMLElement - A pointer to the XML element.
  1008. // [In] attribute - The requested attribute.
  1009. //
  1010. // Return:
  1011. // A bstr with the attribute value.
  1012. // NULL if there wasn't enough memory to allocated the bstr.
  1013. //
  1014. // Comments:
  1015. // This function keeps a table of attributes and their properties. It bases
  1016. // attribute look up on this table.
  1017. //
  1018. ////////////////////////////////////////////////////////////////////////////////
  1019. BSTR
  1020. XML_GetAttribute(
  1021. IXMLElement* pIXMLElement,
  1022. XML_ATTRIBUTE attrIndex
  1023. )
  1024. {
  1025. //
  1026. // A table is used to read values associated with a given xml element. The
  1027. // xml element can have attributes (values inside the elements tag) or child
  1028. // elements (elements between tags).
  1029. //
  1030. // Rules:
  1031. // 1) If child is NULL. Read the Attribute from the current item.
  1032. // 2) If child is not NULL, read the Attribute from the child
  1033. // item.
  1034. // 3) If AttributeType is NULL, use the Attribute value to read the
  1035. // attribute.
  1036. // 4) If AttributeType is not NULL, verify that the item contains
  1037. // the AttributeType attribute before using Attribute to read
  1038. // the value.
  1039. // 5) If the value is not found use Default as the return value.
  1040. //
  1041. static const struct _tagXML_ATTRIBUTE_ARRAY
  1042. {
  1043. LPWSTR szChildW;
  1044. LPWSTR szAttributeW;
  1045. LPWSTR szQualifierW;
  1046. LPWSTR szQualifierValueW;
  1047. XML_ATTRIBUTE attrSecondary;
  1048. LPWSTR szDefaultW;
  1049. BOOL fUseBaseURL;
  1050. XML_ATTRIBUTE attribute; // Only used in ASSERT.
  1051. }
  1052. aAttribTable[] =
  1053. {
  1054. /*
  1055. Child Attribute Qualifier Qual. Value Secondary Lookup Default Base URL Enum Check
  1056. -------------- -------------- ----------- ------------ ----------------- ---------- -------- -----------------*/
  1057. {WSTR_TITLE, NULL, NULL, NULL, XML_TITLE_ATTR, WSTR_EMPTY, FALSE, XML_TITLE },
  1058. {NULL, WSTR_TITLE, NULL, NULL, XML_HREF, WSTR_EMPTY, FALSE, XML_TITLE_ATTR },
  1059. {NULL, WSTR_HREF, NULL, NULL, XML_A_HREF, WSTR_EMPTY, TRUE, XML_HREF },
  1060. {WSTR_ABSTRACT, NULL, NULL, NULL, XML_ABSTRACT_ATTR, WSTR_EMPTY, FALSE, XML_ABSTRACT },
  1061. {NULL, WSTR_ABSTRACT, NULL, NULL, XML_HREF, WSTR_EMPTY, FALSE, XML_ABSTRACT_ATTR},
  1062. {WSTR_LOGO, WSTR_HREF, WSTR_STYLE, WSTR_ICON, XML_NULL, NULL, TRUE, XML_ICON },
  1063. {WSTR_LOGO, WSTR_HREF, WSTR_STYLE, WSTR_IMAGE, XML_LOGO_DEFAULT, NULL, TRUE, XML_LOGO },
  1064. {WSTR_LOGO, WSTR_HREF, NULL, NULL, XML_NULL, NULL, TRUE, XML_LOGO_DEFAULT },
  1065. {NULL, WSTR_SELF, NULL, NULL, XML_SELF_OLD, NULL, TRUE, XML_SELF },
  1066. {WSTR_SELF, WSTR_HREF, NULL, NULL, XML_NULL, NULL, TRUE, XML_SELF_OLD },
  1067. {NULL, WSTR_BASE, NULL, NULL, XML_NULL, NULL, FALSE, XML_BASE },
  1068. {WSTR_USAGE, WSTR_VALUE, NULL, NULL, XML_SHOW, NULL, FALSE, XML_USAGE },
  1069. {WSTR_USAGE, WSTR_VALUE, WSTR_VALUE, WSTR_CHANNEL, XML_SHOW_CHANNEL, NULL, FALSE, XML_USAGE_CHANNEL},
  1070. {WSTR_USAGE, WSTR_VALUE, WSTR_VALUE, WSTR_DSKCMP, XML_SHOW_DSKCMP, NULL, FALSE, XML_USAGE_DSKCMP },
  1071. {WSTR_WIDTH, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_ZERO, FALSE, XML_WIDTH },
  1072. {WSTR_HEIGHT, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_ZERO, FALSE, XML_HEIGHT },
  1073. {WSTR_RESIZE, WSTR_VALUE, NULL, NULL, XML_NULL, NULL, FALSE, XML_CANRESIZE },
  1074. {WSTR_RESIZEX, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_YES, FALSE, XML_CANRESIZEX },
  1075. {WSTR_RESIZEY, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_YES, FALSE, XML_CANRESIZEY },
  1076. {WSTR_PREFLEFT, WSTR_VALUE, NULL, NULL, XML_NULL, NULL, FALSE, XML_PREFERREDLEFT},
  1077. {WSTR_PREFTOP, WSTR_VALUE, NULL, NULL, XML_NULL, NULL, FALSE, XML_PREFERREDTOP },
  1078. {WSTR_OPENAS, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_HTML, FALSE, XML_OPENAS },
  1079. {NULL, WSTR_SHOW, NULL, NULL, XML_NULL, NULL, FALSE, XML_SHOW },
  1080. {NULL, WSTR_SHOW, WSTR_SHOW, WSTR_CHANNEL, XML_NULL, NULL, FALSE, XML_SHOW_CHANNEL },
  1081. {NULL, WSTR_SHOW, WSTR_SHOW, WSTR_DSKCMP, XML_NULL, NULL, FALSE, XML_SHOW_DSKCMP },
  1082. {WSTR_A, WSTR_HREF, NULL, NULL, XML_INFOURI, WSTR_EMPTY, TRUE, XML_A_HREF },
  1083. {NULL, WSTR_INFOURI, NULL, NULL, XML_NULL, WSTR_EMPTY, TRUE, XML_INFOURI },
  1084. {WSTR_LOGO, WSTR_HREF, WSTR_STYLE, WSTR_IMAGEW, XML_NULL, NULL, TRUE, XML_LOGO_WIDE },
  1085. {WSTR_LOGIN, NULL, NULL, NULL, XML_NULL, NULL, FALSE, XML_LOGIN },
  1086. {WSTR_USAGE, WSTR_VALUE, WSTR_VALUE, WSTR_SOFTWAREUPDATE, XML_SHOW_SOFTWAREUPDATE, NULL, FALSE, XML_USAGE_SOFTWAREUPDATE},
  1087. {NULL, WSTR_SHOW, WSTR_SHOW, WSTR_SOFTWAREUPDATE, XML_NULL, NULL, FALSE, XML_SHOW_SOFTWAREUPDATE },
  1088. {WSTR_ITEMSTATE,WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_NORMAL,FALSE, XML_ITEMSTATE },
  1089. };
  1090. ASSERT(pIXMLElement);
  1091. //
  1092. // REVIEW: aAttribTable attribute field only used in debug builds.
  1093. //
  1094. ASSERT(attrIndex == aAttribTable[attrIndex].attribute);
  1095. BSTR bstrRet = NULL;
  1096. if (NULL == aAttribTable[attrIndex].szAttributeW)
  1097. {
  1098. bstrRet = XML_GetGrandChildContent(pIXMLElement,
  1099. aAttribTable[attrIndex].szChildW);
  1100. }
  1101. else if (NULL != aAttribTable[attrIndex].szChildW)
  1102. {
  1103. bstrRet = XML_GetChildAttribute(pIXMLElement,
  1104. aAttribTable[attrIndex].szChildW,
  1105. aAttribTable[attrIndex].szAttributeW,
  1106. aAttribTable[attrIndex].szQualifierW,
  1107. aAttribTable[attrIndex].szQualifierValueW);
  1108. }
  1109. else
  1110. {
  1111. bstrRet = XML_GetElementAttribute(pIXMLElement,
  1112. aAttribTable[attrIndex].szAttributeW,
  1113. aAttribTable[attrIndex].szQualifierW,
  1114. aAttribTable[attrIndex].szQualifierValueW);
  1115. }
  1116. //
  1117. // If the title or tooltip aren't displayable on the local system use the
  1118. // URL in their place.
  1119. //
  1120. if (bstrRet && (XML_TITLE == attrIndex || XML_TITLE_ATTR == attrIndex ||
  1121. XML_ABSTRACT == attrIndex))
  1122. {
  1123. if (!StrLocallyDisplayable(bstrRet))
  1124. {
  1125. SysFreeString(bstrRet);
  1126. bstrRet = NULL;
  1127. }
  1128. }
  1129. //
  1130. // Special cases:
  1131. // TITLE can also be an attribute.
  1132. // ABSTRACT can also be an attribute.
  1133. // LOGO elements don't have to have the TYPE="IMAGE"
  1134. // SELF is now an attribute SELF_OLD can be removed in the future.
  1135. // USAGE can also be specified via the SHOW attribute.
  1136. // USAGE_CHANNEL should also check for SHOW="Channel".
  1137. // USAGE_DSKCMP should also check for SHOW="DesktopComponent"
  1138. //
  1139. if (NULL == bstrRet && XML_NULL != aAttribTable[attrIndex].attrSecondary)
  1140. {
  1141. bstrRet = XML_GetAttribute(pIXMLElement,
  1142. aAttribTable[attrIndex].attrSecondary);
  1143. }
  1144. //
  1145. // Combine URL if required.
  1146. //
  1147. if (bstrRet && aAttribTable[attrIndex].fUseBaseURL)
  1148. {
  1149. BSTR bstrBaseURL = XML_GetBaseURL(pIXMLElement);
  1150. if (bstrBaseURL)
  1151. {
  1152. BSTR bstrCombinedURL = XML_CombineURL(bstrBaseURL, bstrRet);
  1153. if (bstrCombinedURL)
  1154. {
  1155. SysFreeString(bstrRet);
  1156. bstrRet = bstrCombinedURL;
  1157. }
  1158. SysFreeString(bstrBaseURL);
  1159. }
  1160. }
  1161. /* The following prevent long urls from over-running the pidl buffer */
  1162. if (bstrRet &&
  1163. (attrIndex == XML_HREF) &&
  1164. (SysStringLen(bstrRet) > INTERNET_MAX_URL_LENGTH))
  1165. {
  1166. SysReAllocStringLen(&bstrRet, bstrRet, INTERNET_MAX_URL_LENGTH-1);
  1167. }
  1168. //
  1169. // Set default return value.
  1170. //
  1171. if (NULL == bstrRet && aAttribTable[attrIndex].szDefaultW)
  1172. bstrRet = SysAllocString(aAttribTable[attrIndex].szDefaultW);
  1173. return bstrRet;
  1174. }
  1175. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1176. //
  1177. // *** XML_GetFirstChildContent ***
  1178. //
  1179. // Description:
  1180. // Returns a bstr value from first child of the given element.
  1181. //
  1182. // Parameters:
  1183. // [In] pIXMLElement - A pointer to the element.
  1184. // The caller is responsible for freeing the returned bstr.
  1185. //
  1186. // Comments:
  1187. // If pIElement represents
  1188. //
  1189. // <Title>Harvey is a Cool Cat<B>this will be ignored</B></Title>
  1190. //
  1191. // Then this function will return
  1192. //
  1193. // "Harvey is a Cool Cat"
  1194. //
  1195. // REVIEW THIS IS A TEMPORARY ROUTINE UNTIL THE XML PARSER SUPPORTS THIS DIRECTLY
  1196. //
  1197. ////////////////////////////////////////////////////////////////////////////////
  1198. BSTR
  1199. XML_GetFirstChildContent(
  1200. IXMLElement* pIXMLElement
  1201. )
  1202. {
  1203. ASSERT(pIXMLElement);
  1204. BSTR bstrRet = NULL;
  1205. IXMLElementCollection* pIXMLElementCollection;
  1206. if ((SUCCEEDED(pIXMLElement->get_children(&pIXMLElementCollection)))
  1207. && pIXMLElementCollection)
  1208. {
  1209. ASSERT(pIXMLElementCollection);
  1210. LONG nCount;
  1211. HRESULT hr = pIXMLElementCollection->get_length(&nCount);
  1212. ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount));
  1213. if (nCount >= 1)
  1214. {
  1215. IXMLElement* pChildIXMLElement;
  1216. if (SUCCEEDED(XML_GetElementByIndex(pIXMLElementCollection, 0,
  1217. &pChildIXMLElement)))
  1218. {
  1219. ASSERT(pChildIXMLElement);
  1220. if (FAILED(pChildIXMLElement->get_text(&bstrRet)))
  1221. {
  1222. bstrRet = NULL;
  1223. }
  1224. pChildIXMLElement->Release();
  1225. }
  1226. }
  1227. pIXMLElementCollection->Release();
  1228. }
  1229. return bstrRet;
  1230. }
  1231. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1232. //
  1233. // *** XML_GetGrandChildContent ***
  1234. //
  1235. // Description:
  1236. // Returns a bstr value from the requested child of the given element.
  1237. //
  1238. // Parameters:
  1239. // [In] pIXMLElement - A pointer to the element.
  1240. // [In] szChildW - The name of the child element.
  1241. // The caller is responsible for freeing the returned bstr.
  1242. //
  1243. // Comments:
  1244. // If pIElement represents
  1245. //
  1246. // <Channel>
  1247. // <Title>Harvey is a Cool Cat</Title>
  1248. // </Channel>
  1249. //
  1250. // Then this function will return
  1251. //
  1252. // "Harvey is a Cool Cat" for "TITLE",
  1253. //
  1254. ////////////////////////////////////////////////////////////////////////////////
  1255. BSTR
  1256. XML_GetGrandChildContent(
  1257. IXMLElement* pIXMLElement,
  1258. LPWSTR szChildW
  1259. )
  1260. {
  1261. ASSERT(pIXMLElement);
  1262. ASSERT(szChildW);
  1263. BSTR bstrRet = NULL;
  1264. IXMLElementCollection* pIXMLElementCollection;
  1265. if ((SUCCEEDED(pIXMLElement->get_children(&pIXMLElementCollection)))
  1266. && pIXMLElementCollection)
  1267. {
  1268. ASSERT(pIXMLElementCollection);
  1269. LONG nCount;
  1270. HRESULT hr = pIXMLElementCollection->get_length(&nCount);
  1271. ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount));
  1272. for (int i = 0; (i < nCount) && !bstrRet; i++)
  1273. {
  1274. IXMLElement* pChildIXMLElement;
  1275. if (SUCCEEDED(XML_GetElementByIndex(pIXMLElementCollection, i,
  1276. &pChildIXMLElement)))
  1277. {
  1278. ASSERT(pChildIXMLElement);
  1279. BSTR bstrTagName;
  1280. if (SUCCEEDED(pChildIXMLElement->get_tagName(&bstrTagName)) && bstrTagName)
  1281. {
  1282. ASSERT(bstrTagName);
  1283. if (StrEqlW(bstrTagName, szChildW))
  1284. {
  1285. bstrRet = XML_GetFirstChildContent(pChildIXMLElement);
  1286. //
  1287. // If the tag exists, but it is empty, return the empty
  1288. // string.
  1289. //
  1290. if (NULL == bstrRet)
  1291. bstrRet = SysAllocString(L"");
  1292. }
  1293. SysFreeString(bstrTagName);
  1294. }
  1295. pChildIXMLElement->Release();
  1296. }
  1297. }
  1298. pIXMLElementCollection->Release();
  1299. }
  1300. return bstrRet;
  1301. }
  1302. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1303. //
  1304. // *** XML_GetChildAttribute ***
  1305. //
  1306. //
  1307. // Description:
  1308. // Returns a bstr value from the requested child of the given element.
  1309. //
  1310. // Parameters:
  1311. // [In] pIXMLElement - A pointer to the element.
  1312. // [In] szChildW - The name of the child element.
  1313. // [In] szAttributeW - The name of the attribute.
  1314. // [In] szQualifierW - The name of the attribute qualifier.
  1315. // [In] szQualifierValueW - The required value of the qaulifier.
  1316. //
  1317. // Return:
  1318. // A bstr of the value contained in the child element if it is found.
  1319. // NULL if the child element or its value isn't found.
  1320. //
  1321. // Comments:
  1322. // This function will return atributes found in the child elements of the
  1323. // given element. For example:
  1324. //
  1325. // If pIElement represents
  1326. //
  1327. // <Channel>
  1328. // <Title VALUE="foo">
  1329. // <Author VALUE="bar">
  1330. // <Logo HRREF="url" TYPE="ICON">
  1331. // </Channel>
  1332. //
  1333. // Then this function will return
  1334. //
  1335. // "foo" for "TITLE", "VALUE", "", ""
  1336. // "bar" for "AUTHOR", "VALUE", "", ""
  1337. // "url" for "LOGO", "HREF", "TYPE", "ICON"
  1338. //
  1339. // NULL when the names have any other values.
  1340. //
  1341. // The caller is responsible for freeing the returned bstr.
  1342. //
  1343. ////////////////////////////////////////////////////////////////////////////////
  1344. BSTR
  1345. XML_GetChildAttribute(
  1346. IXMLElement* pIXMLElement,
  1347. LPWSTR szChildW,
  1348. LPWSTR szAttributeW,
  1349. LPWSTR szQualifierW,
  1350. LPWSTR szQualifierValueW
  1351. )
  1352. {
  1353. ASSERT(pIXMLElement);
  1354. ASSERT(szChildW);
  1355. ASSERT(szAttributeW);
  1356. BSTR bstrRet = NULL;
  1357. IXMLElementCollection* pIXMLElementCollection;
  1358. if ((SUCCEEDED(pIXMLElement->get_children(&pIXMLElementCollection)))
  1359. && pIXMLElementCollection)
  1360. {
  1361. ASSERT(pIXMLElementCollection);
  1362. LONG nCount;
  1363. //
  1364. // REVIEW: hr only used in debug builds.
  1365. //
  1366. HRESULT hr = pIXMLElementCollection->get_length(&nCount);
  1367. ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount));
  1368. for (int i = 0; (i < nCount) && !bstrRet; i++)
  1369. {
  1370. IXMLElement* pChildIXMLElement;
  1371. if (SUCCEEDED(XML_GetElementByIndex(pIXMLElementCollection, i,
  1372. &pChildIXMLElement)))
  1373. {
  1374. ASSERT(pChildIXMLElement);
  1375. BSTR bstrTagName;
  1376. if (SUCCEEDED(pChildIXMLElement->get_tagName(&bstrTagName)) && bstrTagName)
  1377. {
  1378. ASSERT(bstrTagName);
  1379. if (StrEqlW(bstrTagName, szChildW))
  1380. {
  1381. bstrRet = XML_GetElementAttribute(pChildIXMLElement,
  1382. szAttributeW,
  1383. szQualifierW,
  1384. szQualifierValueW);
  1385. }
  1386. SysFreeString(bstrTagName);
  1387. }
  1388. pChildIXMLElement->Release();
  1389. }
  1390. }
  1391. pIXMLElementCollection->Release();
  1392. }
  1393. return bstrRet;
  1394. }
  1395. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1396. //
  1397. // *** XML_GetElementAttribute ***
  1398. //
  1399. //
  1400. // Description:
  1401. // Returns the bstr value of of the requested attribute if it is found.
  1402. //
  1403. // Parameters:
  1404. // [In] pIXMLElement - The element that contains the attribute.
  1405. // [In] szAttributeW - The name of the attribute.
  1406. // [In] szQualifierW - The type qualifier for the atribute.
  1407. // [In] szQualifierValueW - The required value of the qaulifier.
  1408. //
  1409. // Return:
  1410. // A bstr containig the attributes value if it was found.
  1411. // NULL if the attribute wasn't found.
  1412. //
  1413. // Comments:
  1414. // The function will return attributes found inside of tags. For
  1415. // example:
  1416. //
  1417. // If pIXMLElement represents
  1418. //
  1419. // <Channel HREF="foo" Cloneable="NO">
  1420. // <USAGE VALUE="Channel">
  1421. // <USAGE VALUE="Screen Saver">
  1422. //
  1423. // Then this function will return
  1424. //
  1425. // "foo" for "HREF", "", ""
  1426. // "NO" for "Cloneable", "", ""
  1427. // "CHANNEL" for "VALUE", "VALUE", "CHANNEL"
  1428. // NULL for "VALUE", "VALUE", "NONE"
  1429. // "foo" for "HREF", "CLONEABLE", "NO"
  1430. //
  1431. // The caller is responsible for freeing the returned bstr.
  1432. //
  1433. ////////////////////////////////////////////////////////////////////////////////
  1434. BSTR
  1435. XML_GetElementAttribute(
  1436. IXMLElement* pIXMLElement,
  1437. LPWSTR szAttributeW,
  1438. LPWSTR szQualifierW,
  1439. LPWSTR szQualifierValueW
  1440. )
  1441. {
  1442. ASSERT(pIXMLElement);
  1443. ASSERT(szAttributeW);
  1444. ASSERT((NULL == szQualifierW && NULL == szQualifierValueW) ||
  1445. (szQualifierW && szQualifierValueW));
  1446. BSTR bstrRet = NULL;
  1447. VARIANT var;
  1448. VariantInit(&var);
  1449. if (NULL == szQualifierW)
  1450. {
  1451. if (SUCCEEDED(pIXMLElement->getAttribute(szAttributeW, &var)))
  1452. {
  1453. ASSERT(var.vt == VT_BSTR || NULL == var.bstrVal);
  1454. bstrRet = var.bstrVal;
  1455. }
  1456. }
  1457. else
  1458. {
  1459. if (SUCCEEDED(pIXMLElement->getAttribute(szQualifierW, &var)))
  1460. {
  1461. ASSERT(var.vt == VT_BSTR || NULL == var.bstrVal);
  1462. if(var.bstrVal)
  1463. {
  1464. if (0 == StrCmpIW(var.bstrVal, szQualifierValueW))
  1465. {
  1466. bstrRet = XML_GetElementAttribute(pIXMLElement, szAttributeW,
  1467. NULL, NULL);
  1468. }
  1469. }
  1470. VariantClear(&var);
  1471. }
  1472. }
  1473. return bstrRet;
  1474. }
  1475. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1476. //
  1477. // *** XML_GetScreenSaverURL ***
  1478. //
  1479. //
  1480. // Description:
  1481. // Returns the screen saver URL of the first screen saver component in the channel.
  1482. //
  1483. // Parameters:
  1484. // [In] pXMLDocument - An XML document
  1485. // [Out] pbstrSSURL - The pointer that receives the screen saver URL.
  1486. //
  1487. // Return:
  1488. // S_OK if the screen saver URL was returned.
  1489. // E_FAIL if the screen saver URL couldn't be returned.
  1490. //
  1491. // Comments:
  1492. // This function gets the first screen saver element and then looks
  1493. // for the first top-level ITEM with a usage of ScreenSaver.
  1494. //
  1495. ////////////////////////////////////////////////////////////////////////////////
  1496. HRESULT
  1497. XML_GetScreenSaverURL(
  1498. IXMLDocument * pXMLDocument,
  1499. BSTR * pbstrSSURL)
  1500. {
  1501. HRESULT hr;
  1502. ASSERT(pXMLDocument);
  1503. ASSERT(pbstrSSURL);
  1504. IXMLElement* pIXMLElement;
  1505. LONG lDontCare;
  1506. hr = XML_GetFirstChannelElement(pXMLDocument, &pIXMLElement, &lDontCare);
  1507. if (SUCCEEDED(hr))
  1508. {
  1509. IXMLElement* pSSElement;
  1510. ASSERT(pIXMLElement);
  1511. hr = XML_GetScreenSaverElement(pIXMLElement, &pSSElement);
  1512. if (SUCCEEDED(hr))
  1513. {
  1514. ASSERT(pSSElement);
  1515. *pbstrSSURL = XML_GetAttribute(pSSElement, XML_HREF);
  1516. hr = *pbstrSSURL ? S_OK : E_FAIL;
  1517. pSSElement->Release();
  1518. }
  1519. pIXMLElement->Release();
  1520. }
  1521. return hr;
  1522. }
  1523. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1524. //
  1525. // *** XML_GetScreenSaverElement ***
  1526. //
  1527. //
  1528. // Description:
  1529. // Returns the IXMLElement of the first screen saver component in the channel.
  1530. //
  1531. // Parameters:
  1532. // [In] pXMLElemet - An XML element
  1533. // [Out] ppIXMLElement - The pointer that receives the screen saver element.
  1534. //
  1535. // Return:
  1536. // S_OK if the first screen saver element was returned.
  1537. // E_FAIL if the element couldn't be returned.
  1538. //
  1539. // Comments:
  1540. // This function gets the first screen saver element and then looks
  1541. // for the first top-level ITEM with a usage of ScreenSaver.
  1542. //
  1543. ////////////////////////////////////////////////////////////////////////////////
  1544. HRESULT
  1545. XML_GetScreenSaverElement(
  1546. IXMLElement * pXMLElement,
  1547. IXMLElement ** ppScreenSaverElement)
  1548. {
  1549. ASSERT(pXMLElement);
  1550. ASSERT(ppScreenSaverElement);
  1551. IXMLElementCollection * pIXMLElementCollection;
  1552. HRESULT hr;
  1553. hr = pXMLElement->get_children(&pIXMLElementCollection);
  1554. if (SUCCEEDED(hr) && pIXMLElementCollection)
  1555. {
  1556. LONG nCount;
  1557. hr = pIXMLElementCollection->get_length(&nCount);
  1558. ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount));
  1559. hr = E_FAIL;
  1560. BOOL bScreenSaver = FALSE;
  1561. for (int i = 0; (i < nCount) && !bScreenSaver; i++)
  1562. {
  1563. IXMLElement * pIXMLElement;
  1564. HRESULT hr2 = XML_GetElementByIndex(pIXMLElementCollection,
  1565. i,
  1566. &pIXMLElement);
  1567. if (SUCCEEDED(hr2))
  1568. {
  1569. ASSERT(pIXMLElement != NULL);
  1570. if (bScreenSaver = XML_IsScreenSaver(pIXMLElement))
  1571. {
  1572. pIXMLElement->AddRef();
  1573. *ppScreenSaverElement = pIXMLElement;
  1574. hr = S_OK;
  1575. }
  1576. pIXMLElement->Release();
  1577. }
  1578. hr = FAILED(hr2) ? hr2 : hr;
  1579. }
  1580. pIXMLElementCollection->Release();
  1581. }
  1582. else
  1583. hr = E_FAIL;
  1584. ASSERT((SUCCEEDED(hr) && *ppScreenSaverElement) || FAILED(hr));
  1585. return hr;
  1586. }
  1587. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1588. //
  1589. // *** XML_GetSubscriptionInfo ***
  1590. //
  1591. //
  1592. // Description:
  1593. // Fills a structure with the subscription info for the given element.
  1594. //
  1595. // Parameters:
  1596. // [In] pIXMLElement - An xml element. The element doesn't have to be a
  1597. // subscription element.
  1598. // [Out] psi - The subscription info structure used by the
  1599. // subscription manager.
  1600. //
  1601. // Return:
  1602. // S_OK if any information was obtained.
  1603. //
  1604. // Comments:
  1605. // This function uses a webcheck API that fills a task trigger with
  1606. // subscription information.
  1607. //
  1608. // This function assumes that the psi->pTrigger points to a TASK_TRIGGER.
  1609. //
  1610. ////////////////////////////////////////////////////////////////////////////////
  1611. HRESULT
  1612. XML_GetSubscriptionInfo(
  1613. IXMLElement* pIXMLElement,
  1614. SUBSCRIPTIONINFO* psi
  1615. )
  1616. {
  1617. ASSERT(pIXMLElement);
  1618. ASSERT(psi);
  1619. ASSERT(psi->pTrigger);
  1620. HRESULT hr = E_FAIL;
  1621. #ifndef UNIX
  1622. HINSTANCE hinst = LoadLibrary(TEXT("webcheck.dll"));
  1623. if (hinst)
  1624. {
  1625. typedef (*PFTRIGGERFUNCTION)(IXMLElement* pIXMLElement,
  1626. TASK_TRIGGER* ptt);
  1627. PFTRIGGERFUNCTION XMLSheduleElementToTaskTrigger;
  1628. XMLSheduleElementToTaskTrigger = (PFTRIGGERFUNCTION)
  1629. GetProcAddress(hinst,
  1630. "XMLScheduleElementToTaskTrigger");
  1631. if (XMLSheduleElementToTaskTrigger)
  1632. {
  1633. ((TASK_TRIGGER*)(psi->pTrigger))->cbTriggerSize =
  1634. sizeof(TASK_TRIGGER);
  1635. hr = XMLSheduleElementToTaskTrigger(pIXMLElement,
  1636. (TASK_TRIGGER*)psi->pTrigger);
  1637. if (FAILED(hr))
  1638. psi->pTrigger = NULL;
  1639. }
  1640. FreeLibrary(hinst);
  1641. }
  1642. // See if there is a screen saver available.
  1643. IXMLElement * pScreenSaverElement;
  1644. if (SUCCEEDED(XML_GetScreenSaverElement( pIXMLElement,
  1645. &pScreenSaverElement)))
  1646. {
  1647. psi->fUpdateFlags |= SUBSINFO_CHANNELFLAGS;
  1648. psi->fChannelFlags |= CHANNEL_AGENT_PRECACHE_SCRNSAVER;
  1649. pScreenSaverElement->Release();
  1650. }
  1651. BSTR bstrLogin = XML_GetAttribute(pIXMLElement, XML_LOGIN);
  1652. if (bstrLogin)
  1653. {
  1654. psi->bNeedPassword = TRUE;
  1655. psi->fUpdateFlags |= SUBSINFO_NEEDPASSWORD; //this member is now valid
  1656. SysFreeString(bstrLogin);
  1657. }
  1658. #endif /* !UNIX */
  1659. return hr;
  1660. }
  1661. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1662. //
  1663. // *** XML_GetBaseURL ***
  1664. //
  1665. //
  1666. // Description:
  1667. // Returns the base url for the given collection.
  1668. //
  1669. // Parameters:
  1670. // [In] pIXMLElement - A pointer to an XML element.
  1671. //
  1672. // Return:
  1673. // A bstr containing the base URL if there is one.
  1674. // NULL if ther isn't a base URL.
  1675. //
  1676. // Comments:
  1677. // If the current element has a BASE attribute return this attributes value.
  1678. // Else return the BASE attribute of its parent.
  1679. //
  1680. ////////////////////////////////////////////////////////////////////////////////
  1681. BSTR
  1682. XML_GetBaseURL(
  1683. IXMLElement* pIXMLElement
  1684. )
  1685. {
  1686. ASSERT(pIXMLElement);
  1687. BSTR bstrRet = XML_GetAttribute(pIXMLElement, XML_BASE);
  1688. if (NULL == bstrRet)
  1689. {
  1690. IXMLElement* pParentIXMLElement;
  1691. if (SUCCEEDED(pIXMLElement->get_parent(&pParentIXMLElement)) && pParentIXMLElement)
  1692. {
  1693. ASSERT(pParentIXMLElement);
  1694. bstrRet = XML_GetBaseURL(pParentIXMLElement);
  1695. pParentIXMLElement->Release();
  1696. }
  1697. }
  1698. return bstrRet;
  1699. }
  1700. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1701. //
  1702. // *** XML_CombineURL ***
  1703. //
  1704. //
  1705. // Description:
  1706. // Combine the given URL with the base URL.
  1707. //
  1708. // Parameters:
  1709. // [In] bstrBaseURL - The base URL.
  1710. // [In] bstrRelURL - The relative URL.
  1711. //
  1712. // Return:
  1713. // A combination of the base and relative URL.
  1714. //
  1715. // Comments:
  1716. //
  1717. //
  1718. ////////////////////////////////////////////////////////////////////////////////
  1719. BSTR
  1720. XML_CombineURL(
  1721. BSTR bstrBaseURL,
  1722. BSTR bstrRelURL
  1723. )
  1724. {
  1725. ASSERT(bstrBaseURL);
  1726. ASSERT(bstrRelURL);
  1727. BSTR bstrRet = NULL;
  1728. WCHAR wszCombinedURL[INTERNET_MAX_URL_LENGTH];
  1729. DWORD cch = ARRAYSIZE(wszCombinedURL);
  1730. if (InternetCombineUrlW(bstrBaseURL, bstrRelURL, wszCombinedURL, &cch, 0))
  1731. bstrRet = SysAllocString(wszCombinedURL);
  1732. return bstrRet;
  1733. }
  1734. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1735. //
  1736. // *** XML_IsCdfDisplayable ***
  1737. //
  1738. //
  1739. // Description:
  1740. // Determines if the given item should be displayed in the cdf view.
  1741. //
  1742. // Parameters:
  1743. // [In] pIXMLElement - A pointer to the IXMLElement interface of an object.
  1744. //
  1745. // Return:
  1746. // TRUE if the object should be displayed.
  1747. // FALSE otherwise.
  1748. //
  1749. // Comments:
  1750. // aCDFTypes contains the tag names of XML items that the cdf shell
  1751. // shell extension displays.
  1752. //
  1753. ////////////////////////////////////////////////////////////////////////////////
  1754. BOOL
  1755. XML_IsCdfDisplayable(
  1756. IXMLElement* pIXMLElement
  1757. )
  1758. {
  1759. #define KEYWORDS (sizeof(aCDFTypes) / sizeof(aCDFTypes[0]))
  1760. static const LPWSTR aCDFTypes[] = {
  1761. WSTR_ITEM,
  1762. WSTR_CHANNEL,
  1763. WSTR_SOFTDIST
  1764. };
  1765. ASSERT(pIXMLElement);
  1766. BOOL bRet = FALSE;
  1767. BSTR pStr;
  1768. HRESULT hr = pIXMLElement->get_tagName(&pStr);
  1769. if (SUCCEEDED(hr) && pStr)
  1770. {
  1771. ASSERT(pStr);
  1772. for(int i = 0; (i < KEYWORDS) && !bRet; i++)
  1773. bRet = StrEqlW(pStr, aCDFTypes[i]);
  1774. if (bRet)
  1775. bRet = XML_IsUsageChannel(pIXMLElement);
  1776. //
  1777. // Special processing.
  1778. //
  1779. if (bRet && StrEqlW(pStr, WSTR_SOFTDIST))
  1780. bRet = XML_IsSoftDistDisplayable(pIXMLElement);
  1781. SysFreeString(pStr);
  1782. }
  1783. return bRet;
  1784. }
  1785. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1786. //
  1787. // *** XML_IsSoftDistDisplayable ***
  1788. //
  1789. //
  1790. // Description:
  1791. // Determins if the given software distribution element should be displayed.
  1792. //
  1793. // Parameters:
  1794. // [In] pIXMLElement - Pointer to the software distribution xml element.
  1795. //
  1796. // Return:
  1797. // TRUE if the element should be displayed.
  1798. // FALSE if the element shouldn't be displayed.
  1799. //
  1800. // Comments:
  1801. // This function asks the software disribution COM object if this software
  1802. // distribution tag should be displayed on this users machine.
  1803. //
  1804. ////////////////////////////////////////////////////////////////////////////////
  1805. BOOL
  1806. XML_IsSoftDistDisplayable(
  1807. IXMLElement* pIXMLElement
  1808. )
  1809. {
  1810. ASSERT(pIXMLElement);
  1811. ISoftDistExt* pISoftDistExt;
  1812. HRESULT hr = CoCreateInstance(CLSID_SoftDistExt, NULL, CLSCTX_INPROC_SERVER,
  1813. IID_ISoftDistExt, (void**)&pISoftDistExt);
  1814. if (SUCCEEDED(hr))
  1815. {
  1816. ASSERT(pISoftDistExt);
  1817. hr = pISoftDistExt->ProcessSoftDist(NULL, pIXMLElement, 0);
  1818. pISoftDistExt->Release();
  1819. }
  1820. return SUCCEEDED(hr) ? TRUE : FALSE;
  1821. }
  1822. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1823. //
  1824. // *** XML_IsUsageChannel ***
  1825. //
  1826. //
  1827. // Description:
  1828. // Determines if this item should be displayed in channel view based on its
  1829. // usage tag.
  1830. //
  1831. // Parameters:
  1832. // [In] pIXMLelement - A pointer to the element.
  1833. //
  1834. // Return:
  1835. // TRUE if the item should be displayed in the channel view.
  1836. // FALSE otherwise.
  1837. //
  1838. // Comments:
  1839. // If an element doesn't have a USAGE tag then it gets displayed. If an
  1840. // element has any numberf of usage tags one of them must have a value of
  1841. // CHANNEL or will not get displayed.
  1842. //
  1843. ////////////////////////////////////////////////////////////////////////////////
  1844. BOOL
  1845. XML_IsUsageChannel(
  1846. IXMLElement* pIXMLElement
  1847. )
  1848. {
  1849. ASSERT(pIXMLElement);
  1850. BOOL bRet;
  1851. //
  1852. // First check if there are any USAGE elements.
  1853. //
  1854. BSTR bstrUsage = XML_GetAttribute(pIXMLElement, XML_USAGE);
  1855. if (bstrUsage)
  1856. {
  1857. //
  1858. // See if USAGE is CHANNEL.
  1859. //
  1860. if (StrEqlW(bstrUsage, WSTR_CHANNEL))
  1861. {
  1862. bRet = TRUE;
  1863. }
  1864. else
  1865. {
  1866. //
  1867. // Check if there are any other USAGE tags with value CHANNEL.
  1868. //
  1869. BSTR bstrChannel = XML_GetAttribute(pIXMLElement,
  1870. XML_USAGE_CHANNEL);
  1871. if (bstrChannel)
  1872. {
  1873. SysFreeString(bstrChannel);
  1874. bRet = TRUE;
  1875. }
  1876. else
  1877. {
  1878. bRet = FALSE;
  1879. }
  1880. }
  1881. SysFreeString(bstrUsage);
  1882. }
  1883. else
  1884. {
  1885. bRet = TRUE; // No USAGE tag defaults channel usage.
  1886. }
  1887. return bRet;
  1888. }
  1889. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1890. //
  1891. // *** XML_IsChannel ***
  1892. //
  1893. //
  1894. // Description:
  1895. // Determines if the given XML item is a channel.
  1896. //
  1897. // Parameters:
  1898. // [In] pIXMLElement - A pointer to the IXMLElement interface of an object.
  1899. //
  1900. // Return:
  1901. // TRUE if the object is a channel.
  1902. // FALSE otherwise.
  1903. //
  1904. // Comments:
  1905. //
  1906. //
  1907. ////////////////////////////////////////////////////////////////////////////////
  1908. BOOL
  1909. XML_IsChannel(
  1910. IXMLElement* pIXMLElement
  1911. )
  1912. {
  1913. ASSERT(pIXMLElement);
  1914. BOOL bRet = FALSE;
  1915. BSTR pStr;
  1916. HRESULT hr = pIXMLElement->get_tagName(&pStr);
  1917. if (SUCCEEDED(hr) && pStr)
  1918. {
  1919. ASSERT(pStr);
  1920. bRet = StrEqlW(pStr, WSTR_CHANNEL);
  1921. SysFreeString(pStr);
  1922. }
  1923. return bRet;
  1924. }
  1925. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1926. //
  1927. // *** XML_IsDesktopComponent ***
  1928. //
  1929. //
  1930. // Description:
  1931. // Determines if the given XML item is a desktop component.
  1932. //
  1933. // Parameters:
  1934. // [In] pIXMLElement - A pointer to the IXMLElement interface of an object.
  1935. //
  1936. // Return:
  1937. // TRUE if the object is a desktop component.
  1938. // FALSE otherwise.
  1939. //
  1940. // Comments:
  1941. //
  1942. //
  1943. ////////////////////////////////////////////////////////////////////////////////
  1944. BOOL
  1945. XML_IsDesktopComponent(
  1946. IXMLElement* pIXMLElement
  1947. )
  1948. {
  1949. ASSERT(pIXMLElement);
  1950. BOOL bRet;
  1951. BSTR bstr = XML_GetAttribute(pIXMLElement, XML_USAGE_DSKCMP);
  1952. if (bstr)
  1953. {
  1954. SysFreeString(bstr);
  1955. bRet = TRUE;
  1956. }
  1957. else
  1958. {
  1959. bRet = FALSE;
  1960. }
  1961. return bRet;
  1962. }
  1963. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1964. //
  1965. // *** XML_IsScreenSaver ***
  1966. //
  1967. //
  1968. // Description:
  1969. // Determines if the given XML item is a screen saver.
  1970. //
  1971. // Parameters:
  1972. // [In] pIXMLElement - A pointer to the IXMLElement interface of an object.
  1973. //
  1974. // Return:
  1975. // TRUE if the object is a screen saver
  1976. // FALSE otherwise.
  1977. //
  1978. // Comments:
  1979. //
  1980. //
  1981. ////////////////////////////////////////////////////////////////////////////////
  1982. BOOL
  1983. XML_IsScreenSaver(
  1984. IXMLElement* pIXMLElement
  1985. )
  1986. {
  1987. ASSERT(pIXMLElement);
  1988. BOOL bRet;
  1989. BSTR bstrUsage = XML_GetAttribute(pIXMLElement, XML_USAGE);
  1990. if (bstrUsage)
  1991. {
  1992. bRet = (
  1993. (StrCmpIW(bstrUsage, WSTR_SCRNSAVE) == 0)
  1994. ||
  1995. (StrCmpIW(bstrUsage, WSTR_SMARTSCRN) == 0)
  1996. );
  1997. SysFreeString(bstrUsage);
  1998. }
  1999. else
  2000. {
  2001. bRet = FALSE;
  2002. }
  2003. return bRet;
  2004. }
  2005. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2006. //
  2007. // *** XML_IsDesktopComponentUsage ***
  2008. //
  2009. //
  2010. // Description:
  2011. // Determines if the given XML item is a desktop component usage element.
  2012. //
  2013. // Parameters:
  2014. // [In] pIXMLElement - A pointer to the IXMLElement interface of an object.
  2015. //
  2016. // Return:
  2017. // TRUE if the object is a desktop component usage element.
  2018. // FALSE otherwise.
  2019. //
  2020. // Comments:
  2021. //
  2022. //
  2023. ////////////////////////////////////////////////////////////////////////////////
  2024. BOOL
  2025. XML_IsDesktopComponentUsage(
  2026. IXMLElement* pIXMLElement
  2027. )
  2028. {
  2029. ASSERT(pIXMLElement);
  2030. BOOL bRet = FALSE;
  2031. BSTR bstrName;
  2032. if (SUCCEEDED(pIXMLElement->get_tagName(&bstrName)) && bstrName)
  2033. {
  2034. ASSERT(bstrName);
  2035. if (StrEqlW(bstrName, WSTR_USAGE))
  2036. {
  2037. BSTR bstrValue = XML_GetElementAttribute(pIXMLElement, WSTR_VALUE, NULL,
  2038. NULL);
  2039. if (bstrValue)
  2040. {
  2041. bRet = (0 == StrCmpIW(bstrValue, WSTR_DSKCMP));
  2042. SysFreeString(bstrValue);
  2043. }
  2044. }
  2045. SysFreeString(bstrName);
  2046. }
  2047. return bRet;
  2048. }
  2049. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2050. //
  2051. // *** XML_IsFolder ***
  2052. //
  2053. //
  2054. // Description:
  2055. // Determines if the given item is a folder.
  2056. //
  2057. // Parameters:
  2058. // [In] pIXMLElement - A pointer to the IXMLElement interface of an object.
  2059. //
  2060. // Return:
  2061. // TRUE if the object contains other cdf displayable objects.
  2062. // FALSE otherwise.
  2063. //
  2064. // Comments:
  2065. // An item is a folder if at least one of its children is displayable as a
  2066. // cdf item.
  2067. //
  2068. ////////////////////////////////////////////////////////////////////////////////
  2069. BOOL
  2070. XML_IsFolder(
  2071. IXMLElement* pIXMLElement
  2072. )
  2073. {
  2074. ASSERT(pIXMLElement);
  2075. BOOL bRet = FALSE;
  2076. IXMLElementCollection* pIXMLElementCollection;
  2077. HRESULT hr = pIXMLElement->get_children(&pIXMLElementCollection);
  2078. if (SUCCEEDED(hr) && pIXMLElementCollection)
  2079. {
  2080. ASSERT(pIXMLElementCollection);
  2081. LONG nCount;
  2082. hr = pIXMLElementCollection->get_length(&nCount);
  2083. ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount));
  2084. for (int i = 0; (i < nCount) && !bRet; i++)
  2085. {
  2086. IXMLElement* pIXMLElementTemp;
  2087. hr = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElementTemp);
  2088. if (SUCCEEDED(hr))
  2089. {
  2090. ASSERT(pIXMLElementTemp);
  2091. if (XML_IsCdfDisplayable(pIXMLElementTemp))
  2092. bRet = TRUE;
  2093. pIXMLElementTemp->Release();
  2094. }
  2095. }
  2096. pIXMLElementCollection->Release();
  2097. }
  2098. return bRet;
  2099. }
  2100. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2101. //
  2102. // *** XML_ContainsFolder ***
  2103. //
  2104. //
  2105. // Description:
  2106. // Determines if there are any cdf folders in the given collection.
  2107. //
  2108. // Parameters:
  2109. // [In] pIXMLElementCollection - A pointer to the collection.
  2110. //
  2111. // Return:
  2112. // TRUE if the collection contains a cf folder.
  2113. // FALSE otherwise.
  2114. //
  2115. // Comments:
  2116. //
  2117. //
  2118. ////////////////////////////////////////////////////////////////////////////////
  2119. BOOL
  2120. XML_ContainsFolder(
  2121. IXMLElementCollection* pIXMLElementCollection
  2122. )
  2123. {
  2124. ASSERT(pIXMLElementCollection);
  2125. BOOL bContainsFolder = FALSE;
  2126. LONG nCount;
  2127. HRESULT hr = pIXMLElementCollection->get_length(&nCount);
  2128. ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount));
  2129. for (int i = 0; (i < nCount) && !bContainsFolder; i++)
  2130. {
  2131. IXMLElement* pIXMLElement;
  2132. hr = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElement);
  2133. if (SUCCEEDED(hr))
  2134. {
  2135. ASSERT(pIXMLElement);
  2136. bContainsFolder = XML_IsFolder(pIXMLElement);
  2137. pIXMLElement->Release();
  2138. }
  2139. }
  2140. return bContainsFolder;
  2141. }
  2142. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2143. //
  2144. // *** XML_ChildContainsFolder ***
  2145. //
  2146. //
  2147. // Description:
  2148. //
  2149. //
  2150. // Parameters:
  2151. //
  2152. //
  2153. // Return:
  2154. //
  2155. //
  2156. // Comments:
  2157. //
  2158. //
  2159. ////////////////////////////////////////////////////////////////////////////////
  2160. BOOL
  2161. XML_ChildContainsFolder(
  2162. IXMLElementCollection *pIXMLElementCollectionParent,
  2163. ULONG nIndexChild
  2164. )
  2165. {
  2166. BOOL bRet = FALSE;
  2167. IXMLElement* pIXMLElement;
  2168. HRESULT hr = XML_GetElementByIndex(pIXMLElementCollectionParent,
  2169. nIndexChild, &pIXMLElement);
  2170. if (SUCCEEDED(hr))
  2171. {
  2172. ASSERT(pIXMLElement);
  2173. IXMLElementCollection* pIXMLElementCollection;
  2174. hr = pIXMLElement->get_children(&pIXMLElementCollection);
  2175. if (SUCCEEDED(hr) && pIXMLElementCollection)
  2176. {
  2177. ASSERT(pIXMLElementCollection);
  2178. bRet = XML_ContainsFolder(pIXMLElementCollection);
  2179. pIXMLElementCollection->Release();
  2180. }
  2181. pIXMLElement->Release();
  2182. }
  2183. return bRet;
  2184. }
  2185. #ifdef DEBUG
  2186. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2187. //
  2188. // *** XML_IsCdfidlMemberOf ***
  2189. //
  2190. //
  2191. // Description:
  2192. // Checks if the cdf item id list is associated with a member of the given
  2193. // element collection.
  2194. //
  2195. // Parameters:
  2196. // [In] pIXMLElementCollection - The element collection to check.
  2197. // [In] pcdfidl - A pointer to cdf item id list
  2198. //
  2199. // Return:
  2200. // TRUE if the given id list can be associated with an elemnt of the given
  2201. // collection.
  2202. // FALSE otherwise.
  2203. //
  2204. // Comments:
  2205. // This function checks if the last id in the list could have been
  2206. // generated from its corresponding element in the element collection.
  2207. //
  2208. ////////////////////////////////////////////////////////////////////////////////
  2209. BOOL
  2210. XML_IsCdfidlMemberOf(
  2211. IXMLElementCollection* pIXMLElementCollection,
  2212. PCDFITEMIDLIST pcdfidl
  2213. )
  2214. {
  2215. ASSERT(CDFIDL_IsValid(pcdfidl));
  2216. BOOL bRet = FALSE;
  2217. //
  2218. // pIXMLElementCollection is NULL when a Folder hasn't been initialized.
  2219. // It isn't always neccessary to parse the cdf to get pidl info from
  2220. // the pidl. pIXMLElement collection will be NULL in low memory situations
  2221. // also. Don't return FALSE for these cases. Also check for special
  2222. // pidls that aren't in element collections.
  2223. //
  2224. if (pIXMLElementCollection &&
  2225. CDFIDL_GetIndexId(&pcdfidl->mkid) != INDEX_CHANNEL_LINK)
  2226. {
  2227. IXMLElement* pIXMLElement;
  2228. HRESULT hr = XML_GetElementByIndex(pIXMLElementCollection,
  2229. CDFIDL_GetIndexId(&pcdfidl->mkid),
  2230. &pIXMLElement);
  2231. if (SUCCEEDED(hr))
  2232. {
  2233. ASSERT(pIXMLElement);
  2234. PCDFITEMIDLIST pcdfidlElement;
  2235. pcdfidlElement = CDFIDL_CreateFromXMLElement(pIXMLElement,
  2236. CDFIDL_GetIndexId(&pcdfidl->mkid));
  2237. if (pcdfidlElement)
  2238. {
  2239. ASSERT(CDFIDL_IsValid(pcdfidlElement));
  2240. bRet = (0 == CDFIDL_CompareId(&pcdfidl->mkid,
  2241. &pcdfidlElement->mkid));
  2242. CDFIDL_Free(pcdfidlElement);
  2243. }
  2244. pIXMLElement->Release();
  2245. }
  2246. }
  2247. else
  2248. {
  2249. bRet = TRUE;
  2250. }
  2251. return bRet;
  2252. }
  2253. #endif //DEBUG
  2254. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2255. //
  2256. // *** XML_IsStrEqualW ***
  2257. //
  2258. //
  2259. // Description:
  2260. // Determines if two WCHAR strings are equal.
  2261. //
  2262. // Parameters:
  2263. // [In] p1 - The first string to compare.
  2264. // [In] p2 - The second string to compare.
  2265. //
  2266. // Return:
  2267. // TRUE if the strings are equal.
  2268. // FALSE otherwise.
  2269. //
  2270. // Comments:
  2271. // lstrcmpW doesn't work on W95 so this function has its own strcmp logic.
  2272. //
  2273. ////////////////////////////////////////////////////////////////////////////////
  2274. #if 0
  2275. inline
  2276. BOOL
  2277. XML_IsStrEqualW(
  2278. LPWSTR p1,
  2279. LPWSTR p2
  2280. )
  2281. {
  2282. ASSERT(p1);
  2283. ASSERT(p2);
  2284. while ((*p1 == *p2) && *p1 && *p2)
  2285. {
  2286. p1++; p2++;
  2287. }
  2288. return (*p1 == *p2);
  2289. }
  2290. #endif