* The Shell.. for a long time we dreamed of having a compatible, properly working...
[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 <objbase.h>
34 #include <ole2.h>
35 #include <xmllite.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 HRESULT (WINAPI *pCreateXmlWriter)(REFIID riid, void **ppvObject, IMalloc *pMalloc);
42 static HRESULT (WINAPI *pCreateXmlWriterOutputWithEncodingName)(IUnknown *stream,
43 IMalloc *imalloc,
44 LPCWSTR encoding_name,
45 IXmlWriterOutput **output);
46
47 static HRESULT WINAPI testoutput_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
48 {
49 if (IsEqualGUID(riid, &IID_IUnknown)) {
50 *obj = iface;
51 return S_OK;
52 }
53 else {
54 ok(0, "unknown riid=%s\n", wine_dbgstr_guid(riid));
55 return E_NOINTERFACE;
56 }
57 }
58
59 static ULONG WINAPI testoutput_AddRef(IUnknown *iface)
60 {
61 return 2;
62 }
63
64 static ULONG WINAPI testoutput_Release(IUnknown *iface)
65 {
66 return 1;
67 }
68
69 static const IUnknownVtbl testoutputvtbl = {
70 testoutput_QueryInterface,
71 testoutput_AddRef,
72 testoutput_Release
73 };
74
75 static IUnknown testoutput = { &testoutputvtbl };
76
77 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
78 {
79 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
80 {
81 *obj = iface;
82 return S_OK;
83 }
84
85 *obj = NULL;
86 return E_NOINTERFACE;
87 }
88
89 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
90 {
91 return 2;
92 }
93
94 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
95 {
96 return 1;
97 }
98
99 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
100 {
101 ok(0, "unexpected call\n");
102 return E_NOTIMPL;
103 }
104
105 static ULONG g_write_len;
106 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
107 {
108 g_write_len = cb;
109 *written = cb;
110 return S_OK;
111 }
112
113 static const ISequentialStreamVtbl teststreamvtbl =
114 {
115 teststream_QueryInterface,
116 teststream_AddRef,
117 teststream_Release,
118 teststream_Read,
119 teststream_Write
120 };
121
122 static ISequentialStream teststream = { &teststreamvtbl };
123
124 static void test_writer_create(void)
125 {
126 HRESULT hr;
127 IXmlWriter *writer;
128 LONG_PTR value;
129
130 /* crashes native */
131 if (0)
132 {
133 pCreateXmlWriter(&IID_IXmlWriter, NULL, NULL);
134 pCreateXmlWriter(NULL, (void**)&writer, NULL);
135 }
136
137 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
138 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
139
140 /* check default properties values */
141 value = 0;
142 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ByteOrderMark, &value);
143 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
144 ok(value == TRUE, "got %ld\n", value);
145
146 value = TRUE;
147 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_Indent, &value);
148 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
149 ok(value == FALSE, "got %ld\n", value);
150
151 value = TRUE;
152 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, &value);
153 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
154 ok(value == FALSE, "got %ld\n", value);
155
156 value = XmlConformanceLevel_Auto;
157 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ConformanceLevel, &value);
158 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
159 ok(value == XmlConformanceLevel_Document, "got %ld\n", value);
160
161 IXmlWriter_Release(writer);
162 }
163
164 static BOOL init_pointers(void)
165 {
166 /* don't free module here, it's to be unloaded on exit */
167 HMODULE mod = LoadLibraryA("xmllite.dll");
168
169 if (!mod)
170 {
171 win_skip("xmllite library not available\n");
172 return FALSE;
173 }
174
175 #define MAKEFUNC(f) if (!(p##f = (void*)GetProcAddress(mod, #f))) return FALSE;
176 MAKEFUNC(CreateXmlWriter);
177 MAKEFUNC(CreateXmlWriterOutputWithEncodingName);
178 #undef MAKEFUNC
179
180 return TRUE;
181 }
182
183 static void test_writeroutput(void)
184 {
185 static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
186 IXmlWriterOutput *output;
187 IUnknown *unk;
188 HRESULT hr;
189
190 output = NULL;
191 hr = pCreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output);
192 ok(hr == S_OK, "got %08x\n", hr);
193 IUnknown_Release(output);
194
195 hr = pCreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output);
196 ok(hr == S_OK, "got %08x\n", hr);
197 unk = NULL;
198 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
199 ok(hr == S_OK, "got %08x\n", hr);
200 ok(unk != NULL, "got %p\n", unk);
201 /* releasing 'unk' crashes on native */
202 IUnknown_Release(output);
203 }
204
205 static void test_writestartdocument(void)
206 {
207 static const char fullprolog[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
208 static const char prologversion[] = "<?xml version=\"1.0\"?>";
209 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
210 static const WCHAR xmlW[] = {'x','m','l',0};
211 IXmlWriter *writer;
212 HGLOBAL hglobal;
213 IStream *stream;
214 HRESULT hr;
215 char *ptr;
216
217 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
218 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
219
220 /* output not set */
221 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
222 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
223
224 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
225 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
226
227 hr = IXmlWriter_Flush(writer);
228 ok(hr == S_OK, "got 0x%08x\n", hr);
229
230 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
231 ok(hr == S_OK, "got 0x%08x\n", hr);
232
233 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
234 ok(hr == S_OK, "got 0x%08x\n", hr);
235
236 /* nothing written yet */
237 hr = IXmlWriter_Flush(writer);
238 ok(hr == S_OK, "got 0x%08x\n", hr);
239
240 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
241 ok(hr == S_OK, "got 0x%08x\n", hr);
242
243 hr = IXmlWriter_Flush(writer);
244 ok(hr == S_OK, "got 0x%08x\n", hr);
245
246 hr = GetHGlobalFromStream(stream, &hglobal);
247 ok(hr == S_OK, "got 0x%08x\n", hr);
248
249 ptr = GlobalLock(hglobal);
250 ok(!strncmp(ptr, fullprolog, strlen(fullprolog)), "got %s, expected %s\n", ptr, fullprolog);
251 GlobalUnlock(hglobal);
252
253 /* one more time */
254 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
255 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
256 IStream_Release(stream);
257
258 /* now add PI manually, and try to start a document */
259 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
260 ok(hr == S_OK, "got 0x%08x\n", hr);
261
262 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
263 ok(hr == S_OK, "got 0x%08x\n", hr);
264
265 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
266 ok(hr == S_OK, "got 0x%08x\n", hr);
267
268 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
269 ok(hr == S_OK, "got 0x%08x\n", hr);
270
271 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
272 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
273
274 /* another attempt to add 'xml' PI */
275 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
276 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
277
278 hr = IXmlWriter_Flush(writer);
279 ok(hr == S_OK, "got 0x%08x\n", hr);
280
281 hr = GetHGlobalFromStream(stream, &hglobal);
282 ok(hr == S_OK, "got 0x%08x\n", hr);
283
284 ptr = GlobalLock(hglobal);
285 ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr);
286 GlobalUnlock(hglobal);
287
288 IStream_Release(stream);
289 IXmlWriter_Release(writer);
290 }
291
292 static void test_flush(void)
293 {
294 IXmlWriter *writer;
295 HRESULT hr;
296
297 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
298 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
299
300 hr = IXmlWriter_SetOutput(writer, (IUnknown*)&teststream);
301 ok(hr == S_OK, "got 0x%08x\n", hr);
302
303 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
304 ok(hr == S_OK, "got 0x%08x\n", hr);
305
306 g_write_len = 0;
307 hr = IXmlWriter_Flush(writer);
308 ok(hr == S_OK, "got 0x%08x\n", hr);
309 ok(g_write_len > 0, "got %d\n", g_write_len);
310
311 g_write_len = 1;
312 hr = IXmlWriter_Flush(writer);
313 ok(hr == S_OK, "got 0x%08x\n", hr);
314 ok(g_write_len == 0, "got %d\n", g_write_len);
315
316 /* Release() flushes too */
317 g_write_len = 1;
318 IXmlWriter_Release(writer);
319 ok(g_write_len == 0, "got %d\n", g_write_len);
320 }
321
322 static void test_omitxmldeclaration(void)
323 {
324 static const char prologversion[] = "<?xml version=\"1.0\"?>";
325 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
326 static const WCHAR xmlW[] = {'x','m','l',0};
327 IXmlWriter *writer;
328 HGLOBAL hglobal;
329 IStream *stream;
330 HRESULT hr;
331 char *ptr;
332
333 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
334 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
335
336 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
337 ok(hr == S_OK, "got 0x%08x\n", hr);
338
339 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
340 ok(hr == S_OK, "got 0x%08x\n", hr);
341
342 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
343 ok(hr == S_OK, "got 0x%08x\n", hr);
344
345 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
346 ok(hr == S_OK, "got 0x%08x\n", hr);
347
348 hr = IXmlWriter_Flush(writer);
349 ok(hr == S_OK, "got 0x%08x\n", hr);
350
351 hr = GetHGlobalFromStream(stream, &hglobal);
352 ok(hr == S_OK, "got 0x%08x\n", hr);
353
354 ptr = GlobalLock(hglobal);
355 ok(!ptr, "got %p\n", ptr);
356 GlobalUnlock(hglobal);
357
358 /* one more time */
359 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
360 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
361
362 IStream_Release(stream);
363
364 /* now add PI manually, and try to start a document */
365 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
366 ok(hr == S_OK, "got 0x%08x\n", hr);
367
368 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
369 ok(hr == S_OK, "got 0x%08x\n", hr);
370
371 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
372 ok(hr == S_OK, "got 0x%08x\n", hr);
373
374 hr = IXmlWriter_Flush(writer);
375 ok(hr == S_OK, "got 0x%08x\n", hr);
376
377 hr = GetHGlobalFromStream(stream, &hglobal);
378 ok(hr == S_OK, "got 0x%08x\n", hr);
379
380 ptr = GlobalLock(hglobal);
381 ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr);
382 GlobalUnlock(hglobal);
383
384 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
385 ok(hr == S_OK, "got 0x%08x\n", hr);
386
387 hr = IXmlWriter_Flush(writer);
388 ok(hr == S_OK, "got 0x%08x\n", hr);
389
390 ptr = GlobalLock(hglobal);
391 ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr);
392 GlobalUnlock(hglobal);
393
394 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
395 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
396
397 hr = IXmlWriter_Flush(writer);
398 ok(hr == S_OK, "got 0x%08x\n", hr);
399
400 ptr = GlobalLock(hglobal);
401 ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr);
402 GlobalUnlock(hglobal);
403
404 /* another attempt to add 'xml' PI */
405 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
406 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
407
408 hr = IXmlWriter_Flush(writer);
409 ok(hr == S_OK, "got 0x%08x\n", hr);
410
411 IStream_Release(stream);
412 IXmlWriter_Release(writer);
413 }
414
415 static void test_bom(void)
416 {
417 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
418 static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
419 static const WCHAR xmlW[] = {'x','m','l',0};
420 static const WCHAR aW[] = {'a',0};
421 IXmlWriterOutput *output;
422 unsigned char *ptr;
423 IXmlWriter *writer;
424 IStream *stream;
425 HGLOBAL hglobal;
426 HRESULT hr;
427
428 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
429 ok(hr == S_OK, "got 0x%08x\n", hr);
430
431 hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
432 ok(hr == S_OK, "got %08x\n", hr);
433
434 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
435 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
436
437 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
438 ok(hr == S_OK, "got 0x%08x\n", hr);
439
440 hr = IXmlWriter_SetOutput(writer, output);
441 ok(hr == S_OK, "got 0x%08x\n", hr);
442
443 /* BOM is on by default */
444 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
445 ok(hr == S_OK, "got 0x%08x\n", hr);
446
447 hr = IXmlWriter_Flush(writer);
448 ok(hr == S_OK, "got 0x%08x\n", hr);
449
450 hr = GetHGlobalFromStream(stream, &hglobal);
451 ok(hr == S_OK, "got 0x%08x\n", hr);
452
453 ptr = GlobalLock(hglobal);
454 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
455 GlobalUnlock(hglobal);
456
457 IStream_Release(stream);
458 IUnknown_Release(output);
459
460 /* start with PI */
461 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
462 ok(hr == S_OK, "got 0x%08x\n", hr);
463
464 hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
465 ok(hr == S_OK, "got %08x\n", hr);
466
467 hr = IXmlWriter_SetOutput(writer, output);
468 ok(hr == S_OK, "got 0x%08x\n", hr);
469
470 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
471 ok(hr == S_OK, "got 0x%08x\n", hr);
472
473 hr = IXmlWriter_Flush(writer);
474 ok(hr == S_OK, "got 0x%08x\n", hr);
475
476 hr = GetHGlobalFromStream(stream, &hglobal);
477 ok(hr == S_OK, "got 0x%08x\n", hr);
478
479 ptr = GlobalLock(hglobal);
480 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
481 GlobalUnlock(hglobal);
482
483 IUnknown_Release(output);
484 IStream_Release(stream);
485
486 /* start with element */
487 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
488 ok(hr == S_OK, "got 0x%08x\n", hr);
489
490 hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
491 ok(hr == S_OK, "got %08x\n", hr);
492
493 hr = IXmlWriter_SetOutput(writer, output);
494 ok(hr == S_OK, "got 0x%08x\n", hr);
495
496 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
497 ok(hr == S_OK, "got 0x%08x\n", hr);
498
499 hr = IXmlWriter_Flush(writer);
500 ok(hr == S_OK, "got 0x%08x\n", hr);
501
502 hr = GetHGlobalFromStream(stream, &hglobal);
503 ok(hr == S_OK, "got 0x%08x\n", hr);
504
505 ptr = GlobalLock(hglobal);
506 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
507 GlobalUnlock(hglobal);
508
509 IUnknown_Release(output);
510 IStream_Release(stream);
511
512 /* WriteElementString */
513 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
514 ok(hr == S_OK, "got 0x%08x\n", hr);
515
516 hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
517 ok(hr == S_OK, "got %08x\n", hr);
518
519 hr = IXmlWriter_SetOutput(writer, output);
520 ok(hr == S_OK, "got 0x%08x\n", hr);
521
522 hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
523 ok(hr == S_OK, "got 0x%08x\n", hr);
524
525 hr = IXmlWriter_Flush(writer);
526 ok(hr == S_OK, "got 0x%08x\n", hr);
527
528 hr = GetHGlobalFromStream(stream, &hglobal);
529 ok(hr == S_OK, "got 0x%08x\n", hr);
530
531 ptr = GlobalLock(hglobal);
532 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
533 GlobalUnlock(hglobal);
534
535 IUnknown_Release(output);
536 IStream_Release(stream);
537
538 IXmlWriter_Release(writer);
539 }
540
541 static void test_writestartelement(void)
542 {
543 static const WCHAR valueW[] = {'v','a','l','u','e',0};
544 static const char *str = "<a><b>value</b>";
545 static const WCHAR aW[] = {'a',0};
546 static const WCHAR bW[] = {'b',0};
547 char *ptr;
548 IXmlWriter *writer;
549 IStream *stream;
550 HGLOBAL hglobal;
551 HRESULT hr;
552
553 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
554 ok(hr == S_OK, "got 0x%08x\n", hr);
555
556 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
557 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
558
559 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
560 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
561
562 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
563 ok(hr == S_OK, "got 0x%08x\n", hr);
564
565 hr = IXmlWriter_WriteStartElement(writer, aW, NULL, NULL);
566 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
567
568 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
569 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
570
571 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, aW);
572 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
573
574 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
575 ok(hr == S_OK, "got 0x%08x\n", hr);
576
577 hr = GetHGlobalFromStream(stream, &hglobal);
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 hr = IXmlWriter_Flush(writer);
584 ok(hr == S_OK, "got 0x%08x\n", hr);
585
586 ptr = GlobalLock(hglobal);
587 ok(!strncmp(ptr, "<a", 2), "got %s\n", ptr);
588 GlobalUnlock(hglobal);
589
590 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
591 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
592
593 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
594 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
595
596 hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
597 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
598
599 IStream_Release(stream);
600 IXmlWriter_Release(writer);
601
602 /* WriteElementString */
603 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
604 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
605
606 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
607 ok(hr == S_OK, "got 0x%08x\n", hr);
608
609 hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
610 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
611
612 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
613 ok(hr == S_OK, "got 0x%08x\n", hr);
614
615 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
616 ok(hr == S_OK, "got 0x%08x\n", hr);
617
618 hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
619 ok(hr == S_OK, "got 0x%08x\n", hr);
620
621 hr = IXmlWriter_Flush(writer);
622 ok(hr == S_OK, "got 0x%08x\n", hr);
623
624 hr = GetHGlobalFromStream(stream, &hglobal);
625 ok(hr == S_OK, "got 0x%08x\n", hr);
626
627 ptr = GlobalLock(hglobal);
628 ok(!strncmp(ptr, str, strlen(str)), "got %s\n", ptr);
629 GlobalUnlock(hglobal);
630
631 IStream_Release(stream);
632 IXmlWriter_Release(writer);
633 }
634
635 static void test_writeendelement(void)
636 {
637 static const WCHAR aW[] = {'a',0};
638 static const WCHAR bW[] = {'b',0};
639 char *ptr;
640 IXmlWriter *writer;
641 IStream *stream;
642 HGLOBAL hglobal;
643 HRESULT hr;
644
645 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
646 ok(hr == S_OK, "got 0x%08x\n", hr);
647
648 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
649 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
650
651 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
652 ok(hr == S_OK, "got 0x%08x\n", hr);
653
654 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
655 ok(hr == S_OK, "got 0x%08x\n", hr);
656
657 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
658 ok(hr == S_OK, "got 0x%08x\n", hr);
659
660 hr = IXmlWriter_WriteEndElement(writer);
661 ok(hr == S_OK, "got 0x%08x\n", hr);
662
663 hr = IXmlWriter_WriteEndElement(writer);
664 ok(hr == S_OK, "got 0x%08x\n", hr);
665
666 hr = GetHGlobalFromStream(stream, &hglobal);
667 ok(hr == S_OK, "got 0x%08x\n", hr);
668
669 hr = IXmlWriter_Flush(writer);
670 ok(hr == S_OK, "got 0x%08x\n", hr);
671
672 ptr = GlobalLock(hglobal);
673 ok(!strncmp(ptr, "<a><b /></a>", 12), "got %s\n", ptr);
674 GlobalUnlock(hglobal);
675
676 IXmlWriter_Release(writer);
677 IStream_Release(stream);
678 }
679
680 START_TEST(writer)
681 {
682 if (!init_pointers())
683 return;
684
685 test_writer_create();
686 test_writeroutput();
687 test_writestartdocument();
688 test_writestartelement();
689 test_writeendelement();
690 test_flush();
691 test_omitxmldeclaration();
692 test_bom();
693 }