2 * XMLLite IXmlWriter tests
4 * Copyright 2011 (C) Alistair Leslie-Hughes
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/heap.h"
31 #include "wine/test.h"
34 DEFINE_GUID(IID_IXmlWriterOutput
, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
36 static const WCHAR aW
[] = {'a',0};
38 #define EXPECT_REF(obj, ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
39 static void _expect_ref(IUnknown
*obj
, ULONG ref
, int line
)
43 refcount
= IUnknown_Release(obj
);
44 ok_(__FILE__
, line
)(refcount
== ref
, "expected refcount %d, got %d\n", ref
, refcount
);
47 static void check_output_raw(IStream
*stream
, const void *expected
, SIZE_T size
, int line
)
54 hr
= GetHGlobalFromStream(stream
, &hglobal
);
55 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get the stream handle, hr %#x.\n", hr
);
57 content_size
= GlobalSize(hglobal
);
58 ok_(__FILE__
, line
)(size
== content_size
, "Unexpected test output size %ld.\n", content_size
);
59 ptr
= GlobalLock(hglobal
);
60 if (size
<= content_size
)
61 ok_(__FILE__
, line
)(!memcmp(expected
, ptr
, size
), "Unexpected output content.\n");
62 if (size
!= content_size
&& *ptr
== 0xfeff)
63 ok_(__FILE__
, line
)(0, "Content: %s.\n", wine_dbgstr_wn(ptr
, content_size
/ sizeof(WCHAR
)));
65 GlobalUnlock(hglobal
);
68 static void check_output(IStream
*stream
, const char *expected
, BOOL todo
, int line
)
70 int len
= strlen(expected
), size
;
75 hr
= GetHGlobalFromStream(stream
, &hglobal
);
76 ok_(__FILE__
, line
)(hr
== S_OK
, "got 0x%08x\n", hr
);
78 size
= GlobalSize(hglobal
);
79 ptr
= GlobalLock(hglobal
);
84 ok_(__FILE__
, line
)(0, "data size mismatch, expected %u, got %u\n", len
, size
);
85 ok_(__FILE__
, line
)(0, "got |%s|, expected |%s|\n", ptr
, expected
);
88 ok_(__FILE__
, line
)(!strncmp(ptr
, expected
, len
), "got |%s|, expected |%s|\n", ptr
, expected
);
90 GlobalUnlock(hglobal
);
92 #define CHECK_OUTPUT(stream, expected) check_output(stream, expected, FALSE, __LINE__)
93 #define CHECK_OUTPUT_TODO(stream, expected) check_output(stream, expected, TRUE, __LINE__)
94 #define CHECK_OUTPUT_RAW(stream, expected, size) check_output_raw(stream, expected, size, __LINE__)
96 static WCHAR
*strdupAtoW(const char *str
)
101 if (!str
) return ret
;
102 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
103 ret
= heap_alloc(len
* sizeof(WCHAR
));
105 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
109 static void writer_set_property(IXmlWriter
*writer
, XmlWriterProperty property
)
113 hr
= IXmlWriter_SetProperty(writer
, property
, TRUE
);
114 ok(hr
== S_OK
, "Failed to set writer property, hr %#x.\n", hr
);
117 /* used to test all Write* methods for consistent error state */
118 static void check_writer_state(IXmlWriter
*writer
, HRESULT exp_hr
)
120 static const WCHAR aW
[] = {'a',0};
123 /* FIXME: add WriteAttributes */
125 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, aW
, NULL
, aW
);
126 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
128 hr
= IXmlWriter_WriteCData(writer
, aW
);
129 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
131 hr
= IXmlWriter_WriteCharEntity(writer
, aW
[0]);
132 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
134 hr
= IXmlWriter_WriteChars(writer
, aW
, 1);
135 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
137 hr
= IXmlWriter_WriteComment(writer
, aW
);
138 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
140 hr
= IXmlWriter_WriteDocType(writer
, aW
, NULL
, NULL
, NULL
);
141 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
143 hr
= IXmlWriter_WriteElementString(writer
, NULL
, aW
, NULL
, aW
);
144 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
146 hr
= IXmlWriter_WriteEndDocument(writer
);
147 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
149 hr
= IXmlWriter_WriteEndElement(writer
);
150 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
152 hr
= IXmlWriter_WriteEntityRef(writer
, aW
);
153 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
155 hr
= IXmlWriter_WriteFullEndElement(writer
);
156 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
158 hr
= IXmlWriter_WriteName(writer
, aW
);
159 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
161 hr
= IXmlWriter_WriteNmToken(writer
, aW
);
162 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
164 /* FIXME: add WriteNode */
165 /* FIXME: add WriteNodeShallow */
167 hr
= IXmlWriter_WriteProcessingInstruction(writer
, aW
, aW
);
168 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
170 hr
= IXmlWriter_WriteQualifiedName(writer
, aW
, NULL
);
171 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
173 hr
= IXmlWriter_WriteRaw(writer
, aW
);
174 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
176 hr
= IXmlWriter_WriteRawChars(writer
, aW
, 1);
177 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
179 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
180 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
182 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
183 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
185 hr
= IXmlWriter_WriteString(writer
, aW
);
186 ok(hr
== exp_hr
, "got 0x%08x, expected 0x%08x\n", hr
, exp_hr
);
188 /* FIXME: add WriteSurrogateCharEntity */
189 /* FIXME: add WriteWhitespace */
192 static IStream
*writer_set_output(IXmlWriter
*writer
)
197 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
198 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
200 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)stream
);
201 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
206 static HRESULT WINAPI
testoutput_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
208 if (IsEqualGUID(riid
, &IID_IUnknown
)) {
213 ok(0, "unknown riid=%s\n", wine_dbgstr_guid(riid
));
214 return E_NOINTERFACE
;
218 static ULONG WINAPI
testoutput_AddRef(IUnknown
*iface
)
223 static ULONG WINAPI
testoutput_Release(IUnknown
*iface
)
228 static const IUnknownVtbl testoutputvtbl
= {
229 testoutput_QueryInterface
,
234 static IUnknown testoutput
= { &testoutputvtbl
};
236 static HRESULT WINAPI
teststream_QueryInterface(ISequentialStream
*iface
, REFIID riid
, void **obj
)
238 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_ISequentialStream
))
245 return E_NOINTERFACE
;
248 static ULONG WINAPI
teststream_AddRef(ISequentialStream
*iface
)
253 static ULONG WINAPI
teststream_Release(ISequentialStream
*iface
)
258 static HRESULT WINAPI
teststream_Read(ISequentialStream
*iface
, void *pv
, ULONG cb
, ULONG
*pread
)
260 ok(0, "unexpected call\n");
264 static ULONG g_write_len
;
265 static HRESULT WINAPI
teststream_Write(ISequentialStream
*iface
, const void *pv
, ULONG cb
, ULONG
*written
)
272 static const ISequentialStreamVtbl teststreamvtbl
=
274 teststream_QueryInterface
,
281 static ISequentialStream teststream
= { &teststreamvtbl
};
283 static void test_writer_create(void)
293 CreateXmlWriter(&IID_IXmlWriter
, NULL
, NULL
);
294 CreateXmlWriter(NULL
, (void**)&writer
, NULL
);
297 hr
= CreateXmlWriter(&IID_IStream
, (void **)&unk
, NULL
);
298 ok(hr
== E_NOINTERFACE
, "got %08x\n", hr
);
300 hr
= CreateXmlWriter(&IID_IUnknown
, (void **)&unk
, NULL
);
301 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
302 hr
= IUnknown_QueryInterface(unk
, &IID_IXmlWriter
, (void **)&writer
);
303 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
304 ok(unk
== (IUnknown
*)writer
, "unexpected interface pointer\n");
305 IUnknown_Release(unk
);
306 IXmlWriter_Release(writer
);
308 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
309 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
311 /* check default properties values */
313 hr
= IXmlWriter_GetProperty(writer
, XmlWriterProperty_ByteOrderMark
, &value
);
314 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
315 ok(value
== TRUE
, "got %ld\n", value
);
318 hr
= IXmlWriter_GetProperty(writer
, XmlWriterProperty_Indent
, &value
);
319 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
320 ok(value
== FALSE
, "got %ld\n", value
);
323 hr
= IXmlWriter_GetProperty(writer
, XmlWriterProperty_OmitXmlDeclaration
, &value
);
324 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
325 ok(value
== FALSE
, "got %ld\n", value
);
327 value
= XmlConformanceLevel_Auto
;
328 hr
= IXmlWriter_GetProperty(writer
, XmlWriterProperty_ConformanceLevel
, &value
);
329 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
330 ok(value
== XmlConformanceLevel_Document
, "got %ld\n", value
);
332 IXmlWriter_Release(writer
);
335 static void test_invalid_output_encoding(IXmlWriter
*writer
, IUnknown
*output
)
339 hr
= IXmlWriter_SetOutput(writer
, output
);
340 ok(hr
== S_OK
, "Failed to set output, hr %#x.\n", hr
);
342 /* TODO: WriteAttributes */
344 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, aW
, NULL
, aW
);
345 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
347 hr
= IXmlWriter_WriteCData(writer
, aW
);
348 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
350 hr
= IXmlWriter_WriteCharEntity(writer
, 0x100);
351 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
353 hr
= IXmlWriter_WriteChars(writer
, aW
, 1);
354 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
356 hr
= IXmlWriter_WriteComment(writer
, aW
);
357 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
359 hr
= IXmlWriter_WriteDocType(writer
, aW
, NULL
, NULL
, NULL
);
360 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
362 hr
= IXmlWriter_WriteElementString(writer
, NULL
, aW
, NULL
, NULL
);
363 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
365 hr
= IXmlWriter_WriteEndDocument(writer
);
366 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
368 hr
= IXmlWriter_WriteEndElement(writer
);
369 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
371 hr
= IXmlWriter_WriteEntityRef(writer
, aW
);
372 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
374 hr
= IXmlWriter_WriteFullEndElement(writer
);
375 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
377 hr
= IXmlWriter_WriteName(writer
, aW
);
378 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
380 hr
= IXmlWriter_WriteNmToken(writer
, aW
);
381 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
383 /* TODO: WriteNode */
384 /* TODO: WriteNodeShallow */
386 hr
= IXmlWriter_WriteProcessingInstruction(writer
, aW
, aW
);
387 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
389 hr
= IXmlWriter_WriteQualifiedName(writer
, aW
, NULL
);
390 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
392 hr
= IXmlWriter_WriteRaw(writer
, aW
);
393 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
395 hr
= IXmlWriter_WriteRawChars(writer
, aW
, 1);
396 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
398 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
399 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
401 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
402 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
404 hr
= IXmlWriter_WriteString(writer
, aW
);
405 ok(hr
== MX_E_ENCODING
, "Unexpected hr %#x.\n", hr
);
407 /* TODO: WriteSurrogateCharEntity */
408 /* ًُُTODO: WriteWhitespace */
410 hr
= IXmlWriter_Flush(writer
);
411 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
414 static void test_writeroutput(void)
416 static const WCHAR utf16W
[] = {'u','t','f','-','1','6',0};
417 static const WCHAR usasciiW
[] = {'u','s','-','a','s','c','i','i',0};
418 static const WCHAR dummyW
[] = {'d','u','m','m','y',0};
419 static const WCHAR utf16_outputW
[] = {0xfeff,'<','a'};
420 IXmlWriterOutput
*output
;
427 hr
= CreateXmlWriterOutputWithEncodingName(&testoutput
, NULL
, NULL
, &output
);
428 ok(hr
== S_OK
, "got %08x\n", hr
);
429 EXPECT_REF(output
, 1);
430 IUnknown_Release(output
);
432 hr
= CreateXmlWriterOutputWithEncodingName(&testoutput
, NULL
, utf16W
, &output
);
433 ok(hr
== S_OK
, "got %08x\n", hr
);
435 hr
= IUnknown_QueryInterface(output
, &IID_IXmlWriterOutput
, (void**)&unk
);
436 ok(hr
== S_OK
, "got %08x\n", hr
);
438 ok(unk
!= NULL
&& unk
!= output
, "got %p, output %p\n", unk
, output
);
439 EXPECT_REF(output
, 2);
440 /* releasing 'unk' crashes on native */
441 IUnknown_Release(output
);
442 EXPECT_REF(output
, 1);
443 IUnknown_Release(output
);
446 hr
= CreateXmlWriterOutputWithEncodingCodePage(&testoutput
, NULL
, ~0u, &output
);
447 ok(hr
== S_OK
, "got %08x\n", hr
);
448 IUnknown_Release(output
);
450 hr
= CreateXmlWriterOutputWithEncodingCodePage(&testoutput
, NULL
, CP_UTF8
, &output
);
451 ok(hr
== S_OK
, "got %08x\n", hr
);
453 hr
= IUnknown_QueryInterface(output
, &IID_IXmlWriterOutput
, (void**)&unk
);
454 ok(hr
== S_OK
, "got %08x\n", hr
);
455 ok(unk
!= NULL
, "got %p\n", unk
);
456 /* releasing 'unk' crashes on native */
457 IUnknown_Release(output
);
458 IUnknown_Release(output
);
460 /* create with us-ascii */
462 hr
= CreateXmlWriterOutputWithEncodingName(&testoutput
, NULL
, usasciiW
, &output
);
463 ok(hr
== S_OK
, "got %08x\n", hr
);
464 IUnknown_Release(output
);
466 /* Output with codepage 1200. */
467 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void **)&writer
, NULL
);
468 ok(hr
== S_OK
, "Failed to create writer, hr %#x.\n", hr
);
470 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
471 ok(hr
== S_OK
, "Failed to create stream, hr %#x.\n", hr
);
473 hr
= CreateXmlWriterOutputWithEncodingCodePage((IUnknown
*)stream
, NULL
, 1200, &output
);
474 ok(hr
== S_OK
, "Failed to create writer output, hr %#x.\n", hr
);
476 hr
= IXmlWriter_SetOutput(writer
, output
);
477 ok(hr
== S_OK
, "Failed to set writer output, hr %#x.\n", hr
);
479 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
480 ok(hr
== S_OK
, "Write failed, hr %#x.\n", hr
);
482 hr
= IXmlWriter_Flush(writer
);
483 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
485 CHECK_OUTPUT_RAW(stream
, utf16_outputW
, sizeof(utf16_outputW
));
487 IStream_Release(stream
);
488 IUnknown_Release(output
);
490 /* Create output with meaningless code page value. */
491 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
492 ok(hr
== S_OK
, "Failed to create stream, hr %#x.\n", hr
);
495 hr
= CreateXmlWriterOutputWithEncodingCodePage((IUnknown
*)stream
, NULL
, ~0u, &output
);
496 ok(hr
== S_OK
, "Failed to create writer output, hr %#x.\n", hr
);
498 test_invalid_output_encoding(writer
, output
);
499 CHECK_OUTPUT(stream
, "");
501 IStream_Release(stream
);
502 IUnknown_Release(output
);
504 /* Same, with invalid encoding name. */
505 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
506 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
509 hr
= CreateXmlWriterOutputWithEncodingName((IUnknown
*)stream
, NULL
, dummyW
, &output
);
510 ok(hr
== S_OK
, "got %08x\n", hr
);
512 test_invalid_output_encoding(writer
, output
);
513 CHECK_OUTPUT(stream
, "");
515 IStream_Release(stream
);
516 IUnknown_Release(output
);
518 IXmlWriter_Release(writer
);
521 static void test_writestartdocument(void)
523 static const char fullprolog
[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
524 static const char *prologversion2
= "<?xml version=\"1.0\" encoding=\"uS-asCii\"?>";
525 static const char prologversion
[] = "<?xml version=\"1.0\"?>";
526 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
527 static const WCHAR usasciiW
[] = {'u','S','-','a','s','C','i','i',0};
528 static const WCHAR xmlW
[] = {'x','m','l',0};
529 IXmlWriterOutput
*output
;
534 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
535 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
538 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
539 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
541 hr
= IXmlWriter_WriteProcessingInstruction(writer
, xmlW
, versionW
);
542 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
544 hr
= IXmlWriter_Flush(writer
);
545 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
547 stream
= writer_set_output(writer
);
549 /* nothing written yet */
550 hr
= IXmlWriter_Flush(writer
);
551 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
553 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
554 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
556 hr
= IXmlWriter_Flush(writer
);
557 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
559 CHECK_OUTPUT(stream
, fullprolog
);
562 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
563 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
564 IStream_Release(stream
);
566 /* now add PI manually, and try to start a document */
567 stream
= writer_set_output(writer
);
569 hr
= IXmlWriter_WriteProcessingInstruction(writer
, xmlW
, versionW
);
570 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
572 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
573 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
575 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
576 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
578 /* another attempt to add 'xml' PI */
579 hr
= IXmlWriter_WriteProcessingInstruction(writer
, xmlW
, versionW
);
580 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
582 hr
= IXmlWriter_Flush(writer
);
583 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
585 CHECK_OUTPUT(stream
, prologversion
);
587 IStream_Release(stream
);
588 IXmlWriter_Release(writer
);
590 /* create with us-ascii */
591 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
592 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
595 hr
= CreateXmlWriterOutputWithEncodingName((IUnknown
*)stream
, NULL
, usasciiW
, &output
);
596 ok(hr
== S_OK
, "got %08x\n", hr
);
598 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void **)&writer
, NULL
);
599 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
601 hr
= IXmlWriter_SetOutput(writer
, output
);
602 ok(hr
== S_OK
, "got %08x\n", hr
);
604 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
605 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
607 hr
= IXmlWriter_Flush(writer
);
608 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
610 CHECK_OUTPUT(stream
, prologversion2
);
612 IStream_Release(stream
);
613 IXmlWriter_Release(writer
);
614 IUnknown_Release(output
);
617 static void test_flush(void)
622 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
623 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
625 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)&teststream
);
626 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
628 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
629 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
632 hr
= IXmlWriter_Flush(writer
);
633 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
634 ok(g_write_len
> 0, "got %d\n", g_write_len
);
637 hr
= IXmlWriter_Flush(writer
);
638 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
639 ok(g_write_len
== 0, "got %d\n", g_write_len
);
641 /* Release() flushes too */
643 IXmlWriter_Release(writer
);
644 ok(g_write_len
== 0, "got %d\n", g_write_len
);
647 static void test_omitxmldeclaration(void)
649 static const char prologversion
[] = "<?xml version=\"1.0\"?>";
650 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
651 static const WCHAR xmlW
[] = {'x','m','l',0};
658 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
659 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
661 stream
= writer_set_output(writer
);
663 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
665 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
666 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
668 hr
= IXmlWriter_Flush(writer
);
669 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
671 hr
= GetHGlobalFromStream(stream
, &hglobal
);
672 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
674 ptr
= GlobalLock(hglobal
);
675 ok(!ptr
, "got %p\n", ptr
);
676 GlobalUnlock(hglobal
);
679 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
680 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
682 IStream_Release(stream
);
684 /* now add PI manually, and try to start a document */
685 stream
= writer_set_output(writer
);
687 hr
= IXmlWriter_WriteProcessingInstruction(writer
, xmlW
, versionW
);
688 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
690 hr
= IXmlWriter_Flush(writer
);
691 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
693 CHECK_OUTPUT(stream
, prologversion
);
695 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
696 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
698 hr
= IXmlWriter_Flush(writer
);
699 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
701 CHECK_OUTPUT(stream
, prologversion
);
703 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
704 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
706 hr
= IXmlWriter_Flush(writer
);
707 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
709 CHECK_OUTPUT(stream
, prologversion
);
711 /* another attempt to add 'xml' PI */
712 hr
= IXmlWriter_WriteProcessingInstruction(writer
, xmlW
, versionW
);
713 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
715 hr
= IXmlWriter_Flush(writer
);
716 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
718 IStream_Release(stream
);
719 IXmlWriter_Release(writer
);
722 static void test_bom(void)
724 static const WCHAR piW
[] = {0xfeff,'<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>'};
725 static const WCHAR aopenW
[] = {0xfeff,'<','a'};
726 static const WCHAR afullW
[] = {0xfeff,'<','a',' ','/','>'};
727 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
728 static const WCHAR utf16W
[] = {'u','t','f','-','1','6',0};
729 static const WCHAR xmlW
[] = {'x','m','l',0};
730 static const WCHAR bomW
[] = {0xfeff};
731 IXmlWriterOutput
*output
;
737 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
738 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
740 hr
= CreateXmlWriterOutputWithEncodingName((IUnknown
*)stream
, NULL
, utf16W
, &output
);
741 ok(hr
== S_OK
, "got %08x\n", hr
);
743 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
744 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
746 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
748 hr
= IXmlWriter_SetOutput(writer
, output
);
749 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
751 /* BOM is on by default */
752 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
753 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
755 hr
= IXmlWriter_Flush(writer
);
756 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
758 CHECK_OUTPUT_RAW(stream
, bomW
, sizeof(bomW
));
760 IStream_Release(stream
);
761 IUnknown_Release(output
);
764 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
765 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
767 hr
= CreateXmlWriterOutputWithEncodingName((IUnknown
*)stream
, NULL
, utf16W
, &output
);
768 ok(hr
== S_OK
, "got %08x\n", hr
);
770 hr
= IXmlWriter_SetOutput(writer
, output
);
771 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
773 hr
= IXmlWriter_WriteProcessingInstruction(writer
, xmlW
, versionW
);
774 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
776 hr
= IXmlWriter_Flush(writer
);
777 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
779 CHECK_OUTPUT_RAW(stream
, piW
, sizeof(piW
));
781 IUnknown_Release(output
);
782 IStream_Release(stream
);
784 /* start with element */
785 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
786 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
788 hr
= CreateXmlWriterOutputWithEncodingName((IUnknown
*)stream
, NULL
, utf16W
, &output
);
789 ok(hr
== S_OK
, "got %08x\n", hr
);
791 hr
= IXmlWriter_SetOutput(writer
, output
);
792 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
794 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
795 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
797 hr
= IXmlWriter_Flush(writer
);
798 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
800 CHECK_OUTPUT_RAW(stream
, aopenW
, sizeof(aopenW
));
802 IUnknown_Release(output
);
803 IStream_Release(stream
);
805 /* WriteElementString */
806 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
807 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
809 hr
= CreateXmlWriterOutputWithEncodingName((IUnknown
*)stream
, NULL
, utf16W
, &output
);
810 ok(hr
== S_OK
, "got %08x\n", hr
);
812 hr
= IXmlWriter_SetOutput(writer
, output
);
813 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
815 writer_set_property(writer
, XmlWriterProperty_Indent
);
817 hr
= IXmlWriter_WriteElementString(writer
, NULL
, aW
, NULL
, NULL
);
818 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
820 hr
= IXmlWriter_Flush(writer
);
821 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
823 hr
= GetHGlobalFromStream(stream
, &hglobal
);
824 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
826 CHECK_OUTPUT_RAW(stream
, afullW
, sizeof(afullW
));
828 IUnknown_Release(output
);
829 IStream_Release(stream
);
831 IXmlWriter_Release(writer
);
834 static HRESULT
write_start_element(IXmlWriter
*writer
, const char *prefix
, const char *local
,
837 WCHAR
*prefixW
, *localW
, *uriW
;
840 prefixW
= strdupAtoW(prefix
);
841 localW
= strdupAtoW(local
);
842 uriW
= strdupAtoW(uri
);
844 hr
= IXmlWriter_WriteStartElement(writer
, prefixW
, localW
, uriW
);
853 static HRESULT
write_element_string(IXmlWriter
*writer
, const char *prefix
, const char *local
,
854 const char *uri
, const char *value
)
856 WCHAR
*prefixW
, *localW
, *uriW
, *valueW
;
859 prefixW
= strdupAtoW(prefix
);
860 localW
= strdupAtoW(local
);
861 uriW
= strdupAtoW(uri
);
862 valueW
= strdupAtoW(value
);
864 hr
= IXmlWriter_WriteElementString(writer
, prefixW
, localW
, uriW
, valueW
);
874 static HRESULT
write_string(IXmlWriter
*writer
, const char *str
)
879 strW
= strdupAtoW(str
);
881 hr
= IXmlWriter_WriteString(writer
, strW
);
888 static void test_WriteStartElement(void)
896 const char *output_partial
;
901 start_element_tests
[] =
903 { "prefix", "local", "uri", "<prefix:local xmlns:prefix=\"uri\" />", "<prefix:local" },
904 { NULL
, "local", "uri", "<local xmlns=\"uri\" />", "<local" },
905 { "", "local", "uri", "<local xmlns=\"uri\" />", "<local" },
906 { "", "local", "uri", "<local xmlns=\"uri\" />", "<local" },
908 { "prefix", NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
909 { NULL
, NULL
, "uri", NULL
, NULL
, E_INVALIDARG
},
910 { NULL
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
911 { NULL
, "prefix:local", "uri", NULL
, NULL
, WC_E_NAMECHARACTER
},
912 { "pre:fix", "local", "uri", NULL
, NULL
, WC_E_NAMECHARACTER
},
913 { NULL
, ":local", "uri", NULL
, NULL
, WC_E_NAMECHARACTER
},
914 { ":", "local", "uri", NULL
, NULL
, WC_E_NAMECHARACTER
},
915 { NULL
, "local", "http://www.w3.org/2000/xmlns/", NULL
, NULL
, WR_E_XMLNSPREFIXDECLARATION
},
916 { "prefix", "local", "http://www.w3.org/2000/xmlns/", NULL
, NULL
, WR_E_XMLNSURIDECLARATION
},
918 static const WCHAR aW
[] = {'a',0};
924 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
925 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
927 hr
= write_start_element(writer
, NULL
, "a", NULL
);
928 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
930 stream
= writer_set_output(writer
);
932 hr
= write_start_element(writer
, NULL
, "a", NULL
);
933 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
935 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
936 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
938 hr
= IXmlWriter_Flush(writer
);
939 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
941 CHECK_OUTPUT(stream
, "<a");
943 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
944 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
946 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, NULL
, NULL
);
947 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
949 hr
= IXmlWriter_WriteProcessingInstruction(writer
, aW
, aW
);
950 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
952 IStream_Release(stream
);
953 IXmlWriter_Release(writer
);
955 /* WriteElementString */
956 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
957 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
959 hr
= write_element_string(writer
, NULL
, "b", NULL
, "value");
960 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
962 stream
= writer_set_output(writer
);
964 hr
= write_start_element(writer
, "prefix", "a", "uri");
965 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
967 hr
= write_element_string(writer
, NULL
, "b", NULL
, "value");
968 ok(hr
== S_OK
, "Failed to write element string, hr %#x.\n", hr
);
970 hr
= write_element_string(writer
, NULL
, "c", NULL
, NULL
);
971 ok(hr
== S_OK
, "Failed to write element string, hr %#x.\n", hr
);
973 hr
= write_start_element(writer
, NULL
, "d", "uri");
974 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
976 hr
= write_start_element(writer
, "", "e", "uri");
977 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
979 hr
= write_start_element(writer
, "prefix2", "f", "uri");
980 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
982 hr
= IXmlWriter_Flush(writer
);
983 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
986 "<prefix:a xmlns:prefix=\"uri\">"
993 IStream_Release(stream
);
995 /* WriteStartElement */
996 for (i
= 0; i
< ARRAY_SIZE(start_element_tests
); ++i
)
998 stream
= writer_set_output(writer
);
1000 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1002 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1003 ok(hr
== S_OK
, "Failed to start document, hr %#x.\n", hr
);
1005 hr
= write_start_element(writer
, start_element_tests
[i
].prefix
, start_element_tests
[i
].local
,
1006 start_element_tests
[i
].uri
);
1007 ok(hr
== start_element_tests
[i
].hr
, "%u: unexpected hr %#x.\n", i
, hr
);
1009 if (SUCCEEDED(start_element_tests
[i
].hr
))
1011 hr
= IXmlWriter_Flush(writer
);
1012 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
1014 check_output(stream
, start_element_tests
[i
].output_partial
, start_element_tests
[i
].todo_partial
, __LINE__
);
1016 hr
= IXmlWriter_WriteEndDocument(writer
);
1017 ok(hr
== S_OK
, "Failed to end document, hr %#x.\n", hr
);
1019 hr
= IXmlWriter_Flush(writer
);
1020 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
1022 check_output(stream
, start_element_tests
[i
].output
, start_element_tests
[i
].todo
, __LINE__
);
1025 IStream_Release(stream
);
1028 IXmlWriter_Release(writer
);
1031 static void test_WriteElementString(void)
1043 element_string_tests
[] =
1045 { "prefix", "local", "uri", "value", "<prefix:local xmlns:prefix=\"uri\">value</prefix:local>" },
1046 { NULL
, "local", "uri", "value", "<local xmlns=\"uri\">value</local>" },
1047 { "", "local", "uri", "value", "<local xmlns=\"uri\">value</local>" },
1048 { "prefix", "local", "uri", NULL
, "<prefix:local xmlns:prefix=\"uri\" />" },
1049 { NULL
, "local", "uri", NULL
, "<local xmlns=\"uri\" />" },
1050 { "", "local", "uri", NULL
, "<local xmlns=\"uri\" />" },
1051 { NULL
, "local", NULL
, NULL
, "<local />" },
1052 { "prefix", "local", "uri", "", "<prefix:local xmlns:prefix=\"uri\"></prefix:local>" },
1053 { NULL
, "local", "uri", "", "<local xmlns=\"uri\"></local>" },
1054 { "", "local", "uri", "", "<local xmlns=\"uri\"></local>" },
1055 { NULL
, "local", NULL
, "", "<local></local>" },
1056 { "", "local", "http://www.w3.org/2000/xmlns/", NULL
, "<local xmlns=\"http://www.w3.org/2000/xmlns/\" />" },
1058 { "prefix", NULL
, NULL
, "value", NULL
, E_INVALIDARG
},
1059 { NULL
, NULL
, "uri", "value", NULL
, E_INVALIDARG
},
1060 { NULL
, NULL
, NULL
, "value", NULL
, E_INVALIDARG
},
1061 { NULL
, "prefix:local", "uri", "value", NULL
, WC_E_NAMECHARACTER
},
1062 { NULL
, ":local", "uri", "value", NULL
, WC_E_NAMECHARACTER
},
1063 { ":", "local", "uri", "value", NULL
, WC_E_NAMECHARACTER
},
1064 { "prefix", "local", NULL
, "value", NULL
, WR_E_NSPREFIXWITHEMPTYNSURI
},
1065 { "prefix", "local", "", "value", NULL
, WR_E_NSPREFIXWITHEMPTYNSURI
},
1066 { NULL
, "local", "http://www.w3.org/2000/xmlns/", "value", NULL
, WR_E_XMLNSPREFIXDECLARATION
},
1067 { "prefix", "local", "http://www.w3.org/2000/xmlns/", "value", NULL
, WR_E_XMLNSURIDECLARATION
},
1074 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1075 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1077 hr
= write_element_string(writer
, NULL
, "b", NULL
, "value");
1078 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
1080 stream
= writer_set_output(writer
);
1082 hr
= write_start_element(writer
, NULL
, "a", NULL
);
1083 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1085 hr
= write_element_string(writer
, NULL
, "b", NULL
, "value");
1086 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1088 hr
= write_element_string(writer
, NULL
, "b", NULL
, NULL
);
1089 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1091 hr
= write_element_string(writer
, "prefix", "b", "uri", NULL
);
1092 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1094 hr
= write_start_element(writer
, "prefix", "c", "uri");
1095 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
1097 hr
= write_element_string(writer
, "prefix", "d", NULL
, NULL
);
1098 ok(hr
== S_OK
, "Failed to write element, hr %#x.\n", hr
);
1100 hr
= write_element_string(writer
, "prefix2", "d", "uri", NULL
);
1101 ok(hr
== S_OK
, "Failed to write element, hr %#x.\n", hr
);
1103 hr
= write_element_string(writer
, NULL
, "e", "uri", NULL
);
1104 ok(hr
== S_OK
, "Failed to write element, hr %#x.\n", hr
);
1106 hr
= write_element_string(writer
, "prefix", "f", "uri2", NULL
);
1107 ok(hr
== S_OK
, "Failed to write element, hr %#x.\n", hr
);
1109 hr
= write_element_string(writer
, NULL
, "g", "uri3", NULL
);
1110 ok(hr
== S_OK
, "Failed to write element, hr %#x.\n", hr
);
1112 hr
= write_element_string(writer
, "prefix", "h", NULL
, NULL
);
1113 ok(hr
== S_OK
, "Failed to write element, hr %#x.\n", hr
);
1115 hr
= write_element_string(writer
, "prefix_i", "i", NULL
, NULL
);
1116 ok(hr
== WR_E_NSPREFIXWITHEMPTYNSURI
, "Failed to write element, hr %#x.\n", hr
);
1118 hr
= write_element_string(writer
, "", "j", "uri", NULL
);
1119 ok(hr
== S_OK
, "Failed to write element, hr %#x.\n", hr
);
1121 hr
= IXmlWriter_Flush(writer
);
1122 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1124 CHECK_OUTPUT(stream
,
1125 "<a><b>value</b><b />"
1126 "<prefix:b xmlns:prefix=\"uri\" />"
1127 "<prefix:c xmlns:prefix=\"uri\">"
1129 "<prefix2:d xmlns:prefix2=\"uri\" />"
1131 "<prefix:f xmlns:prefix=\"uri2\" />"
1132 "<g xmlns=\"uri3\" />"
1134 "<j xmlns=\"uri\" />");
1136 IStream_Release(stream
);
1138 for (i
= 0; i
< ARRAY_SIZE(element_string_tests
); ++i
)
1140 stream
= writer_set_output(writer
);
1142 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1144 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1145 ok(hr
== S_OK
, "Failed to start document, hr %#x.\n", hr
);
1147 hr
= write_element_string(writer
, element_string_tests
[i
].prefix
, element_string_tests
[i
].local
,
1148 element_string_tests
[i
].uri
, element_string_tests
[i
].value
);
1149 ok(hr
== element_string_tests
[i
].hr
, "%u: unexpected hr %#x.\n", i
, hr
);
1151 if (SUCCEEDED(element_string_tests
[i
].hr
))
1153 hr
= IXmlWriter_Flush(writer
);
1154 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
1156 check_output(stream
, element_string_tests
[i
].output
, element_string_tests
[i
].todo
, __LINE__
);
1158 hr
= IXmlWriter_WriteEndDocument(writer
);
1159 ok(hr
== S_OK
, "Failed to end document, hr %#x.\n", hr
);
1161 hr
= IXmlWriter_Flush(writer
);
1162 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
1164 check_output(stream
, element_string_tests
[i
].output
, element_string_tests
[i
].todo
, __LINE__
);
1167 IStream_Release(stream
);
1170 IXmlWriter_Release(writer
);
1173 static void test_WriteEndElement(void)
1179 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1180 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1182 stream
= writer_set_output(writer
);
1184 hr
= write_start_element(writer
, NULL
, "a", NULL
);
1185 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1187 hr
= write_start_element(writer
, NULL
, "b", NULL
);
1188 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1190 hr
= IXmlWriter_WriteEndElement(writer
);
1191 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1193 hr
= IXmlWriter_WriteEndElement(writer
);
1194 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1196 hr
= IXmlWriter_Flush(writer
);
1197 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1199 CHECK_OUTPUT(stream
, "<a><b /></a>");
1201 IXmlWriter_Release(writer
);
1202 IStream_Release(stream
);
1205 static void test_writeenddocument(void)
1207 static const WCHAR aW
[] = {'a',0};
1208 static const WCHAR bW
[] = {'b',0};
1215 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1216 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1218 hr
= IXmlWriter_WriteEndDocument(writer
);
1219 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
1221 stream
= writer_set_output(writer
);
1223 /* WriteEndDocument resets it to initial state */
1224 hr
= IXmlWriter_WriteEndDocument(writer
);
1225 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1227 hr
= IXmlWriter_WriteEndDocument(writer
);
1228 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1230 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1231 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1233 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
1234 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1236 hr
= IXmlWriter_SetOutput(writer
, (IUnknown
*)stream
);
1237 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1239 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
1240 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1242 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, bW
, NULL
);
1243 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1245 hr
= IXmlWriter_WriteEndDocument(writer
);
1246 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1248 hr
= GetHGlobalFromStream(stream
, &hglobal
);
1249 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1251 ptr
= GlobalLock(hglobal
);
1252 ok(ptr
== NULL
, "got %p\n", ptr
);
1254 /* we still need to flush manually, WriteEndDocument doesn't do that */
1255 hr
= IXmlWriter_Flush(writer
);
1256 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1258 CHECK_OUTPUT(stream
, "<a><b /></a>");
1260 IXmlWriter_Release(writer
);
1261 IStream_Release(stream
);
1264 static void test_WriteComment(void)
1266 static const WCHAR closeW
[] = {'-','-','>',0};
1267 static const WCHAR aW
[] = {'a',0};
1268 static const WCHAR bW
[] = {'b',0};
1273 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1274 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1276 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1278 hr
= IXmlWriter_WriteComment(writer
, aW
);
1279 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
1281 stream
= writer_set_output(writer
);
1283 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1284 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1286 hr
= IXmlWriter_WriteComment(writer
, aW
);
1287 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1289 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, bW
, NULL
);
1290 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1292 hr
= IXmlWriter_WriteComment(writer
, aW
);
1293 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1295 hr
= IXmlWriter_WriteComment(writer
, NULL
);
1296 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1298 hr
= IXmlWriter_WriteComment(writer
, closeW
);
1299 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1301 hr
= IXmlWriter_Flush(writer
);
1302 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1304 CHECK_OUTPUT(stream
, "<!--a--><b><!--a--><!----><!--- ->-->");
1306 IXmlWriter_Release(writer
);
1307 IStream_Release(stream
);
1310 static void test_WriteCData(void)
1312 static const WCHAR closeW
[] = {']',']','>',0};
1313 static const WCHAR close2W
[] = {'a',']',']','>','b',0};
1314 static const WCHAR aW
[] = {'a',0};
1315 static const WCHAR bW
[] = {'b',0};
1320 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1321 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1323 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1325 hr
= IXmlWriter_WriteCData(writer
, aW
);
1326 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
1328 stream
= writer_set_output(writer
);
1330 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, bW
, NULL
);
1331 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1333 hr
= IXmlWriter_WriteCData(writer
, aW
);
1334 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1336 hr
= IXmlWriter_WriteCData(writer
, NULL
);
1337 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1339 hr
= IXmlWriter_WriteCData(writer
, closeW
);
1340 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1342 hr
= IXmlWriter_WriteCData(writer
, close2W
);
1343 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1345 hr
= IXmlWriter_Flush(writer
);
1346 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1348 CHECK_OUTPUT(stream
,
1357 IXmlWriter_Release(writer
);
1358 IStream_Release(stream
);
1361 static void test_WriteRaw(void)
1363 static const WCHAR rawW
[] = {'a','<',':',0};
1364 static const WCHAR aW
[] = {'a',0};
1369 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1370 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1372 hr
= IXmlWriter_WriteRaw(writer
, NULL
);
1373 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1375 hr
= IXmlWriter_WriteRaw(writer
, rawW
);
1376 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
1378 stream
= writer_set_output(writer
);
1380 hr
= IXmlWriter_WriteRaw(writer
, NULL
);
1381 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1383 hr
= IXmlWriter_WriteRaw(writer
, rawW
);
1384 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1386 hr
= IXmlWriter_WriteRaw(writer
, rawW
);
1387 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1389 hr
= IXmlWriter_WriteComment(writer
, rawW
);
1390 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1392 hr
= IXmlWriter_WriteRaw(writer
, rawW
);
1393 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1395 hr
= IXmlWriter_WriteElementString(writer
, NULL
, aW
, NULL
, aW
);
1396 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1398 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Yes
);
1399 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1401 hr
= IXmlWriter_WriteComment(writer
, rawW
);
1402 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1404 hr
= IXmlWriter_WriteEndDocument(writer
);
1405 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1407 hr
= IXmlWriter_WriteRaw(writer
, rawW
);
1408 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1410 hr
= IXmlWriter_Flush(writer
);
1411 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1413 CHECK_OUTPUT(stream
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>a<:a<:<!--a<:-->a<:<a>a</a>");
1415 IXmlWriter_Release(writer
);
1416 IStream_Release(stream
);
1419 static void test_writer_state(void)
1421 static const WCHAR aW
[] = {'a',0};
1426 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1427 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1430 check_writer_state(writer
, E_UNEXPECTED
);
1432 /* set output and call 'wrong' method, WriteEndElement */
1433 stream
= writer_set_output(writer
);
1435 hr
= IXmlWriter_WriteEndElement(writer
);
1436 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1438 check_writer_state(writer
, WR_E_INVALIDACTION
);
1439 IStream_Release(stream
);
1441 /* WriteAttributeString */
1442 stream
= writer_set_output(writer
);
1444 hr
= IXmlWriter_WriteAttributeString(writer
, NULL
, aW
, NULL
, aW
);
1445 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1447 check_writer_state(writer
, WR_E_INVALIDACTION
);
1448 IStream_Release(stream
);
1450 /* WriteEndDocument */
1451 stream
= writer_set_output(writer
);
1453 hr
= IXmlWriter_WriteEndDocument(writer
);
1454 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1456 check_writer_state(writer
, WR_E_INVALIDACTION
);
1457 IStream_Release(stream
);
1459 /* WriteFullEndElement */
1460 stream
= writer_set_output(writer
);
1462 hr
= IXmlWriter_WriteFullEndElement(writer
);
1463 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1465 check_writer_state(writer
, WR_E_INVALIDACTION
);
1466 IStream_Release(stream
);
1469 stream
= writer_set_output(writer
);
1471 hr
= IXmlWriter_WriteCData(writer
, aW
);
1472 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1474 check_writer_state(writer
, WR_E_INVALIDACTION
);
1475 IStream_Release(stream
);
1478 stream
= writer_set_output(writer
);
1480 hr
= IXmlWriter_WriteName(writer
, aW
);
1481 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1483 check_writer_state(writer
, WR_E_INVALIDACTION
);
1484 IStream_Release(stream
);
1487 stream
= writer_set_output(writer
);
1489 hr
= IXmlWriter_WriteNmToken(writer
, aW
);
1490 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1492 check_writer_state(writer
, WR_E_INVALIDACTION
);
1493 IStream_Release(stream
);
1496 stream
= writer_set_output(writer
);
1498 hr
= IXmlWriter_WriteString(writer
, aW
);
1499 ok(hr
== WR_E_INVALIDACTION
, "got 0x%08x\n", hr
);
1501 check_writer_state(writer
, WR_E_INVALIDACTION
);
1502 IStream_Release(stream
);
1504 IXmlWriter_Release(writer
);
1507 static void test_indentation(void)
1509 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
1510 static const WCHAR aW
[] = {'a',0};
1511 static const WCHAR bW
[] = {'b',0};
1516 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1517 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1519 stream
= writer_set_output(writer
);
1521 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1522 writer_set_property(writer
, XmlWriterProperty_Indent
);
1524 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1525 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1527 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
1528 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1530 hr
= IXmlWriter_WriteComment(writer
, commentW
);
1531 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1533 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, bW
, NULL
);
1534 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1536 hr
= IXmlWriter_WriteEndDocument(writer
);
1537 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1539 hr
= IXmlWriter_Flush(writer
);
1540 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1542 CHECK_OUTPUT(stream
,
1544 " <!--comment-->\r\n"
1548 IStream_Release(stream
);
1550 /* WriteElementString */
1551 stream
= writer_set_output(writer
);
1553 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
1554 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1556 hr
= IXmlWriter_WriteElementString(writer
, NULL
, bW
, NULL
, NULL
);
1557 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1559 hr
= IXmlWriter_WriteElementString(writer
, NULL
, bW
, NULL
, NULL
);
1560 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1562 hr
= IXmlWriter_WriteEndElement(writer
);
1563 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1565 hr
= IXmlWriter_Flush(writer
);
1566 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
1568 CHECK_OUTPUT(stream
,
1574 IStream_Release(stream
);
1576 IXmlWriter_Release(writer
);
1579 static HRESULT
write_attribute_string(IXmlWriter
*writer
, const char *prefix
, const char *local
,
1580 const char *uri
, const char *value
)
1582 WCHAR
*prefixW
, *localW
, *uriW
, *valueW
;
1585 prefixW
= strdupAtoW(prefix
);
1586 localW
= strdupAtoW(local
);
1587 uriW
= strdupAtoW(uri
);
1588 valueW
= strdupAtoW(value
);
1590 hr
= IXmlWriter_WriteAttributeString(writer
, prefixW
, localW
, uriW
, valueW
);
1600 static void test_WriteAttributeString(void)
1609 const char *output_partial
;
1617 { NULL
, "a", NULL
, "b", "<e a=\"b\" />", "<e a=\"b\"" },
1618 { "", "a", NULL
, "b", "<e a=\"b\" />", "<e a=\"b\"" },
1619 { NULL
, "a", "", "b", "<e a=\"b\" />", "<e a=\"b\"" },
1620 { "", "a", "", "b", "<e a=\"b\" />", "<e a=\"b\"" },
1621 { "prefix", "local", "uri", "b", "<e prefix:local=\"b\" xmlns:prefix=\"uri\" />", "<e prefix:local=\"b\"" },
1622 { NULL
, "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e xmlns:a=\"defuri\" />", "<e xmlns:a=\"defuri\"" },
1623 { "xmlns", "a", NULL
, "uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1624 { "xmlns", "a", "", "uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1625 { "prefix", "xmlns", "uri", "value", "<e prefix:xmlns=\"value\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"value\"" },
1626 { "prefix", "xmlns", "uri", NULL
, "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1627 { "prefix", "xmlns", "uri", "", "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1628 { "prefix", "xmlns", NULL
, "uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1629 { "prefix", "xmlns", "", "uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1630 { "xml", "space", NULL
, "preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1631 { "xml", "space", "", "preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1632 { "xml", "space", NULL
, "default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1633 { "xml", "space", "", "default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1634 { "xml", "a", NULL
, "value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1635 { "xml", "a", "", "value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1637 /* Autogenerated prefix names. */
1638 { NULL
, "a", "defuri", NULL
, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK
, 1, 1, 1 },
1639 { NULL
, "a", "defuri", "b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK
, 1, 1, 1 },
1640 { "", "a", "defuri", NULL
, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK
, 1, 1, 1 },
1641 { NULL
, "a", "defuri", "", "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK
, 1, 1, 1 },
1642 { "", "a", "defuri", "b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK
, 1, 1, 1 },
1644 /* Failing cases. */
1645 { NULL
, NULL
, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG
},
1646 { "", "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION
, 1, 1, 1 },
1647 { "", NULL
, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG
},
1648 { "", "", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG
, 1, 1, 1 },
1649 { NULL
, "", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG
, 1, 1, 1 },
1650 { "prefix", "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", WR_E_XMLNSURIDECLARATION
, 1, 1, 1 },
1651 { "prefix", NULL
, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG
},
1652 { "prefix", NULL
, NULL
, "b", "<e />", "<e", E_INVALIDARG
},
1653 { "prefix", NULL
, "uri", NULL
, "<e />", "<e", E_INVALIDARG
},
1654 { "xml", NULL
, NULL
, "value", "<e />", "<e", E_INVALIDARG
},
1655 { "xmlns", "a", "defuri", NULL
, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION
},
1656 { "xmlns", "a", "b", "uri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION
},
1657 { NULL
, "xmlns", "uri", NULL
, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION
, 0, 0, 1 },
1658 { "xmlns", NULL
, "uri", NULL
, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION
, 0, 0, 1 },
1659 { "pre:fix", "local", "uri", "b", "<e />", "<e", WC_E_NAMECHARACTER
},
1660 { "pre:fix", NULL
, "uri", "b", "<e />", "<e", E_INVALIDARG
},
1661 { "prefix", "lo:cal", "uri", "b", "<e />", "<e", WC_E_NAMECHARACTER
},
1662 { "xmlns", NULL
, NULL
, "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED
},
1663 { "xmlns", NULL
, "", "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED
},
1664 { "xmlns", "", NULL
, "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED
},
1665 { "xmlns", "", "", "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED
},
1666 { "xml", "space", "", "value", "<e />", "<e", WR_E_INVALIDXMLSPACE
},
1667 { "xml", "space", NULL
, "value", "<e />", "<e", WR_E_INVALIDXMLSPACE
},
1668 { "xml", "a", "uri", "value", "<e />", "<e", WR_E_XMLPREFIXDECLARATION
},
1669 { "xml", "space", NULL
, "preServe", "<e />", "<e", WR_E_INVALIDXMLSPACE
},
1670 { "xml", "space", NULL
, "defAult", "<e />", "<e", WR_E_INVALIDXMLSPACE
},
1671 { "xml", "space", NULL
, NULL
, "<e />", "<e", WR_E_INVALIDXMLSPACE
},
1672 { "xml", "space", NULL
, "", "<e />", "<e", WR_E_INVALIDXMLSPACE
},
1680 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1681 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1683 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1685 for (i
= 0; i
< ARRAY_SIZE(attribute_tests
); ++i
)
1687 stream
= writer_set_output(writer
);
1689 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1690 ok(hr
== S_OK
, "Failed to start document, hr %#x.\n", hr
);
1692 hr
= write_start_element(writer
, NULL
, "e", NULL
);
1693 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
1695 hr
= write_attribute_string(writer
, attribute_tests
[i
].prefix
, attribute_tests
[i
].local
,
1696 attribute_tests
[i
].uri
, attribute_tests
[i
].value
);
1697 todo_wine_if(attribute_tests
[i
].todo_hr
)
1698 ok(hr
== attribute_tests
[i
].hr
, "%u: unexpected hr %#x, expected %#x.\n", i
, hr
, attribute_tests
[i
].hr
);
1700 hr
= IXmlWriter_Flush(writer
);
1701 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
1703 check_output(stream
, attribute_tests
[i
].output_partial
, attribute_tests
[i
].todo_partial
, __LINE__
);
1705 hr
= IXmlWriter_WriteEndDocument(writer
);
1706 ok(hr
== S_OK
, "Failed to end document, hr %#x.\n", hr
);
1708 hr
= IXmlWriter_Flush(writer
);
1709 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
1711 check_output(stream
, attribute_tests
[i
].output
, attribute_tests
[i
].todo
, __LINE__
);
1712 IStream_Release(stream
);
1715 /* With namespaces */
1716 stream
= writer_set_output(writer
);
1718 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1719 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1721 hr
= write_start_element(writer
, "p", "a", "outeruri");
1722 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1724 hr
= write_attribute_string(writer
, "prefix", "local", "uri", "b");
1725 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1727 hr
= write_attribute_string(writer
, NULL
, "a", NULL
, "b");
1728 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1730 hr
= write_attribute_string(writer
, "xmlns", "prefix", NULL
, "uri");
1731 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1733 hr
= write_attribute_string(writer
, "p", "attr", NULL
, "value");
1734 ok(hr
== S_OK
, "Failed to write attribute string, hr %#x.\n", hr
);
1736 hr
= write_attribute_string(writer
, "prefix", "local", NULL
, "b");
1738 ok(hr
== WR_E_DUPLICATEATTRIBUTE
, "got 0x%08x\n", hr
);
1740 hr
= write_start_element(writer
, NULL
, "b", NULL
);
1741 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1743 hr
= write_attribute_string(writer
, NULL
, "attr2", "outeruri", "value");
1744 ok(hr
== S_OK
, "Failed to write attribute string, hr %#x.\n", hr
);
1746 hr
= write_attribute_string(writer
, "pr", "attr3", "outeruri", "value");
1747 ok(hr
== S_OK
, "Failed to write attribute string, hr %#x.\n", hr
);
1749 hr
= IXmlWriter_WriteEndDocument(writer
);
1750 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1752 hr
= IXmlWriter_Flush(writer
);
1753 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1755 CHECK_OUTPUT_TODO(stream
,
1756 "<p:a prefix:local=\"b\" a=\"b\" xmlns:prefix=\"uri\" p:attr=\"value\" xmlns:p=\"outeruri\">"
1757 "<b p:attr2=\"value\" pr:attr3=\"value\" xmlns:pr=\"outeruri\" />"
1760 IStream_Release(stream
);
1762 /* Define prefix, write attribute with it. */
1763 stream
= writer_set_output(writer
);
1765 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1766 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1768 hr
= write_start_element(writer
, NULL
, "e", NULL
);
1769 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1771 hr
= write_attribute_string(writer
, "xmlns", "prefix", NULL
, "uri");
1772 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1774 hr
= write_attribute_string(writer
, "prefix", "attr", NULL
, "value");
1775 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1777 hr
= IXmlWriter_WriteEndDocument(writer
);
1778 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1780 hr
= IXmlWriter_Flush(writer
);
1781 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1783 CHECK_OUTPUT(stream
,
1784 "<e xmlns:prefix=\"uri\" prefix:attr=\"value\" />");
1786 IStream_Release(stream
);
1788 IXmlWriter_Release(writer
);
1791 static void test_WriteFullEndElement(void)
1793 static const WCHAR aW
[] = {'a',0};
1798 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1799 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1801 /* standalone element */
1802 stream
= writer_set_output(writer
);
1804 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1805 writer_set_property(writer
, XmlWriterProperty_Indent
);
1807 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1808 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1810 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
1811 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1813 hr
= IXmlWriter_WriteFullEndElement(writer
);
1814 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1816 hr
= IXmlWriter_WriteEndDocument(writer
);
1817 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1819 hr
= IXmlWriter_Flush(writer
);
1820 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1822 CHECK_OUTPUT(stream
,
1824 IStream_Release(stream
);
1826 /* nested elements */
1827 stream
= writer_set_output(writer
);
1829 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1830 writer_set_property(writer
, XmlWriterProperty_Indent
);
1832 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1833 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1835 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
1836 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1838 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
1839 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1841 hr
= IXmlWriter_WriteFullEndElement(writer
);
1842 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1844 hr
= IXmlWriter_WriteEndDocument(writer
);
1845 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1847 hr
= IXmlWriter_Flush(writer
);
1848 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1850 CHECK_OUTPUT(stream
,
1855 IXmlWriter_Release(writer
);
1856 IStream_Release(stream
);
1859 static void test_WriteCharEntity(void)
1861 static const WCHAR aW
[] = {'a',0};
1866 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1867 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1869 /* without indentation */
1870 stream
= writer_set_output(writer
);
1872 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1874 hr
= IXmlWriter_WriteStartDocument(writer
, XmlStandalone_Omit
);
1875 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1877 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
1878 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1880 hr
= IXmlWriter_WriteCharEntity(writer
, 0x100);
1881 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1883 hr
= IXmlWriter_WriteStartElement(writer
, NULL
, aW
, NULL
);
1884 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1886 hr
= IXmlWriter_WriteEndDocument(writer
);
1887 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1889 hr
= IXmlWriter_Flush(writer
);
1890 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1892 CHECK_OUTPUT(stream
,
1893 "<a>Ā<a /></a>");
1895 IXmlWriter_Release(writer
);
1896 IStream_Release(stream
);
1899 static void test_WriteString(void)
1905 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void**)&writer
, NULL
);
1906 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1908 writer_set_property(writer
, XmlWriterProperty_OmitXmlDeclaration
);
1910 hr
= write_string(writer
, "a");
1911 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
1913 hr
= write_string(writer
, NULL
);
1914 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1916 hr
= write_string(writer
, "");
1917 ok(hr
== E_UNEXPECTED
, "got 0x%08x\n", hr
);
1919 stream
= writer_set_output(writer
);
1921 hr
= write_start_element(writer
, NULL
, "b", NULL
);
1922 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1924 hr
= write_string(writer
, NULL
);
1925 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1927 hr
= write_string(writer
, "");
1928 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1930 hr
= write_string(writer
, "a");
1931 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1933 /* WriteString automatically escapes markup characters */
1934 hr
= write_string(writer
, "<&\">=");
1935 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1937 hr
= IXmlWriter_Flush(writer
);
1938 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1940 CHECK_OUTPUT(stream
,
1941 "<b>a<&\">=");
1942 IStream_Release(stream
);
1944 stream
= writer_set_output(writer
);
1946 hr
= write_start_element(writer
, NULL
, "b", NULL
);
1947 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1949 hr
= write_string(writer
, NULL
);
1950 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1952 hr
= IXmlWriter_Flush(writer
);
1953 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1955 CHECK_OUTPUT(stream
,
1958 hr
= write_string(writer
, "");
1959 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1961 hr
= IXmlWriter_Flush(writer
);
1962 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
1964 CHECK_OUTPUT(stream
,
1967 IStream_Release(stream
);
1968 IXmlWriter_Release(writer
);
1970 /* With indentation */
1971 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void **)&writer
, NULL
);
1972 ok(hr
== S_OK
, "Failed to create a writer, hr %#x.\n", hr
);
1974 stream
= writer_set_output(writer
);
1976 writer_set_property(writer
, XmlWriterProperty_Indent
);
1978 hr
= write_start_element(writer
, NULL
, "a", NULL
);
1979 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
1981 hr
= write_start_element(writer
, NULL
, "b", NULL
);
1982 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
1984 hr
= write_string(writer
, "text");
1985 ok(hr
== S_OK
, "Failed to write a string, hr %#x.\n", hr
);
1987 hr
= IXmlWriter_Flush(writer
);
1988 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
1990 CHECK_OUTPUT(stream
,
1994 hr
= IXmlWriter_WriteFullEndElement(writer
);
1995 ok(hr
== S_OK
, "Failed to end element, hr %#x.\n", hr
);
1997 hr
= IXmlWriter_Flush(writer
);
1998 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
2000 CHECK_OUTPUT(stream
,
2004 hr
= IXmlWriter_WriteFullEndElement(writer
);
2005 ok(hr
== S_OK
, "Failed to end element, hr %#x.\n", hr
);
2007 hr
= IXmlWriter_Flush(writer
);
2008 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
2010 CHECK_OUTPUT(stream
,
2015 IStream_Release(stream
);
2017 stream
= writer_set_output(writer
);
2019 hr
= write_start_element(writer
, NULL
, "a", NULL
);
2020 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
2022 hr
= write_start_element(writer
, NULL
, "b", NULL
);
2023 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
2025 hr
= IXmlWriter_WriteEndElement(writer
);
2026 ok(hr
== S_OK
, "Failed to end element, hr %#x.\n", hr
);
2028 hr
= IXmlWriter_Flush(writer
);
2029 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
2031 CHECK_OUTPUT(stream
,
2035 hr
= write_start_element(writer
, NULL
, "c", NULL
);
2036 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
2038 hr
= write_attribute_string(writer
, NULL
, "attr", NULL
, "value");
2039 ok(hr
== S_OK
, "Failed to write attribute string, hr %#x.\n", hr
);
2041 hr
= IXmlWriter_Flush(writer
);
2042 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
2044 CHECK_OUTPUT(stream
,
2047 " <c attr=\"value\"");
2049 hr
= write_string(writer
, "text");
2050 ok(hr
== S_OK
, "Failed to write a string, hr %#x.\n", hr
);
2052 hr
= IXmlWriter_Flush(writer
);
2053 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
2055 CHECK_OUTPUT(stream
,
2058 " <c attr=\"value\">text");
2060 hr
= IXmlWriter_WriteEndElement(writer
);
2061 ok(hr
== S_OK
, "Failed to end element, hr %#x.\n", hr
);
2063 hr
= IXmlWriter_Flush(writer
);
2064 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
2066 CHECK_OUTPUT(stream
,
2069 " <c attr=\"value\">text</c>");
2071 hr
= write_start_element(writer
, NULL
, "d", NULL
);
2072 ok(hr
== S_OK
, "Failed to start element, hr %#x.\n", hr
);
2074 hr
= write_string(writer
, "");
2075 ok(hr
== S_OK
, "Failed to write a string, hr %#x.\n", hr
);
2077 hr
= IXmlWriter_WriteEndElement(writer
);
2078 ok(hr
== S_OK
, "Failed to end element, hr %#x.\n", hr
);
2080 hr
= IXmlWriter_Flush(writer
);
2081 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
2083 CHECK_OUTPUT(stream
,
2086 " <c attr=\"value\">text</c>\r\n"
2089 hr
= IXmlWriter_WriteEndElement(writer
);
2090 ok(hr
== S_OK
, "Failed to end element, hr %#x.\n", hr
);
2092 hr
= IXmlWriter_Flush(writer
);
2093 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
2095 CHECK_OUTPUT(stream
,
2098 " <c attr=\"value\">text</c>\r\n"
2102 IXmlWriter_Release(writer
);
2103 IStream_Release(stream
);
2106 static HRESULT
write_doctype(IXmlWriter
*writer
, const char *name
, const char *pubid
, const char *sysid
,
2109 WCHAR
*nameW
, *pubidW
, *sysidW
, *subsetW
;
2112 nameW
= strdupAtoW(name
);
2113 pubidW
= strdupAtoW(pubid
);
2114 sysidW
= strdupAtoW(sysid
);
2115 subsetW
= strdupAtoW(subset
);
2117 hr
= IXmlWriter_WriteDocType(writer
, nameW
, pubidW
, sysidW
, subsetW
);
2127 static void test_WriteDocType(void)
2139 { "a", "", NULL
, NULL
, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2140 { "a", NULL
, NULL
, NULL
, "<!DOCTYPE a>" },
2141 { "a", NULL
, "", NULL
, "<!DOCTYPE a SYSTEM \"\">" },
2142 { "a", "", "", NULL
, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2143 { "a", "pubid", "", NULL
, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2144 { "a", "pubid", NULL
, NULL
, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2145 { "a", "", "sysid", NULL
, "<!DOCTYPE a PUBLIC \"\" \"sysid\">" },
2146 { "a", NULL
, NULL
, "", "<!DOCTYPE a []>" },
2147 { "a", NULL
, NULL
, "subset", "<!DOCTYPE a [subset]>" },
2148 { "a", "", NULL
, "subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2149 { "a", NULL
, "", "subset", "<!DOCTYPE a SYSTEM \"\" [subset]>" },
2150 { "a", "", "", "subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2151 { "a", "pubid", NULL
, "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2152 { "a", "pubid", "", "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2153 { "a", NULL
, "sysid", "subset", "<!DOCTYPE a SYSTEM \"sysid\" [subset]>" },
2154 { "a", "", "sysid", "subset", "<!DOCTYPE a PUBLIC \"\" \"sysid\" [subset]>" },
2155 { "a", "pubid", "sysid", "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"sysid\" [subset]>" },
2157 static const WCHAR pubidW
[] = {'p',0x100,'i','d',0};
2158 static const WCHAR nameW
[] = {'-','a',0};
2159 static const WCHAR emptyW
[] = { 0 };
2165 hr
= CreateXmlWriter(&IID_IXmlWriter
, (void **)&writer
, NULL
);
2166 ok(hr
== S_OK
, "Failed to create writer instance, hr %#x.\n", hr
);
2168 stream
= writer_set_output(writer
);
2170 hr
= IXmlWriter_WriteDocType(writer
, NULL
, NULL
, NULL
, NULL
);
2171 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
2173 hr
= IXmlWriter_WriteDocType(writer
, emptyW
, NULL
, NULL
, NULL
);
2174 ok(hr
== E_INVALIDARG
, "Unexpected hr %#x.\n", hr
);
2176 /* Name validation. */
2177 hr
= IXmlWriter_WriteDocType(writer
, nameW
, NULL
, NULL
, NULL
);
2178 ok(hr
== WC_E_NAMECHARACTER
, "Unexpected hr %#x.\n", hr
);
2180 /* Pubid validation. */
2181 hr
= IXmlWriter_WriteDocType(writer
, aW
, pubidW
, NULL
, NULL
);
2182 ok(hr
== WC_E_PUBLICID
, "Unexpected hr %#x.\n", hr
);
2184 IStream_Release(stream
);
2186 for (i
= 0; i
< ARRAY_SIZE(doctype_tests
); i
++)
2188 stream
= writer_set_output(writer
);
2190 hr
= write_doctype(writer
, doctype_tests
[i
].name
, doctype_tests
[i
].pubid
, doctype_tests
[i
].sysid
,
2191 doctype_tests
[i
].subset
);
2192 ok(hr
== S_OK
, "%u: failed to write doctype, hr %#x.\n", i
, hr
);
2194 hr
= IXmlWriter_Flush(writer
);
2195 ok(hr
== S_OK
, "Failed to flush, hr %#x.\n", hr
);
2197 CHECK_OUTPUT(stream
, doctype_tests
[i
].output
);
2199 hr
= write_doctype(writer
, doctype_tests
[i
].name
, doctype_tests
[i
].pubid
, doctype_tests
[i
].sysid
,
2200 doctype_tests
[i
].subset
);
2201 ok(hr
== WR_E_INVALIDACTION
, "Unexpected hr %#x.\n", hr
);
2203 IStream_Release(stream
);
2206 IXmlWriter_Release(writer
);
2211 test_writer_create();
2212 test_writer_state();
2213 test_writeroutput();
2214 test_writestartdocument();
2215 test_WriteStartElement();
2216 test_WriteElementString();
2217 test_WriteEndElement();
2219 test_omitxmldeclaration();
2221 test_writeenddocument();
2222 test_WriteComment();
2226 test_WriteAttributeString();
2227 test_WriteFullEndElement();
2228 test_WriteCharEntity();
2230 test_WriteDocType();