4 * Copyright 2008 Piotr Caban
5 * Copyright 2011 Thomas Mullaly
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "msxml2did.h"
35 #include "wine/test.h"
37 #define EXPECT_HR(hr,hr_exp) \
38 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
40 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
41 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
43 ULONG rc
= IUnknown_AddRef(obj
);
44 IUnknown_Release(obj
);
45 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
48 static BSTR
alloc_str_from_narrow(const char *str
)
50 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
51 BSTR ret
= SysAllocStringLen(NULL
, len
- 1); /* NUL character added automatically */
52 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
56 static BSTR alloced_bstrs
[512];
57 static int alloced_bstrs_count
;
59 static BSTR
_bstr_(const char *str
)
61 assert(alloced_bstrs_count
< sizeof(alloced_bstrs
)/sizeof(alloced_bstrs
[0]));
62 alloced_bstrs
[alloced_bstrs_count
] = alloc_str_from_narrow(str
);
63 return alloced_bstrs
[alloced_bstrs_count
++];
66 static void free_bstrs(void)
69 for (i
= 0; i
< alloced_bstrs_count
; i
++)
70 SysFreeString(alloced_bstrs
[i
]);
71 alloced_bstrs_count
= 0;
76 CH_PUTDOCUMENTLOCATOR
,
79 CH_STARTPREFIXMAPPING
,
84 CH_IGNORABLEWHITESPACE
,
85 CH_PROCESSINGINSTRUCTION
,
92 static const WCHAR szSimpleXML
[] = {
93 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
94 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
95 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
96 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
97 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
100 static const WCHAR szCarriageRetTest
[] = {
101 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
102 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
103 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
104 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
105 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
108 static const WCHAR szUtf16XML
[] = {
109 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
110 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
111 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
114 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
116 static const CHAR szUtf8XML
[] =
117 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
119 static const CHAR szTestXML
[] =
120 "<?xml version=\"1.0\" ?>\n"
122 " <Number>1234</Number>\n"
123 " <Name>Captain Ahab</Name>\n"
126 static const CHAR szTestAttributes
[] =
127 "<?xml version=\"1.0\" ?>\n"
128 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
129 "<node1 xmlns:p=\"test\" />"
132 typedef struct _contenthandlercheck
{
142 } content_handler_test
;
144 static content_handler_test contentHandlerTest1
[] = {
145 { CH_PUTDOCUMENTLOCATOR
, 0, 0, 1, 0 },
146 { CH_STARTDOCUMENT
, 0, 0, 1, 22 },
147 { CH_STARTELEMENT
, 2, 14, 2, 13, "", "BankAccount", "BankAccount" },
148 { CH_CHARACTERS
, 2, 14, 3, 4, "\n " },
149 { CH_STARTELEMENT
, 3, 12, 3, 11, "", "Number", "Number" },
150 { CH_CHARACTERS
, 3, 12, 3, 16, "1234" },
151 { CH_ENDELEMENT
, 3, 18, 3, 24, "", "Number", "Number" },
152 { CH_CHARACTERS
, 3, 25, 4, 4, "\n " },
153 { CH_STARTELEMENT
, 4, 10, 4, 9, "", "Name", "Name" },
154 { CH_CHARACTERS
, 4, 10, 4, 22, "Captain Ahab" },
155 { CH_ENDELEMENT
, 4, 24, 4, 28, "", "Name", "Name" },
156 { CH_CHARACTERS
, 4, 29, 5, 1, "\n" },
157 { CH_ENDELEMENT
, 5, 3, 5, 14, "", "BankAccount", "BankAccount" },
158 { CH_ENDDOCUMENT
, 0, 0, 6, 0 },
162 static content_handler_test contentHandlerTest2
[] = {
163 { CH_PUTDOCUMENTLOCATOR
, 0, 0, 1, 0 },
164 { CH_STARTDOCUMENT
, 0, 0, 1, 21 },
165 { CH_STARTELEMENT
, 2, 14, 2, 13, "", "BankAccount", "BankAccount" },
166 { CH_CHARACTERS
, 2, 14, 3, 0, "\n" },
167 { CH_CHARACTERS
, 2, 16, 3, 2, "\t" },
168 { CH_STARTELEMENT
, 3, 10, 3, 9, "", "Number", "Number" },
169 { CH_CHARACTERS
, 3, 10, 3, 14, "1234" },
170 { CH_ENDELEMENT
, 3, 16, 3, 22, "", "Number", "Number" },
171 { CH_CHARACTERS
, 3, 23, 4, 0, "\n" },
172 { CH_CHARACTERS
, 3, 25, 4, 2, "\t" },
173 { CH_STARTELEMENT
, 4, 8, 4, 7, "", "Name", "Name" },
174 { CH_CHARACTERS
, 4, 8, 4, 20, "Captain Ahab" },
175 { CH_ENDELEMENT
, 4, 22, 4, 26, "", "Name", "Name" },
176 { CH_CHARACTERS
, 4, 27, 5, 0, "\n" },
177 { CH_ENDELEMENT
, 5, 3, 5, 14, "", "BankAccount", "BankAccount" },
178 { CH_ENDDOCUMENT
, 0, 0, 6, 0 },
182 static content_handler_test contentHandlerTestError
[] = {
183 { CH_PUTDOCUMENTLOCATOR
, 0, 0, 1, 0, NULL
, NULL
, NULL
, E_FAIL
},
184 { EH_FATALERROR
, 0, 0, 0, 0, NULL
, NULL
, NULL
, E_FAIL
},
188 static content_handler_test contentHandlerTestCallbackResults
[] = {
189 { CH_PUTDOCUMENTLOCATOR
, 0, 0, 1, 0, NULL
, NULL
, NULL
, S_FALSE
},
190 { CH_STARTDOCUMENT
, 0, 0, 1, 22, NULL
, NULL
, NULL
, S_FALSE
},
191 { EH_FATALERROR
, 0, 0, 0, 0, NULL
, NULL
, NULL
, S_FALSE
},
195 static content_handler_test contentHandlerTestCallbackResult6
[] = {
196 { CH_PUTDOCUMENTLOCATOR
, 0, 0, 1, 0, NULL
, NULL
, NULL
, S_FALSE
},
197 { CH_STARTDOCUMENT
, 0, 0, 1, 22, NULL
, NULL
, NULL
, S_FALSE
},
198 { CH_STARTELEMENT
, 2, 14, 2, 13, "", "BankAccount", "BankAccount", S_FALSE
},
199 { CH_CHARACTERS
, 2, 14, 3, 4, "\n ", NULL
, NULL
, S_FALSE
},
200 { CH_STARTELEMENT
, 3, 12, 3, 11, "", "Number", "Number", S_FALSE
},
201 { CH_CHARACTERS
, 3, 12, 3, 16, "1234", NULL
, NULL
, S_FALSE
},
202 { CH_ENDELEMENT
, 3, 18, 3, 24, "", "Number", "Number", S_FALSE
},
203 { CH_CHARACTERS
, 3, 25, 4, 4, "\n ", NULL
, NULL
, S_FALSE
},
204 { CH_STARTELEMENT
, 4, 10, 4, 9, "", "Name", "Name", S_FALSE
},
205 { CH_CHARACTERS
, 4, 10, 4, 22, "Captain Ahab", NULL
, NULL
, S_FALSE
},
206 { CH_ENDELEMENT
, 4, 24, 4, 28, "", "Name", "Name", S_FALSE
},
207 { CH_CHARACTERS
, 4, 29, 5, 1, "\n", NULL
, NULL
, S_FALSE
},
208 { CH_ENDELEMENT
, 5, 3, 5, 14, "", "BankAccount", "BankAccount", S_FALSE
},
209 { CH_ENDDOCUMENT
, 0, 0, 6, 0, NULL
, NULL
, NULL
, S_FALSE
},
213 static content_handler_test contentHandlerTestAttributes
[] = {
214 { CH_PUTDOCUMENTLOCATOR
, 0, 0, 1, 0 },
215 { CH_STARTDOCUMENT
, 0, 0, 1, 22 },
216 { CH_STARTPREFIXMAPPING
, 2, 96, 2, 95, "test", "prefix_test" },
217 { CH_STARTPREFIXMAPPING
, 2, 96, 2, 95, "", "prefix" },
218 { CH_STARTELEMENT
, 2, 96, 2, 95, "prefix", "document", "document" },
219 { CH_CHARACTERS
, 2, 96, 3, 1, "\n" },
220 { CH_STARTPREFIXMAPPING
, 3, 25, 3, 24, "p", "test" },
221 { CH_STARTELEMENT
, 3, 25, 3, 24, "prefix", "node1", "node1" },
222 { CH_ENDELEMENT
, 3, 25, 3, 24, "prefix", "node1", "node1" },
223 { CH_ENDPREFIXMAPPING
, 3, 25, 3, 24, "p" },
224 { CH_ENDELEMENT
, 3, 27, 3, 35, "prefix", "document", "document" },
225 { CH_ENDPREFIXMAPPING
, 3, 27, 3, 35, "" },
226 { CH_ENDPREFIXMAPPING
, 3, 27, 3, 35, "test" },
227 { CH_ENDDOCUMENT
, 0, 0, 4, 0 },
231 static content_handler_test contentHandlerTestAttributes6
[] = {
232 { CH_PUTDOCUMENTLOCATOR
, 0, 0, 1, 0 },
233 { CH_STARTDOCUMENT
, 0, 0, 1, 22 },
234 { CH_STARTPREFIXMAPPING
, 2, 96, 2, 95, "test", "prefix_test" },
235 { CH_STARTPREFIXMAPPING
, 2, 96, 2, 95, "", "prefix" },
236 { CH_STARTELEMENT
, 2, 96, 2, 95, "prefix", "document", "document" },
237 { CH_CHARACTERS
, 2, 96, 3, 1, "\n" },
238 { CH_STARTPREFIXMAPPING
, 3, 25, 3, 24, "p", "test" },
239 { CH_STARTELEMENT
, 3, 25, 3, 24, "prefix", "node1", "node1" },
240 { CH_ENDELEMENT
, 3, 25, 3, 24, "prefix", "node1", "node1" },
241 { CH_ENDPREFIXMAPPING
, 3, 25, 3, 24, "p" },
242 { CH_ENDELEMENT
, 3, 27, 3, 35, "prefix", "document", "document" },
243 { CH_ENDPREFIXMAPPING
, 3, 27, 3, 35, "test" },
244 { CH_ENDPREFIXMAPPING
, 3, 27, 3, 35, "" },
245 { CH_ENDDOCUMENT
, 0, 0, 4, 0 },
249 static content_handler_test
*expectCall
;
250 static ISAXLocator
*locator
;
253 static void test_saxstr(unsigned line
, const WCHAR
*szStr
, int nStr
, const char *szTest
)
259 ok_(__FILE__
,line
) (szStr
== NULL
, "szStr != NULL\n");
260 ok_(__FILE__
,line
) (nStr
== 0, "nStr = %d, expected 0\n", nStr
);
264 len
= strlen(szTest
);
265 ok_(__FILE__
,line
) (len
== nStr
, "nStr = %d, expected %d (%s)\n", nStr
, len
, szTest
);
269 MultiByteToWideChar(CP_ACP
, 0, szTest
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
270 ok_(__FILE__
,line
) (!memcmp(szStr
, buf
, len
*sizeof(WCHAR
)), "unexpected szStr %s, expected %s\n",
271 wine_dbgstr_wn(szStr
, nStr
), szTest
);
274 static BOOL
test_expect_call(CH id
)
276 ok(expectCall
->id
== id
, "unexpected call %d, expected %d\n", id
, expectCall
->id
);
277 return expectCall
->id
== id
;
280 static void test_locator(unsigned line
, int loc_line
, int loc_column
)
283 ISAXLocator_getLineNumber(locator
, &rline
);
284 ISAXLocator_getColumnNumber(locator
, &rcolumn
);
286 ok_(__FILE__
,line
) (rline
== loc_line
,
287 "unexpected line %d, expected %d\n", rline
, loc_line
);
288 ok_(__FILE__
,line
) (rcolumn
== loc_column
,
289 "unexpected column %d, expected %d\n", rcolumn
, loc_column
);
292 static HRESULT WINAPI
contentHandler_QueryInterface(
293 ISAXContentHandler
* iface
,
299 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
305 return E_NOINTERFACE
;
311 static ULONG WINAPI
contentHandler_AddRef(
312 ISAXContentHandler
* iface
)
317 static ULONG WINAPI
contentHandler_Release(
318 ISAXContentHandler
* iface
)
323 static HRESULT WINAPI
contentHandler_putDocumentLocator(
324 ISAXContentHandler
* iface
,
325 ISAXLocator
*pLocator
)
327 ISAXAttributes
*attr
;
330 if(!test_expect_call(CH_PUTDOCUMENTLOCATOR
))
334 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
335 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
337 if(msxml_version
>= 6) {
338 hres
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
339 ok(hres
== S_OK
, "QueryInterface failed: %x\n", hres
);
340 ISAXAttributes_Release(attr
);
343 return (expectCall
++)->ret
;
346 static ISAXAttributes
*test_attr_ptr
;
347 static HRESULT WINAPI
contentHandler_startDocument(
348 ISAXContentHandler
* iface
)
350 if(!test_expect_call(CH_STARTDOCUMENT
))
353 test_attr_ptr
= NULL
;
354 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
355 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
357 return (expectCall
++)->ret
;
360 static HRESULT WINAPI
contentHandler_endDocument(
361 ISAXContentHandler
* iface
)
363 if(!test_expect_call(CH_ENDDOCUMENT
))
366 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
367 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
369 return (expectCall
++)->ret
;
372 static HRESULT WINAPI
contentHandler_startPrefixMapping(
373 ISAXContentHandler
* iface
,
374 const WCHAR
*pPrefix
,
379 if(!test_expect_call(CH_STARTPREFIXMAPPING
))
382 test_saxstr(__LINE__
, pPrefix
, nPrefix
, expectCall
->arg1
);
383 test_saxstr(__LINE__
, pUri
, nUri
, expectCall
->arg2
);
384 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
385 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
387 return (expectCall
++)->ret
;
390 static HRESULT WINAPI
contentHandler_endPrefixMapping(
391 ISAXContentHandler
* iface
,
392 const WCHAR
*pPrefix
,
395 if(!test_expect_call(CH_ENDPREFIXMAPPING
))
398 test_saxstr(__LINE__
, pPrefix
, nPrefix
, expectCall
->arg1
);
399 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
400 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
402 return (expectCall
++)->ret
;
405 static HRESULT WINAPI
contentHandler_startElement(
406 ISAXContentHandler
* iface
,
407 const WCHAR
*pNamespaceUri
,
409 const WCHAR
*pLocalName
,
413 ISAXAttributes
*pAttr
)
418 if(!test_expect_call(CH_STARTELEMENT
))
421 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, expectCall
->arg1
);
422 test_saxstr(__LINE__
, pLocalName
, nLocalName
, expectCall
->arg2
);
423 test_saxstr(__LINE__
, pQName
, nQName
, expectCall
->arg3
);
424 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
425 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
428 test_attr_ptr
= pAttr
;
429 ok(test_attr_ptr
== pAttr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, pAttr
);
431 if(expectCall
== contentHandlerTestAttributes
+4) {
432 const WCHAR
*uri_ptr
= NULL
;
434 /* msxml3 returns attributes and namespaces in the input order */
435 hres
= ISAXAttributes_getLength(pAttr
, &len
);
436 ok(hres
== S_OK
, "getLength returned %x\n", hres
);
437 ok(len
== 5, "Incorrect number of attributes: %d\n", len
);
438 ok(msxml_version
< 6, "wrong msxml_version: %d\n", msxml_version
);
440 for(i
=0; i
<len
; i
++) {
441 hres
= ISAXAttributes_getName(pAttr
, i
, &pNamespaceUri
, &nNamespaceUri
,
442 &pLocalName
, &nLocalName
, &pQName
, &nQName
);
443 ok(hres
== S_OK
, "getName returned %x\n", hres
);
446 todo_wine
ok(i
==3, "Incorrect attributes order\n");
447 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "");
448 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "arg2");
449 test_saxstr(__LINE__
, pQName
, nQName
, "arg2");
450 } else if(nQName
== 5) {
451 todo_wine
ok(i
==1, "Incorrect attributes order\n");
452 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "");
453 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "");
454 test_saxstr(__LINE__
, pQName
, nQName
, "xmlns");
455 } else if(nQName
== 8) {
456 todo_wine
ok(i
==4, "Incorrect attributes order\n");
457 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "prefix_test");
458 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "ar3");
459 test_saxstr(__LINE__
, pQName
, nQName
, "test:ar3");
460 ok(uri_ptr
== pNamespaceUri
, "Incorrect NamespaceUri pointer\n");
461 } else if(nQName
== 9) {
462 todo_wine
ok(i
==2, "Incorrect attributes order\n");
463 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "prefix_test");
464 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "arg1");
465 test_saxstr(__LINE__
, pQName
, nQName
, "test:arg1");
466 uri_ptr
= pNamespaceUri
;
467 } else if(nQName
== 10) {
468 todo_wine
ok(i
==0, "Incorrect attributes order\n");
469 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "");
470 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "");
471 test_saxstr(__LINE__
, pQName
, nQName
, "xmlns:test");
473 ok(0, "Unexpected attribute\n");
476 } else if(expectCall
== contentHandlerTestAttributes6
+4) {
477 const WCHAR
*uri_ptr
;
479 /* msxml6 returns attributes first and then namespaces */
480 hres
= ISAXAttributes_getLength(pAttr
, &len
);
481 ok(hres
== S_OK
, "getLength returned %x\n", hres
);
482 ok(len
== 5, "Incorrect number of attributes: %d\n", len
);
483 ok(msxml_version
>= 6, "wrong msxml_version: %d\n", msxml_version
);
485 hres
= ISAXAttributes_getName(pAttr
, 0, &pNamespaceUri
, &nNamespaceUri
,
486 &pLocalName
, &nLocalName
, &pQName
, &nQName
);
487 ok(hres
== S_OK
, "getName returned %x\n", hres
);
488 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "prefix_test");
489 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "arg1");
490 test_saxstr(__LINE__
, pQName
, nQName
, "test:arg1");
491 uri_ptr
= pNamespaceUri
;
493 hres
= ISAXAttributes_getName(pAttr
, 1, &pNamespaceUri
, &nNamespaceUri
,
494 &pLocalName
, &nLocalName
, &pQName
, &nQName
);
495 ok(hres
== S_OK
, "getName returned %x\n", hres
);
496 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "");
497 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "arg2");
498 test_saxstr(__LINE__
, pQName
, nQName
, "arg2");
500 hres
= ISAXAttributes_getName(pAttr
, 2, &pNamespaceUri
, &nNamespaceUri
,
501 &pLocalName
, &nLocalName
, &pQName
, &nQName
);
502 ok(hres
== S_OK
, "getName returned %x\n", hres
);
503 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "prefix_test");
504 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "ar3");
505 test_saxstr(__LINE__
, pQName
, nQName
, "test:ar3");
506 ok(uri_ptr
== pNamespaceUri
, "Incorrect NamespaceUri pointer\n");
508 hres
= ISAXAttributes_getName(pAttr
, 3, &pNamespaceUri
, &nNamespaceUri
,
509 &pLocalName
, &nLocalName
, &pQName
, &nQName
);
510 ok(hres
== S_OK
, "getName returned %x\n", hres
);
511 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "http://www.w3.org/2000/xmlns/");
512 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "");
513 test_saxstr(__LINE__
, pQName
, nQName
, "xmlns:test");
515 hres
= ISAXAttributes_getName(pAttr
, 4, &pNamespaceUri
, &nNamespaceUri
,
516 &pLocalName
, &nLocalName
, &pQName
, &nQName
);
517 ok(hres
== S_OK
, "getName returned %x\n", hres
);
518 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, "http://www.w3.org/2000/xmlns/");
519 test_saxstr(__LINE__
, pLocalName
, nLocalName
, "");
520 test_saxstr(__LINE__
, pQName
, nQName
, "xmlns");
523 return (expectCall
++)->ret
;
526 static HRESULT WINAPI
contentHandler_endElement(
527 ISAXContentHandler
* iface
,
528 const WCHAR
*pNamespaceUri
,
530 const WCHAR
*pLocalName
,
535 if(!test_expect_call(CH_ENDELEMENT
))
538 test_saxstr(__LINE__
, pNamespaceUri
, nNamespaceUri
, expectCall
->arg1
);
539 test_saxstr(__LINE__
, pLocalName
, nLocalName
, expectCall
->arg2
);
540 test_saxstr(__LINE__
, pQName
, nQName
, expectCall
->arg3
);
541 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
542 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
544 return (expectCall
++)->ret
;
547 static HRESULT WINAPI
contentHandler_characters(
548 ISAXContentHandler
* iface
,
552 if(!test_expect_call(CH_CHARACTERS
))
555 test_saxstr(__LINE__
, pChars
, nChars
, expectCall
->arg1
);
556 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
557 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
559 return (expectCall
++)->ret
;
562 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
563 ISAXContentHandler
* iface
,
567 if(!test_expect_call(CH_IGNORABLEWHITESPACE
))
570 test_saxstr(__LINE__
, pChars
, nChars
, expectCall
->arg1
);
571 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
572 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
574 return (expectCall
++)->ret
;
577 static HRESULT WINAPI
contentHandler_processingInstruction(
578 ISAXContentHandler
* iface
,
579 const WCHAR
*pTarget
,
584 if(!test_expect_call(CH_PROCESSINGINSTRUCTION
))
587 test_saxstr(__LINE__
, pTarget
, nTarget
, expectCall
->arg1
);
588 test_saxstr(__LINE__
, pData
, nData
, expectCall
->arg2
);
589 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
590 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
592 return (expectCall
++)->ret
;
595 static HRESULT WINAPI
contentHandler_skippedEntity(
596 ISAXContentHandler
* iface
,
600 if(!test_expect_call(CH_SKIPPEDENTITY
))
603 test_saxstr(__LINE__
, pName
, nName
, expectCall
->arg1
);
604 test_locator(__LINE__
, msxml_version
>=6 ? expectCall
->line_v6
: expectCall
->line
,
605 msxml_version
>=6 ? expectCall
->column_v6
: expectCall
->column
);
607 return (expectCall
++)->ret
;
611 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
613 contentHandler_QueryInterface
,
614 contentHandler_AddRef
,
615 contentHandler_Release
,
616 contentHandler_putDocumentLocator
,
617 contentHandler_startDocument
,
618 contentHandler_endDocument
,
619 contentHandler_startPrefixMapping
,
620 contentHandler_endPrefixMapping
,
621 contentHandler_startElement
,
622 contentHandler_endElement
,
623 contentHandler_characters
,
624 contentHandler_ignorableWhitespace
,
625 contentHandler_processingInstruction
,
626 contentHandler_skippedEntity
629 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
631 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
632 ISAXErrorHandler
* iface
,
638 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
644 return E_NOINTERFACE
;
650 static ULONG WINAPI
isaxerrorHandler_AddRef(
651 ISAXErrorHandler
* iface
)
656 static ULONG WINAPI
isaxerrorHandler_Release(
657 ISAXErrorHandler
* iface
)
662 static HRESULT WINAPI
isaxerrorHandler_error(
663 ISAXErrorHandler
* iface
,
664 ISAXLocator
*pLocator
,
665 const WCHAR
*pErrorMessage
,
668 ok(0, "unexpected call\n");
672 static HRESULT WINAPI
isaxerrorHandler_fatalError(
673 ISAXErrorHandler
* iface
,
674 ISAXLocator
*pLocator
,
675 const WCHAR
*pErrorMessage
,
678 if(!test_expect_call(EH_FATALERROR
))
681 ok(hrErrorCode
== expectCall
->ret
, "hrErrorCode = %x, expected %x\n", hrErrorCode
, expectCall
->ret
);
687 static HRESULT WINAPI
isaxerrorHanddler_ignorableWarning(
688 ISAXErrorHandler
* iface
,
689 ISAXLocator
*pLocator
,
690 const WCHAR
*pErrorMessage
,
693 ok(0, "unexpected call\n");
697 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
699 isaxerrorHandler_QueryInterface
,
700 isaxerrorHandler_AddRef
,
701 isaxerrorHandler_Release
,
702 isaxerrorHandler_error
,
703 isaxerrorHandler_fatalError
,
704 isaxerrorHanddler_ignorableWarning
707 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
709 static HRESULT WINAPI
isaxattributes_QueryInterface(
710 ISAXAttributes
* iface
,
716 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
722 return E_NOINTERFACE
;
728 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
733 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
738 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
744 static HRESULT WINAPI
isaxattributes_getURI(
745 ISAXAttributes
* iface
,
750 ok(0, "unexpected call\n");
754 static HRESULT WINAPI
isaxattributes_getLocalName(
755 ISAXAttributes
* iface
,
757 const WCHAR
**pLocalName
,
758 int *pLocalNameLength
)
760 ok(0, "unexpected call\n");
764 static HRESULT WINAPI
isaxattributes_getQName(
765 ISAXAttributes
* iface
,
767 const WCHAR
**pQName
,
770 static const WCHAR attr1W
[] = {'a',':','a','t','t','r','1','j','u','n','k',0};
771 static const WCHAR attr2W
[] = {'a','t','t','r','2','j','u','n','k',0};
773 ok(nIndex
== 0 || nIndex
== 1, "invalid index received %d\n", nIndex
);
775 *pQName
= (nIndex
== 0) ? attr1W
: attr2W
;
776 *pQNameLength
= (nIndex
== 0) ? 7 : 5;
781 static HRESULT WINAPI
isaxattributes_getName(
782 ISAXAttributes
* iface
,
786 const WCHAR
** pLocalName
,
787 int * pLocalNameSize
,
788 const WCHAR
** pQName
,
791 ok(0, "unexpected call\n");
795 static HRESULT WINAPI
isaxattributes_getIndexFromName(
796 ISAXAttributes
* iface
,
799 const WCHAR
* pLocalName
,
803 ok(0, "unexpected call\n");
807 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
808 ISAXAttributes
* iface
,
809 const WCHAR
* pQName
,
813 ok(0, "unexpected call\n");
817 static HRESULT WINAPI
isaxattributes_getType(
818 ISAXAttributes
* iface
,
820 const WCHAR
** pType
,
823 ok(0, "unexpected call\n");
827 static HRESULT WINAPI
isaxattributes_getTypeFromName(
828 ISAXAttributes
* iface
,
831 const WCHAR
* pLocalName
,
833 const WCHAR
** pType
,
836 ok(0, "unexpected call\n");
840 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
841 ISAXAttributes
* iface
,
842 const WCHAR
* pQName
,
844 const WCHAR
** pType
,
847 ok(0, "unexpected call\n");
851 static HRESULT WINAPI
isaxattributes_getValue(
852 ISAXAttributes
* iface
,
854 const WCHAR
** pValue
,
857 static const WCHAR attrval1W
[] = {'a','1','j','u','n','k',0};
858 static const WCHAR attrval2W
[] = {'a','2','j','u','n','k',0};
860 ok(nIndex
== 0 || nIndex
== 1, "invalid index received %d\n", nIndex
);
862 *pValue
= (nIndex
== 0) ? attrval1W
: attrval2W
;
868 static HRESULT WINAPI
isaxattributes_getValueFromName(
869 ISAXAttributes
* iface
,
872 const WCHAR
* pLocalName
,
874 const WCHAR
** pValue
,
877 ok(0, "unexpected call\n");
881 static HRESULT WINAPI
isaxattributes_getValueFromQName(
882 ISAXAttributes
* iface
,
883 const WCHAR
* pQName
,
885 const WCHAR
** pValue
,
888 ok(0, "unexpected call\n");
892 static const ISAXAttributesVtbl SAXAttributesVtbl
=
894 isaxattributes_QueryInterface
,
895 isaxattributes_AddRef
,
896 isaxattributes_Release
,
897 isaxattributes_getLength
,
898 isaxattributes_getURI
,
899 isaxattributes_getLocalName
,
900 isaxattributes_getQName
,
901 isaxattributes_getName
,
902 isaxattributes_getIndexFromName
,
903 isaxattributes_getIndexFromQName
,
904 isaxattributes_getType
,
905 isaxattributes_getTypeFromName
,
906 isaxattributes_getTypeFromQName
,
907 isaxattributes_getValue
,
908 isaxattributes_getValueFromName
,
909 isaxattributes_getValueFromQName
912 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
914 static int handler_addrefcalled
;
916 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **ppvObject
)
920 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
921 IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
927 return E_NOINTERFACE
;
933 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
935 handler_addrefcalled
++;
939 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
944 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
945 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
946 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
948 ok(0, "call not expected\n");
952 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
954 ok(0, "call not expected\n");
958 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
959 const WCHAR
* pName
, int nName
)
961 ok(0, "call not expected\n");
965 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
966 const WCHAR
* pName
, int nName
)
968 ok(0, "call not expected\n");
972 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
974 ok(0, "call not expected\n");
978 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
980 ok(0, "call not expected\n");
984 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
985 const WCHAR
* pChars
, int nChars
)
987 ok(0, "call not expected\n");
991 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
993 isaxlexical_QueryInterface
,
996 isaxlexical_startDTD
,
998 isaxlexical_startEntity
,
999 isaxlexical_endEntity
,
1000 isaxlexical_startCDATA
,
1001 isaxlexical_endCDATA
,
1005 static ISAXLexicalHandler saxlexicalhandler
= { &SAXLexicalHandlerVtbl
};
1007 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **ppvObject
)
1011 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
1012 IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1018 return E_NOINTERFACE
;
1024 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1026 handler_addrefcalled
++;
1030 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1035 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1036 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1038 ok(0, "call not expected\n");
1042 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1043 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1044 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1045 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1047 ok(0, "call not expected\n");
1051 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1052 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1054 ok(0, "call not expected\n");
1058 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1059 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1060 const WCHAR
* pSystemId
, int nSystemId
)
1062 ok(0, "call not expected\n");
1066 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1068 isaxdecl_QueryInterface
,
1071 isaxdecl_elementDecl
,
1072 isaxdecl_attributeDecl
,
1073 isaxdecl_internalEntityDecl
,
1074 isaxdecl_externalEntityDecl
1077 static ISAXDeclHandler saxdeclhandler
= { &SAXDeclHandlerVtbl
};
1079 typedef struct mxwriter_write_test_t
{
1085 } mxwriter_write_test
;
1087 typedef struct mxwriter_stream_test_t
{
1089 const char *encoding
;
1090 mxwriter_write_test expected_writes
[4];
1091 } mxwriter_stream_test
;
1093 static const mxwriter_write_test
*current_write_test
;
1094 static DWORD current_stream_test_index
;
1096 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1100 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1103 return E_NOINTERFACE
;
1108 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1113 static ULONG WINAPI
istream_Release(IStream
*iface
)
1118 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1120 ok(0, "unexpected call\n");
1124 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1128 ok(pv
!= NULL
, "pv == NULL\n");
1130 if(current_write_test
->last
) {
1131 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
1135 fail
= current_write_test
->fail_write
;
1137 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
1138 current_write_test
->cb
, cb
, current_stream_test_index
);
1141 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
1143 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
1145 ++current_write_test
;
1150 return fail
? E_FAIL
: S_OK
;
1153 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1154 ULARGE_INTEGER
*plibNewPosition
)
1156 ok(0, "unexpected call\n");
1160 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1162 ok(0, "unexpected call\n");
1166 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1167 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1169 ok(0, "unexpected call\n");
1173 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1175 ok(0, "unexpected call\n");
1179 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1181 ok(0, "unexpected call\n");
1185 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1186 ULARGE_INTEGER cb
, DWORD dwLockType
)
1188 ok(0, "unexpected call\n");
1192 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1193 ULARGE_INTEGER cb
, DWORD dwLockType
)
1195 ok(0, "unexpected call\n");
1199 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1201 ok(0, "unexpected call\n");
1205 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1207 ok(0, "unexpected call\n");
1211 static const IStreamVtbl StreamVtbl
= {
1212 istream_QueryInterface
,
1223 istream_UnlockRegion
,
1228 static IStream mxstream
= { &StreamVtbl
};
1230 static void test_saxreader(int version
)
1233 ISAXXMLReader
*reader
= NULL
;
1235 ISAXContentHandler
*lpContentHandler
;
1236 ISAXErrorHandler
*lpErrorHandler
;
1238 SAFEARRAYBOUND SADim
[1];
1239 char *pSAData
= NULL
;
1241 ULARGE_INTEGER liSize
;
1242 LARGE_INTEGER liPos
;
1245 static const CHAR testXmlA
[] = "test.xml";
1246 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
1247 IXMLDOMDocument
*domDocument
;
1251 msxml_version
= version
;
1253 hr
= CoCreateInstance(&CLSID_SAXXMLReader30
, NULL
, CLSCTX_INPROC_SERVER
,
1254 &IID_ISAXXMLReader
, (LPVOID
*)&reader
);
1255 } else if(version
== 6) {
1256 hr
= CoCreateInstance(&CLSID_SAXXMLReader60
, NULL
, CLSCTX_INPROC_SERVER
,
1257 &IID_ISAXXMLReader
, (LPVOID
*)&reader
);
1258 if(hr
== REGDB_E_CLASSNOTREG
) {
1259 win_skip("SAXXMLReader6 not registered\n");
1263 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
1264 &IID_ISAXXMLReader
, (LPVOID
*)&reader
);
1266 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1269 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
1270 ok(hr
== E_POINTER
, "Expected E_POINTER, got %08x\n", hr
);
1272 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
1273 ok(hr
== E_POINTER
, "Expected E_POINTER, got %08x\n", hr
);
1276 hr
= ISAXXMLReader_getContentHandler(reader
, &lpContentHandler
);
1277 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1278 ok(lpContentHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpContentHandler
);
1280 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
1281 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1282 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
1284 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
1285 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1287 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
1288 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1290 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
1291 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1293 hr
= ISAXXMLReader_getContentHandler(reader
, &lpContentHandler
);
1294 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1295 ok(lpContentHandler
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, lpContentHandler
);
1297 V_VT(&var
) = VT_BSTR
;
1298 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
1300 expectCall
= contentHandlerTest1
;
1301 hr
= ISAXXMLReader_parse(reader
, var
);
1302 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1303 test_expect_call(CH_ENDTEST
);
1307 SADim
[0].lLbound
= 0;
1308 SADim
[0].cElements
= sizeof(szTestXML
)-1;
1309 pSA
= SafeArrayCreate(VT_UI1
, 1, SADim
);
1310 SafeArrayAccessData(pSA
, (void**)&pSAData
);
1311 memcpy(pSAData
, szTestXML
, sizeof(szTestXML
)-1);
1312 SafeArrayUnaccessData(pSA
);
1313 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
1314 V_ARRAY(&var
) = pSA
;
1316 expectCall
= contentHandlerTest1
;
1317 hr
= ISAXXMLReader_parse(reader
, var
);
1318 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1319 test_expect_call(CH_ENDTEST
);
1321 SafeArrayDestroy(pSA
);
1323 CreateStreamOnHGlobal(NULL
, TRUE
, &iStream
);
1324 liSize
.QuadPart
= strlen(szTestXML
);
1325 IStream_SetSize(iStream
, liSize
);
1326 IStream_Write(iStream
, szTestXML
, strlen(szTestXML
), &bytesWritten
);
1328 IStream_Seek(iStream
, liPos
, STREAM_SEEK_SET
, NULL
);
1329 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
1330 V_UNKNOWN(&var
) = (IUnknown
*)iStream
;
1332 expectCall
= contentHandlerTest1
;
1333 hr
= ISAXXMLReader_parse(reader
, var
);
1334 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1335 test_expect_call(CH_ENDTEST
);
1337 IStream_Release(iStream
);
1339 CreateStreamOnHGlobal(NULL
, TRUE
, &iStream
);
1340 liSize
.QuadPart
= strlen(szTestAttributes
);
1341 IStream_SetSize(iStream
, liSize
);
1342 IStream_Write(iStream
, szTestAttributes
, strlen(szTestAttributes
), &bytesWritten
);
1344 IStream_Seek(iStream
, liPos
, STREAM_SEEK_SET
, NULL
);
1345 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
1346 V_UNKNOWN(&var
) = (IUnknown
*)iStream
;
1349 expectCall
= contentHandlerTestAttributes6
;
1351 expectCall
= contentHandlerTestAttributes
;
1352 hr
= ISAXXMLReader_parse(reader
, var
);
1353 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1354 test_expect_call(CH_ENDTEST
);
1356 IStream_Release(iStream
);
1358 V_VT(&var
) = VT_BSTR
;
1359 V_BSTR(&var
) = SysAllocString(szCarriageRetTest
);
1361 expectCall
= contentHandlerTest2
;
1362 hr
= ISAXXMLReader_parse(reader
, var
);
1363 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1364 test_expect_call(CH_ENDTEST
);
1368 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1369 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
1370 WriteFile(file
, szTestXML
, sizeof(szTestXML
)-1, &bytesWritten
, NULL
);
1373 expectCall
= contentHandlerTest1
;
1374 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1375 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1376 test_expect_call(CH_ENDTEST
);
1378 expectCall
= contentHandlerTestError
;
1379 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1380 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
1381 test_expect_call(CH_ENDTEST
);
1384 expectCall
= contentHandlerTestCallbackResult6
;
1386 expectCall
= contentHandlerTestCallbackResults
;
1387 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1388 ok(hr
== (version
>=6 ? S_OK
: S_FALSE
), "Expected S_FALSE, got %08x\n", hr
);
1389 test_expect_call(CH_ENDTEST
);
1391 DeleteFileA(testXmlA
);
1393 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
1394 &IID_IXMLDOMDocument
, (LPVOID
*)&domDocument
);
1397 skip("Failed to create DOMDocument instance\n");
1400 bstrData
= SysAllocString(szSimpleXML
);
1401 hr
= IXMLDOMDocument_loadXML(domDocument
, bstrData
, &vBool
);
1402 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1403 V_VT(&var
) = VT_UNKNOWN
;
1404 V_UNKNOWN(&var
) = (IUnknown
*)domDocument
;
1406 expectCall
= contentHandlerTest2
;
1407 hr
= ISAXXMLReader_parse(reader
, var
);
1408 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1409 test_expect_call(CH_ENDTEST
);
1410 IXMLDOMDocument_Release(domDocument
);
1412 ISAXXMLReader_Release(reader
);
1413 SysFreeString(bstrData
);
1416 struct saxreader_props_test_t
1418 const char *prop_name
;
1422 static const struct saxreader_props_test_t props_test_data
[] = {
1423 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&saxlexicalhandler
},
1424 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&saxdeclhandler
},
1428 static void test_saxreader_properties(void)
1430 const struct saxreader_props_test_t
*ptr
= props_test_data
;
1431 ISAXXMLReader
*reader
;
1434 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
1435 &IID_ISAXXMLReader
, (void**)&reader
);
1436 EXPECT_HR(hr
, S_OK
);
1438 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
1439 EXPECT_HR(hr
, E_POINTER
);
1441 while (ptr
->prop_name
)
1445 V_VT(&v
) = VT_EMPTY
;
1446 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
1447 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
1448 EXPECT_HR(hr
, S_OK
);
1449 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
1450 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
1452 V_VT(&v
) = VT_UNKNOWN
;
1453 V_UNKNOWN(&v
) = ptr
->iface
;
1454 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
1455 EXPECT_HR(hr
, S_OK
);
1457 V_VT(&v
) = VT_EMPTY
;
1458 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
1459 handler_addrefcalled
= 0;
1460 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
1461 EXPECT_HR(hr
, S_OK
);
1462 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
1463 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
1464 ok(handler_addrefcalled
== 1, "AddRef called %d times\n", handler_addrefcalled
);
1467 V_VT(&v
) = VT_EMPTY
;
1468 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
1469 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
1470 EXPECT_HR(hr
, S_OK
);
1472 V_VT(&v
) = VT_EMPTY
;
1473 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
1474 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
1475 EXPECT_HR(hr
, S_OK
);
1476 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
1477 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
1479 V_VT(&v
) = VT_UNKNOWN
;
1480 V_UNKNOWN(&v
) = ptr
->iface
;
1481 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
1482 EXPECT_HR(hr
, S_OK
);
1484 /* only VT_EMPTY seems to be valid to reset property */
1486 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
1487 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
1488 EXPECT_HR(hr
, E_INVALIDARG
);
1490 V_VT(&v
) = VT_EMPTY
;
1491 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
1492 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
1493 EXPECT_HR(hr
, S_OK
);
1494 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
1495 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
1498 V_VT(&v
) = VT_UNKNOWN
;
1499 V_UNKNOWN(&v
) = NULL
;
1500 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
1501 EXPECT_HR(hr
, S_OK
);
1503 V_VT(&v
) = VT_EMPTY
;
1504 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
1505 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
1506 EXPECT_HR(hr
, S_OK
);
1507 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
1508 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
1513 ISAXXMLReader_Release(reader
);
1517 struct feature_ns_entry_t
{
1523 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
1524 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
},
1525 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
},
1526 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
},
1527 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
},
1531 static void test_saxreader_features(void)
1533 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
1534 ISAXXMLReader
*reader
;
1541 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
1544 win_skip("can't create %s instance\n", entry
->clsid
);
1550 hr
= ISAXXMLReader_getFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), &value
);
1551 EXPECT_HR(hr
, S_OK
);
1553 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
1555 ISAXXMLReader_Release(reader
);
1561 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
1562 static const CHAR UTF8BOMTest
[] =
1563 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
1566 struct enc_test_entry_t
{
1574 static const struct enc_test_entry_t encoding_test_data
[] = {
1575 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, 1 },
1576 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, 1 },
1577 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, 0 },
1578 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, 0 },
1582 static void test_encoding(void)
1584 const struct enc_test_entry_t
*entry
= encoding_test_data
;
1585 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
1586 static const CHAR testXmlA
[] = "test.xml";
1587 ISAXXMLReader
*reader
;
1594 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
1597 win_skip("can't create %s instance\n", entry
->clsid
);
1602 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1603 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
1604 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
1607 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1609 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
1611 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
1613 DeleteFileA(testXmlA
);
1614 ISAXXMLReader_Release(reader
);
1620 static void test_mxwriter_contenthandler(void)
1622 ISAXContentHandler
*handler
;
1623 IMXWriter
*writer
, *writer2
;
1626 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
1627 &IID_IMXWriter
, (void**)&writer
);
1628 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1630 EXPECT_REF(writer
, 1);
1632 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&handler
);
1633 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1634 EXPECT_REF(writer
, 2);
1635 EXPECT_REF(handler
, 2);
1637 hr
= ISAXContentHandler_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
1638 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1639 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
1640 EXPECT_REF(writer
, 3);
1641 EXPECT_REF(writer2
, 3);
1642 IMXWriter_Release(writer2
);
1644 ISAXContentHandler_Release(handler
);
1645 IMXWriter_Release(writer
);
1648 struct msxmlsupported_data_t
1655 static struct msxmlsupported_data_t msxmlsupported_data
[] =
1657 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
1658 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
1659 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
1660 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
1664 static BOOL
is_mxwriter_supported(const GUID
*clsid
, const struct msxmlsupported_data_t
*table
)
1666 while (table
->clsid
)
1668 if (table
->clsid
== clsid
) return table
->supported
;
1674 struct mxwriter_props_t
1678 VARIANT_BOOL disable_escape
;
1679 VARIANT_BOOL indent
;
1680 VARIANT_BOOL omitdecl
;
1681 VARIANT_BOOL standalone
;
1682 const char *encoding
;
1685 static const struct mxwriter_props_t mxwriter_default_props
[] =
1687 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
1688 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
1689 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
1690 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
1694 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
1698 while (table
->clsid
)
1705 if (!is_mxwriter_supported(table
->clsid
, msxmlsupported_data
))
1712 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
1713 &IID_IMXWriter
, (void**)&writer
);
1714 EXPECT_HR(hr
, S_OK
);
1717 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
1718 EXPECT_HR(hr
, S_OK
);
1719 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
1721 b
= !table
->disable_escape
;
1722 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
1723 EXPECT_HR(hr
, S_OK
);
1724 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
1725 table
->disable_escape
);
1728 hr
= IMXWriter_get_indent(writer
, &b
);
1729 EXPECT_HR(hr
, S_OK
);
1730 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
1732 b
= !table
->omitdecl
;
1733 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
1734 EXPECT_HR(hr
, S_OK
);
1735 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
1737 b
= !table
->standalone
;
1738 hr
= IMXWriter_get_standalone(writer
, &b
);
1739 EXPECT_HR(hr
, S_OK
);
1740 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
1742 hr
= IMXWriter_get_encoding(writer
, &encoding
);
1743 EXPECT_HR(hr
, S_OK
);
1744 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
1745 i
, wine_dbgstr_w(encoding
), table
->encoding
);
1746 SysFreeString(encoding
);
1748 IMXWriter_Release(writer
);
1755 static void test_mxwriter_properties(void)
1757 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
1758 static const WCHAR emptyW
[] = {0};
1759 static const WCHAR testW
[] = {'t','e','s','t',0};
1765 test_mxwriter_default_properties(mxwriter_default_props
);
1767 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
1768 &IID_IMXWriter
, (void**)&writer
);
1769 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1771 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
1772 ok(hr
== E_POINTER
, "got %08x\n", hr
);
1774 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
1775 ok(hr
== E_POINTER
, "got %08x\n", hr
);
1777 hr
= IMXWriter_get_indent(writer
, NULL
);
1778 ok(hr
== E_POINTER
, "got %08x\n", hr
);
1780 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
1781 ok(hr
== E_POINTER
, "got %08x\n", hr
);
1783 hr
= IMXWriter_get_standalone(writer
, NULL
);
1784 ok(hr
== E_POINTER
, "got %08x\n", hr
);
1787 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
1788 ok(hr
== S_OK
, "got %08x\n", hr
);
1791 hr
= IMXWriter_get_standalone(writer
, &b
);
1792 ok(hr
== S_OK
, "got %08x\n", hr
);
1793 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
1795 hr
= IMXWriter_get_encoding(writer
, NULL
);
1796 ok(hr
== E_POINTER
, "got %08x\n", hr
);
1798 /* UTF-16 is a default setting apparently */
1799 str
= (void*)0xdeadbeef;
1800 hr
= IMXWriter_get_encoding(writer
, &str
);
1801 ok(hr
== S_OK
, "got %08x\n", hr
);
1802 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
1804 str2
= (void*)0xdeadbeef;
1805 hr
= IMXWriter_get_encoding(writer
, &str2
);
1806 ok(hr
== S_OK
, "got %08x\n", hr
);
1807 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
1809 SysFreeString(str2
);
1812 /* put empty string */
1813 str
= SysAllocString(emptyW
);
1814 hr
= IMXWriter_put_encoding(writer
, str
);
1815 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
1818 str
= (void*)0xdeadbeef;
1819 hr
= IMXWriter_get_encoding(writer
, &str
);
1820 ok(hr
== S_OK
, "got %08x\n", hr
);
1821 ok(!lstrcmpW(str
, emptyW
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
1824 /* invalid encoding name */
1825 str
= SysAllocString(testW
);
1826 hr
= IMXWriter_put_encoding(writer
, str
);
1827 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
1830 hr
= IMXWriter_get_version(writer
, NULL
);
1831 ok(hr
== E_POINTER
, "got %08x\n", hr
);
1832 /* default version is 'surprisingly' 1.0 */
1833 hr
= IMXWriter_get_version(writer
, &str
);
1834 ok(hr
== S_OK
, "got %08x\n", hr
);
1835 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
1838 /* store version string as is */
1839 hr
= IMXWriter_put_version(writer
, NULL
);
1840 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
1842 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
1843 ok(hr
== S_OK
, "got %08x\n", hr
);
1845 hr
= IMXWriter_put_version(writer
, _bstr_(""));
1846 ok(hr
== S_OK
, "got %08x\n", hr
);
1847 hr
= IMXWriter_get_version(writer
, &str
);
1848 ok(hr
== S_OK
, "got %08x\n", hr
);
1849 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
1852 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
1853 ok(hr
== S_OK
, "got %08x\n", hr
);
1854 hr
= IMXWriter_get_version(writer
, &str
);
1855 ok(hr
== S_OK
, "got %08x\n", hr
);
1856 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
1859 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
1860 ok(hr
== S_OK
, "got %08x\n", hr
);
1861 hr
= IMXWriter_get_version(writer
, &str
);
1862 ok(hr
== S_OK
, "got %08x\n", hr
);
1863 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
1866 IMXWriter_Release(writer
);
1870 static void test_mxwriter_flush(void)
1872 ISAXContentHandler
*content
;
1875 ULARGE_INTEGER pos2
;
1880 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
1881 &IID_IMXWriter
, (void**)&writer
);
1882 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1884 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1885 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1886 EXPECT_REF(stream
, 1);
1888 /* detach when nothing was attached */
1889 V_VT(&dest
) = VT_EMPTY
;
1890 hr
= IMXWriter_put_output(writer
, dest
);
1891 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1894 V_VT(&dest
) = VT_UNKNOWN
;
1895 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
1896 hr
= IMXWriter_put_output(writer
, dest
);
1897 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1898 todo_wine
EXPECT_REF(stream
, 3);
1900 /* detach setting VT_EMPTY destination */
1901 V_VT(&dest
) = VT_EMPTY
;
1902 hr
= IMXWriter_put_output(writer
, dest
);
1903 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1904 EXPECT_REF(stream
, 1);
1906 V_VT(&dest
) = VT_UNKNOWN
;
1907 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
1908 hr
= IMXWriter_put_output(writer
, dest
);
1909 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1911 /* flush() doesn't detach a stream */
1912 hr
= IMXWriter_flush(writer
);
1913 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1914 todo_wine
EXPECT_REF(stream
, 3);
1917 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
1918 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1919 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
1921 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
1922 ok(hr
== S_OK
, "got %08x\n", hr
);
1924 hr
= ISAXContentHandler_startDocument(content
);
1925 ok(hr
== S_OK
, "got %08x\n", hr
);
1928 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
1929 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1930 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
1932 /* already started */
1933 hr
= ISAXContentHandler_startDocument(content
);
1934 ok(hr
== S_OK
, "got %08x\n", hr
);
1936 hr
= ISAXContentHandler_endDocument(content
);
1937 ok(hr
== S_OK
, "got %08x\n", hr
);
1939 /* flushed on endDocument() */
1941 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
1942 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1943 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
1945 ISAXContentHandler_Release(content
);
1946 IStream_Release(stream
);
1947 IMXWriter_Release(writer
);
1950 static void test_mxwriter_startenddocument(void)
1952 ISAXContentHandler
*content
;
1957 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
1958 &IID_IMXWriter
, (void**)&writer
);
1959 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1961 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
1962 ok(hr
== S_OK
, "got %08x\n", hr
);
1964 hr
= ISAXContentHandler_startDocument(content
);
1965 ok(hr
== S_OK
, "got %08x\n", hr
);
1967 hr
= ISAXContentHandler_endDocument(content
);
1968 ok(hr
== S_OK
, "got %08x\n", hr
);
1970 V_VT(&dest
) = VT_EMPTY
;
1971 hr
= IMXWriter_get_output(writer
, &dest
);
1972 ok(hr
== S_OK
, "got %08x\n", hr
);
1973 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
1974 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
1975 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
1976 VariantClear(&dest
);
1978 /* now try another startDocument */
1979 hr
= ISAXContentHandler_startDocument(content
);
1980 ok(hr
== S_OK
, "got %08x\n", hr
);
1981 /* and get duplicated prolog */
1982 V_VT(&dest
) = VT_EMPTY
;
1983 hr
= IMXWriter_get_output(writer
, &dest
);
1984 ok(hr
== S_OK
, "got %08x\n", hr
);
1985 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
1986 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
1987 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
1988 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
1989 VariantClear(&dest
);
1991 ISAXContentHandler_Release(content
);
1992 IMXWriter_Release(writer
);
1994 /* now with omitted declaration */
1995 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
1996 &IID_IMXWriter
, (void**)&writer
);
1997 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
1999 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2000 ok(hr
== S_OK
, "got %08x\n", hr
);
2002 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2003 ok(hr
== S_OK
, "got %08x\n", hr
);
2005 hr
= ISAXContentHandler_startDocument(content
);
2006 ok(hr
== S_OK
, "got %08x\n", hr
);
2008 hr
= ISAXContentHandler_endDocument(content
);
2009 ok(hr
== S_OK
, "got %08x\n", hr
);
2011 V_VT(&dest
) = VT_EMPTY
;
2012 hr
= IMXWriter_get_output(writer
, &dest
);
2013 ok(hr
== S_OK
, "got %08x\n", hr
);
2014 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2015 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2016 VariantClear(&dest
);
2018 ISAXContentHandler_Release(content
);
2019 IMXWriter_Release(writer
);
2031 struct writer_startendelement_t
{
2033 enum startendtype type
;
2035 const char *local_name
;
2039 ISAXAttributes
*attr
;
2042 static const struct writer_startendelement_t writer_startendelement
[] = {
2044 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2045 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2046 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2047 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
2048 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2050 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2051 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2052 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
2053 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2054 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2056 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2057 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
2058 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2059 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2060 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2062 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
2063 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2064 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2065 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2066 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2068 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2069 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2070 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2071 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
2072 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2074 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2075 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2076 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2077 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2078 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2080 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2081 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2082 /* endElement tests */
2083 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2084 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2085 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2087 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
2088 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2089 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2090 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2091 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
2093 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2094 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2095 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2096 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
2097 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2099 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2100 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2101 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
2102 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2103 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2105 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2106 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2107 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2108 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2109 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2111 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
2112 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2113 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2114 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2115 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2117 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2118 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2119 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2120 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2122 /* with attributes */
2123 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\">", S_OK
, &saxattributes
},
2125 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\">", S_OK
, &saxattributes
},
2126 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\">", S_OK
, &saxattributes
},
2127 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\">", S_OK
, &saxattributes
},
2128 /* empty elements */
2129 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\"/>", S_OK
, &saxattributes
},
2130 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\"/>", S_OK
, &saxattributes
},
2132 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\"/>", S_OK
, &saxattributes
},
2133 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", "<uri:local a:attr1=\"a1\" attr2=\"a2\"/>", S_OK
, &saxattributes
},
2134 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
2135 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
2136 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
2138 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
2142 static void get_supported_mxwriter_data(struct msxmlsupported_data_t
*table
)
2144 while (table
->clsid
)
2149 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2150 &IID_IMXWriter
, (void**)&writer
);
2151 if (hr
== S_OK
) IMXWriter_Release(writer
);
2153 table
->supported
= hr
== S_OK
;
2154 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
2160 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
2164 while (table
->clsid
)
2166 ISAXContentHandler
*content
;
2170 if (!is_mxwriter_supported(table
->clsid
, msxmlsupported_data
))
2177 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2178 &IID_IMXWriter
, (void**)&writer
);
2179 EXPECT_HR(hr
, S_OK
);
2181 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2182 EXPECT_HR(hr
, S_OK
);
2184 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2185 EXPECT_HR(hr
, S_OK
);
2187 hr
= ISAXContentHandler_startDocument(content
);
2188 EXPECT_HR(hr
, S_OK
);
2190 if (table
->type
== StartElement
)
2192 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
2193 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
), table
->attr
);
2194 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
2196 else if (table
->type
== EndElement
)
2198 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
2199 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
));
2200 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
2204 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
2205 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
), table
->attr
);
2206 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
2207 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
2208 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
));
2209 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
2217 V_VT(&dest
) = VT_EMPTY
;
2218 hr
= IMXWriter_get_output(writer
, &dest
);
2219 EXPECT_HR(hr
, S_OK
);
2220 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2221 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
2222 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
2223 VariantClear(&dest
);
2226 ISAXContentHandler_Release(content
);
2227 IMXWriter_Release(writer
);
2236 static void test_mxwriter_startendelement(void)
2238 ISAXContentHandler
*content
;
2243 test_mxwriter_startendelement_batch(writer_startendelement
);
2245 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2246 &IID_IMXWriter
, (void**)&writer
);
2247 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2249 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2250 ok(hr
== S_OK
, "got %08x\n", hr
);
2252 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2253 ok(hr
== S_OK
, "got %08x\n", hr
);
2255 hr
= ISAXContentHandler_startDocument(content
);
2256 ok(hr
== S_OK
, "got %08x\n", hr
);
2258 /* all string pointers should be not null */
2259 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
2260 ok(hr
== S_OK
, "got %08x\n", hr
);
2262 V_VT(&dest
) = VT_EMPTY
;
2263 hr
= IMXWriter_get_output(writer
, &dest
);
2264 ok(hr
== S_OK
, "got %08x\n", hr
);
2265 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2266 ok(!lstrcmpW(_bstr_("<>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2267 VariantClear(&dest
);
2269 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
2270 ok(hr
== S_OK
, "got %08x\n", hr
);
2272 V_VT(&dest
) = VT_EMPTY
;
2273 hr
= IMXWriter_get_output(writer
, &dest
);
2274 ok(hr
== S_OK
, "got %08x\n", hr
);
2275 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2276 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2277 VariantClear(&dest
);
2279 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
2280 EXPECT_HR(hr
, E_INVALIDARG
);
2282 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
2283 EXPECT_HR(hr
, E_INVALIDARG
);
2285 /* only local name is an error too */
2286 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
2287 EXPECT_HR(hr
, E_INVALIDARG
);
2289 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
2290 EXPECT_HR(hr
, S_OK
);
2292 V_VT(&dest
) = VT_EMPTY
;
2293 hr
= IMXWriter_get_output(writer
, &dest
);
2294 EXPECT_HR(hr
, S_OK
);
2295 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2296 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2297 VariantClear(&dest
);
2299 hr
= ISAXContentHandler_endDocument(content
);
2300 EXPECT_HR(hr
, S_OK
);
2302 V_VT(&dest
) = VT_EMPTY
;
2303 hr
= IMXWriter_put_output(writer
, dest
);
2304 EXPECT_HR(hr
, S_OK
);
2306 hr
= ISAXContentHandler_startDocument(content
);
2307 EXPECT_HR(hr
, S_OK
);
2309 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
2310 EXPECT_HR(hr
, S_OK
);
2312 V_VT(&dest
) = VT_EMPTY
;
2313 hr
= IMXWriter_get_output(writer
, &dest
);
2314 EXPECT_HR(hr
, S_OK
);
2315 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2316 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2317 VariantClear(&dest
);
2319 ISAXContentHandler_endDocument(content
);
2320 IMXWriter_flush(writer
);
2322 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
2323 EXPECT_HR(hr
, S_OK
);
2324 V_VT(&dest
) = VT_EMPTY
;
2325 hr
= IMXWriter_get_output(writer
, &dest
);
2326 EXPECT_HR(hr
, S_OK
);
2327 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2328 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2329 VariantClear(&dest
);
2331 ISAXContentHandler_Release(content
);
2332 IMXWriter_Release(writer
);
2336 static void test_mxwriter_characters(void)
2338 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
2339 ISAXContentHandler
*content
;
2344 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2345 &IID_IMXWriter
, (void**)&writer
);
2346 EXPECT_HR(hr
, S_OK
);
2348 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2349 EXPECT_HR(hr
, S_OK
);
2351 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2352 EXPECT_HR(hr
, S_OK
);
2354 hr
= ISAXContentHandler_startDocument(content
);
2355 EXPECT_HR(hr
, S_OK
);
2357 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
2358 EXPECT_HR(hr
, E_INVALIDARG
);
2360 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
2361 EXPECT_HR(hr
, S_OK
);
2363 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
2364 EXPECT_HR(hr
, S_OK
);
2366 V_VT(&dest
) = VT_EMPTY
;
2367 hr
= IMXWriter_get_output(writer
, &dest
);
2368 EXPECT_HR(hr
, S_OK
);
2369 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2370 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2371 VariantClear(&dest
);
2373 hr
= ISAXContentHandler_endDocument(content
);
2374 EXPECT_HR(hr
, S_OK
);
2376 ISAXContentHandler_Release(content
);
2377 IMXWriter_Release(writer
);
2379 /* try empty characters data to see if element is closed */
2380 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2381 &IID_IMXWriter
, (void**)&writer
);
2382 EXPECT_HR(hr
, S_OK
);
2384 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2385 EXPECT_HR(hr
, S_OK
);
2387 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2388 EXPECT_HR(hr
, S_OK
);
2390 hr
= ISAXContentHandler_startDocument(content
);
2391 EXPECT_HR(hr
, S_OK
);
2393 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
2394 EXPECT_HR(hr
, S_OK
);
2396 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
2397 EXPECT_HR(hr
, S_OK
);
2399 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
2400 EXPECT_HR(hr
, S_OK
);
2402 V_VT(&dest
) = VT_EMPTY
;
2403 hr
= IMXWriter_get_output(writer
, &dest
);
2404 EXPECT_HR(hr
, S_OK
);
2405 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2406 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2407 VariantClear(&dest
);
2409 ISAXContentHandler_Release(content
);
2410 IMXWriter_Release(writer
);
2415 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
2417 VARIANT_TRUE
,"UTF-16",
2419 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
2420 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
2425 VARIANT_FALSE
,"UTF-16",
2427 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
2432 VARIANT_TRUE
,"UTF-8",
2434 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
2435 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
2436 * and the writer is released.
2443 VARIANT_TRUE
,"UTF-16",
2445 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
2446 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
2451 VARIANT_TRUE
,"UTF-16",
2453 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
2454 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
2460 static void test_mxwriter_stream(void)
2463 ISAXContentHandler
*content
;
2468 ULARGE_INTEGER pos2
;
2469 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
2471 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
2472 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
2474 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2475 &IID_IMXWriter
, (void**)&writer
);
2476 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
2478 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2479 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
2481 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
2482 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
2484 V_VT(&dest
) = VT_UNKNOWN
;
2485 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
2486 hr
= IMXWriter_put_output(writer
, dest
);
2487 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
2488 VariantClear(&dest
);
2490 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
2491 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
2493 current_write_test
= test
->expected_writes
;
2495 hr
= ISAXContentHandler_startDocument(content
);
2496 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
2498 hr
= ISAXContentHandler_endDocument(content
);
2499 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
2501 ISAXContentHandler_Release(content
);
2502 IMXWriter_Release(writer
);
2504 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
2505 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
2508 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2509 &IID_IMXWriter
, (void**)&writer
);
2510 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
2512 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2513 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
2515 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2516 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
2518 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
2519 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
2521 V_VT(&dest
) = VT_UNKNOWN
;
2522 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
2523 hr
= IMXWriter_put_output(writer
, dest
);
2524 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
2526 hr
= ISAXContentHandler_startDocument(content
);
2527 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
2529 /* Setting output of the mxwriter causes the current output to be flushed,
2530 * and the writer to start over.
2532 V_VT(&dest
) = VT_EMPTY
;
2533 hr
= IMXWriter_put_output(writer
, dest
);
2534 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
2537 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2538 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
2539 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
2541 hr
= ISAXContentHandler_startDocument(content
);
2542 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
2544 hr
= ISAXContentHandler_endDocument(content
);
2545 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
2547 V_VT(&dest
) = VT_EMPTY
;
2548 hr
= IMXWriter_get_output(writer
, &dest
);
2549 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
2550 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
2551 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
2552 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2553 VariantClear(&dest
);
2555 ISAXContentHandler_Release(content
);
2556 IMXWriter_Release(writer
);
2561 static void test_mxwriter_encoding(void)
2564 ISAXContentHandler
*content
;
2568 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2569 &IID_IMXWriter
, (void**)&writer
);
2570 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
2572 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2573 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
2575 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
2576 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
2578 hr
= ISAXContentHandler_startDocument(content
);
2579 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
2581 hr
= ISAXContentHandler_endDocument(content
);
2582 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
2584 /* The content is always re-encoded to UTF-16 when the output is
2585 * retrieved as a BSTR.
2587 V_VT(&dest
) = VT_EMPTY
;
2588 hr
= IMXWriter_get_output(writer
, &dest
);
2589 todo_wine
ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
2590 todo_wine
ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
2591 if (V_VT(&dest
) == VT_BSTR
) todo_wine
ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
2592 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2593 VariantClear(&dest
);
2595 ISAXContentHandler_Release(content
);
2596 IMXWriter_Release(writer
);
2601 static void test_obj_dispex(IUnknown
*obj
)
2603 static const WCHAR starW
[] = {'*',0};
2604 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
2605 IDispatchEx
*dispex
;
2612 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
2613 EXPECT_HR(hr
, S_OK
);
2614 if (FAILED(hr
)) return;
2617 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
2618 EXPECT_HR(hr
, S_OK
);
2619 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
2621 name
= SysAllocString(starW
);
2622 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
2623 EXPECT_HR(hr
, E_NOTIMPL
);
2624 SysFreeString(name
);
2626 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
2627 EXPECT_HR(hr
, E_NOTIMPL
);
2630 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
2631 EXPECT_HR(hr
, E_NOTIMPL
);
2632 ok(props
== 0, "expected 0 got %d\n", props
);
2634 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
2635 EXPECT_HR(hr
, E_NOTIMPL
);
2636 if (SUCCEEDED(hr
)) SysFreeString(name
);
2638 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
2639 EXPECT_HR(hr
, E_NOTIMPL
);
2641 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
2642 EXPECT_HR(hr
, E_NOTIMPL
);
2643 if (hr
== S_OK
&& unk
) IUnknown_Release(unk
);
2645 IDispatchEx_Release(dispex
);
2648 static void test_dispex(void)
2650 IVBSAXXMLReader
*vbreader
;
2651 ISAXXMLReader
*reader
;
2655 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2656 &IID_ISAXXMLReader
, (void**)&reader
);
2657 EXPECT_HR(hr
, S_OK
);
2659 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
2660 EXPECT_HR(hr
, S_OK
);
2661 test_obj_dispex(unk
);
2662 IUnknown_Release(unk
);
2664 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
2665 EXPECT_HR(hr
, S_OK
);
2666 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
2667 EXPECT_HR(hr
, S_OK
);
2668 test_obj_dispex(unk
);
2669 IUnknown_Release(unk
);
2670 IVBSAXXMLReader_Release(vbreader
);
2672 ISAXXMLReader_Release(reader
);
2675 START_TEST(saxreader
)
2677 ISAXXMLReader
*reader
;
2680 hr
= CoInitialize(NULL
);
2681 ok(hr
== S_OK
, "failed to init com\n");
2683 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2684 &IID_ISAXXMLReader
, (void**)&reader
);
2688 skip("Failed to create SAXXMLReader instance\n");
2692 ISAXXMLReader_Release(reader
);
2697 test_saxreader_properties();
2698 test_saxreader_features();
2702 /* MXXMLWriter tests */
2703 get_supported_mxwriter_data(msxmlsupported_data
);
2704 if (is_mxwriter_supported(&CLSID_MXXMLWriter
, msxmlsupported_data
))
2706 test_mxwriter_contenthandler();
2707 test_mxwriter_startenddocument();
2708 test_mxwriter_startendelement();
2709 test_mxwriter_characters();
2710 test_mxwriter_properties();
2711 test_mxwriter_flush();
2712 test_mxwriter_stream();
2713 test_mxwriter_encoding();
2716 win_skip("MXXMLWriter not supported\n");