2 * SAXReader/MXWriter tests
4 * Copyright 2008 Piotr Caban
5 * Copyright 2011 Thomas Mullaly
6 * Copyright 2012 Nikolay Sivov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define WIN32_NO_STATUS
25 #define COM_NO_WINDOWS_H
33 #include <wine/test.h>
34 //#include "windows.h"
38 #include <msxml2did.h>
43 #define EXPECT_HR(hr,hr_exp) \
44 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
46 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
47 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
49 ULONG rc
= IUnknown_AddRef(obj
);
50 IUnknown_Release(obj
);
51 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
54 static LONG
get_refcount(void *iface
)
56 IUnknown
*unk
= iface
;
59 ref
= IUnknown_AddRef(unk
);
60 IUnknown_Release(unk
);
64 struct msxmlsupported_data_t
71 static BOOL
is_clsid_supported(const GUID
*clsid
, const struct msxmlsupported_data_t
*table
)
75 if (table
->clsid
== clsid
) return table
->supported
;
81 static BSTR
alloc_str_from_narrow(const char *str
)
83 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
84 BSTR ret
= SysAllocStringLen(NULL
, len
- 1); /* NUL character added automatically */
85 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
89 static BSTR alloced_bstrs
[512];
90 static int alloced_bstrs_count
;
92 static BSTR
_bstr_(const char *str
)
94 assert(alloced_bstrs_count
< sizeof(alloced_bstrs
)/sizeof(alloced_bstrs
[0]));
95 alloced_bstrs
[alloced_bstrs_count
] = alloc_str_from_narrow(str
);
96 return alloced_bstrs
[alloced_bstrs_count
++];
99 static void free_bstrs(void)
102 for (i
= 0; i
< alloced_bstrs_count
; i
++)
103 SysFreeString(alloced_bstrs
[i
]);
104 alloced_bstrs_count
= 0;
107 static void test_saxstr(const char *file
, unsigned line
, BSTR str
, const char *expected
, int todo
, int *failcount
)
109 int len
, lenexp
, cmp
;
112 len
= SysStringLen(str
);
119 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
122 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
128 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
131 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
135 lenexp
= strlen(expected
);
136 if (lenexp
!= len
&& todo
)
140 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
143 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
145 /* exit earlier on length mismatch */
146 if (lenexp
!= len
) return;
148 MultiByteToWideChar(CP_ACP
, 0, expected
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
150 cmp
= memcmp(str
, buf
, lenexp
*sizeof(WCHAR
));
155 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
156 wine_dbgstr_wn(str
, len
), expected
);
159 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
160 wine_dbgstr_wn(str
, len
), expected
);
165 CH_PUTDOCUMENTLOCATOR
,
168 CH_STARTPREFIXMAPPING
,
173 CH_IGNORABLEWHITESPACE
,
174 CH_PROCESSINGINSTRUCTION
,
184 static const char *event_names
[EVENT_LAST
] = {
186 "putDocumentLocator",
189 "startPrefixMapping",
194 "ignorableWhitespace",
195 "processingInstruction",
204 struct attribute_entry
{
210 /* used for actual call data only, null for expected call data */
226 /* allocated once at startElement callback */
227 struct attribute_entry
*attributes
;
230 /* used for actual call data only, null for expected call data */
240 struct call_entry
*sequence
;
243 #define CONTENT_HANDLER_INDEX 0
244 #define NUM_CALL_SEQUENCES 1
245 static struct call_sequence
*sequences
[NUM_CALL_SEQUENCES
];
247 static void init_call_entry(ISAXLocator
*locator
, struct call_entry
*call
)
249 memset(call
, 0, sizeof(*call
));
250 ISAXLocator_getLineNumber(locator
, &call
->line
);
251 ISAXLocator_getColumnNumber(locator
, &call
->column
);
254 static void add_call(struct call_sequence
**seq
, int sequence_index
,
255 const struct call_entry
*call
)
257 struct call_sequence
*call_seq
= seq
[sequence_index
];
259 if (!call_seq
->sequence
)
262 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0,
263 call_seq
->size
* sizeof (struct call_entry
));
266 if (call_seq
->count
== call_seq
->size
)
269 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
271 call_seq
->size
* sizeof (struct call_entry
));
274 assert(call_seq
->sequence
);
276 call_seq
->sequence
[call_seq
->count
].id
= call
->id
;
277 call_seq
->sequence
[call_seq
->count
].line
= call
->line
;
278 call_seq
->sequence
[call_seq
->count
].column
= call
->column
;
279 call_seq
->sequence
[call_seq
->count
].arg1W
= call
->arg1W
;
280 call_seq
->sequence
[call_seq
->count
].arg2W
= call
->arg2W
;
281 call_seq
->sequence
[call_seq
->count
].arg3W
= call
->arg3W
;
282 call_seq
->sequence
[call_seq
->count
].ret
= call
->ret
;
283 call_seq
->sequence
[call_seq
->count
].attr_count
= call
->attr_count
;
284 call_seq
->sequence
[call_seq
->count
].attributes
= call
->attributes
;
289 static inline void flush_sequence(struct call_sequence
**seg
, int sequence_index
)
293 struct call_sequence
*call_seq
= seg
[sequence_index
];
295 for (i
= 0; i
< call_seq
->count
; i
++)
299 for (j
= 0; j
< call_seq
->sequence
[i
].attr_count
; j
++)
301 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].uriW
);
302 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].localW
);
303 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].qnameW
);
306 SysFreeString(call_seq
->sequence
[i
].arg1W
);
307 SysFreeString(call_seq
->sequence
[i
].arg2W
);
308 SysFreeString(call_seq
->sequence
[i
].arg3W
);
311 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
312 call_seq
->sequence
= NULL
;
313 call_seq
->count
= call_seq
->size
= 0;
316 static inline void flush_sequences(struct call_sequence
**seq
, int n
)
319 for (i
= 0; i
< n
; i
++)
320 flush_sequence(seq
, i
);
323 static const char *get_event_name(CH event
)
325 return event_names
[event
];
328 static void compare_attributes(const struct call_entry
*actual
, const struct call_entry
*expected
, const char *context
,
329 int todo
, const char *file
, int line
, int *failcount
)
333 /* attribute count is not stored for expected data */
334 if (expected
->attributes
)
336 struct attribute_entry
*ptr
= expected
->attributes
;
337 while (ptr
->uri
) { lenexp
++; ptr
++; };
340 /* check count first and exit earlier */
341 if (actual
->attr_count
!= lenexp
&& todo
)
345 ok_(file
, line
) (FALSE
, "%s: in event %s expecting attr count %d got %d\n",
346 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
349 ok_(file
, line
) (actual
->attr_count
== lenexp
, "%s: in event %s expecting attr count %d got %d\n",
350 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
352 if (actual
->attr_count
!= lenexp
) return;
354 /* now compare all attributes strings */
355 for (i
= 0; i
< actual
->attr_count
; i
++)
357 test_saxstr(file
, line
, actual
->attributes
[i
].uriW
, expected
->attributes
[i
].uri
, todo
, failcount
);
358 test_saxstr(file
, line
, actual
->attributes
[i
].localW
, expected
->attributes
[i
].local
, todo
, failcount
);
359 test_saxstr(file
, line
, actual
->attributes
[i
].qnameW
, expected
->attributes
[i
].qname
, todo
, failcount
);
360 test_saxstr(file
, line
, actual
->attributes
[i
].valueW
, expected
->attributes
[i
].value
, todo
, failcount
);
364 static void ok_sequence_(struct call_sequence
**seq
, int sequence_index
,
365 const struct call_entry
*expected
, const char *context
, int todo
,
366 const char *file
, int line
)
368 struct call_sequence
*call_seq
= seq
[sequence_index
];
369 static const struct call_entry end_of_sequence
= { CH_ENDTEST
};
370 const struct call_entry
*actual
, *sequence
;
373 add_call(seq
, sequence_index
, &end_of_sequence
);
375 sequence
= call_seq
->sequence
;
378 while (expected
->id
!= CH_ENDTEST
&& actual
->id
!= CH_ENDTEST
)
380 if (expected
->id
== actual
->id
)
382 /* always test position data */
383 if (expected
->line
!= actual
->line
&& todo
)
388 ok_(file
, line
) (FALSE
,
389 "%s: in event %s expecting line %d got %d\n",
390 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
395 ok_(file
, line
) (expected
->line
== actual
->line
,
396 "%s: in event %s expecting line %d got %d\n",
397 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
400 if (expected
->column
!= actual
->column
&& todo
)
405 ok_(file
, line
) (FALSE
,
406 "%s: in event %s expecting column %d got %d\n",
407 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
412 ok_(file
, line
) (expected
->column
== actual
->column
,
413 "%s: in event %s expecting column %d got %d\n",
414 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
419 case CH_PUTDOCUMENTLOCATOR
:
420 case CH_STARTDOCUMENT
:
425 case CH_STARTPREFIXMAPPING
:
427 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
428 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
430 case CH_ENDPREFIXMAPPING
:
432 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
434 case CH_STARTELEMENT
:
435 /* compare attributes */
436 compare_attributes(actual
, expected
, context
, todo
, file
, line
, &failcount
);
439 /* uri, localname, qname */
440 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
441 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
442 test_saxstr(file
, line
, actual
->arg3W
, expected
->arg3
, todo
, &failcount
);
445 case CH_IGNORABLEWHITESPACE
:
447 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
449 case CH_PROCESSINGINSTRUCTION
:
451 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
452 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
454 case CH_SKIPPEDENTITY
:
456 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
459 /* test return value only */
460 if (expected
->ret
!= actual
->ret
&& todo
)
463 ok_(file
, line
) (FALSE
,
464 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
465 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
468 ok_(file
, line
) (expected
->ret
== actual
->ret
,
469 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
470 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
473 case EH_IGNORABLEWARNING
:
475 ok(0, "%s: callback not handled, %s\n", context
, get_event_name(actual
->id
));
485 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
486 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
489 flush_sequence(seq
, sequence_index
);
494 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
495 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
505 if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
508 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
509 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
513 else if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
515 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
516 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
519 if (todo
&& !failcount
) /* succeeded yet marked todo */
523 ok_(file
, line
)(TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
527 flush_sequence(seq
, sequence_index
);
530 #define ok_sequence(seq, index, exp, contx, todo) \
531 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
533 static void init_call_sequences(struct call_sequence
**seq
, int n
)
537 for (i
= 0; i
< n
; i
++)
538 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct call_sequence
));
541 static const WCHAR szSimpleXML
[] = {
542 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
543 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
544 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
545 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
546 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
549 static const WCHAR carriage_ret_test
[] = {
550 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
551 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
552 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
553 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
554 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
557 static const WCHAR szUtf16XML
[] = {
558 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
559 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
560 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
563 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
565 static const CHAR szUtf8XML
[] =
566 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
568 static const char utf8xml2
[] =
569 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n";
571 static const char testXML
[] =
572 "<?xml version=\"1.0\" ?>\n"
574 " <Number>1234</Number>\n"
575 " <Name>Captain Ahab</Name>\n"
578 static const char test_attributes
[] =
579 "<?xml version=\"1.0\" ?>\n"
580 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
581 "<node1 xmlns:p=\"test\" />"
584 static const char test_cdata_xml
[] =
585 "<?xml version=\"1.0\" ?>"
586 "<a><![CDATA[Some \r\ntext\n\r\ndata\n\n]]></a>";
588 static const char test2_cdata_xml
[] =
589 "<?xml version=\"1.0\" ?>"
590 "<a><![CDATA[\n\r\nSome \r\ntext\n\r\ndata\n\n]]></a>";
592 static const char test3_cdata_xml
[] =
593 "<?xml version=\"1.0\" ?><a><![CDATA[Some text data]]></a>";
595 static struct call_entry content_handler_test1
[] = {
596 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
597 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
598 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
599 { CH_CHARACTERS
, 2, 14, S_OK
, "\n " },
600 { CH_STARTELEMENT
, 3, 12, S_OK
, "", "Number", "Number" },
601 { CH_CHARACTERS
, 3, 12, S_OK
, "1234" },
602 { CH_ENDELEMENT
, 3, 18, S_OK
, "", "Number", "Number" },
603 { CH_CHARACTERS
, 3, 25, S_OK
, "\n " },
604 { CH_STARTELEMENT
, 4, 10, S_OK
, "", "Name", "Name" },
605 { CH_CHARACTERS
, 4, 10, S_OK
, "Captain Ahab" },
606 { CH_ENDELEMENT
, 4, 24, S_OK
, "", "Name", "Name" },
607 { CH_CHARACTERS
, 4, 29, S_OK
, "\n" },
608 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
609 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
613 /* applies to versions 4 and 6 */
614 static struct call_entry content_handler_test1_alternate
[] = {
615 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
616 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
617 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
618 { CH_CHARACTERS
, 3, 4, S_OK
, "\n " },
619 { CH_STARTELEMENT
, 3, 11, S_OK
, "", "Number", "Number" },
620 { CH_CHARACTERS
, 3, 16, S_OK
, "1234" },
621 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "Number", "Number" },
622 { CH_CHARACTERS
, 4, 4, S_OK
, "\n " },
623 { CH_STARTELEMENT
, 4, 9, S_OK
, "", "Name", "Name" },
624 { CH_CHARACTERS
, 4, 22, S_OK
, "Captain Ahab" },
625 { CH_ENDELEMENT
, 4, 28, S_OK
, "", "Name", "Name" },
626 { CH_CHARACTERS
, 5, 1, S_OK
, "\n" },
627 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
628 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
632 static struct call_entry content_handler_test2
[] = {
633 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
634 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
635 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
636 { CH_CHARACTERS
, 2, 14, S_OK
, "\n" },
637 { CH_CHARACTERS
, 2, 16, S_OK
, "\t" },
638 { CH_STARTELEMENT
, 3, 10, S_OK
, "", "Number", "Number" },
639 { CH_CHARACTERS
, 3, 10, S_OK
, "1234" },
640 { CH_ENDELEMENT
, 3, 16, S_OK
, "", "Number", "Number" },
641 { CH_CHARACTERS
, 3, 23, S_OK
, "\n" },
642 { CH_CHARACTERS
, 3, 25, S_OK
, "\t" },
643 { CH_STARTELEMENT
, 4, 8, S_OK
, "", "Name", "Name" },
644 { CH_CHARACTERS
, 4, 8, S_OK
, "Captain Ahab" },
645 { CH_ENDELEMENT
, 4, 22, S_OK
, "", "Name", "Name" },
646 { CH_CHARACTERS
, 4, 27, S_OK
, "\n" },
647 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
648 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
652 static struct call_entry content_handler_test2_alternate
[] = {
653 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
654 { CH_STARTDOCUMENT
, 1, 21, S_OK
},
655 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
656 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
657 { CH_CHARACTERS
, 3, 2, S_OK
, "\t" },
658 { CH_STARTELEMENT
, 3, 9, S_OK
, "", "Number", "Number" },
659 { CH_CHARACTERS
, 3, 14, S_OK
, "1234" },
660 { CH_ENDELEMENT
, 3, 22, S_OK
, "", "Number", "Number" },
661 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
662 { CH_CHARACTERS
, 4, 2, S_OK
, "\t" },
663 { CH_STARTELEMENT
, 4, 7, S_OK
, "", "Name", "Name" },
664 { CH_CHARACTERS
, 4, 20, S_OK
, "Captain Ahab" },
665 { CH_ENDELEMENT
, 4, 26, S_OK
, "", "Name", "Name" },
666 { CH_CHARACTERS
, 5, 0, S_OK
, "\n" },
667 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
668 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
672 static struct call_entry content_handler_testerror
[] = {
673 { CH_PUTDOCUMENTLOCATOR
, 0, 0, E_FAIL
},
674 { EH_FATALERROR
, 0, 0, E_FAIL
},
678 static struct call_entry content_handler_testerror_alternate
[] = {
679 { CH_PUTDOCUMENTLOCATOR
, 1, 0, E_FAIL
},
680 { EH_FATALERROR
, 1, 0, E_FAIL
},
684 static struct call_entry content_handler_test_callback_rets
[] = {
685 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_FALSE
},
686 { CH_STARTDOCUMENT
, 0, 0, S_FALSE
},
687 { EH_FATALERROR
, 0, 0, S_FALSE
},
691 static struct call_entry content_handler_test_callback_rets_alt
[] = {
692 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_FALSE
},
693 { CH_STARTDOCUMENT
, 1, 22, S_FALSE
},
694 { CH_STARTELEMENT
, 2, 13, S_FALSE
, "", "BankAccount", "BankAccount" },
695 { CH_CHARACTERS
, 3, 4, S_FALSE
, "\n " },
696 { CH_STARTELEMENT
, 3, 11, S_FALSE
, "", "Number", "Number" },
697 { CH_CHARACTERS
, 3, 16, S_FALSE
, "1234" },
698 { CH_ENDELEMENT
, 3, 24, S_FALSE
, "", "Number", "Number" },
699 { CH_CHARACTERS
, 4, 4, S_FALSE
, "\n " },
700 { CH_STARTELEMENT
, 4, 9, S_FALSE
, "", "Name", "Name" },
701 { CH_CHARACTERS
, 4, 22, S_FALSE
, "Captain Ahab" },
702 { CH_ENDELEMENT
, 4, 28, S_FALSE
, "", "Name", "Name" },
703 { CH_CHARACTERS
, 5, 1, S_FALSE
, "\n" },
704 { CH_ENDELEMENT
, 5, 14, S_FALSE
, "", "BankAccount", "BankAccount" },
705 { CH_ENDDOCUMENT
, 6, 0, S_FALSE
},
709 static struct attribute_entry ch_attributes1
[] = {
710 { "", "", "xmlns:test", "prefix_test" },
711 { "", "", "xmlns", "prefix" },
712 { "prefix_test", "arg1", "test:arg1", "arg1" },
713 { "", "arg2", "arg2", "arg2" },
714 { "prefix_test", "ar3", "test:ar3", "arg3" },
718 static struct attribute_entry ch_attributes2
[] = {
719 { "", "", "xmlns:p", "test" },
723 static struct call_entry content_handler_test_attributes
[] = {
724 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
725 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
726 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
727 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
728 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes1
},
729 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
730 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
731 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
732 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
733 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
734 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
735 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
736 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
737 { CH_ENDDOCUMENT
, 0, 0 },
741 static struct attribute_entry ch_attributes_alt_4
[] = {
742 { "prefix_test", "arg1", "test:arg1", "arg1" },
743 { "", "arg2", "arg2", "arg2" },
744 { "prefix_test", "ar3", "test:ar3", "arg3" },
745 { "", "", "xmlns:test", "prefix_test" },
746 { "", "", "xmlns", "prefix" },
750 static struct call_entry content_handler_test_attributes_alternate_4
[] = {
751 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
752 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
753 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
754 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
755 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_4
},
756 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
757 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
758 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
759 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
760 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
761 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
762 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
763 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
764 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
768 /* 'namespace' feature switched off */
769 static struct attribute_entry ch_attributes_alt_no_ns
[] = {
770 { "", "", "xmlns:test", "prefix_test" },
771 { "", "", "xmlns", "prefix" },
772 { "", "", "test:arg1", "arg1" },
773 { "", "", "arg2", "arg2" },
774 { "", "", "test:ar3", "arg3" },
778 static struct call_entry content_handler_test_attributes_alt_no_ns
[] = {
779 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
780 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
781 { CH_STARTELEMENT
, 2, 95, S_OK
, "", "", "document", ch_attributes_alt_no_ns
},
782 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
783 { CH_STARTELEMENT
, 3, 24, S_OK
, "", "", "node1", ch_attributes2
},
784 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "", "node1" },
785 { CH_ENDELEMENT
, 3, 35, S_OK
, "", "", "document" },
786 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
790 static struct attribute_entry ch_attributes_alt_6
[] = {
791 { "prefix_test", "arg1", "test:arg1", "arg1" },
792 { "", "arg2", "arg2", "arg2" },
793 { "prefix_test", "ar3", "test:ar3", "arg3" },
794 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
795 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
799 static struct attribute_entry ch_attributes2_6
[] = {
800 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
804 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
805 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
806 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
807 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
808 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
809 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
810 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
811 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
812 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
813 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
814 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
815 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
816 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
817 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
818 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
822 /* 'namespaces' is on, 'namespace-prefixes' if off */
823 static struct attribute_entry ch_attributes_no_prefix
[] = {
824 { "prefix_test", "arg1", "test:arg1", "arg1" },
825 { "", "arg2", "arg2", "arg2" },
826 { "prefix_test", "ar3", "test:ar3", "arg3" },
830 static struct call_entry content_handler_test_attributes_alt_no_prefix
[] = {
831 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
832 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
833 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
834 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
835 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
836 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
837 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
838 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", NULL
},
839 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
840 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
841 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
842 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
843 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
844 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
848 static struct call_entry content_handler_test_attributes_no_prefix
[] = {
849 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
850 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
851 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
852 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
853 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
854 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
855 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
856 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", NULL
},
857 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
858 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
859 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
860 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
861 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
862 { CH_ENDDOCUMENT
, 0, 0 },
866 static struct attribute_entry xmlspace_attrs
[] = {
867 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
871 static struct call_entry xmlspaceattr_test
[] = {
872 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
873 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
874 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
875 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
876 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
877 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
881 static struct call_entry xmlspaceattr_test_alternate
[] = {
882 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
883 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
884 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
885 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
886 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
887 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
891 /* attribute value normalization test */
892 static const char attribute_normalize
[] =
893 "<?xml version=\"1.0\" ?>\n"
894 "<a attr1=\" \r \n \tattr_value A \t \r \n\r\n \n\"/>\n";
896 static struct attribute_entry attribute_norm_attrs
[] = {
897 { "", "attr1", "attr1", " attr_value A " },
901 static struct call_entry attribute_norm
[] = {
902 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
903 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
904 { CH_STARTELEMENT
, 6, 4, S_OK
, "", "a", "a", attribute_norm_attrs
},
905 { CH_ENDELEMENT
, 6, 4, S_OK
, "", "a", "a" },
906 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
910 static struct call_entry attribute_norm_alt
[] = {
911 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
912 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
913 { CH_STARTELEMENT
, 8, 3, S_OK
, "", "a", "a", attribute_norm_attrs
},
914 { CH_ENDELEMENT
, 8, 3, S_OK
, "", "a", "a" },
915 { CH_ENDDOCUMENT
, 9, 0, S_OK
},
919 static struct call_entry cdata_test
[] = {
920 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
921 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
922 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
923 { LH_STARTCDATA
, 1, 35, S_OK
},
924 { CH_CHARACTERS
, 1, 35, S_OK
, "Some \n" },
925 { CH_CHARACTERS
, 1, 42, S_OK
, "text\n\n" },
926 { CH_CHARACTERS
, 1, 49, S_OK
, "data\n\n" },
927 { LH_ENDCDATA
, 1, 49, S_OK
},
928 { CH_ENDELEMENT
, 6, 6, S_OK
, "", "a", "a" },
929 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
933 static struct call_entry cdata_test2
[] = {
934 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
935 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
936 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
937 { LH_STARTCDATA
, 1, 35, S_OK
},
938 { CH_CHARACTERS
, 1, 35, S_OK
, "\n\n" },
939 { CH_CHARACTERS
, 1, 38, S_OK
, "Some \n" },
940 { CH_CHARACTERS
, 1, 45, S_OK
, "text\n\n" },
941 { CH_CHARACTERS
, 1, 52, S_OK
, "data\n\n" },
942 { LH_ENDCDATA
, 1, 52, S_OK
},
943 { CH_ENDELEMENT
, 8, 6, S_OK
, "", "a", "a" },
944 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
948 static struct call_entry cdata_test3
[] = {
949 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
950 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
951 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
952 { LH_STARTCDATA
, 1, 35, S_OK
},
953 { CH_CHARACTERS
, 1, 35, S_OK
, "Some text data" },
954 { LH_ENDCDATA
, 1, 35, S_OK
},
955 { CH_ENDELEMENT
, 1, 54, S_OK
, "", "a", "a" },
956 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
960 /* this is what MSXML6 does */
961 static struct call_entry cdata_test_alt
[] = {
962 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
963 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
964 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
965 { LH_STARTCDATA
, 1, 34, S_OK
},
966 { CH_CHARACTERS
, 1, 40, S_OK
, "Some " },
967 { CH_CHARACTERS
, 2, 0, S_OK
, "\n" },
968 { CH_CHARACTERS
, 3, 1, S_OK
, "text\n" },
969 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
970 { CH_CHARACTERS
, 6, 3, S_OK
, "data\n\n" },
971 { LH_ENDCDATA
, 6, 3, S_OK
},
972 { CH_ENDELEMENT
, 6, 7, S_OK
, "", "a", "a" },
973 { CH_ENDDOCUMENT
, 6, 7, S_OK
},
977 static struct call_entry cdata_test2_alt
[] = {
978 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
979 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
980 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
981 { LH_STARTCDATA
, 1, 34, S_OK
},
982 { CH_CHARACTERS
, 2, 1, S_OK
, "\n" },
983 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
984 { CH_CHARACTERS
, 3, 6, S_OK
, "Some " },
985 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
986 { CH_CHARACTERS
, 5, 1, S_OK
, "text\n" },
987 { CH_CHARACTERS
, 6, 0, S_OK
, "\n" },
988 { CH_CHARACTERS
, 8, 3, S_OK
, "data\n\n" },
989 { LH_ENDCDATA
, 8, 3, S_OK
},
990 { CH_ENDELEMENT
, 8, 7, S_OK
, "", "a", "a" },
991 { CH_ENDDOCUMENT
, 8, 7, S_OK
},
995 static struct call_entry cdata_test3_alt
[] = {
996 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
997 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
998 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
999 { LH_STARTCDATA
, 1, 34, S_OK
},
1000 { CH_CHARACTERS
, 1, 51, S_OK
, "Some text data" },
1001 { LH_ENDCDATA
, 1, 51, S_OK
},
1002 { CH_ENDELEMENT
, 1, 55, S_OK
, "", "a", "a" },
1003 { CH_ENDDOCUMENT
, 1, 55, S_OK
},
1007 static const char xmlspace_attr
[] =
1008 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
1009 "<a xml:space=\"preserve\"> Some text data </a>";
1011 static struct call_entry
*expectCall
;
1012 static ISAXLocator
*locator
;
1013 static ISAXXMLReader
*g_reader
;
1016 static void set_expected_seq(struct call_entry
*expected
)
1018 expectCall
= expected
;
1021 /* to be called once on each tested callback return */
1022 static HRESULT
get_expected_ret(void)
1024 HRESULT hr
= expectCall
->ret
;
1025 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
1029 static HRESULT WINAPI
contentHandler_QueryInterface(
1030 ISAXContentHandler
* iface
,
1036 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
1042 return E_NOINTERFACE
;
1048 static ULONG WINAPI
contentHandler_AddRef(
1049 ISAXContentHandler
* iface
)
1054 static ULONG WINAPI
contentHandler_Release(
1055 ISAXContentHandler
* iface
)
1060 static HRESULT WINAPI
contentHandler_putDocumentLocator(
1061 ISAXContentHandler
* iface
,
1062 ISAXLocator
*pLocator
)
1064 struct call_entry call
;
1069 init_call_entry(locator
, &call
);
1070 call
.id
= CH_PUTDOCUMENTLOCATOR
;
1071 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1073 if (msxml_version
>= 6) {
1074 ISAXAttributes
*attr
, *attr1
;
1075 IMXAttributes
*mxattr
;
1077 EXPECT_REF(pLocator
, 1);
1078 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
1079 EXPECT_HR(hr
, S_OK
);
1080 EXPECT_REF(pLocator
, 2);
1081 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
1082 EXPECT_HR(hr
, S_OK
);
1083 EXPECT_REF(pLocator
, 3);
1084 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
1086 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
1087 EXPECT_HR(hr
, E_NOINTERFACE
);
1089 ISAXAttributes_Release(attr
);
1090 ISAXAttributes_Release(attr1
);
1093 return get_expected_ret();
1096 static ISAXAttributes
*test_attr_ptr
;
1097 static HRESULT WINAPI
contentHandler_startDocument(
1098 ISAXContentHandler
* iface
)
1100 struct call_entry call
;
1102 init_call_entry(locator
, &call
);
1103 call
.id
= CH_STARTDOCUMENT
;
1104 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1106 test_attr_ptr
= NULL
;
1108 return get_expected_ret();
1111 static HRESULT WINAPI
contentHandler_endDocument(
1112 ISAXContentHandler
* iface
)
1114 struct call_entry call
;
1116 init_call_entry(locator
, &call
);
1117 call
.id
= CH_ENDDOCUMENT
;
1118 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1120 return get_expected_ret();
1123 static HRESULT WINAPI
contentHandler_startPrefixMapping(
1124 ISAXContentHandler
* iface
,
1125 const WCHAR
*prefix
, int prefix_len
,
1126 const WCHAR
*uri
, int uri_len
)
1128 struct call_entry call
;
1130 init_call_entry(locator
, &call
);
1131 call
.id
= CH_STARTPREFIXMAPPING
;
1132 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
1133 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
1134 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1136 return get_expected_ret();
1139 static HRESULT WINAPI
contentHandler_endPrefixMapping(
1140 ISAXContentHandler
* iface
,
1141 const WCHAR
*prefix
, int len
)
1143 struct call_entry call
;
1145 init_call_entry(locator
, &call
);
1146 call
.id
= CH_ENDPREFIXMAPPING
;
1147 call
.arg1W
= SysAllocStringLen(prefix
, len
);
1148 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1150 return get_expected_ret();
1153 static HRESULT WINAPI
contentHandler_startElement(
1154 ISAXContentHandler
* iface
,
1155 const WCHAR
*uri
, int uri_len
,
1156 const WCHAR
*localname
, int local_len
,
1157 const WCHAR
*qname
, int qname_len
,
1158 ISAXAttributes
*saxattr
)
1160 struct call_entry call
;
1161 IMXAttributes
*mxattr
;
1165 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
1166 EXPECT_HR(hr
, E_NOINTERFACE
);
1168 init_call_entry(locator
, &call
);
1169 call
.id
= CH_STARTELEMENT
;
1170 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1171 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1172 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1175 test_attr_ptr
= saxattr
;
1176 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
1178 /* store actual attributes */
1180 hr
= ISAXAttributes_getLength(saxattr
, &len
);
1181 EXPECT_HR(hr
, S_OK
);
1188 struct attribute_entry
*attr
;
1189 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
1192 hr
= ISAXXMLReader_getFeature(g_reader
, _bstr_("http://xml.org/sax/features/namespaces"), &v
);
1193 EXPECT_HR(hr
, S_OK
);
1195 for (i
= 0; i
< len
; i
++)
1200 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
1201 &localname
, &local_len
, &qname
, &qname_len
);
1202 EXPECT_HR(hr
, S_OK
);
1204 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
1205 EXPECT_HR(hr
, S_OK
);
1207 /* if 'namespaces' switched off uri and local name contains garbage */
1208 if (v
== VARIANT_FALSE
&& msxml_version
> 0)
1210 attr
[i
].uriW
= SysAllocStringLen(NULL
, 0);
1211 attr
[i
].localW
= SysAllocStringLen(NULL
, 0);
1215 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
1216 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
1219 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
1220 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
1223 call
.attributes
= attr
;
1224 call
.attr_count
= len
;
1227 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1229 return get_expected_ret();
1232 static HRESULT WINAPI
contentHandler_endElement(
1233 ISAXContentHandler
* iface
,
1234 const WCHAR
*uri
, int uri_len
,
1235 const WCHAR
*localname
, int local_len
,
1236 const WCHAR
*qname
, int qname_len
)
1238 struct call_entry call
;
1240 init_call_entry(locator
, &call
);
1241 call
.id
= CH_ENDELEMENT
;
1242 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1243 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1244 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1245 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1247 return get_expected_ret();
1250 static HRESULT WINAPI
contentHandler_characters(
1251 ISAXContentHandler
* iface
,
1255 struct call_entry call
;
1257 init_call_entry(locator
, &call
);
1258 call
.id
= CH_CHARACTERS
;
1259 call
.arg1W
= SysAllocStringLen(chars
, len
);
1260 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1262 return get_expected_ret();
1265 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1266 ISAXContentHandler
* iface
,
1267 const WCHAR
*chars
, int len
)
1269 struct call_entry call
;
1271 init_call_entry(locator
, &call
);
1272 call
.id
= CH_IGNORABLEWHITESPACE
;
1273 call
.arg1W
= SysAllocStringLen(chars
, len
);
1274 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1276 return get_expected_ret();
1279 static HRESULT WINAPI
contentHandler_processingInstruction(
1280 ISAXContentHandler
* iface
,
1281 const WCHAR
*target
, int target_len
,
1282 const WCHAR
*data
, int data_len
)
1284 struct call_entry call
;
1286 init_call_entry(locator
, &call
);
1287 call
.id
= CH_PROCESSINGINSTRUCTION
;
1288 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1289 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1290 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1292 return get_expected_ret();
1295 static HRESULT WINAPI
contentHandler_skippedEntity(
1296 ISAXContentHandler
* iface
,
1297 const WCHAR
*name
, int len
)
1299 struct call_entry call
;
1301 init_call_entry(locator
, &call
);
1302 call
.id
= CH_SKIPPEDENTITY
;
1303 call
.arg1W
= SysAllocStringLen(name
, len
);
1304 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1306 return get_expected_ret();
1309 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1311 contentHandler_QueryInterface
,
1312 contentHandler_AddRef
,
1313 contentHandler_Release
,
1314 contentHandler_putDocumentLocator
,
1315 contentHandler_startDocument
,
1316 contentHandler_endDocument
,
1317 contentHandler_startPrefixMapping
,
1318 contentHandler_endPrefixMapping
,
1319 contentHandler_startElement
,
1320 contentHandler_endElement
,
1321 contentHandler_characters
,
1322 contentHandler_ignorableWhitespace
,
1323 contentHandler_processingInstruction
,
1324 contentHandler_skippedEntity
1327 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1329 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1330 ISAXErrorHandler
* iface
,
1336 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1342 return E_NOINTERFACE
;
1348 static ULONG WINAPI
isaxerrorHandler_AddRef(
1349 ISAXErrorHandler
* iface
)
1354 static ULONG WINAPI
isaxerrorHandler_Release(
1355 ISAXErrorHandler
* iface
)
1360 static HRESULT WINAPI
isaxerrorHandler_error(
1361 ISAXErrorHandler
* iface
,
1362 ISAXLocator
*pLocator
,
1363 const WCHAR
*pErrorMessage
,
1364 HRESULT hrErrorCode
)
1366 ok(0, "unexpected call\n");
1370 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1371 ISAXErrorHandler
* iface
,
1372 ISAXLocator
*pLocator
,
1373 const WCHAR
*message
,
1376 struct call_entry call
;
1378 init_call_entry(locator
, &call
);
1379 call
.id
= EH_FATALERROR
;
1382 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1388 static HRESULT WINAPI
isaxerrorHandler_ignorableWarning(
1389 ISAXErrorHandler
* iface
,
1390 ISAXLocator
*pLocator
,
1391 const WCHAR
*pErrorMessage
,
1392 HRESULT hrErrorCode
)
1394 ok(0, "unexpected call\n");
1398 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1400 isaxerrorHandler_QueryInterface
,
1401 isaxerrorHandler_AddRef
,
1402 isaxerrorHandler_Release
,
1403 isaxerrorHandler_error
,
1404 isaxerrorHandler_fatalError
,
1405 isaxerrorHandler_ignorableWarning
1408 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1410 static HRESULT WINAPI
isaxattributes_QueryInterface(
1411 ISAXAttributes
* iface
,
1417 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1423 return E_NOINTERFACE
;
1429 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1434 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1439 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1445 static HRESULT WINAPI
isaxattributes_getURI(
1446 ISAXAttributes
* iface
,
1451 ok(0, "unexpected call\n");
1455 static HRESULT WINAPI
isaxattributes_getLocalName(
1456 ISAXAttributes
* iface
,
1458 const WCHAR
**pLocalName
,
1459 int *pLocalNameLength
)
1461 ok(0, "unexpected call\n");
1465 static HRESULT WINAPI
isaxattributes_getQName(
1466 ISAXAttributes
* iface
,
1468 const WCHAR
**QName
,
1471 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1472 {'a','t','t','r','2','j','u','n','k',0},
1473 {'a','t','t','r','3',0}};
1474 static const int attrqnamelen
[] = {7, 5, 5};
1476 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1478 *QName
= attrqnamesW
[index
];
1479 *QNameLength
= attrqnamelen
[index
];
1484 static HRESULT WINAPI
isaxattributes_getName(
1485 ISAXAttributes
* iface
,
1489 const WCHAR
** pLocalName
,
1490 int * pLocalNameSize
,
1491 const WCHAR
** pQName
,
1494 ok(0, "unexpected call\n");
1498 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1499 ISAXAttributes
* iface
,
1502 const WCHAR
* pLocalName
,
1503 int cocalNameLength
,
1506 ok(0, "unexpected call\n");
1510 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1511 ISAXAttributes
* iface
,
1512 const WCHAR
* pQName
,
1516 ok(0, "unexpected call\n");
1520 static HRESULT WINAPI
isaxattributes_getType(
1521 ISAXAttributes
* iface
,
1523 const WCHAR
** pType
,
1526 ok(0, "unexpected call\n");
1530 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1531 ISAXAttributes
* iface
,
1534 const WCHAR
* pLocalName
,
1536 const WCHAR
** pType
,
1539 ok(0, "unexpected call\n");
1543 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1544 ISAXAttributes
* iface
,
1545 const WCHAR
* pQName
,
1547 const WCHAR
** pType
,
1550 ok(0, "unexpected call\n");
1554 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1555 const WCHAR
**value
, int *nValue
)
1557 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1558 {'a','2','j','u','n','k',0},
1559 {'<','&','"','>',0}};
1560 static const int attrvalueslen
[] = {2, 2, 4};
1562 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1564 *value
= attrvaluesW
[index
];
1565 *nValue
= attrvalueslen
[index
];
1570 static HRESULT WINAPI
isaxattributes_getValueFromName(
1571 ISAXAttributes
* iface
,
1574 const WCHAR
* pLocalName
,
1576 const WCHAR
** pValue
,
1579 ok(0, "unexpected call\n");
1583 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1584 ISAXAttributes
* iface
,
1585 const WCHAR
* pQName
,
1587 const WCHAR
** pValue
,
1590 ok(0, "unexpected call\n");
1594 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1596 isaxattributes_QueryInterface
,
1597 isaxattributes_AddRef
,
1598 isaxattributes_Release
,
1599 isaxattributes_getLength
,
1600 isaxattributes_getURI
,
1601 isaxattributes_getLocalName
,
1602 isaxattributes_getQName
,
1603 isaxattributes_getName
,
1604 isaxattributes_getIndexFromName
,
1605 isaxattributes_getIndexFromQName
,
1606 isaxattributes_getType
,
1607 isaxattributes_getTypeFromName
,
1608 isaxattributes_getTypeFromQName
,
1609 isaxattributes_getValue
,
1610 isaxattributes_getValueFromName
,
1611 isaxattributes_getValueFromQName
1614 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1616 struct saxlexicalhandler
1618 ISAXLexicalHandler ISAXLexicalHandler_iface
;
1621 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1624 static inline struct saxlexicalhandler
*impl_from_ISAXLexicalHandler( ISAXLexicalHandler
*iface
)
1626 return CONTAINING_RECORD(iface
, struct saxlexicalhandler
, ISAXLexicalHandler_iface
);
1629 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **out
)
1631 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1635 if (IsEqualGUID(riid
, &IID_IUnknown
))
1638 ok(0, "got unexpected IID_IUnknown query\n");
1640 else if (IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1642 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1647 ISAXLexicalHandler_AddRef(iface
);
1649 return E_NOINTERFACE
;
1654 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1656 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1657 return InterlockedIncrement(&handler
->ref
);
1660 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1662 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1663 return InterlockedDecrement(&handler
->ref
);
1666 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1667 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1668 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1670 ok(0, "call not expected\n");
1674 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1676 ok(0, "call not expected\n");
1680 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1681 const WCHAR
* pName
, int nName
)
1683 ok(0, "call not expected\n");
1687 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1688 const WCHAR
* pName
, int nName
)
1690 ok(0, "call not expected\n");
1694 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1696 struct call_entry call
;
1698 init_call_entry(locator
, &call
);
1699 call
.id
= LH_STARTCDATA
;
1700 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1702 return get_expected_ret();
1705 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1707 struct call_entry call
;
1709 init_call_entry(locator
, &call
);
1710 call
.id
= LH_ENDCDATA
;
1711 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1713 return get_expected_ret();
1716 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1717 const WCHAR
* pChars
, int nChars
)
1719 ok(0, "call not expected\n");
1723 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1725 isaxlexical_QueryInterface
,
1727 isaxlexical_Release
,
1728 isaxlexical_startDTD
,
1730 isaxlexical_startEntity
,
1731 isaxlexical_endEntity
,
1732 isaxlexical_startCDATA
,
1733 isaxlexical_endCDATA
,
1737 static void init_saxlexicalhandler(struct saxlexicalhandler
*handler
, HRESULT hr
)
1739 handler
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1741 handler
->qi_hr
= hr
;
1744 struct saxdeclhandler
1746 ISAXDeclHandler ISAXDeclHandler_iface
;
1749 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1752 static inline struct saxdeclhandler
*impl_from_ISAXDeclHandler( ISAXDeclHandler
*iface
)
1754 return CONTAINING_RECORD(iface
, struct saxdeclhandler
, ISAXDeclHandler_iface
);
1757 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **out
)
1759 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1763 if (IsEqualGUID(riid
, &IID_IUnknown
))
1766 ok(0, "got unexpected IID_IUnknown query\n");
1768 else if (IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1770 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1775 ISAXDeclHandler_AddRef(iface
);
1777 return E_NOINTERFACE
;
1782 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1784 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1785 return InterlockedIncrement(&handler
->ref
);
1788 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1790 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1791 return InterlockedDecrement(&handler
->ref
);
1794 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1795 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1797 ok(0, "call not expected\n");
1801 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1802 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1803 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1804 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1806 ok(0, "call not expected\n");
1810 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1811 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1813 ok(0, "call not expected\n");
1817 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1818 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1819 const WCHAR
* pSystemId
, int nSystemId
)
1821 ok(0, "call not expected\n");
1825 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1827 isaxdecl_QueryInterface
,
1830 isaxdecl_elementDecl
,
1831 isaxdecl_attributeDecl
,
1832 isaxdecl_internalEntityDecl
,
1833 isaxdecl_externalEntityDecl
1836 static void init_saxdeclhandler(struct saxdeclhandler
*handler
, HRESULT hr
)
1838 handler
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1840 handler
->qi_hr
= hr
;
1843 typedef struct mxwriter_write_test_t
{
1849 } mxwriter_write_test
;
1851 typedef struct mxwriter_stream_test_t
{
1853 const char *encoding
;
1854 mxwriter_write_test expected_writes
[4];
1855 } mxwriter_stream_test
;
1857 static const mxwriter_write_test
*current_write_test
;
1858 static DWORD current_stream_test_index
;
1860 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1864 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1867 return E_NOINTERFACE
;
1872 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1877 static ULONG WINAPI
istream_Release(IStream
*iface
)
1882 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1884 ok(0, "unexpected call\n");
1888 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1892 ok(pv
!= NULL
, "pv == NULL\n");
1894 if(current_write_test
->last
) {
1895 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
1899 fail
= current_write_test
->fail_write
;
1901 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
1902 current_write_test
->cb
, cb
, current_stream_test_index
);
1905 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
1907 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
1909 ++current_write_test
;
1914 return fail
? E_FAIL
: S_OK
;
1917 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1918 ULARGE_INTEGER
*plibNewPosition
)
1920 ok(0, "unexpected call\n");
1924 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1926 ok(0, "unexpected call\n");
1930 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1931 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1933 ok(0, "unexpected call\n");
1937 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1939 ok(0, "unexpected call\n");
1943 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1945 ok(0, "unexpected call\n");
1949 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1950 ULARGE_INTEGER cb
, DWORD dwLockType
)
1952 ok(0, "unexpected call\n");
1956 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1957 ULARGE_INTEGER cb
, DWORD dwLockType
)
1959 ok(0, "unexpected call\n");
1963 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1965 ok(0, "unexpected call\n");
1969 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1971 ok(0, "unexpected call\n");
1975 static const IStreamVtbl StreamVtbl
= {
1976 istream_QueryInterface
,
1987 istream_UnlockRegion
,
1992 static IStream mxstream
= { &StreamVtbl
};
1994 static struct msxmlsupported_data_t reader_support_data
[] =
1996 { &CLSID_SAXXMLReader
, "SAXReader" },
1997 { &CLSID_SAXXMLReader30
, "SAXReader30" },
1998 { &CLSID_SAXXMLReader40
, "SAXReader40" },
1999 { &CLSID_SAXXMLReader60
, "SAXReader60" },
2003 static struct saxlexicalhandler lexicalhandler
;
2004 static struct saxdeclhandler declhandler
;
2006 static IStream
*create_test_stream(const char *data
, int len
)
2008 ULARGE_INTEGER size
;
2013 if (len
== -1) len
= strlen(data
);
2014 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2015 size
.QuadPart
= len
;
2016 IStream_SetSize(stream
, size
);
2017 IStream_Write(stream
, data
, len
, &written
);
2019 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2024 static void test_saxreader(void)
2026 const struct msxmlsupported_data_t
*table
= reader_support_data
;
2028 ISAXXMLReader
*reader
= NULL
;
2030 ISAXContentHandler
*content
;
2031 ISAXErrorHandler
*lpErrorHandler
;
2033 SAFEARRAYBOUND SADim
[1];
2038 static const CHAR testXmlA
[] = "test.xml";
2039 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2040 IXMLDOMDocument
*doc
;
2043 while (table
->clsid
)
2045 struct call_entry
*test_seq
;
2046 ISAXEntityResolver
*resolver
;
2049 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
2055 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2056 EXPECT_HR(hr
, S_OK
);
2059 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2061 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2066 /* crashes on old versions */
2067 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
2068 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2070 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
2071 EXPECT_HR(hr
, E_POINTER
);
2073 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
2074 EXPECT_HR(hr
, E_POINTER
);
2077 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2078 EXPECT_HR(hr
, S_OK
);
2079 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
2081 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
2082 EXPECT_HR(hr
, S_OK
);
2083 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
2085 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
2086 EXPECT_HR(hr
, S_OK
);
2088 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
2089 EXPECT_HR(hr
, S_OK
);
2091 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
2092 EXPECT_HR(hr
, S_OK
);
2094 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2095 EXPECT_HR(hr
, S_OK
);
2096 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
2098 V_VT(&var
) = VT_BSTR
;
2099 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
2101 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2102 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2103 test_seq
= content_handler_test1_alternate
;
2105 test_seq
= content_handler_test1
;
2106 set_expected_seq(test_seq
);
2107 hr
= ISAXXMLReader_parse(reader
, var
);
2108 EXPECT_HR(hr
, S_OK
);
2109 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
2113 SADim
[0].lLbound
= 0;
2114 SADim
[0].cElements
= sizeof(testXML
)-1;
2115 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
2116 SafeArrayAccessData(sa
, (void**)&ptr
);
2117 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
2118 SafeArrayUnaccessData(sa
);
2119 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
2122 set_expected_seq(test_seq
);
2123 hr
= ISAXXMLReader_parse(reader
, var
);
2124 EXPECT_HR(hr
, S_OK
);
2125 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from safe array", FALSE
);
2127 SafeArrayDestroy(sa
);
2129 stream
= create_test_stream(testXML
, -1);
2130 V_VT(&var
) = VT_UNKNOWN
;
2131 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2133 set_expected_seq(test_seq
);
2134 hr
= ISAXXMLReader_parse(reader
, var
);
2135 EXPECT_HR(hr
, S_OK
);
2136 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
2138 IStream_Release(stream
);
2140 stream
= create_test_stream(test_attributes
, -1);
2141 V_VT(&var
) = VT_UNKNOWN
;
2142 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2144 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2145 test_seq
= content_handler_test_attributes_alternate_4
;
2146 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2147 test_seq
= content_handler_test_attributes_alternate_6
;
2149 test_seq
= content_handler_test_attributes
;
2151 set_expected_seq(test_seq
);
2152 hr
= ISAXXMLReader_parse(reader
, var
);
2153 EXPECT_HR(hr
, S_OK
);
2155 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2156 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2157 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2159 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2161 IStream_Release(stream
);
2163 V_VT(&var
) = VT_BSTR
;
2164 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
2166 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2167 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2168 test_seq
= content_handler_test2_alternate
;
2170 test_seq
= content_handler_test2
;
2172 set_expected_seq(test_seq
);
2173 hr
= ISAXXMLReader_parse(reader
, var
);
2174 EXPECT_HR(hr
, S_OK
);
2175 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
2180 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2181 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2182 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
2185 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2186 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2187 test_seq
= content_handler_test1_alternate
;
2189 test_seq
= content_handler_test1
;
2190 set_expected_seq(test_seq
);
2191 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2192 EXPECT_HR(hr
, S_OK
);
2193 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
2196 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2197 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2198 test_seq
= content_handler_testerror_alternate
;
2200 test_seq
= content_handler_testerror
;
2201 set_expected_seq(test_seq
);
2202 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2203 EXPECT_HR(hr
, E_FAIL
);
2204 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
2206 /* callback ret values */
2207 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2208 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2210 test_seq
= content_handler_test_callback_rets_alt
;
2211 set_expected_seq(test_seq
);
2212 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2213 EXPECT_HR(hr
, S_OK
);
2217 test_seq
= content_handler_test_callback_rets
;
2218 set_expected_seq(test_seq
);
2219 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2220 EXPECT_HR(hr
, S_FALSE
);
2222 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
2224 DeleteFileA(testXmlA
);
2226 /* parse from IXMLDOMDocument */
2227 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
2228 &IID_IXMLDOMDocument
, (void**)&doc
);
2229 EXPECT_HR(hr
, S_OK
);
2231 str
= SysAllocString(szSimpleXML
);
2232 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
2233 EXPECT_HR(hr
, S_OK
);
2236 V_VT(&var
) = VT_UNKNOWN
;
2237 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
2239 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2240 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2241 test_seq
= content_handler_test2_alternate
;
2243 test_seq
= content_handler_test2
;
2245 set_expected_seq(test_seq
);
2246 hr
= ISAXXMLReader_parse(reader
, var
);
2247 EXPECT_HR(hr
, S_OK
);
2248 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
2249 IXMLDOMDocument_Release(doc
);
2251 /* xml:space test */
2252 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2253 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2255 test_seq
= xmlspaceattr_test_alternate
;
2258 test_seq
= xmlspaceattr_test
;
2260 set_expected_seq(test_seq
);
2261 V_VT(&var
) = VT_BSTR
;
2262 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
2263 hr
= ISAXXMLReader_parse(reader
, var
);
2264 EXPECT_HR(hr
, S_OK
);
2266 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2267 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2269 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
2272 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
2274 /* switch off 'namespaces' feature */
2275 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE
);
2276 EXPECT_HR(hr
, S_OK
);
2278 stream
= create_test_stream(test_attributes
, -1);
2279 V_VT(&var
) = VT_UNKNOWN
;
2280 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2282 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2283 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2285 test_seq
= content_handler_test_attributes_alt_no_ns
;
2288 test_seq
= content_handler_test_attributes
;
2290 set_expected_seq(test_seq
);
2291 hr
= ISAXXMLReader_parse(reader
, var
);
2292 EXPECT_HR(hr
, S_OK
);
2293 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2294 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_TRUE
);
2295 EXPECT_HR(hr
, S_OK
);
2297 /* switch off 'namespace-prefixes' feature */
2298 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_FALSE
);
2299 EXPECT_HR(hr
, S_OK
);
2301 stream
= create_test_stream(test_attributes
, -1);
2302 V_VT(&var
) = VT_UNKNOWN
;
2303 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2305 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2306 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2308 test_seq
= content_handler_test_attributes_alt_no_prefix
;
2311 test_seq
= content_handler_test_attributes_no_prefix
;
2313 set_expected_seq(test_seq
);
2314 hr
= ISAXXMLReader_parse(reader
, var
);
2315 EXPECT_HR(hr
, S_OK
);
2316 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2318 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_TRUE
);
2319 EXPECT_HR(hr
, S_OK
);
2321 /* attribute normalization */
2322 stream
= create_test_stream(attribute_normalize
, -1);
2323 V_VT(&var
) = VT_UNKNOWN
;
2324 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2326 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2327 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2329 test_seq
= attribute_norm_alt
;
2332 test_seq
= attribute_norm
;
2334 set_expected_seq(test_seq
);
2335 hr
= ISAXXMLReader_parse(reader
, var
);
2336 EXPECT_HR(hr
, S_OK
);
2337 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "attribute value normalization", TRUE
);
2339 resolver
= (void*)0xdeadbeef;
2340 hr
= ISAXXMLReader_getEntityResolver(reader
, &resolver
);
2341 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2342 ok(resolver
== NULL
, "got %p\n", resolver
);
2344 hr
= ISAXXMLReader_putEntityResolver(reader
, NULL
);
2345 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "got 0x%08x\n", hr
);
2347 /* CDATA sections */
2348 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2350 V_VT(&var
) = VT_UNKNOWN
;
2351 V_UNKNOWN(&var
) = (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
;
2352 hr
= ISAXXMLReader_putProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), var
);
2353 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2355 stream
= create_test_stream(test_cdata_xml
, -1);
2356 V_VT(&var
) = VT_UNKNOWN
;
2357 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2359 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2360 test_seq
= cdata_test_alt
;
2362 test_seq
= cdata_test
;
2364 set_expected_seq(test_seq
);
2365 hr
= ISAXXMLReader_parse(reader
, var
);
2366 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2367 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "cdata test", TRUE
);
2369 /* 2. CDATA sections */
2370 stream
= create_test_stream(test2_cdata_xml
, -1);
2371 V_VT(&var
) = VT_UNKNOWN
;
2372 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2374 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2375 test_seq
= cdata_test2_alt
;
2377 test_seq
= cdata_test2
;
2379 set_expected_seq(test_seq
);
2380 hr
= ISAXXMLReader_parse(reader
, var
);
2381 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2382 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "cdata test 2", TRUE
);
2384 IStream_Release(stream
);
2386 /* 3. CDATA sections */
2387 stream
= create_test_stream(test3_cdata_xml
, -1);
2388 V_VT(&var
) = VT_UNKNOWN
;
2389 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2391 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2392 test_seq
= cdata_test3_alt
;
2394 test_seq
= cdata_test3
;
2396 set_expected_seq(test_seq
);
2397 hr
= ISAXXMLReader_parse(reader
, var
);
2398 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2399 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "cdata test 3", TRUE
);
2401 IStream_Release(stream
);
2403 ISAXXMLReader_Release(reader
);
2410 struct saxreader_props_test_t
2412 const char *prop_name
;
2416 static const struct saxreader_props_test_t props_test_data
[] = {
2417 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
},
2418 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&declhandler
.ISAXDeclHandler_iface
},
2422 static void test_saxreader_properties(void)
2424 const struct saxreader_props_test_t
*ptr
= props_test_data
;
2425 ISAXXMLReader
*reader
;
2429 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2430 &IID_ISAXXMLReader
, (void**)&reader
);
2431 EXPECT_HR(hr
, S_OK
);
2433 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
2434 EXPECT_HR(hr
, E_POINTER
);
2436 while (ptr
->prop_name
)
2440 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2441 init_saxdeclhandler(&declhandler
, S_OK
);
2443 V_VT(&v
) = VT_EMPTY
;
2444 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2445 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2446 EXPECT_HR(hr
, S_OK
);
2447 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2448 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2450 V_VT(&v
) = VT_UNKNOWN
;
2451 V_UNKNOWN(&v
) = ptr
->iface
;
2452 ref
= get_refcount(ptr
->iface
);
2453 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2454 EXPECT_HR(hr
, S_OK
);
2455 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2457 V_VT(&v
) = VT_EMPTY
;
2458 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2460 ref
= get_refcount(ptr
->iface
);
2461 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2462 EXPECT_HR(hr
, S_OK
);
2463 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2464 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2465 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2468 V_VT(&v
) = VT_EMPTY
;
2469 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2470 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2471 EXPECT_HR(hr
, S_OK
);
2473 V_VT(&v
) = VT_EMPTY
;
2474 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2475 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2476 EXPECT_HR(hr
, S_OK
);
2477 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2478 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2480 V_VT(&v
) = VT_UNKNOWN
;
2481 V_UNKNOWN(&v
) = ptr
->iface
;
2482 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2483 EXPECT_HR(hr
, S_OK
);
2485 /* only VT_EMPTY seems to be valid to reset property */
2487 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2488 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2489 EXPECT_HR(hr
, E_INVALIDARG
);
2491 V_VT(&v
) = VT_EMPTY
;
2492 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2493 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2494 EXPECT_HR(hr
, S_OK
);
2495 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2496 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2499 V_VT(&v
) = VT_UNKNOWN
;
2500 V_UNKNOWN(&v
) = NULL
;
2501 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2502 EXPECT_HR(hr
, S_OK
);
2504 V_VT(&v
) = VT_EMPTY
;
2505 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2506 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2507 EXPECT_HR(hr
, S_OK
);
2508 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2509 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2511 /* block QueryInterface on handler riid */
2512 V_VT(&v
) = VT_UNKNOWN
;
2513 V_UNKNOWN(&v
) = ptr
->iface
;
2514 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2515 EXPECT_HR(hr
, S_OK
);
2517 init_saxlexicalhandler(&lexicalhandler
, E_NOINTERFACE
);
2518 init_saxdeclhandler(&declhandler
, E_NOINTERFACE
);
2520 V_VT(&v
) = VT_UNKNOWN
;
2521 V_UNKNOWN(&v
) = ptr
->iface
;
2522 EXPECT_REF(ptr
->iface
, 1);
2523 ref
= get_refcount(ptr
->iface
);
2524 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2525 EXPECT_HR(hr
, E_NOINTERFACE
);
2526 EXPECT_REF(ptr
->iface
, 1);
2528 V_VT(&v
) = VT_EMPTY
;
2529 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2530 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2531 EXPECT_HR(hr
, S_OK
);
2532 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2533 ok(V_UNKNOWN(&v
) != NULL
, "got %p\n", V_UNKNOWN(&v
));
2539 ISAXXMLReader_Release(reader
);
2541 if (!is_clsid_supported(&CLSID_SAXXMLReader40
, reader_support_data
))
2544 hr
= CoCreateInstance(&CLSID_SAXXMLReader40
, NULL
, CLSCTX_INPROC_SERVER
,
2545 &IID_ISAXXMLReader
, (void**)&reader
);
2546 EXPECT_HR(hr
, S_OK
);
2548 /* xmldecl-version property */
2549 V_VT(&v
) = VT_EMPTY
;
2550 V_BSTR(&v
) = (void*)0xdeadbeef;
2551 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2552 EXPECT_HR(hr
, S_OK
);
2553 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2554 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2556 /* stream without declaration */
2558 V_BSTR(&v
) = _bstr_("<element></element>");
2559 hr
= ISAXXMLReader_parse(reader
, v
);
2560 EXPECT_HR(hr
, S_OK
);
2562 V_VT(&v
) = VT_EMPTY
;
2563 V_BSTR(&v
) = (void*)0xdeadbeef;
2564 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2565 EXPECT_HR(hr
, S_OK
);
2566 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2567 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2569 /* stream with declaration */
2571 V_BSTR(&v
) = _bstr_("<?xml version=\"1.0\"?><element></element>");
2572 hr
= ISAXXMLReader_parse(reader
, v
);
2573 EXPECT_HR(hr
, S_OK
);
2575 V_VT(&v
) = VT_EMPTY
;
2576 V_BSTR(&v
) = (void*)0xdeadbeef;
2577 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2578 EXPECT_HR(hr
, S_OK
);
2579 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2580 ok(!lstrcmpW(V_BSTR(&v
), _bstr_("1.0")), "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2583 ISAXXMLReader_Release(reader
);
2587 struct feature_ns_entry_t
{
2591 VARIANT_BOOL value2
; /* feature value after feature set to 0xc */
2594 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2595 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
, VARIANT_FALSE
},
2596 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
, VARIANT_FALSE
},
2597 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
, VARIANT_TRUE
},
2598 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
, VARIANT_TRUE
},
2602 static const char *feature_names
[] = {
2603 "http://xml.org/sax/features/namespaces",
2604 "http://xml.org/sax/features/namespace-prefixes",
2608 static void test_saxreader_features(void)
2610 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2611 ISAXXMLReader
*reader
;
2619 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2622 win_skip("can't create %s instance\n", entry
->clsid
);
2627 name
= feature_names
;
2631 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2632 EXPECT_HR(hr
, S_OK
);
2633 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2636 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), value
);
2637 EXPECT_HR(hr
, S_OK
);
2640 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2641 EXPECT_HR(hr
, S_OK
);
2642 ok(entry
->value2
== value
, "%s: got wrong value %x, expected %x\n", entry
->clsid
, value
, entry
->value2
);
2644 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_FALSE
);
2645 EXPECT_HR(hr
, S_OK
);
2647 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2648 EXPECT_HR(hr
, S_OK
);
2649 ok(value
== VARIANT_FALSE
, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry
->clsid
, value
);
2651 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_TRUE
);
2652 EXPECT_HR(hr
, S_OK
);
2654 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2655 EXPECT_HR(hr
, S_OK
);
2656 ok(value
== VARIANT_TRUE
, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry
->clsid
, value
);
2661 ISAXXMLReader_Release(reader
);
2667 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2668 static const CHAR UTF8BOMTest
[] =
2669 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2672 struct enc_test_entry_t
{
2680 static const struct enc_test_entry_t encoding_test_data
[] = {
2681 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, 1 },
2682 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, 1 },
2683 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, 0 },
2684 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, 0 },
2688 static void test_saxreader_encoding(void)
2690 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2691 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2692 static const CHAR testXmlA
[] = "test.xml";
2696 ISAXXMLReader
*reader
;
2702 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2705 win_skip("can't create %s instance\n", entry
->clsid
);
2710 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2711 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2712 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2715 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2717 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2719 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2721 DeleteFileA(testXmlA
);
2723 /* try BSTR input with no BOM or '<?xml' instruction */
2724 V_VT(&input
) = VT_BSTR
;
2725 V_BSTR(&input
) = _bstr_("<element></element>");
2726 hr
= ISAXXMLReader_parse(reader
, input
);
2727 EXPECT_HR(hr
, S_OK
);
2729 ISAXXMLReader_Release(reader
);
2736 static void test_mxwriter_handlers(void)
2738 ISAXContentHandler
*handler
;
2739 IMXWriter
*writer
, *writer2
;
2740 ISAXDeclHandler
*decl
;
2741 ISAXLexicalHandler
*lh
;
2744 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2745 &IID_IMXWriter
, (void**)&writer
);
2746 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2748 EXPECT_REF(writer
, 1);
2750 /* ISAXContentHandler */
2751 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&handler
);
2752 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2753 EXPECT_REF(writer
, 2);
2754 EXPECT_REF(handler
, 2);
2756 hr
= ISAXContentHandler_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2757 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2758 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2759 EXPECT_REF(writer
, 3);
2760 EXPECT_REF(writer2
, 3);
2761 IMXWriter_Release(writer2
);
2762 ISAXContentHandler_Release(handler
);
2764 /* ISAXLexicalHandler */
2765 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lh
);
2766 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2767 EXPECT_REF(writer
, 2);
2770 hr
= ISAXLexicalHandler_QueryInterface(lh
, &IID_IMXWriter
, (void**)&writer2
);
2771 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2772 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2773 EXPECT_REF(writer
, 3);
2774 EXPECT_REF(writer2
, 3);
2775 IMXWriter_Release(writer2
);
2776 ISAXLexicalHandler_Release(lh
);
2778 /* ISAXDeclHandler */
2779 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
2780 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2781 EXPECT_REF(writer
, 2);
2784 hr
= ISAXDeclHandler_QueryInterface(decl
, &IID_IMXWriter
, (void**)&writer2
);
2785 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2786 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2787 EXPECT_REF(writer
, 3);
2788 EXPECT_REF(writer2
, 3);
2789 IMXWriter_Release(writer2
);
2790 ISAXDeclHandler_Release(decl
);
2792 IMXWriter_Release(writer
);
2796 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2798 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2799 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2800 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2801 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2805 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2807 { &CLSID_SAXAttributes
, "SAXAttributes" },
2808 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2809 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2810 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2814 struct mxwriter_props_t
2818 VARIANT_BOOL disable_escape
;
2819 VARIANT_BOOL indent
;
2820 VARIANT_BOOL omitdecl
;
2821 VARIANT_BOOL standalone
;
2822 const char *encoding
;
2825 static const struct mxwriter_props_t mxwriter_default_props
[] =
2827 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2828 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2829 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2830 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2834 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2838 while (table
->clsid
)
2845 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2852 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2853 &IID_IMXWriter
, (void**)&writer
);
2854 EXPECT_HR(hr
, S_OK
);
2857 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
2858 EXPECT_HR(hr
, S_OK
);
2859 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
2861 b
= !table
->disable_escape
;
2862 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
2863 EXPECT_HR(hr
, S_OK
);
2864 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
2865 table
->disable_escape
);
2868 hr
= IMXWriter_get_indent(writer
, &b
);
2869 EXPECT_HR(hr
, S_OK
);
2870 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
2872 b
= !table
->omitdecl
;
2873 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
2874 EXPECT_HR(hr
, S_OK
);
2875 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
2877 b
= !table
->standalone
;
2878 hr
= IMXWriter_get_standalone(writer
, &b
);
2879 EXPECT_HR(hr
, S_OK
);
2880 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
2882 hr
= IMXWriter_get_encoding(writer
, &encoding
);
2883 EXPECT_HR(hr
, S_OK
);
2884 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
2885 i
, wine_dbgstr_w(encoding
), table
->encoding
);
2886 SysFreeString(encoding
);
2888 IMXWriter_Release(writer
);
2895 static void test_mxwriter_properties(void)
2897 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
2898 static const WCHAR emptyW
[] = {0};
2899 static const WCHAR testW
[] = {'t','e','s','t',0};
2900 ISAXContentHandler
*content
;
2907 test_mxwriter_default_properties(mxwriter_default_props
);
2909 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2910 &IID_IMXWriter
, (void**)&writer
);
2911 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2913 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
2914 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2916 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
2917 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2919 hr
= IMXWriter_get_indent(writer
, NULL
);
2920 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2922 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
2923 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2925 hr
= IMXWriter_get_standalone(writer
, NULL
);
2926 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2929 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
2930 ok(hr
== S_OK
, "got %08x\n", hr
);
2933 hr
= IMXWriter_get_standalone(writer
, &b
);
2934 ok(hr
== S_OK
, "got %08x\n", hr
);
2935 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
2937 hr
= IMXWriter_get_encoding(writer
, NULL
);
2938 EXPECT_HR(hr
, E_POINTER
);
2940 /* UTF-16 is a default setting apparently */
2941 str
= (void*)0xdeadbeef;
2942 hr
= IMXWriter_get_encoding(writer
, &str
);
2943 EXPECT_HR(hr
, S_OK
);
2944 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
2946 str2
= (void*)0xdeadbeef;
2947 hr
= IMXWriter_get_encoding(writer
, &str2
);
2948 ok(hr
== S_OK
, "got %08x\n", hr
);
2949 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
2951 SysFreeString(str2
);
2954 /* put empty string */
2955 str
= SysAllocString(emptyW
);
2956 hr
= IMXWriter_put_encoding(writer
, str
);
2957 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2960 str
= (void*)0xdeadbeef;
2961 hr
= IMXWriter_get_encoding(writer
, &str
);
2962 EXPECT_HR(hr
, S_OK
);
2963 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
2966 /* invalid encoding name */
2967 str
= SysAllocString(testW
);
2968 hr
= IMXWriter_put_encoding(writer
, str
);
2969 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2972 /* test case sensivity */
2973 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
2974 EXPECT_HR(hr
, S_OK
);
2975 str
= (void*)0xdeadbeef;
2976 hr
= IMXWriter_get_encoding(writer
, &str
);
2977 EXPECT_HR(hr
, S_OK
);
2978 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
2981 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
2982 EXPECT_HR(hr
, S_OK
);
2983 str
= (void*)0xdeadbeef;
2984 hr
= IMXWriter_get_encoding(writer
, &str
);
2985 EXPECT_HR(hr
, S_OK
);
2986 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
2989 /* how it affects document creation */
2990 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2991 EXPECT_HR(hr
, S_OK
);
2993 hr
= ISAXContentHandler_startDocument(content
);
2994 EXPECT_HR(hr
, S_OK
);
2995 hr
= ISAXContentHandler_endDocument(content
);
2996 EXPECT_HR(hr
, S_OK
);
2998 V_VT(&dest
) = VT_EMPTY
;
2999 hr
= IMXWriter_get_output(writer
, &dest
);
3000 EXPECT_HR(hr
, S_OK
);
3001 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3002 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
3003 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3004 VariantClear(&dest
);
3005 ISAXContentHandler_Release(content
);
3007 hr
= IMXWriter_get_version(writer
, NULL
);
3008 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3009 /* default version is 'surprisingly' 1.0 */
3010 hr
= IMXWriter_get_version(writer
, &str
);
3011 ok(hr
== S_OK
, "got %08x\n", hr
);
3012 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
3015 /* store version string as is */
3016 hr
= IMXWriter_put_version(writer
, NULL
);
3017 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3019 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
3020 ok(hr
== S_OK
, "got %08x\n", hr
);
3022 hr
= IMXWriter_put_version(writer
, _bstr_(""));
3023 ok(hr
== S_OK
, "got %08x\n", hr
);
3024 hr
= IMXWriter_get_version(writer
, &str
);
3025 ok(hr
== S_OK
, "got %08x\n", hr
);
3026 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
3029 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
3030 ok(hr
== S_OK
, "got %08x\n", hr
);
3031 hr
= IMXWriter_get_version(writer
, &str
);
3032 ok(hr
== S_OK
, "got %08x\n", hr
);
3033 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
3036 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
3037 ok(hr
== S_OK
, "got %08x\n", hr
);
3038 hr
= IMXWriter_get_version(writer
, &str
);
3039 ok(hr
== S_OK
, "got %08x\n", hr
);
3040 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
3043 IMXWriter_Release(writer
);
3047 static void test_mxwriter_flush(void)
3049 static const WCHAR emptyW
[] = {0};
3050 ISAXContentHandler
*content
;
3053 ULARGE_INTEGER pos2
;
3061 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3062 &IID_IMXWriter
, (void**)&writer
);
3063 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3065 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3066 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3067 EXPECT_REF(stream
, 1);
3069 /* detach when nothing was attached */
3070 V_VT(&dest
) = VT_EMPTY
;
3071 hr
= IMXWriter_put_output(writer
, dest
);
3072 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3075 V_VT(&dest
) = VT_UNKNOWN
;
3076 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3077 hr
= IMXWriter_put_output(writer
, dest
);
3078 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3079 todo_wine
EXPECT_REF(stream
, 3);
3081 /* detach setting VT_EMPTY destination */
3082 V_VT(&dest
) = VT_EMPTY
;
3083 hr
= IMXWriter_put_output(writer
, dest
);
3084 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3085 EXPECT_REF(stream
, 1);
3087 V_VT(&dest
) = VT_UNKNOWN
;
3088 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3089 hr
= IMXWriter_put_output(writer
, dest
);
3090 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3092 /* flush() doesn't detach a stream */
3093 hr
= IMXWriter_flush(writer
);
3094 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3095 todo_wine
EXPECT_REF(stream
, 3);
3098 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3099 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3100 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3102 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3103 ok(hr
== S_OK
, "got %08x\n", hr
);
3105 hr
= ISAXContentHandler_startDocument(content
);
3106 ok(hr
== S_OK
, "got %08x\n", hr
);
3109 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3110 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3111 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
3113 /* already started */
3114 hr
= ISAXContentHandler_startDocument(content
);
3115 ok(hr
== S_OK
, "got %08x\n", hr
);
3117 hr
= ISAXContentHandler_endDocument(content
);
3118 ok(hr
== S_OK
, "got %08x\n", hr
);
3120 /* flushed on endDocument() */
3122 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3123 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3124 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
3126 IStream_Release(stream
);
3128 /* auto-flush feature */
3129 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3130 EXPECT_HR(hr
, S_OK
);
3131 EXPECT_REF(stream
, 1);
3133 V_VT(&dest
) = VT_UNKNOWN
;
3134 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3135 hr
= IMXWriter_put_output(writer
, dest
);
3136 EXPECT_HR(hr
, S_OK
);
3138 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_FALSE
);
3139 EXPECT_HR(hr
, S_OK
);
3141 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3142 EXPECT_HR(hr
, S_OK
);
3144 hr
= ISAXContentHandler_startDocument(content
);
3145 EXPECT_HR(hr
, S_OK
);
3147 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3148 EXPECT_HR(hr
, S_OK
);
3150 /* internal buffer is flushed automatically on certain threshold */
3153 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3154 EXPECT_HR(hr
, S_OK
);
3155 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3158 buff
= HeapAlloc(GetProcessHeap(), 0, len
);
3159 memset(buff
, 'A', len
);
3160 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3161 EXPECT_HR(hr
, S_OK
);
3165 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3166 EXPECT_HR(hr
, S_OK
);
3168 ok(pos2
.QuadPart
!= 0, "unexpected stream beginning\n");
3170 hr
= IMXWriter_get_output(writer
, NULL
);
3171 EXPECT_HR(hr
, E_POINTER
);
3173 ref
= get_refcount(stream
);
3174 V_VT(&dest
) = VT_EMPTY
;
3175 hr
= IMXWriter_get_output(writer
, &dest
);
3176 EXPECT_HR(hr
, S_OK
);
3177 ok(V_VT(&dest
) == VT_UNKNOWN
, "got vt type %d\n", V_VT(&dest
));
3178 ok(V_UNKNOWN(&dest
) == (IUnknown
*)stream
, "got pointer %p\n", V_UNKNOWN(&dest
));
3179 ok(ref
+1 == get_refcount(stream
), "expected increased refcount\n");
3180 VariantClear(&dest
);
3182 hr
= ISAXContentHandler_endDocument(content
);
3183 EXPECT_HR(hr
, S_OK
);
3185 IStream_Release(stream
);
3187 /* test char count lower than threshold */
3188 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3189 EXPECT_HR(hr
, S_OK
);
3190 EXPECT_REF(stream
, 1);
3192 hr
= ISAXContentHandler_startDocument(content
);
3193 EXPECT_HR(hr
, S_OK
);
3195 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3196 EXPECT_HR(hr
, S_OK
);
3200 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3201 EXPECT_HR(hr
, S_OK
);
3202 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3204 memset(buff
, 'A', len
);
3205 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
- 8);
3206 EXPECT_HR(hr
, S_OK
);
3210 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3211 EXPECT_HR(hr
, S_OK
);
3212 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3214 hr
= ISAXContentHandler_endDocument(content
);
3215 EXPECT_HR(hr
, S_OK
);
3217 /* test auto-flush function when stream is not set */
3218 V_VT(&dest
) = VT_EMPTY
;
3219 hr
= IMXWriter_put_output(writer
, dest
);
3220 EXPECT_HR(hr
, S_OK
);
3222 hr
= ISAXContentHandler_startDocument(content
);
3223 EXPECT_HR(hr
, S_OK
);
3225 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3226 EXPECT_HR(hr
, S_OK
);
3228 memset(buff
, 'A', len
);
3229 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3230 EXPECT_HR(hr
, S_OK
);
3232 V_VT(&dest
) = VT_EMPTY
;
3233 hr
= IMXWriter_get_output(writer
, &dest
);
3234 EXPECT_HR(hr
, S_OK
);
3235 len
+= strlen("<a>");
3236 ok(SysStringLen(V_BSTR(&dest
)) == len
, "got len=%d, expected %d\n", SysStringLen(V_BSTR(&dest
)), len
);
3237 VariantClear(&dest
);
3239 HeapFree(GetProcessHeap(), 0, buff
);
3240 ISAXContentHandler_Release(content
);
3241 IStream_Release(stream
);
3242 IMXWriter_Release(writer
);
3246 static void test_mxwriter_startenddocument(void)
3248 ISAXContentHandler
*content
;
3253 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3254 &IID_IMXWriter
, (void**)&writer
);
3255 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3257 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3258 ok(hr
== S_OK
, "got %08x\n", hr
);
3260 hr
= ISAXContentHandler_startDocument(content
);
3261 ok(hr
== S_OK
, "got %08x\n", hr
);
3263 hr
= ISAXContentHandler_endDocument(content
);
3264 ok(hr
== S_OK
, "got %08x\n", hr
);
3266 V_VT(&dest
) = VT_EMPTY
;
3267 hr
= IMXWriter_get_output(writer
, &dest
);
3268 ok(hr
== S_OK
, "got %08x\n", hr
);
3269 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3270 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3271 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3272 VariantClear(&dest
);
3274 /* now try another startDocument */
3275 hr
= ISAXContentHandler_startDocument(content
);
3276 ok(hr
== S_OK
, "got %08x\n", hr
);
3277 /* and get duplicated prolog */
3278 V_VT(&dest
) = VT_EMPTY
;
3279 hr
= IMXWriter_get_output(writer
, &dest
);
3280 ok(hr
== S_OK
, "got %08x\n", hr
);
3281 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3282 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
3283 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3284 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3285 VariantClear(&dest
);
3287 ISAXContentHandler_Release(content
);
3288 IMXWriter_Release(writer
);
3290 /* now with omitted declaration */
3291 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3292 &IID_IMXWriter
, (void**)&writer
);
3293 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3295 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3296 ok(hr
== S_OK
, "got %08x\n", hr
);
3298 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3299 ok(hr
== S_OK
, "got %08x\n", hr
);
3301 hr
= ISAXContentHandler_startDocument(content
);
3302 ok(hr
== S_OK
, "got %08x\n", hr
);
3304 hr
= ISAXContentHandler_endDocument(content
);
3305 ok(hr
== S_OK
, "got %08x\n", hr
);
3307 V_VT(&dest
) = VT_EMPTY
;
3308 hr
= IMXWriter_get_output(writer
, &dest
);
3309 ok(hr
== S_OK
, "got %08x\n", hr
);
3310 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3311 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3312 VariantClear(&dest
);
3314 ISAXContentHandler_Release(content
);
3315 IMXWriter_Release(writer
);
3322 StartElement
= 0x001,
3324 StartEndElement
= 0x011,
3325 DisableEscaping
= 0x100
3328 struct writer_startendelement_t
{
3330 enum startendtype type
;
3332 const char *local_name
;
3336 ISAXAttributes
*attr
;
3339 static const char startelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\">";
3340 static const char startendelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\"/>";
3341 static const char startendelement_noescape_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&\">\"/>";
3343 static const struct writer_startendelement_t writer_startendelement
[] = {
3345 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3346 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3347 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3348 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
3349 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3351 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3352 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3353 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
3354 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3355 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3357 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3358 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
3359 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3360 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3361 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3363 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
3364 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3365 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3366 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3367 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3369 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3370 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3371 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3372 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
3373 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3375 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3376 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3377 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3378 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3379 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3381 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3382 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3383 /* endElement tests */
3384 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3385 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3386 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3388 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
3389 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3390 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3391 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3392 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
3394 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3395 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3396 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3397 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
3398 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3400 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3401 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3402 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
3403 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3404 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3406 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3407 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3408 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3409 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3410 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3412 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
3413 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3414 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3415 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3416 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3418 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3419 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3420 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3421 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3423 /* with attributes */
3424 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3426 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3427 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3428 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3429 /* empty elements */
3430 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3431 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3433 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3434 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3435 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
3436 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
3437 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
3439 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
3441 /* with disabled output escaping */
3442 { &CLSID_MXXMLWriter
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3443 { &CLSID_MXXMLWriter30
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3444 { &CLSID_MXXMLWriter40
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3445 { &CLSID_MXXMLWriter60
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3450 static void get_class_support_data(struct msxmlsupported_data_t
*table
, REFIID riid
)
3452 while (table
->clsid
)
3457 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, riid
, (void**)&unk
);
3458 if (hr
== S_OK
) IUnknown_Release(unk
);
3460 table
->supported
= hr
== S_OK
;
3461 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
3467 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
3471 while (table
->clsid
)
3473 ISAXContentHandler
*content
;
3477 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3484 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3485 &IID_IMXWriter
, (void**)&writer
);
3486 EXPECT_HR(hr
, S_OK
);
3488 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3489 EXPECT_HR(hr
, S_OK
);
3491 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3492 EXPECT_HR(hr
, S_OK
);
3494 hr
= ISAXContentHandler_startDocument(content
);
3495 EXPECT_HR(hr
, S_OK
);
3497 if (table
->type
& DisableEscaping
)
3499 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3500 EXPECT_HR(hr
, S_OK
);
3503 if (table
->type
& StartElement
)
3505 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3506 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
), table
->attr
);
3507 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3510 if (table
->type
& EndElement
)
3512 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3513 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
));
3514 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3522 V_VT(&dest
) = VT_EMPTY
;
3523 hr
= IMXWriter_get_output(writer
, &dest
);
3524 EXPECT_HR(hr
, S_OK
);
3525 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3526 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3527 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3528 VariantClear(&dest
);
3531 ISAXContentHandler_Release(content
);
3532 IMXWriter_Release(writer
);
3541 /* point of these test is to start/end element with different names and name lengths */
3542 struct writer_startendelement2_t
{
3544 const char *qnamestart
;
3546 const char *qnameend
;
3552 static const struct writer_startendelement2_t writer_startendelement2
[] = {
3553 { &CLSID_MXXMLWriter
, "a", -1, "b", -1, "<a/>", S_OK
},
3554 { &CLSID_MXXMLWriter30
, "a", -1, "b", -1, "<a/>", S_OK
},
3555 { &CLSID_MXXMLWriter40
, "a", -1, "b", -1, "<a/>", S_OK
},
3556 /* -1 length is not allowed for version 6 */
3557 { &CLSID_MXXMLWriter60
, "a", -1, "b", -1, "<a/>", E_INVALIDARG
},
3559 { &CLSID_MXXMLWriter
, "a", 1, "b", 1, "<a/>", S_OK
},
3560 { &CLSID_MXXMLWriter30
, "a", 1, "b", 1, "<a/>", S_OK
},
3561 { &CLSID_MXXMLWriter40
, "a", 1, "b", 1, "<a/>", S_OK
},
3562 { &CLSID_MXXMLWriter60
, "a", 1, "b", 1, "<a/>", S_OK
},
3566 static void test_mxwriter_startendelement_batch2(const struct writer_startendelement2_t
*table
)
3570 while (table
->clsid
)
3572 ISAXContentHandler
*content
;
3576 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3583 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3584 &IID_IMXWriter
, (void**)&writer
);
3585 EXPECT_HR(hr
, S_OK
);
3587 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3588 EXPECT_HR(hr
, S_OK
);
3590 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3591 EXPECT_HR(hr
, S_OK
);
3593 hr
= ISAXContentHandler_startDocument(content
);
3594 EXPECT_HR(hr
, S_OK
);
3596 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3597 _bstr_(table
->qnamestart
), table
->qnamestart_len
, NULL
);
3598 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3600 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3601 _bstr_(table
->qnameend
), table
->qnameend_len
);
3602 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3609 V_VT(&dest
) = VT_EMPTY
;
3610 hr
= IMXWriter_get_output(writer
, &dest
);
3611 EXPECT_HR(hr
, S_OK
);
3612 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3613 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3614 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3615 VariantClear(&dest
);
3618 ISAXContentHandler_Release(content
);
3619 IMXWriter_Release(writer
);
3629 static void test_mxwriter_startendelement(void)
3631 ISAXContentHandler
*content
;
3636 test_mxwriter_startendelement_batch(writer_startendelement
);
3637 test_mxwriter_startendelement_batch2(writer_startendelement2
);
3639 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3640 &IID_IMXWriter
, (void**)&writer
);
3641 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3643 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3644 ok(hr
== S_OK
, "got %08x\n", hr
);
3646 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3647 ok(hr
== S_OK
, "got %08x\n", hr
);
3649 hr
= ISAXContentHandler_startDocument(content
);
3650 ok(hr
== S_OK
, "got %08x\n", hr
);
3652 /* all string pointers should be not null */
3653 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
3654 ok(hr
== S_OK
, "got %08x\n", hr
);
3656 V_VT(&dest
) = VT_EMPTY
;
3657 hr
= IMXWriter_get_output(writer
, &dest
);
3658 ok(hr
== S_OK
, "got %08x\n", hr
);
3659 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3660 ok(!lstrcmpW(_bstr_("<>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3661 VariantClear(&dest
);
3663 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
3664 ok(hr
== S_OK
, "got %08x\n", hr
);
3666 V_VT(&dest
) = VT_EMPTY
;
3667 hr
= IMXWriter_get_output(writer
, &dest
);
3668 ok(hr
== S_OK
, "got %08x\n", hr
);
3669 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3670 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3671 VariantClear(&dest
);
3673 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
3674 EXPECT_HR(hr
, E_INVALIDARG
);
3676 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
3677 EXPECT_HR(hr
, E_INVALIDARG
);
3679 /* only local name is an error too */
3680 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
3681 EXPECT_HR(hr
, E_INVALIDARG
);
3683 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
3684 EXPECT_HR(hr
, S_OK
);
3686 V_VT(&dest
) = VT_EMPTY
;
3687 hr
= IMXWriter_get_output(writer
, &dest
);
3688 EXPECT_HR(hr
, S_OK
);
3689 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3690 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3691 VariantClear(&dest
);
3693 hr
= ISAXContentHandler_endDocument(content
);
3694 EXPECT_HR(hr
, S_OK
);
3696 V_VT(&dest
) = VT_EMPTY
;
3697 hr
= IMXWriter_put_output(writer
, dest
);
3698 EXPECT_HR(hr
, S_OK
);
3700 V_VT(&dest
) = VT_EMPTY
;
3701 hr
= IMXWriter_get_output(writer
, &dest
);
3702 EXPECT_HR(hr
, S_OK
);
3703 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3704 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3705 VariantClear(&dest
);
3707 hr
= ISAXContentHandler_startDocument(content
);
3708 EXPECT_HR(hr
, S_OK
);
3710 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
3711 EXPECT_HR(hr
, S_OK
);
3713 V_VT(&dest
) = VT_EMPTY
;
3714 hr
= IMXWriter_get_output(writer
, &dest
);
3715 EXPECT_HR(hr
, S_OK
);
3716 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3717 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3718 VariantClear(&dest
);
3720 ISAXContentHandler_endDocument(content
);
3721 IMXWriter_flush(writer
);
3723 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
3724 EXPECT_HR(hr
, S_OK
);
3725 V_VT(&dest
) = VT_EMPTY
;
3726 hr
= IMXWriter_get_output(writer
, &dest
);
3727 EXPECT_HR(hr
, S_OK
);
3728 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3729 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3730 VariantClear(&dest
);
3732 V_VT(&dest
) = VT_EMPTY
;
3733 hr
= IMXWriter_put_output(writer
, dest
);
3734 EXPECT_HR(hr
, S_OK
);
3737 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), -1, NULL
);
3738 EXPECT_HR(hr
, S_OK
);
3739 V_VT(&dest
) = VT_EMPTY
;
3740 hr
= IMXWriter_get_output(writer
, &dest
);
3741 EXPECT_HR(hr
, S_OK
);
3742 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3743 ok(!lstrcmpW(_bstr_("<a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3744 VariantClear(&dest
);
3746 ISAXContentHandler_Release(content
);
3747 IMXWriter_Release(writer
);
3751 struct writer_characters_t
{
3757 static const struct writer_characters_t writer_characters
[] = {
3758 { &CLSID_MXXMLWriter
, "< > & \"", "< > & \"" },
3759 { &CLSID_MXXMLWriter30
, "< > & \"", "< > & \"" },
3760 { &CLSID_MXXMLWriter40
, "< > & \"", "< > & \"" },
3761 { &CLSID_MXXMLWriter60
, "< > & \"", "< > & \"" },
3765 static void test_mxwriter_characters(void)
3767 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
3768 const struct writer_characters_t
*table
= writer_characters
;
3769 ISAXContentHandler
*content
;
3775 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3776 &IID_IMXWriter
, (void**)&writer
);
3777 EXPECT_HR(hr
, S_OK
);
3779 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3780 EXPECT_HR(hr
, S_OK
);
3782 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3783 EXPECT_HR(hr
, S_OK
);
3785 hr
= ISAXContentHandler_startDocument(content
);
3786 EXPECT_HR(hr
, S_OK
);
3788 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
3789 EXPECT_HR(hr
, E_INVALIDARG
);
3791 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3792 EXPECT_HR(hr
, S_OK
);
3794 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
3795 EXPECT_HR(hr
, S_OK
);
3797 V_VT(&dest
) = VT_EMPTY
;
3798 hr
= IMXWriter_get_output(writer
, &dest
);
3799 EXPECT_HR(hr
, S_OK
);
3800 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3801 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3802 VariantClear(&dest
);
3804 hr
= ISAXContentHandler_endDocument(content
);
3805 EXPECT_HR(hr
, S_OK
);
3807 ISAXContentHandler_Release(content
);
3808 IMXWriter_Release(writer
);
3810 /* try empty characters data to see if element is closed */
3811 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3812 &IID_IMXWriter
, (void**)&writer
);
3813 EXPECT_HR(hr
, S_OK
);
3815 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3816 EXPECT_HR(hr
, S_OK
);
3818 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3819 EXPECT_HR(hr
, S_OK
);
3821 hr
= ISAXContentHandler_startDocument(content
);
3822 EXPECT_HR(hr
, S_OK
);
3824 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3825 EXPECT_HR(hr
, S_OK
);
3827 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3828 EXPECT_HR(hr
, S_OK
);
3830 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3831 EXPECT_HR(hr
, S_OK
);
3833 V_VT(&dest
) = VT_EMPTY
;
3834 hr
= IMXWriter_get_output(writer
, &dest
);
3835 EXPECT_HR(hr
, S_OK
);
3836 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3837 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3838 VariantClear(&dest
);
3840 ISAXContentHandler_Release(content
);
3841 IMXWriter_Release(writer
);
3844 while (table
->clsid
)
3846 ISAXContentHandler
*content
;
3851 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3858 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3859 &IID_IMXWriter
, (void**)&writer
);
3860 EXPECT_HR(hr
, S_OK
);
3862 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3863 EXPECT_HR(hr
, S_OK
);
3865 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3866 EXPECT_HR(hr
, S_OK
);
3868 hr
= ISAXContentHandler_startDocument(content
);
3869 EXPECT_HR(hr
, S_OK
);
3871 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
3872 EXPECT_HR(hr
, S_OK
);
3877 V_VT(&dest
) = VT_EMPTY
;
3878 hr
= IMXWriter_get_output(writer
, &dest
);
3879 EXPECT_HR(hr
, S_OK
);
3880 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3881 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3882 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3883 VariantClear(&dest
);
3886 /* with disabled escaping */
3887 V_VT(&dest
) = VT_EMPTY
;
3888 hr
= IMXWriter_put_output(writer
, dest
);
3889 EXPECT_HR(hr
, S_OK
);
3891 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3892 EXPECT_HR(hr
, S_OK
);
3894 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
3895 EXPECT_HR(hr
, S_OK
);
3900 V_VT(&dest
) = VT_EMPTY
;
3901 hr
= IMXWriter_get_output(writer
, &dest
);
3902 EXPECT_HR(hr
, S_OK
);
3903 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3904 ok(!lstrcmpW(_bstr_(table
->data
), V_BSTR(&dest
)),
3905 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->data
);
3906 VariantClear(&dest
);
3909 ISAXContentHandler_Release(content
);
3910 IMXWriter_Release(writer
);
3919 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
3921 VARIANT_TRUE
,"UTF-16",
3923 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3924 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3929 VARIANT_FALSE
,"UTF-16",
3931 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3936 VARIANT_TRUE
,"UTF-8",
3938 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
3939 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3940 * and the writer is released.
3947 VARIANT_TRUE
,"utf-8",
3949 {FALSE
,(const BYTE
*)utf8xml2
,sizeof(utf8xml2
)-1},
3950 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3951 * and the writer is released.
3958 VARIANT_TRUE
,"UTF-16",
3960 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3961 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3966 VARIANT_TRUE
,"UTF-16",
3968 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
3969 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3975 static void test_mxwriter_stream(void)
3978 ISAXContentHandler
*content
;
3983 ULARGE_INTEGER pos2
;
3984 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
3986 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
3987 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
3989 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3990 &IID_IMXWriter
, (void**)&writer
);
3991 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
3993 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3994 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
3996 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
3997 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
3999 V_VT(&dest
) = VT_UNKNOWN
;
4000 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
4001 hr
= IMXWriter_put_output(writer
, dest
);
4002 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
4003 VariantClear(&dest
);
4005 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
4006 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
4008 current_write_test
= test
->expected_writes
;
4010 hr
= ISAXContentHandler_startDocument(content
);
4011 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4013 hr
= ISAXContentHandler_endDocument(content
);
4014 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4016 ISAXContentHandler_Release(content
);
4017 IMXWriter_Release(writer
);
4019 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
4020 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
4023 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4024 &IID_IMXWriter
, (void**)&writer
);
4025 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4027 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4028 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
4030 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4031 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4033 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4034 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
4036 V_VT(&dest
) = VT_UNKNOWN
;
4037 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4038 hr
= IMXWriter_put_output(writer
, dest
);
4039 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4041 hr
= ISAXContentHandler_startDocument(content
);
4042 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4044 /* Setting output of the mxwriter causes the current output to be flushed,
4045 * and the writer to start over.
4047 V_VT(&dest
) = VT_EMPTY
;
4048 hr
= IMXWriter_put_output(writer
, dest
);
4049 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4052 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4053 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
4054 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
4056 hr
= ISAXContentHandler_startDocument(content
);
4057 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4059 hr
= ISAXContentHandler_endDocument(content
);
4060 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
4062 V_VT(&dest
) = VT_EMPTY
;
4063 hr
= IMXWriter_get_output(writer
, &dest
);
4064 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
4065 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4066 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4067 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4068 VariantClear(&dest
);
4070 /* test when BOM is written to output stream */
4071 V_VT(&dest
) = VT_EMPTY
;
4072 hr
= IMXWriter_put_output(writer
, dest
);
4073 EXPECT_HR(hr
, S_OK
);
4076 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
4077 EXPECT_HR(hr
, S_OK
);
4079 V_VT(&dest
) = VT_UNKNOWN
;
4080 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4081 hr
= IMXWriter_put_output(writer
, dest
);
4082 EXPECT_HR(hr
, S_OK
);
4084 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_TRUE
);
4085 EXPECT_HR(hr
, S_OK
);
4087 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4088 EXPECT_HR(hr
, S_OK
);
4090 hr
= ISAXContentHandler_startDocument(content
);
4091 EXPECT_HR(hr
, S_OK
);
4095 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4096 EXPECT_HR(hr
, S_OK
);
4097 ok(pos2
.QuadPart
== 2, "got wrong position\n");
4099 ISAXContentHandler_Release(content
);
4100 IMXWriter_Release(writer
);
4105 static const char *encoding_names
[] = {
4118 static void test_mxwriter_encoding(void)
4120 ISAXContentHandler
*content
;
4131 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4132 &IID_IMXWriter
, (void**)&writer
);
4133 EXPECT_HR(hr
, S_OK
);
4135 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4136 EXPECT_HR(hr
, S_OK
);
4138 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4139 EXPECT_HR(hr
, S_OK
);
4141 hr
= ISAXContentHandler_startDocument(content
);
4142 EXPECT_HR(hr
, S_OK
);
4144 hr
= ISAXContentHandler_endDocument(content
);
4145 EXPECT_HR(hr
, S_OK
);
4147 /* The content is always re-encoded to UTF-16 when the output is
4148 * retrieved as a BSTR.
4150 V_VT(&dest
) = VT_EMPTY
;
4151 hr
= IMXWriter_get_output(writer
, &dest
);
4152 EXPECT_HR(hr
, S_OK
);
4153 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4154 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4155 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4156 VariantClear(&dest
);
4158 /* switch encoding when something is written already */
4159 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4160 EXPECT_HR(hr
, S_OK
);
4162 V_VT(&dest
) = VT_UNKNOWN
;
4163 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4164 hr
= IMXWriter_put_output(writer
, dest
);
4165 EXPECT_HR(hr
, S_OK
);
4167 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4168 EXPECT_HR(hr
, S_OK
);
4170 /* write empty element */
4171 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
4172 EXPECT_HR(hr
, S_OK
);
4174 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
4175 EXPECT_HR(hr
, S_OK
);
4178 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4179 EXPECT_HR(hr
, S_OK
);
4181 hr
= IMXWriter_flush(writer
);
4182 EXPECT_HR(hr
, S_OK
);
4184 hr
= GetHGlobalFromStream(stream
, &g
);
4185 EXPECT_HR(hr
, S_OK
);
4187 ptr
= GlobalLock(g
);
4188 ok(!strncmp(ptr
, "<a/>", 4), "got %c%c%c%c\n", ptr
[0],ptr
[1],ptr
[2],ptr
[3]);
4191 /* so output is unaffected, encoding name is stored however */
4192 hr
= IMXWriter_get_encoding(writer
, &s
);
4193 EXPECT_HR(hr
, S_OK
);
4194 ok(!lstrcmpW(s
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(s
));
4197 IStream_Release(stream
);
4200 enc
= encoding_names
[i
];
4203 char expectedA
[200];
4205 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4206 EXPECT_HR(hr
, S_OK
);
4208 V_VT(&dest
) = VT_UNKNOWN
;
4209 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4210 hr
= IMXWriter_put_output(writer
, dest
);
4211 EXPECT_HR(hr
, S_OK
);
4213 hr
= IMXWriter_put_encoding(writer
, _bstr_(enc
));
4214 ok(hr
== S_OK
|| broken(hr
!= S_OK
) /* old win versions do not support certain encodings */,
4215 "%s: encoding not accepted\n", enc
);
4218 enc
= encoding_names
[++i
];
4219 IStream_Release(stream
);
4223 hr
= ISAXContentHandler_startDocument(content
);
4224 EXPECT_HR(hr
, S_OK
);
4226 hr
= ISAXContentHandler_endDocument(content
);
4227 EXPECT_HR(hr
, S_OK
);
4229 hr
= IMXWriter_flush(writer
);
4230 EXPECT_HR(hr
, S_OK
);
4232 /* prepare expected string */
4234 strcat(expectedA
, "<?xml version=\"1.0\" encoding=\"");
4235 strcat(expectedA
, enc
);
4236 strcat(expectedA
, "\" standalone=\"no\"?>\r\n");
4238 hr
= GetHGlobalFromStream(stream
, &g
);
4239 EXPECT_HR(hr
, S_OK
);
4241 ptr
= GlobalLock(g
);
4242 ok(!strncmp(ptr
, expectedA
, strlen(expectedA
)), "%s: got %s, expected %.50s\n", enc
, ptr
, expectedA
);
4245 V_VT(&dest
) = VT_EMPTY
;
4246 hr
= IMXWriter_put_output(writer
, dest
);
4247 EXPECT_HR(hr
, S_OK
);
4249 IStream_Release(stream
);
4251 enc
= encoding_names
[++i
];
4254 ISAXContentHandler_Release(content
);
4255 IMXWriter_Release(writer
);
4260 static void test_obj_dispex(IUnknown
*obj
)
4262 static const WCHAR starW
[] = {'*',0};
4263 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
4264 IDispatchEx
*dispex
;
4271 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
4272 EXPECT_HR(hr
, S_OK
);
4273 if (FAILED(hr
)) return;
4276 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
4277 EXPECT_HR(hr
, S_OK
);
4278 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
4280 name
= SysAllocString(starW
);
4281 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
4282 EXPECT_HR(hr
, E_NOTIMPL
);
4283 SysFreeString(name
);
4285 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
4286 EXPECT_HR(hr
, E_NOTIMPL
);
4289 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
4290 EXPECT_HR(hr
, E_NOTIMPL
);
4291 ok(props
== 0, "expected 0 got %d\n", props
);
4293 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
4294 EXPECT_HR(hr
, E_NOTIMPL
);
4295 if (SUCCEEDED(hr
)) SysFreeString(name
);
4297 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
4298 EXPECT_HR(hr
, E_NOTIMPL
);
4300 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
4301 EXPECT_HR(hr
, E_NOTIMPL
);
4302 if (hr
== S_OK
&& unk
) IUnknown_Release(unk
);
4304 IDispatchEx_Release(dispex
);
4307 static void test_dispex(void)
4309 IVBSAXXMLReader
*vbreader
;
4310 ISAXXMLReader
*reader
;
4314 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
4315 &IID_ISAXXMLReader
, (void**)&reader
);
4316 EXPECT_HR(hr
, S_OK
);
4318 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
4319 EXPECT_HR(hr
, S_OK
);
4320 test_obj_dispex(unk
);
4321 IUnknown_Release(unk
);
4323 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
4324 EXPECT_HR(hr
, S_OK
);
4325 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
4326 EXPECT_HR(hr
, S_OK
);
4327 test_obj_dispex(unk
);
4328 IUnknown_Release(unk
);
4329 IVBSAXXMLReader_Release(vbreader
);
4331 ISAXXMLReader_Release(reader
);
4334 static void test_mxwriter_dispex(void)
4336 IDispatchEx
*dispex
;
4341 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4342 &IID_IMXWriter
, (void**)&writer
);
4343 EXPECT_HR(hr
, S_OK
);
4345 hr
= IMXWriter_QueryInterface(writer
, &IID_IDispatchEx
, (void**)&dispex
);
4346 EXPECT_HR(hr
, S_OK
);
4347 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4348 test_obj_dispex(unk
);
4349 IUnknown_Release(unk
);
4350 IDispatchEx_Release(dispex
);
4352 IMXWriter_Release(writer
);
4355 static void test_mxwriter_comment(void)
4357 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
4358 ISAXContentHandler
*content
;
4359 ISAXLexicalHandler
*lexical
;
4364 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4365 &IID_IMXWriter
, (void**)&writer
);
4366 EXPECT_HR(hr
, S_OK
);
4368 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4369 EXPECT_HR(hr
, S_OK
);
4371 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4372 EXPECT_HR(hr
, S_OK
);
4374 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4375 EXPECT_HR(hr
, S_OK
);
4377 hr
= ISAXContentHandler_startDocument(content
);
4378 EXPECT_HR(hr
, S_OK
);
4380 hr
= ISAXLexicalHandler_comment(lexical
, NULL
, 0);
4381 EXPECT_HR(hr
, E_INVALIDARG
);
4383 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, 0);
4384 EXPECT_HR(hr
, S_OK
);
4386 V_VT(&dest
) = VT_EMPTY
;
4387 hr
= IMXWriter_get_output(writer
, &dest
);
4388 EXPECT_HR(hr
, S_OK
);
4389 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4390 ok(!lstrcmpW(_bstr_("<!---->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4391 VariantClear(&dest
);
4393 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, sizeof(commentW
)/sizeof(WCHAR
)-1);
4394 EXPECT_HR(hr
, S_OK
);
4396 V_VT(&dest
) = VT_EMPTY
;
4397 hr
= IMXWriter_get_output(writer
, &dest
);
4398 EXPECT_HR(hr
, S_OK
);
4399 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4400 ok(!lstrcmpW(_bstr_("<!---->\r\n<!--comment-->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4401 VariantClear(&dest
);
4403 ISAXContentHandler_Release(content
);
4404 ISAXLexicalHandler_Release(lexical
);
4405 IMXWriter_Release(writer
);
4409 static void test_mxwriter_cdata(void)
4411 ISAXContentHandler
*content
;
4412 ISAXLexicalHandler
*lexical
;
4417 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4418 &IID_IMXWriter
, (void**)&writer
);
4419 EXPECT_HR(hr
, S_OK
);
4421 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4422 EXPECT_HR(hr
, S_OK
);
4424 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4425 EXPECT_HR(hr
, S_OK
);
4427 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4428 EXPECT_HR(hr
, S_OK
);
4430 hr
= ISAXContentHandler_startDocument(content
);
4431 EXPECT_HR(hr
, S_OK
);
4433 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4434 EXPECT_HR(hr
, S_OK
);
4436 V_VT(&dest
) = VT_EMPTY
;
4437 hr
= IMXWriter_get_output(writer
, &dest
);
4438 EXPECT_HR(hr
, S_OK
);
4439 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4440 ok(!lstrcmpW(_bstr_("<![CDATA["), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4441 VariantClear(&dest
);
4443 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4444 EXPECT_HR(hr
, S_OK
);
4446 /* all these are escaped for text nodes */
4447 hr
= ISAXContentHandler_characters(content
, _bstr_("< > & \""), 7);
4448 EXPECT_HR(hr
, S_OK
);
4450 hr
= ISAXLexicalHandler_endCDATA(lexical
);
4451 EXPECT_HR(hr
, S_OK
);
4453 V_VT(&dest
) = VT_EMPTY
;
4454 hr
= IMXWriter_get_output(writer
, &dest
);
4455 EXPECT_HR(hr
, S_OK
);
4456 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4457 ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4458 VariantClear(&dest
);
4460 ISAXContentHandler_Release(content
);
4461 ISAXLexicalHandler_Release(lexical
);
4462 IMXWriter_Release(writer
);
4466 static void test_mxwriter_pi(void)
4468 static const WCHAR targetW
[] = {'t','a','r','g','e','t',0};
4469 static const WCHAR dataW
[] = {'d','a','t','a',0};
4470 ISAXContentHandler
*content
;
4475 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4476 &IID_IMXWriter
, (void**)&writer
);
4477 EXPECT_HR(hr
, S_OK
);
4479 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4480 EXPECT_HR(hr
, S_OK
);
4482 hr
= ISAXContentHandler_processingInstruction(content
, NULL
, 0, NULL
, 0);
4483 EXPECT_HR(hr
, E_INVALIDARG
);
4485 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 0, NULL
, 0);
4486 EXPECT_HR(hr
, S_OK
);
4488 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, NULL
, 0);
4489 EXPECT_HR(hr
, S_OK
);
4491 V_VT(&dest
) = VT_EMPTY
;
4492 hr
= IMXWriter_get_output(writer
, &dest
);
4493 EXPECT_HR(hr
, S_OK
);
4494 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4495 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4496 VariantClear(&dest
);
4498 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 4, dataW
, 4);
4499 EXPECT_HR(hr
, S_OK
);
4501 V_VT(&dest
) = VT_EMPTY
;
4502 hr
= IMXWriter_get_output(writer
, &dest
);
4503 EXPECT_HR(hr
, S_OK
);
4504 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4505 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n<?targ data?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4506 VariantClear(&dest
);
4508 V_VT(&dest
) = VT_EMPTY
;
4509 hr
= IMXWriter_put_output(writer
, dest
);
4510 EXPECT_HR(hr
, S_OK
);
4512 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, dataW
, 0);
4513 EXPECT_HR(hr
, S_OK
);
4515 V_VT(&dest
) = VT_EMPTY
;
4516 hr
= IMXWriter_get_output(writer
, &dest
);
4517 EXPECT_HR(hr
, S_OK
);
4518 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4519 ok(!lstrcmpW(_bstr_("<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4520 VariantClear(&dest
);
4523 ISAXContentHandler_Release(content
);
4524 IMXWriter_Release(writer
);
4527 static void test_mxwriter_ignorablespaces(void)
4529 static const WCHAR dataW
[] = {'d','a','t','a',0};
4530 ISAXContentHandler
*content
;
4535 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4536 &IID_IMXWriter
, (void**)&writer
);
4537 EXPECT_HR(hr
, S_OK
);
4539 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4540 EXPECT_HR(hr
, S_OK
);
4542 hr
= ISAXContentHandler_ignorableWhitespace(content
, NULL
, 0);
4543 EXPECT_HR(hr
, E_INVALIDARG
);
4545 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 0);
4546 EXPECT_HR(hr
, S_OK
);
4548 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 4);
4549 EXPECT_HR(hr
, S_OK
);
4551 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 1);
4552 EXPECT_HR(hr
, S_OK
);
4554 V_VT(&dest
) = VT_EMPTY
;
4555 hr
= IMXWriter_get_output(writer
, &dest
);
4556 EXPECT_HR(hr
, S_OK
);
4557 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4558 ok(!lstrcmpW(_bstr_("datad"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4559 VariantClear(&dest
);
4561 ISAXContentHandler_Release(content
);
4562 IMXWriter_Release(writer
);
4565 static void test_mxwriter_dtd(void)
4567 static const WCHAR contentW
[] = {'c','o','n','t','e','n','t'};
4568 static const WCHAR nameW
[] = {'n','a','m','e'};
4569 static const WCHAR pubW
[] = {'p','u','b'};
4570 static const WCHAR sysW
[] = {'s','y','s'};
4571 ISAXContentHandler
*content
;
4572 ISAXLexicalHandler
*lexical
;
4573 ISAXDeclHandler
*decl
;
4578 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4579 &IID_IMXWriter
, (void**)&writer
);
4580 EXPECT_HR(hr
, S_OK
);
4582 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4583 EXPECT_HR(hr
, S_OK
);
4585 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4586 EXPECT_HR(hr
, S_OK
);
4588 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
4589 EXPECT_HR(hr
, S_OK
);
4591 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4592 EXPECT_HR(hr
, S_OK
);
4594 hr
= ISAXContentHandler_startDocument(content
);
4595 EXPECT_HR(hr
, S_OK
);
4597 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, NULL
, 0);
4598 EXPECT_HR(hr
, E_INVALIDARG
);
4600 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4601 EXPECT_HR(hr
, E_INVALIDARG
);
4603 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4604 EXPECT_HR(hr
, E_INVALIDARG
);
4606 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4607 EXPECT_HR(hr
, E_INVALIDARG
);
4609 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0, NULL
, 0);
4610 EXPECT_HR(hr
, S_OK
);
4612 V_VT(&dest
) = VT_EMPTY
;
4613 hr
= IMXWriter_get_output(writer
, &dest
);
4614 EXPECT_HR(hr
, S_OK
);
4615 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4616 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4617 VariantClear(&dest
);
4619 /* system id is required if public is present */
4620 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4621 EXPECT_HR(hr
, E_INVALIDARG
);
4623 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
),
4624 pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4625 EXPECT_HR(hr
, S_OK
);
4627 V_VT(&dest
) = VT_EMPTY
;
4628 hr
= IMXWriter_get_output(writer
, &dest
);
4629 EXPECT_HR(hr
, S_OK
);
4630 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4631 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4632 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4633 VariantClear(&dest
);
4635 hr
= ISAXLexicalHandler_endDTD(lexical
);
4636 EXPECT_HR(hr
, S_OK
);
4638 hr
= ISAXLexicalHandler_endDTD(lexical
);
4639 EXPECT_HR(hr
, S_OK
);
4641 V_VT(&dest
) = VT_EMPTY
;
4642 hr
= IMXWriter_get_output(writer
, &dest
);
4643 EXPECT_HR(hr
, S_OK
);
4644 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4645 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4646 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n"),
4647 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4648 VariantClear(&dest
);
4650 /* element declaration */
4651 V_VT(&dest
) = VT_EMPTY
;
4652 hr
= IMXWriter_put_output(writer
, dest
);
4653 EXPECT_HR(hr
, S_OK
);
4655 hr
= ISAXDeclHandler_elementDecl(decl
, NULL
, 0, NULL
, 0);
4656 EXPECT_HR(hr
, E_INVALIDARG
);
4658 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0);
4659 EXPECT_HR(hr
, E_INVALIDARG
);
4661 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, sizeof(contentW
)/sizeof(WCHAR
));
4662 EXPECT_HR(hr
, S_OK
);
4664 V_VT(&dest
) = VT_EMPTY
;
4665 hr
= IMXWriter_get_output(writer
, &dest
);
4666 EXPECT_HR(hr
, S_OK
);
4667 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4668 ok(!lstrcmpW(_bstr_("<!ELEMENT name content>\r\n"),
4669 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4670 VariantClear(&dest
);
4672 V_VT(&dest
) = VT_EMPTY
;
4673 hr
= IMXWriter_put_output(writer
, dest
);
4674 EXPECT_HR(hr
, S_OK
);
4676 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, 0);
4677 EXPECT_HR(hr
, S_OK
);
4679 V_VT(&dest
) = VT_EMPTY
;
4680 hr
= IMXWriter_get_output(writer
, &dest
);
4681 EXPECT_HR(hr
, S_OK
);
4682 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4683 ok(!lstrcmpW(_bstr_("<!ELEMENT name >\r\n"),
4684 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4685 VariantClear(&dest
);
4687 /* attribute declaration */
4688 V_VT(&dest
) = VT_EMPTY
;
4689 hr
= IMXWriter_put_output(writer
, dest
);
4690 EXPECT_HR(hr
, S_OK
);
4692 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4693 _bstr_("attribute"), strlen("attribute"), _bstr_("CDATA"), strlen("CDATA"),
4694 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value"), strlen("value"));
4695 EXPECT_HR(hr
, S_OK
);
4697 V_VT(&dest
) = VT_EMPTY
;
4698 hr
= IMXWriter_get_output(writer
, &dest
);
4699 EXPECT_HR(hr
, S_OK
);
4700 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4701 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"),
4702 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4703 VariantClear(&dest
);
4705 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4706 _bstr_("attribute2"), strlen("attribute2"), _bstr_("CDATA"), strlen("CDATA"),
4707 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value2"), strlen("value2"));
4708 EXPECT_HR(hr
, S_OK
);
4710 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element2"), strlen("element2"),
4711 _bstr_("attribute3"), strlen("attribute3"), _bstr_("CDATA"), strlen("CDATA"),
4712 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value3"), strlen("value3"));
4713 EXPECT_HR(hr
, S_OK
);
4715 V_VT(&dest
) = VT_EMPTY
;
4716 hr
= IMXWriter_get_output(writer
, &dest
);
4717 EXPECT_HR(hr
, S_OK
);
4718 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4719 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"
4720 "<!ATTLIST element attribute2 CDATA #REQUIRED \"value2\">\r\n"
4721 "<!ATTLIST element2 attribute3 CDATA #REQUIRED \"value3\">\r\n"),
4722 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4723 VariantClear(&dest
);
4725 /* internal entities */
4726 V_VT(&dest
) = VT_EMPTY
;
4727 hr
= IMXWriter_put_output(writer
, dest
);
4728 EXPECT_HR(hr
, S_OK
);
4730 hr
= ISAXDeclHandler_internalEntityDecl(decl
, NULL
, 0, NULL
, 0);
4731 EXPECT_HR(hr
, E_INVALIDARG
);
4733 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0);
4734 EXPECT_HR(hr
, E_INVALIDARG
);
4736 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("value"), strlen("value"));
4737 EXPECT_HR(hr
, S_OK
);
4739 V_VT(&dest
) = VT_EMPTY
;
4740 hr
= IMXWriter_get_output(writer
, &dest
);
4741 EXPECT_HR(hr
, S_OK
);
4742 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4743 ok(!lstrcmpW(_bstr_("<!ENTITY name \"value\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4744 VariantClear(&dest
);
4746 ISAXContentHandler_Release(content
);
4747 ISAXLexicalHandler_Release(lexical
);
4748 ISAXDeclHandler_Release(decl
);
4749 IMXWriter_Release(writer
);
4761 } addattribute_test_t
;
4763 static const addattribute_test_t addattribute_data
[] = {
4764 { &CLSID_SAXAttributes
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4765 { &CLSID_SAXAttributes30
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4766 { &CLSID_SAXAttributes40
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4767 { &CLSID_SAXAttributes60
, NULL
, NULL
, "ns:qname", NULL
, "value", S_OK
},
4769 { &CLSID_SAXAttributes
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4770 { &CLSID_SAXAttributes30
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4771 { &CLSID_SAXAttributes40
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4772 { &CLSID_SAXAttributes60
, NULL
, "qname", "ns:qname", NULL
, "value", S_OK
},
4774 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4775 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4776 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4777 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", NULL
, "value", S_OK
},
4779 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4780 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4781 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4782 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4787 static void test_mxattr_addAttribute(void)
4789 const addattribute_test_t
*table
= addattribute_data
;
4792 while (table
->clsid
)
4794 ISAXAttributes
*saxattr
;
4795 IMXAttributes
*mxattr
;
4800 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
4807 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4808 &IID_IMXAttributes
, (void**)&mxattr
);
4809 EXPECT_HR(hr
, S_OK
);
4811 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4812 EXPECT_HR(hr
, S_OK
);
4814 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
4815 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4816 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4818 hr
= ISAXAttributes_getLength(saxattr
, NULL
);
4819 EXPECT_HR(hr
, E_POINTER
);
4823 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4824 EXPECT_HR(hr
, S_OK
);
4825 ok(len
== 0, "got %d\n", len
);
4827 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
4828 EXPECT_HR(hr
, E_INVALIDARG
);
4830 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
4831 EXPECT_HR(hr
, E_INVALIDARG
);
4833 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
4834 EXPECT_HR(hr
, E_INVALIDARG
);
4836 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
4837 EXPECT_HR(hr
, E_INVALIDARG
);
4839 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
4840 EXPECT_HR(hr
, E_INVALIDARG
);
4842 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
4843 EXPECT_HR(hr
, E_INVALIDARG
);
4845 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
4846 EXPECT_HR(hr
, E_INVALIDARG
);
4848 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
4849 EXPECT_HR(hr
, E_INVALIDARG
);
4851 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_(table
->uri
), _bstr_(table
->local
),
4852 _bstr_(table
->qname
), _bstr_(table
->type
), _bstr_(table
->value
));
4853 ok(hr
== table
->hr
, "%d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
4857 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
4858 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4859 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4861 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
4862 EXPECT_HR(hr
, E_POINTER
);
4864 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
4865 EXPECT_HR(hr
, E_POINTER
);
4867 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
4868 EXPECT_HR(hr
, E_POINTER
);
4870 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
4871 EXPECT_HR(hr
, E_POINTER
);
4873 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
4874 EXPECT_HR(hr
, E_POINTER
);
4876 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
4877 EXPECT_HR(hr
, E_POINTER
);
4881 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
4882 EXPECT_HR(hr
, S_OK
);
4883 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4885 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
4888 value
= (void*)0xdeadbeef;
4889 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
4890 EXPECT_HR(hr
, S_OK
);
4894 ok(!lstrcmpW(_bstr_(table
->type
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4896 ok(lstrlenW(value
) == len
, "%d: got wrong type value length %d\n", i
, len
);
4900 ok(*value
== 0, "%d: got type value %s\n", i
, wine_dbgstr_w(value
));
4901 ok(len
== 0, "%d: got wrong type value length %d\n", i
, len
);
4904 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, NULL
);
4905 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4906 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4908 EXPECT_HR(hr
, E_POINTER
);
4911 EXPECT_HR(hr
, E_INVALIDARG
);
4913 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, &index
);
4914 EXPECT_HR(hr
, E_INVALIDARG
);
4917 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_("nonexistent"), 11, &index
);
4918 EXPECT_HR(hr
, E_INVALIDARG
);
4919 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4922 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), 0, &index
);
4923 EXPECT_HR(hr
, E_INVALIDARG
);
4924 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4927 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &index
);
4928 EXPECT_HR(hr
, S_OK
);
4929 ok(index
== 0, "%d: got wrong index %d\n", i
, index
);
4932 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
)-1, &index
);
4933 EXPECT_HR(hr
, E_INVALIDARG
);
4934 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4936 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes40
) ||
4937 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes60
))
4939 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4940 EXPECT_HR(hr
, E_INVALIDARG
);
4942 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4943 EXPECT_HR(hr
, E_INVALIDARG
);
4945 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4946 EXPECT_HR(hr
, E_INVALIDARG
);
4948 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
4949 EXPECT_HR(hr
, E_INVALIDARG
);
4951 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
4952 EXPECT_HR(hr
, E_INVALIDARG
);
4954 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
4955 EXPECT_HR(hr
, E_INVALIDARG
);
4959 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4960 EXPECT_HR(hr
, E_POINTER
);
4962 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4963 EXPECT_HR(hr
, E_POINTER
);
4965 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4966 EXPECT_HR(hr
, E_POINTER
);
4968 /* versions 4 and 6 crash */
4969 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, NULL
);
4970 EXPECT_HR(hr
, E_POINTER
);
4972 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, &len
);
4973 EXPECT_HR(hr
, E_POINTER
);
4975 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
4976 EXPECT_HR(hr
, E_POINTER
);
4978 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
4979 EXPECT_HR(hr
, E_POINTER
);
4981 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
4982 EXPECT_HR(hr
, E_POINTER
);
4984 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, &value
, NULL
);
4985 EXPECT_HR(hr
, E_POINTER
);
4987 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, NULL
, &len
);
4988 EXPECT_HR(hr
, E_POINTER
);
4990 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
), _bstr_(table
->local
),
4991 strlen(table
->local
), NULL
, NULL
);
4992 EXPECT_HR(hr
, E_POINTER
);
4995 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &value
, &len
);
4996 EXPECT_HR(hr
, S_OK
);
4997 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4999 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5002 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
),
5003 _bstr_(table
->local
), strlen(table
->local
), &value
, &len
);
5004 EXPECT_HR(hr
, S_OK
);
5005 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5007 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5012 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5013 EXPECT_HR(hr
, S_OK
);
5014 if (table
->hr
== S_OK
)
5015 ok(len
== 1, "%d: got %d length, expected 1\n", i
, len
);
5017 ok(len
== 0, "%d: got %d length, expected 0\n", i
, len
);
5019 ISAXAttributes_Release(saxattr
);
5020 IMXAttributes_Release(mxattr
);
5029 static void test_mxattr_clear(void)
5031 ISAXAttributes
*saxattr
;
5032 IMXAttributes
*mxattr
;
5037 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5038 &IID_IMXAttributes
, (void**)&mxattr
);
5039 EXPECT_HR(hr
, S_OK
);
5041 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5042 EXPECT_HR(hr
, S_OK
);
5044 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, NULL
);
5045 EXPECT_HR(hr
, E_INVALIDARG
);
5047 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5048 EXPECT_HR(hr
, E_INVALIDARG
);
5050 hr
= IMXAttributes_clear(mxattr
);
5051 EXPECT_HR(hr
, S_OK
);
5053 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("local"),
5054 _bstr_("qname"), _bstr_("type"), _bstr_("value"));
5055 EXPECT_HR(hr
, S_OK
);
5058 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5059 EXPECT_HR(hr
, S_OK
);
5060 ok(len
== 1, "got %d\n", len
);
5063 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, &len
);
5064 EXPECT_HR(hr
, E_POINTER
);
5065 ok(len
== -1, "got %d\n", len
);
5067 ptr
= (void*)0xdeadbeef;
5068 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, NULL
);
5069 EXPECT_HR(hr
, E_POINTER
);
5070 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5073 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5074 EXPECT_HR(hr
, S_OK
);
5075 ok(len
== 5, "got %d\n", len
);
5076 ok(!lstrcmpW(ptr
, _bstr_("qname")), "got %s\n", wine_dbgstr_w(ptr
));
5078 hr
= IMXAttributes_clear(mxattr
);
5079 EXPECT_HR(hr
, S_OK
);
5082 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5083 EXPECT_HR(hr
, S_OK
);
5084 ok(len
== 0, "got %d\n", len
);
5087 ptr
= (void*)0xdeadbeef;
5088 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5089 EXPECT_HR(hr
, E_INVALIDARG
);
5090 ok(len
== -1, "got %d\n", len
);
5091 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5093 IMXAttributes_Release(mxattr
);
5094 ISAXAttributes_Release(saxattr
);
5098 static void test_mxattr_dispex(void)
5100 IMXAttributes
*mxattr
;
5101 IDispatchEx
*dispex
;
5105 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5106 &IID_IMXAttributes
, (void**)&mxattr
);
5107 EXPECT_HR(hr
, S_OK
);
5109 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IDispatchEx
, (void**)&dispex
);
5110 EXPECT_HR(hr
, S_OK
);
5111 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
5112 test_obj_dispex(unk
);
5113 IUnknown_Release(unk
);
5114 IDispatchEx_Release(dispex
);
5116 IMXAttributes_Release(mxattr
);
5119 static void test_mxattr_qi(void)
5121 IVBSAXAttributes
*vbsaxattr
, *vbsaxattr2
;
5122 ISAXAttributes
*saxattr
;
5123 IMXAttributes
*mxattr
;
5126 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5127 &IID_IMXAttributes
, (void**)&mxattr
);
5128 EXPECT_HR(hr
, S_OK
);
5130 EXPECT_REF(mxattr
, 1);
5131 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5132 EXPECT_HR(hr
, S_OK
);
5134 EXPECT_REF(mxattr
, 2);
5135 EXPECT_REF(saxattr
, 2);
5137 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr
);
5138 EXPECT_HR(hr
, S_OK
);
5140 EXPECT_REF(vbsaxattr
, 3);
5141 EXPECT_REF(mxattr
, 3);
5142 EXPECT_REF(saxattr
, 3);
5144 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr2
);
5145 EXPECT_HR(hr
, S_OK
);
5147 EXPECT_REF(vbsaxattr
, 4);
5148 EXPECT_REF(mxattr
, 4);
5149 EXPECT_REF(saxattr
, 4);
5151 IMXAttributes_Release(mxattr
);
5152 ISAXAttributes_Release(saxattr
);
5153 IVBSAXAttributes_Release(vbsaxattr
);
5154 IVBSAXAttributes_Release(vbsaxattr2
);
5157 static struct msxmlsupported_data_t saxattr_support_data
[] =
5159 { &CLSID_SAXAttributes
, "SAXAttributes" },
5160 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
5161 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
5162 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
5166 static void test_mxattr_localname(void)
5168 static const WCHAR localname1W
[] = {'l','o','c','a','l','n','a','m','e','1',0};
5169 static const WCHAR localnameW
[] = {'l','o','c','a','l','n','a','m','e',0};
5170 static const WCHAR uri1W
[] = {'u','r','i','1',0};
5171 static const WCHAR uriW
[] = {'u','r','i',0};
5173 const struct msxmlsupported_data_t
*table
= saxattr_support_data
;
5175 while (table
->clsid
)
5177 ISAXAttributes
*saxattr
;
5178 IMXAttributes
*mxattr
;
5182 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5188 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5189 &IID_IMXAttributes
, (void**)&mxattr
);
5190 EXPECT_HR(hr
, S_OK
);
5192 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5193 EXPECT_HR(hr
, S_OK
);
5195 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, &index
);
5196 EXPECT_HR(hr
, E_INVALIDARG
);
5198 /* add some ambiguos attribute names */
5199 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5200 _bstr_("a:localname"), _bstr_(""), _bstr_("value"));
5201 EXPECT_HR(hr
, S_OK
);
5202 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5203 _bstr_("b:localname"), _bstr_(""), _bstr_("value"));
5204 EXPECT_HR(hr
, S_OK
);
5207 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localnameW
, lstrlenW(localnameW
), &index
);
5208 EXPECT_HR(hr
, S_OK
);
5209 ok(index
== 0, "%s: got index %d\n", table
->name
, index
);
5212 hr
= ISAXAttributes_getIndexFromName(saxattr
, uri1W
, lstrlenW(uri1W
), localnameW
, lstrlenW(localnameW
), &index
);
5213 EXPECT_HR(hr
, E_INVALIDARG
);
5214 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5217 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), &index
);
5218 EXPECT_HR(hr
, E_INVALIDARG
);
5219 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5221 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5222 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5224 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5225 EXPECT_HR(hr
, E_POINTER
);
5227 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5228 EXPECT_HR(hr
, E_POINTER
);
5232 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5233 EXPECT_HR(hr
, E_INVALIDARG
);
5235 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5236 EXPECT_HR(hr
, E_INVALIDARG
);
5239 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), NULL
, 0, &index
);
5240 EXPECT_HR(hr
, E_INVALIDARG
);
5242 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, localname1W
, lstrlenW(localname1W
), &index
);
5243 EXPECT_HR(hr
, E_INVALIDARG
);
5247 ISAXAttributes_Release(saxattr
);
5248 IMXAttributes_Release(mxattr
);
5252 START_TEST(saxreader
)
5254 ISAXXMLReader
*reader
;
5257 hr
= CoInitialize(NULL
);
5258 ok(hr
== S_OK
, "failed to init com\n");
5260 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
5261 &IID_ISAXXMLReader
, (void**)&reader
);
5265 skip("Failed to create SAXXMLReader instance\n");
5269 ISAXXMLReader_Release(reader
);
5271 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
5273 get_class_support_data(reader_support_data
, &IID_ISAXXMLReader
);
5276 test_saxreader_properties();
5277 test_saxreader_features();
5278 test_saxreader_encoding();
5281 /* MXXMLWriter tests */
5282 get_class_support_data(mxwriter_support_data
, &IID_IMXWriter
);
5283 if (is_clsid_supported(&CLSID_MXXMLWriter
, mxwriter_support_data
))
5285 test_mxwriter_handlers();
5286 test_mxwriter_startenddocument();
5287 test_mxwriter_startendelement();
5288 test_mxwriter_characters();
5289 test_mxwriter_comment();
5290 test_mxwriter_cdata();
5292 test_mxwriter_ignorablespaces();
5293 test_mxwriter_dtd();
5294 test_mxwriter_properties();
5295 test_mxwriter_flush();
5296 test_mxwriter_stream();
5297 test_mxwriter_encoding();
5298 test_mxwriter_dispex();
5301 win_skip("MXXMLWriter not supported\n");
5303 /* SAXAttributes tests */
5304 get_class_support_data(mxattributes_support_data
, &IID_IMXAttributes
);
5305 if (is_clsid_supported(&CLSID_SAXAttributes
, mxattributes_support_data
))
5308 test_mxattr_addAttribute();
5309 test_mxattr_clear();
5310 test_mxattr_localname();
5311 test_mxattr_dispex();
5314 skip("SAXAttributes not supported\n");