diff options
Diffstat (limited to 'src/dutil/atomutil.cpp')
-rw-r--r-- | src/dutil/atomutil.cpp | 1284 |
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 | |||
6 | static HRESULT ParseAtomDocument( | ||
7 | __in IXMLDOMDocument *pixd, | ||
8 | __out ATOM_FEED **ppFeed | ||
9 | ); | ||
10 | static HRESULT ParseAtomFeed( | ||
11 | __in IXMLDOMNode *pixnFeed, | ||
12 | __out ATOM_FEED **ppFeed | ||
13 | ); | ||
14 | static HRESULT ParseAtomAuthor( | ||
15 | __in IXMLDOMNode* pixnAuthor, | ||
16 | __in ATOM_AUTHOR* pAuthor | ||
17 | ); | ||
18 | static HRESULT ParseAtomCategory( | ||
19 | __in IXMLDOMNode* pixnCategory, | ||
20 | __in ATOM_CATEGORY* pCategory | ||
21 | ); | ||
22 | static HRESULT ParseAtomEntry( | ||
23 | __in IXMLDOMNode* pixnEntry, | ||
24 | __in ATOM_ENTRY* pEntry | ||
25 | ); | ||
26 | static HRESULT ParseAtomLink( | ||
27 | __in IXMLDOMNode* pixnLink, | ||
28 | __in ATOM_LINK* pLink | ||
29 | ); | ||
30 | static HRESULT ParseAtomUnknownElement( | ||
31 | __in IXMLDOMNode *pNode, | ||
32 | __inout ATOM_UNKNOWN_ELEMENT** ppUnknownElement | ||
33 | ); | ||
34 | static HRESULT ParseAtomUnknownAttribute( | ||
35 | __in IXMLDOMNode *pNode, | ||
36 | __inout ATOM_UNKNOWN_ATTRIBUTE** ppUnknownAttribute | ||
37 | ); | ||
38 | static HRESULT AssignDateTime( | ||
39 | __in FILETIME* pft, | ||
40 | __in IXMLDOMNode* pNode | ||
41 | ); | ||
42 | static HRESULT AssignString( | ||
43 | __out_z LPWSTR* pwzValue, | ||
44 | __in IXMLDOMNode* pNode | ||
45 | ); | ||
46 | static void FreeAtomAuthor( | ||
47 | __in_opt ATOM_AUTHOR* pAuthor | ||
48 | ); | ||
49 | static void FreeAtomContent( | ||
50 | __in_opt ATOM_CONTENT* pContent | ||
51 | ); | ||
52 | static void FreeAtomCategory( | ||
53 | __in_opt ATOM_CATEGORY* pCategory | ||
54 | ); | ||
55 | static void FreeAtomEntry( | ||
56 | __in_opt ATOM_ENTRY* pEntry | ||
57 | ); | ||
58 | static void FreeAtomLink( | ||
59 | __in_opt ATOM_LINK* pLink | ||
60 | ); | ||
61 | static void FreeAtomUnknownElementList( | ||
62 | __in_opt ATOM_UNKNOWN_ELEMENT* pUnknownElement | ||
63 | ); | ||
64 | static void FreeAtomUnknownAttributeList( | ||
65 | __in_opt ATOM_UNKNOWN_ATTRIBUTE* pUnknownAttribute | ||
66 | ); | ||
67 | |||
68 | template<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 | *********************************************************************/ | ||
80 | extern "C" HRESULT DAPI AtomInitialize() | ||
81 | { | ||
82 | return XmlInitialize(); | ||
83 | } | ||
84 | |||
85 | |||
86 | /******************************************************************** | ||
87 | AtomUninitialize - Uninitialize ATOM utilities. | ||
88 | |||
89 | *********************************************************************/ | ||
90 | extern "C" void DAPI AtomUninitialize() | ||
91 | { | ||
92 | XmlUninitialize(); | ||
93 | } | ||
94 | |||
95 | |||
96 | /******************************************************************** | ||
97 | AtomParseFromString - parses out an ATOM feed from a string. | ||
98 | |||
99 | *********************************************************************/ | ||
100 | extern "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 | |||
121 | LExit: | ||
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 | *********************************************************************/ | ||
133 | extern "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 | |||
154 | LExit: | ||
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 | *********************************************************************/ | ||
166 | extern "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 | |||
183 | LExit: | ||
184 | ReleaseAtomFeed(pNewFeed); | ||
185 | |||
186 | return hr; | ||
187 | } | ||
188 | |||
189 | |||
190 | /******************************************************************** | ||
191 | AtomFreeFeed - parses out an ATOM feed from a string. | ||
192 | |||
193 | *********************************************************************/ | ||
194 | extern "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 | *********************************************************************/ | ||
243 | static 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 | |||
273 | LExit: | ||
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 | *********************************************************************/ | ||
286 | static 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 | |||
423 | LExit: | ||
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 | *********************************************************************/ | ||
439 | template<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 | |||
478 | LExit: | ||
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 | *********************************************************************/ | ||
490 | static 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 | |||
529 | LExit: | ||
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 | *********************************************************************/ | ||
542 | static 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 | |||
597 | LExit: | ||
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 | *********************************************************************/ | ||
611 | static 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 | |||
662 | LExit: | ||
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 | *********************************************************************/ | ||
676 | static 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 | |||
800 | LExit: | ||
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 | *********************************************************************/ | ||
814 | static 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 | |||
889 | LExit: | ||
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 | *********************************************************************/ | ||
903 | static 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 | |||
971 | LExit: | ||
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 | *********************************************************************/ | ||
988 | static 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 | |||
1037 | LExit: | ||
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 | *********************************************************************/ | ||
1052 | static 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 | |||
1080 | LExit: | ||
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 | *********************************************************************/ | ||
1091 | static 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 | |||
1119 | LExit: | ||
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 | *********************************************************************/ | ||
1130 | static 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 | *********************************************************************/ | ||
1147 | static 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 | *********************************************************************/ | ||
1166 | static 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 | *********************************************************************/ | ||
1185 | static 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 | *********************************************************************/ | ||
1226 | static 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 | *********************************************************************/ | ||
1248 | static 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 | *********************************************************************/ | ||
1270 | static 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 | } | ||