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