aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/rssutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/rssutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/rssutil.cpp647
1 files changed, 647 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/rssutil.cpp b/src/libs/dutil/WixToolset.DUtil/rssutil.cpp
new file mode 100644
index 00000000..8f994dfc
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/rssutil.cpp
@@ -0,0 +1,647 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5
6// Exit macros
7#define RssExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_RSSUTIL, x, s, __VA_ARGS__)
8#define RssExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_RSSUTIL, x, s, __VA_ARGS__)
9#define RssExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_RSSUTIL, x, s, __VA_ARGS__)
10#define RssExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_RSSUTIL, x, s, __VA_ARGS__)
11#define RssExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_RSSUTIL, x, s, __VA_ARGS__)
12#define RssExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_RSSUTIL, x, s, __VA_ARGS__)
13#define RssExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_RSSUTIL, p, x, e, s, __VA_ARGS__)
14#define RssExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_RSSUTIL, p, x, s, __VA_ARGS__)
15#define RssExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_RSSUTIL, p, x, e, s, __VA_ARGS__)
16#define RssExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_RSSUTIL, p, x, s, __VA_ARGS__)
17#define RssExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_RSSUTIL, e, x, s, __VA_ARGS__)
18#define RssExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_RSSUTIL, g, x, s, __VA_ARGS__)
19
20static HRESULT ParseRssDocument(
21 __in IXMLDOMDocument *pixd,
22 __out RSS_CHANNEL **ppChannel
23 );
24static HRESULT ParseRssChannel(
25 __in IXMLDOMNode *pixnChannel,
26 __out RSS_CHANNEL **ppChannel
27 );
28static HRESULT ParseRssItem(
29 __in IXMLDOMNode *pixnItem,
30 __in DWORD cItem,
31 __in_xcount(pChannel->cItems) RSS_CHANNEL *pChannel
32 );
33static HRESULT ParseRssUnknownElement(
34 __in IXMLDOMNode *pNode,
35 __inout RSS_UNKNOWN_ELEMENT** ppUnknownElement
36 );
37static HRESULT ParseRssUnknownAttribute(
38 __in IXMLDOMNode *pNode,
39 __inout RSS_UNKNOWN_ATTRIBUTE** ppUnknownAttribute
40 );
41static void FreeRssUnknownElementList(
42 __in_opt RSS_UNKNOWN_ELEMENT* pUnknownElement
43 );
44static void FreeRssUnknownAttributeList(
45 __in_opt RSS_UNKNOWN_ATTRIBUTE* pUnknownAttribute
46 );
47
48
49/********************************************************************
50 RssInitialize - Initialize RSS utilities.
51
52*********************************************************************/
53extern "C" HRESULT DAPI RssInitialize()
54{
55 return XmlInitialize();
56}
57
58
59/********************************************************************
60 RssUninitialize - Uninitialize RSS utilities.
61
62*********************************************************************/
63extern "C" void DAPI RssUninitialize()
64{
65 XmlUninitialize();
66}
67
68
69/********************************************************************
70 RssParseFromString - parses out an RSS channel from a string.
71
72*********************************************************************/
73extern "C" HRESULT DAPI RssParseFromString(
74 __in_z LPCWSTR wzRssString,
75 __out RSS_CHANNEL **ppChannel
76 )
77{
78 Assert(wzRssString);
79 Assert(ppChannel);
80
81 HRESULT hr = S_OK;
82 RSS_CHANNEL *pNewChannel = NULL;
83 IXMLDOMDocument *pixdRss = NULL;
84
85 hr = XmlLoadDocument(wzRssString, &pixdRss);
86 RssExitOnFailure(hr, "Failed to load RSS string as XML document.");
87
88 hr = ParseRssDocument(pixdRss, &pNewChannel);
89 RssExitOnFailure(hr, "Failed to parse RSS document.");
90
91 *ppChannel = pNewChannel;
92 pNewChannel = NULL;
93
94LExit:
95 ReleaseObject(pixdRss);
96
97 ReleaseRssChannel(pNewChannel);
98
99 return hr;
100}
101
102
103/********************************************************************
104 RssParseFromFile - parses out an RSS channel from a file path.
105
106*********************************************************************/
107extern "C" HRESULT DAPI RssParseFromFile(
108 __in_z LPCWSTR wzRssFile,
109 __out RSS_CHANNEL **ppChannel
110 )
111{
112 Assert(wzRssFile);
113 Assert(ppChannel);
114
115 HRESULT hr = S_OK;
116 RSS_CHANNEL *pNewChannel = NULL;
117 IXMLDOMDocument *pixdRss = NULL;
118
119 hr = XmlLoadDocumentFromFile(wzRssFile, &pixdRss);
120 RssExitOnFailure(hr, "Failed to load RSS string as XML document.");
121
122 hr = ParseRssDocument(pixdRss, &pNewChannel);
123 RssExitOnFailure(hr, "Failed to parse RSS document.");
124
125 *ppChannel = pNewChannel;
126 pNewChannel = NULL;
127
128LExit:
129 ReleaseObject(pixdRss);
130
131 ReleaseRssChannel(pNewChannel);
132
133 return hr;
134}
135
136
137/********************************************************************
138 RssFreeChannel - parses out an RSS channel from a string.
139
140*********************************************************************/
141extern "C" void DAPI RssFreeChannel(
142 __in_xcount(pChannel->cItems) RSS_CHANNEL *pChannel
143 )
144{
145 if (pChannel)
146 {
147 for (DWORD i = 0; i < pChannel->cItems; ++i)
148 {
149 ReleaseStr(pChannel->rgItems[i].wzTitle);
150 ReleaseStr(pChannel->rgItems[i].wzLink);
151 ReleaseStr(pChannel->rgItems[i].wzDescription);
152 ReleaseStr(pChannel->rgItems[i].wzGuid);
153 ReleaseStr(pChannel->rgItems[i].wzEnclosureUrl);
154 ReleaseStr(pChannel->rgItems[i].wzEnclosureType);
155
156 FreeRssUnknownElementList(pChannel->rgItems[i].pUnknownElements);
157 }
158
159 ReleaseStr(pChannel->wzTitle);
160 ReleaseStr(pChannel->wzLink);
161 ReleaseStr(pChannel->wzDescription);
162 FreeRssUnknownElementList(pChannel->pUnknownElements);
163
164 MemFree(pChannel);
165 }
166}
167
168
169/********************************************************************
170 ParseRssDocument - parses out an RSS channel from a loaded XML DOM document.
171
172*********************************************************************/
173static HRESULT ParseRssDocument(
174 __in IXMLDOMDocument *pixd,
175 __out RSS_CHANNEL **ppChannel
176 )
177{
178 Assert(pixd);
179 Assert(ppChannel);
180
181 HRESULT hr = S_OK;
182 IXMLDOMElement *pRssElement = NULL;
183 IXMLDOMNodeList *pChannelNodes = NULL;
184 IXMLDOMNode *pNode = NULL;
185 BSTR bstrNodeName = NULL;
186
187 RSS_CHANNEL *pNewChannel = NULL;
188
189 //
190 // Get the document element and start processing channels.
191 //
192 hr = pixd ->get_documentElement(&pRssElement);
193 RssExitOnFailure(hr, "failed get_documentElement in ParseRssDocument");
194
195 hr = pRssElement->get_childNodes(&pChannelNodes);
196 RssExitOnFailure(hr, "Failed to get child nodes of Rss Document element.");
197
198 while (S_OK == (hr = XmlNextElement(pChannelNodes, &pNode, &bstrNodeName)))
199 {
200 if (0 == lstrcmpW(bstrNodeName, L"channel"))
201 {
202 hr = ParseRssChannel(pNode, &pNewChannel);
203 RssExitOnFailure(hr, "Failed to parse RSS channel.");
204 }
205 else if (0 == lstrcmpW(bstrNodeName, L"link"))
206 {
207 }
208
209 ReleaseNullBSTR(bstrNodeName);
210 ReleaseNullObject(pNode);
211 }
212
213 if (S_FALSE == hr)
214 {
215 hr = S_OK;
216 }
217
218 *ppChannel = pNewChannel;
219 pNewChannel = NULL;
220
221LExit:
222 ReleaseBSTR(bstrNodeName);
223 ReleaseObject(pNode);
224 ReleaseObject(pChannelNodes);
225 ReleaseObject(pRssElement);
226
227 ReleaseRssChannel(pNewChannel);
228
229 return hr;
230}
231
232
233/********************************************************************
234 ParseRssChannel - parses out an RSS channel from a loaded XML DOM element.
235
236*********************************************************************/
237static HRESULT ParseRssChannel(
238 __in IXMLDOMNode *pixnChannel,
239 __out RSS_CHANNEL **ppChannel
240 )
241{
242 Assert(pixnChannel);
243 Assert(ppChannel);
244
245 HRESULT hr = S_OK;
246 IXMLDOMNodeList *pNodeList = NULL;
247
248 RSS_CHANNEL *pNewChannel = NULL;
249 long cItems = 0;
250
251 IXMLDOMNode *pNode = NULL;
252 BSTR bstrNodeName = NULL;
253 BSTR bstrNodeValue = NULL;
254
255 //
256 // First, calculate how many RSS items we're going to have and allocate
257 // the RSS_CHANNEL structure
258 //
259 hr = XmlSelectNodes(pixnChannel, L"item", &pNodeList);
260 RssExitOnFailure(hr, "Failed to select all RSS items in an RSS channel.");
261
262 hr = pNodeList->get_length(&cItems);
263 RssExitOnFailure(hr, "Failed to count the number of RSS items in RSS channel.");
264
265 pNewChannel = static_cast<RSS_CHANNEL*>(MemAlloc(sizeof(RSS_CHANNEL) + sizeof(RSS_ITEM) * cItems, TRUE));
266 RssExitOnNull(pNewChannel, hr, E_OUTOFMEMORY, "Failed to allocate RSS channel structure.");
267
268 pNewChannel->cItems = cItems;
269
270 //
271 // Process the elements under a channel now.
272 //
273 hr = pixnChannel->get_childNodes(&pNodeList);
274 RssExitOnFailure(hr, "Failed to get child nodes of RSS channel element.");
275
276 cItems = 0; // reset the counter and use this to walk through the channel items
277 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName)))
278 {
279 if (0 == lstrcmpW(bstrNodeName, L"title"))
280 {
281 hr = XmlGetText(pNode, &bstrNodeValue);
282 RssExitOnFailure(hr, "Failed to get RSS channel title.");
283
284 hr = StrAllocString(&pNewChannel->wzTitle, bstrNodeValue, 0);
285 RssExitOnFailure(hr, "Failed to allocate RSS channel title.");
286 }
287 else if (0 == lstrcmpW(bstrNodeName, L"link"))
288 {
289 hr = XmlGetText(pNode, &bstrNodeValue);
290 RssExitOnFailure(hr, "Failed to get RSS channel link.");
291
292 hr = StrAllocString(&pNewChannel->wzLink, bstrNodeValue, 0);
293 RssExitOnFailure(hr, "Failed to allocate RSS channel link.");
294 }
295 else if (0 == lstrcmpW(bstrNodeName, L"description"))
296 {
297 hr = XmlGetText(pNode, &bstrNodeValue);
298 RssExitOnFailure(hr, "Failed to get RSS channel description.");
299
300 hr = StrAllocString(&pNewChannel->wzDescription, bstrNodeValue, 0);
301 RssExitOnFailure(hr, "Failed to allocate RSS channel description.");
302 }
303 else if (0 == lstrcmpW(bstrNodeName, L"ttl"))
304 {
305 hr = XmlGetText(pNode, &bstrNodeValue);
306 RssExitOnFailure(hr, "Failed to get RSS channel description.");
307
308 pNewChannel->dwTimeToLive = (DWORD)wcstoul(bstrNodeValue, NULL, 10);
309 }
310 else if (0 == lstrcmpW(bstrNodeName, L"item"))
311 {
312 hr = ParseRssItem(pNode, cItems, pNewChannel);
313 RssExitOnFailure(hr, "Failed to parse RSS item.");
314
315 ++cItems;
316 }
317 else
318 {
319 hr = ParseRssUnknownElement(pNode, &pNewChannel->pUnknownElements);
320 RssExitOnFailure(hr, "Failed to parse unknown RSS channel element: %ls", bstrNodeName);
321 }
322
323 ReleaseNullBSTR(bstrNodeValue);
324 ReleaseNullBSTR(bstrNodeName);
325 ReleaseNullObject(pNode);
326 }
327
328 *ppChannel = pNewChannel;
329 pNewChannel = NULL;
330
331LExit:
332 ReleaseBSTR(bstrNodeName);
333 ReleaseObject(pNode);
334 ReleaseObject(pNodeList);
335
336 ReleaseRssChannel(pNewChannel);
337
338 return hr;
339}
340
341
342/********************************************************************
343 ParseRssItem - parses out an RSS item from a loaded XML DOM node.
344
345*********************************************************************/
346static HRESULT ParseRssItem(
347 __in IXMLDOMNode *pixnItem,
348 __in DWORD cItem,
349 __in_xcount(pChannel->cItems) RSS_CHANNEL *pChannel
350 )
351{
352 HRESULT hr = S_OK;
353
354 RSS_ITEM *pItem = NULL;
355 IXMLDOMNodeList *pNodeList = NULL;
356
357 IXMLDOMNode *pNode = NULL;
358 BSTR bstrNodeName = NULL;
359 BSTR bstrNodeValue = NULL;
360
361 //
362 // First make sure we're dealing with a valid item.
363 //
364 if (pChannel->cItems <= cItem)
365 {
366 hr = E_UNEXPECTED;
367 RssExitOnFailure(hr, "Unexpected number of items parsed.");
368 }
369
370 pItem = pChannel->rgItems + cItem;
371
372 //
373 // Process the elements under an item now.
374 //
375 hr = pixnItem->get_childNodes(&pNodeList);
376 RssExitOnFailure(hr, "Failed to get child nodes of RSS item element.");
377 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName)))
378 {
379 if (0 == lstrcmpW(bstrNodeName, L"title"))
380 {
381 hr = XmlGetText(pNode, &bstrNodeValue);
382 RssExitOnFailure(hr, "Failed to get RSS channel title.");
383
384 hr = StrAllocString(&pItem->wzTitle, bstrNodeValue, 0);
385 RssExitOnFailure(hr, "Failed to allocate RSS item title.");
386 }
387 else if (0 == lstrcmpW(bstrNodeName, L"link"))
388 {
389 hr = XmlGetText(pNode, &bstrNodeValue);
390 RssExitOnFailure(hr, "Failed to get RSS channel link.");
391
392 hr = StrAllocString(&pItem->wzLink, bstrNodeValue, 0);
393 RssExitOnFailure(hr, "Failed to allocate RSS item link.");
394 }
395 else if (0 == lstrcmpW(bstrNodeName, L"description"))
396 {
397 hr = XmlGetText(pNode, &bstrNodeValue);
398 RssExitOnFailure(hr, "Failed to get RSS item description.");
399
400 hr = StrAllocString(&pItem->wzDescription, bstrNodeValue, 0);
401 RssExitOnFailure(hr, "Failed to allocate RSS item description.");
402 }
403 else if (0 == lstrcmpW(bstrNodeName, L"guid"))
404 {
405 hr = XmlGetText(pNode, &bstrNodeValue);
406 RssExitOnFailure(hr, "Failed to get RSS item guid.");
407
408 hr = StrAllocString(&pItem->wzGuid, bstrNodeValue, 0);
409 RssExitOnFailure(hr, "Failed to allocate RSS item guid.");
410 }
411 else if (0 == lstrcmpW(bstrNodeName, L"pubDate"))
412 {
413 hr = XmlGetText(pNode, &bstrNodeValue);
414 RssExitOnFailure(hr, "Failed to get RSS item guid.");
415
416 hr = TimeFromString(bstrNodeValue, &pItem->ftPublished);
417 RssExitOnFailure(hr, "Failed to convert RSS item time.");
418 }
419 else if (0 == lstrcmpW(bstrNodeName, L"enclosure"))
420 {
421 hr = XmlGetAttribute(pNode, L"url", &bstrNodeValue);
422 RssExitOnFailure(hr, "Failed to get RSS item enclosure url.");
423
424 hr = StrAllocString(&pItem->wzEnclosureUrl, bstrNodeValue, 0);
425 RssExitOnFailure(hr, "Failed to allocate RSS item enclosure url.");
426 ReleaseNullBSTR(bstrNodeValue);
427
428 hr = XmlGetAttributeNumber(pNode, L"length", &pItem->dwEnclosureSize);
429 RssExitOnFailure(hr, "Failed to get RSS item enclosure length.");
430
431 hr = XmlGetAttribute(pNode, L"type", &bstrNodeValue);
432 RssExitOnFailure(hr, "Failed to get RSS item enclosure type.");
433
434 hr = StrAllocString(&pItem->wzEnclosureType, bstrNodeValue, 0);
435 RssExitOnFailure(hr, "Failed to allocate RSS item enclosure type.");
436 }
437 else
438 {
439 hr = ParseRssUnknownElement(pNode, &pItem->pUnknownElements);
440 RssExitOnFailure(hr, "Failed to parse unknown RSS item element: %ls", bstrNodeName);
441 }
442
443 ReleaseNullBSTR(bstrNodeValue);
444 ReleaseNullBSTR(bstrNodeName);
445 ReleaseNullObject(pNode);
446 }
447
448LExit:
449 ReleaseBSTR(bstrNodeValue);
450 ReleaseBSTR(bstrNodeName);
451 ReleaseObject(pNode);
452 ReleaseObject(pNodeList);
453
454 return hr;
455}
456
457
458/********************************************************************
459 ParseRssUnknownElement - parses out an unknown item from the RSS feed from a loaded XML DOM node.
460
461*********************************************************************/
462static HRESULT ParseRssUnknownElement(
463 __in IXMLDOMNode *pNode,
464 __inout RSS_UNKNOWN_ELEMENT** ppUnknownElement
465 )
466{
467 Assert(ppUnknownElement);
468
469 HRESULT hr = S_OK;
470 BSTR bstrNodeNamespace = NULL;
471 BSTR bstrNodeName = NULL;
472 BSTR bstrNodeValue = NULL;
473 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
474 IXMLDOMNode* pixnAttribute = NULL;
475 RSS_UNKNOWN_ELEMENT* pNewUnknownElement;
476
477 pNewUnknownElement = static_cast<RSS_UNKNOWN_ELEMENT*>(MemAlloc(sizeof(RSS_UNKNOWN_ELEMENT), TRUE));
478 RssExitOnNull(pNewUnknownElement, hr, E_OUTOFMEMORY, "Failed to allocate unknown element.");
479
480 hr = pNode->get_namespaceURI(&bstrNodeNamespace);
481 if (S_OK == hr)
482 {
483 hr = StrAllocString(&pNewUnknownElement->wzNamespace, bstrNodeNamespace, 0);
484 RssExitOnFailure(hr, "Failed to allocate RSS unknown element namespace.");
485 }
486 else if (S_FALSE == hr)
487 {
488 hr = S_OK;
489 }
490 RssExitOnFailure(hr, "Failed to get unknown element namespace.");
491
492 hr = pNode->get_baseName(&bstrNodeName);
493 RssExitOnFailure(hr, "Failed to get unknown element name.");
494
495 hr = StrAllocString(&pNewUnknownElement->wzElement, bstrNodeName, 0);
496 RssExitOnFailure(hr, "Failed to allocate RSS unknown element name.");
497
498 hr = XmlGetText(pNode, &bstrNodeValue);
499 RssExitOnFailure(hr, "Failed to get unknown element value.");
500
501 hr = StrAllocString(&pNewUnknownElement->wzValue, bstrNodeValue, 0);
502 RssExitOnFailure(hr, "Failed to allocate RSS unknown element value.");
503
504 hr = pNode->get_attributes(&pixnnmAttributes);
505 RssExitOnFailure(hr, "Failed get attributes on RSS unknown element.");
506
507 while (S_OK == (hr = pixnnmAttributes->nextNode(&pixnAttribute)))
508 {
509 hr = ParseRssUnknownAttribute(pixnAttribute, &pNewUnknownElement->pAttributes);
510 RssExitOnFailure(hr, "Failed to parse attribute on RSS unknown element.");
511
512 ReleaseNullObject(pixnAttribute);
513 }
514
515 if (S_FALSE == hr)
516 {
517 hr = S_OK;
518 }
519 RssExitOnFailure(hr, "Failed to enumerate all attributes on RSS unknown element.");
520
521 RSS_UNKNOWN_ELEMENT** ppTail = ppUnknownElement;
522 while (*ppTail)
523 {
524 ppTail = &(*ppTail)->pNext;
525 }
526
527 *ppTail = pNewUnknownElement;
528 pNewUnknownElement = NULL;
529
530LExit:
531 FreeRssUnknownElementList(pNewUnknownElement);
532
533 ReleaseBSTR(bstrNodeNamespace);
534 ReleaseBSTR(bstrNodeName);
535 ReleaseBSTR(bstrNodeValue);
536 ReleaseObject(pixnnmAttributes);
537 ReleaseObject(pixnAttribute);
538
539 return hr;
540}
541
542
543/********************************************************************
544 ParseRssUnknownAttribute - parses out attribute from an unknown element
545
546*********************************************************************/
547static HRESULT ParseRssUnknownAttribute(
548 __in IXMLDOMNode *pNode,
549 __inout RSS_UNKNOWN_ATTRIBUTE** ppUnknownAttribute
550 )
551{
552 Assert(ppUnknownAttribute);
553
554 HRESULT hr = S_OK;
555 BSTR bstrNodeNamespace = NULL;
556 BSTR bstrNodeName = NULL;
557 BSTR bstrNodeValue = NULL;
558 RSS_UNKNOWN_ATTRIBUTE* pNewUnknownAttribute;
559
560 pNewUnknownAttribute = static_cast<RSS_UNKNOWN_ATTRIBUTE*>(MemAlloc(sizeof(RSS_UNKNOWN_ATTRIBUTE), TRUE));
561 RssExitOnNull(pNewUnknownAttribute, hr, E_OUTOFMEMORY, "Failed to allocate unknown attribute.");
562
563 hr = pNode->get_namespaceURI(&bstrNodeNamespace);
564 if (S_OK == hr)
565 {
566 hr = StrAllocString(&pNewUnknownAttribute->wzNamespace, bstrNodeNamespace, 0);
567 RssExitOnFailure(hr, "Failed to allocate RSS unknown attribute namespace.");
568 }
569 else if (S_FALSE == hr)
570 {
571 hr = S_OK;
572 }
573 RssExitOnFailure(hr, "Failed to get unknown attribute namespace.");
574
575 hr = pNode->get_baseName(&bstrNodeName);
576 RssExitOnFailure(hr, "Failed to get unknown attribute name.");
577
578 hr = StrAllocString(&pNewUnknownAttribute->wzAttribute, bstrNodeName, 0);
579 RssExitOnFailure(hr, "Failed to allocate RSS unknown attribute name.");
580
581 hr = XmlGetText(pNode, &bstrNodeValue);
582 RssExitOnFailure(hr, "Failed to get unknown attribute value.");
583
584 hr = StrAllocString(&pNewUnknownAttribute->wzValue, bstrNodeValue, 0);
585 RssExitOnFailure(hr, "Failed to allocate RSS unknown attribute value.");
586
587 RSS_UNKNOWN_ATTRIBUTE** ppTail = ppUnknownAttribute;
588 while (*ppTail)
589 {
590 ppTail = &(*ppTail)->pNext;
591 }
592
593 *ppTail = pNewUnknownAttribute;
594 pNewUnknownAttribute = NULL;
595
596LExit:
597 FreeRssUnknownAttributeList(pNewUnknownAttribute);
598
599 ReleaseBSTR(bstrNodeNamespace);
600 ReleaseBSTR(bstrNodeName);
601 ReleaseBSTR(bstrNodeValue);
602
603 return hr;
604}
605
606
607/********************************************************************
608 FreeRssUnknownElement - releases all of the memory used by a list of unknown elements
609
610*********************************************************************/
611static void FreeRssUnknownElementList(
612 __in_opt RSS_UNKNOWN_ELEMENT* pUnknownElement
613 )
614{
615 while (pUnknownElement)
616 {
617 RSS_UNKNOWN_ELEMENT* pFree = pUnknownElement;
618 pUnknownElement = pUnknownElement->pNext;
619
620 FreeRssUnknownAttributeList(pFree->pAttributes);
621 ReleaseStr(pFree->wzNamespace);
622 ReleaseStr(pFree->wzElement);
623 ReleaseStr(pFree->wzValue);
624 MemFree(pFree);
625 }
626}
627
628
629/********************************************************************
630 FreeRssUnknownAttribute - releases all of the memory used by a list of unknown attributes
631
632*********************************************************************/
633static void FreeRssUnknownAttributeList(
634 __in_opt RSS_UNKNOWN_ATTRIBUTE* pUnknownAttribute
635 )
636{
637 while (pUnknownAttribute)
638 {
639 RSS_UNKNOWN_ATTRIBUTE* pFree = pUnknownAttribute;
640 pUnknownAttribute = pUnknownAttribute->pNext;
641
642 ReleaseStr(pFree->wzNamespace);
643 ReleaseStr(pFree->wzAttribute);
644 ReleaseStr(pFree->wzValue);
645 MemFree(pFree);
646 }
647}