[XMLLITE_WINETEST] Sync with Wine Staging 1.9.16. CORE-11866
[reactos.git] / rostests / winetests / xmllite / writer.c
1 /*
2 * XMLLite IXmlWriter tests
3 *
4 * Copyright 2011 (C) Alistair Leslie-Hughes
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define CONST_VTABLE
26 #define COBJMACROS
27
28 #include <stdarg.h>
29 //#include <stdio.h>
30
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <objbase.h>
35 #include <ole2.h>
36 #include <xmllite.h>
37 #include <wine/test.h>
38
39 #include <initguid.h>
40 DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
41
42 static void check_output(IStream *stream, const char *expected, BOOL todo, int line)
43 {
44 HGLOBAL hglobal;
45 int len = strlen(expected), size;
46 char *ptr;
47 HRESULT hr;
48
49 hr = GetHGlobalFromStream(stream, &hglobal);
50 ok_(__FILE__, line)(hr == S_OK, "got 0x%08x\n", hr);
51
52 size = GlobalSize(hglobal);
53 ptr = GlobalLock(hglobal);
54 todo_wine_if(todo)
55 {
56 if (size != len)
57 {
58 ok_(__FILE__, line)(0, "data size mismatch, expected %u, got %u\n", len, size);
59 ok_(__FILE__, line)(0, "got %s, expected %s\n", ptr, expected);
60 }
61 else
62 ok_(__FILE__, line)(!strncmp(ptr, expected, len), "got %s, expected %s\n", ptr, expected);
63 }
64 GlobalUnlock(hglobal);
65 }
66 #define CHECK_OUTPUT(stream, expected) check_output(stream, expected, FALSE, __LINE__)
67 #define CHECK_OUTPUT_TODO(stream, expected) check_output(stream, expected, TRUE, __LINE__)
68
69 /* used to test all Write* methods for consistent error state */
70 static void check_writer_state(IXmlWriter *writer, HRESULT exp_hr)
71 {
72 static const WCHAR aW[] = {'a',0};
73 HRESULT hr;
74
75 /* FIXME: add WriteAttributes */
76
77 hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, aW);
78 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
79
80 hr = IXmlWriter_WriteCData(writer, aW);
81 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
82
83 hr = IXmlWriter_WriteCharEntity(writer, aW[0]);
84 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
85
86 hr = IXmlWriter_WriteChars(writer, aW, 1);
87 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
88
89 hr = IXmlWriter_WriteComment(writer, aW);
90 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
91
92 /* FIXME: add WriteDocType */
93
94 hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, aW);
95 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
96
97 hr = IXmlWriter_WriteEndDocument(writer);
98 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
99
100 hr = IXmlWriter_WriteEndElement(writer);
101 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
102
103 hr = IXmlWriter_WriteEntityRef(writer, aW);
104 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
105
106 hr = IXmlWriter_WriteFullEndElement(writer);
107 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
108
109 hr = IXmlWriter_WriteName(writer, aW);
110 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
111
112 hr = IXmlWriter_WriteNmToken(writer, aW);
113 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
114
115 /* FIXME: add WriteNode */
116 /* FIXME: add WriteNodeShallow */
117
118 hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
119 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
120
121 hr = IXmlWriter_WriteQualifiedName(writer, aW, NULL);
122 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
123
124 hr = IXmlWriter_WriteRaw(writer, aW);
125 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
126
127 hr = IXmlWriter_WriteRawChars(writer, aW, 1);
128 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
129
130 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
131 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
132
133 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
134 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
135
136 hr = IXmlWriter_WriteString(writer, aW);
137 ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
138
139 /* FIXME: add WriteSurrogateCharEntity */
140 /* FIXME: add WriteWhitespace */
141 }
142
143 static IStream *writer_set_output(IXmlWriter *writer)
144 {
145 IStream *stream;
146 HRESULT hr;
147
148 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
149 ok(hr == S_OK, "got 0x%08x\n", hr);
150
151 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
152 ok(hr == S_OK, "got 0x%08x\n", hr);
153
154 return stream;
155 }
156
157 static HRESULT WINAPI testoutput_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
158 {
159 if (IsEqualGUID(riid, &IID_IUnknown)) {
160 *obj = iface;
161 return S_OK;
162 }
163 else {
164 ok(0, "unknown riid=%s\n", wine_dbgstr_guid(riid));
165 return E_NOINTERFACE;
166 }
167 }
168
169 static ULONG WINAPI testoutput_AddRef(IUnknown *iface)
170 {
171 return 2;
172 }
173
174 static ULONG WINAPI testoutput_Release(IUnknown *iface)
175 {
176 return 1;
177 }
178
179 static const IUnknownVtbl testoutputvtbl = {
180 testoutput_QueryInterface,
181 testoutput_AddRef,
182 testoutput_Release
183 };
184
185 static IUnknown testoutput = { &testoutputvtbl };
186
187 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
188 {
189 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
190 {
191 *obj = iface;
192 return S_OK;
193 }
194
195 *obj = NULL;
196 return E_NOINTERFACE;
197 }
198
199 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
200 {
201 return 2;
202 }
203
204 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
205 {
206 return 1;
207 }
208
209 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
210 {
211 ok(0, "unexpected call\n");
212 return E_NOTIMPL;
213 }
214
215 static ULONG g_write_len;
216 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
217 {
218 g_write_len = cb;
219 *written = cb;
220 return S_OK;
221 }
222
223 static const ISequentialStreamVtbl teststreamvtbl =
224 {
225 teststream_QueryInterface,
226 teststream_AddRef,
227 teststream_Release,
228 teststream_Read,
229 teststream_Write
230 };
231
232 static ISequentialStream teststream = { &teststreamvtbl };
233
234 static void test_writer_create(void)
235 {
236 HRESULT hr;
237 IXmlWriter *writer;
238 LONG_PTR value;
239
240 /* crashes native */
241 if (0)
242 {
243 CreateXmlWriter(&IID_IXmlWriter, NULL, NULL);
244 CreateXmlWriter(NULL, (void**)&writer, NULL);
245 }
246
247 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
248 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
249
250 /* check default properties values */
251 value = 0;
252 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ByteOrderMark, &value);
253 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
254 ok(value == TRUE, "got %ld\n", value);
255
256 value = TRUE;
257 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_Indent, &value);
258 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
259 ok(value == FALSE, "got %ld\n", value);
260
261 value = TRUE;
262 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, &value);
263 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
264 ok(value == FALSE, "got %ld\n", value);
265
266 value = XmlConformanceLevel_Auto;
267 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ConformanceLevel, &value);
268 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
269 ok(value == XmlConformanceLevel_Document, "got %ld\n", value);
270
271 IXmlWriter_Release(writer);
272 }
273
274 static void test_writeroutput(void)
275 {
276 static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
277 IXmlWriterOutput *output;
278 IUnknown *unk;
279 HRESULT hr;
280
281 output = NULL;
282 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output);
283 ok(hr == S_OK, "got %08x\n", hr);
284 IUnknown_Release(output);
285
286 hr = CreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output);
287 ok(hr == S_OK, "got %08x\n", hr);
288 unk = NULL;
289 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
290 ok(hr == S_OK, "got %08x\n", hr);
291 ok(unk != NULL, "got %p\n", unk);
292 /* releasing 'unk' crashes on native */
293 IUnknown_Release(output);
294
295 output = NULL;
296 hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, ~0u, &output);
297 ok(hr == S_OK, "got %08x\n", hr);
298 IUnknown_Release(output);
299
300 hr = CreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, CP_UTF8, &output);
301 ok(hr == S_OK, "got %08x\n", hr);
302 unk = NULL;
303 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
304 ok(hr == S_OK, "got %08x\n", hr);
305 ok(unk != NULL, "got %p\n", unk);
306 /* releasing 'unk' crashes on native */
307 IUnknown_Release(output);
308 }
309
310 static void test_writestartdocument(void)
311 {
312 static const char fullprolog[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
313 static const char prologversion[] = "<?xml version=\"1.0\"?>";
314 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
315 static const WCHAR xmlW[] = {'x','m','l',0};
316 IXmlWriter *writer;
317 IStream *stream;
318 HRESULT hr;
319
320 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
321 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
322
323 /* output not set */
324 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
325 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
326
327 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
328 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
329
330 hr = IXmlWriter_Flush(writer);
331 ok(hr == S_OK, "got 0x%08x\n", hr);
332
333 stream = writer_set_output(writer);
334
335 /* nothing written yet */
336 hr = IXmlWriter_Flush(writer);
337 ok(hr == S_OK, "got 0x%08x\n", hr);
338
339 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
340 ok(hr == S_OK, "got 0x%08x\n", hr);
341
342 hr = IXmlWriter_Flush(writer);
343 ok(hr == S_OK, "got 0x%08x\n", hr);
344
345 CHECK_OUTPUT(stream, fullprolog);
346
347 /* one more time */
348 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
349 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
350 IStream_Release(stream);
351
352 /* now add PI manually, and try to start a document */
353 stream = writer_set_output(writer);
354
355 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
356 ok(hr == S_OK, "got 0x%08x\n", hr);
357
358 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
359 ok(hr == S_OK, "got 0x%08x\n", hr);
360
361 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
362 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
363
364 /* another attempt to add 'xml' PI */
365 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
366 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
367
368 hr = IXmlWriter_Flush(writer);
369 ok(hr == S_OK, "got 0x%08x\n", hr);
370
371 CHECK_OUTPUT(stream, prologversion);
372
373 IStream_Release(stream);
374 IXmlWriter_Release(writer);
375 }
376
377 static void test_flush(void)
378 {
379 IXmlWriter *writer;
380 HRESULT hr;
381
382 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
383 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
384
385 hr = IXmlWriter_SetOutput(writer, (IUnknown*)&teststream);
386 ok(hr == S_OK, "got 0x%08x\n", hr);
387
388 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
389 ok(hr == S_OK, "got 0x%08x\n", hr);
390
391 g_write_len = 0;
392 hr = IXmlWriter_Flush(writer);
393 ok(hr == S_OK, "got 0x%08x\n", hr);
394 ok(g_write_len > 0, "got %d\n", g_write_len);
395
396 g_write_len = 1;
397 hr = IXmlWriter_Flush(writer);
398 ok(hr == S_OK, "got 0x%08x\n", hr);
399 ok(g_write_len == 0, "got %d\n", g_write_len);
400
401 /* Release() flushes too */
402 g_write_len = 1;
403 IXmlWriter_Release(writer);
404 ok(g_write_len == 0, "got %d\n", g_write_len);
405 }
406
407 static void test_omitxmldeclaration(void)
408 {
409 static const char prologversion[] = "<?xml version=\"1.0\"?>";
410 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
411 static const WCHAR xmlW[] = {'x','m','l',0};
412 IXmlWriter *writer;
413 HGLOBAL hglobal;
414 IStream *stream;
415 HRESULT hr;
416 char *ptr;
417
418 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
419 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
420
421 stream = writer_set_output(writer);
422
423 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
424 ok(hr == S_OK, "got 0x%08x\n", hr);
425
426 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
427 ok(hr == S_OK, "got 0x%08x\n", hr);
428
429 hr = IXmlWriter_Flush(writer);
430 ok(hr == S_OK, "got 0x%08x\n", hr);
431
432 hr = GetHGlobalFromStream(stream, &hglobal);
433 ok(hr == S_OK, "got 0x%08x\n", hr);
434
435 ptr = GlobalLock(hglobal);
436 ok(!ptr, "got %p\n", ptr);
437 GlobalUnlock(hglobal);
438
439 /* one more time */
440 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
441 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
442
443 IStream_Release(stream);
444
445 /* now add PI manually, and try to start a document */
446 stream = writer_set_output(writer);
447
448 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
449 ok(hr == S_OK, "got 0x%08x\n", hr);
450
451 hr = IXmlWriter_Flush(writer);
452 ok(hr == S_OK, "got 0x%08x\n", hr);
453
454 CHECK_OUTPUT(stream, prologversion);
455
456 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
457 ok(hr == S_OK, "got 0x%08x\n", hr);
458
459 hr = IXmlWriter_Flush(writer);
460 ok(hr == S_OK, "got 0x%08x\n", hr);
461
462 CHECK_OUTPUT(stream, prologversion);
463
464 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
465 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
466
467 hr = IXmlWriter_Flush(writer);
468 ok(hr == S_OK, "got 0x%08x\n", hr);
469
470 CHECK_OUTPUT(stream, prologversion);
471
472 /* another attempt to add 'xml' PI */
473 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
474 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
475
476 hr = IXmlWriter_Flush(writer);
477 ok(hr == S_OK, "got 0x%08x\n", hr);
478
479 IStream_Release(stream);
480 IXmlWriter_Release(writer);
481 }
482
483 static void test_bom(void)
484 {
485 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
486 static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
487 static const WCHAR xmlW[] = {'x','m','l',0};
488 static const WCHAR aW[] = {'a',0};
489 IXmlWriterOutput *output;
490 unsigned char *ptr;
491 IXmlWriter *writer;
492 IStream *stream;
493 HGLOBAL hglobal;
494 HRESULT hr;
495
496 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
497 ok(hr == S_OK, "got 0x%08x\n", hr);
498
499 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
500 ok(hr == S_OK, "got %08x\n", hr);
501
502 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
503 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
504
505 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
506 ok(hr == S_OK, "got 0x%08x\n", hr);
507
508 hr = IXmlWriter_SetOutput(writer, output);
509 ok(hr == S_OK, "got 0x%08x\n", hr);
510
511 /* BOM is on by default */
512 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
513 ok(hr == S_OK, "got 0x%08x\n", hr);
514
515 hr = IXmlWriter_Flush(writer);
516 ok(hr == S_OK, "got 0x%08x\n", hr);
517
518 hr = GetHGlobalFromStream(stream, &hglobal);
519 ok(hr == S_OK, "got 0x%08x\n", hr);
520
521 ptr = GlobalLock(hglobal);
522 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
523 GlobalUnlock(hglobal);
524
525 IStream_Release(stream);
526 IUnknown_Release(output);
527
528 /* start with PI */
529 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
530 ok(hr == S_OK, "got 0x%08x\n", hr);
531
532 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
533 ok(hr == S_OK, "got %08x\n", hr);
534
535 hr = IXmlWriter_SetOutput(writer, output);
536 ok(hr == S_OK, "got 0x%08x\n", hr);
537
538 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
539 ok(hr == S_OK, "got 0x%08x\n", hr);
540
541 hr = IXmlWriter_Flush(writer);
542 ok(hr == S_OK, "got 0x%08x\n", hr);
543
544 hr = GetHGlobalFromStream(stream, &hglobal);
545 ok(hr == S_OK, "got 0x%08x\n", hr);
546
547 ptr = GlobalLock(hglobal);
548 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
549 GlobalUnlock(hglobal);
550
551 IUnknown_Release(output);
552 IStream_Release(stream);
553
554 /* start with element */
555 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
556 ok(hr == S_OK, "got 0x%08x\n", hr);
557
558 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
559 ok(hr == S_OK, "got %08x\n", hr);
560
561 hr = IXmlWriter_SetOutput(writer, output);
562 ok(hr == S_OK, "got 0x%08x\n", hr);
563
564 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
565 ok(hr == S_OK, "got 0x%08x\n", hr);
566
567 hr = IXmlWriter_Flush(writer);
568 ok(hr == S_OK, "got 0x%08x\n", hr);
569
570 hr = GetHGlobalFromStream(stream, &hglobal);
571 ok(hr == S_OK, "got 0x%08x\n", hr);
572
573 ptr = GlobalLock(hglobal);
574 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
575 GlobalUnlock(hglobal);
576
577 IUnknown_Release(output);
578 IStream_Release(stream);
579
580 /* WriteElementString */
581 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
582 ok(hr == S_OK, "got 0x%08x\n", hr);
583
584 hr = CreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
585 ok(hr == S_OK, "got %08x\n", hr);
586
587 hr = IXmlWriter_SetOutput(writer, output);
588 ok(hr == S_OK, "got 0x%08x\n", hr);
589
590 hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
591 ok(hr == S_OK, "got 0x%08x\n", hr);
592
593 hr = IXmlWriter_Flush(writer);
594 ok(hr == S_OK, "got 0x%08x\n", hr);
595
596 hr = GetHGlobalFromStream(stream, &hglobal);
597 ok(hr == S_OK, "got 0x%08x\n", hr);
598
599 ptr = GlobalLock(hglobal);
600 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
601 GlobalUnlock(hglobal);
602
603 IUnknown_Release(output);
604 IStream_Release(stream);
605
606 IXmlWriter_Release(writer);
607 }
608
609 static void test_writestartelement(void)
610 {
611 static const WCHAR valueW[] = {'v','a','l','u','e',0};
612 static const char *str = "<a><b>value</b>";
613 static const WCHAR aW[] = {'a',0};
614 static const WCHAR bW[] = {'b',0};
615 IXmlWriter *writer;
616 IStream *stream;
617 HRESULT hr;
618
619 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
620 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
621
622 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
623 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
624
625 stream = writer_set_output(writer);
626
627 hr = IXmlWriter_WriteStartElement(writer, aW, NULL, NULL);
628 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
629
630 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
631 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
632
633 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, aW);
634 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
635
636 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
637 ok(hr == S_OK, "got 0x%08x\n", hr);
638
639 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
640 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
641
642 hr = IXmlWriter_Flush(writer);
643 ok(hr == S_OK, "got 0x%08x\n", hr);
644
645 CHECK_OUTPUT(stream, "<a");
646
647 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
648 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
649
650 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
651 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
652
653 hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
654 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
655
656 IStream_Release(stream);
657 IXmlWriter_Release(writer);
658
659 /* WriteElementString */
660 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
661 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
662
663 hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
664 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
665
666 stream = writer_set_output(writer);
667
668 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
669 ok(hr == S_OK, "got 0x%08x\n", hr);
670
671 hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
672 ok(hr == S_OK, "got 0x%08x\n", hr);
673
674 hr = IXmlWriter_Flush(writer);
675 ok(hr == S_OK, "got 0x%08x\n", hr);
676
677 CHECK_OUTPUT(stream, str);
678
679 IStream_Release(stream);
680 IXmlWriter_Release(writer);
681 }
682
683 static void test_writeendelement(void)
684 {
685 static const WCHAR aW[] = {'a',0};
686 static const WCHAR bW[] = {'b',0};
687 IXmlWriter *writer;
688 IStream *stream;
689 HRESULT hr;
690
691 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
692 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
693
694 stream = writer_set_output(writer);
695
696 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
697 ok(hr == S_OK, "got 0x%08x\n", hr);
698
699 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
700 ok(hr == S_OK, "got 0x%08x\n", hr);
701
702 hr = IXmlWriter_WriteEndElement(writer);
703 ok(hr == S_OK, "got 0x%08x\n", hr);
704
705 hr = IXmlWriter_WriteEndElement(writer);
706 ok(hr == S_OK, "got 0x%08x\n", hr);
707
708 hr = IXmlWriter_Flush(writer);
709 ok(hr == S_OK, "got 0x%08x\n", hr);
710
711 CHECK_OUTPUT(stream, "<a><b /></a>");
712
713 IXmlWriter_Release(writer);
714 IStream_Release(stream);
715 }
716
717 static void test_writeenddocument(void)
718 {
719 static const WCHAR aW[] = {'a',0};
720 static const WCHAR bW[] = {'b',0};
721 IXmlWriter *writer;
722 IStream *stream;
723 HGLOBAL hglobal;
724 HRESULT hr;
725 char *ptr;
726
727 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
728 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
729
730 hr = IXmlWriter_WriteEndDocument(writer);
731 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
732
733 stream = writer_set_output(writer);
734
735 /* WriteEndDocument resets it to initial state */
736 hr = IXmlWriter_WriteEndDocument(writer);
737 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
738
739 hr = IXmlWriter_WriteEndDocument(writer);
740 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
741
742 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
743 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
744
745 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
746 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
747
748 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
749 ok(hr == S_OK, "got 0x%08x\n", hr);
750
751 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
752 ok(hr == S_OK, "got 0x%08x\n", hr);
753
754 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
755 ok(hr == S_OK, "got 0x%08x\n", hr);
756
757 hr = IXmlWriter_WriteEndDocument(writer);
758 ok(hr == S_OK, "got 0x%08x\n", hr);
759
760 hr = GetHGlobalFromStream(stream, &hglobal);
761 ok(hr == S_OK, "got 0x%08x\n", hr);
762
763 ptr = GlobalLock(hglobal);
764 ok(ptr == NULL, "got %p\n", ptr);
765
766 /* we still need to flush manually, WriteEndDocument doesn't do that */
767 hr = IXmlWriter_Flush(writer);
768 ok(hr == S_OK, "got 0x%08x\n", hr);
769
770 CHECK_OUTPUT(stream, "<a><b /></a>");
771
772 IXmlWriter_Release(writer);
773 IStream_Release(stream);
774 }
775
776 static void test_WriteComment(void)
777 {
778 static const WCHAR closeW[] = {'-','-','>',0};
779 static const WCHAR aW[] = {'a',0};
780 static const WCHAR bW[] = {'b',0};
781 IXmlWriter *writer;
782 IStream *stream;
783 HRESULT hr;
784
785 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
786 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
787
788 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
789 ok(hr == S_OK, "got 0x%08x\n", hr);
790
791 hr = IXmlWriter_WriteComment(writer, aW);
792 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
793
794 stream = writer_set_output(writer);
795
796 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
797 ok(hr == S_OK, "got 0x%08x\n", hr);
798
799 hr = IXmlWriter_WriteComment(writer, aW);
800 ok(hr == S_OK, "got 0x%08x\n", hr);
801
802 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
803 ok(hr == S_OK, "got 0x%08x\n", hr);
804
805 hr = IXmlWriter_WriteComment(writer, aW);
806 ok(hr == S_OK, "got 0x%08x\n", hr);
807
808 hr = IXmlWriter_WriteComment(writer, NULL);
809 ok(hr == S_OK, "got 0x%08x\n", hr);
810
811 hr = IXmlWriter_WriteComment(writer, closeW);
812 ok(hr == S_OK, "got 0x%08x\n", hr);
813
814 hr = IXmlWriter_Flush(writer);
815 ok(hr == S_OK, "got 0x%08x\n", hr);
816
817 CHECK_OUTPUT(stream, "<!--a--><b><!--a--><!----><!--- ->-->");
818
819 IXmlWriter_Release(writer);
820 IStream_Release(stream);
821 }
822
823 static void test_WriteCData(void)
824 {
825 static const WCHAR closeW[] = {']',']','>',0};
826 static const WCHAR close2W[] = {'a',']',']','>','b',0};
827 static const WCHAR aW[] = {'a',0};
828 static const WCHAR bW[] = {'b',0};
829 IXmlWriter *writer;
830 IStream *stream;
831 HRESULT hr;
832
833 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
834 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
835
836 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
837 ok(hr == S_OK, "got 0x%08x\n", hr);
838
839 hr = IXmlWriter_WriteCData(writer, aW);
840 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
841
842 stream = writer_set_output(writer);
843
844 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
845 ok(hr == S_OK, "got 0x%08x\n", hr);
846
847 hr = IXmlWriter_WriteCData(writer, aW);
848 ok(hr == S_OK, "got 0x%08x\n", hr);
849
850 hr = IXmlWriter_WriteCData(writer, NULL);
851 ok(hr == S_OK, "got 0x%08x\n", hr);
852
853 hr = IXmlWriter_WriteCData(writer, closeW);
854 ok(hr == S_OK, "got 0x%08x\n", hr);
855
856 hr = IXmlWriter_WriteCData(writer, close2W);
857 ok(hr == S_OK, "got 0x%08x\n", hr);
858
859 hr = IXmlWriter_Flush(writer);
860 ok(hr == S_OK, "got 0x%08x\n", hr);
861
862 CHECK_OUTPUT(stream,
863 "<b>"
864 "<![CDATA[a]]>"
865 "<![CDATA[]]>"
866 "<![CDATA[]]]]>"
867 "<![CDATA[>]]>"
868 "<![CDATA[a]]]]>"
869 "<![CDATA[>b]]>");
870
871 IXmlWriter_Release(writer);
872 IStream_Release(stream);
873 }
874
875 static void test_WriteRaw(void)
876 {
877 static const WCHAR rawW[] = {'a','<',':',0};
878 static const WCHAR aW[] = {'a',0};
879 IXmlWriter *writer;
880 IStream *stream;
881 HRESULT hr;
882
883 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
884 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
885
886 hr = IXmlWriter_WriteRaw(writer, NULL);
887 ok(hr == S_OK, "got 0x%08x\n", hr);
888
889 hr = IXmlWriter_WriteRaw(writer, rawW);
890 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
891
892 stream = writer_set_output(writer);
893
894 hr = IXmlWriter_WriteRaw(writer, NULL);
895 ok(hr == S_OK, "got 0x%08x\n", hr);
896
897 hr = IXmlWriter_WriteRaw(writer, rawW);
898 ok(hr == S_OK, "got 0x%08x\n", hr);
899
900 hr = IXmlWriter_WriteRaw(writer, rawW);
901 ok(hr == S_OK, "got 0x%08x\n", hr);
902
903 hr = IXmlWriter_WriteComment(writer, rawW);
904 ok(hr == S_OK, "got 0x%08x\n", hr);
905
906 hr = IXmlWriter_WriteRaw(writer, rawW);
907 ok(hr == S_OK, "got 0x%08x\n", hr);
908
909 hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, aW);
910 ok(hr == S_OK, "got 0x%08x\n", hr);
911
912 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
913 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
914
915 hr = IXmlWriter_WriteComment(writer, rawW);
916 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
917
918 hr = IXmlWriter_WriteEndDocument(writer);
919 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
920
921 hr = IXmlWriter_WriteRaw(writer, rawW);
922 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
923
924 hr = IXmlWriter_Flush(writer);
925 ok(hr == S_OK, "got 0x%08x\n", hr);
926
927 CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>a<:a<:<!--a<:-->a<:<a>a</a>");
928
929 IXmlWriter_Release(writer);
930 IStream_Release(stream);
931 }
932
933 static void test_writer_state(void)
934 {
935 static const WCHAR aW[] = {'a',0};
936 IXmlWriter *writer;
937 IStream *stream;
938 HRESULT hr;
939
940 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
941 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
942
943 /* initial state */
944 check_writer_state(writer, E_UNEXPECTED);
945
946 /* set output and call 'wrong' method, WriteEndElement */
947 stream = writer_set_output(writer);
948
949 hr = IXmlWriter_WriteEndElement(writer);
950 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
951
952 check_writer_state(writer, WR_E_INVALIDACTION);
953 IStream_Release(stream);
954
955 /* WriteAttributeString */
956 stream = writer_set_output(writer);
957
958 hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, aW);
959 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
960
961 check_writer_state(writer, WR_E_INVALIDACTION);
962 IStream_Release(stream);
963
964 /* WriteEndDocument */
965 stream = writer_set_output(writer);
966
967 hr = IXmlWriter_WriteEndDocument(writer);
968 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
969
970 check_writer_state(writer, WR_E_INVALIDACTION);
971 IStream_Release(stream);
972
973 /* WriteFullEndElement */
974 stream = writer_set_output(writer);
975
976 hr = IXmlWriter_WriteFullEndElement(writer);
977 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
978
979 check_writer_state(writer, WR_E_INVALIDACTION);
980 IStream_Release(stream);
981
982 /* WriteCData */
983 stream = writer_set_output(writer);
984
985 hr = IXmlWriter_WriteCData(writer, aW);
986 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
987
988 check_writer_state(writer, WR_E_INVALIDACTION);
989 IStream_Release(stream);
990
991 /* WriteName */
992 stream = writer_set_output(writer);
993
994 hr = IXmlWriter_WriteName(writer, aW);
995 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
996
997 check_writer_state(writer, WR_E_INVALIDACTION);
998 IStream_Release(stream);
999
1000 /* WriteNmToken */
1001 stream = writer_set_output(writer);
1002
1003 hr = IXmlWriter_WriteNmToken(writer, aW);
1004 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1005
1006 check_writer_state(writer, WR_E_INVALIDACTION);
1007 IStream_Release(stream);
1008
1009 /* WriteString */
1010 stream = writer_set_output(writer);
1011
1012 hr = IXmlWriter_WriteString(writer, aW);
1013 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1014
1015 check_writer_state(writer, WR_E_INVALIDACTION);
1016 IStream_Release(stream);
1017
1018 IXmlWriter_Release(writer);
1019 }
1020
1021 static void test_indentation(void)
1022 {
1023 static const WCHAR commentW[] = {'c','o','m','m','e','n','t',0};
1024 static const WCHAR aW[] = {'a',0};
1025 static const WCHAR bW[] = {'b',0};
1026 IXmlWriter *writer;
1027 IStream *stream;
1028 HRESULT hr;
1029
1030 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1031 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1032
1033 stream = writer_set_output(writer);
1034
1035 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
1036 ok(hr == S_OK, "got 0x%08x\n", hr);
1037
1038 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_Indent, TRUE);
1039 ok(hr == S_OK, "got 0x%08x\n", hr);
1040
1041 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1042 ok(hr == S_OK, "got 0x%08x\n", hr);
1043
1044 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1045 ok(hr == S_OK, "got 0x%08x\n", hr);
1046
1047 hr = IXmlWriter_WriteComment(writer, commentW);
1048 ok(hr == S_OK, "got 0x%08x\n", hr);
1049
1050 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
1051 ok(hr == S_OK, "got 0x%08x\n", hr);
1052
1053 hr = IXmlWriter_WriteEndDocument(writer);
1054 ok(hr == S_OK, "got 0x%08x\n", hr);
1055
1056 hr = IXmlWriter_Flush(writer);
1057 ok(hr == S_OK, "got 0x%08x\n", hr);
1058
1059 CHECK_OUTPUT(stream,
1060 "<a>\r\n"
1061 " <!--comment-->\r\n"
1062 " <b />\r\n"
1063 "</a>");
1064
1065 IXmlWriter_Release(writer);
1066 IStream_Release(stream);
1067 }
1068
1069 static void test_WriteAttributeString(void)
1070 {
1071 static const WCHAR prefixW[] = {'p','r','e','f','i','x',0};
1072 static const WCHAR localW[] = {'l','o','c','a','l',0};
1073 static const WCHAR uriW[] = {'u','r','i',0};
1074 static const WCHAR uri2W[] = {'u','r','i','2',0};
1075 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
1076 static const WCHAR aW[] = {'a',0};
1077 static const WCHAR bW[] = {'b',0};
1078 IXmlWriter *writer;
1079 IStream *stream;
1080 HRESULT hr;
1081
1082 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1083 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1084
1085 stream = writer_set_output(writer);
1086
1087 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
1088 ok(hr == S_OK, "got 0x%08x\n", hr);
1089
1090 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1091 ok(hr == S_OK, "got 0x%08x\n", hr);
1092
1093 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1094 ok(hr == S_OK, "got 0x%08x\n", hr);
1095
1096 hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, bW);
1097 ok(hr == S_OK, "got 0x%08x\n", hr);
1098
1099 hr = IXmlWriter_WriteEndDocument(writer);
1100 ok(hr == S_OK, "got 0x%08x\n", hr);
1101
1102 hr = IXmlWriter_Flush(writer);
1103 ok(hr == S_OK, "got 0x%08x\n", hr);
1104
1105 CHECK_OUTPUT(stream,
1106 "<a a=\"b\" />");
1107 IStream_Release(stream);
1108
1109 /* with namespaces */
1110 stream = writer_set_output(writer);
1111
1112 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1113 ok(hr == S_OK, "got 0x%08x\n", hr);
1114
1115 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1116 ok(hr == S_OK, "got 0x%08x\n", hr);
1117
1118 hr = IXmlWriter_WriteAttributeString(writer, aW, NULL, NULL, bW);
1119 todo_wine
1120 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1121
1122 hr = IXmlWriter_WriteAttributeString(writer, prefixW, localW, uriW, bW);
1123 todo_wine
1124 ok(hr == S_OK, "got 0x%08x\n", hr);
1125
1126 hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, bW);
1127 ok(hr == S_OK, "got 0x%08x\n", hr);
1128
1129 hr = IXmlWriter_WriteAttributeString(writer, NULL, xmlnsW, uri2W, NULL);
1130 todo_wine
1131 ok(hr == WR_E_XMLNSPREFIXDECLARATION, "got 0x%08x\n", hr);
1132
1133 hr = IXmlWriter_WriteAttributeString(writer, NULL, xmlnsW, NULL, uri2W);
1134 todo_wine
1135 ok(hr == WR_E_NSPREFIXDECLARED, "got 0x%08x\n", hr);
1136
1137 hr = IXmlWriter_WriteAttributeString(writer, prefixW, localW, NULL, bW);
1138 todo_wine
1139 ok(hr == WR_E_DUPLICATEATTRIBUTE, "got 0x%08x\n", hr);
1140
1141 hr = IXmlWriter_WriteEndDocument(writer);
1142 ok(hr == S_OK, "got 0x%08x\n", hr);
1143
1144 hr = IXmlWriter_Flush(writer);
1145 ok(hr == S_OK, "got 0x%08x\n", hr);
1146
1147 CHECK_OUTPUT_TODO(stream,
1148 "<a prefix:local=\"b\" a=\"b\" xmlns:prefix=\"uri\" />");
1149
1150 IXmlWriter_Release(writer);
1151 IStream_Release(stream);
1152 }
1153
1154 static void test_WriteFullEndElement(void)
1155 {
1156 static const WCHAR aW[] = {'a',0};
1157 IXmlWriter *writer;
1158 IStream *stream;
1159 HRESULT hr;
1160
1161 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1162 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1163
1164 /* standalone element */
1165 stream = writer_set_output(writer);
1166
1167 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
1168 ok(hr == S_OK, "got 0x%08x\n", hr);
1169
1170 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_Indent, TRUE);
1171 ok(hr == S_OK, "got 0x%08x\n", hr);
1172
1173 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1174 ok(hr == S_OK, "got 0x%08x\n", hr);
1175
1176 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1177 ok(hr == S_OK, "got 0x%08x\n", hr);
1178
1179 hr = IXmlWriter_WriteFullEndElement(writer);
1180 ok(hr == S_OK, "got 0x%08x\n", hr);
1181
1182 hr = IXmlWriter_WriteEndDocument(writer);
1183 ok(hr == S_OK, "got 0x%08x\n", hr);
1184
1185 hr = IXmlWriter_Flush(writer);
1186 ok(hr == S_OK, "got 0x%08x\n", hr);
1187
1188 CHECK_OUTPUT(stream,
1189 "<a></a>");
1190 IStream_Release(stream);
1191
1192 /* nested elements */
1193 stream = writer_set_output(writer);
1194
1195 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
1196 ok(hr == S_OK, "got 0x%08x\n", hr);
1197
1198 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_Indent, TRUE);
1199 ok(hr == S_OK, "got 0x%08x\n", hr);
1200
1201 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1202 ok(hr == S_OK, "got 0x%08x\n", hr);
1203
1204 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1205 ok(hr == S_OK, "got 0x%08x\n", hr);
1206
1207 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1208 ok(hr == S_OK, "got 0x%08x\n", hr);
1209
1210 hr = IXmlWriter_WriteFullEndElement(writer);
1211 ok(hr == S_OK, "got 0x%08x\n", hr);
1212
1213 hr = IXmlWriter_WriteEndDocument(writer);
1214 ok(hr == S_OK, "got 0x%08x\n", hr);
1215
1216 hr = IXmlWriter_Flush(writer);
1217 ok(hr == S_OK, "got 0x%08x\n", hr);
1218
1219 CHECK_OUTPUT(stream,
1220 "<a>\r\n"
1221 " <a></a>\r\n"
1222 "</a>");
1223
1224 IXmlWriter_Release(writer);
1225 IStream_Release(stream);
1226 }
1227
1228 static void test_WriteCharEntity(void)
1229 {
1230 static const WCHAR aW[] = {'a',0};
1231 IXmlWriter *writer;
1232 IStream *stream;
1233 HRESULT hr;
1234
1235 hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1236 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1237
1238 /* without indentation */
1239 stream = writer_set_output(writer);
1240
1241 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
1242 ok(hr == S_OK, "got 0x%08x\n", hr);
1243
1244 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1245 ok(hr == S_OK, "got 0x%08x\n", hr);
1246
1247 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1248 ok(hr == S_OK, "got 0x%08x\n", hr);
1249
1250 hr = IXmlWriter_WriteCharEntity(writer, 0x100);
1251 ok(hr == S_OK, "got 0x%08x\n", hr);
1252
1253 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1254 ok(hr == S_OK, "got 0x%08x\n", hr);
1255
1256 hr = IXmlWriter_WriteEndDocument(writer);
1257 ok(hr == S_OK, "got 0x%08x\n", hr);
1258
1259 hr = IXmlWriter_Flush(writer);
1260 ok(hr == S_OK, "got 0x%08x\n", hr);
1261
1262 CHECK_OUTPUT(stream,
1263 "<a>&#x100;<a /></a>");
1264
1265 IXmlWriter_Release(writer);
1266 IStream_Release(stream);
1267 }
1268
1269 START_TEST(writer)
1270 {
1271 test_writer_create();
1272 test_writer_state();
1273 test_writeroutput();
1274 test_writestartdocument();
1275 test_writestartelement();
1276 test_writeendelement();
1277 test_flush();
1278 test_omitxmldeclaration();
1279 test_bom();
1280 test_writeenddocument();
1281 test_WriteComment();
1282 test_WriteCData();
1283 test_WriteRaw();
1284 test_indentation();
1285 test_WriteAttributeString();
1286 test_WriteFullEndElement();
1287 test_WriteCharEntity();
1288 }