aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/atomutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dutil/atomutil.cpp')
-rw-r--r--src/dutil/atomutil.cpp1284
1 files changed, 1284 insertions, 0 deletions
diff --git a/src/dutil/atomutil.cpp b/src/dutil/atomutil.cpp
new file mode 100644
index 00000000..4a12fb80
--- /dev/null
+++ b/src/dutil/atomutil.cpp
@@ -0,0 +1,1284 @@
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
6static HRESULT ParseAtomDocument(
7 __in IXMLDOMDocument *pixd,
8 __out ATOM_FEED **ppFeed
9 );
10static HRESULT ParseAtomFeed(
11 __in IXMLDOMNode *pixnFeed,
12 __out ATOM_FEED **ppFeed
13 );
14static HRESULT ParseAtomAuthor(
15 __in IXMLDOMNode* pixnAuthor,
16 __in ATOM_AUTHOR* pAuthor
17 );
18static HRESULT ParseAtomCategory(
19 __in IXMLDOMNode* pixnCategory,
20 __in ATOM_CATEGORY* pCategory
21 );
22static HRESULT ParseAtomEntry(
23 __in IXMLDOMNode* pixnEntry,
24 __in ATOM_ENTRY* pEntry
25 );
26static HRESULT ParseAtomLink(
27 __in IXMLDOMNode* pixnLink,
28 __in ATOM_LINK* pLink
29 );
30static HRESULT ParseAtomUnknownElement(
31 __in IXMLDOMNode *pNode,
32 __inout ATOM_UNKNOWN_ELEMENT** ppUnknownElement
33 );
34static HRESULT ParseAtomUnknownAttribute(
35 __in IXMLDOMNode *pNode,
36 __inout ATOM_UNKNOWN_ATTRIBUTE** ppUnknownAttribute
37 );
38static HRESULT AssignDateTime(
39 __in FILETIME* pft,
40 __in IXMLDOMNode* pNode
41 );
42static HRESULT AssignString(
43 __out_z LPWSTR* pwzValue,
44 __in IXMLDOMNode* pNode
45 );
46static void FreeAtomAuthor(
47 __in_opt ATOM_AUTHOR* pAuthor
48 );
49static void FreeAtomContent(
50 __in_opt ATOM_CONTENT* pContent
51 );
52static void FreeAtomCategory(
53 __in_opt ATOM_CATEGORY* pCategory
54 );
55static void FreeAtomEntry(
56 __in_opt ATOM_ENTRY* pEntry
57 );
58static void FreeAtomLink(
59 __in_opt ATOM_LINK* pLink
60 );
61static void FreeAtomUnknownElementList(
62 __in_opt ATOM_UNKNOWN_ELEMENT* pUnknownElement
63 );
64static void FreeAtomUnknownAttributeList(
65 __in_opt ATOM_UNKNOWN_ATTRIBUTE* pUnknownAttribute
66 );
67
68template<class T> static HRESULT AllocateAtomType(
69 __in IXMLDOMNode* pixnParent,
70 __in LPCWSTR wzT,
71 __out T** pprgT,
72 __out DWORD* pcT
73 );
74
75
76/********************************************************************
77 AtomInitialize - Initialize ATOM utilities.
78
79*********************************************************************/
80extern "C" HRESULT DAPI AtomInitialize()
81{
82 return XmlInitialize();
83}
84
85
86/********************************************************************
87 AtomUninitialize - Uninitialize ATOM utilities.
88
89*********************************************************************/
90extern "C" void DAPI AtomUninitialize()
91{
92 XmlUninitialize();
93}
94
95
96/********************************************************************
97 AtomParseFromString - parses out an ATOM feed from a string.
98
99*********************************************************************/
100extern "C" HRESULT DAPI AtomParseFromString(
101 __in LPCWSTR wzAtomString,
102 __out ATOM_FEED **ppFeed
103 )
104{
105 Assert(wzAtomString);
106 Assert(ppFeed);
107
108 HRESULT hr = S_OK;
109 ATOM_FEED *pNewFeed = NULL;
110 IXMLDOMDocument *pixdAtom = NULL;
111
112 hr = XmlLoadDocument(wzAtomString, &pixdAtom);
113 ExitOnFailure(hr, "Failed to load ATOM string as XML document.");
114
115 hr = ParseAtomDocument(pixdAtom, &pNewFeed);
116 ExitOnFailure(hr, "Failed to parse ATOM document.");
117
118 *ppFeed = pNewFeed;
119 pNewFeed = NULL;
120
121LExit:
122 ReleaseAtomFeed(pNewFeed);
123 ReleaseObject(pixdAtom);
124
125 return hr;
126}
127
128
129/********************************************************************
130 AtomParseFromFile - parses out an ATOM feed from a file path.
131
132*********************************************************************/
133extern "C" HRESULT DAPI AtomParseFromFile(
134 __in LPCWSTR wzAtomFile,
135 __out ATOM_FEED **ppFeed
136 )
137{
138 Assert(wzAtomFile);
139 Assert(ppFeed);
140
141 HRESULT hr = S_OK;
142 ATOM_FEED *pNewFeed = NULL;
143 IXMLDOMDocument *pixdAtom = NULL;
144
145 hr = XmlLoadDocumentFromFile(wzAtomFile, &pixdAtom);
146 ExitOnFailure(hr, "Failed to load ATOM string as XML document.");
147
148 hr = ParseAtomDocument(pixdAtom, &pNewFeed);
149 ExitOnFailure(hr, "Failed to parse ATOM document.");
150
151 *ppFeed = pNewFeed;
152 pNewFeed = NULL;
153
154LExit:
155 ReleaseAtomFeed(pNewFeed);
156 ReleaseObject(pixdAtom);
157
158 return hr;
159}
160
161
162/********************************************************************
163 AtomParseFromDocument - parses out an ATOM feed from an XML document.
164
165*********************************************************************/
166extern "C" HRESULT DAPI AtomParseFromDocument(
167 __in IXMLDOMDocument* pixdDocument,
168 __out ATOM_FEED **ppFeed
169 )
170{
171 Assert(pixdDocument);
172 Assert(ppFeed);
173
174 HRESULT hr = S_OK;
175 ATOM_FEED *pNewFeed = NULL;
176
177 hr = ParseAtomDocument(pixdDocument, &pNewFeed);
178 ExitOnFailure(hr, "Failed to parse ATOM document.");
179
180 *ppFeed = pNewFeed;
181 pNewFeed = NULL;
182
183LExit:
184 ReleaseAtomFeed(pNewFeed);
185
186 return hr;
187}
188
189
190/********************************************************************
191 AtomFreeFeed - parses out an ATOM feed from a string.
192
193*********************************************************************/
194extern "C" void DAPI AtomFreeFeed(
195 __in_xcount(pFeed->cItems) ATOM_FEED *pFeed
196 )
197{
198 if (pFeed)
199 {
200 FreeAtomUnknownElementList(pFeed->pUnknownElements);
201 ReleaseObject(pFeed->pixn);
202
203 for (DWORD i = 0; i < pFeed->cLinks; ++i)
204 {
205 FreeAtomLink(pFeed->rgLinks + i);
206 }
207 ReleaseMem(pFeed->rgLinks);
208
209 for (DWORD i = 0; i < pFeed->cEntries; ++i)
210 {
211 FreeAtomEntry(pFeed->rgEntries + i);
212 }
213 ReleaseMem(pFeed->rgEntries);
214
215 for (DWORD i = 0; i < pFeed->cCategories; ++i)
216 {
217 FreeAtomCategory(pFeed->rgCategories + i);
218 }
219 ReleaseMem(pFeed->rgCategories);
220
221 for (DWORD i = 0; i < pFeed->cAuthors; ++i)
222 {
223 FreeAtomAuthor(pFeed->rgAuthors + i);
224 }
225 ReleaseMem(pFeed->rgAuthors);
226
227 ReleaseStr(pFeed->wzGenerator);
228 ReleaseStr(pFeed->wzIcon);
229 ReleaseStr(pFeed->wzId);
230 ReleaseStr(pFeed->wzLogo);
231 ReleaseStr(pFeed->wzSubtitle);
232 ReleaseStr(pFeed->wzTitle);
233
234 MemFree(pFeed);
235 }
236}
237
238
239/********************************************************************
240 ParseAtomDocument - parses out an ATOM feed from a loaded XML DOM document.
241
242*********************************************************************/
243static HRESULT ParseAtomDocument(
244 __in IXMLDOMDocument *pixd,
245 __out ATOM_FEED **ppFeed
246 )
247{
248 Assert(pixd);
249 Assert(ppFeed);
250
251 HRESULT hr = S_OK;
252 IXMLDOMElement *pFeedElement = NULL;
253
254 ATOM_FEED *pNewFeed = NULL;
255
256 //
257 // Get the document element and start processing feeds.
258 //
259 hr = pixd->get_documentElement(&pFeedElement);
260 ExitOnFailure(hr, "failed get_documentElement in ParseAtomDocument");
261
262 hr = ParseAtomFeed(pFeedElement, &pNewFeed);
263 ExitOnFailure(hr, "Failed to parse ATOM feed.");
264
265 if (S_FALSE == hr)
266 {
267 hr = S_OK;
268 }
269
270 *ppFeed = pNewFeed;
271 pNewFeed = NULL;
272
273LExit:
274 ReleaseObject(pFeedElement);
275
276 ReleaseAtomFeed(pNewFeed);
277
278 return hr;
279}
280
281
282/********************************************************************
283 ParseAtomFeed - parses out an ATOM feed from a loaded XML DOM element.
284
285*********************************************************************/
286static HRESULT ParseAtomFeed(
287 __in IXMLDOMNode *pixnFeed,
288 __out ATOM_FEED **ppFeed
289 )
290{
291 Assert(pixnFeed);
292 Assert(ppFeed);
293
294 HRESULT hr = S_OK;
295 IXMLDOMNodeList *pNodeList = NULL;
296
297 ATOM_FEED *pNewFeed = NULL;
298 DWORD cAuthors = 0;
299 DWORD cCategories = 0;
300 DWORD cEntries = 0;
301 DWORD cLinks = 0;
302
303 IXMLDOMNode *pNode = NULL;
304 BSTR bstrNodeName = NULL;
305
306 // First, allocate the new feed and all the possible sub elements.
307 pNewFeed = (ATOM_FEED*)MemAlloc(sizeof(ATOM_FEED), TRUE);
308 ExitOnNull(pNewFeed, hr, E_OUTOFMEMORY, "Failed to allocate ATOM feed structure.");
309
310 pNewFeed->pixn = pixnFeed;
311 pNewFeed->pixn->AddRef();
312
313 hr = AllocateAtomType<ATOM_AUTHOR>(pixnFeed, L"author", &pNewFeed->rgAuthors, &pNewFeed->cAuthors);
314 ExitOnFailure(hr, "Failed to allocate ATOM feed authors.");
315
316 hr = AllocateAtomType<ATOM_CATEGORY>(pixnFeed, L"category", &pNewFeed->rgCategories, &pNewFeed->cCategories);
317 ExitOnFailure(hr, "Failed to allocate ATOM feed categories.");
318
319 hr = AllocateAtomType<ATOM_ENTRY>(pixnFeed, L"entry", &pNewFeed->rgEntries, &pNewFeed->cEntries);
320 ExitOnFailure(hr, "Failed to allocate ATOM feed entries.");
321
322 hr = AllocateAtomType<ATOM_LINK>(pixnFeed, L"link", &pNewFeed->rgLinks, &pNewFeed->cLinks);
323 ExitOnFailure(hr, "Failed to allocate ATOM feed links.");
324
325 // Second, process the elements under a feed.
326 hr = pixnFeed->get_childNodes(&pNodeList);
327 ExitOnFailure(hr, "Failed to get child nodes of ATOM feed element.");
328
329 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName)))
330 {
331 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"generator", -1))
332 {
333 hr = AssignString(&pNewFeed->wzGenerator, pNode);
334 ExitOnFailure(hr, "Failed to allocate ATOM feed generator.");
335 }
336 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"icon", -1))
337 {
338 hr = AssignString(&pNewFeed->wzIcon, pNode);
339 ExitOnFailure(hr, "Failed to allocate ATOM feed icon.");
340 }
341 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"id", -1))
342 {
343 hr = AssignString(&pNewFeed->wzId, pNode);
344 ExitOnFailure(hr, "Failed to allocate ATOM feed id.");
345 }
346 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"logo", -1))
347 {
348 hr = AssignString(&pNewFeed->wzLogo, pNode);
349 ExitOnFailure(hr, "Failed to allocate ATOM feed logo.");
350 }
351 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"subtitle", -1))
352 {
353 hr = AssignString(&pNewFeed->wzSubtitle, pNode);
354 ExitOnFailure(hr, "Failed to allocate ATOM feed subtitle.");
355 }
356 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"title", -1))
357 {
358 hr = AssignString(&pNewFeed->wzTitle, pNode);
359 ExitOnFailure(hr, "Failed to allocate ATOM feed title.");
360 }
361 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"updated", -1))
362 {
363 hr = AssignDateTime(&pNewFeed->ftUpdated, pNode);
364 ExitOnFailure(hr, "Failed to allocate ATOM feed updated.");
365 }
366 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"author", -1))
367 {
368 hr = ParseAtomAuthor(pNode, &pNewFeed->rgAuthors[cAuthors]);
369 ExitOnFailure(hr, "Failed to parse ATOM author.");
370
371 ++cAuthors;
372 }
373 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"category", -1))
374 {
375 hr = ParseAtomCategory(pNode, &pNewFeed->rgCategories[cCategories]);
376 ExitOnFailure(hr, "Failed to parse ATOM category.");
377
378 ++cCategories;
379 }
380 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"entry", -1))
381 {
382 hr = ParseAtomEntry(pNode, &pNewFeed->rgEntries[cEntries]);
383 ExitOnFailure(hr, "Failed to parse ATOM entry.");
384
385 ++cEntries;
386 }
387 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"link", -1))
388 {
389 hr = ParseAtomLink(pNode, &pNewFeed->rgLinks[cLinks]);
390 ExitOnFailure(hr, "Failed to parse ATOM link.");
391
392 ++cLinks;
393 }
394 else
395 {
396 hr = ParseAtomUnknownElement(pNode, &pNewFeed->pUnknownElements);
397 ExitOnFailure(hr, "Failed to parse unknown ATOM feed element: %ls", bstrNodeName);
398 }
399
400 ReleaseNullBSTR(bstrNodeName);
401 ReleaseNullObject(pNode);
402 }
403
404 if (!pNewFeed->wzId || !*pNewFeed->wzId)
405 {
406 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
407 ExitOnRootFailure(hr, "Failed to find required feed/id element.");
408 }
409 else if (!pNewFeed->wzTitle || !*pNewFeed->wzTitle)
410 {
411 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
412 ExitOnRootFailure(hr, "Failed to find required feed/title element.");
413 }
414 else if (0 == pNewFeed->ftUpdated.dwHighDateTime && 0 == pNewFeed->ftUpdated.dwLowDateTime)
415 {
416 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
417 ExitOnRootFailure(hr, "Failed to find required feed/updated element.");
418 }
419
420 *ppFeed = pNewFeed;
421 pNewFeed = NULL;
422
423LExit:
424 ReleaseBSTR(bstrNodeName);
425 ReleaseObject(pNode);
426 ReleaseObject(pNodeList);
427
428 ReleaseAtomFeed(pNewFeed);
429
430 return hr;
431}
432
433
434/********************************************************************
435 AllocateAtomType - allocates enough space for all of the ATOM elements
436 of a particular type under a particular node.
437
438*********************************************************************/
439template<class T> static HRESULT AllocateAtomType(
440 __in IXMLDOMNode* pixnParent,
441 __in LPCWSTR wzT,
442 __out T** pprgT,
443 __out DWORD* pcT
444 )
445{
446 HRESULT hr = S_OK;
447 IXMLDOMNodeList *pNodeList = NULL;
448
449 long cT = 0;
450 T* prgT = NULL;
451
452 hr = XmlSelectNodes(pixnParent, wzT, &pNodeList);
453 ExitOnFailure(hr, "Failed to select all ATOM %ls.", wzT);
454
455 if (S_OK == hr)
456 {
457 hr = pNodeList->get_length(&cT);
458 ExitOnFailure(hr, "Failed to count the number of ATOM %ls.", wzT);
459
460 if (cT == 0)
461 {
462 ExitFunction();
463 }
464
465 prgT = static_cast<T*>(MemAlloc(sizeof(T) * cT, TRUE));
466 ExitOnNull(prgT, hr, E_OUTOFMEMORY, "Failed to allocate ATOM.");
467
468 *pcT = cT;
469 *pprgT = prgT;
470 prgT = NULL;
471 }
472 else
473 {
474 *pprgT = NULL;
475 *pcT = 0;
476 }
477
478LExit:
479 ReleaseMem(prgT);
480 ReleaseObject(pNodeList);
481
482 return hr;
483}
484
485
486/********************************************************************
487 ParseAtomAuthor - parses out an ATOM author from a loaded XML DOM node.
488
489*********************************************************************/
490static HRESULT ParseAtomAuthor(
491 __in IXMLDOMNode* pixnAuthor,
492 __in ATOM_AUTHOR* pAuthor
493 )
494{
495 HRESULT hr = S_OK;
496
497 IXMLDOMNodeList *pNodeList = NULL;
498 IXMLDOMNode *pNode = NULL;
499 BSTR bstrNodeName = NULL;
500
501 hr = pixnAuthor->get_childNodes(&pNodeList);
502 ExitOnFailure(hr, "Failed to get child nodes of ATOM author element.");
503
504 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName)))
505 {
506 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"name", -1))
507 {
508 hr = AssignString(&pAuthor->wzName, pNode);
509 ExitOnFailure(hr, "Failed to allocate ATOM author name.");
510 }
511 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"email", -1))
512 {
513 hr = AssignString(&pAuthor->wzEmail, pNode);
514 ExitOnFailure(hr, "Failed to allocate ATOM author email.");
515 }
516 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"uri", -1))
517 {
518 hr = AssignString(&pAuthor->wzUrl, pNode);
519 ExitOnFailure(hr, "Failed to allocate ATOM author uri.");
520 }
521
522 ReleaseNullBSTR(bstrNodeName);
523 ReleaseNullObject(pNode);
524 }
525 ExitOnFailure(hr, "Failed to process all ATOM author elements.");
526
527 hr = S_OK;
528
529LExit:
530 ReleaseBSTR(bstrNodeName);
531 ReleaseObject(pNode);
532 ReleaseObject(pNodeList);
533
534 return hr;
535}
536
537
538/********************************************************************
539 ParseAtomCategory - parses out an ATOM category from a loaded XML DOM node.
540
541*********************************************************************/
542static HRESULT ParseAtomCategory(
543 __in IXMLDOMNode* pixnCategory,
544 __in ATOM_CATEGORY* pCategory
545 )
546{
547 HRESULT hr = S_OK;
548
549 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
550 IXMLDOMNodeList *pNodeList = NULL;
551 IXMLDOMNode *pNode = NULL;
552 BSTR bstrNodeName = NULL;
553
554 // Process attributes first.
555 hr = pixnCategory->get_attributes(&pixnnmAttributes);
556 ExitOnFailure(hr, "Failed get attributes on ATOM unknown element.");
557
558 while (S_OK == (hr = XmlNextAttribute(pixnnmAttributes, &pNode, &bstrNodeName)))
559 {
560 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"label", -1))
561 {
562 hr = AssignString(&pCategory->wzLabel, pNode);
563 ExitOnFailure(hr, "Failed to allocate ATOM category label.");
564 }
565 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"scheme", -1))
566 {
567 hr = AssignString(&pCategory->wzScheme, pNode);
568 ExitOnFailure(hr, "Failed to allocate ATOM category scheme.");
569 }
570 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"term", -1))
571 {
572 hr = AssignString(&pCategory->wzTerm, pNode);
573 ExitOnFailure(hr, "Failed to allocate ATOM category term.");
574 }
575
576 ReleaseNullBSTR(bstrNodeName);
577 ReleaseNullObject(pNode);
578 }
579 ExitOnFailure(hr, "Failed to process all ATOM category attributes.");
580
581 // Process elements second.
582 hr = pixnCategory->get_childNodes(&pNodeList);
583 ExitOnFailure(hr, "Failed to get child nodes of ATOM category element.");
584
585 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName)))
586 {
587 hr = ParseAtomUnknownElement(pNode, &pCategory->pUnknownElements);
588 ExitOnFailure(hr, "Failed to parse unknown ATOM category element: %ls", bstrNodeName);
589
590 ReleaseNullBSTR(bstrNodeName);
591 ReleaseNullObject(pNode);
592 }
593 ExitOnFailure(hr, "Failed to process all ATOM category elements.");
594
595 hr = S_OK;
596
597LExit:
598 ReleaseBSTR(bstrNodeName);
599 ReleaseObject(pNode);
600 ReleaseObject(pNodeList);
601 ReleaseObject(pixnnmAttributes);
602
603 return hr;
604}
605
606
607/********************************************************************
608 ParseAtomContent - parses out an ATOM content from a loaded XML DOM node.
609
610*********************************************************************/
611static HRESULT ParseAtomContent(
612 __in IXMLDOMNode* pixnContent,
613 __in ATOM_CONTENT* pContent
614 )
615{
616 HRESULT hr = S_OK;
617
618 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
619 IXMLDOMNodeList *pNodeList = NULL;
620 IXMLDOMNode *pNode = NULL;
621 BSTR bstrNodeName = NULL;
622
623 // Process attributes first.
624 hr = pixnContent->get_attributes(&pixnnmAttributes);
625 ExitOnFailure(hr, "Failed get attributes on ATOM unknown element.");
626
627 while (S_OK == (hr = XmlNextAttribute(pixnnmAttributes, &pNode, &bstrNodeName)))
628 {
629 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"type", -1))
630 {
631 hr = AssignString(&pContent->wzType, pNode);
632 ExitOnFailure(hr, "Failed to allocate ATOM content type.");
633 }
634 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"url", -1))
635 {
636 hr = AssignString(&pContent->wzUrl, pNode);
637 ExitOnFailure(hr, "Failed to allocate ATOM content scheme.");
638 }
639
640 ReleaseNullBSTR(bstrNodeName);
641 ReleaseNullObject(pNode);
642 }
643 ExitOnFailure(hr, "Failed to process all ATOM content attributes.");
644
645 // Process elements second.
646 hr = pixnContent->get_childNodes(&pNodeList);
647 ExitOnFailure(hr, "Failed to get child nodes of ATOM content element.");
648
649 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName)))
650 {
651 hr = ParseAtomUnknownElement(pNode, &pContent->pUnknownElements);
652 ExitOnFailure(hr, "Failed to parse unknown ATOM content element: %ls", bstrNodeName);
653
654 ReleaseNullBSTR(bstrNodeName);
655 ReleaseNullObject(pNode);
656 }
657 ExitOnFailure(hr, "Failed to process all ATOM content elements.");
658
659 hr = AssignString(&pContent->wzValue, pixnContent);
660 ExitOnFailure(hr, "Failed to allocate ATOM content value.");
661
662LExit:
663 ReleaseBSTR(bstrNodeName);
664 ReleaseObject(pNode);
665 ReleaseObject(pNodeList);
666 ReleaseObject(pixnnmAttributes);
667
668 return hr;
669}
670
671
672/********************************************************************
673 ParseAtomEntry - parses out an ATOM entry from a loaded XML DOM node.
674
675*********************************************************************/
676static HRESULT ParseAtomEntry(
677 __in IXMLDOMNode* pixnEntry,
678 __in ATOM_ENTRY* pEntry
679 )
680{
681 HRESULT hr = S_OK;
682
683 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
684 IXMLDOMNodeList *pNodeList = NULL;
685 IXMLDOMNode *pNode = NULL;
686 BSTR bstrNodeName = NULL;
687
688 DWORD cAuthors = 0;
689 DWORD cCategories = 0;
690 DWORD cLinks = 0;
691
692 pEntry->pixn = pixnEntry;
693 pEntry->pixn->AddRef();
694
695 // First, allocate all the possible sub elements.
696 hr = AllocateAtomType<ATOM_AUTHOR>(pixnEntry, L"author", &pEntry->rgAuthors, &pEntry->cAuthors);
697 ExitOnFailure(hr, "Failed to allocate ATOM entry authors.");
698
699 hr = AllocateAtomType<ATOM_CATEGORY>(pixnEntry, L"category", &pEntry->rgCategories, &pEntry->cCategories);
700 ExitOnFailure(hr, "Failed to allocate ATOM entry categories.");
701
702 hr = AllocateAtomType<ATOM_LINK>(pixnEntry, L"link", &pEntry->rgLinks, &pEntry->cLinks);
703 ExitOnFailure(hr, "Failed to allocate ATOM entry links.");
704
705 // Second, process elements.
706 hr = pixnEntry->get_childNodes(&pNodeList);
707 ExitOnFailure(hr, "Failed to get child nodes of ATOM entry element.");
708
709 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName)))
710 {
711 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"id", -1))
712 {
713 hr = AssignString(&pEntry->wzId, pNode);
714 ExitOnFailure(hr, "Failed to allocate ATOM entry id.");
715 }
716 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"summary", -1))
717 {
718 hr = AssignString(&pEntry->wzSummary, pNode);
719 ExitOnFailure(hr, "Failed to allocate ATOM entry summary.");
720 }
721 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"title", -1))
722 {
723 hr = AssignString(&pEntry->wzTitle, pNode);
724 ExitOnFailure(hr, "Failed to allocate ATOM entry title.");
725 }
726 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"published", -1))
727 {
728 hr = AssignDateTime(&pEntry->ftPublished, pNode);
729 ExitOnFailure(hr, "Failed to allocate ATOM entry published.");
730 }
731 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"updated", -1))
732 {
733 hr = AssignDateTime(&pEntry->ftUpdated, pNode);
734 ExitOnFailure(hr, "Failed to allocate ATOM entry updated.");
735 }
736 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"author", -1))
737 {
738 hr = ParseAtomAuthor(pNode, &pEntry->rgAuthors[cAuthors]);
739 ExitOnFailure(hr, "Failed to parse ATOM entry author.");
740
741 ++cAuthors;
742 }
743 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"category", -1))
744 {
745 hr = ParseAtomCategory(pNode, &pEntry->rgCategories[cCategories]);
746 ExitOnFailure(hr, "Failed to parse ATOM entry category.");
747
748 ++cCategories;
749 }
750 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"content", -1))
751 {
752 if (NULL != pEntry->pContent)
753 {
754 hr = E_UNEXPECTED;
755 ExitOnFailure(hr, "Cannot have two content elements in ATOM entry.");
756 }
757
758 pEntry->pContent = static_cast<ATOM_CONTENT*>(MemAlloc(sizeof(ATOM_CONTENT), TRUE));
759 ExitOnNull(pEntry->pContent, hr, E_OUTOFMEMORY, "Failed to allocate ATOM entry content.");
760
761 hr = ParseAtomContent(pNode, pEntry->pContent);
762 ExitOnFailure(hr, "Failed to parse ATOM entry content.");
763 }
764 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"link", -1))
765 {
766 hr = ParseAtomLink(pNode, &pEntry->rgLinks[cLinks]);
767 ExitOnFailure(hr, "Failed to parse ATOM entry link.");
768
769 ++cLinks;
770 }
771 else
772 {
773 hr = ParseAtomUnknownElement(pNode, &pEntry->pUnknownElements);
774 ExitOnFailure(hr, "Failed to parse unknown ATOM entry element: %ls", bstrNodeName);
775 }
776
777 ReleaseNullBSTR(bstrNodeName);
778 ReleaseNullObject(pNode);
779 }
780 ExitOnFailure(hr, "Failed to process all ATOM entry elements.");
781
782 if (!pEntry->wzId || !*pEntry->wzId)
783 {
784 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
785 ExitOnRootFailure(hr, "Failed to find required feed/entry/id element.");
786 }
787 else if (!pEntry->wzTitle || !*pEntry->wzTitle)
788 {
789 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
790 ExitOnRootFailure(hr, "Failed to find required feed/entry/title element.");
791 }
792 else if (0 == pEntry->ftUpdated.dwHighDateTime && 0 == pEntry->ftUpdated.dwLowDateTime)
793 {
794 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
795 ExitOnRootFailure(hr, "Failed to find required feed/entry/updated element.");
796 }
797
798 hr = S_OK;
799
800LExit:
801 ReleaseBSTR(bstrNodeName);
802 ReleaseObject(pNode);
803 ReleaseObject(pNodeList);
804 ReleaseObject(pixnnmAttributes);
805
806 return hr;
807}
808
809
810/********************************************************************
811 ParseAtomLink - parses out an ATOM link from a loaded XML DOM node.
812
813*********************************************************************/
814static HRESULT ParseAtomLink(
815 __in IXMLDOMNode* pixnLink,
816 __in ATOM_LINK* pLink
817 )
818{
819 HRESULT hr = S_OK;
820
821 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
822 IXMLDOMNodeList *pNodeList = NULL;
823 IXMLDOMNode *pNode = NULL;
824 BSTR bstrNodeName = NULL;
825
826 // Process attributes first.
827 hr = pixnLink->get_attributes(&pixnnmAttributes);
828 ExitOnFailure(hr, "Failed get attributes for ATOM link.");
829
830 while (S_OK == (hr = XmlNextAttribute(pixnnmAttributes, &pNode, &bstrNodeName)))
831 {
832 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"rel", -1))
833 {
834 hr = AssignString(&pLink->wzRel, pNode);
835 ExitOnFailure(hr, "Failed to allocate ATOM link rel.");
836 }
837 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"href", -1))
838 {
839 hr = AssignString(&pLink->wzUrl, pNode);
840 ExitOnFailure(hr, "Failed to allocate ATOM link href.");
841 }
842 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"length", -1))
843 {
844 hr = XmlGetAttributeLargeNumber(pixnLink, bstrNodeName, &pLink->dw64Length);
845 if (E_INVALIDARG == hr)
846 {
847 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
848 }
849 ExitOnFailure(hr, "Failed to parse ATOM link length.");
850 }
851 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"title", -1))
852 {
853 hr = AssignString(&pLink->wzTitle, pNode);
854 ExitOnFailure(hr, "Failed to allocate ATOM link title.");
855 }
856 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, bstrNodeName, -1, L"type", -1))
857 {
858 hr = AssignString(&pLink->wzType, pNode);
859 ExitOnFailure(hr, "Failed to allocate ATOM link type.");
860 }
861 else
862 {
863 hr = ParseAtomUnknownAttribute(pNode, &pLink->pUnknownAttributes);
864 ExitOnFailure(hr, "Failed to parse unknown ATOM link attribute: %ls", bstrNodeName);
865 }
866
867 ReleaseNullBSTR(bstrNodeName);
868 ReleaseNullObject(pNode);
869 }
870 ExitOnFailure(hr, "Failed to process all ATOM link attributes.");
871
872 // Process elements second.
873 hr = pixnLink->get_childNodes(&pNodeList);
874 ExitOnFailure(hr, "Failed to get child nodes of ATOM link element.");
875
876 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName)))
877 {
878 hr = ParseAtomUnknownElement(pNode, &pLink->pUnknownElements);
879 ExitOnFailure(hr, "Failed to parse unknown ATOM link element: %ls", bstrNodeName);
880
881 ReleaseNullBSTR(bstrNodeName);
882 ReleaseNullObject(pNode);
883 }
884 ExitOnFailure(hr, "Failed to process all ATOM link elements.");
885
886 hr = AssignString(&pLink->wzValue, pixnLink);
887 ExitOnFailure(hr, "Failed to allocate ATOM link value.");
888
889LExit:
890 ReleaseBSTR(bstrNodeName);
891 ReleaseObject(pNode);
892 ReleaseObject(pNodeList);
893 ReleaseObject(pixnnmAttributes);
894
895 return hr;
896}
897
898
899/********************************************************************
900 ParseAtomUnknownElement - parses out an unknown item from the ATOM feed from a loaded XML DOM node.
901
902*********************************************************************/
903static HRESULT ParseAtomUnknownElement(
904 __in IXMLDOMNode *pNode,
905 __inout ATOM_UNKNOWN_ELEMENT** ppUnknownElement
906 )
907{
908 Assert(ppUnknownElement);
909
910 HRESULT hr = S_OK;
911 BSTR bstrNodeNamespace = NULL;
912 BSTR bstrNodeName = NULL;
913 BSTR bstrNodeValue = NULL;
914 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
915 IXMLDOMNode* pixnAttribute = NULL;
916 ATOM_UNKNOWN_ELEMENT* pNewUnknownElement;
917
918 pNewUnknownElement = (ATOM_UNKNOWN_ELEMENT*)MemAlloc(sizeof(ATOM_UNKNOWN_ELEMENT), TRUE);
919 ExitOnNull(pNewUnknownElement, hr, E_OUTOFMEMORY, "Failed to allocate unknown element.");
920
921 hr = pNode->get_namespaceURI(&bstrNodeNamespace);
922 if (S_OK == hr)
923 {
924 hr = StrAllocString(&pNewUnknownElement->wzNamespace, bstrNodeNamespace, 0);
925 ExitOnFailure(hr, "Failed to allocate ATOM unknown element namespace.");
926 }
927 else if (S_FALSE == hr)
928 {
929 hr = S_OK;
930 }
931 ExitOnFailure(hr, "Failed to get unknown element namespace.");
932
933 hr = pNode->get_baseName(&bstrNodeName);
934 ExitOnFailure(hr, "Failed to get unknown element name.");
935
936 hr = StrAllocString(&pNewUnknownElement->wzElement, bstrNodeName, 0);
937 ExitOnFailure(hr, "Failed to allocate ATOM unknown element name.");
938
939 hr = XmlGetText(pNode, &bstrNodeValue);
940 ExitOnFailure(hr, "Failed to get unknown element value.");
941
942 hr = StrAllocString(&pNewUnknownElement->wzValue, bstrNodeValue, 0);
943 ExitOnFailure(hr, "Failed to allocate ATOM unknown element value.");
944
945 hr = pNode->get_attributes(&pixnnmAttributes);
946 ExitOnFailure(hr, "Failed get attributes on ATOM unknown element.");
947
948 while (S_OK == (hr = pixnnmAttributes->nextNode(&pixnAttribute)))
949 {
950 hr = ParseAtomUnknownAttribute(pixnAttribute, &pNewUnknownElement->pAttributes);
951 ExitOnFailure(hr, "Failed to parse attribute on ATOM unknown element.");
952
953 ReleaseNullObject(pixnAttribute);
954 }
955
956 if (S_FALSE == hr)
957 {
958 hr = S_OK;
959 }
960 ExitOnFailure(hr, "Failed to enumerate all attributes on ATOM unknown element.");
961
962 ATOM_UNKNOWN_ELEMENT** ppTail = ppUnknownElement;
963 while (*ppTail)
964 {
965 ppTail = &(*ppTail)->pNext;
966 }
967
968 *ppTail = pNewUnknownElement;
969 pNewUnknownElement = NULL;
970
971LExit:
972 FreeAtomUnknownElementList(pNewUnknownElement);
973
974 ReleaseBSTR(bstrNodeNamespace);
975 ReleaseBSTR(bstrNodeName);
976 ReleaseBSTR(bstrNodeValue);
977 ReleaseObject(pixnnmAttributes);
978 ReleaseObject(pixnAttribute);
979
980 return hr;
981}
982
983
984/********************************************************************
985 ParseAtomUnknownAttribute - parses out attribute from an unknown element
986
987*********************************************************************/
988static HRESULT ParseAtomUnknownAttribute(
989 __in IXMLDOMNode *pNode,
990 __inout ATOM_UNKNOWN_ATTRIBUTE** ppUnknownAttribute
991 )
992{
993 Assert(ppUnknownAttribute);
994
995 HRESULT hr = S_OK;
996 BSTR bstrNodeNamespace = NULL;
997 BSTR bstrNodeName = NULL;
998 BSTR bstrNodeValue = NULL;
999 ATOM_UNKNOWN_ATTRIBUTE* pNewUnknownAttribute;
1000
1001 pNewUnknownAttribute = (ATOM_UNKNOWN_ATTRIBUTE*)MemAlloc(sizeof(ATOM_UNKNOWN_ATTRIBUTE), TRUE);
1002 ExitOnNull(pNewUnknownAttribute, hr, E_OUTOFMEMORY, "Failed to allocate unknown attribute.");
1003
1004 hr = pNode->get_namespaceURI(&bstrNodeNamespace);
1005 if (S_OK == hr)
1006 {
1007 hr = StrAllocString(&pNewUnknownAttribute->wzNamespace, bstrNodeNamespace, 0);
1008 ExitOnFailure(hr, "Failed to allocate ATOM unknown attribute namespace.");
1009 }
1010 else if (S_FALSE == hr)
1011 {
1012 hr = S_OK;
1013 }
1014 ExitOnFailure(hr, "Failed to get unknown attribute namespace.");
1015
1016 hr = pNode->get_baseName(&bstrNodeName);
1017 ExitOnFailure(hr, "Failed to get unknown attribute name.");
1018
1019 hr = StrAllocString(&pNewUnknownAttribute->wzAttribute, bstrNodeName, 0);
1020 ExitOnFailure(hr, "Failed to allocate ATOM unknown attribute name.");
1021
1022 hr = XmlGetText(pNode, &bstrNodeValue);
1023 ExitOnFailure(hr, "Failed to get unknown attribute value.");
1024
1025 hr = StrAllocString(&pNewUnknownAttribute->wzValue, bstrNodeValue, 0);
1026 ExitOnFailure(hr, "Failed to allocate ATOM unknown attribute value.");
1027
1028 ATOM_UNKNOWN_ATTRIBUTE** ppTail = ppUnknownAttribute;
1029 while (*ppTail)
1030 {
1031 ppTail = &(*ppTail)->pNext;
1032 }
1033
1034 *ppTail = pNewUnknownAttribute;
1035 pNewUnknownAttribute = NULL;
1036
1037LExit:
1038 FreeAtomUnknownAttributeList(pNewUnknownAttribute);
1039
1040 ReleaseBSTR(bstrNodeNamespace);
1041 ReleaseBSTR(bstrNodeName);
1042 ReleaseBSTR(bstrNodeValue);
1043
1044 return hr;
1045}
1046
1047
1048/********************************************************************
1049 AssignDateTime - assigns the value of a node to a FILETIME struct.
1050
1051*********************************************************************/
1052static HRESULT AssignDateTime(
1053 __in FILETIME* pft,
1054 __in IXMLDOMNode* pNode
1055 )
1056{
1057 HRESULT hr = S_OK;
1058 BSTR bstrValue = NULL;
1059
1060 if (0 != pft->dwHighDateTime || 0 != pft->dwLowDateTime)
1061 {
1062 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
1063 ExitOnRootFailure(hr, "Already process this datetime value.");
1064 }
1065
1066 hr = XmlGetText(pNode, &bstrValue);
1067 ExitOnFailure(hr, "Failed to get value.");
1068
1069 if (S_OK == hr)
1070 {
1071 hr = TimeFromString3339(bstrValue, pft);
1072 ExitOnFailure(hr, "Failed to convert value to time.");
1073 }
1074 else
1075 {
1076 ZeroMemory(pft, sizeof(FILETIME));
1077 hr = S_OK;
1078 }
1079
1080LExit:
1081 ReleaseBSTR(bstrValue);
1082
1083 return hr;
1084}
1085
1086
1087/********************************************************************
1088 AssignString - assigns the value of a node to a dynamic string.
1089
1090*********************************************************************/
1091static HRESULT AssignString(
1092 __out_z LPWSTR* pwzValue,
1093 __in IXMLDOMNode* pNode
1094 )
1095{
1096 HRESULT hr = S_OK;
1097 BSTR bstrValue = NULL;
1098
1099 if (pwzValue && *pwzValue)
1100 {
1101 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
1102 ExitOnRootFailure(hr, "Already processed this value.");
1103 }
1104
1105 hr = XmlGetText(pNode, &bstrValue);
1106 ExitOnFailure(hr, "Failed to get value.");
1107
1108 if (S_OK == hr)
1109 {
1110 hr = StrAllocString(pwzValue, bstrValue, 0);
1111 ExitOnFailure(hr, "Failed to allocate value.");
1112 }
1113 else
1114 {
1115 ReleaseNullStr(pwzValue);
1116 hr = S_OK;
1117 }
1118
1119LExit:
1120 ReleaseBSTR(bstrValue);
1121
1122 return hr;
1123}
1124
1125
1126/********************************************************************
1127 FreeAtomAuthor - releases all of the memory used by an ATOM author.
1128
1129*********************************************************************/
1130static void FreeAtomAuthor(
1131 __in_opt ATOM_AUTHOR* pAuthor
1132 )
1133{
1134 if (pAuthor)
1135 {
1136 ReleaseStr(pAuthor->wzUrl);
1137 ReleaseStr(pAuthor->wzEmail);
1138 ReleaseStr(pAuthor->wzName);
1139 }
1140}
1141
1142
1143/********************************************************************
1144 FreeAtomCategory - releases all of the memory used by an ATOM category.
1145
1146*********************************************************************/
1147static void FreeAtomCategory(
1148 __in_opt ATOM_CATEGORY* pCategory
1149 )
1150{
1151 if (pCategory)
1152 {
1153 FreeAtomUnknownElementList(pCategory->pUnknownElements);
1154
1155 ReleaseStr(pCategory->wzTerm);
1156 ReleaseStr(pCategory->wzScheme);
1157 ReleaseStr(pCategory->wzLabel);
1158 }
1159}
1160
1161
1162/********************************************************************
1163 FreeAtomContent - releases all of the memory used by an ATOM content.
1164
1165*********************************************************************/
1166static void FreeAtomContent(
1167 __in_opt ATOM_CONTENT* pContent
1168 )
1169{
1170 if (pContent)
1171 {
1172 FreeAtomUnknownElementList(pContent->pUnknownElements);
1173
1174 ReleaseStr(pContent->wzValue);
1175 ReleaseStr(pContent->wzUrl);
1176 ReleaseStr(pContent->wzType);
1177 }
1178}
1179
1180
1181/********************************************************************
1182 FreeAtomEntry - releases all of the memory used by an ATOM entry.
1183
1184*********************************************************************/
1185static void FreeAtomEntry(
1186 __in_opt ATOM_ENTRY* pEntry
1187 )
1188{
1189 if (pEntry)
1190 {
1191 FreeAtomUnknownElementList(pEntry->pUnknownElements);
1192 ReleaseObject(pEntry->pixn);
1193
1194 for (DWORD i = 0; i < pEntry->cLinks; ++i)
1195 {
1196 FreeAtomLink(pEntry->rgLinks + i);
1197 }
1198 ReleaseMem(pEntry->rgLinks);
1199
1200 for (DWORD i = 0; i < pEntry->cCategories; ++i)
1201 {
1202 FreeAtomCategory(pEntry->rgCategories + i);
1203 }
1204 ReleaseMem(pEntry->rgCategories);
1205
1206 for (DWORD i = 0; i < pEntry->cAuthors; ++i)
1207 {
1208 FreeAtomAuthor(pEntry->rgAuthors + i);
1209 }
1210 ReleaseMem(pEntry->rgAuthors);
1211
1212 FreeAtomContent(pEntry->pContent);
1213 ReleaseMem(pEntry->pContent);
1214
1215 ReleaseStr(pEntry->wzTitle);
1216 ReleaseStr(pEntry->wzSummary);
1217 ReleaseStr(pEntry->wzId);
1218 }
1219}
1220
1221
1222/********************************************************************
1223 FreeAtomLink - releases all of the memory used by an ATOM link.
1224
1225*********************************************************************/
1226static void FreeAtomLink(
1227 __in_opt ATOM_LINK* pLink
1228 )
1229{
1230 if (pLink)
1231 {
1232 FreeAtomUnknownElementList(pLink->pUnknownElements);
1233 FreeAtomUnknownAttributeList(pLink->pUnknownAttributes);
1234
1235 ReleaseStr(pLink->wzValue);
1236 ReleaseStr(pLink->wzUrl);
1237 ReleaseStr(pLink->wzType);
1238 ReleaseStr(pLink->wzTitle);
1239 ReleaseStr(pLink->wzRel);
1240 }
1241}
1242
1243
1244/********************************************************************
1245 FreeAtomUnknownElement - releases all of the memory used by a list of unknown elements
1246
1247*********************************************************************/
1248static void FreeAtomUnknownElementList(
1249 __in_opt ATOM_UNKNOWN_ELEMENT* pUnknownElement
1250 )
1251{
1252 while (pUnknownElement)
1253 {
1254 ATOM_UNKNOWN_ELEMENT* pFree = pUnknownElement;
1255 pUnknownElement = pUnknownElement->pNext;
1256
1257 FreeAtomUnknownAttributeList(pFree->pAttributes);
1258 ReleaseStr(pFree->wzNamespace);
1259 ReleaseStr(pFree->wzElement);
1260 ReleaseStr(pFree->wzValue);
1261 MemFree(pFree);
1262 }
1263}
1264
1265
1266/********************************************************************
1267 FreeAtomUnknownAttribute - releases all of the memory used by a list of unknown attributes
1268
1269*********************************************************************/
1270static void FreeAtomUnknownAttributeList(
1271 __in_opt ATOM_UNKNOWN_ATTRIBUTE* pUnknownAttribute
1272 )
1273{
1274 while (pUnknownAttribute)
1275 {
1276 ATOM_UNKNOWN_ATTRIBUTE* pFree = pUnknownAttribute;
1277 pUnknownAttribute = pUnknownAttribute->pNext;
1278
1279 ReleaseStr(pFree->wzNamespace);
1280 ReleaseStr(pFree->wzAttribute);
1281 ReleaseStr(pFree->wzValue);
1282 MemFree(pFree);
1283 }
1284}