[XMLLITE_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / rostests / winetests / xmllite / writer.c
1 /*
2 * XMLLite IXmlWriter tests
3 *
4 * Copyright 2011 (C) Alistair Leslie-Hughes
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define CONST_VTABLE
26 #define COBJMACROS
27
28 #include <stdarg.h>
29 //#include <stdio.h>
30
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <objbase.h>
35 #include <ole2.h>
36 #include <xmllite.h>
37 #include <wine/test.h>
38
39 #include <initguid.h>
40 DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
41
42 static HRESULT (WINAPI *pCreateXmlWriter)(REFIID riid, void **ppvObject, IMalloc *pMalloc);
43 static HRESULT (WINAPI *pCreateXmlWriterOutputWithEncodingName)(IUnknown *stream,
44 IMalloc *imalloc,
45 LPCWSTR encoding_name,
46 IXmlWriterOutput **output);
47 static HRESULT (WINAPI *pCreateXmlWriterOutputWithEncodingCodePage)(IUnknown *stream,
48 IMalloc *imalloc,
49 UINT codepage,
50 IXmlWriterOutput **output);
51
52 static HRESULT WINAPI testoutput_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
53 {
54 if (IsEqualGUID(riid, &IID_IUnknown)) {
55 *obj = iface;
56 return S_OK;
57 }
58 else {
59 ok(0, "unknown riid=%s\n", wine_dbgstr_guid(riid));
60 return E_NOINTERFACE;
61 }
62 }
63
64 static ULONG WINAPI testoutput_AddRef(IUnknown *iface)
65 {
66 return 2;
67 }
68
69 static ULONG WINAPI testoutput_Release(IUnknown *iface)
70 {
71 return 1;
72 }
73
74 static const IUnknownVtbl testoutputvtbl = {
75 testoutput_QueryInterface,
76 testoutput_AddRef,
77 testoutput_Release
78 };
79
80 static IUnknown testoutput = { &testoutputvtbl };
81
82 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
83 {
84 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
85 {
86 *obj = iface;
87 return S_OK;
88 }
89
90 *obj = NULL;
91 return E_NOINTERFACE;
92 }
93
94 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
95 {
96 return 2;
97 }
98
99 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
100 {
101 return 1;
102 }
103
104 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
105 {
106 ok(0, "unexpected call\n");
107 return E_NOTIMPL;
108 }
109
110 static ULONG g_write_len;
111 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
112 {
113 g_write_len = cb;
114 *written = cb;
115 return S_OK;
116 }
117
118 static const ISequentialStreamVtbl teststreamvtbl =
119 {
120 teststream_QueryInterface,
121 teststream_AddRef,
122 teststream_Release,
123 teststream_Read,
124 teststream_Write
125 };
126
127 static ISequentialStream teststream = { &teststreamvtbl };
128
129 static void test_writer_create(void)
130 {
131 HRESULT hr;
132 IXmlWriter *writer;
133 LONG_PTR value;
134
135 /* crashes native */
136 if (0)
137 {
138 pCreateXmlWriter(&IID_IXmlWriter, NULL, NULL);
139 pCreateXmlWriter(NULL, (void**)&writer, NULL);
140 }
141
142 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
143 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
144
145 /* check default properties values */
146 value = 0;
147 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ByteOrderMark, &value);
148 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
149 ok(value == TRUE, "got %ld\n", value);
150
151 value = TRUE;
152 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_Indent, &value);
153 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
154 ok(value == FALSE, "got %ld\n", value);
155
156 value = TRUE;
157 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, &value);
158 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
159 ok(value == FALSE, "got %ld\n", value);
160
161 value = XmlConformanceLevel_Auto;
162 hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ConformanceLevel, &value);
163 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
164 ok(value == XmlConformanceLevel_Document, "got %ld\n", value);
165
166 IXmlWriter_Release(writer);
167 }
168
169 static BOOL init_pointers(void)
170 {
171 /* don't free module here, it's to be unloaded on exit */
172 HMODULE mod = LoadLibraryA("xmllite.dll");
173
174 if (!mod)
175 {
176 win_skip("xmllite library not available\n");
177 return FALSE;
178 }
179
180 #define MAKEFUNC(f) if (!(p##f = (void*)GetProcAddress(mod, #f))) return FALSE;
181 MAKEFUNC(CreateXmlWriter);
182 MAKEFUNC(CreateXmlWriterOutputWithEncodingName);
183 MAKEFUNC(CreateXmlWriterOutputWithEncodingCodePage);
184 #undef MAKEFUNC
185
186 return TRUE;
187 }
188
189 static void test_writeroutput(void)
190 {
191 static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
192 IXmlWriterOutput *output;
193 IUnknown *unk;
194 HRESULT hr;
195
196 output = NULL;
197 hr = pCreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output);
198 ok(hr == S_OK, "got %08x\n", hr);
199 IUnknown_Release(output);
200
201 hr = pCreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output);
202 ok(hr == S_OK, "got %08x\n", hr);
203 unk = NULL;
204 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
205 ok(hr == S_OK, "got %08x\n", hr);
206 ok(unk != NULL, "got %p\n", unk);
207 /* releasing 'unk' crashes on native */
208 IUnknown_Release(output);
209
210 output = NULL;
211 hr = pCreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, ~0u, &output);
212 ok(hr == S_OK, "got %08x\n", hr);
213 IUnknown_Release(output);
214
215 hr = pCreateXmlWriterOutputWithEncodingCodePage(&testoutput, NULL, CP_UTF8, &output);
216 ok(hr == S_OK, "got %08x\n", hr);
217 unk = NULL;
218 hr = IUnknown_QueryInterface(output, &IID_IXmlWriterOutput, (void**)&unk);
219 ok(hr == S_OK, "got %08x\n", hr);
220 ok(unk != NULL, "got %p\n", unk);
221 /* releasing 'unk' crashes on native */
222 IUnknown_Release(output);
223 }
224
225 static void test_writestartdocument(void)
226 {
227 static const char fullprolog[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
228 static const char prologversion[] = "<?xml version=\"1.0\"?>";
229 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
230 static const WCHAR xmlW[] = {'x','m','l',0};
231 IXmlWriter *writer;
232 HGLOBAL hglobal;
233 IStream *stream;
234 HRESULT hr;
235 char *ptr;
236
237 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
238 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
239
240 /* output not set */
241 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
242 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
243
244 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
245 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
246
247 hr = IXmlWriter_Flush(writer);
248 ok(hr == S_OK, "got 0x%08x\n", hr);
249
250 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
251 ok(hr == S_OK, "got 0x%08x\n", hr);
252
253 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
254 ok(hr == S_OK, "got 0x%08x\n", hr);
255
256 /* nothing written yet */
257 hr = IXmlWriter_Flush(writer);
258 ok(hr == S_OK, "got 0x%08x\n", hr);
259
260 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
261 ok(hr == S_OK, "got 0x%08x\n", hr);
262
263 hr = IXmlWriter_Flush(writer);
264 ok(hr == S_OK, "got 0x%08x\n", hr);
265
266 hr = GetHGlobalFromStream(stream, &hglobal);
267 ok(hr == S_OK, "got 0x%08x\n", hr);
268
269 ptr = GlobalLock(hglobal);
270 ok(!strncmp(ptr, fullprolog, strlen(fullprolog)), "got %s, expected %s\n", ptr, fullprolog);
271 GlobalUnlock(hglobal);
272
273 /* one more time */
274 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
275 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
276 IStream_Release(stream);
277
278 /* now add PI manually, and try to start a document */
279 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
280 ok(hr == S_OK, "got 0x%08x\n", hr);
281
282 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
283 ok(hr == S_OK, "got 0x%08x\n", hr);
284
285 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
286 ok(hr == S_OK, "got 0x%08x\n", hr);
287
288 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
289 ok(hr == S_OK, "got 0x%08x\n", hr);
290
291 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
292 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
293
294 /* another attempt to add 'xml' PI */
295 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
296 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
297
298 hr = IXmlWriter_Flush(writer);
299 ok(hr == S_OK, "got 0x%08x\n", hr);
300
301 hr = GetHGlobalFromStream(stream, &hglobal);
302 ok(hr == S_OK, "got 0x%08x\n", hr);
303
304 ptr = GlobalLock(hglobal);
305 ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr);
306 GlobalUnlock(hglobal);
307
308 IStream_Release(stream);
309 IXmlWriter_Release(writer);
310 }
311
312 static void test_flush(void)
313 {
314 IXmlWriter *writer;
315 HRESULT hr;
316
317 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
318 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
319
320 hr = IXmlWriter_SetOutput(writer, (IUnknown*)&teststream);
321 ok(hr == S_OK, "got 0x%08x\n", hr);
322
323 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
324 ok(hr == S_OK, "got 0x%08x\n", hr);
325
326 g_write_len = 0;
327 hr = IXmlWriter_Flush(writer);
328 ok(hr == S_OK, "got 0x%08x\n", hr);
329 ok(g_write_len > 0, "got %d\n", g_write_len);
330
331 g_write_len = 1;
332 hr = IXmlWriter_Flush(writer);
333 ok(hr == S_OK, "got 0x%08x\n", hr);
334 ok(g_write_len == 0, "got %d\n", g_write_len);
335
336 /* Release() flushes too */
337 g_write_len = 1;
338 IXmlWriter_Release(writer);
339 ok(g_write_len == 0, "got %d\n", g_write_len);
340 }
341
342 static void test_omitxmldeclaration(void)
343 {
344 static const char prologversion[] = "<?xml version=\"1.0\"?>";
345 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
346 static const WCHAR xmlW[] = {'x','m','l',0};
347 IXmlWriter *writer;
348 HGLOBAL hglobal;
349 IStream *stream;
350 HRESULT hr;
351 char *ptr;
352
353 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
354 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
355
356 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
357 ok(hr == S_OK, "got 0x%08x\n", hr);
358
359 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
360 ok(hr == S_OK, "got 0x%08x\n", hr);
361
362 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
363 ok(hr == S_OK, "got 0x%08x\n", hr);
364
365 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
366 ok(hr == S_OK, "got 0x%08x\n", hr);
367
368 hr = IXmlWriter_Flush(writer);
369 ok(hr == S_OK, "got 0x%08x\n", hr);
370
371 hr = GetHGlobalFromStream(stream, &hglobal);
372 ok(hr == S_OK, "got 0x%08x\n", hr);
373
374 ptr = GlobalLock(hglobal);
375 ok(!ptr, "got %p\n", ptr);
376 GlobalUnlock(hglobal);
377
378 /* one more time */
379 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
380 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
381
382 IStream_Release(stream);
383
384 /* now add PI manually, and try to start a document */
385 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
386 ok(hr == S_OK, "got 0x%08x\n", hr);
387
388 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
389 ok(hr == S_OK, "got 0x%08x\n", hr);
390
391 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
392 ok(hr == S_OK, "got 0x%08x\n", hr);
393
394 hr = IXmlWriter_Flush(writer);
395 ok(hr == S_OK, "got 0x%08x\n", hr);
396
397 hr = GetHGlobalFromStream(stream, &hglobal);
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 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
405 ok(hr == S_OK, "got 0x%08x\n", hr);
406
407 hr = IXmlWriter_Flush(writer);
408 ok(hr == S_OK, "got 0x%08x\n", hr);
409
410 ptr = GlobalLock(hglobal);
411 ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr);
412 GlobalUnlock(hglobal);
413
414 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
415 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
416
417 hr = IXmlWriter_Flush(writer);
418 ok(hr == S_OK, "got 0x%08x\n", hr);
419
420 ptr = GlobalLock(hglobal);
421 ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr);
422 GlobalUnlock(hglobal);
423
424 /* another attempt to add 'xml' PI */
425 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
426 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
427
428 hr = IXmlWriter_Flush(writer);
429 ok(hr == S_OK, "got 0x%08x\n", hr);
430
431 IStream_Release(stream);
432 IXmlWriter_Release(writer);
433 }
434
435 static void test_bom(void)
436 {
437 static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0};
438 static const WCHAR utf16W[] = {'u','t','f','-','1','6',0};
439 static const WCHAR xmlW[] = {'x','m','l',0};
440 static const WCHAR aW[] = {'a',0};
441 IXmlWriterOutput *output;
442 unsigned char *ptr;
443 IXmlWriter *writer;
444 IStream *stream;
445 HGLOBAL hglobal;
446 HRESULT hr;
447
448 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
449 ok(hr == S_OK, "got 0x%08x\n", hr);
450
451 hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
452 ok(hr == S_OK, "got %08x\n", hr);
453
454 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
455 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
456
457 hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE);
458 ok(hr == S_OK, "got 0x%08x\n", hr);
459
460 hr = IXmlWriter_SetOutput(writer, output);
461 ok(hr == S_OK, "got 0x%08x\n", hr);
462
463 /* BOM is on by default */
464 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
465 ok(hr == S_OK, "got 0x%08x\n", hr);
466
467 hr = IXmlWriter_Flush(writer);
468 ok(hr == S_OK, "got 0x%08x\n", hr);
469
470 hr = GetHGlobalFromStream(stream, &hglobal);
471 ok(hr == S_OK, "got 0x%08x\n", hr);
472
473 ptr = GlobalLock(hglobal);
474 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
475 GlobalUnlock(hglobal);
476
477 IStream_Release(stream);
478 IUnknown_Release(output);
479
480 /* start with PI */
481 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
482 ok(hr == S_OK, "got 0x%08x\n", hr);
483
484 hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
485 ok(hr == S_OK, "got %08x\n", hr);
486
487 hr = IXmlWriter_SetOutput(writer, output);
488 ok(hr == S_OK, "got 0x%08x\n", hr);
489
490 hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW);
491 ok(hr == S_OK, "got 0x%08x\n", hr);
492
493 hr = IXmlWriter_Flush(writer);
494 ok(hr == S_OK, "got 0x%08x\n", hr);
495
496 hr = GetHGlobalFromStream(stream, &hglobal);
497 ok(hr == S_OK, "got 0x%08x\n", hr);
498
499 ptr = GlobalLock(hglobal);
500 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
501 GlobalUnlock(hglobal);
502
503 IUnknown_Release(output);
504 IStream_Release(stream);
505
506 /* start with element */
507 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
508 ok(hr == S_OK, "got 0x%08x\n", hr);
509
510 hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
511 ok(hr == S_OK, "got %08x\n", hr);
512
513 hr = IXmlWriter_SetOutput(writer, output);
514 ok(hr == S_OK, "got 0x%08x\n", hr);
515
516 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
517 ok(hr == S_OK, "got 0x%08x\n", hr);
518
519 hr = IXmlWriter_Flush(writer);
520 ok(hr == S_OK, "got 0x%08x\n", hr);
521
522 hr = GetHGlobalFromStream(stream, &hglobal);
523 ok(hr == S_OK, "got 0x%08x\n", hr);
524
525 ptr = GlobalLock(hglobal);
526 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
527 GlobalUnlock(hglobal);
528
529 IUnknown_Release(output);
530 IStream_Release(stream);
531
532 /* WriteElementString */
533 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
534 ok(hr == S_OK, "got 0x%08x\n", hr);
535
536 hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output);
537 ok(hr == S_OK, "got %08x\n", hr);
538
539 hr = IXmlWriter_SetOutput(writer, output);
540 ok(hr == S_OK, "got 0x%08x\n", hr);
541
542 hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
543 ok(hr == S_OK, "got 0x%08x\n", hr);
544
545 hr = IXmlWriter_Flush(writer);
546 ok(hr == S_OK, "got 0x%08x\n", hr);
547
548 hr = GetHGlobalFromStream(stream, &hglobal);
549 ok(hr == S_OK, "got 0x%08x\n", hr);
550
551 ptr = GlobalLock(hglobal);
552 ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]);
553 GlobalUnlock(hglobal);
554
555 IUnknown_Release(output);
556 IStream_Release(stream);
557
558 IXmlWriter_Release(writer);
559 }
560
561 static void test_writestartelement(void)
562 {
563 static const WCHAR valueW[] = {'v','a','l','u','e',0};
564 static const char *str = "<a><b>value</b>";
565 static const WCHAR aW[] = {'a',0};
566 static const WCHAR bW[] = {'b',0};
567 char *ptr;
568 IXmlWriter *writer;
569 IStream *stream;
570 HGLOBAL hglobal;
571 HRESULT hr;
572
573 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
574 ok(hr == S_OK, "got 0x%08x\n", hr);
575
576 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
577 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
578
579 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
580 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
581
582 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
583 ok(hr == S_OK, "got 0x%08x\n", hr);
584
585 hr = IXmlWriter_WriteStartElement(writer, aW, NULL, NULL);
586 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
587
588 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
589 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
590
591 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, aW);
592 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
593
594 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
595 ok(hr == S_OK, "got 0x%08x\n", hr);
596
597 hr = GetHGlobalFromStream(stream, &hglobal);
598 ok(hr == S_OK, "got 0x%08x\n", hr);
599
600 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
601 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
602
603 hr = IXmlWriter_Flush(writer);
604 ok(hr == S_OK, "got 0x%08x\n", hr);
605
606 ptr = GlobalLock(hglobal);
607 ok(!strncmp(ptr, "<a", 2), "got %s\n", ptr);
608 GlobalUnlock(hglobal);
609
610 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes);
611 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
612
613 hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL);
614 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
615
616 hr = IXmlWriter_WriteProcessingInstruction(writer, aW, aW);
617 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
618
619 IStream_Release(stream);
620 IXmlWriter_Release(writer);
621
622 /* WriteElementString */
623 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
624 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
625
626 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
627 ok(hr == S_OK, "got 0x%08x\n", hr);
628
629 hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
630 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
631
632 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
633 ok(hr == S_OK, "got 0x%08x\n", hr);
634
635 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
636 ok(hr == S_OK, "got 0x%08x\n", hr);
637
638 hr = IXmlWriter_WriteElementString(writer, NULL, bW, NULL, valueW);
639 ok(hr == S_OK, "got 0x%08x\n", hr);
640
641 hr = IXmlWriter_Flush(writer);
642 ok(hr == S_OK, "got 0x%08x\n", hr);
643
644 hr = GetHGlobalFromStream(stream, &hglobal);
645 ok(hr == S_OK, "got 0x%08x\n", hr);
646
647 ptr = GlobalLock(hglobal);
648 ok(!strncmp(ptr, str, strlen(str)), "got %s\n", ptr);
649 GlobalUnlock(hglobal);
650
651 IStream_Release(stream);
652 IXmlWriter_Release(writer);
653 }
654
655 static void test_writeendelement(void)
656 {
657 static const WCHAR aW[] = {'a',0};
658 static const WCHAR bW[] = {'b',0};
659 char *ptr;
660 IXmlWriter *writer;
661 IStream *stream;
662 HGLOBAL hglobal;
663 HRESULT hr;
664
665 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
666 ok(hr == S_OK, "got 0x%08x\n", hr);
667
668 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
669 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
670
671 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
672 ok(hr == S_OK, "got 0x%08x\n", hr);
673
674 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
675 ok(hr == S_OK, "got 0x%08x\n", hr);
676
677 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
678 ok(hr == S_OK, "got 0x%08x\n", hr);
679
680 hr = IXmlWriter_WriteEndElement(writer);
681 ok(hr == S_OK, "got 0x%08x\n", hr);
682
683 hr = IXmlWriter_WriteEndElement(writer);
684 ok(hr == S_OK, "got 0x%08x\n", hr);
685
686 hr = GetHGlobalFromStream(stream, &hglobal);
687 ok(hr == S_OK, "got 0x%08x\n", hr);
688
689 hr = IXmlWriter_Flush(writer);
690 ok(hr == S_OK, "got 0x%08x\n", hr);
691
692 ptr = GlobalLock(hglobal);
693 ok(!strncmp(ptr, "<a><b /></a>", 12), "got %s\n", ptr);
694 GlobalUnlock(hglobal);
695
696 IXmlWriter_Release(writer);
697 IStream_Release(stream);
698 }
699
700 static void test_writeenddocument(void)
701 {
702 static const WCHAR aW[] = {'a',0};
703 static const WCHAR bW[] = {'b',0};
704 IXmlWriter *writer;
705 IStream *stream;
706 HGLOBAL hglobal;
707 HRESULT hr;
708 char *ptr;
709
710 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
711 ok(hr == S_OK, "got 0x%08x\n", hr);
712
713 hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL);
714 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
715
716 hr = IXmlWriter_WriteEndDocument(writer);
717 ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
718
719 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
720 ok(hr == S_OK, "got 0x%08x\n", hr);
721
722 /* WriteEndDocument resets it to initial state */
723 hr = IXmlWriter_WriteEndDocument(writer);
724 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
725
726 hr = IXmlWriter_WriteEndDocument(writer);
727 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
728
729 hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Omit);
730 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
731
732 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
733 ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr);
734
735 hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream);
736 ok(hr == S_OK, "got 0x%08x\n", hr);
737
738 hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL);
739 ok(hr == S_OK, "got 0x%08x\n", hr);
740
741 hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
742 ok(hr == S_OK, "got 0x%08x\n", hr);
743
744 hr = IXmlWriter_WriteEndDocument(writer);
745 ok(hr == S_OK, "got 0x%08x\n", hr);
746
747 hr = GetHGlobalFromStream(stream, &hglobal);
748 ok(hr == S_OK, "got 0x%08x\n", hr);
749
750 ptr = GlobalLock(hglobal);
751 ok(ptr == NULL, "got %p\n", ptr);
752
753 /* we still need to flush manually, WriteEndDocument doesn't do that */
754 hr = IXmlWriter_Flush(writer);
755 ok(hr == S_OK, "got 0x%08x\n", hr);
756
757 ptr = GlobalLock(hglobal);
758 ok(ptr != NULL, "got %p\n", ptr);
759 ok(!strncmp(ptr, "<a><b /></a>", 12), "got %s\n", ptr);
760 GlobalUnlock(hglobal);
761
762 IXmlWriter_Release(writer);
763 IStream_Release(stream);
764 }
765
766 START_TEST(writer)
767 {
768 if (!init_pointers())
769 return;
770
771 test_writer_create();
772 test_writeroutput();
773 test_writestartdocument();
774 test_writestartelement();
775 test_writeendelement();
776 test_flush();
777 test_omitxmldeclaration();
778 test_bom();
779 test_writeenddocument();
780 }