diff options
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/rssutil.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/rssutil.cpp | 647 |
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 | |||
20 | static HRESULT ParseRssDocument( | ||
21 | __in IXMLDOMDocument *pixd, | ||
22 | __out RSS_CHANNEL **ppChannel | ||
23 | ); | ||
24 | static HRESULT ParseRssChannel( | ||
25 | __in IXMLDOMNode *pixnChannel, | ||
26 | __out RSS_CHANNEL **ppChannel | ||
27 | ); | ||
28 | static HRESULT ParseRssItem( | ||
29 | __in IXMLDOMNode *pixnItem, | ||
30 | __in DWORD cItem, | ||
31 | __in_xcount(pChannel->cItems) RSS_CHANNEL *pChannel | ||
32 | ); | ||
33 | static HRESULT ParseRssUnknownElement( | ||
34 | __in IXMLDOMNode *pNode, | ||
35 | __inout RSS_UNKNOWN_ELEMENT** ppUnknownElement | ||
36 | ); | ||
37 | static HRESULT ParseRssUnknownAttribute( | ||
38 | __in IXMLDOMNode *pNode, | ||
39 | __inout RSS_UNKNOWN_ATTRIBUTE** ppUnknownAttribute | ||
40 | ); | ||
41 | static void FreeRssUnknownElementList( | ||
42 | __in_opt RSS_UNKNOWN_ELEMENT* pUnknownElement | ||
43 | ); | ||
44 | static void FreeRssUnknownAttributeList( | ||
45 | __in_opt RSS_UNKNOWN_ATTRIBUTE* pUnknownAttribute | ||
46 | ); | ||
47 | |||
48 | |||
49 | /******************************************************************** | ||
50 | RssInitialize - Initialize RSS utilities. | ||
51 | |||
52 | *********************************************************************/ | ||
53 | extern "C" HRESULT DAPI RssInitialize() | ||
54 | { | ||
55 | return XmlInitialize(); | ||
56 | } | ||
57 | |||
58 | |||
59 | /******************************************************************** | ||
60 | RssUninitialize - Uninitialize RSS utilities. | ||
61 | |||
62 | *********************************************************************/ | ||
63 | extern "C" void DAPI RssUninitialize() | ||
64 | { | ||
65 | XmlUninitialize(); | ||
66 | } | ||
67 | |||
68 | |||
69 | /******************************************************************** | ||
70 | RssParseFromString - parses out an RSS channel from a string. | ||
71 | |||
72 | *********************************************************************/ | ||
73 | extern "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 | |||
94 | LExit: | ||
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 | *********************************************************************/ | ||
107 | extern "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 | |||
128 | LExit: | ||
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 | *********************************************************************/ | ||
141 | extern "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 | *********************************************************************/ | ||
173 | static 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 | |||
221 | LExit: | ||
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 | *********************************************************************/ | ||
237 | static 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 | |||
331 | LExit: | ||
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 | *********************************************************************/ | ||
346 | static 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 | |||
448 | LExit: | ||
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 | *********************************************************************/ | ||
462 | static 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 | |||
530 | LExit: | ||
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 | *********************************************************************/ | ||
547 | static 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 | |||
596 | LExit: | ||
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 | *********************************************************************/ | ||
611 | static 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 | *********************************************************************/ | ||
633 | static 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 | } | ||