main
cpp 1,437 lines 39.4 KB
Raw
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 #include "precomp.h"
4
5
6 // Exit macros
7 #define XmlExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_XMLUTIL, x, s, __VA_ARGS__)
8 #define XmlExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_XMLUTIL, x, s, __VA_ARGS__)
9 #define XmlExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_XMLUTIL, x, s, __VA_ARGS__)
10 #define XmlExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_XMLUTIL, x, s, __VA_ARGS__)
11 #define XmlExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_XMLUTIL, x, s, __VA_ARGS__)
12 #define XmlExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_XMLUTIL, x, s, __VA_ARGS__)
13 #define XmlExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_XMLUTIL, p, x, e, s, __VA_ARGS__)
14 #define XmlExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_XMLUTIL, p, x, s, __VA_ARGS__)
15 #define XmlExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_XMLUTIL, p, x, e, s, __VA_ARGS__)
16 #define XmlExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_XMLUTIL, p, x, s, __VA_ARGS__)
17 #define XmlExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_XMLUTIL, e, x, s, __VA_ARGS__)
18 #define XmlExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_XMLUTIL, g, x, s, __VA_ARGS__)
19
20 // intialization globals
21 CLSID vclsidXMLDOM = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0} };
22 static volatile LONG vcXmlInitialized = 0;
23 static BOOL vfMsxml40 = FALSE;
24 static BOOL fComInitialized = FALSE;
25 BOOL vfMsxml30 = FALSE;
26
27 /********************************************************************
28 XmlInitialize - finds an appropriate version of the XML DOM
29
30 *********************************************************************/
31 extern "C" HRESULT DAPI XmlInitialize(
32 )
33 {
34 HRESULT hr = S_OK;
35
36 if (!fComInitialized)
37 {
38 hr = ::CoInitialize(0);
39 if (RPC_E_CHANGED_MODE != hr)
40 {
41 XmlExitOnFailure(hr, "failed to initialize COM");
42 fComInitialized = TRUE;
43 }
44 }
45
46 LONG cInitialized = ::InterlockedIncrement(&vcXmlInitialized);
47 if (1 == cInitialized)
48 {
49 // NOTE: 4.0 behaves differently than 3.0 so there may be problems doing this
50 #if 0
51 hr = ::CLSIDFromProgID(L"Msxml2.DOMDocument.4.0", &vclsidXMLDOM);
52 if (S_OK == hr)
53 {
54 vfMsxml40 = TRUE;
55 Trace(REPORT_VERBOSE, "found Msxml2.DOMDocument.4.0");
56 ExitFunction();
57 }
58 #endif
59 hr = ::CLSIDFromProgID(L"Msxml2.DOMDocument", &vclsidXMLDOM);
60 if (FAILED(hr))
61 {
62 // try to fall back to old MSXML
63 hr = ::CLSIDFromProgID(L"MSXML.DOMDocument", &vclsidXMLDOM);
64 }
65 XmlExitOnFailure(hr, "failed to get CLSID for XML DOM");
66
67 Assert(IsEqualCLSID(vclsidXMLDOM, XmlUtil_CLSID_DOMDocument) ||
68 IsEqualCLSID(vclsidXMLDOM, XmlUtil_CLSID_DOMDocument20) ||
69 IsEqualCLSID(vclsidXMLDOM, XmlUtil_CLSID_DOMDocument26) ||
70 IsEqualCLSID(vclsidXMLDOM, XmlUtil_CLSID_DOMDocument30) ||
71 IsEqualCLSID(vclsidXMLDOM, XmlUtil_CLSID_DOMDocument40) ||
72 IsEqualCLSID(vclsidXMLDOM, XmlUtil_CLSID_DOMDocument50) ||
73 IsEqualCLSID(vclsidXMLDOM, XmlUtil_CLSID_DOMDocument60));
74 }
75
76 hr = S_OK;
77 LExit:
78 return hr;
79 }
80
81
82 /********************************************************************
83 XmUninitialize -
84
85 *********************************************************************/
86 extern "C" void DAPI XmlUninitialize(
87 )
88 {
89 AssertSz(vcXmlInitialized, "XmlUninitialize called when not initialized");
90
91 LONG cInitialized = ::InterlockedDecrement(&vcXmlInitialized);
92
93 if (0 == cInitialized)
94 {
95 memset(&vclsidXMLDOM, 0, sizeof(vclsidXMLDOM));
96
97 if (fComInitialized)
98 {
99 ::CoUninitialize();
100 }
101 }
102 }
103
104 extern "C" HRESULT DAPI XmlCreateElement(
105 __in IXMLDOMDocument *pixdDocument,
106 __in_z LPCWSTR wzElementName,
107 __out IXMLDOMElement **ppixnElement
108 )
109 {
110 if (!ppixnElement || !pixdDocument)
111 {
112 return E_INVALIDARG;
113 }
114
115 HRESULT hr = S_OK;
116 BSTR bstrElementName = ::SysAllocString(wzElementName);
117 XmlExitOnNull(bstrElementName, hr, E_OUTOFMEMORY, "failed SysAllocString");
118 hr = pixdDocument->createElement(bstrElementName, ppixnElement);
119 LExit:
120 ReleaseBSTR(bstrElementName);
121 return hr;
122 }
123
124
125 /********************************************************************
126 XmlCreateDocument -
127
128 *********************************************************************/
129 extern "C" HRESULT DAPI XmlCreateDocument(
130 __in_opt LPCWSTR pwzElementName,
131 __out IXMLDOMDocument** ppixdDocument,
132 __out_opt IXMLDOMElement** ppixeRootElement
133 )
134 {
135 HRESULT hr = S_OK;
136 BOOL (WINAPI *pfnDisableWow64)(__out PVOID* ) = NULL;
137 BOOLEAN (WINAPI *pfnEnableWow64)(__in BOOLEAN ) = NULL;
138 BOOL (WINAPI *pfnRevertWow64)(__in PVOID ) = NULL;
139 BOOL fWow64Available = FALSE;
140 void *pvWow64State = NULL;
141
142 // RELEASEME
143 IXMLDOMElement* pixeRootElement = NULL;
144 IXMLDOMDocument *pixdDocument = NULL;
145
146 // Test if we have access to the Wow64 API, and store the result in fWow64Available
147 HMODULE hKernel32 = ::GetModuleHandleA("kernel32.dll");
148 XmlExitOnNullWithLastError(hKernel32, hr, "failed to get handle to kernel32.dll");
149
150 // This will test if we have access to the Wow64 API
151 if (NULL != GetProcAddress(hKernel32, "IsWow64Process"))
152 {
153 pfnDisableWow64 = (BOOL (WINAPI *)(PVOID *))::GetProcAddress(hKernel32, "Wow64DisableWow64FsRedirection");
154 pfnEnableWow64 = (BOOLEAN (WINAPI *)(BOOLEAN))::GetProcAddress(hKernel32, "Wow64EnableWow64FsRedirection");
155 pfnRevertWow64 = (BOOL (WINAPI *)(PVOID))::GetProcAddress(hKernel32, "Wow64RevertWow64FsRedirection");
156
157 fWow64Available = pfnDisableWow64 && pfnEnableWow64 && pfnRevertWow64;
158 }
159
160 // create the top level XML document
161 AssertSz(vcXmlInitialized, "XmlInitialize() was not called");
162
163 // Enable Wow64 Redirection, if possible
164 if (fWow64Available)
165 {
166 // We want to enable Wow64 redirection, but the Wow64 API requires us to disable it first to get its current state (so we can revert it later)
167 pfnDisableWow64(&pvWow64State);
168 // If we fail to enable it, don't bother trying to disable it later on
169 fWow64Available = pfnEnableWow64(TRUE);
170 }
171
172 hr = ::CoCreateInstance(vclsidXMLDOM, NULL, CLSCTX_INPROC_SERVER, XmlUtil_IID_IXMLDOMDocument, (void**)&pixdDocument);
173 XmlExitOnFailure(hr, "failed to create XML DOM Document");
174 Assert(pixdDocument);
175
176 if (IsEqualCLSID(vclsidXMLDOM, XmlUtil_CLSID_DOMDocument30) || IsEqualCLSID(vclsidXMLDOM, XmlUtil_CLSID_DOMDocument20))
177 {
178 vfMsxml30 = TRUE;
179 }
180
181 if (pwzElementName)
182 {
183 hr = XmlCreateElement(pixdDocument, pwzElementName, &pixeRootElement);
184 XmlExitOnFailure(hr, "failed XmlCreateElement");
185 hr = pixdDocument->appendChild(pixeRootElement, NULL);
186 XmlExitOnFailure(hr, "failed appendChild");
187 }
188
189 *ppixdDocument = pixdDocument;
190 pixdDocument = NULL;
191
192 if (ppixeRootElement)
193 {
194 *ppixeRootElement = pixeRootElement;
195 pixeRootElement = NULL;
196 }
197
198 LExit:
199 // Re-disable Wow64 Redirection, if appropriate
200 if (fWow64Available && !pfnRevertWow64(pvWow64State))
201 {
202 // If we expected to be able to revert, and couldn't, fail in the only graceful way we can
203 ::ExitProcess(1);
204 }
205
206 ReleaseObject(pixeRootElement);
207 ReleaseObject(pixdDocument);
208 return hr;
209 }
210
211
212 /********************************************************************
213 XmlLoadDocument -
214
215 *********************************************************************/
216 extern "C" HRESULT DAPI XmlLoadDocument(
217 __in_z LPCWSTR wzDocument,
218 __out IXMLDOMDocument** ppixdDocument
219 )
220 {
221 return XmlLoadDocumentEx(wzDocument, 0, ppixdDocument);
222 }
223
224
225 /********************************************************************
226 XmlReportParseError -
227
228 *********************************************************************/
229 static void XmlReportParseError(
230 __in IXMLDOMParseError* pixpe
231 )
232 {
233 HRESULT hr = S_OK;
234 long lNumber = 0;
235 BSTR bstr = NULL;
236
237 Trace(REPORT_STANDARD, "Failed to parse XML. IXMLDOMParseError reports:");
238
239 hr = pixpe->get_errorCode(&lNumber);
240 XmlExitOnFailure(hr, "Failed to query IXMLDOMParseError.errorCode.");
241 Trace(REPORT_STANDARD, "errorCode = 0x%x", lNumber);
242
243 hr = pixpe->get_filepos(&lNumber);
244 XmlExitOnFailure(hr, "Failed to query IXMLDOMParseError.filepos.");
245 Trace(REPORT_STANDARD, "filepos = %d", lNumber);
246
247 hr = pixpe->get_line(&lNumber);
248 XmlExitOnFailure(hr, "Failed to query IXMLDOMParseError.line.");
249 Trace(REPORT_STANDARD, "line = %d", lNumber);
250
251 hr = pixpe->get_linepos(&lNumber);
252 XmlExitOnFailure(hr, "Failed to query IXMLDOMParseError.linepos.");
253 Trace(REPORT_STANDARD, "linepos = %d", lNumber);
254
255 hr = pixpe->get_reason(&bstr);
256 XmlExitOnFailure(hr, "Failed to query IXMLDOMParseError.reason.");
257 Trace(REPORT_STANDARD, "reason = %ls", bstr);
258 ReleaseNullBSTR(bstr);
259
260 hr = pixpe->get_srcText (&bstr);
261 XmlExitOnFailure(hr, "Failed to query IXMLDOMParseError.srcText .");
262 Trace(REPORT_STANDARD, "srcText = %ls", bstr);
263 ReleaseNullBSTR(bstr);
264
265 LExit:
266 ReleaseBSTR(bstr);
267 }
268
269 /********************************************************************
270 XmlLoadDocumentEx -
271
272 *********************************************************************/
273 extern "C" HRESULT DAPI XmlLoadDocumentEx(
274 __in_z LPCWSTR wzDocument,
275 __in DWORD dwAttributes,
276 __out IXMLDOMDocument** ppixdDocument
277 )
278 {
279 HRESULT hr = S_OK;
280 VARIANT_BOOL vbSuccess = 0;
281
282 // RELEASEME
283 IXMLDOMDocument* pixd = NULL;
284 IXMLDOMParseError* pixpe = NULL;
285 BSTR bstrLoad = NULL;
286
287 if (!wzDocument || !*wzDocument)
288 {
289 hr = E_UNEXPECTED;
290 XmlExitOnFailure(hr, "string must be non-null");
291 }
292
293 hr = XmlCreateDocument(NULL, &pixd);
294 if (hr == S_FALSE)
295 {
296 hr = E_FAIL;
297 }
298 XmlExitOnFailure(hr, "failed XmlCreateDocument");
299
300 if (dwAttributes & XML_LOAD_PRESERVE_WHITESPACE)
301 {
302 hr = pixd->put_preserveWhiteSpace(VARIANT_TRUE);
303 XmlExitOnFailure(hr, "failed put_preserveWhiteSpace");
304 }
305
306 // Security issue. Avoid triggering anything external.
307 hr = pixd->put_validateOnParse(VARIANT_FALSE);
308 XmlExitOnFailure(hr, "failed put_validateOnParse");
309 hr = pixd->put_resolveExternals(VARIANT_FALSE);
310 XmlExitOnFailure(hr, "failed put_resolveExternals");
311
312 bstrLoad = ::SysAllocString(wzDocument);
313 XmlExitOnNull(bstrLoad, hr, E_OUTOFMEMORY, "failed to allocate bstr for Load in XmlLoadDocumentEx");
314
315 hr = pixd->loadXML(bstrLoad, &vbSuccess);
316 if (S_FALSE == hr)
317 {
318 hr = HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
319 }
320
321 if (FAILED(hr) && S_OK == pixd->get_parseError(&pixpe))
322 {
323 XmlReportParseError(pixpe);
324 }
325
326 XmlExitOnFailure(hr, "failed loadXML");
327
328
329 hr = S_OK;
330 LExit:
331 if (ppixdDocument)
332 {
333 *ppixdDocument = pixd;
334 pixd = NULL;
335 }
336 ReleaseBSTR(bstrLoad);
337 ReleaseObject(pixd);
338 ReleaseObject(pixpe);
339
340 return hr;
341 }
342
343
344 /*******************************************************************
345 XmlLoadDocumentFromFile
346
347 ********************************************************************/
348 extern "C" HRESULT DAPI XmlLoadDocumentFromFile(
349 __in_z LPCWSTR wzPath,
350 __out IXMLDOMDocument** ppixdDocument
351 )
352 {
353 return XmlLoadDocumentFromFileEx(wzPath, 0, ppixdDocument);
354 }
355
356
357 /*******************************************************************
358 XmlLoadDocumentFromFileEx
359
360 ********************************************************************/
361 extern "C" HRESULT DAPI XmlLoadDocumentFromFileEx(
362 __in_z LPCWSTR wzPath,
363 __in DWORD dwAttributes,
364 __out IXMLDOMDocument** ppixdDocument
365 )
366 {
367 HRESULT hr = S_OK;
368 VARIANT varPath;
369 VARIANT_BOOL vbSuccess = 0;
370
371 IXMLDOMDocument* pixd = NULL;
372 IXMLDOMParseError* pixpe = NULL;
373
374 ::VariantInit(&varPath);
375 varPath.vt = VT_BSTR;
376 varPath.bstrVal = ::SysAllocString(wzPath);
377 XmlExitOnNull(varPath.bstrVal, hr, E_OUTOFMEMORY, "failed to allocate bstr for Path in XmlLoadDocumentFromFileEx");
378
379 hr = XmlCreateDocument(NULL, &pixd);
380 if (hr == S_FALSE)
381 {
382 hr = E_FAIL;
383 }
384 XmlExitOnFailure(hr, "failed XmlCreateDocument");
385
386 if (dwAttributes & XML_LOAD_PRESERVE_WHITESPACE)
387 {
388 hr = pixd->put_preserveWhiteSpace(VARIANT_TRUE);
389 XmlExitOnFailure(hr, "failed put_preserveWhiteSpace");
390 }
391
392 // Avoid triggering anything external.
393 hr = pixd->put_validateOnParse(VARIANT_FALSE);
394 XmlExitOnFailure(hr, "failed put_validateOnParse");
395 hr = pixd->put_resolveExternals(VARIANT_FALSE);
396 XmlExitOnFailure(hr, "failed put_resolveExternals");
397
398 pixd->put_async(VARIANT_FALSE);
399 hr = pixd->load(varPath, &vbSuccess);
400 if (S_FALSE == hr)
401 {
402 hr = HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
403 }
404
405 if (FAILED(hr) && S_OK == pixd->get_parseError(&pixpe))
406 {
407 XmlReportParseError(pixpe);
408 }
409
410 XmlExitOnFailure(hr, "failed to load XML from: %ls", wzPath);
411
412 if (ppixdDocument)
413 {
414 *ppixdDocument = pixd;
415 pixd = NULL;
416 }
417
418 hr = S_OK;
419 LExit:
420 ReleaseVariant(varPath);
421 ReleaseObject(pixd);
422 ReleaseObject(pixpe);
423
424 return hr;
425 }
426
427
428 /********************************************************************
429 XmlLoadDocumentFromBuffer
430
431 *********************************************************************/
432 extern "C" HRESULT DAPI XmlLoadDocumentFromBuffer(
433 __in_bcount(cbSource) const BYTE* pbSource,
434 __in SIZE_T cbSource,
435 __out IXMLDOMDocument** ppixdDocument
436 )
437 {
438 HRESULT hr = S_OK;
439 IXMLDOMDocument* pixdDocument = NULL;
440 SAFEARRAY sa = { };
441 VARIANT vtXmlSource;
442 VARIANT_BOOL vbSuccess = 0;
443
444 ::VariantInit(&vtXmlSource);
445
446 // create document
447 hr = XmlCreateDocument(NULL, &pixdDocument);
448 if (hr == S_FALSE)
449 {
450 hr = E_FAIL;
451 }
452 XmlExitOnFailure(hr, "failed XmlCreateDocument");
453
454 // Security issue. Avoid triggering anything external.
455 hr = pixdDocument->put_validateOnParse(VARIANT_FALSE);
456 XmlExitOnFailure(hr, "failed put_validateOnParse");
457 hr = pixdDocument->put_resolveExternals(VARIANT_FALSE);
458 XmlExitOnFailure(hr, "failed put_resolveExternals");
459
460 // load document
461 sa.cDims = 1;
462 sa.fFeatures = FADF_STATIC | FADF_FIXEDSIZE;
463 sa.cbElements = 1;
464 sa.pvData = (PVOID)pbSource;
465 sa.rgsabound[0].cElements = (ULONG)cbSource;
466 vtXmlSource.vt = VT_ARRAY | VT_UI1;
467 vtXmlSource.parray = &sa;
468
469 hr = pixdDocument->load(vtXmlSource, &vbSuccess);
470 if (S_FALSE == hr)
471 {
472 hr = HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
473 }
474 XmlExitOnFailure(hr, "failed loadXML");
475
476 // return value
477 *ppixdDocument = pixdDocument;
478 pixdDocument = NULL;
479
480 LExit:
481 ReleaseObject(pixdDocument);
482 return hr;
483 }
484
485
486 /********************************************************************
487 XmlSetAttribute -
488
489 *********************************************************************/
490 extern "C" HRESULT DAPI XmlSetAttribute(
491 __in IXMLDOMNode* pixnNode,
492 __in_z LPCWSTR pwzAttribute,
493 __in_z LPCWSTR pwzAttributeValue
494 )
495 {
496 HRESULT hr = S_OK;
497 VARIANT varAttributeValue;
498 ::VariantInit(&varAttributeValue);
499
500 // RELEASEME
501 IXMLDOMDocument* pixdDocument = NULL;
502 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
503 IXMLDOMAttribute* pixaAttribute = NULL;
504 IXMLDOMNode* pixaNode = NULL;
505 BSTR bstrAttributeName = ::SysAllocString(pwzAttribute);
506 XmlExitOnNull(bstrAttributeName, hr, E_OUTOFMEMORY, "failed to allocate bstr for AttributeName in XmlSetAttribute");
507
508 hr = pixnNode->get_attributes(&pixnnmAttributes);
509 XmlExitOnFailure(hr, "failed get_attributes in XmlSetAttribute(%ls)", pwzAttribute);
510
511 hr = pixnNode->get_ownerDocument(&pixdDocument);
512 if (hr == S_FALSE)
513 {
514 hr = E_FAIL;
515 }
516 XmlExitOnFailure(hr, "failed get_ownerDocument in XmlSetAttribute");
517
518 hr = pixdDocument->createAttribute(bstrAttributeName, &pixaAttribute);
519 XmlExitOnFailure(hr, "failed createAttribute in XmlSetAttribute(%ls)", pwzAttribute);
520
521 varAttributeValue.vt = VT_BSTR;
522 varAttributeValue.bstrVal = ::SysAllocString(pwzAttributeValue);
523 if (!varAttributeValue.bstrVal)
524 {
525 hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
526 }
527 XmlExitOnFailure(hr, "failed SysAllocString in XmlSetAttribute");
528
529 hr = pixaAttribute->put_nodeValue(varAttributeValue);
530 XmlExitOnFailure(hr, "failed put_nodeValue in XmlSetAttribute(%ls)", pwzAttribute);
531
532 hr = pixnnmAttributes->setNamedItem(pixaAttribute, &pixaNode);
533 XmlExitOnFailure(hr, "failed setNamedItem in XmlSetAttribute(%ls)", pwzAttribute);
534
535 LExit:
536 ReleaseObject(pixdDocument);
537 ReleaseObject(pixnnmAttributes);
538 ReleaseObject(pixaAttribute);
539 ReleaseObject(pixaNode);
540 ReleaseBSTR(varAttributeValue.bstrVal);
541 ReleaseBSTR(bstrAttributeName);
542
543 return hr;
544 }
545
546
547 /********************************************************************
548 XmlSelectSingleNode -
549
550 *********************************************************************/
551 extern "C" HRESULT DAPI XmlSelectSingleNode(
552 __in IXMLDOMNode* pixnParent,
553 __in_z LPCWSTR wzXPath,
554 __out IXMLDOMNode **ppixnChild
555 )
556 {
557 HRESULT hr = S_OK;
558
559 BSTR bstrXPath = NULL;
560
561 XmlExitOnNull(pixnParent, hr, E_UNEXPECTED, "pixnParent parameter was null in XmlSelectSingleNode");
562 XmlExitOnNull(ppixnChild, hr, E_UNEXPECTED, "ppixnChild parameter was null in XmlSelectSingleNode");
563
564 bstrXPath = ::SysAllocString(wzXPath ? wzXPath : L"");
565 XmlExitOnNull(bstrXPath, hr, E_OUTOFMEMORY, "failed to allocate bstr for XPath expression in XmlSelectSingleNode");
566
567 hr = pixnParent->selectSingleNode(bstrXPath, ppixnChild);
568
569 LExit:
570 ReleaseBSTR(bstrXPath);
571
572 return hr;
573 }
574
575
576 /********************************************************************
577 XmlCreateTextNode -
578
579 *********************************************************************/
580 extern "C" HRESULT DAPI XmlCreateTextNode(
581 __in IXMLDOMDocument *pixdDocument,
582 __in_z LPCWSTR wzText,
583 __out IXMLDOMText **ppixnTextNode
584 )
585 {
586 if (!ppixnTextNode || !pixdDocument)
587 {
588 return E_INVALIDARG;
589 }
590
591 HRESULT hr = S_OK;
592 BSTR bstrText = ::SysAllocString(wzText);
593 XmlExitOnNull(bstrText, hr, E_OUTOFMEMORY, "failed SysAllocString");
594 hr = pixdDocument->createTextNode(bstrText, ppixnTextNode);
595 LExit:
596 ReleaseBSTR(bstrText);
597
598 return hr;
599 }
600
601
602 /********************************************************************
603 XmlGetText
604
605 *********************************************************************/
606 extern "C" HRESULT DAPI XmlGetText(
607 __in IXMLDOMNode* pixnNode,
608 __deref_out_z BSTR* pbstrText
609 )
610 {
611 return pixnNode->get_text(pbstrText);
612 }
613
614
615 /********************************************************************
616 XmlGetAttribute
617
618 *********************************************************************/
619 extern "C" HRESULT DAPI XmlGetAttribute(
620 __in IXMLDOMNode* pixnNode,
621 __in_z LPCWSTR pwzAttribute,
622 __deref_out_z BSTR* pbstrAttributeValue
623 )
624 {
625 Assert(pixnNode);
626 HRESULT hr = S_OK;
627
628 // RELEASEME
629 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
630 IXMLDOMNode* pixnAttribute = NULL;
631 VARIANT varAttributeValue;
632 BSTR bstrAttribute = SysAllocString(pwzAttribute);
633
634 // INIT
635 ::VariantInit(&varAttributeValue);
636
637 // get attribute value from source
638 hr = pixnNode->get_attributes(&pixnnmAttributes);
639 XmlExitOnFailure(hr, "failed get_attributes");
640
641 hr = XmlGetNamedItem(pixnnmAttributes, bstrAttribute, &pixnAttribute);
642 if (S_FALSE == hr)
643 {
644 // hr = E_FAIL;
645 ExitFunction();
646 }
647 XmlExitOnFailure(hr, "failed getNamedItem in XmlGetAttribute(%ls)", pwzAttribute);
648
649 hr = pixnAttribute->get_nodeValue(&varAttributeValue);
650 XmlExitOnFailure(hr, "failed get_nodeValue in XmlGetAttribute(%ls)", pwzAttribute);
651
652 // steal the BSTR from the VARIANT
653 if (S_OK == hr && pbstrAttributeValue)
654 {
655 *pbstrAttributeValue = varAttributeValue.bstrVal;
656 varAttributeValue.bstrVal = NULL;
657 }
658
659 LExit:
660 ReleaseObject(pixnnmAttributes);
661 ReleaseObject(pixnAttribute);
662 ReleaseVariant(varAttributeValue);
663 ReleaseBSTR(bstrAttribute);
664
665 return hr;
666 }
667
668
669 /********************************************************************
670 XmlGetAttributeEx
671
672 *********************************************************************/
673 HRESULT DAPI XmlGetAttributeEx(
674 __in IXMLDOMNode* pixnNode,
675 __in_z LPCWSTR wzAttribute,
676 __deref_out_z LPWSTR* psczAttributeValue
677 )
678 {
679 Assert(pixnNode);
680 HRESULT hr = S_OK;
681 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
682 IXMLDOMNode* pixnAttribute = NULL;
683 VARIANT varAttributeValue;
684 BSTR bstrAttribute = NULL;
685
686 ::VariantInit(&varAttributeValue);
687
688 // get attribute value from source
689 hr = pixnNode->get_attributes(&pixnnmAttributes);
690 XmlExitOnFailure(hr, "Failed get_attributes.");
691
692 bstrAttribute = ::SysAllocString(wzAttribute);
693 XmlExitOnNull(bstrAttribute, hr, E_OUTOFMEMORY, "Failed to allocate attribute name BSTR.");
694
695 hr = XmlGetNamedItem(pixnnmAttributes, bstrAttribute, &pixnAttribute);
696 if (S_FALSE == hr)
697 {
698 ExitFunction1(hr = E_NOTFOUND);
699 }
700 XmlExitOnFailure(hr, "Failed getNamedItem in XmlGetAttribute(%ls)", wzAttribute);
701
702 hr = pixnAttribute->get_nodeValue(&varAttributeValue);
703 if (S_FALSE == hr)
704 {
705 ExitFunction1(hr = E_NOTFOUND);
706 }
707 XmlExitOnFailure(hr, "Failed get_nodeValue in XmlGetAttribute(%ls)", wzAttribute);
708
709 // copy value
710 hr = StrAllocString(psczAttributeValue, varAttributeValue.bstrVal, 0);
711 XmlExitOnFailure(hr, "Failed to copy attribute value.");
712
713 LExit:
714 ReleaseObject(pixnnmAttributes);
715 ReleaseObject(pixnAttribute);
716 ReleaseVariant(varAttributeValue);
717 ReleaseBSTR(bstrAttribute);
718
719 return hr;
720 }
721
722
723 /********************************************************************
724 XmlGetYesNoAttribute
725
726 *********************************************************************/
727 HRESULT DAPI XmlGetYesNoAttribute(
728 __in IXMLDOMNode* pixnNode,
729 __in_z LPCWSTR wzAttribute,
730 __out BOOL* pfYes
731 )
732 {
733 HRESULT hr = S_OK;
734 LPWSTR sczValue = NULL;
735
736 hr = XmlGetAttributeEx(pixnNode, wzAttribute, &sczValue);
737 if (E_NOTFOUND != hr)
738 {
739 XmlExitOnFailure(hr, "Failed to get attribute.");
740
741 *pfYes = CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczValue, -1, L"yes", -1);
742 }
743
744 LExit:
745 ReleaseStr(sczValue);
746
747 return hr;
748 }
749
750
751
752 /********************************************************************
753 XmlGetAttributeNumber
754
755 *********************************************************************/
756 extern "C" HRESULT DAPI XmlGetAttributeNumber(
757 __in IXMLDOMNode* pixnNode,
758 __in_z LPCWSTR pwzAttribute,
759 __out DWORD* pdwValue
760 )
761 {
762 HRESULT hr = XmlGetAttributeNumberBase(pixnNode, pwzAttribute, 10, pdwValue);
763 return hr;
764 }
765
766
767 /********************************************************************
768 XmlGetAttributeNumberBase
769
770 *********************************************************************/
771 extern "C" HRESULT DAPI XmlGetAttributeNumberBase(
772 __in IXMLDOMNode* pixnNode,
773 __in_z LPCWSTR pwzAttribute,
774 __in int nBase,
775 __out DWORD* pdwValue
776 )
777 {
778 HRESULT hr = S_OK;
779 BSTR bstrPointer = NULL;
780
781 hr = XmlGetAttribute(pixnNode, pwzAttribute, &bstrPointer);
782 XmlExitOnFailure(hr, "Failed to get value from attribute.");
783
784 if (S_OK == hr)
785 {
786 *pdwValue = wcstoul(bstrPointer, NULL, nBase);
787 }
788
789 LExit:
790 ReleaseBSTR(bstrPointer);
791 return hr;
792 }
793
794
795 /********************************************************************
796 XmlGetAttributeUInt16
797
798 *********************************************************************/
799 extern "C" HRESULT DAPI XmlGetAttributeUInt16(
800 __in IXMLDOMNode* pixnNode,
801 __in_z LPCWSTR pwzAttribute,
802 __out WORD* pwValue
803 )
804 {
805 HRESULT hr = S_OK;
806 BSTR bstrValue = NULL;
807
808 hr = XmlGetAttribute(pixnNode, pwzAttribute, &bstrValue);
809 XmlExitOnFailure(hr, "failed XmlGetAttribute");
810
811 if (S_OK == hr)
812 {
813 WORD w = 0;
814 hr = StrStringToUInt16(bstrValue, 0, &w);
815 XmlExitOnFailure(hr, "Failed to treat attribute value as UInt16.");
816
817 *pwValue = w;
818 }
819 else
820 {
821 *pwValue = 0;
822 }
823
824 LExit:
825 ReleaseBSTR(bstrValue);
826 return hr;
827 }
828
829
830 /********************************************************************
831 XmlGetAttributeInt32
832
833 *********************************************************************/
834 extern "C" HRESULT DAPI XmlGetAttributeInt32(
835 __in IXMLDOMNode* pixnNode,
836 __in_z LPCWSTR pwzAttribute,
837 __out int* piValue
838 )
839 {
840 HRESULT hr = S_OK;
841 BSTR bstrValue = NULL;
842
843 hr = XmlGetAttribute(pixnNode, pwzAttribute, &bstrValue);
844 XmlExitOnFailure(hr, "failed XmlGetAttribute");
845
846 if (S_OK == hr)
847 {
848 int i = 0;
849 hr = StrStringToInt32(bstrValue, 0, &i);
850 XmlExitOnFailure(hr, "Failed to treat attribute value as Int32.");
851
852 *piValue = i;
853 }
854 else
855 {
856 *piValue = 0;
857 }
858
859 LExit:
860 ReleaseBSTR(bstrValue);
861 return hr;
862 }
863
864
865 /********************************************************************
866 XmlGetAttributeUInt32
867
868 *********************************************************************/
869 extern "C" HRESULT DAPI XmlGetAttributeUInt32(
870 __in IXMLDOMNode* pixnNode,
871 __in_z LPCWSTR pwzAttribute,
872 __out DWORD* pdwValue
873 )
874 {
875 HRESULT hr = S_OK;
876 BSTR bstrValue = NULL;
877
878 hr = XmlGetAttribute(pixnNode, pwzAttribute, &bstrValue);
879 XmlExitOnFailure(hr, "failed XmlGetAttribute");
880
881 if (S_OK == hr)
882 {
883 UINT dw = 0;
884 hr = StrStringToUInt32(bstrValue, 0, &dw);
885 XmlExitOnFailure(hr, "Failed to treat attribute value as UInt32.");
886
887 *pdwValue = dw;
888 }
889 else
890 {
891 *pdwValue = 0;
892 }
893
894 LExit:
895 ReleaseBSTR(bstrValue);
896 return hr;
897 }
898
899
900 /********************************************************************
901 XmlGetAttributeUInt64
902
903 *********************************************************************/
904 extern "C" HRESULT DAPI XmlGetAttributeUInt64(
905 __in IXMLDOMNode* pixnNode,
906 __in_z LPCWSTR pwzAttribute,
907 __out DWORD64* pqwValue
908 )
909 {
910 HRESULT hr = S_OK;
911 BSTR bstrValue = NULL;
912
913 hr = XmlGetAttribute(pixnNode, pwzAttribute, &bstrValue);
914 XmlExitOnFailure(hr, "failed XmlGetAttribute");
915
916 if (S_OK == hr)
917 {
918 DWORD64 qw = 0;
919 hr = StrStringToUInt64(bstrValue, 0, &qw);
920 XmlExitOnFailure(hr, "Failed to treat attribute value as UInt64.");
921
922 *pqwValue = qw;
923 }
924 else
925 {
926 *pqwValue = 0;
927 }
928
929 LExit:
930 ReleaseBSTR(bstrValue);
931 return hr;
932 }
933
934
935 /********************************************************************
936 XmlGetNamedItem -
937
938 *********************************************************************/
939 extern "C" HRESULT DAPI XmlGetNamedItem(
940 __in IXMLDOMNamedNodeMap *pixnmAttributes,
941 __in_opt LPCWSTR wzName,
942 __out IXMLDOMNode **ppixnNamedItem
943 )
944 {
945 if (!pixnmAttributes || !ppixnNamedItem)
946 {
947 return E_INVALIDARG;
948 }
949
950 HRESULT hr = S_OK;
951 BSTR bstrName = ::SysAllocString(wzName);
952 XmlExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString");
953
954 hr = pixnmAttributes->getNamedItem(bstrName, ppixnNamedItem);
955
956 LExit:
957 ReleaseBSTR(bstrName);
958 return hr;
959 }
960
961
962 /********************************************************************
963 XmlSetText -
964
965 *********************************************************************/
966 extern "C" HRESULT DAPI XmlSetText(
967 __in IXMLDOMNode *pixnNode,
968 __in_z LPCWSTR pwzText
969 )
970 {
971 Assert(pixnNode && pwzText);
972 HRESULT hr = S_OK;
973 DOMNodeType dnType;
974
975 // RELEASEME
976 IXMLDOMDocument* pixdDocument = NULL;
977 IXMLDOMNodeList* pixnlNodeList = NULL;
978 IXMLDOMNode* pixnChildNode = NULL;
979 IXMLDOMText* pixtTextNode = NULL;
980 VARIANT varText;
981
982 ::VariantInit(&varText);
983
984 // find the text node
985 hr = pixnNode->get_childNodes(&pixnlNodeList);
986 XmlExitOnFailure(hr, "failed to get child nodes");
987
988 while (S_OK == (hr = pixnlNodeList->nextNode(&pixnChildNode)))
989 {
990 hr = pixnChildNode->get_nodeType(&dnType);
991 XmlExitOnFailure(hr, "failed to get node type");
992
993 if (NODE_TEXT == dnType)
994 break;
995 ReleaseNullObject(pixnChildNode);
996 }
997 if (S_FALSE == hr)
998 {
999 hr = S_OK;
1000 }
1001
1002 if (pixnChildNode)
1003 {
1004 varText.vt = VT_BSTR;
1005 varText.bstrVal = ::SysAllocString(pwzText);
1006 if (!varText.bstrVal)
1007 {
1008 hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
1009 }
1010 XmlExitOnFailure(hr, "failed SysAllocString in XmlSetText");
1011
1012 hr = pixnChildNode->put_nodeValue(varText);
1013 XmlExitOnFailure(hr, "failed IXMLDOMNode::put_nodeValue");
1014 }
1015 else
1016 {
1017 hr = pixnNode->get_ownerDocument(&pixdDocument);
1018 if (hr == S_FALSE)
1019 {
1020 hr = E_FAIL;
1021 }
1022 XmlExitOnFailure(hr, "failed get_ownerDocument in XmlSetAttribute");
1023
1024 hr = XmlCreateTextNode(pixdDocument, pwzText, &pixtTextNode);
1025 XmlExitOnFailure(hr, "failed createTextNode in XmlSetText(%ls)", pwzText);
1026
1027 hr = pixnNode->appendChild(pixtTextNode, NULL);
1028 XmlExitOnFailure(hr, "failed appendChild in XmlSetText(%ls)", pwzText);
1029 }
1030
1031 hr = *pwzText ? S_OK : S_FALSE;
1032
1033 LExit:
1034 ReleaseObject(pixnlNodeList);
1035 ReleaseObject(pixnChildNode);
1036 ReleaseObject(pixdDocument);
1037 ReleaseObject(pixtTextNode);
1038 ReleaseVariant(varText);
1039 return hr;
1040 }
1041
1042
1043 /********************************************************************
1044 XmlSetTextNumber -
1045
1046 *********************************************************************/
1047 extern "C" HRESULT DAPI XmlSetTextNumber(
1048 __in IXMLDOMNode *pixnNode,
1049 __in DWORD dwValue
1050 )
1051 {
1052 HRESULT hr = S_OK;
1053 WCHAR wzValue[12];
1054
1055 hr = ::StringCchPrintfW(wzValue, countof(wzValue), L"%u", dwValue);
1056 XmlExitOnFailure(hr, "Failed to format numeric value as string.");
1057
1058 hr = XmlSetText(pixnNode, wzValue);
1059
1060 LExit:
1061 return hr;
1062 }
1063
1064
1065 /********************************************************************
1066 XmlCreateChild -
1067
1068 *********************************************************************/
1069 extern "C" HRESULT DAPI XmlCreateChild(
1070 __in IXMLDOMNode* pixnParent,
1071 __in_z LPCWSTR pwzElementType,
1072 __out IXMLDOMNode** ppixnChild
1073 )
1074 {
1075 HRESULT hr = S_OK;
1076
1077 // RELEASEME
1078 IXMLDOMDocument* pixdDocument = NULL;
1079 IXMLDOMNode* pixnChild = NULL;
1080
1081 hr = pixnParent->get_ownerDocument(&pixdDocument);
1082 if (hr == S_FALSE)
1083 {
1084 hr = E_FAIL;
1085 }
1086 XmlExitOnFailure(hr, "failed get_ownerDocument");
1087
1088 hr = XmlCreateElement(pixdDocument, pwzElementType, (IXMLDOMElement**) &pixnChild);
1089 if (hr == S_FALSE)
1090 {
1091 hr = E_FAIL;
1092 }
1093 XmlExitOnFailure(hr, "failed createElement");
1094
1095 pixnParent->appendChild(pixnChild,NULL);
1096 if (hr == S_FALSE)
1097 {
1098 hr = E_FAIL;
1099 }
1100 XmlExitOnFailure(hr, "failed appendChild");
1101
1102 if (ppixnChild)
1103 {
1104 *ppixnChild = pixnChild;
1105 pixnChild = NULL;
1106 }
1107
1108 LExit:
1109 ReleaseObject(pixdDocument);
1110 ReleaseObject(pixnChild);
1111 return hr;
1112 }
1113
1114 /********************************************************************
1115 XmlRemoveAttribute -
1116
1117 *********************************************************************/
1118 extern "C" HRESULT DAPI XmlRemoveAttribute(
1119 __in IXMLDOMNode* pixnNode,
1120 __in_z LPCWSTR pwzAttribute
1121 )
1122 {
1123 HRESULT hr = S_OK;
1124
1125 // RELEASEME
1126 IXMLDOMNamedNodeMap* pixnnmAttributes = NULL;
1127 BSTR bstrAttribute = ::SysAllocString(pwzAttribute);
1128 XmlExitOnNull(bstrAttribute, hr, E_OUTOFMEMORY, "failed to allocate bstr for attribute in XmlRemoveAttribute");
1129
1130 hr = pixnNode->get_attributes(&pixnnmAttributes);
1131 XmlExitOnFailure(hr, "failed get_attributes in RemoveXmlAttribute(%ls)", pwzAttribute);
1132
1133 hr = pixnnmAttributes->removeNamedItem(bstrAttribute, NULL);
1134 XmlExitOnFailure(hr, "failed removeNamedItem in RemoveXmlAttribute(%ls)", pwzAttribute);
1135
1136 LExit:
1137 ReleaseObject(pixnnmAttributes);
1138 ReleaseBSTR(bstrAttribute);
1139
1140 return hr;
1141 }
1142
1143
1144 /********************************************************************
1145 XmlSelectNodes -
1146
1147 *********************************************************************/
1148 extern "C" HRESULT DAPI XmlSelectNodes(
1149 __in IXMLDOMNode* pixnParent,
1150 __in_z LPCWSTR wzXPath,
1151 __out IXMLDOMNodeList **ppixnlChildren
1152 )
1153 {
1154 HRESULT hr = S_OK;
1155
1156 BSTR bstrXPath = NULL;
1157
1158 XmlExitOnNull(pixnParent, hr, E_UNEXPECTED, "pixnParent parameter was null in XmlSelectNodes");
1159 XmlExitOnNull(ppixnlChildren, hr, E_UNEXPECTED, "ppixnChild parameter was null in XmlSelectNodes");
1160
1161 bstrXPath = ::SysAllocString(wzXPath ? wzXPath : L"");
1162 XmlExitOnNull(bstrXPath, hr, E_OUTOFMEMORY, "failed to allocate bstr for XPath expression in XmlSelectNodes");
1163
1164 hr = pixnParent->selectNodes(bstrXPath, ppixnlChildren);
1165
1166 LExit:
1167 ReleaseBSTR(bstrXPath);
1168 return hr;
1169 }
1170
1171
1172 /********************************************************************
1173 XmlNextAttribute - returns the next attribute in a node list
1174
1175 NOTE: pbstrAttribute is optional
1176 returns S_OK if found an element
1177 returns S_FALSE if no element found
1178 returns E_* if something went wrong
1179 ********************************************************************/
1180 extern "C" HRESULT DAPI XmlNextAttribute(
1181 __in IXMLDOMNamedNodeMap* pixnnm,
1182 __out IXMLDOMNode** pixnAttribute,
1183 __deref_opt_out_z_opt BSTR* pbstrAttribute
1184 )
1185 {
1186 Assert(pixnnm && pixnAttribute);
1187
1188 HRESULT hr = S_OK;
1189 IXMLDOMNode* pixn = NULL;
1190 DOMNodeType nt;
1191
1192 // null out the return values
1193 *pixnAttribute = NULL;
1194 if (pbstrAttribute)
1195 {
1196 *pbstrAttribute = NULL;
1197 }
1198
1199 hr = pixnnm->nextNode(&pixn);
1200 XmlExitOnFailure(hr, "Failed to get next attribute.");
1201
1202 if (S_OK == hr)
1203 {
1204 hr = pixn->get_nodeType(&nt);
1205 XmlExitOnFailure(hr, "failed to get node type");
1206
1207 if (NODE_ATTRIBUTE != nt)
1208 {
1209 hr = E_UNEXPECTED;
1210 XmlExitOnFailure(hr, "Failed to get expected node type back: attribute");
1211 }
1212
1213 // if the caller asked for the attribute name
1214 if (pbstrAttribute)
1215 {
1216 hr = pixn->get_baseName(pbstrAttribute);
1217 XmlExitOnFailure(hr, "failed to get attribute name");
1218 }
1219
1220 *pixnAttribute = pixn;
1221 pixn = NULL;
1222 }
1223
1224 LExit:
1225 ReleaseObject(pixn);
1226 return hr;
1227 }
1228
1229
1230 /********************************************************************
1231 XmlNextElement - returns the next element in a node list
1232
1233 NOTE: pbstrElement is optional
1234 returns S_OK if found an element
1235 returns S_FALSE if no element found
1236 returns E_* if something went wrong
1237 ********************************************************************/
1238 extern "C" HRESULT DAPI XmlNextElement(
1239 __in IXMLDOMNodeList* pixnl,
1240 __out IXMLDOMNode** pixnElement,
1241 __deref_opt_out_z_opt BSTR* pbstrElement
1242 )
1243 {
1244 Assert(pixnl && pixnElement);
1245
1246 HRESULT hr = S_OK;
1247 IXMLDOMNode* pixn = NULL;
1248 DOMNodeType nt;
1249
1250 // null out the return values
1251 *pixnElement = NULL;
1252 if (pbstrElement)
1253 {
1254 *pbstrElement = NULL;
1255 }
1256
1257 //
1258 // find the next element in the list
1259 //
1260 while (S_OK == (hr = pixnl->nextNode(&pixn)))
1261 {
1262 hr = pixn->get_nodeType(&nt);
1263 XmlExitOnFailure(hr, "failed to get node type");
1264
1265 if (NODE_ELEMENT == nt)
1266 break;
1267
1268 ReleaseNullObject(pixn);
1269 }
1270 XmlExitOnFailure(hr, "failed to get next element");
1271
1272 // if we have a node and the caller asked for the element name
1273 if (pixn && pbstrElement)
1274 {
1275 hr = pixn->get_baseName(pbstrElement);
1276 XmlExitOnFailure(hr, "failed to get element name");
1277 }
1278
1279 *pixnElement = pixn;
1280 pixn = NULL;
1281
1282 hr = *pixnElement ? S_OK : S_FALSE;
1283 LExit:
1284 ReleaseObject(pixn);
1285 return hr;
1286 }
1287
1288
1289 /********************************************************************
1290 XmlRemoveChildren -
1291
1292 *********************************************************************/
1293 extern "C" HRESULT DAPI XmlRemoveChildren(
1294 __in IXMLDOMNode* pixnSource,
1295 __in_z LPCWSTR pwzXPath
1296 )
1297 {
1298 HRESULT hr = S_OK;
1299
1300 // RELEASEME
1301 IXMLDOMNodeList* pixnlNodeList = NULL;
1302 IXMLDOMNode* pixnNode = NULL;
1303 IXMLDOMNode* pixnRemoveChild = NULL;
1304
1305 if (pwzXPath)
1306 {
1307 hr = XmlSelectNodes(pixnSource, pwzXPath, &pixnlNodeList);
1308 XmlExitOnFailure(hr, "failed XmlSelectNodes");
1309 }
1310 else
1311 {
1312 hr = pixnSource->get_childNodes(&pixnlNodeList);
1313 XmlExitOnFailure(hr, "failed childNodes");
1314 }
1315 if (S_FALSE == hr)
1316 {
1317 ExitFunction();
1318 }
1319
1320 while (S_OK == (hr = pixnlNodeList->nextNode(&pixnNode)))
1321 {
1322 hr = pixnSource->removeChild(pixnNode, &pixnRemoveChild);
1323 XmlExitOnFailure(hr, "failed removeChild");
1324
1325 ReleaseNullObject(pixnRemoveChild);
1326 ReleaseNullObject(pixnNode);
1327 }
1328 if (S_FALSE == hr)
1329 {
1330 hr = S_OK;
1331 }
1332
1333 LExit:
1334 ReleaseObject(pixnlNodeList);
1335 ReleaseObject(pixnNode);
1336 ReleaseObject(pixnRemoveChild);
1337
1338 return hr;
1339 }
1340
1341
1342 /********************************************************************
1343 XmlSaveDocument -
1344
1345 *********************************************************************/
1346 extern "C" HRESULT DAPI XmlSaveDocument(
1347 __in IXMLDOMDocument* pixdDocument,
1348 __inout LPCWSTR wzPath
1349 )
1350 {
1351 HRESULT hr = S_OK;
1352
1353 // RELEASEME
1354 VARIANT varsDestPath;
1355
1356 ::VariantInit(&varsDestPath);
1357 varsDestPath.vt = VT_BSTR;
1358 varsDestPath.bstrVal = ::SysAllocString(wzPath);
1359 if (!varsDestPath.bstrVal)
1360 {
1361 hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
1362 }
1363 XmlExitOnFailure(hr, "failed to create BSTR");
1364
1365 hr = pixdDocument->save(varsDestPath);
1366 if (hr == S_FALSE)
1367 {
1368 hr = E_FAIL;
1369 }
1370 XmlExitOnFailure(hr, "failed save in WriteDocument");
1371
1372 LExit:
1373 ReleaseVariant(varsDestPath);
1374 return hr;
1375 }
1376
1377
1378 /********************************************************************
1379 XmlSaveDocumentToBuffer
1380
1381 *********************************************************************/
1382 extern "C" HRESULT DAPI XmlSaveDocumentToBuffer(
1383 __in IXMLDOMDocument* pixdDocument,
1384 __deref_out_bcount(*pcbDest) BYTE** ppbDest,
1385 __out DWORD* pcbDest
1386 )
1387 {
1388 HRESULT hr = S_OK;
1389 IStream* pStream = NULL;
1390 LARGE_INTEGER li = { };
1391 STATSTG statstg = { };
1392 BYTE* pbDest = NULL;
1393 ULONG cbRead = 0;
1394 VARIANT vtDestination;
1395
1396 ::VariantInit(&vtDestination);
1397
1398 // create stream
1399 hr = ::CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1400 XmlExitOnFailure(hr, "Failed to create stream.");
1401
1402 // write document to stream
1403 vtDestination.vt = VT_UNKNOWN;
1404 vtDestination.punkVal = (IUnknown*)pStream;
1405 hr = pixdDocument->save(vtDestination);
1406 XmlExitOnFailure(hr, "Failed to save document.");
1407
1408 // get stream size
1409 hr = pStream->Stat(&statstg, STATFLAG_NONAME);
1410 XmlExitOnFailure(hr, "Failed to get stream size.");
1411
1412 // allocate buffer
1413 pbDest = static_cast<BYTE*>(MemAlloc(statstg.cbSize.LowPart, TRUE));
1414 XmlExitOnNull(pbDest, hr, E_OUTOFMEMORY, "Failed to allocate destination buffer.");
1415
1416 // read data from stream
1417 li.QuadPart = 0;
1418 hr = pStream->Seek(li, STREAM_SEEK_SET, NULL);
1419 XmlExitOnFailure(hr, "Failed to seek stream.");
1420
1421 hr = pStream->Read(pbDest, statstg.cbSize.LowPart, &cbRead);
1422 if (cbRead < statstg.cbSize.LowPart)
1423 {
1424 hr = E_FAIL;
1425 }
1426 XmlExitOnFailure(hr, "Failed to read stream content to buffer.");
1427
1428 // return value
1429 *ppbDest = pbDest;
1430 pbDest = NULL;
1431 *pcbDest = statstg.cbSize.LowPart;
1432
1433 LExit:
1434 ReleaseObject(pStream);
1435 ReleaseMem(pbDest);
1436 return hr;
1437 }