diff options
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/xmlutil.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/xmlutil.cpp | 1332 |
1 files changed, 1332 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/xmlutil.cpp b/src/libs/dutil/WixToolset.DUtil/xmlutil.cpp new file mode 100644 index 00000000..0f1e611d --- /dev/null +++ b/src/libs/dutil/WixToolset.DUtil/xmlutil.cpp | |||
@@ -0,0 +1,1332 @@ | |||
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 | XmlGetAttributeLargeNumber | ||
797 | |||
798 | *********************************************************************/ | ||
799 | extern "C" HRESULT DAPI XmlGetAttributeLargeNumber( | ||
800 | __in IXMLDOMNode* pixnNode, | ||
801 | __in_z LPCWSTR pwzAttribute, | ||
802 | __out DWORD64* pdw64Value | ||
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 | LONGLONG ll = 0; | ||
814 | hr = StrStringToInt64(bstrValue, 0, &ll); | ||
815 | XmlExitOnFailure(hr, "Failed to treat attribute value as number."); | ||
816 | |||
817 | *pdw64Value = ll; | ||
818 | } | ||
819 | else | ||
820 | { | ||
821 | *pdw64Value = 0; | ||
822 | } | ||
823 | |||
824 | LExit: | ||
825 | ReleaseBSTR(bstrValue); | ||
826 | return hr; | ||
827 | } | ||
828 | |||
829 | |||
830 | /******************************************************************** | ||
831 | XmlGetNamedItem - | ||
832 | |||
833 | *********************************************************************/ | ||
834 | extern "C" HRESULT DAPI XmlGetNamedItem( | ||
835 | __in IXMLDOMNamedNodeMap *pixnmAttributes, | ||
836 | __in_opt LPCWSTR wzName, | ||
837 | __out IXMLDOMNode **ppixnNamedItem | ||
838 | ) | ||
839 | { | ||
840 | if (!pixnmAttributes || !ppixnNamedItem) | ||
841 | { | ||
842 | return E_INVALIDARG; | ||
843 | } | ||
844 | |||
845 | HRESULT hr = S_OK; | ||
846 | BSTR bstrName = ::SysAllocString(wzName); | ||
847 | XmlExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString"); | ||
848 | |||
849 | hr = pixnmAttributes->getNamedItem(bstrName, ppixnNamedItem); | ||
850 | |||
851 | LExit: | ||
852 | ReleaseBSTR(bstrName); | ||
853 | return hr; | ||
854 | } | ||
855 | |||
856 | |||
857 | /******************************************************************** | ||
858 | XmlSetText - | ||
859 | |||
860 | *********************************************************************/ | ||
861 | extern "C" HRESULT DAPI XmlSetText( | ||
862 | __in IXMLDOMNode *pixnNode, | ||
863 | __in_z LPCWSTR pwzText | ||
864 | ) | ||
865 | { | ||
866 | Assert(pixnNode && pwzText); | ||
867 | HRESULT hr = S_OK; | ||
868 | DOMNodeType dnType; | ||
869 | |||
870 | // RELEASEME | ||
871 | IXMLDOMDocument* pixdDocument = NULL; | ||
872 | IXMLDOMNodeList* pixnlNodeList = NULL; | ||
873 | IXMLDOMNode* pixnChildNode = NULL; | ||
874 | IXMLDOMText* pixtTextNode = NULL; | ||
875 | VARIANT varText; | ||
876 | |||
877 | ::VariantInit(&varText); | ||
878 | |||
879 | // find the text node | ||
880 | hr = pixnNode->get_childNodes(&pixnlNodeList); | ||
881 | XmlExitOnFailure(hr, "failed to get child nodes"); | ||
882 | |||
883 | while (S_OK == (hr = pixnlNodeList->nextNode(&pixnChildNode))) | ||
884 | { | ||
885 | hr = pixnChildNode->get_nodeType(&dnType); | ||
886 | XmlExitOnFailure(hr, "failed to get node type"); | ||
887 | |||
888 | if (NODE_TEXT == dnType) | ||
889 | break; | ||
890 | ReleaseNullObject(pixnChildNode); | ||
891 | } | ||
892 | if (S_FALSE == hr) | ||
893 | { | ||
894 | hr = S_OK; | ||
895 | } | ||
896 | |||
897 | if (pixnChildNode) | ||
898 | { | ||
899 | varText.vt = VT_BSTR; | ||
900 | varText.bstrVal = ::SysAllocString(pwzText); | ||
901 | if (!varText.bstrVal) | ||
902 | { | ||
903 | hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY); | ||
904 | } | ||
905 | XmlExitOnFailure(hr, "failed SysAllocString in XmlSetText"); | ||
906 | |||
907 | hr = pixnChildNode->put_nodeValue(varText); | ||
908 | XmlExitOnFailure(hr, "failed IXMLDOMNode::put_nodeValue"); | ||
909 | } | ||
910 | else | ||
911 | { | ||
912 | hr = pixnNode->get_ownerDocument(&pixdDocument); | ||
913 | if (hr == S_FALSE) | ||
914 | { | ||
915 | hr = E_FAIL; | ||
916 | } | ||
917 | XmlExitOnFailure(hr, "failed get_ownerDocument in XmlSetAttribute"); | ||
918 | |||
919 | hr = XmlCreateTextNode(pixdDocument, pwzText, &pixtTextNode); | ||
920 | XmlExitOnFailure(hr, "failed createTextNode in XmlSetText(%ls)", pwzText); | ||
921 | |||
922 | hr = pixnNode->appendChild(pixtTextNode, NULL); | ||
923 | XmlExitOnFailure(hr, "failed appendChild in XmlSetText(%ls)", pwzText); | ||
924 | } | ||
925 | |||
926 | hr = *pwzText ? S_OK : S_FALSE; | ||
927 | |||
928 | LExit: | ||
929 | ReleaseObject(pixnlNodeList); | ||
930 | ReleaseObject(pixnChildNode); | ||
931 | ReleaseObject(pixdDocument); | ||
932 | ReleaseObject(pixtTextNode); | ||
933 | ReleaseVariant(varText); | ||
934 | return hr; | ||
935 | } | ||
936 | |||
937 | |||
938 | /******************************************************************** | ||
939 | XmlSetTextNumber - | ||
940 | |||
941 | *********************************************************************/ | ||
942 | extern "C" HRESULT DAPI XmlSetTextNumber( | ||
943 | __in IXMLDOMNode *pixnNode, | ||
944 | __in DWORD dwValue | ||
945 | ) | ||
946 | { | ||
947 | HRESULT hr = S_OK; | ||
948 | WCHAR wzValue[12]; | ||
949 | |||
950 | hr = ::StringCchPrintfW(wzValue, countof(wzValue), L"%u", dwValue); | ||
951 | XmlExitOnFailure(hr, "Failed to format numeric value as string."); | ||
952 | |||
953 | hr = XmlSetText(pixnNode, wzValue); | ||
954 | |||
955 | LExit: | ||
956 | return hr; | ||
957 | } | ||
958 | |||
959 | |||
960 | /******************************************************************** | ||
961 | XmlCreateChild - | ||
962 | |||
963 | *********************************************************************/ | ||
964 | extern "C" HRESULT DAPI XmlCreateChild( | ||
965 | __in IXMLDOMNode* pixnParent, | ||
966 | __in_z LPCWSTR pwzElementType, | ||
967 | __out IXMLDOMNode** ppixnChild | ||
968 | ) | ||
969 | { | ||
970 | HRESULT hr = S_OK; | ||
971 | |||
972 | // RELEASEME | ||
973 | IXMLDOMDocument* pixdDocument = NULL; | ||
974 | IXMLDOMNode* pixnChild = NULL; | ||
975 | |||
976 | hr = pixnParent->get_ownerDocument(&pixdDocument); | ||
977 | if (hr == S_FALSE) | ||
978 | { | ||
979 | hr = E_FAIL; | ||
980 | } | ||
981 | XmlExitOnFailure(hr, "failed get_ownerDocument"); | ||
982 | |||
983 | hr = XmlCreateElement(pixdDocument, pwzElementType, (IXMLDOMElement**) &pixnChild); | ||
984 | if (hr == S_FALSE) | ||
985 | { | ||
986 | hr = E_FAIL; | ||
987 | } | ||
988 | XmlExitOnFailure(hr, "failed createElement"); | ||
989 | |||
990 | pixnParent->appendChild(pixnChild,NULL); | ||
991 | if (hr == S_FALSE) | ||
992 | { | ||
993 | hr = E_FAIL; | ||
994 | } | ||
995 | XmlExitOnFailure(hr, "failed appendChild"); | ||
996 | |||
997 | if (ppixnChild) | ||
998 | { | ||
999 | *ppixnChild = pixnChild; | ||
1000 | pixnChild = NULL; | ||
1001 | } | ||
1002 | |||
1003 | LExit: | ||
1004 | ReleaseObject(pixdDocument); | ||
1005 | ReleaseObject(pixnChild); | ||
1006 | return hr; | ||
1007 | } | ||
1008 | |||
1009 | /******************************************************************** | ||
1010 | XmlRemoveAttribute - | ||
1011 | |||
1012 | *********************************************************************/ | ||
1013 | extern "C" HRESULT DAPI XmlRemoveAttribute( | ||
1014 | __in IXMLDOMNode* pixnNode, | ||
1015 | __in_z LPCWSTR pwzAttribute | ||
1016 | ) | ||
1017 | { | ||
1018 | HRESULT hr = S_OK; | ||
1019 | |||
1020 | // RELEASEME | ||
1021 | IXMLDOMNamedNodeMap* pixnnmAttributes = NULL; | ||
1022 | BSTR bstrAttribute = ::SysAllocString(pwzAttribute); | ||
1023 | XmlExitOnNull(bstrAttribute, hr, E_OUTOFMEMORY, "failed to allocate bstr for attribute in XmlRemoveAttribute"); | ||
1024 | |||
1025 | hr = pixnNode->get_attributes(&pixnnmAttributes); | ||
1026 | XmlExitOnFailure(hr, "failed get_attributes in RemoveXmlAttribute(%ls)", pwzAttribute); | ||
1027 | |||
1028 | hr = pixnnmAttributes->removeNamedItem(bstrAttribute, NULL); | ||
1029 | XmlExitOnFailure(hr, "failed removeNamedItem in RemoveXmlAttribute(%ls)", pwzAttribute); | ||
1030 | |||
1031 | LExit: | ||
1032 | ReleaseObject(pixnnmAttributes); | ||
1033 | ReleaseBSTR(bstrAttribute); | ||
1034 | |||
1035 | return hr; | ||
1036 | } | ||
1037 | |||
1038 | |||
1039 | /******************************************************************** | ||
1040 | XmlSelectNodes - | ||
1041 | |||
1042 | *********************************************************************/ | ||
1043 | extern "C" HRESULT DAPI XmlSelectNodes( | ||
1044 | __in IXMLDOMNode* pixnParent, | ||
1045 | __in_z LPCWSTR wzXPath, | ||
1046 | __out IXMLDOMNodeList **ppixnlChildren | ||
1047 | ) | ||
1048 | { | ||
1049 | HRESULT hr = S_OK; | ||
1050 | |||
1051 | BSTR bstrXPath = NULL; | ||
1052 | |||
1053 | XmlExitOnNull(pixnParent, hr, E_UNEXPECTED, "pixnParent parameter was null in XmlSelectNodes"); | ||
1054 | XmlExitOnNull(ppixnlChildren, hr, E_UNEXPECTED, "ppixnChild parameter was null in XmlSelectNodes"); | ||
1055 | |||
1056 | bstrXPath = ::SysAllocString(wzXPath ? wzXPath : L""); | ||
1057 | XmlExitOnNull(bstrXPath, hr, E_OUTOFMEMORY, "failed to allocate bstr for XPath expression in XmlSelectNodes"); | ||
1058 | |||
1059 | hr = pixnParent->selectNodes(bstrXPath, ppixnlChildren); | ||
1060 | |||
1061 | LExit: | ||
1062 | ReleaseBSTR(bstrXPath); | ||
1063 | return hr; | ||
1064 | } | ||
1065 | |||
1066 | |||
1067 | /******************************************************************** | ||
1068 | XmlNextAttribute - returns the next attribute in a node list | ||
1069 | |||
1070 | NOTE: pbstrAttribute is optional | ||
1071 | returns S_OK if found an element | ||
1072 | returns S_FALSE if no element found | ||
1073 | returns E_* if something went wrong | ||
1074 | ********************************************************************/ | ||
1075 | extern "C" HRESULT DAPI XmlNextAttribute( | ||
1076 | __in IXMLDOMNamedNodeMap* pixnnm, | ||
1077 | __out IXMLDOMNode** pixnAttribute, | ||
1078 | __deref_opt_out_z_opt BSTR* pbstrAttribute | ||
1079 | ) | ||
1080 | { | ||
1081 | Assert(pixnnm && pixnAttribute); | ||
1082 | |||
1083 | HRESULT hr = S_OK; | ||
1084 | IXMLDOMNode* pixn = NULL; | ||
1085 | DOMNodeType nt; | ||
1086 | |||
1087 | // null out the return values | ||
1088 | *pixnAttribute = NULL; | ||
1089 | if (pbstrAttribute) | ||
1090 | { | ||
1091 | *pbstrAttribute = NULL; | ||
1092 | } | ||
1093 | |||
1094 | hr = pixnnm->nextNode(&pixn); | ||
1095 | XmlExitOnFailure(hr, "Failed to get next attribute."); | ||
1096 | |||
1097 | if (S_OK == hr) | ||
1098 | { | ||
1099 | hr = pixn->get_nodeType(&nt); | ||
1100 | XmlExitOnFailure(hr, "failed to get node type"); | ||
1101 | |||
1102 | if (NODE_ATTRIBUTE != nt) | ||
1103 | { | ||
1104 | hr = E_UNEXPECTED; | ||
1105 | XmlExitOnFailure(hr, "Failed to get expected node type back: attribute"); | ||
1106 | } | ||
1107 | |||
1108 | // if the caller asked for the attribute name | ||
1109 | if (pbstrAttribute) | ||
1110 | { | ||
1111 | hr = pixn->get_baseName(pbstrAttribute); | ||
1112 | XmlExitOnFailure(hr, "failed to get attribute name"); | ||
1113 | } | ||
1114 | |||
1115 | *pixnAttribute = pixn; | ||
1116 | pixn = NULL; | ||
1117 | } | ||
1118 | |||
1119 | LExit: | ||
1120 | ReleaseObject(pixn); | ||
1121 | return hr; | ||
1122 | } | ||
1123 | |||
1124 | |||
1125 | /******************************************************************** | ||
1126 | XmlNextElement - returns the next element in a node list | ||
1127 | |||
1128 | NOTE: pbstrElement is optional | ||
1129 | returns S_OK if found an element | ||
1130 | returns S_FALSE if no element found | ||
1131 | returns E_* if something went wrong | ||
1132 | ********************************************************************/ | ||
1133 | extern "C" HRESULT DAPI XmlNextElement( | ||
1134 | __in IXMLDOMNodeList* pixnl, | ||
1135 | __out IXMLDOMNode** pixnElement, | ||
1136 | __deref_opt_out_z_opt BSTR* pbstrElement | ||
1137 | ) | ||
1138 | { | ||
1139 | Assert(pixnl && pixnElement); | ||
1140 | |||
1141 | HRESULT hr = S_OK; | ||
1142 | IXMLDOMNode* pixn = NULL; | ||
1143 | DOMNodeType nt; | ||
1144 | |||
1145 | // null out the return values | ||
1146 | *pixnElement = NULL; | ||
1147 | if (pbstrElement) | ||
1148 | { | ||
1149 | *pbstrElement = NULL; | ||
1150 | } | ||
1151 | |||
1152 | // | ||
1153 | // find the next element in the list | ||
1154 | // | ||
1155 | while (S_OK == (hr = pixnl->nextNode(&pixn))) | ||
1156 | { | ||
1157 | hr = pixn->get_nodeType(&nt); | ||
1158 | XmlExitOnFailure(hr, "failed to get node type"); | ||
1159 | |||
1160 | if (NODE_ELEMENT == nt) | ||
1161 | break; | ||
1162 | |||
1163 | ReleaseNullObject(pixn); | ||
1164 | } | ||
1165 | XmlExitOnFailure(hr, "failed to get next element"); | ||
1166 | |||
1167 | // if we have a node and the caller asked for the element name | ||
1168 | if (pixn && pbstrElement) | ||
1169 | { | ||
1170 | hr = pixn->get_baseName(pbstrElement); | ||
1171 | XmlExitOnFailure(hr, "failed to get element name"); | ||
1172 | } | ||
1173 | |||
1174 | *pixnElement = pixn; | ||
1175 | pixn = NULL; | ||
1176 | |||
1177 | hr = *pixnElement ? S_OK : S_FALSE; | ||
1178 | LExit: | ||
1179 | ReleaseObject(pixn); | ||
1180 | return hr; | ||
1181 | } | ||
1182 | |||
1183 | |||
1184 | /******************************************************************** | ||
1185 | XmlRemoveChildren - | ||
1186 | |||
1187 | *********************************************************************/ | ||
1188 | extern "C" HRESULT DAPI XmlRemoveChildren( | ||
1189 | __in IXMLDOMNode* pixnSource, | ||
1190 | __in_z LPCWSTR pwzXPath | ||
1191 | ) | ||
1192 | { | ||
1193 | HRESULT hr = S_OK; | ||
1194 | |||
1195 | // RELEASEME | ||
1196 | IXMLDOMNodeList* pixnlNodeList = NULL; | ||
1197 | IXMLDOMNode* pixnNode = NULL; | ||
1198 | IXMLDOMNode* pixnRemoveChild = NULL; | ||
1199 | |||
1200 | if (pwzXPath) | ||
1201 | { | ||
1202 | hr = XmlSelectNodes(pixnSource, pwzXPath, &pixnlNodeList); | ||
1203 | XmlExitOnFailure(hr, "failed XmlSelectNodes"); | ||
1204 | } | ||
1205 | else | ||
1206 | { | ||
1207 | hr = pixnSource->get_childNodes(&pixnlNodeList); | ||
1208 | XmlExitOnFailure(hr, "failed childNodes"); | ||
1209 | } | ||
1210 | if (S_FALSE == hr) | ||
1211 | { | ||
1212 | ExitFunction(); | ||
1213 | } | ||
1214 | |||
1215 | while (S_OK == (hr = pixnlNodeList->nextNode(&pixnNode))) | ||
1216 | { | ||
1217 | hr = pixnSource->removeChild(pixnNode, &pixnRemoveChild); | ||
1218 | XmlExitOnFailure(hr, "failed removeChild"); | ||
1219 | |||
1220 | ReleaseNullObject(pixnRemoveChild); | ||
1221 | ReleaseNullObject(pixnNode); | ||
1222 | } | ||
1223 | if (S_FALSE == hr) | ||
1224 | { | ||
1225 | hr = S_OK; | ||
1226 | } | ||
1227 | |||
1228 | LExit: | ||
1229 | ReleaseObject(pixnlNodeList); | ||
1230 | ReleaseObject(pixnNode); | ||
1231 | ReleaseObject(pixnRemoveChild); | ||
1232 | |||
1233 | return hr; | ||
1234 | } | ||
1235 | |||
1236 | |||
1237 | /******************************************************************** | ||
1238 | XmlSaveDocument - | ||
1239 | |||
1240 | *********************************************************************/ | ||
1241 | extern "C" HRESULT DAPI XmlSaveDocument( | ||
1242 | __in IXMLDOMDocument* pixdDocument, | ||
1243 | __inout LPCWSTR wzPath | ||
1244 | ) | ||
1245 | { | ||
1246 | HRESULT hr = S_OK; | ||
1247 | |||
1248 | // RELEASEME | ||
1249 | VARIANT varsDestPath; | ||
1250 | |||
1251 | ::VariantInit(&varsDestPath); | ||
1252 | varsDestPath.vt = VT_BSTR; | ||
1253 | varsDestPath.bstrVal = ::SysAllocString(wzPath); | ||
1254 | if (!varsDestPath.bstrVal) | ||
1255 | { | ||
1256 | hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY); | ||
1257 | } | ||
1258 | XmlExitOnFailure(hr, "failed to create BSTR"); | ||
1259 | |||
1260 | hr = pixdDocument->save(varsDestPath); | ||
1261 | if (hr == S_FALSE) | ||
1262 | { | ||
1263 | hr = E_FAIL; | ||
1264 | } | ||
1265 | XmlExitOnFailure(hr, "failed save in WriteDocument"); | ||
1266 | |||
1267 | LExit: | ||
1268 | ReleaseVariant(varsDestPath); | ||
1269 | return hr; | ||
1270 | } | ||
1271 | |||
1272 | |||
1273 | /******************************************************************** | ||
1274 | XmlSaveDocumentToBuffer | ||
1275 | |||
1276 | *********************************************************************/ | ||
1277 | extern "C" HRESULT DAPI XmlSaveDocumentToBuffer( | ||
1278 | __in IXMLDOMDocument* pixdDocument, | ||
1279 | __deref_out_bcount(*pcbDest) BYTE** ppbDest, | ||
1280 | __out DWORD* pcbDest | ||
1281 | ) | ||
1282 | { | ||
1283 | HRESULT hr = S_OK; | ||
1284 | IStream* pStream = NULL; | ||
1285 | LARGE_INTEGER li = { }; | ||
1286 | STATSTG statstg = { }; | ||
1287 | BYTE* pbDest = NULL; | ||
1288 | ULONG cbRead = 0; | ||
1289 | VARIANT vtDestination; | ||
1290 | |||
1291 | ::VariantInit(&vtDestination); | ||
1292 | |||
1293 | // create stream | ||
1294 | hr = ::CreateStreamOnHGlobal(NULL, TRUE, &pStream); | ||
1295 | XmlExitOnFailure(hr, "Failed to create stream."); | ||
1296 | |||
1297 | // write document to stream | ||
1298 | vtDestination.vt = VT_UNKNOWN; | ||
1299 | vtDestination.punkVal = (IUnknown*)pStream; | ||
1300 | hr = pixdDocument->save(vtDestination); | ||
1301 | XmlExitOnFailure(hr, "Failed to save document."); | ||
1302 | |||
1303 | // get stream size | ||
1304 | hr = pStream->Stat(&statstg, STATFLAG_NONAME); | ||
1305 | XmlExitOnFailure(hr, "Failed to get stream size."); | ||
1306 | |||
1307 | // allocate buffer | ||
1308 | pbDest = static_cast<BYTE*>(MemAlloc(statstg.cbSize.LowPart, TRUE)); | ||
1309 | XmlExitOnNull(pbDest, hr, E_OUTOFMEMORY, "Failed to allocate destination buffer."); | ||
1310 | |||
1311 | // read data from stream | ||
1312 | li.QuadPart = 0; | ||
1313 | hr = pStream->Seek(li, STREAM_SEEK_SET, NULL); | ||
1314 | XmlExitOnFailure(hr, "Failed to seek stream."); | ||
1315 | |||
1316 | hr = pStream->Read(pbDest, statstg.cbSize.LowPart, &cbRead); | ||
1317 | if (cbRead < statstg.cbSize.LowPart) | ||
1318 | { | ||
1319 | hr = E_FAIL; | ||
1320 | } | ||
1321 | XmlExitOnFailure(hr, "Failed to read stream content to buffer."); | ||
1322 | |||
1323 | // return value | ||
1324 | *ppbDest = pbDest; | ||
1325 | pbDest = NULL; | ||
1326 | *pcbDest = statstg.cbSize.LowPart; | ||
1327 | |||
1328 | LExit: | ||
1329 | ReleaseObject(pStream); | ||
1330 | ReleaseMem(pbDest); | ||
1331 | return hr; | ||
1332 | } | ||