ReactOS  0.4.14-dev-854-gb9426a3
writer.c
Go to the documentation of this file.
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 #ifdef __REACTOS__
22 #define CONST_VTABLE
23 #endif
24 
25 #define COBJMACROS
26 
27 #include <stdarg.h>
28 #include <stdio.h>
29 
30 #include "windef.h"
31 #include "winbase.h"
32 #include "ole2.h"
33 #include "xmllite.h"
34 
35 #include "wine/heap.h"
36 #include "wine/test.h"
37 
38 #include "initguid.h"
39 DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
40 
41 static const WCHAR aW[] = {'a',0};
42 
43 #define EXPECT_REF(obj, ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
44 static void _expect_ref(IUnknown *obj, ULONG ref, int line)
45 {
46  ULONG refcount;
47  IUnknown_AddRef(obj);
48  refcount = IUnknown_Release(obj);
49  ok_(__FILE__, line)(refcount == ref, "expected refcount %d, got %d\n", ref, refcount);
50 }
51 
52 static void check_output_raw(IStream *stream, const void *expected, SIZE_T size, int line)
53 {
54  SIZE_T content_size;
55  HGLOBAL hglobal;
56  HRESULT hr;
57  WCHAR *ptr;
58 
59  hr = GetHGlobalFromStream(stream, &hglobal);
60  ok_(__FILE__, line)(hr == S_OK, "Failed to get the stream handle, hr %#x.\n", hr);
61 
62  content_size = GlobalSize(hglobal);
63  ok_(__FILE__, line)(size == content_size, "Unexpected test output size %ld.\n", content_size);
64  ptr = GlobalLock(hglobal);
65  if (size <= content_size)
66  ok_(__FILE__, line)(!memcmp(expected, ptr, size), "Unexpected output content.\n");
67  if (size != content_size && *ptr == 0xfeff)
68  ok_(__FILE__, line)(0, "Content: %s.\n", wine_dbgstr_wn(ptr, content_size / sizeof(WCHAR)));
69 
70  GlobalUnlock(hglobal);
71 }
72 
73 static void check_output(IStream *stream, const char *expected, BOOL todo, int line)
74 {
75  int len = strlen(expected), size;
76  HGLOBAL hglobal;
77  HRESULT hr;
78  char *ptr;
79 
80  hr = GetHGlobalFromStream(stream, &hglobal);
81  ok_(__FILE__, line)(hr == S_OK, "got 0x%08x\n", hr);
82 
83  size = GlobalSize(hglobal);
84  ptr = GlobalLock(hglobal);
86  {
87  if (size != len)
88  {
89  ok_(__FILE__, line)(0, "data size mismatch, expected %u, got %u\n", len, size);
90  ok_(__FILE__, line)(0, "got |%s|, expected |%s|\n", ptr, expected);
91  }
92  else
93  ok_(__FILE__, line)(!strncmp(ptr, expected, len), "got |%s|, expected |%s|\n", ptr, expected);
94  }
95  GlobalUnlock(hglobal);
96 }
97 #define CHECK_OUTPUT(stream, expected) check_output(stream, expected, FALSE, __LINE__)
98 #define CHECK_OUTPUT_TODO(stream, expected) check_output(stream, expected, TRUE, __LINE__)
99 #define CHECK_OUTPUT_RAW(stream, expected, size) check_output_raw(stream, expected, size, __LINE__)
100 
101 static WCHAR *strdupAtoW(const char *str)
102 {
103  WCHAR *ret = NULL;
104  DWORD len;
105 
106  if (!str) return ret;
107  len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
108  ret = heap_alloc(len * sizeof(WCHAR));
109  if (ret)
110  MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
111  return ret;
112 }
113 
115 {
116  HRESULT hr;
117 
118  hr = IXmlWriter_SetProperty(writer, property, TRUE);
119  ok(hr == S_OK, "Failed to set writer property, hr %#x.\n", hr);
120 }
121 
122 /* used to test all Write* methods for consistent error state */
123 static void check_writer_state(IXmlWriter *writer, HRESULT exp_hr)
124 {
125  static const WCHAR aW[] = {'a',0};
126  HRESULT hr;
127 
128  /* FIXME: add WriteAttributes */
129 
130  hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, aW);
131  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
132 
133  hr = IXmlWriter_WriteCData(writer, aW);
134  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
135 
136  hr = IXmlWriter_WriteCharEntity(writer, aW[0]);
137  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
138 
139  hr = IXmlWriter_WriteChars(writer, aW, 1);
140  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
141 
142  hr = IXmlWriter_WriteComment(writer, aW);
143  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
144 
145  hr = IXmlWriter_WriteDocType(writer, aW, NULL, NULL, NULL);
146  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
147 
148  hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, aW);
149  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
150 
151  hr = IXmlWriter_WriteEndDocument(writer);
152  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
153 
154  hr = IXmlWriter_WriteEndElement(writer);
155  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
156 
157  hr = IXmlWriter_WriteEntityRef(writer, aW);
158  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
159 
160  hr = IXmlWriter_WriteFullEndElement(writer);
161  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
162 
163  hr = IXmlWriter_WriteName(writer, aW);
164  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
165 
166  hr = IXmlWriter_WriteNmToken(writer, aW);
167  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
168 
169  /* FIXME: add WriteNode */
170  /* FIXME: add WriteNodeShallow */
171 
172  hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
173  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
174 
175  hr = IXmlWriter_WriteQualifiedName(writer, aW, NULL);
176  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
177 
178  hr = IXmlWriter_WriteRaw(writer, aW);
179  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
180 
181  hr = IXmlWriter_WriteRawChars(writer, aW, 1);
182  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
183 
184  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
185  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
186 
187  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
188  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
189 
190  hr = IXmlWriter_WriteString(writer, aW);
191  ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
192 
193  /* FIXME: add WriteSurrogateCharEntity */
194  /* FIXME: add WriteWhitespace */
195 }
196 
198 {
199  IStream *stream;
200  HRESULT hr;
201 
203  ok(hr == S_OK, "got 0x%08x\n", hr);
204 
205  hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
206  ok(hr == S_OK, "got 0x%08x\n", hr);
207 
208  return stream;
209 }
210 
212 {
213  if (IsEqualGUID(riid, &IID_IUnknown)) {
214  *obj = iface;
215  return S_OK;
216  }
217  else {
218  ok(0, "unknown riid=%s\n", wine_dbgstr_guid(riid));
219  return E_NOINTERFACE;
220  }
221 }
222 
224 {
225  return 2;
226 }
227 
229 {
230  return 1;
231 }
232 
233 static const IUnknownVtbl testoutputvtbl = {
237 };
238 
240 
242 {
243  if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
244  {
245  *obj = iface;
246  return S_OK;
247  }
248 
249  *obj = NULL;
250  return E_NOINTERFACE;
251 }
252 
254 {
255  return 2;
256 }
257 
259 {
260  return 1;
261 }
262 
264 {
265  ok(0, "unexpected call\n");
266  return E_NOTIMPL;
267 }
268 
270 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
271 {
272  g_write_len = cb;
273  *written = cb;
274  return S_OK;
275 }
276 
277 static const ISequentialStreamVtbl teststreamvtbl =
278 {
284 };
285 
287 
288 static void test_writer_create(void)
289 {
290  HRESULT hr;
291  IXmlWriter *writer;
292  LONG_PTR value;
293  IUnknown *unk;
294 
295  /* crashes native */
296  if (0)
297  {
298  CreateXmlWriter(&IID_IXmlWriter, NULL, NULL);
299  CreateXmlWriter(NULL, (void**)&writer, NULL);
300  }
301 
302  hr = CreateXmlWriter(&IID_IStream, (void **)&unk, NULL);
303  ok(hr == E_NOINTERFACE, "got %08x\n", hr);
304 
305  hr = CreateXmlWriter(&IID_IUnknown, (void **)&unk, NULL);
306  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
307  hr = IUnknown_QueryInterface(unk, &IID_IXmlWriter, (void **)&writer);
308  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
309  ok(unk == (IUnknown *)writer, "unexpected interface pointer\n");
310  IUnknown_Release(unk);
311  IXmlWriter_Release(writer);
312 
313  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
314  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
315 
316  /* check default properties values */
317  value = 0;
318  hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ByteOrderMark, &value);
319  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
320  ok(value == TRUE, "got %ld\n", value);
321 
322  value = TRUE;
323  hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_Indent, &value);
324  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
325  ok(value == FALSE, "got %ld\n", value);
326 
327  value = TRUE;
328  hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, &value);
329  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
330  ok(value == FALSE, "got %ld\n", value);
331 
333  hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ConformanceLevel, &value);
334  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
335  ok(value == XmlConformanceLevel_Document, "got %ld\n", value);
336 
337  IXmlWriter_Release(writer);
338 }
339 
341 {
342  HRESULT hr;
343 
344  hr = IXmlWriter_SetOutput(writer, output);
345  ok(hr == S_OK, "Failed to set output, hr %#x.\n", hr);
346 
347  /* TODO: WriteAttributes */
348 
349  hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, aW);
350  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
351 
352  hr = IXmlWriter_WriteCData(writer, aW);
353  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
354 
355  hr = IXmlWriter_WriteCharEntity(writer, 0x100);
356  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
357 
358  hr = IXmlWriter_WriteChars(writer, aW, 1);
359  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
360 
361  hr = IXmlWriter_WriteComment(writer, aW);
362  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
363 
364  hr = IXmlWriter_WriteDocType(writer, aW, NULL, NULL, NULL);
365  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
366 
367  hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
368  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
369 
370  hr = IXmlWriter_WriteEndDocument(writer);
371  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
372 
373  hr = IXmlWriter_WriteEndElement(writer);
374  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
375 
376  hr = IXmlWriter_WriteEntityRef(writer, aW);
377  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
378 
379  hr = IXmlWriter_WriteFullEndElement(writer);
380  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
381 
382  hr = IXmlWriter_WriteName(writer, aW);
383  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
384 
385  hr = IXmlWriter_WriteNmToken(writer, aW);
386  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
387 
388  /* TODO: WriteNode */
389  /* TODO: WriteNodeShallow */
390 
391  hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
392  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
393 
394  hr = IXmlWriter_WriteQualifiedName(writer, aW, NULL);
395  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
396 
397  hr = IXmlWriter_WriteRaw(writer, aW);
398  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
399 
400  hr = IXmlWriter_WriteRawChars(writer, aW, 1);
401  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
402 
403  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
404  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
405 
406  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
407  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
408 
409  hr = IXmlWriter_WriteString(writer, aW);
410  ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
411 
412  /* TODO: WriteSurrogateCharEntity */
413  /* ًُُTODO: WriteWhitespace */
414 
415  hr = IXmlWriter_Flush(writer);
416  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
417 }
418 
419 static void test_writeroutput(void)
420 {
421  static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
422  static const WCHAR usasciiW[] = {'u','s','-','a','s','c','i','i',0};
423  static const WCHAR dummyW[] = {'d','u','m','m','y',0};
424  static const WCHAR utf16_outputW[] = {0xfeff,'<','a'};
426  IXmlWriter *writer;
427  IStream *stream;
428  IUnknown *unk;
429  HRESULT hr;
430 
431  output = NULL;
433  ok(hr == S_OK, "got %08x\n", hr);
434  EXPECT_REF(output, 1);
435  IUnknown_Release(output);
436 
438  ok(hr == S_OK, "got %08x\n", hr);
439  unk = NULL;
440  hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
441  ok(hr == S_OK, "got %08x\n", hr);
442 todo_wine
443  ok(unk != NULL && unk != output, "got %p, output %p\n", unk, output);
444  EXPECT_REF(output, 2);
445  /* releasing 'unk' crashes on native */
446  IUnknown_Release(output);
447  EXPECT_REF(output, 1);
448  IUnknown_Release(output);
449 
450  output = NULL;
452  ok(hr == S_OK, "got %08x\n", hr);
453  IUnknown_Release(output);
454 
456  ok(hr == S_OK, "got %08x\n", hr);
457  unk = NULL;
458  hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
459  ok(hr == S_OK, "got %08x\n", hr);
460  ok(unk != NULL, "got %p\n", unk);
461  /* releasing 'unk' crashes on native */
462  IUnknown_Release(output);
463  IUnknown_Release(output);
464 
465  /* create with us-ascii */
466  output = NULL;
468  ok(hr == S_OK, "got %08x\n", hr);
469  IUnknown_Release(output);
470 
471  /* Output with codepage 1200. */
472  hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
473  ok(hr == S_OK, "Failed to create writer, hr %#x.\n", hr);
474 
476  ok(hr == S_OK, "Failed to create stream, hr %#x.\n", hr);
477 
479  ok(hr == S_OK, "Failed to create writer output, hr %#x.\n", hr);
480 
481  hr = IXmlWriter_SetOutput(writer, output);
482  ok(hr == S_OK, "Failed to set writer output, hr %#x.\n", hr);
483 
484  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
485  ok(hr == S_OK, "Write failed, hr %#x.\n", hr);
486 
487  hr = IXmlWriter_Flush(writer);
488  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
489 
490  CHECK_OUTPUT_RAW(stream, utf16_outputW, sizeof(utf16_outputW));
491 
492  IStream_Release(stream);
493  IUnknown_Release(output);
494 
495  /* Create output with meaningless code page value. */
497  ok(hr == S_OK, "Failed to create stream, hr %#x.\n", hr);
498 
499  output = NULL;
501  ok(hr == S_OK, "Failed to create writer output, hr %#x.\n", hr);
502 
504  CHECK_OUTPUT(stream, "");
505 
506  IStream_Release(stream);
507  IUnknown_Release(output);
508 
509  /* Same, with invalid encoding name. */
511  ok(hr == S_OK, "got 0x%08x\n", hr);
512 
513  output = NULL;
515  ok(hr == S_OK, "got %08x\n", hr);
516 
518  CHECK_OUTPUT(stream, "");
519 
520  IStream_Release(stream);
521  IUnknown_Release(output);
522 
523  IXmlWriter_Release(writer);
524 }
525 
526 static void test_writestartdocument(void)
527 {
528  static const char fullprolog[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
529  static const char *prologversion2 = "<?xml version=\"1.0\" encoding=\"uS-asCii\"?>";
530  static const char prologversion[] = "<?xml version=\"1.0\"?>";
531  static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
532  static const WCHAR usasciiW[] = {'u','S','-','a','s','C','i','i',0};
533  static const WCHAR xmlW[] = {'x','m','l',0};
535  IXmlWriter *writer;
536  IStream *stream;
537  HRESULT hr;
538 
539  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
540  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
541 
542  /* output not set */
543  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
544  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
545 
546  hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
547  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
548 
549  hr = IXmlWriter_Flush(writer);
550  ok(hr == S_OK, "got 0x%08x\n", hr);
551 
552  stream = writer_set_output(writer);
553 
554  /* nothing written yet */
555  hr = IXmlWriter_Flush(writer);
556  ok(hr == S_OK, "got 0x%08x\n", hr);
557 
558  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
559  ok(hr == S_OK, "got 0x%08x\n", hr);
560 
561  hr = IXmlWriter_Flush(writer);
562  ok(hr == S_OK, "got 0x%08x\n", hr);
563 
564  CHECK_OUTPUT(stream, fullprolog);
565 
566  /* one more time */
567  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
568  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
569  IStream_Release(stream);
570 
571  /* now add PI manually, and try to start a document */
572  stream = writer_set_output(writer);
573 
574  hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
575  ok(hr == S_OK, "got 0x%08x\n", hr);
576 
577  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
578  ok(hr == S_OK, "got 0x%08x\n", hr);
579 
580  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
581  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
582 
583  /* another attempt to add 'xml' PI */
584  hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
585  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
586 
587  hr = IXmlWriter_Flush(writer);
588  ok(hr == S_OK, "got 0x%08x\n", hr);
589 
590  CHECK_OUTPUT(stream, prologversion);
591 
592  IStream_Release(stream);
593  IXmlWriter_Release(writer);
594 
595  /* create with us-ascii */
597  ok(hr == S_OK, "got 0x%08x\n", hr);
598 
599  output = NULL;
601  ok(hr == S_OK, "got %08x\n", hr);
602 
603  hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
604  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
605 
606  hr = IXmlWriter_SetOutput(writer, output);
607  ok(hr == S_OK, "got %08x\n", hr);
608 
609  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
610  ok(hr == S_OK, "got 0x%08x\n", hr);
611 
612  hr = IXmlWriter_Flush(writer);
613  ok(hr == S_OK, "got 0x%08x\n", hr);
614 
615  CHECK_OUTPUT(stream, prologversion2);
616 
617  IStream_Release(stream);
618  IXmlWriter_Release(writer);
619  IUnknown_Release(output);
620 }
621 
622 static void test_flush(void)
623 {
624  IXmlWriter *writer;
625  HRESULT hr;
626 
627  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
628  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
629 
630  hr = IXmlWriter_SetOutput(writer, (IUnknown*)&teststream);
631  ok(hr == S_OK, "got 0x%08x\n", hr);
632 
633  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
634  ok(hr == S_OK, "got 0x%08x\n", hr);
635 
636  g_write_len = 0;
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);
640 
641  g_write_len = 1;
642  hr = IXmlWriter_Flush(writer);
643  ok(hr == S_OK, "got 0x%08x\n", hr);
644  ok(g_write_len == 0, "got %d\n", g_write_len);
645 
646  /* Release() flushes too */
647  g_write_len = 1;
648  IXmlWriter_Release(writer);
649  ok(g_write_len == 0, "got %d\n", g_write_len);
650 }
651 
652 static void test_omitxmldeclaration(void)
653 {
654  static const char prologversion[] = "<?xml version=\"1.0\"?>";
655  static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
656  static const WCHAR xmlW[] = {'x','m','l',0};
657  IXmlWriter *writer;
658  HGLOBAL hglobal;
659  IStream *stream;
660  HRESULT hr;
661  char *ptr;
662 
663  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
664  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
665 
666  stream = writer_set_output(writer);
667 
669 
670  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
671  ok(hr == S_OK, "got 0x%08x\n", hr);
672 
673  hr = IXmlWriter_Flush(writer);
674  ok(hr == S_OK, "got 0x%08x\n", hr);
675 
676  hr = GetHGlobalFromStream(stream, &hglobal);
677  ok(hr == S_OK, "got 0x%08x\n", hr);
678 
679  ptr = GlobalLock(hglobal);
680  ok(!ptr, "got %p\n", ptr);
681  GlobalUnlock(hglobal);
682 
683  /* one more time */
684  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
685  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
686 
687  IStream_Release(stream);
688 
689  /* now add PI manually, and try to start a document */
690  stream = writer_set_output(writer);
691 
692  hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
693  ok(hr == S_OK, "got 0x%08x\n", hr);
694 
695  hr = IXmlWriter_Flush(writer);
696  ok(hr == S_OK, "got 0x%08x\n", hr);
697 
698  CHECK_OUTPUT(stream, prologversion);
699 
700  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
701  ok(hr == S_OK, "got 0x%08x\n", hr);
702 
703  hr = IXmlWriter_Flush(writer);
704  ok(hr == S_OK, "got 0x%08x\n", hr);
705 
706  CHECK_OUTPUT(stream, prologversion);
707 
708  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
709  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
710 
711  hr = IXmlWriter_Flush(writer);
712  ok(hr == S_OK, "got 0x%08x\n", hr);
713 
714  CHECK_OUTPUT(stream, prologversion);
715 
716  /* another attempt to add 'xml' PI */
717  hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
718  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
719 
720  hr = IXmlWriter_Flush(writer);
721  ok(hr == S_OK, "got 0x%08x\n", hr);
722 
723  IStream_Release(stream);
724  IXmlWriter_Release(writer);
725 }
726 
727 static void test_bom(void)
728 {
729  static const WCHAR piW[] = {0xfeff,'<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>'};
730  static const WCHAR aopenW[] = {0xfeff,'<','a'};
731  static const WCHAR afullW[] = {0xfeff,'<','a',' ','/','>'};
732  static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
733  static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
734  static const WCHAR xmlW[] = {'x','m','l',0};
735  static const WCHAR bomW[] = {0xfeff};
737  IXmlWriter *writer;
738  IStream *stream;
739  HGLOBAL hglobal;
740  HRESULT hr;
741 
743  ok(hr == S_OK, "got 0x%08x\n", hr);
744 
746  ok(hr == S_OK, "got %08x\n", hr);
747 
748  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
749  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
750 
752 
753  hr = IXmlWriter_SetOutput(writer, output);
754  ok(hr == S_OK, "got 0x%08x\n", hr);
755 
756  /* BOM is on by default */
757  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
758  ok(hr == S_OK, "got 0x%08x\n", hr);
759 
760  hr = IXmlWriter_Flush(writer);
761  ok(hr == S_OK, "got 0x%08x\n", hr);
762 
763  CHECK_OUTPUT_RAW(stream, bomW, sizeof(bomW));
764 
765  IStream_Release(stream);
766  IUnknown_Release(output);
767 
768  /* start with PI */
770  ok(hr == S_OK, "got 0x%08x\n", hr);
771 
773  ok(hr == S_OK, "got %08x\n", hr);
774 
775  hr = IXmlWriter_SetOutput(writer, output);
776  ok(hr == S_OK, "got 0x%08x\n", hr);
777 
778  hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
779  ok(hr == S_OK, "got 0x%08x\n", hr);
780 
781  hr = IXmlWriter_Flush(writer);
782  ok(hr == S_OK, "got 0x%08x\n", hr);
783 
784  CHECK_OUTPUT_RAW(stream, piW, sizeof(piW));
785 
786  IUnknown_Release(output);
787  IStream_Release(stream);
788 
789  /* start with element */
791  ok(hr == S_OK, "got 0x%08x\n", hr);
792 
794  ok(hr == S_OK, "got %08x\n", hr);
795 
796  hr = IXmlWriter_SetOutput(writer, output);
797  ok(hr == S_OK, "got 0x%08x\n", hr);
798 
799  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
800  ok(hr == S_OK, "got 0x%08x\n", hr);
801 
802  hr = IXmlWriter_Flush(writer);
803  ok(hr == S_OK, "got 0x%08x\n", hr);
804 
805  CHECK_OUTPUT_RAW(stream, aopenW, sizeof(aopenW));
806 
807  IUnknown_Release(output);
808  IStream_Release(stream);
809 
810  /* WriteElementString */
812  ok(hr == S_OK, "got 0x%08x\n", hr);
813 
815  ok(hr == S_OK, "got %08x\n", hr);
816 
817  hr = IXmlWriter_SetOutput(writer, output);
818  ok(hr == S_OK, "got 0x%08x\n", hr);
819 
821 
822  hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
823  ok(hr == S_OK, "got 0x%08x\n", hr);
824 
825  hr = IXmlWriter_Flush(writer);
826  ok(hr == S_OK, "got 0x%08x\n", hr);
827 
828  hr = GetHGlobalFromStream(stream, &hglobal);
829  ok(hr == S_OK, "got 0x%08x\n", hr);
830 
831  CHECK_OUTPUT_RAW(stream, afullW, sizeof(afullW));
832 
833  IUnknown_Release(output);
834  IStream_Release(stream);
835 
836  IXmlWriter_Release(writer);
837 }
838 
839 static HRESULT write_start_element(IXmlWriter *writer, const char *prefix, const char *local,
840  const char *uri)
841 {
842  WCHAR *prefixW, *localW, *uriW;
843  HRESULT hr;
844 
845  prefixW = strdupAtoW(prefix);
846  localW = strdupAtoW(local);
847  uriW = strdupAtoW(uri);
848 
849  hr = IXmlWriter_WriteStartElement(writer, prefixW, localW, uriW);
850 
851  heap_free(prefixW);
852  heap_free(localW);
853  heap_free(uriW);
854 
855  return hr;
856 }
857 
858 static HRESULT write_element_string(IXmlWriter *writer, const char *prefix, const char *local,
859  const char *uri, const char *value)
860 {
861  WCHAR *prefixW, *localW, *uriW, *valueW;
862  HRESULT hr;
863 
864  prefixW = strdupAtoW(prefix);
865  localW = strdupAtoW(local);
866  uriW = strdupAtoW(uri);
868 
869  hr = IXmlWriter_WriteElementString(writer, prefixW, localW, uriW, valueW);
870 
871  heap_free(prefixW);
872  heap_free(localW);
873  heap_free(uriW);
874  heap_free(valueW);
875 
876  return hr;
877 }
878 
879 static HRESULT write_string(IXmlWriter *writer, const char *str)
880 {
881  WCHAR *strW;
882  HRESULT hr;
883 
884  strW = strdupAtoW(str);
885 
886  hr = IXmlWriter_WriteString(writer, strW);
887 
888  heap_free(strW);
889 
890  return hr;
891 }
892 
893 static void test_WriteStartElement(void)
894 {
895  static const struct
896  {
897  const char *prefix;
898  const char *local;
899  const char *uri;
900  const char *output;
901  const char *output_partial;
902  HRESULT hr;
903  int todo;
904  int todo_partial;
905  }
906  start_element_tests[] =
907  {
908  { "prefix", "local", "uri", "<prefix:local xmlns:prefix=\"uri\" />", "<prefix:local" },
909  { NULL, "local", "uri", "<local xmlns=\"uri\" />", "<local" },
910  { "", "local", "uri", "<local xmlns=\"uri\" />", "<local" },
911  { "", "local", "uri", "<local xmlns=\"uri\" />", "<local" },
912 
913  { "prefix", NULL, NULL, NULL, NULL, E_INVALIDARG },
914  { NULL, NULL, "uri", NULL, NULL, E_INVALIDARG },
915  { NULL, NULL, NULL, NULL, NULL, E_INVALIDARG },
916  { NULL, "prefix:local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
917  { "pre:fix", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
918  { NULL, ":local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
919  { ":", "local", "uri", NULL, NULL, WC_E_NAMECHARACTER },
920  { NULL, "local", "http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSPREFIXDECLARATION },
921  { "prefix", "local", "http://www.w3.org/2000/xmlns/", NULL, NULL, WR_E_XMLNSURIDECLARATION },
922  };
923  static const WCHAR aW[] = {'a',0};
924  IXmlWriter *writer;
925  IStream *stream;
926  unsigned int i;
927  HRESULT hr;
928 
929  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
930  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
931 
932  hr = write_start_element(writer, NULL, "a", NULL);
933  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
934 
935  stream = writer_set_output(writer);
936 
937  hr = write_start_element(writer, NULL, "a", NULL);
938  ok(hr == S_OK, "got 0x%08x\n", hr);
939 
940  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
941  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
942 
943  hr = IXmlWriter_Flush(writer);
944  ok(hr == S_OK, "got 0x%08x\n", hr);
945 
946  CHECK_OUTPUT(stream, "<a");
947 
948  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
949  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
950 
951  hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
952  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
953 
954  hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
955  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
956 
957  IStream_Release(stream);
958  IXmlWriter_Release(writer);
959 
960  /* WriteElementString */
961  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
962  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
963 
964  hr = write_element_string(writer, NULL, "b", NULL, "value");
965  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
966 
967  stream = writer_set_output(writer);
968 
969  hr = write_start_element(writer, "prefix", "a", "uri");
970  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
971 
972  hr = write_element_string(writer, NULL, "b", NULL, "value");
973  ok(hr == S_OK, "Failed to write element string, hr %#x.\n", hr);
974 
975  hr = write_element_string(writer, NULL, "c", NULL, NULL);
976  ok(hr == S_OK, "Failed to write element string, hr %#x.\n", hr);
977 
978  hr = write_start_element(writer, NULL, "d", "uri");
979  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
980 
981  hr = write_start_element(writer, "", "e", "uri");
982  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
983 
984  hr = write_start_element(writer, "prefix2", "f", "uri");
985  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
986 
987  hr = IXmlWriter_Flush(writer);
988  ok(hr == S_OK, "got 0x%08x\n", hr);
989 
991  "<prefix:a xmlns:prefix=\"uri\">"
992  "<b>value</b>"
993  "<c />"
994  "<prefix:d>"
995  "<e xmlns=\"uri\">"
996  "<prefix2:f");
997 
998  IStream_Release(stream);
999 
1000  /* WriteStartElement */
1001  for (i = 0; i < ARRAY_SIZE(start_element_tests); ++i)
1002  {
1003  stream = writer_set_output(writer);
1004 
1006 
1007  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1008  ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
1009 
1010  hr = write_start_element(writer, start_element_tests[i].prefix, start_element_tests[i].local,
1011  start_element_tests[i].uri);
1012  ok(hr == start_element_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
1013 
1014  if (SUCCEEDED(start_element_tests[i].hr))
1015  {
1016  hr = IXmlWriter_Flush(writer);
1017  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1018 
1019  check_output(stream, start_element_tests[i].output_partial, start_element_tests[i].todo_partial, __LINE__);
1020 
1021  hr = IXmlWriter_WriteEndDocument(writer);
1022  ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr);
1023 
1024  hr = IXmlWriter_Flush(writer);
1025  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1026 
1027  check_output(stream, start_element_tests[i].output, start_element_tests[i].todo, __LINE__);
1028  }
1029 
1030  IStream_Release(stream);
1031  }
1032 
1033  IXmlWriter_Release(writer);
1034 }
1035 
1036 static void test_WriteElementString(void)
1037 {
1038  static const struct
1039  {
1040  const char *prefix;
1041  const char *local;
1042  const char *uri;
1043  const char *value;
1044  const char *output;
1045  HRESULT hr;
1046  int todo;
1047  }
1048  element_string_tests[] =
1049  {
1050  { "prefix", "local", "uri", "value", "<prefix:local xmlns:prefix=\"uri\">value</prefix:local>" },
1051  { NULL, "local", "uri", "value", "<local xmlns=\"uri\">value</local>" },
1052  { "", "local", "uri", "value", "<local xmlns=\"uri\">value</local>" },
1053  { "prefix", "local", "uri", NULL, "<prefix:local xmlns:prefix=\"uri\" />" },
1054  { NULL, "local", "uri", NULL, "<local xmlns=\"uri\" />" },
1055  { "", "local", "uri", NULL, "<local xmlns=\"uri\" />" },
1056  { NULL, "local", NULL, NULL, "<local />" },
1057  { "prefix", "local", "uri", "", "<prefix:local xmlns:prefix=\"uri\"></prefix:local>" },
1058  { NULL, "local", "uri", "", "<local xmlns=\"uri\"></local>" },
1059  { "", "local", "uri", "", "<local xmlns=\"uri\"></local>" },
1060  { NULL, "local", NULL, "", "<local></local>" },
1061  { "", "local", "http://www.w3.org/2000/xmlns/", NULL, "<local xmlns=\"http://www.w3.org/2000/xmlns/\" />" },
1062 
1063  { "prefix", NULL, NULL, "value", NULL, E_INVALIDARG },
1064  { NULL, NULL, "uri", "value", NULL, E_INVALIDARG },
1065  { NULL, NULL, NULL, "value", NULL, E_INVALIDARG },
1066  { NULL, "prefix:local", "uri", "value", NULL, WC_E_NAMECHARACTER },
1067  { NULL, ":local", "uri", "value", NULL, WC_E_NAMECHARACTER },
1068  { ":", "local", "uri", "value", NULL, WC_E_NAMECHARACTER },
1069  { "prefix", "local", NULL, "value", NULL, WR_E_NSPREFIXWITHEMPTYNSURI },
1070  { "prefix", "local", "", "value", NULL, WR_E_NSPREFIXWITHEMPTYNSURI },
1071  { NULL, "local", "http://www.w3.org/2000/xmlns/", "value", NULL, WR_E_XMLNSPREFIXDECLARATION },
1072  { "prefix", "local", "http://www.w3.org/2000/xmlns/", "value", NULL, WR_E_XMLNSURIDECLARATION },
1073  };
1074  IXmlWriter *writer;
1075  IStream *stream;
1076  unsigned int i;
1077  HRESULT hr;
1078 
1079  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1080  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1081 
1082  hr = write_element_string(writer, NULL, "b", NULL, "value");
1083  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1084 
1085  stream = writer_set_output(writer);
1086 
1087  hr = write_start_element(writer, NULL, "a", NULL);
1088  ok(hr == S_OK, "got 0x%08x\n", hr);
1089 
1090  hr = write_element_string(writer, NULL, "b", NULL, "value");
1091  ok(hr == S_OK, "got 0x%08x\n", hr);
1092 
1093  hr = write_element_string(writer, NULL, "b", NULL, NULL);
1094  ok(hr == S_OK, "got 0x%08x\n", hr);
1095 
1096  hr = write_element_string(writer, "prefix", "b", "uri", NULL);
1097  ok(hr == S_OK, "got 0x%08x\n", hr);
1098 
1099  hr = write_start_element(writer, "prefix", "c", "uri");
1100  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
1101 
1102  hr = write_element_string(writer, "prefix", "d", NULL, NULL);
1103  ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1104 
1105  hr = write_element_string(writer, "prefix2", "d", "uri", NULL);
1106  ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1107 
1108  hr = write_element_string(writer, NULL, "e", "uri", NULL);
1109  ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1110 
1111  hr = write_element_string(writer, "prefix", "f", "uri2", NULL);
1112  ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1113 
1114  hr = write_element_string(writer, NULL, "g", "uri3", NULL);
1115  ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1116 
1117  hr = write_element_string(writer, "prefix", "h", NULL, NULL);
1118  ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1119 
1120  hr = write_element_string(writer, "prefix_i", "i", NULL, NULL);
1121  ok(hr == WR_E_NSPREFIXWITHEMPTYNSURI, "Failed to write element, hr %#x.\n", hr);
1122 
1123  hr = write_element_string(writer, "", "j", "uri", NULL);
1124  ok(hr == S_OK, "Failed to write element, hr %#x.\n", hr);
1125 
1126  hr = IXmlWriter_Flush(writer);
1127  ok(hr == S_OK, "got 0x%08x\n", hr);
1128 
1130  "<a><b>value</b><b />"
1131  "<prefix:b xmlns:prefix=\"uri\" />"
1132  "<prefix:c xmlns:prefix=\"uri\">"
1133  "<prefix:d />"
1134  "<prefix2:d xmlns:prefix2=\"uri\" />"
1135  "<prefix:e />"
1136  "<prefix:f xmlns:prefix=\"uri2\" />"
1137  "<g xmlns=\"uri3\" />"
1138  "<prefix:h />"
1139  "<j xmlns=\"uri\" />");
1140 
1141  IStream_Release(stream);
1142 
1143  for (i = 0; i < ARRAY_SIZE(element_string_tests); ++i)
1144  {
1145  stream = writer_set_output(writer);
1146 
1148 
1149  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1150  ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
1151 
1152  hr = write_element_string(writer, element_string_tests[i].prefix, element_string_tests[i].local,
1153  element_string_tests[i].uri, element_string_tests[i].value);
1154  ok(hr == element_string_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
1155 
1156  if (SUCCEEDED(element_string_tests[i].hr))
1157  {
1158  hr = IXmlWriter_Flush(writer);
1159  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1160 
1161  check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__);
1162 
1163  hr = IXmlWriter_WriteEndDocument(writer);
1164  ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr);
1165 
1166  hr = IXmlWriter_Flush(writer);
1167  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1168 
1169  check_output(stream, element_string_tests[i].output, element_string_tests[i].todo, __LINE__);
1170  }
1171 
1172  IStream_Release(stream);
1173  }
1174 
1175  IXmlWriter_Release(writer);
1176 }
1177 
1178 static void test_WriteEndElement(void)
1179 {
1180  IXmlWriter *writer;
1181  IStream *stream;
1182  HRESULT hr;
1183 
1184  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1185  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1186 
1187  stream = writer_set_output(writer);
1188 
1189  hr = write_start_element(writer, NULL, "a", NULL);
1190  ok(hr == S_OK, "got 0x%08x\n", hr);
1191 
1192  hr = write_start_element(writer, NULL, "b", NULL);
1193  ok(hr == S_OK, "got 0x%08x\n", hr);
1194 
1195  hr = IXmlWriter_WriteEndElement(writer);
1196  ok(hr == S_OK, "got 0x%08x\n", hr);
1197 
1198  hr = IXmlWriter_WriteEndElement(writer);
1199  ok(hr == S_OK, "got 0x%08x\n", hr);
1200 
1201  hr = IXmlWriter_Flush(writer);
1202  ok(hr == S_OK, "got 0x%08x\n", hr);
1203 
1204  CHECK_OUTPUT(stream, "<a><b /></a>");
1205 
1206  IXmlWriter_Release(writer);
1207  IStream_Release(stream);
1208 }
1209 
1210 static void test_writeenddocument(void)
1211 {
1212  static const WCHAR aW[] = {'a',0};
1213  static const WCHAR bW[] = {'b',0};
1214  IXmlWriter *writer;
1215  IStream *stream;
1216  HGLOBAL hglobal;
1217  HRESULT hr;
1218  char *ptr;
1219 
1220  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1221  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1222 
1223  hr = IXmlWriter_WriteEndDocument(writer);
1224  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1225 
1226  stream = writer_set_output(writer);
1227 
1228  /* WriteEndDocument resets it to initial state */
1229  hr = IXmlWriter_WriteEndDocument(writer);
1230  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1231 
1232  hr = IXmlWriter_WriteEndDocument(writer);
1233  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1234 
1235  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1236  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1237 
1238  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1239  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1240 
1241  hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
1242  ok(hr == S_OK, "got 0x%08x\n", hr);
1243 
1244  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1245  ok(hr == S_OK, "got 0x%08x\n", hr);
1246 
1247  hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
1248  ok(hr == S_OK, "got 0x%08x\n", hr);
1249 
1250  hr = IXmlWriter_WriteEndDocument(writer);
1251  ok(hr == S_OK, "got 0x%08x\n", hr);
1252 
1253  hr = GetHGlobalFromStream(stream, &hglobal);
1254  ok(hr == S_OK, "got 0x%08x\n", hr);
1255 
1256  ptr = GlobalLock(hglobal);
1257  ok(ptr == NULL, "got %p\n", ptr);
1258 
1259  /* we still need to flush manually, WriteEndDocument doesn't do that */
1260  hr = IXmlWriter_Flush(writer);
1261  ok(hr == S_OK, "got 0x%08x\n", hr);
1262 
1263  CHECK_OUTPUT(stream, "<a><b /></a>");
1264 
1265  IXmlWriter_Release(writer);
1266  IStream_Release(stream);
1267 }
1268 
1269 static void test_WriteComment(void)
1270 {
1271  static const WCHAR closeW[] = {'-','-','>',0};
1272  static const WCHAR aW[] = {'a',0};
1273  static const WCHAR bW[] = {'b',0};
1274  IXmlWriter *writer;
1275  IStream *stream;
1276  HRESULT hr;
1277 
1278  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1279  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1280 
1282 
1283  hr = IXmlWriter_WriteComment(writer, aW);
1284  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1285 
1286  stream = writer_set_output(writer);
1287 
1288  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1289  ok(hr == S_OK, "got 0x%08x\n", hr);
1290 
1291  hr = IXmlWriter_WriteComment(writer, aW);
1292  ok(hr == S_OK, "got 0x%08x\n", hr);
1293 
1294  hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
1295  ok(hr == S_OK, "got 0x%08x\n", hr);
1296 
1297  hr = IXmlWriter_WriteComment(writer, aW);
1298  ok(hr == S_OK, "got 0x%08x\n", hr);
1299 
1300  hr = IXmlWriter_WriteComment(writer, NULL);
1301  ok(hr == S_OK, "got 0x%08x\n", hr);
1302 
1303  hr = IXmlWriter_WriteComment(writer, closeW);
1304  ok(hr == S_OK, "got 0x%08x\n", hr);
1305 
1306  hr = IXmlWriter_Flush(writer);
1307  ok(hr == S_OK, "got 0x%08x\n", hr);
1308 
1309  CHECK_OUTPUT(stream, "<!--a--><b><!--a--><!----><!--- ->-->");
1310 
1311  IXmlWriter_Release(writer);
1312  IStream_Release(stream);
1313 }
1314 
1315 static void test_WriteCData(void)
1316 {
1317  static const WCHAR closeW[] = {']',']','>',0};
1318  static const WCHAR close2W[] = {'a',']',']','>','b',0};
1319  static const WCHAR aW[] = {'a',0};
1320  static const WCHAR bW[] = {'b',0};
1321  IXmlWriter *writer;
1322  IStream *stream;
1323  HRESULT hr;
1324 
1325  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1326  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1327 
1329 
1330  hr = IXmlWriter_WriteCData(writer, aW);
1331  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1332 
1333  stream = writer_set_output(writer);
1334 
1335  hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
1336  ok(hr == S_OK, "got 0x%08x\n", hr);
1337 
1338  hr = IXmlWriter_WriteCData(writer, aW);
1339  ok(hr == S_OK, "got 0x%08x\n", hr);
1340 
1341  hr = IXmlWriter_WriteCData(writer, NULL);
1342  ok(hr == S_OK, "got 0x%08x\n", hr);
1343 
1344  hr = IXmlWriter_WriteCData(writer, closeW);
1345  ok(hr == S_OK, "got 0x%08x\n", hr);
1346 
1347  hr = IXmlWriter_WriteCData(writer, close2W);
1348  ok(hr == S_OK, "got 0x%08x\n", hr);
1349 
1350  hr = IXmlWriter_Flush(writer);
1351  ok(hr == S_OK, "got 0x%08x\n", hr);
1352 
1354  "<b>"
1355  "<![CDATA[a]]>"
1356  "<![CDATA[]]>"
1357  "<![CDATA[]]]]>"
1358  "<![CDATA[>]]>"
1359  "<![CDATA[a]]]]>"
1360  "<![CDATA[>b]]>");
1361 
1362  IXmlWriter_Release(writer);
1363  IStream_Release(stream);
1364 }
1365 
1366 static void test_WriteRaw(void)
1367 {
1368  static const WCHAR rawW[] = {'a','<',':',0};
1369  static const WCHAR aW[] = {'a',0};
1370  IXmlWriter *writer;
1371  IStream *stream;
1372  HRESULT hr;
1373 
1374  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1375  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1376 
1377  hr = IXmlWriter_WriteRaw(writer, NULL);
1378  ok(hr == S_OK, "got 0x%08x\n", hr);
1379 
1380  hr = IXmlWriter_WriteRaw(writer, rawW);
1381  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1382 
1383  stream = writer_set_output(writer);
1384 
1385  hr = IXmlWriter_WriteRaw(writer, NULL);
1386  ok(hr == S_OK, "got 0x%08x\n", hr);
1387 
1388  hr = IXmlWriter_WriteRaw(writer, rawW);
1389  ok(hr == S_OK, "got 0x%08x\n", hr);
1390 
1391  hr = IXmlWriter_WriteRaw(writer, rawW);
1392  ok(hr == S_OK, "got 0x%08x\n", hr);
1393 
1394  hr = IXmlWriter_WriteComment(writer, rawW);
1395  ok(hr == S_OK, "got 0x%08x\n", hr);
1396 
1397  hr = IXmlWriter_WriteRaw(writer, rawW);
1398  ok(hr == S_OK, "got 0x%08x\n", hr);
1399 
1400  hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, aW);
1401  ok(hr == S_OK, "got 0x%08x\n", hr);
1402 
1403  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
1404  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1405 
1406  hr = IXmlWriter_WriteComment(writer, rawW);
1407  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1408 
1409  hr = IXmlWriter_WriteEndDocument(writer);
1410  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1411 
1412  hr = IXmlWriter_WriteRaw(writer, rawW);
1413  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1414 
1415  hr = IXmlWriter_Flush(writer);
1416  ok(hr == S_OK, "got 0x%08x\n", hr);
1417 
1418  CHECK_OUTPUT(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>a<:a<:<!--a<:-->a<:<a>a</a>");
1419 
1420  IXmlWriter_Release(writer);
1421  IStream_Release(stream);
1422 }
1423 
1424 static void test_writer_state(void)
1425 {
1426  static const WCHAR aW[] = {'a',0};
1427  IXmlWriter *writer;
1428  IStream *stream;
1429  HRESULT hr;
1430 
1431  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1432  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1433 
1434  /* initial state */
1436 
1437  /* set output and call 'wrong' method, WriteEndElement */
1438  stream = writer_set_output(writer);
1439 
1440  hr = IXmlWriter_WriteEndElement(writer);
1441  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1442 
1444  IStream_Release(stream);
1445 
1446  /* WriteAttributeString */
1447  stream = writer_set_output(writer);
1448 
1449  hr = IXmlWriter_WriteAttributeString(writer, NULL, aW, NULL, aW);
1450  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1451 
1453  IStream_Release(stream);
1454 
1455  /* WriteEndDocument */
1456  stream = writer_set_output(writer);
1457 
1458  hr = IXmlWriter_WriteEndDocument(writer);
1459  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1460 
1462  IStream_Release(stream);
1463 
1464  /* WriteFullEndElement */
1465  stream = writer_set_output(writer);
1466 
1467  hr = IXmlWriter_WriteFullEndElement(writer);
1468  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1469 
1471  IStream_Release(stream);
1472 
1473  /* WriteCData */
1474  stream = writer_set_output(writer);
1475 
1476  hr = IXmlWriter_WriteCData(writer, aW);
1477  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1478 
1480  IStream_Release(stream);
1481 
1482  /* WriteName */
1483  stream = writer_set_output(writer);
1484 
1485  hr = IXmlWriter_WriteName(writer, aW);
1486  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1487 
1489  IStream_Release(stream);
1490 
1491  /* WriteNmToken */
1492  stream = writer_set_output(writer);
1493 
1494  hr = IXmlWriter_WriteNmToken(writer, aW);
1495  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1496 
1498  IStream_Release(stream);
1499 
1500  /* WriteString */
1501  stream = writer_set_output(writer);
1502 
1503  hr = IXmlWriter_WriteString(writer, aW);
1504  ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
1505 
1507  IStream_Release(stream);
1508 
1509  IXmlWriter_Release(writer);
1510 }
1511 
1512 static void test_indentation(void)
1513 {
1514  static const WCHAR commentW[] = {'c','o','m','m','e','n','t',0};
1515  static const WCHAR aW[] = {'a',0};
1516  static const WCHAR bW[] = {'b',0};
1517  IXmlWriter *writer;
1518  IStream *stream;
1519  HRESULT hr;
1520 
1521  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1522  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1523 
1524  stream = writer_set_output(writer);
1525 
1528 
1529  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1530  ok(hr == S_OK, "got 0x%08x\n", hr);
1531 
1532  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1533  ok(hr == S_OK, "got 0x%08x\n", hr);
1534 
1535  hr = IXmlWriter_WriteComment(writer, commentW);
1536  ok(hr == S_OK, "got 0x%08x\n", hr);
1537 
1538  hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
1539  ok(hr == S_OK, "got 0x%08x\n", hr);
1540 
1541  hr = IXmlWriter_WriteEndDocument(writer);
1542  ok(hr == S_OK, "got 0x%08x\n", hr);
1543 
1544  hr = IXmlWriter_Flush(writer);
1545  ok(hr == S_OK, "got 0x%08x\n", hr);
1546 
1548  "<a>\r\n"
1549  " <!--comment-->\r\n"
1550  " <b />\r\n"
1551  "</a>");
1552 
1553  IStream_Release(stream);
1554 
1555  /* WriteElementString */
1556  stream = writer_set_output(writer);
1557 
1558  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1559  ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1560 
1561  hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, NULL);
1562  ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1563 
1564  hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, NULL);
1565  ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1566 
1567  hr = IXmlWriter_WriteEndElement(writer);
1568  ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1569 
1570  hr = IXmlWriter_Flush(writer);
1571  ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1572 
1574  "<a>\r\n"
1575  " <b />\r\n"
1576  " <b />\r\n"
1577  "</a>");
1578 
1579  IStream_Release(stream);
1580 
1581  IXmlWriter_Release(writer);
1582 }
1583 
1584 static HRESULT write_attribute_string(IXmlWriter *writer, const char *prefix, const char *local,
1585  const char *uri, const char *value)
1586 {
1587  WCHAR *prefixW, *localW, *uriW, *valueW;
1588  HRESULT hr;
1589 
1590  prefixW = strdupAtoW(prefix);
1591  localW = strdupAtoW(local);
1592  uriW = strdupAtoW(uri);
1593  valueW = strdupAtoW(value);
1594 
1595  hr = IXmlWriter_WriteAttributeString(writer, prefixW, localW, uriW, valueW);
1596 
1597  heap_free(prefixW);
1598  heap_free(localW);
1599  heap_free(uriW);
1600  heap_free(valueW);
1601 
1602  return hr;
1603 }
1604 
1605 static void test_WriteAttributeString(void)
1606 {
1607  static const struct
1608  {
1609  const char *prefix;
1610  const char *local;
1611  const char *uri;
1612  const char *value;
1613  const char *output;
1614  const char *output_partial;
1615  HRESULT hr;
1616  int todo;
1617  int todo_partial;
1618  int todo_hr;
1619  }
1620  attribute_tests[] =
1621  {
1622  { NULL, "a", NULL, "b", "<e a=\"b\" />", "<e a=\"b\"" },
1623  { "", "a", NULL, "b", "<e a=\"b\" />", "<e a=\"b\"" },
1624  { NULL, "a", "", "b", "<e a=\"b\" />", "<e a=\"b\"" },
1625  { "", "a", "", "b", "<e a=\"b\" />", "<e a=\"b\"" },
1626  { "prefix", "local", "uri", "b", "<e prefix:local=\"b\" xmlns:prefix=\"uri\" />", "<e prefix:local=\"b\"" },
1627  { NULL, "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e xmlns:a=\"defuri\" />", "<e xmlns:a=\"defuri\"" },
1628  { "xmlns", "a", NULL, "uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1629  { "xmlns", "a", "", "uri", "<e xmlns:a=\"uri\" />", "<e xmlns:a=\"uri\"" },
1630  { "prefix", "xmlns", "uri", "value", "<e prefix:xmlns=\"value\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"value\"" },
1631  { "prefix", "xmlns", "uri", NULL, "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1632  { "prefix", "xmlns", "uri", "", "<e prefix:xmlns=\"\" xmlns:prefix=\"uri\" />", "<e prefix:xmlns=\"\"" },
1633  { "prefix", "xmlns", NULL, "uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1634  { "prefix", "xmlns", "", "uri", "<e xmlns=\"uri\" />", "<e xmlns=\"uri\"" },
1635  { "xml", "space", NULL, "preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1636  { "xml", "space", "", "preserve", "<e xml:space=\"preserve\" />", "<e xml:space=\"preserve\"" },
1637  { "xml", "space", NULL, "default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1638  { "xml", "space", "", "default", "<e xml:space=\"default\" />", "<e xml:space=\"default\"" },
1639  { "xml", "a", NULL, "value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1640  { "xml", "a", "", "value", "<e xml:a=\"value\" />", "<e xml:a=\"value\"" },
1641 
1642  /* Autogenerated prefix names. */
1643  { NULL, "a", "defuri", NULL, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1644  { NULL, "a", "defuri", "b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK, 1, 1, 1 },
1645  { "", "a", "defuri", NULL, "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1646  { NULL, "a", "defuri", "", "<e p1:a=\"\" xmlns:p1=\"defuri\" />", "<e p1:a=\"\"", S_OK, 1, 1, 1 },
1647  { "", "a", "defuri", "b", "<e p1:a=\"b\" xmlns:p1=\"defuri\" />", "<e p1:a=\"b\"", S_OK, 1, 1, 1 },
1648 
1649  /* Failing cases. */
1650  { NULL, NULL, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG },
1651  { "", "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 1, 1, 1 },
1652  { "", NULL, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG },
1653  { "", "", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG, 1, 1, 1 },
1654  { NULL, "", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG, 1, 1, 1 },
1655  { "prefix", "a", "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", WR_E_XMLNSURIDECLARATION, 1, 1, 1 },
1656  { "prefix", NULL, "http://www.w3.org/2000/xmlns/", "defuri", "<e />", "<e", E_INVALIDARG },
1657  { "prefix", NULL, NULL, "b", "<e />", "<e", E_INVALIDARG },
1658  { "prefix", NULL, "uri", NULL, "<e />", "<e", E_INVALIDARG },
1659  { "xml", NULL, NULL, "value", "<e />", "<e", E_INVALIDARG },
1660  { "xmlns", "a", "defuri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION },
1661  { "xmlns", "a", "b", "uri", "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION },
1662  { NULL, "xmlns", "uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
1663  { "xmlns", NULL, "uri", NULL, "<e />", "<e", WR_E_XMLNSPREFIXDECLARATION, 0, 0, 1 },
1664  { "pre:fix", "local", "uri", "b", "<e />", "<e", WC_E_NAMECHARACTER },
1665  { "pre:fix", NULL, "uri", "b", "<e />", "<e", E_INVALIDARG },
1666  { "prefix", "lo:cal", "uri", "b", "<e />", "<e", WC_E_NAMECHARACTER },
1667  { "xmlns", NULL, NULL, "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1668  { "xmlns", NULL, "", "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1669  { "xmlns", "", NULL, "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1670  { "xmlns", "", "", "uri", "<e />", "<e", WR_E_NSPREFIXDECLARED },
1671  { "xml", "space", "", "value", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1672  { "xml", "space", NULL, "value", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1673  { "xml", "a", "uri", "value", "<e />", "<e", WR_E_XMLPREFIXDECLARATION },
1674  { "xml", "space", NULL, "preServe", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1675  { "xml", "space", NULL, "defAult", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1676  { "xml", "space", NULL, NULL, "<e />", "<e", WR_E_INVALIDXMLSPACE },
1677  { "xml", "space", NULL, "", "<e />", "<e", WR_E_INVALIDXMLSPACE },
1678  };
1679 
1680  IXmlWriter *writer;
1681  IStream *stream;
1682  unsigned int i;
1683  HRESULT hr;
1684 
1685  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1686  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1687 
1689 
1690  for (i = 0; i < ARRAY_SIZE(attribute_tests); ++i)
1691  {
1692  stream = writer_set_output(writer);
1693 
1694  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1695  ok(hr == S_OK, "Failed to start document, hr %#x.\n", hr);
1696 
1697  hr = write_start_element(writer, NULL, "e", NULL);
1698  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
1699 
1700  hr = write_attribute_string(writer, attribute_tests[i].prefix, attribute_tests[i].local,
1701  attribute_tests[i].uri, attribute_tests[i].value);
1702  todo_wine_if(attribute_tests[i].todo_hr)
1703  ok(hr == attribute_tests[i].hr, "%u: unexpected hr %#x, expected %#x.\n", i, hr, attribute_tests[i].hr);
1704 
1705  hr = IXmlWriter_Flush(writer);
1706  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1707 
1708  check_output(stream, attribute_tests[i].output_partial, attribute_tests[i].todo_partial, __LINE__);
1709 
1710  hr = IXmlWriter_WriteEndDocument(writer);
1711  ok(hr == S_OK, "Failed to end document, hr %#x.\n", hr);
1712 
1713  hr = IXmlWriter_Flush(writer);
1714  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1715 
1716  check_output(stream, attribute_tests[i].output, attribute_tests[i].todo, __LINE__);
1717  IStream_Release(stream);
1718  }
1719 
1720  /* With namespaces */
1721  stream = writer_set_output(writer);
1722 
1723  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1724  ok(hr == S_OK, "got 0x%08x\n", hr);
1725 
1726  hr = write_start_element(writer, "p", "a", "outeruri");
1727  ok(hr == S_OK, "got 0x%08x\n", hr);
1728 
1729  hr = write_attribute_string(writer, "prefix", "local", "uri", "b");
1730  ok(hr == S_OK, "got 0x%08x\n", hr);
1731 
1732  hr = write_attribute_string(writer, NULL, "a", NULL, "b");
1733  ok(hr == S_OK, "got 0x%08x\n", hr);
1734 
1735  hr = write_attribute_string(writer, "xmlns", "prefix", NULL, "uri");
1736  ok(hr == S_OK, "got 0x%08x\n", hr);
1737 
1738  hr = write_attribute_string(writer, "p", "attr", NULL, "value");
1739  ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
1740 
1741  hr = write_attribute_string(writer, "prefix", "local", NULL, "b");
1742 todo_wine
1743  ok(hr == WR_E_DUPLICATEATTRIBUTE, "got 0x%08x\n", hr);
1744 
1745  hr = write_start_element(writer, NULL, "b", NULL);
1746  ok(hr == S_OK, "got 0x%08x\n", hr);
1747 
1748  hr = write_attribute_string(writer, NULL, "attr2", "outeruri", "value");
1749  ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
1750 
1751  hr = write_attribute_string(writer, "pr", "attr3", "outeruri", "value");
1752  ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
1753 
1754  hr = IXmlWriter_WriteEndDocument(writer);
1755  ok(hr == S_OK, "got 0x%08x\n", hr);
1756 
1757  hr = IXmlWriter_Flush(writer);
1758  ok(hr == S_OK, "got 0x%08x\n", hr);
1759 
1761  "<p:a prefix:local=\"b\" a=\"b\" xmlns:prefix=\"uri\" p:attr=\"value\" xmlns:p=\"outeruri\">"
1762  "<b p:attr2=\"value\" pr:attr3=\"value\" xmlns:pr=\"outeruri\" />"
1763  "</p:a>");
1764 
1765  IStream_Release(stream);
1766 
1767  /* Define prefix, write attribute with it. */
1768  stream = writer_set_output(writer);
1769 
1770  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1771  ok(hr == S_OK, "got 0x%08x\n", hr);
1772 
1773  hr = write_start_element(writer, NULL, "e", NULL);
1774  ok(hr == S_OK, "got 0x%08x\n", hr);
1775 
1776  hr = write_attribute_string(writer, "xmlns", "prefix", NULL, "uri");
1777  ok(hr == S_OK, "got 0x%08x\n", hr);
1778 
1779  hr = write_attribute_string(writer, "prefix", "attr", NULL, "value");
1780  ok(hr == S_OK, "got 0x%08x\n", hr);
1781 
1782  hr = IXmlWriter_WriteEndDocument(writer);
1783  ok(hr == S_OK, "got 0x%08x\n", hr);
1784 
1785  hr = IXmlWriter_Flush(writer);
1786  ok(hr == S_OK, "got 0x%08x\n", hr);
1787 
1789  "<e xmlns:prefix=\"uri\" prefix:attr=\"value\" />");
1790 
1791  IStream_Release(stream);
1792 
1793  IXmlWriter_Release(writer);
1794 }
1795 
1796 static void test_WriteFullEndElement(void)
1797 {
1798  static const WCHAR aW[] = {'a',0};
1799  IXmlWriter *writer;
1800  IStream *stream;
1801  HRESULT hr;
1802 
1803  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1804  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1805 
1806  /* standalone element */
1807  stream = writer_set_output(writer);
1808 
1811 
1812  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1813  ok(hr == S_OK, "got 0x%08x\n", hr);
1814 
1815  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1816  ok(hr == S_OK, "got 0x%08x\n", hr);
1817 
1818  hr = IXmlWriter_WriteFullEndElement(writer);
1819  ok(hr == S_OK, "got 0x%08x\n", hr);
1820 
1821  hr = IXmlWriter_WriteEndDocument(writer);
1822  ok(hr == S_OK, "got 0x%08x\n", hr);
1823 
1824  hr = IXmlWriter_Flush(writer);
1825  ok(hr == S_OK, "got 0x%08x\n", hr);
1826 
1828  "<a></a>");
1829  IStream_Release(stream);
1830 
1831  /* nested elements */
1832  stream = writer_set_output(writer);
1833 
1836 
1837  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1838  ok(hr == S_OK, "got 0x%08x\n", hr);
1839 
1840  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1841  ok(hr == S_OK, "got 0x%08x\n", hr);
1842 
1843  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1844  ok(hr == S_OK, "got 0x%08x\n", hr);
1845 
1846  hr = IXmlWriter_WriteFullEndElement(writer);
1847  ok(hr == S_OK, "got 0x%08x\n", hr);
1848 
1849  hr = IXmlWriter_WriteEndDocument(writer);
1850  ok(hr == S_OK, "got 0x%08x\n", hr);
1851 
1852  hr = IXmlWriter_Flush(writer);
1853  ok(hr == S_OK, "got 0x%08x\n", hr);
1854 
1856  "<a>\r\n"
1857  " <a></a>\r\n"
1858  "</a>");
1859 
1860  IXmlWriter_Release(writer);
1861  IStream_Release(stream);
1862 }
1863 
1864 static void test_WriteCharEntity(void)
1865 {
1866  static const WCHAR aW[] = {'a',0};
1867  IXmlWriter *writer;
1868  IStream *stream;
1869  HRESULT hr;
1870 
1871  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1872  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1873 
1874  /* without indentation */
1875  stream = writer_set_output(writer);
1876 
1878 
1879  hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
1880  ok(hr == S_OK, "got 0x%08x\n", hr);
1881 
1882  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1883  ok(hr == S_OK, "got 0x%08x\n", hr);
1884 
1885  hr = IXmlWriter_WriteCharEntity(writer, 0x100);
1886  ok(hr == S_OK, "got 0x%08x\n", hr);
1887 
1888  hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
1889  ok(hr == S_OK, "got 0x%08x\n", hr);
1890 
1891  hr = IXmlWriter_WriteEndDocument(writer);
1892  ok(hr == S_OK, "got 0x%08x\n", hr);
1893 
1894  hr = IXmlWriter_Flush(writer);
1895  ok(hr == S_OK, "got 0x%08x\n", hr);
1896 
1898  "<a>&#x100;<a /></a>");
1899 
1900  IXmlWriter_Release(writer);
1901  IStream_Release(stream);
1902 }
1903 
1904 static void test_WriteString(void)
1905 {
1906  IXmlWriter *writer;
1907  IStream *stream;
1908  HRESULT hr;
1909 
1910  hr = CreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
1911  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1912 
1914 
1915  hr = write_string(writer, "a");
1916  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1917 
1918  hr = write_string(writer, NULL);
1919  ok(hr == S_OK, "got 0x%08x\n", hr);
1920 
1921  hr = write_string(writer, "");
1922  ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
1923 
1924  stream = writer_set_output(writer);
1925 
1926  hr = write_start_element(writer, NULL, "b", NULL);
1927  ok(hr == S_OK, "got 0x%08x\n", hr);
1928 
1929  hr = write_string(writer, NULL);
1930  ok(hr == S_OK, "got 0x%08x\n", hr);
1931 
1932  hr = write_string(writer, "");
1933  ok(hr == S_OK, "got 0x%08x\n", hr);
1934 
1935  hr = write_string(writer, "a");
1936  ok(hr == S_OK, "got 0x%08x\n", hr);
1937 
1938  /* WriteString automatically escapes markup characters */
1939  hr = write_string(writer, "<&\">=");
1940  ok(hr == S_OK, "got 0x%08x\n", hr);
1941 
1942  hr = IXmlWriter_Flush(writer);
1943  ok(hr == S_OK, "got 0x%08x\n", hr);
1944 
1946  "<b>a&lt;&amp;\"&gt;=");
1947  IStream_Release(stream);
1948 
1949  stream = writer_set_output(writer);
1950 
1951  hr = write_start_element(writer, NULL, "b", NULL);
1952  ok(hr == S_OK, "got 0x%08x\n", hr);
1953 
1954  hr = write_string(writer, NULL);
1955  ok(hr == S_OK, "got 0x%08x\n", hr);
1956 
1957  hr = IXmlWriter_Flush(writer);
1958  ok(hr == S_OK, "got 0x%08x\n", hr);
1959 
1961  "<b");
1962 
1963  hr = write_string(writer, "");
1964  ok(hr == S_OK, "got 0x%08x\n", hr);
1965 
1966  hr = IXmlWriter_Flush(writer);
1967  ok(hr == S_OK, "got 0x%08x\n", hr);
1968 
1970  "<b>");
1971 
1972  IStream_Release(stream);
1973  IXmlWriter_Release(writer);
1974 
1975  /* With indentation */
1976  hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
1977  ok(hr == S_OK, "Failed to create a writer, hr %#x.\n", hr);
1978 
1979  stream = writer_set_output(writer);
1980 
1982 
1983  hr = write_start_element(writer, NULL, "a", NULL);
1984  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
1985 
1986  hr = write_start_element(writer, NULL, "b", NULL);
1987  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
1988 
1989  hr = write_string(writer, "text");
1990  ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
1991 
1992  hr = IXmlWriter_Flush(writer);
1993  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
1994 
1996  "<a>\r\n"
1997  " <b>text");
1998 
1999  hr = IXmlWriter_WriteFullEndElement(writer);
2000  ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2001 
2002  hr = IXmlWriter_Flush(writer);
2003  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2004 
2006  "<a>\r\n"
2007  " <b>text</b>");
2008 
2009  hr = IXmlWriter_WriteFullEndElement(writer);
2010  ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2011 
2012  hr = IXmlWriter_Flush(writer);
2013  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2014 
2016  "<a>\r\n"
2017  " <b>text</b>\r\n"
2018  "</a>");
2019 
2020  IStream_Release(stream);
2021 
2022  stream = writer_set_output(writer);
2023 
2024  hr = write_start_element(writer, NULL, "a", NULL);
2025  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
2026 
2027  hr = write_start_element(writer, NULL, "b", NULL);
2028  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
2029 
2030  hr = IXmlWriter_WriteEndElement(writer);
2031  ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2032 
2033  hr = IXmlWriter_Flush(writer);
2034  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2035 
2037  "<a>\r\n"
2038  " <b />");
2039 
2040  hr = write_start_element(writer, NULL, "c", NULL);
2041  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
2042 
2043  hr = write_attribute_string(writer, NULL, "attr", NULL, "value");
2044  ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
2045 
2046  hr = IXmlWriter_Flush(writer);
2047  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2048 
2050  "<a>\r\n"
2051  " <b />\r\n"
2052  " <c attr=\"value\"");
2053 
2054  hr = write_string(writer, "text");
2055  ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
2056 
2057  hr = IXmlWriter_Flush(writer);
2058  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2059 
2061  "<a>\r\n"
2062  " <b />\r\n"
2063  " <c attr=\"value\">text");
2064 
2065  hr = IXmlWriter_WriteEndElement(writer);
2066  ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2067 
2068  hr = IXmlWriter_Flush(writer);
2069  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2070 
2072  "<a>\r\n"
2073  " <b />\r\n"
2074  " <c attr=\"value\">text</c>");
2075 
2076  hr = write_start_element(writer, NULL, "d", NULL);
2077  ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
2078 
2079  hr = write_string(writer, "");
2080  ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
2081 
2082  hr = IXmlWriter_WriteEndElement(writer);
2083  ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2084 
2085  hr = IXmlWriter_Flush(writer);
2086  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2087 
2089  "<a>\r\n"
2090  " <b />\r\n"
2091  " <c attr=\"value\">text</c>\r\n"
2092  " <d></d>");
2093 
2094  hr = IXmlWriter_WriteEndElement(writer);
2095  ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
2096 
2097  hr = IXmlWriter_Flush(writer);
2098  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2099 
2101  "<a>\r\n"
2102  " <b />\r\n"
2103  " <c attr=\"value\">text</c>\r\n"
2104  " <d></d>\r\n"
2105  "</a>");
2106 
2107  IXmlWriter_Release(writer);
2108  IStream_Release(stream);
2109 }
2110 
2111 static HRESULT write_doctype(IXmlWriter *writer, const char *name, const char *pubid, const char *sysid,
2112  const char *subset)
2113 {
2114  WCHAR *nameW, *pubidW, *sysidW, *subsetW;
2115  HRESULT hr;
2116 
2117  nameW = strdupAtoW(name);
2118  pubidW = strdupAtoW(pubid);
2119  sysidW = strdupAtoW(sysid);
2120  subsetW = strdupAtoW(subset);
2121 
2122  hr = IXmlWriter_WriteDocType(writer, nameW, pubidW, sysidW, subsetW);
2123 
2124  heap_free(nameW);
2125  heap_free(pubidW);
2126  heap_free(sysidW);
2127  heap_free(subsetW);
2128 
2129  return hr;
2130 }
2131 
2132 static void test_WriteDocType(void)
2133 {
2134  static const struct
2135  {
2136  const char *name;
2137  const char *pubid;
2138  const char *sysid;
2139  const char *subset;
2140  const char *output;
2141  }
2142  doctype_tests[] =
2143  {
2144  { "a", "", NULL, NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2145  { "a", NULL, NULL, NULL, "<!DOCTYPE a>" },
2146  { "a", NULL, "", NULL, "<!DOCTYPE a SYSTEM \"\">" },
2147  { "a", "", "", NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
2148  { "a", "pubid", "", NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2149  { "a", "pubid", NULL, NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
2150  { "a", "", "sysid", NULL, "<!DOCTYPE a PUBLIC \"\" \"sysid\">" },
2151  { "a", NULL, NULL, "", "<!DOCTYPE a []>" },
2152  { "a", NULL, NULL, "subset", "<!DOCTYPE a [subset]>" },
2153  { "a", "", NULL, "subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2154  { "a", NULL, "", "subset", "<!DOCTYPE a SYSTEM \"\" [subset]>" },
2155  { "a", "", "", "subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
2156  { "a", "pubid", NULL, "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2157  { "a", "pubid", "", "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
2158  { "a", NULL, "sysid", "subset", "<!DOCTYPE a SYSTEM \"sysid\" [subset]>" },
2159  { "a", "", "sysid", "subset", "<!DOCTYPE a PUBLIC \"\" \"sysid\" [subset]>" },
2160  { "a", "pubid", "sysid", "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"sysid\" [subset]>" },
2161  };
2162  static const WCHAR pubidW[] = {'p',0x100,'i','d',0};
2163  static const WCHAR nameW[] = {'-','a',0};
2164  static const WCHAR emptyW[] = { 0 };
2165  IXmlWriter *writer;
2166  IStream *stream;
2167  unsigned int i;
2168  HRESULT hr;
2169 
2170  hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
2171  ok(hr == S_OK, "Failed to create writer instance, hr %#x.\n", hr);
2172 
2173  stream = writer_set_output(writer);
2174 
2175  hr = IXmlWriter_WriteDocType(writer, NULL, NULL, NULL, NULL);
2176  ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2177 
2178  hr = IXmlWriter_WriteDocType(writer, emptyW, NULL, NULL, NULL);
2179  ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2180 
2181  /* Name validation. */
2182  hr = IXmlWriter_WriteDocType(writer, nameW, NULL, NULL, NULL);
2183  ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#x.\n", hr);
2184 
2185  /* Pubid validation. */
2186  hr = IXmlWriter_WriteDocType(writer, aW, pubidW, NULL, NULL);
2187  ok(hr == WC_E_PUBLICID, "Unexpected hr %#x.\n", hr);
2188 
2189  IStream_Release(stream);
2190 
2191  for (i = 0; i < ARRAY_SIZE(doctype_tests); i++)
2192  {
2193  stream = writer_set_output(writer);
2194 
2195  hr = write_doctype(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
2196  doctype_tests[i].subset);
2197  ok(hr == S_OK, "%u: failed to write doctype, hr %#x.\n", i, hr);
2198 
2199  hr = IXmlWriter_Flush(writer);
2200  ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
2201 
2202  CHECK_OUTPUT(stream, doctype_tests[i].output);
2203 
2204  hr = write_doctype(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
2205  doctype_tests[i].subset);
2206  ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#x.\n", hr);
2207 
2208  IStream_Release(stream);
2209  }
2210 
2211  IXmlWriter_Release(writer);
2212 }
2213 
2214 START_TEST(writer)
2215 {
2223  test_flush();
2225  test_bom();
2228  test_WriteCData();
2229  test_WriteRaw();
2230  test_indentation();
2234  test_WriteString();
2236 }
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
static void test_writeenddocument(void)
Definition: writer.c:1210
HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, IMalloc *imalloc, const WCHAR *encoding, IXmlWriterOutput **out)
Definition: writer.c:1976
static void test_WriteAttributeString(void)
Definition: writer.c:1605
#define CHECK_OUTPUT_RAW(stream, expected, size)
Definition: writer.c:99
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
START_TEST(writer)
Definition: writer.c:2214
static UCHAR ULONG UCHAR ULONG UCHAR * output
Definition: bcrypt.c:29
HRESULT WINAPI GetHGlobalFromStream(IStream *pstm, HGLOBAL *phglobal)
#define E_NOINTERFACE
Definition: winerror.h:2364
static void test_WriteDocType(void)
Definition: writer.c:2132
static void test_flush(void)
Definition: writer.c:622
static IStream * writer_set_output(IXmlWriter *writer)
Definition: writer.c:197
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static void check_output(IStream *stream, const char *expected, BOOL todo, int line)
Definition: writer.c:73
HRESULT hr
Definition: shlfolder.c:183
static void test_WriteString(void)
Definition: writer.c:1904
static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
Definition: writer.c:253
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
const char * uri
Definition: sec_mgr.c:1594
REFIID riid
Definition: precomp.h:44
static void test_omitxmldeclaration(void)
Definition: writer.c:652
#define CP_ACP
Definition: compat.h:99
static const IUnknownVtbl testoutputvtbl
Definition: writer.c:233
XmlWriterProperty
Definition: xmllite.idl:243
ssize_t pread(int fd, void *buf, size_t count, off_t offset)
BOOL todo
Definition: filedlg.c:313
const char * wine_dbgstr_guid(const GUID *guid)
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
static const ISequentialStreamVtbl teststreamvtbl
Definition: writer.c:277
static void test_WriteComment(void)
Definition: writer.c:1269
static void test_writeroutput(void)
Definition: writer.c:419
static void test_WriteElementString(void)
Definition: writer.c:1036
Definition: send.c:47
static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
Definition: writer.c:270
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
static void check_output_raw(IStream *stream, const void *expected, SIZE_T size, int line)
Definition: writer.c:52
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define CP_UTF8
Definition: nls.h:20
unsigned int BOOL
Definition: ntddk_ex.h:94
WCHAR strW[12]
Definition: clipboard.c:2029
static ULONG WINAPI testoutput_Release(IUnknown *iface)
Definition: writer.c:228
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
static void _expect_ref(IUnknown *obj, ULONG ref, int line)
Definition: writer.c:44
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR xmlW[]
Definition: mxnamespace.c:61
Definition: parser.c:48
static const WCHAR valueW[]
Definition: object.c:48
static const WCHAR nameW[]
Definition: main.c:46
#define todo_wine_if(is_todo)
Definition: test.h:163
static HRESULT write_start_element(IXmlWriter *writer, const char *prefix, const char *local, const char *uri)
Definition: writer.c:839
GLsizeiptr size
Definition: glext.h:5919
static HRESULT write_element_string(IXmlWriter *writer, const char *prefix, const char *local, const char *uri, const char *value)
Definition: writer.c:858
__wchar_t WCHAR
Definition: xmlstorage.h:180
static HRESULT write_string(IXmlWriter *writer, const char *str)
Definition: writer.c:879
LONG HRESULT
Definition: typedefs.h:77
static HRESULT write_doctype(IXmlWriter *writer, const char *name, const char *pubid, const char *sysid, const char *subset)
Definition: writer.c:2111
static const WCHAR aW[]
Definition: writer.c:41
const GUID IID_IUnknown
static ULONG WINAPI testoutput_AddRef(IUnknown *iface)
Definition: writer.c:223
#define WINAPI
Definition: msvc.h:6
static IUnknown testoutput
Definition: writer.c:239
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
unsigned long DWORD
Definition: ntddk_ex.h:95
static void test_WriteStartElement(void)
Definition: writer.c:893
static const WCHAR usasciiW[]
Definition: reader.c:89
HRESULT WINAPI CreateXmlWriterOutputWithEncodingCodePage(IUnknown *stream, IMalloc *imalloc, UINT codepage, IXmlWriterOutput **out)
Definition: writer.c:1997
static void test_invalid_output_encoding(IXmlWriter *writer, IUnknown *output)
Definition: writer.c:340
int ret
static void test_indentation(void)
Definition: writer.c:1512
static void test_WriteRaw(void)
Definition: writer.c:1366
static void test_WriteCharEntity(void)
Definition: writer.c:1864
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
#define todo_wine
Definition: test.h:162
Definition: parse.h:22
#define CHECK_OUTPUT(stream, expected)
Definition: writer.c:97
GLuint GLuint stream
Definition: glext.h:7522
#define EXPECT_REF(obj, ref)
Definition: writer.c:43
GLenum GLsizei len
Definition: glext.h:6722
const char * wine_dbgstr_wn(const WCHAR *str, int n)
Definition: compat.c:342
static void writer_set_property(IXmlWriter *writer, XmlWriterProperty property)
Definition: writer.c:114
GLsizei const GLfloat * value
Definition: glext.h:6069
static WCHAR * strdupAtoW(const char *str)
Definition: writer.c:101
static const WCHAR dummyW[]
Definition: directory.c:79
static const WCHAR commentW[]
Definition: reader.c:97
#define local
Definition: zutil.h:30
static void test_WriteEndElement(void)
Definition: writer.c:1178
ULONG_PTR SIZE_T
Definition: typedefs.h:78
static void test_writestartdocument(void)
Definition: writer.c:526
#define S_OK
Definition: intsafe.h:59
static void test_bom(void)
Definition: writer.c:727
static const WCHAR emptyW[]
Definition: navigate.c:40
#define CHECK_OUTPUT_TODO(stream, expected)
Definition: writer.c:98
static HRESULT write_attribute_string(IXmlWriter *writer, const char *prefix, const char *local, const char *uri, const char *value)
Definition: writer.c:1584
#define ARRAY_SIZE(a)
Definition: main.h:24
static ULONG g_write_len
Definition: writer.c:269
#define ok(value,...)
Definition: atltest.h:57
#define E_NOTIMPL
Definition: ddrawi.h:99
static void test_writer_state(void)
Definition: writer.c:1424
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc)
Definition: writer.c:1897
#define MultiByteToWideChar
Definition: compat.h:100
#define E_UNEXPECTED
Definition: winerror.h:2456
static const WCHAR piW[]
Definition: reader.c:98
static void test_WriteFullEndElement(void)
Definition: writer.c:1796
static HMODULE MODULEINFO DWORD cb
Definition: module.c:32
Definition: name.c:38
unsigned int ULONG
Definition: retypes.h:1
static void test_writer_create(void)
Definition: writer.c:288
static void test_WriteCData(void)
Definition: writer.c:1315
static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
Definition: writer.c:241
static void check_writer_state(IXmlWriter *writer, HRESULT exp_hr)
Definition: writer.c:123
static const WCHAR versionW[]
Definition: name.c:52
static HRESULT WINAPI testoutput_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
Definition: writer.c:211
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
Definition: writer.c:263
BOOL expected
Definition: store.c:2063
#define SUCCEEDED(hr)
Definition: intsafe.h:57
static ISequentialStream teststream
Definition: writer.c:286
static const WCHAR utf16W[]
Definition: mxwriter.c:85
static ULONG WINAPI teststream_Release(ISequentialStream *iface)
Definition: writer.c:258
#define ok_(x1, x2)
Definition: atltest.h:61
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a)
GLuint const GLchar * name
Definition: glext.h:6031