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
32 #include "msxml2did.h"
36 #include "wine/test.h"
38 static const WCHAR emptyW
[] = {0};
40 #define EXPECT_HR(hr,hr_exp) \
41 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
43 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
44 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
46 ULONG rc
= IUnknown_AddRef(obj
);
47 IUnknown_Release(obj
);
48 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
51 static LONG
get_refcount(void *iface
)
53 IUnknown
*unk
= iface
;
56 ref
= IUnknown_AddRef(unk
);
57 IUnknown_Release(unk
);
61 struct msxmlsupported_data_t
68 static BOOL
is_clsid_supported(const GUID
*clsid
, const struct msxmlsupported_data_t
*table
)
72 if (table
->clsid
== clsid
) return table
->supported
;
78 static BSTR
alloc_str_from_narrow(const char *str
)
80 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
81 BSTR ret
= SysAllocStringLen(NULL
, len
- 1); /* NUL character added automatically */
82 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
86 static BSTR alloced_bstrs
[512];
87 static int alloced_bstrs_count
;
89 static BSTR
_bstr_(const char *str
)
91 assert(alloced_bstrs_count
< sizeof(alloced_bstrs
)/sizeof(alloced_bstrs
[0]));
92 alloced_bstrs
[alloced_bstrs_count
] = alloc_str_from_narrow(str
);
93 return alloced_bstrs
[alloced_bstrs_count
++];
96 static void free_bstrs(void)
99 for (i
= 0; i
< alloced_bstrs_count
; i
++)
100 SysFreeString(alloced_bstrs
[i
]);
101 alloced_bstrs_count
= 0;
104 static void test_saxstr(const char *file
, unsigned line
, BSTR str
, const char *expected
, BOOL todo
, int *failcount
)
106 int len
, lenexp
, cmp
;
109 len
= SysStringLen(str
);
116 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
119 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
125 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
128 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
132 lenexp
= strlen(expected
);
133 if (lenexp
!= len
&& todo
)
137 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
140 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
142 /* exit earlier on length mismatch */
143 if (lenexp
!= len
) return;
145 MultiByteToWideChar(CP_ACP
, 0, expected
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
147 cmp
= memcmp(str
, buf
, lenexp
*sizeof(WCHAR
));
152 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
153 wine_dbgstr_wn(str
, len
), expected
);
156 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
157 wine_dbgstr_wn(str
, len
), expected
);
162 CH_PUTDOCUMENTLOCATOR
,
165 CH_STARTPREFIXMAPPING
,
170 CH_IGNORABLEWHITESPACE
,
171 CH_PROCESSINGINSTRUCTION
,
181 static const char *event_names
[EVENT_LAST
] = {
183 "putDocumentLocator",
186 "startPrefixMapping",
191 "ignorableWhitespace",
192 "processingInstruction",
201 struct attribute_entry
{
207 /* used for actual call data only, null for expected call data */
223 /* allocated once at startElement callback */
224 struct attribute_entry
*attributes
;
227 /* used for actual call data only, null for expected call data */
237 struct call_entry
*sequence
;
240 #define CONTENT_HANDLER_INDEX 0
241 #define NUM_CALL_SEQUENCES 1
242 static struct call_sequence
*sequences
[NUM_CALL_SEQUENCES
];
244 static void init_call_entry(ISAXLocator
*locator
, struct call_entry
*call
)
246 memset(call
, 0, sizeof(*call
));
247 ISAXLocator_getLineNumber(locator
, &call
->line
);
248 ISAXLocator_getColumnNumber(locator
, &call
->column
);
251 static void add_call(struct call_sequence
**seq
, int sequence_index
,
252 const struct call_entry
*call
)
254 struct call_sequence
*call_seq
= seq
[sequence_index
];
256 if (!call_seq
->sequence
)
259 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0,
260 call_seq
->size
* sizeof (struct call_entry
));
263 if (call_seq
->count
== call_seq
->size
)
266 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
268 call_seq
->size
* sizeof (struct call_entry
));
271 assert(call_seq
->sequence
);
273 call_seq
->sequence
[call_seq
->count
].id
= call
->id
;
274 call_seq
->sequence
[call_seq
->count
].line
= call
->line
;
275 call_seq
->sequence
[call_seq
->count
].column
= call
->column
;
276 call_seq
->sequence
[call_seq
->count
].arg1W
= call
->arg1W
;
277 call_seq
->sequence
[call_seq
->count
].arg2W
= call
->arg2W
;
278 call_seq
->sequence
[call_seq
->count
].arg3W
= call
->arg3W
;
279 call_seq
->sequence
[call_seq
->count
].ret
= call
->ret
;
280 call_seq
->sequence
[call_seq
->count
].attr_count
= call
->attr_count
;
281 call_seq
->sequence
[call_seq
->count
].attributes
= call
->attributes
;
286 static inline void flush_sequence(struct call_sequence
**seg
, int sequence_index
)
290 struct call_sequence
*call_seq
= seg
[sequence_index
];
292 for (i
= 0; i
< call_seq
->count
; i
++)
296 for (j
= 0; j
< call_seq
->sequence
[i
].attr_count
; j
++)
298 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].uriW
);
299 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].localW
);
300 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].qnameW
);
303 SysFreeString(call_seq
->sequence
[i
].arg1W
);
304 SysFreeString(call_seq
->sequence
[i
].arg2W
);
305 SysFreeString(call_seq
->sequence
[i
].arg3W
);
308 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
309 call_seq
->sequence
= NULL
;
310 call_seq
->count
= call_seq
->size
= 0;
313 static const char *get_event_name(CH event
)
315 return event_names
[event
];
318 static void compare_attributes(const struct call_entry
*actual
, const struct call_entry
*expected
, const char *context
,
319 BOOL todo
, const char *file
, int line
, int *failcount
)
323 /* attribute count is not stored for expected data */
324 if (expected
->attributes
)
326 struct attribute_entry
*ptr
= expected
->attributes
;
327 while (ptr
->uri
) { lenexp
++; ptr
++; };
330 /* check count first and exit earlier */
331 if (actual
->attr_count
!= lenexp
&& todo
)
335 ok_(file
, line
) (FALSE
, "%s: in event %s expecting attr count %d got %d\n",
336 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
339 ok_(file
, line
) (actual
->attr_count
== lenexp
, "%s: in event %s expecting attr count %d got %d\n",
340 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
342 if (actual
->attr_count
!= lenexp
) return;
344 /* now compare all attributes strings */
345 for (i
= 0; i
< actual
->attr_count
; i
++)
347 test_saxstr(file
, line
, actual
->attributes
[i
].uriW
, expected
->attributes
[i
].uri
, todo
, failcount
);
348 test_saxstr(file
, line
, actual
->attributes
[i
].localW
, expected
->attributes
[i
].local
, todo
, failcount
);
349 test_saxstr(file
, line
, actual
->attributes
[i
].qnameW
, expected
->attributes
[i
].qname
, todo
, failcount
);
350 test_saxstr(file
, line
, actual
->attributes
[i
].valueW
, expected
->attributes
[i
].value
, todo
, failcount
);
354 static void ok_sequence_(struct call_sequence
**seq
, int sequence_index
,
355 const struct call_entry
*expected
, const char *context
, BOOL todo
,
356 const char *file
, int line
)
358 struct call_sequence
*call_seq
= seq
[sequence_index
];
359 static const struct call_entry end_of_sequence
= { CH_ENDTEST
};
360 const struct call_entry
*actual
, *sequence
;
363 add_call(seq
, sequence_index
, &end_of_sequence
);
365 sequence
= call_seq
->sequence
;
368 while (expected
->id
!= CH_ENDTEST
&& actual
->id
!= CH_ENDTEST
)
370 if (expected
->id
== actual
->id
)
372 if (expected
->line
!= -1)
374 /* always test position data */
375 if (expected
->line
!= actual
->line
&& todo
)
380 ok_(file
, line
) (FALSE
,
381 "%s: in event %s expecting line %d got %d\n",
382 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
387 ok_(file
, line
) (expected
->line
== actual
->line
,
388 "%s: in event %s expecting line %d got %d\n",
389 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
394 if (expected
->column
!= -1)
396 if (expected
->column
!= actual
->column
&& todo
)
401 ok_(file
, line
) (FALSE
,
402 "%s: in event %s expecting column %d got %d\n",
403 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
408 ok_(file
, line
) (expected
->column
== actual
->column
,
409 "%s: in event %s expecting column %d got %d\n",
410 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
416 case CH_PUTDOCUMENTLOCATOR
:
417 case CH_STARTDOCUMENT
:
422 case CH_STARTPREFIXMAPPING
:
424 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
425 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
427 case CH_ENDPREFIXMAPPING
:
429 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
431 case CH_STARTELEMENT
:
432 /* compare attributes */
433 compare_attributes(actual
, expected
, context
, todo
, file
, line
, &failcount
);
436 /* uri, localname, qname */
437 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
438 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
439 test_saxstr(file
, line
, actual
->arg3W
, expected
->arg3
, todo
, &failcount
);
442 case CH_IGNORABLEWHITESPACE
:
444 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
446 case CH_PROCESSINGINSTRUCTION
:
448 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
449 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
451 case CH_SKIPPEDENTITY
:
453 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
456 /* test return value only */
457 if (expected
->ret
!= actual
->ret
&& todo
)
460 ok_(file
, line
) (FALSE
,
461 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
462 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
465 ok_(file
, line
) (expected
->ret
== actual
->ret
,
466 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
467 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
470 case EH_IGNORABLEWARNING
:
472 ok(0, "%s: callback not handled, %s\n", context
, get_event_name(actual
->id
));
482 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
483 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
486 flush_sequence(seq
, sequence_index
);
491 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
492 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
502 if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
505 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
506 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
510 else if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
512 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
513 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
516 if (todo
&& !failcount
) /* succeeded yet marked todo */
520 ok_(file
, line
)(TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
524 flush_sequence(seq
, sequence_index
);
527 #define ok_sequence(seq, index, exp, contx, todo) \
528 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
530 static void init_call_sequences(struct call_sequence
**seq
, int n
)
534 for (i
= 0; i
< n
; i
++)
535 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct call_sequence
));
538 static const WCHAR szSimpleXML
[] = {
539 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
540 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
541 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
542 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
543 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
546 static const WCHAR carriage_ret_test
[] = {
547 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
548 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
549 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
550 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
551 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
554 static const WCHAR szUtf16XML
[] = {
555 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
556 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
557 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
560 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
562 static const CHAR szUtf8XML
[] =
563 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
565 static const char utf8xml2
[] =
566 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n";
568 static const char testXML
[] =
569 "<?xml version=\"1.0\" ?>\n"
571 " <Number>1234</Number>\n"
572 " <Name>Captain Ahab</Name>\n"
575 static const char test_attributes
[] =
576 "<?xml version=\"1.0\" ?>\n"
577 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
578 "<node1 xmlns:p=\"test\" />"
581 static const char test_cdata_xml
[] =
582 "<?xml version=\"1.0\" ?>"
583 "<a><![CDATA[Some \r\ntext\n\r\ndata\n\n]]></a>";
585 static const char test2_cdata_xml
[] =
586 "<?xml version=\"1.0\" ?>"
587 "<a><![CDATA[\n\r\nSome \r\ntext\n\r\ndata\n\n]]></a>";
589 static const char test3_cdata_xml
[] =
590 "<?xml version=\"1.0\" ?><a><![CDATA[Some text data]]></a>";
592 static struct call_entry content_handler_test1
[] = {
593 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
594 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
595 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
596 { CH_CHARACTERS
, 2, 14, S_OK
, "\n " },
597 { CH_STARTELEMENT
, 3, 12, S_OK
, "", "Number", "Number" },
598 { CH_CHARACTERS
, 3, 12, S_OK
, "1234" },
599 { CH_ENDELEMENT
, 3, 18, S_OK
, "", "Number", "Number" },
600 { CH_CHARACTERS
, 3, 25, S_OK
, "\n " },
601 { CH_STARTELEMENT
, 4, 10, S_OK
, "", "Name", "Name" },
602 { CH_CHARACTERS
, 4, 10, S_OK
, "Captain Ahab" },
603 { CH_ENDELEMENT
, 4, 24, S_OK
, "", "Name", "Name" },
604 { CH_CHARACTERS
, 4, 29, S_OK
, "\n" },
605 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
606 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
610 /* applies to versions 4 and 6 */
611 static struct call_entry content_handler_test1_alternate
[] = {
612 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
613 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
614 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
615 { CH_CHARACTERS
, 3, 4, S_OK
, "\n " },
616 { CH_STARTELEMENT
, 3, 11, S_OK
, "", "Number", "Number" },
617 { CH_CHARACTERS
, 3, 16, S_OK
, "1234" },
618 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "Number", "Number" },
619 { CH_CHARACTERS
, 4, 4, S_OK
, "\n " },
620 { CH_STARTELEMENT
, 4, 9, S_OK
, "", "Name", "Name" },
621 { CH_CHARACTERS
, 4, 22, S_OK
, "Captain Ahab" },
622 { CH_ENDELEMENT
, 4, 28, S_OK
, "", "Name", "Name" },
623 { CH_CHARACTERS
, 5, 1, S_OK
, "\n" },
624 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
625 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
629 static struct call_entry content_handler_test2
[] = {
630 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
631 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
632 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
633 { CH_CHARACTERS
, 2, 14, S_OK
, "\n" },
634 { CH_CHARACTERS
, 2, 16, S_OK
, "\t" },
635 { CH_STARTELEMENT
, 3, 10, S_OK
, "", "Number", "Number" },
636 { CH_CHARACTERS
, 3, 10, S_OK
, "1234" },
637 { CH_ENDELEMENT
, 3, 16, S_OK
, "", "Number", "Number" },
638 { CH_CHARACTERS
, 3, 23, S_OK
, "\n" },
639 { CH_CHARACTERS
, 3, 25, S_OK
, "\t" },
640 { CH_STARTELEMENT
, 4, 8, S_OK
, "", "Name", "Name" },
641 { CH_CHARACTERS
, 4, 8, S_OK
, "Captain Ahab" },
642 { CH_ENDELEMENT
, 4, 22, S_OK
, "", "Name", "Name" },
643 { CH_CHARACTERS
, 4, 27, S_OK
, "\n" },
644 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
645 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
649 static struct call_entry content_handler_test2_alternate
[] = {
650 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
651 { CH_STARTDOCUMENT
, 1, 21, S_OK
},
652 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
653 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
654 { CH_CHARACTERS
, 3, 2, S_OK
, "\t" },
655 { CH_STARTELEMENT
, 3, 9, S_OK
, "", "Number", "Number" },
656 { CH_CHARACTERS
, 3, 14, S_OK
, "1234" },
657 { CH_ENDELEMENT
, 3, 22, S_OK
, "", "Number", "Number" },
658 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
659 { CH_CHARACTERS
, 4, 2, S_OK
, "\t" },
660 { CH_STARTELEMENT
, 4, 7, S_OK
, "", "Name", "Name" },
661 { CH_CHARACTERS
, 4, 20, S_OK
, "Captain Ahab" },
662 { CH_ENDELEMENT
, 4, 26, S_OK
, "", "Name", "Name" },
663 { CH_CHARACTERS
, 5, 0, S_OK
, "\n" },
664 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
665 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
669 static struct call_entry content_handler_testerror
[] = {
670 { CH_PUTDOCUMENTLOCATOR
, 0, 0, E_FAIL
},
671 { EH_FATALERROR
, 0, 0, E_FAIL
},
675 static struct call_entry content_handler_testerror_alternate
[] = {
676 { CH_PUTDOCUMENTLOCATOR
, 1, 0, E_FAIL
},
677 { EH_FATALERROR
, 1, 0, E_FAIL
},
681 static struct call_entry content_handler_test_callback_rets
[] = {
682 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_FALSE
},
683 { CH_STARTDOCUMENT
, 0, 0, S_FALSE
},
684 { EH_FATALERROR
, 0, 0, S_FALSE
},
688 static struct call_entry content_handler_test_callback_rets_alt
[] = {
689 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_FALSE
},
690 { CH_STARTDOCUMENT
, 1, 22, S_FALSE
},
691 { CH_STARTELEMENT
, 2, 13, S_FALSE
, "", "BankAccount", "BankAccount" },
692 { CH_CHARACTERS
, 3, 4, S_FALSE
, "\n " },
693 { CH_STARTELEMENT
, 3, 11, S_FALSE
, "", "Number", "Number" },
694 { CH_CHARACTERS
, 3, 16, S_FALSE
, "1234" },
695 { CH_ENDELEMENT
, 3, 24, S_FALSE
, "", "Number", "Number" },
696 { CH_CHARACTERS
, 4, 4, S_FALSE
, "\n " },
697 { CH_STARTELEMENT
, 4, 9, S_FALSE
, "", "Name", "Name" },
698 { CH_CHARACTERS
, 4, 22, S_FALSE
, "Captain Ahab" },
699 { CH_ENDELEMENT
, 4, 28, S_FALSE
, "", "Name", "Name" },
700 { CH_CHARACTERS
, 5, 1, S_FALSE
, "\n" },
701 { CH_ENDELEMENT
, 5, 14, S_FALSE
, "", "BankAccount", "BankAccount" },
702 { CH_ENDDOCUMENT
, 6, 0, S_FALSE
},
706 static struct attribute_entry ch_attributes1
[] = {
707 { "", "", "xmlns:test", "prefix_test" },
708 { "", "", "xmlns", "prefix" },
709 { "prefix_test", "arg1", "test:arg1", "arg1" },
710 { "", "arg2", "arg2", "arg2" },
711 { "prefix_test", "ar3", "test:ar3", "arg3" },
715 static struct attribute_entry ch_attributes2
[] = {
716 { "", "", "xmlns:p", "test" },
720 static struct call_entry content_handler_test_attributes
[] = {
721 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
722 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
723 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
724 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
725 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes1
},
726 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
727 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
728 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
729 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
730 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
731 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
732 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
733 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
734 { CH_ENDDOCUMENT
, 0, 0 },
738 static struct attribute_entry ch_attributes_alt_4
[] = {
739 { "prefix_test", "arg1", "test:arg1", "arg1" },
740 { "", "arg2", "arg2", "arg2" },
741 { "prefix_test", "ar3", "test:ar3", "arg3" },
742 { "", "", "xmlns:test", "prefix_test" },
743 { "", "", "xmlns", "prefix" },
747 static struct call_entry content_handler_test_attributes_alternate_4
[] = {
748 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
749 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
750 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
751 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
752 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_4
},
753 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
754 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
755 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
756 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
757 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
758 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
759 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
760 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
761 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
765 /* 'namespace' feature switched off */
766 static struct attribute_entry ch_attributes_alt_no_ns
[] = {
767 { "", "", "xmlns:test", "prefix_test" },
768 { "", "", "xmlns", "prefix" },
769 { "", "", "test:arg1", "arg1" },
770 { "", "", "arg2", "arg2" },
771 { "", "", "test:ar3", "arg3" },
775 static struct call_entry content_handler_test_attributes_alt_no_ns
[] = {
776 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
777 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
778 { CH_STARTELEMENT
, 2, 95, S_OK
, "", "", "document", ch_attributes_alt_no_ns
},
779 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
780 { CH_STARTELEMENT
, 3, 24, S_OK
, "", "", "node1", ch_attributes2
},
781 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "", "node1" },
782 { CH_ENDELEMENT
, 3, 35, S_OK
, "", "", "document" },
783 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
787 static struct attribute_entry ch_attributes_alt_6
[] = {
788 { "prefix_test", "arg1", "test:arg1", "arg1" },
789 { "", "arg2", "arg2", "arg2" },
790 { "prefix_test", "ar3", "test:ar3", "arg3" },
791 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
792 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
796 static struct attribute_entry ch_attributes2_6
[] = {
797 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
801 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
802 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
803 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
804 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
805 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
806 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
807 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
808 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
809 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
810 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
811 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
812 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
813 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
814 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
815 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
819 /* 'namespaces' is on, 'namespace-prefixes' if off */
820 static struct attribute_entry ch_attributes_no_prefix
[] = {
821 { "prefix_test", "arg1", "test:arg1", "arg1" },
822 { "", "arg2", "arg2", "arg2" },
823 { "prefix_test", "ar3", "test:ar3", "arg3" },
827 static struct call_entry content_handler_test_attributes_alt_no_prefix
[] = {
828 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
829 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
830 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
831 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
832 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
833 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
834 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
835 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", NULL
},
836 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
837 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
838 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
839 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
840 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
841 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
845 static struct call_entry content_handler_test_attributes_no_prefix
[] = {
846 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
847 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
848 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
849 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
850 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
851 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
852 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
853 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", NULL
},
854 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
855 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
856 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
857 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
858 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
859 { CH_ENDDOCUMENT
, 0, 0 },
863 static struct attribute_entry xmlspace_attrs
[] = {
864 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
868 static struct call_entry xmlspaceattr_test
[] = {
869 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
870 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
871 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
872 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
873 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
874 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
878 static struct call_entry xmlspaceattr_test_alternate
[] = {
879 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
880 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
881 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
882 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
883 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
884 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
888 /* attribute value normalization test */
889 static const char attribute_normalize
[] =
890 "<?xml version=\"1.0\" ?>\n"
891 "<a attr1=\" \r \n \tattr_value A & &\t \r \n\r\n \n\"/>\n";
893 static struct attribute_entry attribute_norm_attrs
[] = {
894 { "", "attr1", "attr1", " attr_value A & & " },
898 static struct call_entry attribute_norm
[] = {
899 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
900 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
901 { CH_STARTELEMENT
, 6, 4, S_OK
, "", "a", "a", attribute_norm_attrs
},
902 { CH_ENDELEMENT
, 6, 4, S_OK
, "", "a", "a" },
903 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
907 static struct call_entry attribute_norm_alt
[] = {
908 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
909 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
910 { CH_STARTELEMENT
, 8, 3, S_OK
, "", "a", "a", attribute_norm_attrs
},
911 { CH_ENDELEMENT
, 8, 3, S_OK
, "", "a", "a" },
912 { CH_ENDDOCUMENT
, 9, 0, S_OK
},
916 static struct call_entry cdata_test
[] = {
917 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
918 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
919 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
920 { LH_STARTCDATA
, 1, 35, S_OK
},
921 { CH_CHARACTERS
, 1, 35, S_OK
, "Some \n" },
922 { CH_CHARACTERS
, 1, 42, S_OK
, "text\n\n" },
923 { CH_CHARACTERS
, 1, 49, S_OK
, "data\n\n" },
924 { LH_ENDCDATA
, 1, 49, S_OK
},
925 { CH_ENDELEMENT
, 6, 6, S_OK
, "", "a", "a" },
926 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
930 static struct call_entry cdata_test2
[] = {
931 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
932 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
933 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
934 { LH_STARTCDATA
, 1, 35, S_OK
},
935 { CH_CHARACTERS
, 1, 35, S_OK
, "\n\n" },
936 { CH_CHARACTERS
, 1, 38, S_OK
, "Some \n" },
937 { CH_CHARACTERS
, 1, 45, S_OK
, "text\n\n" },
938 { CH_CHARACTERS
, 1, 52, S_OK
, "data\n\n" },
939 { LH_ENDCDATA
, 1, 52, S_OK
},
940 { CH_ENDELEMENT
, 8, 6, S_OK
, "", "a", "a" },
941 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
945 static struct call_entry cdata_test3
[] = {
946 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
947 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
948 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
949 { LH_STARTCDATA
, 1, 35, S_OK
},
950 { CH_CHARACTERS
, 1, 35, S_OK
, "Some text data" },
951 { LH_ENDCDATA
, 1, 35, S_OK
},
952 { CH_ENDELEMENT
, 1, 54, S_OK
, "", "a", "a" },
953 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
957 /* this is what MSXML6 does */
958 static struct call_entry cdata_test_alt
[] = {
959 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
960 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
961 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
962 { LH_STARTCDATA
, 1, 34, S_OK
},
963 { CH_CHARACTERS
, 1, 40, S_OK
, "Some " },
964 { CH_CHARACTERS
, 2, 0, S_OK
, "\n" },
965 { CH_CHARACTERS
, 3, 1, S_OK
, "text\n" },
966 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
967 { CH_CHARACTERS
, 6, 3, S_OK
, "data\n\n" },
968 { LH_ENDCDATA
, 6, 3, S_OK
},
969 { CH_ENDELEMENT
, 6, 7, S_OK
, "", "a", "a" },
970 { CH_ENDDOCUMENT
, 6, 7, S_OK
},
974 static struct call_entry cdata_test2_alt
[] = {
975 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
976 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
977 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
978 { LH_STARTCDATA
, 1, 34, S_OK
},
979 { CH_CHARACTERS
, 2, 1, S_OK
, "\n" },
980 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
981 { CH_CHARACTERS
, 3, 6, S_OK
, "Some " },
982 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
983 { CH_CHARACTERS
, 5, 1, S_OK
, "text\n" },
984 { CH_CHARACTERS
, 6, 0, S_OK
, "\n" },
985 { CH_CHARACTERS
, 8, 3, S_OK
, "data\n\n" },
986 { LH_ENDCDATA
, 8, 3, S_OK
},
987 { CH_ENDELEMENT
, 8, 7, S_OK
, "", "a", "a" },
988 { CH_ENDDOCUMENT
, 8, 7, S_OK
},
992 static struct call_entry cdata_test3_alt
[] = {
993 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
994 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
995 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
996 { LH_STARTCDATA
, 1, 34, S_OK
},
997 { CH_CHARACTERS
, 1, 51, S_OK
, "Some text data" },
998 { LH_ENDCDATA
, 1, 51, S_OK
},
999 { CH_ENDELEMENT
, 1, 55, S_OK
, "", "a", "a" },
1000 { CH_ENDDOCUMENT
, 1, 55, S_OK
},
1004 static struct attribute_entry read_test_attrs
[] = {
1005 { "", "attr", "attr", "val" },
1009 static struct call_entry read_test_seq
[] = {
1010 { CH_PUTDOCUMENTLOCATOR
, -1, 0, S_OK
},
1011 { CH_STARTDOCUMENT
, -1, -1, S_OK
},
1012 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1013 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1014 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1015 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1016 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1017 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1018 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1019 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1020 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1021 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1022 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1023 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1024 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1025 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1026 { CH_ENDDOCUMENT
, -1, -1, S_OK
},
1030 static const char xmlspace_attr
[] =
1031 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
1032 "<a xml:space=\"preserve\"> Some text data </a>";
1034 static struct call_entry
*expectCall
;
1035 static ISAXLocator
*locator
;
1036 static ISAXXMLReader
*g_reader
;
1039 static void set_expected_seq(struct call_entry
*expected
)
1041 expectCall
= expected
;
1044 /* to be called once on each tested callback return */
1045 static HRESULT
get_expected_ret(void)
1047 HRESULT hr
= expectCall
->ret
;
1048 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
1052 static HRESULT WINAPI
contentHandler_QueryInterface(
1053 ISAXContentHandler
* iface
,
1059 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
1065 return E_NOINTERFACE
;
1071 static ULONG WINAPI
contentHandler_AddRef(
1072 ISAXContentHandler
* iface
)
1077 static ULONG WINAPI
contentHandler_Release(
1078 ISAXContentHandler
* iface
)
1083 static HRESULT WINAPI
contentHandler_putDocumentLocator(
1084 ISAXContentHandler
* iface
,
1085 ISAXLocator
*pLocator
)
1087 struct call_entry call
;
1093 init_call_entry(locator
, &call
);
1094 call
.id
= CH_PUTDOCUMENTLOCATOR
;
1095 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1097 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXLocator
, (void**)&unk
);
1098 EXPECT_HR(hr
, E_NOINTERFACE
);
1100 if (msxml_version
>= 6) {
1101 ISAXAttributes
*attr
, *attr1
;
1102 IMXAttributes
*mxattr
;
1104 EXPECT_REF(pLocator
, 1);
1105 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
1106 EXPECT_HR(hr
, S_OK
);
1107 EXPECT_REF(pLocator
, 2);
1108 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
1109 EXPECT_HR(hr
, S_OK
);
1110 EXPECT_REF(pLocator
, 3);
1111 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
1113 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IVBSAXAttributes
, (void**)&unk
);
1114 EXPECT_HR(hr
, E_NOINTERFACE
);
1116 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXAttributes
, (void**)&unk
);
1117 EXPECT_HR(hr
, E_NOINTERFACE
);
1119 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
1120 EXPECT_HR(hr
, E_NOINTERFACE
);
1122 ISAXAttributes_Release(attr
);
1123 ISAXAttributes_Release(attr1
);
1126 return get_expected_ret();
1129 static ISAXAttributes
*test_attr_ptr
;
1130 static HRESULT WINAPI
contentHandler_startDocument(
1131 ISAXContentHandler
* iface
)
1133 struct call_entry call
;
1135 init_call_entry(locator
, &call
);
1136 call
.id
= CH_STARTDOCUMENT
;
1137 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1139 test_attr_ptr
= NULL
;
1141 return get_expected_ret();
1144 static HRESULT WINAPI
contentHandler_endDocument(
1145 ISAXContentHandler
* iface
)
1147 struct call_entry call
;
1149 init_call_entry(locator
, &call
);
1150 call
.id
= CH_ENDDOCUMENT
;
1151 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1153 return get_expected_ret();
1156 static HRESULT WINAPI
contentHandler_startPrefixMapping(
1157 ISAXContentHandler
* iface
,
1158 const WCHAR
*prefix
, int prefix_len
,
1159 const WCHAR
*uri
, int uri_len
)
1161 struct call_entry call
;
1163 init_call_entry(locator
, &call
);
1164 call
.id
= CH_STARTPREFIXMAPPING
;
1165 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
1166 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
1167 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1169 return get_expected_ret();
1172 static HRESULT WINAPI
contentHandler_endPrefixMapping(
1173 ISAXContentHandler
* iface
,
1174 const WCHAR
*prefix
, int len
)
1176 struct call_entry call
;
1178 init_call_entry(locator
, &call
);
1179 call
.id
= CH_ENDPREFIXMAPPING
;
1180 call
.arg1W
= SysAllocStringLen(prefix
, len
);
1181 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1183 return get_expected_ret();
1186 static HRESULT WINAPI
contentHandler_startElement(
1187 ISAXContentHandler
* iface
,
1188 const WCHAR
*uri
, int uri_len
,
1189 const WCHAR
*localname
, int local_len
,
1190 const WCHAR
*qname
, int qname_len
,
1191 ISAXAttributes
*saxattr
)
1193 struct call_entry call
;
1194 IMXAttributes
*mxattr
;
1198 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
1199 EXPECT_HR(hr
, E_NOINTERFACE
);
1201 init_call_entry(locator
, &call
);
1202 call
.id
= CH_STARTELEMENT
;
1203 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1204 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1205 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1208 test_attr_ptr
= saxattr
;
1209 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
1211 /* store actual attributes */
1213 hr
= ISAXAttributes_getLength(saxattr
, &len
);
1214 EXPECT_HR(hr
, S_OK
);
1221 struct attribute_entry
*attr
;
1222 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
1225 hr
= ISAXXMLReader_getFeature(g_reader
, _bstr_("http://xml.org/sax/features/namespaces"), &v
);
1226 EXPECT_HR(hr
, S_OK
);
1228 for (i
= 0; i
< len
; i
++)
1233 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
1234 &localname
, &local_len
, &qname
, &qname_len
);
1235 EXPECT_HR(hr
, S_OK
);
1237 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
1238 EXPECT_HR(hr
, S_OK
);
1240 /* if 'namespaces' switched off uri and local name contains garbage */
1241 if (v
== VARIANT_FALSE
&& msxml_version
> 0)
1243 attr
[i
].uriW
= SysAllocStringLen(NULL
, 0);
1244 attr
[i
].localW
= SysAllocStringLen(NULL
, 0);
1248 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
1249 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
1252 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
1253 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
1256 call
.attributes
= attr
;
1257 call
.attr_count
= len
;
1260 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1262 return get_expected_ret();
1265 static HRESULT WINAPI
contentHandler_endElement(
1266 ISAXContentHandler
* iface
,
1267 const WCHAR
*uri
, int uri_len
,
1268 const WCHAR
*localname
, int local_len
,
1269 const WCHAR
*qname
, int qname_len
)
1271 struct call_entry call
;
1273 init_call_entry(locator
, &call
);
1274 call
.id
= CH_ENDELEMENT
;
1275 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1276 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1277 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1278 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1280 return get_expected_ret();
1283 static HRESULT WINAPI
contentHandler_characters(
1284 ISAXContentHandler
* iface
,
1288 struct call_entry call
;
1290 init_call_entry(locator
, &call
);
1291 call
.id
= CH_CHARACTERS
;
1292 call
.arg1W
= SysAllocStringLen(chars
, len
);
1293 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1295 return get_expected_ret();
1298 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1299 ISAXContentHandler
* iface
,
1300 const WCHAR
*chars
, int len
)
1302 struct call_entry call
;
1304 init_call_entry(locator
, &call
);
1305 call
.id
= CH_IGNORABLEWHITESPACE
;
1306 call
.arg1W
= SysAllocStringLen(chars
, len
);
1307 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1309 return get_expected_ret();
1312 static HRESULT WINAPI
contentHandler_processingInstruction(
1313 ISAXContentHandler
* iface
,
1314 const WCHAR
*target
, int target_len
,
1315 const WCHAR
*data
, int data_len
)
1317 struct call_entry call
;
1319 init_call_entry(locator
, &call
);
1320 call
.id
= CH_PROCESSINGINSTRUCTION
;
1321 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1322 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1323 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1325 return get_expected_ret();
1328 static HRESULT WINAPI
contentHandler_skippedEntity(
1329 ISAXContentHandler
* iface
,
1330 const WCHAR
*name
, int len
)
1332 struct call_entry call
;
1334 init_call_entry(locator
, &call
);
1335 call
.id
= CH_SKIPPEDENTITY
;
1336 call
.arg1W
= SysAllocStringLen(name
, len
);
1337 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1339 return get_expected_ret();
1342 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1344 contentHandler_QueryInterface
,
1345 contentHandler_AddRef
,
1346 contentHandler_Release
,
1347 contentHandler_putDocumentLocator
,
1348 contentHandler_startDocument
,
1349 contentHandler_endDocument
,
1350 contentHandler_startPrefixMapping
,
1351 contentHandler_endPrefixMapping
,
1352 contentHandler_startElement
,
1353 contentHandler_endElement
,
1354 contentHandler_characters
,
1355 contentHandler_ignorableWhitespace
,
1356 contentHandler_processingInstruction
,
1357 contentHandler_skippedEntity
1360 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1362 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1363 ISAXErrorHandler
* iface
,
1369 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1375 return E_NOINTERFACE
;
1381 static ULONG WINAPI
isaxerrorHandler_AddRef(
1382 ISAXErrorHandler
* iface
)
1387 static ULONG WINAPI
isaxerrorHandler_Release(
1388 ISAXErrorHandler
* iface
)
1393 static HRESULT WINAPI
isaxerrorHandler_error(
1394 ISAXErrorHandler
* iface
,
1395 ISAXLocator
*pLocator
,
1396 const WCHAR
*pErrorMessage
,
1397 HRESULT hrErrorCode
)
1399 ok(0, "unexpected call\n");
1403 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1404 ISAXErrorHandler
* iface
,
1405 ISAXLocator
*pLocator
,
1406 const WCHAR
*message
,
1409 struct call_entry call
;
1411 init_call_entry(locator
, &call
);
1412 call
.id
= EH_FATALERROR
;
1415 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1421 static HRESULT WINAPI
isaxerrorHandler_ignorableWarning(
1422 ISAXErrorHandler
* iface
,
1423 ISAXLocator
*pLocator
,
1424 const WCHAR
*pErrorMessage
,
1425 HRESULT hrErrorCode
)
1427 ok(0, "unexpected call\n");
1431 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1433 isaxerrorHandler_QueryInterface
,
1434 isaxerrorHandler_AddRef
,
1435 isaxerrorHandler_Release
,
1436 isaxerrorHandler_error
,
1437 isaxerrorHandler_fatalError
,
1438 isaxerrorHandler_ignorableWarning
1441 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1443 static HRESULT WINAPI
isaxattributes_QueryInterface(
1444 ISAXAttributes
* iface
,
1450 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1456 return E_NOINTERFACE
;
1462 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1467 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1472 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1478 static HRESULT WINAPI
isaxattributes_getURI(
1479 ISAXAttributes
* iface
,
1484 ok(0, "unexpected call\n");
1488 static HRESULT WINAPI
isaxattributes_getLocalName(
1489 ISAXAttributes
* iface
,
1491 const WCHAR
**pLocalName
,
1492 int *pLocalNameLength
)
1494 ok(0, "unexpected call\n");
1498 static HRESULT WINAPI
isaxattributes_getQName(
1499 ISAXAttributes
* iface
,
1501 const WCHAR
**QName
,
1504 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1505 {'a','t','t','r','2','j','u','n','k',0},
1506 {'a','t','t','r','3',0}};
1507 static const int attrqnamelen
[] = {7, 5, 5};
1509 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1511 if (index
>= 0 && index
<= 2) {
1512 *QName
= attrqnamesW
[index
];
1513 *QNameLength
= attrqnamelen
[index
];
1522 static HRESULT WINAPI
isaxattributes_getName(
1523 ISAXAttributes
* iface
,
1527 const WCHAR
** pLocalName
,
1528 int * pLocalNameSize
,
1529 const WCHAR
** pQName
,
1532 ok(0, "unexpected call\n");
1536 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1537 ISAXAttributes
* iface
,
1540 const WCHAR
* pLocalName
,
1541 int cocalNameLength
,
1544 ok(0, "unexpected call\n");
1548 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1549 ISAXAttributes
* iface
,
1550 const WCHAR
* pQName
,
1554 ok(0, "unexpected call\n");
1558 static HRESULT WINAPI
isaxattributes_getType(
1559 ISAXAttributes
* iface
,
1561 const WCHAR
** pType
,
1564 ok(0, "unexpected call\n");
1568 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1569 ISAXAttributes
* iface
,
1572 const WCHAR
* pLocalName
,
1574 const WCHAR
** pType
,
1577 ok(0, "unexpected call\n");
1581 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1582 ISAXAttributes
* iface
,
1583 const WCHAR
* pQName
,
1585 const WCHAR
** pType
,
1588 ok(0, "unexpected call\n");
1592 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1593 const WCHAR
**value
, int *nValue
)
1595 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1596 {'a','2','j','u','n','k',0},
1597 {'<','&','"','>','\'',0}};
1598 static const int attrvalueslen
[] = {2, 2, 5};
1600 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1602 if (index
>= 0 && index
<= 2) {
1603 *value
= attrvaluesW
[index
];
1604 *nValue
= attrvalueslen
[index
];
1613 static HRESULT WINAPI
isaxattributes_getValueFromName(
1614 ISAXAttributes
* iface
,
1617 const WCHAR
* pLocalName
,
1619 const WCHAR
** pValue
,
1622 ok(0, "unexpected call\n");
1626 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1627 ISAXAttributes
* iface
,
1628 const WCHAR
* pQName
,
1630 const WCHAR
** pValue
,
1633 ok(0, "unexpected call\n");
1637 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1639 isaxattributes_QueryInterface
,
1640 isaxattributes_AddRef
,
1641 isaxattributes_Release
,
1642 isaxattributes_getLength
,
1643 isaxattributes_getURI
,
1644 isaxattributes_getLocalName
,
1645 isaxattributes_getQName
,
1646 isaxattributes_getName
,
1647 isaxattributes_getIndexFromName
,
1648 isaxattributes_getIndexFromQName
,
1649 isaxattributes_getType
,
1650 isaxattributes_getTypeFromName
,
1651 isaxattributes_getTypeFromQName
,
1652 isaxattributes_getValue
,
1653 isaxattributes_getValueFromName
,
1654 isaxattributes_getValueFromQName
1657 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1659 struct saxlexicalhandler
1661 ISAXLexicalHandler ISAXLexicalHandler_iface
;
1664 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1667 static inline struct saxlexicalhandler
*impl_from_ISAXLexicalHandler( ISAXLexicalHandler
*iface
)
1669 return CONTAINING_RECORD(iface
, struct saxlexicalhandler
, ISAXLexicalHandler_iface
);
1672 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **out
)
1674 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1678 if (IsEqualGUID(riid
, &IID_IUnknown
))
1681 ok(0, "got unexpected IID_IUnknown query\n");
1683 else if (IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1685 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1690 ISAXLexicalHandler_AddRef(iface
);
1692 return E_NOINTERFACE
;
1697 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1699 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1700 return InterlockedIncrement(&handler
->ref
);
1703 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1705 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1706 return InterlockedDecrement(&handler
->ref
);
1709 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1710 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1711 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1713 ok(0, "call not expected\n");
1717 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1719 ok(0, "call not expected\n");
1723 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1724 const WCHAR
* pName
, int nName
)
1726 ok(0, "call not expected\n");
1730 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1731 const WCHAR
* pName
, int nName
)
1733 ok(0, "call not expected\n");
1737 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1739 struct call_entry call
;
1741 init_call_entry(locator
, &call
);
1742 call
.id
= LH_STARTCDATA
;
1743 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1745 return get_expected_ret();
1748 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1750 struct call_entry call
;
1752 init_call_entry(locator
, &call
);
1753 call
.id
= LH_ENDCDATA
;
1754 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1756 return get_expected_ret();
1759 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1760 const WCHAR
* pChars
, int nChars
)
1762 ok(0, "call not expected\n");
1766 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1768 isaxlexical_QueryInterface
,
1770 isaxlexical_Release
,
1771 isaxlexical_startDTD
,
1773 isaxlexical_startEntity
,
1774 isaxlexical_endEntity
,
1775 isaxlexical_startCDATA
,
1776 isaxlexical_endCDATA
,
1780 static void init_saxlexicalhandler(struct saxlexicalhandler
*handler
, HRESULT hr
)
1782 handler
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1784 handler
->qi_hr
= hr
;
1787 struct saxdeclhandler
1789 ISAXDeclHandler ISAXDeclHandler_iface
;
1792 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1795 static inline struct saxdeclhandler
*impl_from_ISAXDeclHandler( ISAXDeclHandler
*iface
)
1797 return CONTAINING_RECORD(iface
, struct saxdeclhandler
, ISAXDeclHandler_iface
);
1800 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **out
)
1802 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1806 if (IsEqualGUID(riid
, &IID_IUnknown
))
1809 ok(0, "got unexpected IID_IUnknown query\n");
1811 else if (IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1813 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1818 ISAXDeclHandler_AddRef(iface
);
1820 return E_NOINTERFACE
;
1825 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1827 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1828 return InterlockedIncrement(&handler
->ref
);
1831 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1833 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1834 return InterlockedDecrement(&handler
->ref
);
1837 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1838 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1840 ok(0, "call not expected\n");
1844 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1845 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1846 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1847 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1849 ok(0, "call not expected\n");
1853 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1854 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1856 ok(0, "call not expected\n");
1860 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1861 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1862 const WCHAR
* pSystemId
, int nSystemId
)
1864 ok(0, "call not expected\n");
1868 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1870 isaxdecl_QueryInterface
,
1873 isaxdecl_elementDecl
,
1874 isaxdecl_attributeDecl
,
1875 isaxdecl_internalEntityDecl
,
1876 isaxdecl_externalEntityDecl
1879 static void init_saxdeclhandler(struct saxdeclhandler
*handler
, HRESULT hr
)
1881 handler
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1883 handler
->qi_hr
= hr
;
1886 typedef struct mxwriter_write_test_t
{
1892 } mxwriter_write_test
;
1894 typedef struct mxwriter_stream_test_t
{
1896 const char *encoding
;
1897 mxwriter_write_test expected_writes
[4];
1898 } mxwriter_stream_test
;
1900 static const mxwriter_write_test
*current_write_test
;
1901 static DWORD current_stream_test_index
;
1903 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1907 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1910 return E_NOINTERFACE
;
1915 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1920 static ULONG WINAPI
istream_Release(IStream
*iface
)
1925 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1927 ok(0, "unexpected call\n");
1931 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1933 ok(0, "unexpected call\n");
1937 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1938 ULARGE_INTEGER
*plibNewPosition
)
1940 ok(0, "unexpected call\n");
1944 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1946 ok(0, "unexpected call\n");
1950 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1951 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1953 ok(0, "unexpected call\n");
1957 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1959 ok(0, "unexpected call\n");
1963 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1965 ok(0, "unexpected call\n");
1969 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1970 ULARGE_INTEGER cb
, DWORD dwLockType
)
1972 ok(0, "unexpected call\n");
1976 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1977 ULARGE_INTEGER cb
, DWORD dwLockType
)
1979 ok(0, "unexpected call\n");
1983 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1988 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1990 ok(0, "unexpected call\n");
1994 static HRESULT WINAPI
mxstream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1998 ok(pv
!= NULL
, "pv == NULL\n");
2000 if(current_write_test
->last
) {
2001 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
2005 fail
= current_write_test
->fail_write
;
2007 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
2008 current_write_test
->cb
, cb
, current_stream_test_index
);
2011 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
2013 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
2015 ++current_write_test
;
2020 return fail
? E_FAIL
: S_OK
;
2023 static const IStreamVtbl mxstreamVtbl
= {
2024 istream_QueryInterface
,
2035 istream_UnlockRegion
,
2040 static IStream mxstream
= { &mxstreamVtbl
};
2042 static int read_cnt
;
2044 static HRESULT WINAPI
instream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
2046 static const char *ret_str
;
2049 ret_str
= "<?xml version=\"1.0\" ?>\n<rootelem>";
2050 else if(read_cnt
< 5)
2051 ret_str
= "<elem attr=\"val\">text</elem>";
2052 else if(read_cnt
== 5)
2053 ret_str
= "</rootelem>\n";
2058 strcpy(pv
, ret_str
);
2059 *pcbRead
= strlen(ret_str
);
2063 static const IStreamVtbl instreamVtbl
= {
2064 istream_QueryInterface
,
2075 istream_UnlockRegion
,
2080 static IStream instream
= { &instreamVtbl
};
2082 static struct msxmlsupported_data_t reader_support_data
[] =
2084 { &CLSID_SAXXMLReader
, "SAXReader" },
2085 { &CLSID_SAXXMLReader30
, "SAXReader30" },
2086 { &CLSID_SAXXMLReader40
, "SAXReader40" },
2087 { &CLSID_SAXXMLReader60
, "SAXReader60" },
2091 static struct saxlexicalhandler lexicalhandler
;
2092 static struct saxdeclhandler declhandler
;
2094 static IStream
*create_test_stream(const char *data
, int len
)
2096 ULARGE_INTEGER size
;
2101 if (len
== -1) len
= strlen(data
);
2102 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2103 size
.QuadPart
= len
;
2104 IStream_SetSize(stream
, size
);
2105 IStream_Write(stream
, data
, len
, &written
);
2107 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2112 static void test_saxreader(void)
2114 const struct msxmlsupported_data_t
*table
= reader_support_data
;
2116 ISAXXMLReader
*reader
= NULL
;
2118 ISAXContentHandler
*content
;
2119 ISAXErrorHandler
*lpErrorHandler
;
2121 SAFEARRAYBOUND SADim
[1];
2126 static const CHAR testXmlA
[] = "test.xml";
2127 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2128 IXMLDOMDocument
*doc
;
2132 while (table
->clsid
)
2134 struct call_entry
*test_seq
;
2135 ISAXEntityResolver
*resolver
;
2138 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
2144 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2145 EXPECT_HR(hr
, S_OK
);
2148 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2150 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2155 /* crashes on old versions */
2156 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
2157 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2159 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
2160 EXPECT_HR(hr
, E_POINTER
);
2162 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
2163 EXPECT_HR(hr
, E_POINTER
);
2166 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2167 EXPECT_HR(hr
, S_OK
);
2168 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
2170 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
2171 EXPECT_HR(hr
, S_OK
);
2172 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
2174 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
2175 EXPECT_HR(hr
, S_OK
);
2177 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
2178 EXPECT_HR(hr
, S_OK
);
2180 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
2181 EXPECT_HR(hr
, S_OK
);
2183 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2184 EXPECT_HR(hr
, S_OK
);
2185 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
2187 V_VT(&var
) = VT_BSTR
;
2188 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
2190 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2191 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2192 test_seq
= content_handler_test1_alternate
;
2194 test_seq
= content_handler_test1
;
2195 set_expected_seq(test_seq
);
2196 hr
= ISAXXMLReader_parse(reader
, var
);
2197 EXPECT_HR(hr
, S_OK
);
2198 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
2202 SADim
[0].lLbound
= 0;
2203 SADim
[0].cElements
= sizeof(testXML
)-1;
2204 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
2205 SafeArrayAccessData(sa
, (void**)&ptr
);
2206 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
2207 SafeArrayUnaccessData(sa
);
2208 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
2211 set_expected_seq(test_seq
);
2212 hr
= ISAXXMLReader_parse(reader
, var
);
2213 EXPECT_HR(hr
, S_OK
);
2214 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from safe array", FALSE
);
2216 SafeArrayDestroy(sa
);
2218 stream
= create_test_stream(testXML
, -1);
2219 V_VT(&var
) = VT_UNKNOWN
;
2220 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2222 set_expected_seq(test_seq
);
2223 hr
= ISAXXMLReader_parse(reader
, var
);
2224 EXPECT_HR(hr
, S_OK
);
2225 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
2227 IStream_Release(stream
);
2229 stream
= create_test_stream(test_attributes
, -1);
2230 V_VT(&var
) = VT_UNKNOWN
;
2231 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2233 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2234 test_seq
= content_handler_test_attributes_alternate_4
;
2235 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2236 test_seq
= content_handler_test_attributes_alternate_6
;
2238 test_seq
= content_handler_test_attributes
;
2240 set_expected_seq(test_seq
);
2241 hr
= ISAXXMLReader_parse(reader
, var
);
2242 EXPECT_HR(hr
, S_OK
);
2244 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2245 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2246 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2248 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2250 IStream_Release(stream
);
2252 V_VT(&var
) = VT_UNKNOWN
;
2253 V_UNKNOWN(&var
) = (IUnknown
*)&instream
;
2255 test_seq
= read_test_seq
;
2257 set_expected_seq(test_seq
);
2258 hr
= ISAXXMLReader_parse(reader
, var
);
2259 EXPECT_HR(hr
, S_OK
);
2260 ok(read_cnt
== 7, "read_cnt = %d\n", read_cnt
);
2261 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "Read call test", FALSE
);
2263 V_VT(&var
) = VT_BSTR
;
2264 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
2266 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2267 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2268 test_seq
= content_handler_test2_alternate
;
2270 test_seq
= content_handler_test2
;
2272 set_expected_seq(test_seq
);
2273 hr
= ISAXXMLReader_parse(reader
, var
);
2274 EXPECT_HR(hr
, S_OK
);
2275 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
2280 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2281 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2282 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
2285 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2286 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2287 test_seq
= content_handler_test1_alternate
;
2289 test_seq
= content_handler_test1
;
2290 set_expected_seq(test_seq
);
2291 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2292 EXPECT_HR(hr
, S_OK
);
2293 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
2296 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2297 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2298 test_seq
= content_handler_testerror_alternate
;
2300 test_seq
= content_handler_testerror
;
2301 set_expected_seq(test_seq
);
2302 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2303 EXPECT_HR(hr
, E_FAIL
);
2304 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
2306 /* callback ret values */
2307 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2308 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2310 test_seq
= content_handler_test_callback_rets_alt
;
2311 set_expected_seq(test_seq
);
2312 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2313 EXPECT_HR(hr
, S_OK
);
2317 test_seq
= content_handler_test_callback_rets
;
2318 set_expected_seq(test_seq
);
2319 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2320 EXPECT_HR(hr
, S_FALSE
);
2322 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
2324 DeleteFileA(testXmlA
);
2326 /* parse from IXMLDOMDocument */
2327 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
2328 &IID_IXMLDOMDocument
, (void**)&doc
);
2329 EXPECT_HR(hr
, S_OK
);
2331 str
= SysAllocString(szSimpleXML
);
2332 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
2333 EXPECT_HR(hr
, S_OK
);
2336 V_VT(&var
) = VT_UNKNOWN
;
2337 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
2339 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2340 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2341 test_seq
= content_handler_test2_alternate
;
2343 test_seq
= content_handler_test2
;
2345 set_expected_seq(test_seq
);
2346 hr
= ISAXXMLReader_parse(reader
, var
);
2347 EXPECT_HR(hr
, S_OK
);
2348 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
2349 IXMLDOMDocument_Release(doc
);
2351 /* xml:space test */
2352 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2353 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2355 test_seq
= xmlspaceattr_test_alternate
;
2358 test_seq
= xmlspaceattr_test
;
2360 set_expected_seq(test_seq
);
2361 V_VT(&var
) = VT_BSTR
;
2362 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
2363 hr
= ISAXXMLReader_parse(reader
, var
);
2364 EXPECT_HR(hr
, S_OK
);
2366 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2367 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2369 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
2372 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
2374 /* switch off 'namespaces' feature */
2375 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE
);
2376 EXPECT_HR(hr
, S_OK
);
2378 stream
= create_test_stream(test_attributes
, -1);
2379 V_VT(&var
) = VT_UNKNOWN
;
2380 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2382 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2383 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2385 test_seq
= content_handler_test_attributes_alt_no_ns
;
2388 test_seq
= content_handler_test_attributes
;
2390 set_expected_seq(test_seq
);
2391 hr
= ISAXXMLReader_parse(reader
, var
);
2392 EXPECT_HR(hr
, S_OK
);
2393 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2394 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_TRUE
);
2395 EXPECT_HR(hr
, S_OK
);
2397 /* switch off 'namespace-prefixes' feature */
2398 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_FALSE
);
2399 EXPECT_HR(hr
, S_OK
);
2401 stream
= create_test_stream(test_attributes
, -1);
2402 V_VT(&var
) = VT_UNKNOWN
;
2403 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2405 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2406 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2408 test_seq
= content_handler_test_attributes_alt_no_prefix
;
2411 test_seq
= content_handler_test_attributes_no_prefix
;
2413 set_expected_seq(test_seq
);
2414 hr
= ISAXXMLReader_parse(reader
, var
);
2415 EXPECT_HR(hr
, S_OK
);
2416 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2418 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_TRUE
);
2419 EXPECT_HR(hr
, S_OK
);
2421 /* attribute normalization */
2422 stream
= create_test_stream(attribute_normalize
, -1);
2423 V_VT(&var
) = VT_UNKNOWN
;
2424 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2426 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2427 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2429 test_seq
= attribute_norm_alt
;
2432 test_seq
= attribute_norm
;
2434 set_expected_seq(test_seq
);
2435 hr
= ISAXXMLReader_parse(reader
, var
);
2436 EXPECT_HR(hr
, S_OK
);
2437 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "attribute value normalization", TRUE
);
2438 IStream_Release(stream
);
2440 resolver
= (void*)0xdeadbeef;
2441 hr
= ISAXXMLReader_getEntityResolver(reader
, &resolver
);
2442 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2443 ok(resolver
== NULL
, "got %p\n", resolver
);
2445 hr
= ISAXXMLReader_putEntityResolver(reader
, NULL
);
2446 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "got 0x%08x\n", hr
);
2448 /* CDATA sections */
2449 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2451 V_VT(&var
) = VT_UNKNOWN
;
2452 V_UNKNOWN(&var
) = (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
;
2453 hr
= ISAXXMLReader_putProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), var
);
2454 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2456 stream
= create_test_stream(test_cdata_xml
, -1);
2457 V_VT(&var
) = VT_UNKNOWN
;
2458 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2460 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2461 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2462 test_seq
= cdata_test_alt
;
2464 test_seq
= cdata_test
;
2466 set_expected_seq(test_seq
);
2467 hr
= ISAXXMLReader_parse(reader
, var
);
2468 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2469 sprintf(seqname
, "%s: cdata test", table
->name
);
2470 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2472 IStream_Release(stream
);
2474 /* 2. CDATA sections */
2475 stream
= create_test_stream(test2_cdata_xml
, -1);
2476 V_VT(&var
) = VT_UNKNOWN
;
2477 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2479 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2480 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2481 test_seq
= cdata_test2_alt
;
2483 test_seq
= cdata_test2
;
2485 set_expected_seq(test_seq
);
2486 hr
= ISAXXMLReader_parse(reader
, var
);
2487 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2488 sprintf(seqname
, "%s: cdata test 2", table
->name
);
2489 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2491 IStream_Release(stream
);
2493 /* 3. CDATA sections */
2494 stream
= create_test_stream(test3_cdata_xml
, -1);
2495 V_VT(&var
) = VT_UNKNOWN
;
2496 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2498 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2499 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2500 test_seq
= cdata_test3_alt
;
2502 test_seq
= cdata_test3
;
2504 set_expected_seq(test_seq
);
2505 hr
= ISAXXMLReader_parse(reader
, var
);
2506 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2507 sprintf(seqname
, "%s: cdata test 3", table
->name
);
2508 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2510 IStream_Release(stream
);
2512 ISAXXMLReader_Release(reader
);
2519 struct saxreader_props_test_t
2521 const char *prop_name
;
2525 static const struct saxreader_props_test_t props_test_data
[] = {
2526 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
},
2527 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&declhandler
.ISAXDeclHandler_iface
},
2531 static void test_saxreader_properties(void)
2533 const struct saxreader_props_test_t
*ptr
= props_test_data
;
2534 ISAXXMLReader
*reader
;
2539 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2540 &IID_ISAXXMLReader
, (void**)&reader
);
2541 EXPECT_HR(hr
, S_OK
);
2543 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
2544 EXPECT_HR(hr
, E_POINTER
);
2546 while (ptr
->prop_name
)
2551 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2552 init_saxdeclhandler(&declhandler
, S_OK
);
2554 V_VT(&v
) = VT_EMPTY
;
2555 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2556 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2557 EXPECT_HR(hr
, S_OK
);
2558 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2559 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2562 V_VT(&v
) = VT_UNKNOWN
;
2563 V_UNKNOWN(&v
) = ptr
->iface
;
2564 ref
= get_refcount(ptr
->iface
);
2565 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2566 EXPECT_HR(hr
, S_OK
);
2567 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2570 V_VT(&v
) = VT_DISPATCH
;
2571 V_UNKNOWN(&v
) = ptr
->iface
;
2572 ref
= get_refcount(ptr
->iface
);
2573 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2574 EXPECT_HR(hr
, S_OK
);
2575 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2577 /* VT_VARIANT|VT_BYREF with VT_UNKNOWN in referenced variant */
2578 V_VT(&varref
) = VT_UNKNOWN
;
2579 V_UNKNOWN(&varref
) = ptr
->iface
;
2581 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2582 V_VARIANTREF(&v
) = &varref
;
2583 ref
= get_refcount(ptr
->iface
);
2584 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2585 EXPECT_HR(hr
, S_OK
);
2586 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2588 /* VT_VARIANT|VT_BYREF with VT_DISPATCH in referenced variant */
2589 V_VT(&varref
) = VT_DISPATCH
;
2590 V_UNKNOWN(&varref
) = ptr
->iface
;
2592 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2593 V_VARIANTREF(&v
) = &varref
;
2594 ref
= get_refcount(ptr
->iface
);
2595 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2596 EXPECT_HR(hr
, S_OK
);
2597 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2599 V_VT(&v
) = VT_EMPTY
;
2600 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2602 ref
= get_refcount(ptr
->iface
);
2603 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2604 EXPECT_HR(hr
, S_OK
);
2605 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2606 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2607 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2610 V_VT(&v
) = VT_EMPTY
;
2611 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2612 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2613 EXPECT_HR(hr
, S_OK
);
2615 V_VT(&v
) = VT_EMPTY
;
2616 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2617 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2618 EXPECT_HR(hr
, S_OK
);
2619 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2620 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2622 V_VT(&v
) = VT_UNKNOWN
;
2623 V_UNKNOWN(&v
) = ptr
->iface
;
2624 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2625 EXPECT_HR(hr
, S_OK
);
2627 /* only VT_EMPTY seems to be valid to reset property */
2629 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2630 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2631 EXPECT_HR(hr
, E_INVALIDARG
);
2633 V_VT(&v
) = VT_EMPTY
;
2634 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2635 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2636 EXPECT_HR(hr
, S_OK
);
2637 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2638 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2641 V_VT(&v
) = VT_UNKNOWN
;
2642 V_UNKNOWN(&v
) = NULL
;
2643 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2644 EXPECT_HR(hr
, S_OK
);
2646 V_VT(&v
) = VT_EMPTY
;
2647 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2648 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2649 EXPECT_HR(hr
, S_OK
);
2650 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2651 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2653 /* block QueryInterface on handler riid */
2654 V_VT(&v
) = VT_UNKNOWN
;
2655 V_UNKNOWN(&v
) = ptr
->iface
;
2656 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2657 EXPECT_HR(hr
, S_OK
);
2659 init_saxlexicalhandler(&lexicalhandler
, E_NOINTERFACE
);
2660 init_saxdeclhandler(&declhandler
, E_NOINTERFACE
);
2662 V_VT(&v
) = VT_UNKNOWN
;
2663 V_UNKNOWN(&v
) = ptr
->iface
;
2664 EXPECT_REF(ptr
->iface
, 1);
2665 ref
= get_refcount(ptr
->iface
);
2666 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2667 EXPECT_HR(hr
, E_NOINTERFACE
);
2668 EXPECT_REF(ptr
->iface
, 1);
2670 V_VT(&v
) = VT_EMPTY
;
2671 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2672 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2673 EXPECT_HR(hr
, S_OK
);
2674 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2675 ok(V_UNKNOWN(&v
) != NULL
, "got %p\n", V_UNKNOWN(&v
));
2681 ISAXXMLReader_Release(reader
);
2683 if (!is_clsid_supported(&CLSID_SAXXMLReader40
, reader_support_data
))
2686 hr
= CoCreateInstance(&CLSID_SAXXMLReader40
, NULL
, CLSCTX_INPROC_SERVER
,
2687 &IID_ISAXXMLReader
, (void**)&reader
);
2688 EXPECT_HR(hr
, S_OK
);
2690 /* xmldecl-version property */
2691 V_VT(&v
) = VT_EMPTY
;
2692 V_BSTR(&v
) = (void*)0xdeadbeef;
2693 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2694 EXPECT_HR(hr
, S_OK
);
2695 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2696 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2698 /* stream without declaration */
2700 V_BSTR(&v
) = _bstr_("<element></element>");
2701 hr
= ISAXXMLReader_parse(reader
, v
);
2702 EXPECT_HR(hr
, S_OK
);
2704 V_VT(&v
) = VT_EMPTY
;
2705 V_BSTR(&v
) = (void*)0xdeadbeef;
2706 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2707 EXPECT_HR(hr
, S_OK
);
2708 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2709 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2711 /* stream with declaration */
2713 V_BSTR(&v
) = _bstr_("<?xml version=\"1.0\"?><element></element>");
2714 hr
= ISAXXMLReader_parse(reader
, v
);
2715 EXPECT_HR(hr
, S_OK
);
2717 /* VT_BSTR|VT_BYREF input type */
2718 str
= _bstr_("<?xml version=\"1.0\"?><element></element>");
2719 V_VT(&v
) = VT_BSTR
|VT_BYREF
;
2720 V_BSTRREF(&v
) = &str
;
2721 hr
= ISAXXMLReader_parse(reader
, v
);
2722 EXPECT_HR(hr
, S_OK
);
2724 V_VT(&v
) = VT_EMPTY
;
2725 V_BSTR(&v
) = (void*)0xdeadbeef;
2726 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2727 EXPECT_HR(hr
, S_OK
);
2728 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2729 ok(!lstrcmpW(V_BSTR(&v
), _bstr_("1.0")), "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2732 ISAXXMLReader_Release(reader
);
2736 struct feature_ns_entry_t
{
2740 VARIANT_BOOL value2
; /* feature value after feature set to 0xc */
2743 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2744 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
, VARIANT_FALSE
},
2745 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
, VARIANT_FALSE
},
2746 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
, VARIANT_TRUE
},
2747 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
, VARIANT_TRUE
},
2751 static const char *feature_names
[] = {
2752 "http://xml.org/sax/features/namespaces",
2753 "http://xml.org/sax/features/namespace-prefixes",
2757 static void test_saxreader_features(void)
2759 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2760 ISAXXMLReader
*reader
;
2768 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2771 win_skip("can't create %s instance\n", entry
->clsid
);
2776 name
= feature_names
;
2780 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2781 EXPECT_HR(hr
, S_OK
);
2782 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2785 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), value
);
2786 EXPECT_HR(hr
, S_OK
);
2789 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2790 EXPECT_HR(hr
, S_OK
);
2791 ok(entry
->value2
== value
, "%s: got wrong value %x, expected %x\n", entry
->clsid
, value
, entry
->value2
);
2793 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_FALSE
);
2794 EXPECT_HR(hr
, S_OK
);
2796 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2797 EXPECT_HR(hr
, S_OK
);
2798 ok(value
== VARIANT_FALSE
, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry
->clsid
, value
);
2800 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_TRUE
);
2801 EXPECT_HR(hr
, S_OK
);
2803 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2804 EXPECT_HR(hr
, S_OK
);
2805 ok(value
== VARIANT_TRUE
, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry
->clsid
, value
);
2810 ISAXXMLReader_Release(reader
);
2816 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2817 static const CHAR UTF8BOMTest
[] =
2818 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2821 struct enc_test_entry_t
{
2829 static const struct enc_test_entry_t encoding_test_data
[] = {
2830 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2831 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2832 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, FALSE
},
2833 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, FALSE
},
2837 static void test_saxreader_encoding(void)
2839 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2840 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2841 static const CHAR testXmlA
[] = "test.xml";
2845 ISAXXMLReader
*reader
;
2851 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2854 win_skip("can't create %s instance\n", entry
->clsid
);
2859 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2860 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2861 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2864 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2866 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2868 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2870 DeleteFileA(testXmlA
);
2872 /* try BSTR input with no BOM or '<?xml' instruction */
2873 V_VT(&input
) = VT_BSTR
;
2874 V_BSTR(&input
) = _bstr_("<element></element>");
2875 hr
= ISAXXMLReader_parse(reader
, input
);
2876 EXPECT_HR(hr
, S_OK
);
2878 ISAXXMLReader_Release(reader
);
2885 static void test_mxwriter_handlers(void)
2891 static REFIID riids
[] =
2893 &IID_ISAXContentHandler
,
2894 &IID_ISAXLexicalHandler
,
2895 &IID_ISAXDeclHandler
,
2896 &IID_ISAXDTDHandler
,
2897 &IID_ISAXErrorHandler
,
2898 &IID_IVBSAXDeclHandler
,
2899 &IID_IVBSAXLexicalHandler
,
2900 &IID_IVBSAXContentHandler
,
2901 &IID_IVBSAXDTDHandler
,
2902 &IID_IVBSAXErrorHandler
2905 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2906 &IID_IMXWriter
, (void**)&writer
);
2907 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2909 EXPECT_REF(writer
, 1);
2911 for (i
= 0; i
< sizeof(riids
)/sizeof(REFIID
); i
++)
2916 /* handler from IMXWriter */
2917 hr
= IMXWriter_QueryInterface(writer
, riids
[i
], (void**)&handler
);
2918 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2919 EXPECT_REF(writer
, 2);
2920 EXPECT_REF(handler
, 2);
2922 /* IMXWriter from a handler */
2923 hr
= IUnknown_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2924 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2925 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2926 EXPECT_REF(writer
, 3);
2927 EXPECT_REF(writer2
, 3);
2928 IMXWriter_Release(writer2
);
2929 IUnknown_Release(handler
);
2932 IMXWriter_Release(writer
);
2935 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2937 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2938 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2939 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2940 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2944 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2946 { &CLSID_SAXAttributes
, "SAXAttributes" },
2947 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2948 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2949 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2953 struct mxwriter_props_t
2957 VARIANT_BOOL disable_escape
;
2958 VARIANT_BOOL indent
;
2959 VARIANT_BOOL omitdecl
;
2960 VARIANT_BOOL standalone
;
2961 const char *encoding
;
2964 static const struct mxwriter_props_t mxwriter_default_props
[] =
2966 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2967 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2968 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2969 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2973 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2977 while (table
->clsid
)
2984 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2991 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2992 &IID_IMXWriter
, (void**)&writer
);
2993 EXPECT_HR(hr
, S_OK
);
2996 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
2997 EXPECT_HR(hr
, S_OK
);
2998 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
3000 b
= !table
->disable_escape
;
3001 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
3002 EXPECT_HR(hr
, S_OK
);
3003 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
3004 table
->disable_escape
);
3007 hr
= IMXWriter_get_indent(writer
, &b
);
3008 EXPECT_HR(hr
, S_OK
);
3009 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
3011 b
= !table
->omitdecl
;
3012 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
3013 EXPECT_HR(hr
, S_OK
);
3014 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
3016 b
= !table
->standalone
;
3017 hr
= IMXWriter_get_standalone(writer
, &b
);
3018 EXPECT_HR(hr
, S_OK
);
3019 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
3021 hr
= IMXWriter_get_encoding(writer
, &encoding
);
3022 EXPECT_HR(hr
, S_OK
);
3023 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
3024 i
, wine_dbgstr_w(encoding
), table
->encoding
);
3025 SysFreeString(encoding
);
3027 IMXWriter_Release(writer
);
3034 static void test_mxwriter_properties(void)
3036 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
3037 static const WCHAR testW
[] = {'t','e','s','t',0};
3038 ISAXContentHandler
*content
;
3045 test_mxwriter_default_properties(mxwriter_default_props
);
3047 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3048 &IID_IMXWriter
, (void**)&writer
);
3049 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3051 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
3052 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3054 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
3055 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3057 hr
= IMXWriter_get_indent(writer
, NULL
);
3058 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3060 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
3061 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3063 hr
= IMXWriter_get_standalone(writer
, NULL
);
3064 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3067 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
3068 ok(hr
== S_OK
, "got %08x\n", hr
);
3071 hr
= IMXWriter_get_standalone(writer
, &b
);
3072 ok(hr
== S_OK
, "got %08x\n", hr
);
3073 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
3075 hr
= IMXWriter_get_encoding(writer
, NULL
);
3076 EXPECT_HR(hr
, E_POINTER
);
3078 /* UTF-16 is a default setting apparently */
3079 str
= (void*)0xdeadbeef;
3080 hr
= IMXWriter_get_encoding(writer
, &str
);
3081 EXPECT_HR(hr
, S_OK
);
3082 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
3084 str2
= (void*)0xdeadbeef;
3085 hr
= IMXWriter_get_encoding(writer
, &str2
);
3086 ok(hr
== S_OK
, "got %08x\n", hr
);
3087 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
3089 SysFreeString(str2
);
3092 /* put empty string */
3093 str
= SysAllocString(emptyW
);
3094 hr
= IMXWriter_put_encoding(writer
, str
);
3095 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3098 str
= (void*)0xdeadbeef;
3099 hr
= IMXWriter_get_encoding(writer
, &str
);
3100 EXPECT_HR(hr
, S_OK
);
3101 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
3104 /* invalid encoding name */
3105 str
= SysAllocString(testW
);
3106 hr
= IMXWriter_put_encoding(writer
, str
);
3107 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3110 /* test case sensivity */
3111 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
3112 EXPECT_HR(hr
, S_OK
);
3113 str
= (void*)0xdeadbeef;
3114 hr
= IMXWriter_get_encoding(writer
, &str
);
3115 EXPECT_HR(hr
, S_OK
);
3116 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
3119 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
3120 EXPECT_HR(hr
, S_OK
);
3121 str
= (void*)0xdeadbeef;
3122 hr
= IMXWriter_get_encoding(writer
, &str
);
3123 EXPECT_HR(hr
, S_OK
);
3124 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
3127 /* how it affects document creation */
3128 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3129 EXPECT_HR(hr
, S_OK
);
3131 hr
= ISAXContentHandler_startDocument(content
);
3132 EXPECT_HR(hr
, S_OK
);
3133 hr
= ISAXContentHandler_endDocument(content
);
3134 EXPECT_HR(hr
, S_OK
);
3136 V_VT(&dest
) = VT_EMPTY
;
3137 hr
= IMXWriter_get_output(writer
, &dest
);
3138 EXPECT_HR(hr
, S_OK
);
3139 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3140 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
3141 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3142 VariantClear(&dest
);
3143 ISAXContentHandler_Release(content
);
3145 hr
= IMXWriter_get_version(writer
, NULL
);
3146 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3147 /* default version is 'surprisingly' 1.0 */
3148 hr
= IMXWriter_get_version(writer
, &str
);
3149 ok(hr
== S_OK
, "got %08x\n", hr
);
3150 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
3153 /* store version string as is */
3154 hr
= IMXWriter_put_version(writer
, NULL
);
3155 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3157 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
3158 ok(hr
== S_OK
, "got %08x\n", hr
);
3160 hr
= IMXWriter_put_version(writer
, _bstr_(""));
3161 ok(hr
== S_OK
, "got %08x\n", hr
);
3162 hr
= IMXWriter_get_version(writer
, &str
);
3163 ok(hr
== S_OK
, "got %08x\n", hr
);
3164 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
3167 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
3168 ok(hr
== S_OK
, "got %08x\n", hr
);
3169 hr
= IMXWriter_get_version(writer
, &str
);
3170 ok(hr
== S_OK
, "got %08x\n", hr
);
3171 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
3174 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
3175 ok(hr
== S_OK
, "got %08x\n", hr
);
3176 hr
= IMXWriter_get_version(writer
, &str
);
3177 ok(hr
== S_OK
, "got %08x\n", hr
);
3178 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
3181 IMXWriter_Release(writer
);
3185 static void test_mxwriter_flush(void)
3187 ISAXContentHandler
*content
;
3190 ULARGE_INTEGER pos2
;
3198 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3199 &IID_IMXWriter
, (void**)&writer
);
3200 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3202 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3203 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3204 EXPECT_REF(stream
, 1);
3206 /* detach when nothing was attached */
3207 V_VT(&dest
) = VT_EMPTY
;
3208 hr
= IMXWriter_put_output(writer
, dest
);
3209 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3212 V_VT(&dest
) = VT_UNKNOWN
;
3213 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3214 hr
= IMXWriter_put_output(writer
, dest
);
3215 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3216 todo_wine
EXPECT_REF(stream
, 3);
3218 /* detach setting VT_EMPTY destination */
3219 V_VT(&dest
) = VT_EMPTY
;
3220 hr
= IMXWriter_put_output(writer
, dest
);
3221 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3222 EXPECT_REF(stream
, 1);
3224 V_VT(&dest
) = VT_UNKNOWN
;
3225 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3226 hr
= IMXWriter_put_output(writer
, dest
);
3227 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3229 /* flush() doesn't detach a stream */
3230 hr
= IMXWriter_flush(writer
);
3231 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3232 todo_wine
EXPECT_REF(stream
, 3);
3235 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3236 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3237 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3239 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3240 ok(hr
== S_OK
, "got %08x\n", hr
);
3242 hr
= ISAXContentHandler_startDocument(content
);
3243 ok(hr
== S_OK
, "got %08x\n", hr
);
3246 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3247 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3248 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
3250 /* already started */
3251 hr
= ISAXContentHandler_startDocument(content
);
3252 ok(hr
== S_OK
, "got %08x\n", hr
);
3254 hr
= ISAXContentHandler_endDocument(content
);
3255 ok(hr
== S_OK
, "got %08x\n", hr
);
3257 /* flushed on endDocument() */
3259 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3260 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3261 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
3263 IStream_Release(stream
);
3265 /* auto-flush feature */
3266 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3267 EXPECT_HR(hr
, S_OK
);
3268 EXPECT_REF(stream
, 1);
3270 V_VT(&dest
) = VT_UNKNOWN
;
3271 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3272 hr
= IMXWriter_put_output(writer
, dest
);
3273 EXPECT_HR(hr
, S_OK
);
3275 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_FALSE
);
3276 EXPECT_HR(hr
, S_OK
);
3278 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3279 EXPECT_HR(hr
, S_OK
);
3281 hr
= ISAXContentHandler_startDocument(content
);
3282 EXPECT_HR(hr
, S_OK
);
3284 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3285 EXPECT_HR(hr
, S_OK
);
3287 /* internal buffer is flushed automatically on certain threshold */
3290 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3291 EXPECT_HR(hr
, S_OK
);
3292 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3295 buff
= HeapAlloc(GetProcessHeap(), 0, len
+1);
3296 memset(buff
, 'A', len
);
3298 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3299 EXPECT_HR(hr
, S_OK
);
3303 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3304 EXPECT_HR(hr
, S_OK
);
3306 ok(pos2
.QuadPart
!= 0, "unexpected stream beginning\n");
3308 hr
= IMXWriter_get_output(writer
, NULL
);
3309 EXPECT_HR(hr
, E_POINTER
);
3311 ref
= get_refcount(stream
);
3312 V_VT(&dest
) = VT_EMPTY
;
3313 hr
= IMXWriter_get_output(writer
, &dest
);
3314 EXPECT_HR(hr
, S_OK
);
3315 ok(V_VT(&dest
) == VT_UNKNOWN
, "got vt type %d\n", V_VT(&dest
));
3316 ok(V_UNKNOWN(&dest
) == (IUnknown
*)stream
, "got pointer %p\n", V_UNKNOWN(&dest
));
3317 ok(ref
+1 == get_refcount(stream
), "expected increased refcount\n");
3318 VariantClear(&dest
);
3320 hr
= ISAXContentHandler_endDocument(content
);
3321 EXPECT_HR(hr
, S_OK
);
3323 IStream_Release(stream
);
3325 /* test char count lower than threshold */
3326 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3327 EXPECT_HR(hr
, S_OK
);
3328 EXPECT_REF(stream
, 1);
3330 hr
= ISAXContentHandler_startDocument(content
);
3331 EXPECT_HR(hr
, S_OK
);
3333 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3334 EXPECT_HR(hr
, S_OK
);
3338 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3339 EXPECT_HR(hr
, S_OK
);
3340 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3342 memset(buff
, 'A', len
);
3344 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
- 8);
3345 EXPECT_HR(hr
, S_OK
);
3349 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3350 EXPECT_HR(hr
, S_OK
);
3351 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3353 hr
= ISAXContentHandler_endDocument(content
);
3354 EXPECT_HR(hr
, S_OK
);
3356 /* test auto-flush function when stream is not set */
3357 V_VT(&dest
) = VT_EMPTY
;
3358 hr
= IMXWriter_put_output(writer
, dest
);
3359 EXPECT_HR(hr
, S_OK
);
3361 hr
= ISAXContentHandler_startDocument(content
);
3362 EXPECT_HR(hr
, S_OK
);
3364 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3365 EXPECT_HR(hr
, S_OK
);
3367 memset(buff
, 'A', len
);
3369 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3370 EXPECT_HR(hr
, S_OK
);
3372 V_VT(&dest
) = VT_EMPTY
;
3373 hr
= IMXWriter_get_output(writer
, &dest
);
3374 EXPECT_HR(hr
, S_OK
);
3375 len
+= strlen("<a>");
3376 ok(SysStringLen(V_BSTR(&dest
)) == len
, "got len=%d, expected %d\n", SysStringLen(V_BSTR(&dest
)), len
);
3377 VariantClear(&dest
);
3379 HeapFree(GetProcessHeap(), 0, buff
);
3380 ISAXContentHandler_Release(content
);
3381 IStream_Release(stream
);
3382 IMXWriter_Release(writer
);
3386 static void test_mxwriter_startenddocument(void)
3388 ISAXContentHandler
*content
;
3393 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3394 &IID_IMXWriter
, (void**)&writer
);
3395 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3397 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3398 ok(hr
== S_OK
, "got %08x\n", hr
);
3400 hr
= ISAXContentHandler_startDocument(content
);
3401 ok(hr
== S_OK
, "got %08x\n", hr
);
3403 hr
= ISAXContentHandler_endDocument(content
);
3404 ok(hr
== S_OK
, "got %08x\n", hr
);
3406 V_VT(&dest
) = VT_EMPTY
;
3407 hr
= IMXWriter_get_output(writer
, &dest
);
3408 ok(hr
== S_OK
, "got %08x\n", hr
);
3409 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3410 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3411 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3412 VariantClear(&dest
);
3414 /* now try another startDocument */
3415 hr
= ISAXContentHandler_startDocument(content
);
3416 ok(hr
== S_OK
, "got %08x\n", hr
);
3417 /* and get duplicated prolog */
3418 V_VT(&dest
) = VT_EMPTY
;
3419 hr
= IMXWriter_get_output(writer
, &dest
);
3420 ok(hr
== S_OK
, "got %08x\n", hr
);
3421 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3422 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
3423 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3424 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3425 VariantClear(&dest
);
3427 ISAXContentHandler_Release(content
);
3428 IMXWriter_Release(writer
);
3430 /* now with omitted declaration */
3431 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3432 &IID_IMXWriter
, (void**)&writer
);
3433 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3435 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3436 ok(hr
== S_OK
, "got %08x\n", hr
);
3438 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3439 ok(hr
== S_OK
, "got %08x\n", hr
);
3441 hr
= ISAXContentHandler_startDocument(content
);
3442 ok(hr
== S_OK
, "got %08x\n", hr
);
3444 hr
= ISAXContentHandler_endDocument(content
);
3445 ok(hr
== S_OK
, "got %08x\n", hr
);
3447 V_VT(&dest
) = VT_EMPTY
;
3448 hr
= IMXWriter_get_output(writer
, &dest
);
3449 ok(hr
== S_OK
, "got %08x\n", hr
);
3450 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3451 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3452 VariantClear(&dest
);
3454 ISAXContentHandler_Release(content
);
3455 IMXWriter_Release(writer
);
3462 StartElement
= 0x001,
3464 StartEndElement
= 0x011,
3465 DisableEscaping
= 0x100
3468 struct writer_startendelement_t
{
3470 enum startendtype type
;
3472 const char *local_name
;
3476 ISAXAttributes
*attr
;
3479 static const char startelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\'\">";
3480 static const char startendelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\'\"/>";
3481 static const char startendelement_noescape_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&\">\'\"/>";
3483 static const struct writer_startendelement_t writer_startendelement
[] = {
3485 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3486 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3487 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3488 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
3489 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3491 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3492 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3493 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
3494 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3495 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3497 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3498 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
3499 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3500 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3501 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3503 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
3504 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3505 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3506 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3507 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3509 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3510 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3511 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3512 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
3513 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3515 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3516 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3517 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3518 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3519 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3521 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3522 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3523 /* endElement tests */
3524 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3525 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3526 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3528 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
3529 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3530 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3531 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3532 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
3534 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3535 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3536 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3537 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
3538 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3540 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3541 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3542 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
3543 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3544 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3546 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3547 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3548 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3549 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3550 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3552 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
3553 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3554 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3555 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3556 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3558 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3559 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3560 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3561 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3563 /* with attributes */
3564 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3566 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3567 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3568 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3569 /* empty elements */
3570 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3571 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3573 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3574 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3575 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
3576 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
3577 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
3579 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
3581 /* with disabled output escaping */
3582 { &CLSID_MXXMLWriter
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3583 { &CLSID_MXXMLWriter30
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3584 { &CLSID_MXXMLWriter40
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3585 { &CLSID_MXXMLWriter60
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3590 static void get_class_support_data(struct msxmlsupported_data_t
*table
, REFIID riid
)
3592 while (table
->clsid
)
3597 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, riid
, (void**)&unk
);
3598 if (hr
== S_OK
) IUnknown_Release(unk
);
3600 table
->supported
= hr
== S_OK
;
3601 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
3607 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
3611 while (table
->clsid
)
3613 ISAXContentHandler
*content
;
3617 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3624 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3625 &IID_IMXWriter
, (void**)&writer
);
3626 EXPECT_HR(hr
, S_OK
);
3628 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3629 EXPECT_HR(hr
, S_OK
);
3631 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3632 EXPECT_HR(hr
, S_OK
);
3634 hr
= ISAXContentHandler_startDocument(content
);
3635 EXPECT_HR(hr
, S_OK
);
3637 if (table
->type
& DisableEscaping
)
3639 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3640 EXPECT_HR(hr
, S_OK
);
3643 if (table
->type
& StartElement
)
3645 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), table
->uri
? strlen(table
->uri
) : 0,
3646 _bstr_(table
->local_name
), table
->local_name
? strlen(table
->local_name
) : 0, _bstr_(table
->qname
),
3647 table
->qname
? strlen(table
->qname
) : 0, table
->attr
);
3648 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3651 if (table
->type
& EndElement
)
3653 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), table
->uri
? strlen(table
->uri
) : 0,
3654 _bstr_(table
->local_name
), table
->local_name
? strlen(table
->local_name
) : 0, _bstr_(table
->qname
),
3655 table
->qname
? strlen(table
->qname
) : 0);
3656 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3664 V_VT(&dest
) = VT_EMPTY
;
3665 hr
= IMXWriter_get_output(writer
, &dest
);
3666 EXPECT_HR(hr
, S_OK
);
3667 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3668 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3669 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3670 VariantClear(&dest
);
3673 ISAXContentHandler_Release(content
);
3674 IMXWriter_Release(writer
);
3683 /* point of these test is to start/end element with different names and name lengths */
3684 struct writer_startendelement2_t
{
3686 const char *qnamestart
;
3688 const char *qnameend
;
3694 static const struct writer_startendelement2_t writer_startendelement2
[] = {
3695 { &CLSID_MXXMLWriter
, "a", -1, "b", -1, "<a/>", S_OK
},
3696 { &CLSID_MXXMLWriter30
, "a", -1, "b", -1, "<a/>", S_OK
},
3697 { &CLSID_MXXMLWriter40
, "a", -1, "b", -1, "<a/>", S_OK
},
3698 /* -1 length is not allowed for version 6 */
3699 { &CLSID_MXXMLWriter60
, "a", -1, "b", -1, "<a/>", E_INVALIDARG
},
3701 { &CLSID_MXXMLWriter
, "a", 1, "b", 1, "<a/>", S_OK
},
3702 { &CLSID_MXXMLWriter30
, "a", 1, "b", 1, "<a/>", S_OK
},
3703 { &CLSID_MXXMLWriter40
, "a", 1, "b", 1, "<a/>", S_OK
},
3704 { &CLSID_MXXMLWriter60
, "a", 1, "b", 1, "<a/>", S_OK
},
3708 static void test_mxwriter_startendelement_batch2(const struct writer_startendelement2_t
*table
)
3712 while (table
->clsid
)
3714 ISAXContentHandler
*content
;
3718 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3725 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3726 &IID_IMXWriter
, (void**)&writer
);
3727 EXPECT_HR(hr
, S_OK
);
3729 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3730 EXPECT_HR(hr
, S_OK
);
3732 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3733 EXPECT_HR(hr
, S_OK
);
3735 hr
= ISAXContentHandler_startDocument(content
);
3736 EXPECT_HR(hr
, S_OK
);
3738 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3739 _bstr_(table
->qnamestart
), table
->qnamestart_len
, NULL
);
3740 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3742 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3743 _bstr_(table
->qnameend
), table
->qnameend_len
);
3744 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3751 V_VT(&dest
) = VT_EMPTY
;
3752 hr
= IMXWriter_get_output(writer
, &dest
);
3753 EXPECT_HR(hr
, S_OK
);
3754 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3755 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3756 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3757 VariantClear(&dest
);
3760 ISAXContentHandler_Release(content
);
3761 IMXWriter_Release(writer
);
3771 static void test_mxwriter_startendelement(void)
3773 ISAXContentHandler
*content
;
3778 test_mxwriter_startendelement_batch(writer_startendelement
);
3779 test_mxwriter_startendelement_batch2(writer_startendelement2
);
3781 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3782 &IID_IMXWriter
, (void**)&writer
);
3783 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3785 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3786 ok(hr
== S_OK
, "got %08x\n", hr
);
3788 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3789 ok(hr
== S_OK
, "got %08x\n", hr
);
3791 hr
= ISAXContentHandler_startDocument(content
);
3792 ok(hr
== S_OK
, "got %08x\n", hr
);
3794 /* all string pointers should be not null */
3795 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
3796 ok(hr
== S_OK
, "got %08x\n", hr
);
3798 V_VT(&dest
) = VT_EMPTY
;
3799 hr
= IMXWriter_get_output(writer
, &dest
);
3800 ok(hr
== S_OK
, "got %08x\n", hr
);
3801 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3802 ok(!lstrcmpW(_bstr_("<>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3803 VariantClear(&dest
);
3805 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
3806 ok(hr
== S_OK
, "got %08x\n", hr
);
3808 V_VT(&dest
) = VT_EMPTY
;
3809 hr
= IMXWriter_get_output(writer
, &dest
);
3810 ok(hr
== S_OK
, "got %08x\n", hr
);
3811 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3812 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3813 VariantClear(&dest
);
3815 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
3816 EXPECT_HR(hr
, E_INVALIDARG
);
3818 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
3819 EXPECT_HR(hr
, E_INVALIDARG
);
3821 /* only local name is an error too */
3822 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
3823 EXPECT_HR(hr
, E_INVALIDARG
);
3825 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
3826 EXPECT_HR(hr
, S_OK
);
3828 V_VT(&dest
) = VT_EMPTY
;
3829 hr
= IMXWriter_get_output(writer
, &dest
);
3830 EXPECT_HR(hr
, S_OK
);
3831 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3832 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3833 VariantClear(&dest
);
3835 hr
= ISAXContentHandler_endDocument(content
);
3836 EXPECT_HR(hr
, S_OK
);
3838 V_VT(&dest
) = VT_EMPTY
;
3839 hr
= IMXWriter_put_output(writer
, dest
);
3840 EXPECT_HR(hr
, S_OK
);
3842 V_VT(&dest
) = VT_EMPTY
;
3843 hr
= IMXWriter_get_output(writer
, &dest
);
3844 EXPECT_HR(hr
, S_OK
);
3845 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3846 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3847 VariantClear(&dest
);
3849 hr
= ISAXContentHandler_startDocument(content
);
3850 EXPECT_HR(hr
, S_OK
);
3852 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
3853 EXPECT_HR(hr
, S_OK
);
3855 V_VT(&dest
) = VT_EMPTY
;
3856 hr
= IMXWriter_get_output(writer
, &dest
);
3857 EXPECT_HR(hr
, S_OK
);
3858 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3859 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3860 VariantClear(&dest
);
3862 hr
= ISAXContentHandler_endDocument(content
);
3863 EXPECT_HR(hr
, S_OK
);
3864 IMXWriter_flush(writer
);
3866 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
3867 EXPECT_HR(hr
, S_OK
);
3868 V_VT(&dest
) = VT_EMPTY
;
3869 hr
= IMXWriter_get_output(writer
, &dest
);
3870 EXPECT_HR(hr
, S_OK
);
3871 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3872 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3873 VariantClear(&dest
);
3875 V_VT(&dest
) = VT_EMPTY
;
3876 hr
= IMXWriter_put_output(writer
, dest
);
3877 EXPECT_HR(hr
, S_OK
);
3880 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), -1, NULL
);
3881 EXPECT_HR(hr
, S_OK
);
3882 V_VT(&dest
) = VT_EMPTY
;
3883 hr
= IMXWriter_get_output(writer
, &dest
);
3884 EXPECT_HR(hr
, S_OK
);
3885 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3886 ok(!lstrcmpW(_bstr_("<a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3887 VariantClear(&dest
);
3889 ISAXContentHandler_Release(content
);
3890 IMXWriter_Release(writer
);
3894 struct writer_characters_t
{
3900 static const struct writer_characters_t writer_characters
[] = {
3901 { &CLSID_MXXMLWriter
, "< > & \" \'", "< > & \" \'" },
3902 { &CLSID_MXXMLWriter30
, "< > & \" \'", "< > & \" \'" },
3903 { &CLSID_MXXMLWriter40
, "< > & \" \'", "< > & \" \'" },
3904 { &CLSID_MXXMLWriter60
, "< > & \" \'", "< > & \" \'" },
3908 static void test_mxwriter_characters(void)
3910 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
3911 const struct writer_characters_t
*table
= writer_characters
;
3912 ISAXContentHandler
*content
;
3918 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3919 &IID_IMXWriter
, (void**)&writer
);
3920 EXPECT_HR(hr
, S_OK
);
3922 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3923 EXPECT_HR(hr
, S_OK
);
3925 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3926 EXPECT_HR(hr
, S_OK
);
3928 hr
= ISAXContentHandler_startDocument(content
);
3929 EXPECT_HR(hr
, S_OK
);
3931 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
3932 EXPECT_HR(hr
, E_INVALIDARG
);
3934 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3935 EXPECT_HR(hr
, S_OK
);
3937 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
3938 EXPECT_HR(hr
, S_OK
);
3940 V_VT(&dest
) = VT_EMPTY
;
3941 hr
= IMXWriter_get_output(writer
, &dest
);
3942 EXPECT_HR(hr
, S_OK
);
3943 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3944 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3945 VariantClear(&dest
);
3947 hr
= ISAXContentHandler_endDocument(content
);
3948 EXPECT_HR(hr
, S_OK
);
3950 ISAXContentHandler_Release(content
);
3951 IMXWriter_Release(writer
);
3953 /* try empty characters data to see if element is closed */
3954 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3955 &IID_IMXWriter
, (void**)&writer
);
3956 EXPECT_HR(hr
, S_OK
);
3958 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3959 EXPECT_HR(hr
, S_OK
);
3961 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3962 EXPECT_HR(hr
, S_OK
);
3964 hr
= ISAXContentHandler_startDocument(content
);
3965 EXPECT_HR(hr
, S_OK
);
3967 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3968 EXPECT_HR(hr
, S_OK
);
3970 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3971 EXPECT_HR(hr
, S_OK
);
3973 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3974 EXPECT_HR(hr
, S_OK
);
3976 V_VT(&dest
) = VT_EMPTY
;
3977 hr
= IMXWriter_get_output(writer
, &dest
);
3978 EXPECT_HR(hr
, S_OK
);
3979 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3980 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3981 VariantClear(&dest
);
3983 ISAXContentHandler_Release(content
);
3984 IMXWriter_Release(writer
);
3987 while (table
->clsid
)
3989 ISAXContentHandler
*content
;
3994 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
4001 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4002 &IID_IMXWriter
, (void**)&writer
);
4003 EXPECT_HR(hr
, S_OK
);
4005 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4006 EXPECT_HR(hr
, S_OK
);
4008 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4009 EXPECT_HR(hr
, S_OK
);
4011 hr
= ISAXContentHandler_startDocument(content
);
4012 EXPECT_HR(hr
, S_OK
);
4014 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
4015 EXPECT_HR(hr
, S_OK
);
4020 V_VT(&dest
) = VT_EMPTY
;
4021 hr
= IMXWriter_get_output(writer
, &dest
);
4022 EXPECT_HR(hr
, S_OK
);
4023 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4024 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
4025 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
4026 VariantClear(&dest
);
4029 /* with disabled escaping */
4030 V_VT(&dest
) = VT_EMPTY
;
4031 hr
= IMXWriter_put_output(writer
, dest
);
4032 EXPECT_HR(hr
, S_OK
);
4034 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
4035 EXPECT_HR(hr
, S_OK
);
4037 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
4038 EXPECT_HR(hr
, S_OK
);
4043 V_VT(&dest
) = VT_EMPTY
;
4044 hr
= IMXWriter_get_output(writer
, &dest
);
4045 EXPECT_HR(hr
, S_OK
);
4046 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4047 ok(!lstrcmpW(_bstr_(table
->data
), V_BSTR(&dest
)),
4048 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->data
);
4049 VariantClear(&dest
);
4052 ISAXContentHandler_Release(content
);
4053 IMXWriter_Release(writer
);
4062 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
4064 VARIANT_TRUE
,"UTF-16",
4066 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
4067 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4072 VARIANT_FALSE
,"UTF-16",
4074 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4079 VARIANT_TRUE
,"UTF-8",
4081 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
4082 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
4083 * and the writer is released.
4090 VARIANT_TRUE
,"utf-8",
4092 {FALSE
,(const BYTE
*)utf8xml2
,sizeof(utf8xml2
)-1},
4093 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
4094 * and the writer is released.
4101 VARIANT_TRUE
,"UTF-16",
4103 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
4104 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4109 VARIANT_TRUE
,"UTF-16",
4111 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
4112 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4118 static void test_mxwriter_stream(void)
4121 ISAXContentHandler
*content
;
4126 ULARGE_INTEGER pos2
;
4127 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
4129 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
4130 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
4132 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4133 &IID_IMXWriter
, (void**)&writer
);
4134 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4136 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4137 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4139 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
4140 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
4142 V_VT(&dest
) = VT_UNKNOWN
;
4143 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
4144 hr
= IMXWriter_put_output(writer
, dest
);
4145 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
4146 VariantClear(&dest
);
4148 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
4149 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
4151 current_write_test
= test
->expected_writes
;
4153 hr
= ISAXContentHandler_startDocument(content
);
4154 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4156 hr
= ISAXContentHandler_endDocument(content
);
4157 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4159 ISAXContentHandler_Release(content
);
4160 IMXWriter_Release(writer
);
4162 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
4163 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
4166 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4167 &IID_IMXWriter
, (void**)&writer
);
4168 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4170 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4171 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
4173 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4174 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4176 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4177 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
4179 V_VT(&dest
) = VT_UNKNOWN
;
4180 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4181 hr
= IMXWriter_put_output(writer
, dest
);
4182 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4184 hr
= ISAXContentHandler_startDocument(content
);
4185 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4187 /* Setting output of the mxwriter causes the current output to be flushed,
4188 * and the writer to start over.
4190 V_VT(&dest
) = VT_EMPTY
;
4191 hr
= IMXWriter_put_output(writer
, dest
);
4192 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4195 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4196 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
4197 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
4199 hr
= ISAXContentHandler_startDocument(content
);
4200 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4202 hr
= ISAXContentHandler_endDocument(content
);
4203 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
4205 V_VT(&dest
) = VT_EMPTY
;
4206 hr
= IMXWriter_get_output(writer
, &dest
);
4207 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
4208 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4209 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4210 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4211 VariantClear(&dest
);
4213 /* test when BOM is written to output stream */
4214 V_VT(&dest
) = VT_EMPTY
;
4215 hr
= IMXWriter_put_output(writer
, dest
);
4216 EXPECT_HR(hr
, S_OK
);
4219 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
4220 EXPECT_HR(hr
, S_OK
);
4222 V_VT(&dest
) = VT_UNKNOWN
;
4223 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4224 hr
= IMXWriter_put_output(writer
, dest
);
4225 EXPECT_HR(hr
, S_OK
);
4227 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_TRUE
);
4228 EXPECT_HR(hr
, S_OK
);
4230 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4231 EXPECT_HR(hr
, S_OK
);
4233 hr
= ISAXContentHandler_startDocument(content
);
4234 EXPECT_HR(hr
, S_OK
);
4238 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4239 EXPECT_HR(hr
, S_OK
);
4240 ok(pos2
.QuadPart
== 2, "got wrong position\n");
4242 IStream_Release(stream
);
4243 ISAXContentHandler_Release(content
);
4244 IMXWriter_Release(writer
);
4249 static const char *encoding_names
[] = {
4262 static void test_mxwriter_encoding(void)
4264 ISAXContentHandler
*content
;
4275 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4276 &IID_IMXWriter
, (void**)&writer
);
4277 EXPECT_HR(hr
, S_OK
);
4279 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4280 EXPECT_HR(hr
, S_OK
);
4282 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4283 EXPECT_HR(hr
, S_OK
);
4285 hr
= ISAXContentHandler_startDocument(content
);
4286 EXPECT_HR(hr
, S_OK
);
4288 hr
= ISAXContentHandler_endDocument(content
);
4289 EXPECT_HR(hr
, S_OK
);
4291 /* The content is always re-encoded to UTF-16 when the output is
4292 * retrieved as a BSTR.
4294 V_VT(&dest
) = VT_EMPTY
;
4295 hr
= IMXWriter_get_output(writer
, &dest
);
4296 EXPECT_HR(hr
, S_OK
);
4297 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4298 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4299 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4300 VariantClear(&dest
);
4302 /* switch encoding when something is written already */
4303 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4304 EXPECT_HR(hr
, S_OK
);
4306 V_VT(&dest
) = VT_UNKNOWN
;
4307 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4308 hr
= IMXWriter_put_output(writer
, dest
);
4309 EXPECT_HR(hr
, S_OK
);
4311 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4312 EXPECT_HR(hr
, S_OK
);
4314 /* write empty element */
4315 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
4316 EXPECT_HR(hr
, S_OK
);
4318 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
4319 EXPECT_HR(hr
, S_OK
);
4322 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4323 EXPECT_HR(hr
, S_OK
);
4325 hr
= IMXWriter_flush(writer
);
4326 EXPECT_HR(hr
, S_OK
);
4328 hr
= GetHGlobalFromStream(stream
, &g
);
4329 EXPECT_HR(hr
, S_OK
);
4331 ptr
= GlobalLock(g
);
4332 ok(!strncmp(ptr
, "<a/>", 4), "got %c%c%c%c\n", ptr
[0],ptr
[1],ptr
[2],ptr
[3]);
4335 /* so output is unaffected, encoding name is stored however */
4336 hr
= IMXWriter_get_encoding(writer
, &s
);
4337 EXPECT_HR(hr
, S_OK
);
4338 ok(!lstrcmpW(s
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(s
));
4341 IStream_Release(stream
);
4344 enc
= encoding_names
[i
];
4347 char expectedA
[200];
4349 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4350 EXPECT_HR(hr
, S_OK
);
4352 V_VT(&dest
) = VT_UNKNOWN
;
4353 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4354 hr
= IMXWriter_put_output(writer
, dest
);
4355 EXPECT_HR(hr
, S_OK
);
4357 hr
= IMXWriter_put_encoding(writer
, _bstr_(enc
));
4358 ok(hr
== S_OK
|| broken(hr
!= S_OK
) /* old win versions do not support certain encodings */,
4359 "%s: encoding not accepted\n", enc
);
4362 enc
= encoding_names
[++i
];
4363 IStream_Release(stream
);
4367 hr
= ISAXContentHandler_startDocument(content
);
4368 EXPECT_HR(hr
, S_OK
);
4370 hr
= ISAXContentHandler_endDocument(content
);
4371 EXPECT_HR(hr
, S_OK
);
4373 hr
= IMXWriter_flush(writer
);
4374 EXPECT_HR(hr
, S_OK
);
4376 /* prepare expected string */
4378 strcat(expectedA
, "<?xml version=\"1.0\" encoding=\"");
4379 strcat(expectedA
, enc
);
4380 strcat(expectedA
, "\" standalone=\"no\"?>\r\n");
4382 hr
= GetHGlobalFromStream(stream
, &g
);
4383 EXPECT_HR(hr
, S_OK
);
4385 ptr
= GlobalLock(g
);
4386 ok(!strncmp(ptr
, expectedA
, strlen(expectedA
)), "%s: got %s, expected %.50s\n", enc
, ptr
, expectedA
);
4389 V_VT(&dest
) = VT_EMPTY
;
4390 hr
= IMXWriter_put_output(writer
, dest
);
4391 EXPECT_HR(hr
, S_OK
);
4393 IStream_Release(stream
);
4395 enc
= encoding_names
[++i
];
4398 ISAXContentHandler_Release(content
);
4399 IMXWriter_Release(writer
);
4404 static void test_obj_dispex(IUnknown
*obj
)
4406 static const WCHAR testW
[] = {'t','e','s','t','p','r','o','p',0};
4407 static const WCHAR starW
[] = {'*',0};
4408 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
4409 IDispatchEx
*dispex
;
4417 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
4418 EXPECT_HR(hr
, S_OK
);
4419 if (FAILED(hr
)) return;
4422 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
4423 EXPECT_HR(hr
, S_OK
);
4424 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
4426 name
= SysAllocString(starW
);
4427 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
4428 EXPECT_HR(hr
, E_NOTIMPL
);
4429 SysFreeString(name
);
4431 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
4432 EXPECT_HR(hr
, E_NOTIMPL
);
4435 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
4436 EXPECT_HR(hr
, E_NOTIMPL
);
4437 ok(props
== 0, "expected 0 got %d\n", props
);
4439 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
4440 EXPECT_HR(hr
, E_NOTIMPL
);
4441 if (SUCCEEDED(hr
)) SysFreeString(name
);
4443 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
4444 EXPECT_HR(hr
, E_NOTIMPL
);
4446 unk
= (IUnknown
*)0xdeadbeef;
4447 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
4448 EXPECT_HR(hr
, E_NOTIMPL
);
4449 ok(unk
== (IUnknown
*)0xdeadbeef, "got %p\n", unk
);
4451 name
= SysAllocString(testW
);
4452 hr
= IDispatchEx_GetDispID(dispex
, name
, fdexNameEnsure
, &did
);
4453 ok(hr
== DISP_E_UNKNOWNNAME
, "got 0x%08x\n", hr
);
4454 SysFreeString(name
);
4456 IDispatchEx_Release(dispex
);
4459 static void test_saxreader_dispex(void)
4461 IVBSAXXMLReader
*vbreader
;
4462 ISAXXMLReader
*reader
;
4463 DISPPARAMS dispparams
;
4469 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
4470 &IID_ISAXXMLReader
, (void**)&reader
);
4471 EXPECT_HR(hr
, S_OK
);
4473 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
4474 EXPECT_HR(hr
, S_OK
);
4475 test_obj_dispex(unk
);
4476 IUnknown_Release(unk
);
4478 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
4479 EXPECT_HR(hr
, S_OK
);
4480 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
4481 EXPECT_HR(hr
, S_OK
);
4482 test_obj_dispex(unk
);
4483 IUnknown_Release(unk
);
4485 dispid
= DISPID_PROPERTYPUT
;
4486 dispparams
.cArgs
= 1;
4487 dispparams
.cNamedArgs
= 1;
4488 dispparams
.rgdispidNamedArgs
= &dispid
;
4489 dispparams
.rgvarg
= &arg
;
4491 V_VT(&arg
) = VT_DISPATCH
;
4492 V_DISPATCH(&arg
) = NULL
;
4494 /* propputref is callable as PROPERTYPUT and PROPERTYPUTREF */
4495 hr
= IVBSAXXMLReader_Invoke(vbreader
,
4496 DISPID_SAX_XMLREADER_CONTENTHANDLER
,
4499 DISPATCH_PROPERTYPUT
,
4504 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4506 hr
= IVBSAXXMLReader_Invoke(vbreader
,
4507 DISPID_SAX_XMLREADER_CONTENTHANDLER
,
4510 DISPATCH_PROPERTYPUTREF
,
4515 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4517 IVBSAXXMLReader_Release(vbreader
);
4518 ISAXXMLReader_Release(reader
);
4520 if (is_clsid_supported(&CLSID_SAXXMLReader60
, reader_support_data
))
4522 hr
= CoCreateInstance(&CLSID_SAXXMLReader60
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&unk
);
4523 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4524 test_obj_dispex(unk
);
4525 IUnknown_Release(unk
);
4529 static void test_mxwriter_dispex(void)
4531 IDispatchEx
*dispex
;
4536 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4537 &IID_IMXWriter
, (void**)&writer
);
4538 EXPECT_HR(hr
, S_OK
);
4540 hr
= IMXWriter_QueryInterface(writer
, &IID_IDispatchEx
, (void**)&dispex
);
4541 EXPECT_HR(hr
, S_OK
);
4542 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4543 test_obj_dispex(unk
);
4544 IUnknown_Release(unk
);
4545 IDispatchEx_Release(dispex
);
4546 IMXWriter_Release(writer
);
4548 if (is_clsid_supported(&CLSID_MXXMLWriter60
, mxwriter_support_data
))
4550 hr
= CoCreateInstance(&CLSID_MXXMLWriter60
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&unk
);
4551 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4552 test_obj_dispex(unk
);
4553 IUnknown_Release(unk
);
4557 static void test_mxwriter_comment(void)
4559 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
4560 IVBSAXLexicalHandler
*vblexical
;
4561 ISAXContentHandler
*content
;
4562 ISAXLexicalHandler
*lexical
;
4567 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4568 &IID_IMXWriter
, (void**)&writer
);
4569 EXPECT_HR(hr
, S_OK
);
4571 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4572 EXPECT_HR(hr
, S_OK
);
4574 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4575 EXPECT_HR(hr
, S_OK
);
4577 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4578 EXPECT_HR(hr
, S_OK
);
4580 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4581 EXPECT_HR(hr
, S_OK
);
4583 hr
= ISAXContentHandler_startDocument(content
);
4584 EXPECT_HR(hr
, S_OK
);
4586 hr
= ISAXLexicalHandler_comment(lexical
, NULL
, 0);
4587 EXPECT_HR(hr
, E_INVALIDARG
);
4589 hr
= IVBSAXLexicalHandler_comment(vblexical
, NULL
);
4590 EXPECT_HR(hr
, E_POINTER
);
4592 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, 0);
4593 EXPECT_HR(hr
, S_OK
);
4595 V_VT(&dest
) = VT_EMPTY
;
4596 hr
= IMXWriter_get_output(writer
, &dest
);
4597 EXPECT_HR(hr
, S_OK
);
4598 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4599 ok(!lstrcmpW(_bstr_("<!---->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4600 VariantClear(&dest
);
4602 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, sizeof(commentW
)/sizeof(WCHAR
)-1);
4603 EXPECT_HR(hr
, S_OK
);
4605 V_VT(&dest
) = VT_EMPTY
;
4606 hr
= IMXWriter_get_output(writer
, &dest
);
4607 EXPECT_HR(hr
, S_OK
);
4608 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4609 ok(!lstrcmpW(_bstr_("<!---->\r\n<!--comment-->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4610 VariantClear(&dest
);
4612 ISAXContentHandler_Release(content
);
4613 ISAXLexicalHandler_Release(lexical
);
4614 IVBSAXLexicalHandler_Release(vblexical
);
4615 IMXWriter_Release(writer
);
4619 static void test_mxwriter_cdata(void)
4621 IVBSAXLexicalHandler
*vblexical
;
4622 ISAXContentHandler
*content
;
4623 ISAXLexicalHandler
*lexical
;
4628 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4629 &IID_IMXWriter
, (void**)&writer
);
4630 EXPECT_HR(hr
, S_OK
);
4632 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4633 EXPECT_HR(hr
, S_OK
);
4635 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4636 EXPECT_HR(hr
, S_OK
);
4638 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4639 EXPECT_HR(hr
, S_OK
);
4641 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4642 EXPECT_HR(hr
, S_OK
);
4644 hr
= ISAXContentHandler_startDocument(content
);
4645 EXPECT_HR(hr
, S_OK
);
4647 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4648 EXPECT_HR(hr
, S_OK
);
4650 V_VT(&dest
) = VT_EMPTY
;
4651 hr
= IMXWriter_get_output(writer
, &dest
);
4652 EXPECT_HR(hr
, S_OK
);
4653 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4654 ok(!lstrcmpW(_bstr_("<![CDATA["), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4655 VariantClear(&dest
);
4657 hr
= IVBSAXLexicalHandler_startCDATA(vblexical
);
4658 EXPECT_HR(hr
, S_OK
);
4660 /* all these are escaped for text nodes */
4661 hr
= ISAXContentHandler_characters(content
, _bstr_("< > & \""), 7);
4662 EXPECT_HR(hr
, S_OK
);
4664 hr
= ISAXLexicalHandler_endCDATA(lexical
);
4665 EXPECT_HR(hr
, S_OK
);
4667 V_VT(&dest
) = VT_EMPTY
;
4668 hr
= IMXWriter_get_output(writer
, &dest
);
4669 EXPECT_HR(hr
, S_OK
);
4670 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4671 ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4672 VariantClear(&dest
);
4674 ISAXContentHandler_Release(content
);
4675 ISAXLexicalHandler_Release(lexical
);
4676 IVBSAXLexicalHandler_Release(vblexical
);
4677 IMXWriter_Release(writer
);
4681 static void test_mxwriter_pi(void)
4683 static const WCHAR targetW
[] = {'t','a','r','g','e','t',0};
4684 static const WCHAR dataW
[] = {'d','a','t','a',0};
4685 ISAXContentHandler
*content
;
4690 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4691 &IID_IMXWriter
, (void**)&writer
);
4692 EXPECT_HR(hr
, S_OK
);
4694 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4695 EXPECT_HR(hr
, S_OK
);
4697 hr
= ISAXContentHandler_processingInstruction(content
, NULL
, 0, NULL
, 0);
4698 EXPECT_HR(hr
, E_INVALIDARG
);
4700 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 0, NULL
, 0);
4701 EXPECT_HR(hr
, S_OK
);
4703 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, NULL
, 0);
4704 EXPECT_HR(hr
, S_OK
);
4706 V_VT(&dest
) = VT_EMPTY
;
4707 hr
= IMXWriter_get_output(writer
, &dest
);
4708 EXPECT_HR(hr
, S_OK
);
4709 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4710 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4711 VariantClear(&dest
);
4713 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 4, dataW
, 4);
4714 EXPECT_HR(hr
, S_OK
);
4716 V_VT(&dest
) = VT_EMPTY
;
4717 hr
= IMXWriter_get_output(writer
, &dest
);
4718 EXPECT_HR(hr
, S_OK
);
4719 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4720 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
)));
4721 VariantClear(&dest
);
4723 V_VT(&dest
) = VT_EMPTY
;
4724 hr
= IMXWriter_put_output(writer
, dest
);
4725 EXPECT_HR(hr
, S_OK
);
4727 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, dataW
, 0);
4728 EXPECT_HR(hr
, S_OK
);
4730 V_VT(&dest
) = VT_EMPTY
;
4731 hr
= IMXWriter_get_output(writer
, &dest
);
4732 EXPECT_HR(hr
, S_OK
);
4733 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4734 ok(!lstrcmpW(_bstr_("<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4735 VariantClear(&dest
);
4738 ISAXContentHandler_Release(content
);
4739 IMXWriter_Release(writer
);
4742 static void test_mxwriter_ignorablespaces(void)
4744 static const WCHAR dataW
[] = {'d','a','t','a',0};
4745 ISAXContentHandler
*content
;
4750 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4751 &IID_IMXWriter
, (void**)&writer
);
4752 EXPECT_HR(hr
, S_OK
);
4754 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4755 EXPECT_HR(hr
, S_OK
);
4757 hr
= ISAXContentHandler_ignorableWhitespace(content
, NULL
, 0);
4758 EXPECT_HR(hr
, E_INVALIDARG
);
4760 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 0);
4761 EXPECT_HR(hr
, S_OK
);
4763 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 4);
4764 EXPECT_HR(hr
, S_OK
);
4766 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 1);
4767 EXPECT_HR(hr
, S_OK
);
4769 V_VT(&dest
) = VT_EMPTY
;
4770 hr
= IMXWriter_get_output(writer
, &dest
);
4771 EXPECT_HR(hr
, S_OK
);
4772 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4773 ok(!lstrcmpW(_bstr_("datad"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4774 VariantClear(&dest
);
4776 ISAXContentHandler_Release(content
);
4777 IMXWriter_Release(writer
);
4780 static void test_mxwriter_dtd(void)
4782 static const WCHAR contentW
[] = {'c','o','n','t','e','n','t'};
4783 static const WCHAR nameW
[] = {'n','a','m','e'};
4784 static const WCHAR pubW
[] = {'p','u','b'};
4785 static const WCHAR sysW
[] = {'s','y','s'};
4786 IVBSAXLexicalHandler
*vblexical
;
4787 ISAXContentHandler
*content
;
4788 ISAXLexicalHandler
*lexical
;
4789 IVBSAXDeclHandler
*vbdecl
;
4790 ISAXDeclHandler
*decl
;
4795 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4796 &IID_IMXWriter
, (void**)&writer
);
4797 EXPECT_HR(hr
, S_OK
);
4799 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4800 EXPECT_HR(hr
, S_OK
);
4802 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4803 EXPECT_HR(hr
, S_OK
);
4805 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
4806 EXPECT_HR(hr
, S_OK
);
4808 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXDeclHandler
, (void**)&vbdecl
);
4809 EXPECT_HR(hr
, S_OK
);
4811 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4812 EXPECT_HR(hr
, S_OK
);
4814 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4815 EXPECT_HR(hr
, S_OK
);
4817 hr
= ISAXContentHandler_startDocument(content
);
4818 EXPECT_HR(hr
, S_OK
);
4820 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, NULL
, 0);
4821 EXPECT_HR(hr
, E_INVALIDARG
);
4823 hr
= IVBSAXLexicalHandler_startDTD(vblexical
, NULL
, NULL
, NULL
);
4824 EXPECT_HR(hr
, E_POINTER
);
4826 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4827 EXPECT_HR(hr
, E_INVALIDARG
);
4829 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4830 EXPECT_HR(hr
, E_INVALIDARG
);
4832 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4833 EXPECT_HR(hr
, E_INVALIDARG
);
4835 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0, NULL
, 0);
4836 EXPECT_HR(hr
, S_OK
);
4838 V_VT(&dest
) = VT_EMPTY
;
4839 hr
= IMXWriter_get_output(writer
, &dest
);
4840 EXPECT_HR(hr
, S_OK
);
4841 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4842 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4843 VariantClear(&dest
);
4845 /* system id is required if public is present */
4846 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4847 EXPECT_HR(hr
, E_INVALIDARG
);
4849 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
),
4850 pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4851 EXPECT_HR(hr
, S_OK
);
4853 V_VT(&dest
) = VT_EMPTY
;
4854 hr
= IMXWriter_get_output(writer
, &dest
);
4855 EXPECT_HR(hr
, S_OK
);
4856 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4857 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4858 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4859 VariantClear(&dest
);
4861 hr
= ISAXLexicalHandler_endDTD(lexical
);
4862 EXPECT_HR(hr
, S_OK
);
4864 hr
= IVBSAXLexicalHandler_endDTD(vblexical
);
4865 EXPECT_HR(hr
, S_OK
);
4867 V_VT(&dest
) = VT_EMPTY
;
4868 hr
= IMXWriter_get_output(writer
, &dest
);
4869 EXPECT_HR(hr
, S_OK
);
4870 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4871 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4872 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n"),
4873 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4874 VariantClear(&dest
);
4876 /* element declaration */
4877 V_VT(&dest
) = VT_EMPTY
;
4878 hr
= IMXWriter_put_output(writer
, dest
);
4879 EXPECT_HR(hr
, S_OK
);
4881 hr
= ISAXDeclHandler_elementDecl(decl
, NULL
, 0, NULL
, 0);
4882 EXPECT_HR(hr
, E_INVALIDARG
);
4884 hr
= IVBSAXDeclHandler_elementDecl(vbdecl
, NULL
, NULL
);
4885 EXPECT_HR(hr
, E_POINTER
);
4887 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0);
4888 EXPECT_HR(hr
, E_INVALIDARG
);
4890 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, sizeof(contentW
)/sizeof(WCHAR
));
4891 EXPECT_HR(hr
, S_OK
);
4893 V_VT(&dest
) = VT_EMPTY
;
4894 hr
= IMXWriter_get_output(writer
, &dest
);
4895 EXPECT_HR(hr
, S_OK
);
4896 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4897 ok(!lstrcmpW(_bstr_("<!ELEMENT name content>\r\n"),
4898 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4899 VariantClear(&dest
);
4901 V_VT(&dest
) = VT_EMPTY
;
4902 hr
= IMXWriter_put_output(writer
, dest
);
4903 EXPECT_HR(hr
, S_OK
);
4905 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, 0);
4906 EXPECT_HR(hr
, S_OK
);
4908 V_VT(&dest
) = VT_EMPTY
;
4909 hr
= IMXWriter_get_output(writer
, &dest
);
4910 EXPECT_HR(hr
, S_OK
);
4911 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4912 ok(!lstrcmpW(_bstr_("<!ELEMENT name >\r\n"),
4913 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4914 VariantClear(&dest
);
4916 /* attribute declaration */
4917 V_VT(&dest
) = VT_EMPTY
;
4918 hr
= IMXWriter_put_output(writer
, dest
);
4919 EXPECT_HR(hr
, S_OK
);
4921 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4922 _bstr_("attribute"), strlen("attribute"), _bstr_("CDATA"), strlen("CDATA"),
4923 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value"), strlen("value"));
4924 EXPECT_HR(hr
, S_OK
);
4926 V_VT(&dest
) = VT_EMPTY
;
4927 hr
= IMXWriter_get_output(writer
, &dest
);
4928 EXPECT_HR(hr
, S_OK
);
4929 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4930 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"),
4931 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4932 VariantClear(&dest
);
4934 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4935 _bstr_("attribute2"), strlen("attribute2"), _bstr_("CDATA"), strlen("CDATA"),
4936 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value2"), strlen("value2"));
4937 EXPECT_HR(hr
, S_OK
);
4939 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element2"), strlen("element2"),
4940 _bstr_("attribute3"), strlen("attribute3"), _bstr_("CDATA"), strlen("CDATA"),
4941 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value3"), strlen("value3"));
4942 EXPECT_HR(hr
, S_OK
);
4944 V_VT(&dest
) = VT_EMPTY
;
4945 hr
= IMXWriter_get_output(writer
, &dest
);
4946 EXPECT_HR(hr
, S_OK
);
4947 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4948 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"
4949 "<!ATTLIST element attribute2 CDATA #REQUIRED \"value2\">\r\n"
4950 "<!ATTLIST element2 attribute3 CDATA #REQUIRED \"value3\">\r\n"),
4951 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4952 VariantClear(&dest
);
4954 /* internal entities */
4955 V_VT(&dest
) = VT_EMPTY
;
4956 hr
= IMXWriter_put_output(writer
, dest
);
4957 EXPECT_HR(hr
, S_OK
);
4959 hr
= ISAXDeclHandler_internalEntityDecl(decl
, NULL
, 0, NULL
, 0);
4960 EXPECT_HR(hr
, E_INVALIDARG
);
4962 hr
= IVBSAXDeclHandler_internalEntityDecl(vbdecl
, NULL
, NULL
);
4963 EXPECT_HR(hr
, E_POINTER
);
4965 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0);
4966 EXPECT_HR(hr
, E_INVALIDARG
);
4968 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("value"), strlen("value"));
4969 EXPECT_HR(hr
, S_OK
);
4971 V_VT(&dest
) = VT_EMPTY
;
4972 hr
= IMXWriter_get_output(writer
, &dest
);
4973 EXPECT_HR(hr
, S_OK
);
4974 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4975 ok(!lstrcmpW(_bstr_("<!ENTITY name \"value\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4976 VariantClear(&dest
);
4978 /* external entities */
4979 V_VT(&dest
) = VT_EMPTY
;
4980 hr
= IMXWriter_put_output(writer
, dest
);
4981 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4983 hr
= ISAXDeclHandler_externalEntityDecl(decl
, NULL
, 0, NULL
, 0, NULL
, 0);
4984 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4986 hr
= IVBSAXDeclHandler_externalEntityDecl(vbdecl
, NULL
, NULL
, NULL
);
4987 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
4989 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0, NULL
, 0);
4990 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4992 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"),
4993 _bstr_("sysid"), strlen("sysid"));
4994 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4996 V_VT(&dest
) = VT_EMPTY
;
4997 hr
= IMXWriter_get_output(writer
, &dest
);
4998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4999 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
5000 ok(!lstrcmpW(_bstr_("<!ENTITY name PUBLIC \"pubid\" \"sysid\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
5001 VariantClear(&dest
);
5003 ISAXContentHandler_Release(content
);
5004 ISAXLexicalHandler_Release(lexical
);
5005 IVBSAXLexicalHandler_Release(vblexical
);
5006 IVBSAXDeclHandler_Release(vbdecl
);
5007 ISAXDeclHandler_Release(decl
);
5008 IMXWriter_Release(writer
);
5020 } addattribute_test_t
;
5022 static const addattribute_test_t addattribute_data
[] = {
5023 { &CLSID_SAXAttributes
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5024 { &CLSID_SAXAttributes30
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5025 { &CLSID_SAXAttributes40
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5026 { &CLSID_SAXAttributes60
, NULL
, NULL
, "ns:qname", NULL
, "value", S_OK
},
5028 { &CLSID_SAXAttributes
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5029 { &CLSID_SAXAttributes30
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5030 { &CLSID_SAXAttributes40
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5031 { &CLSID_SAXAttributes60
, NULL
, "qname", "ns:qname", NULL
, "value", S_OK
},
5033 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5034 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5035 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5036 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", NULL
, "value", S_OK
},
5038 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5039 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5040 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5041 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5046 static void test_mxattr_addAttribute(void)
5048 const addattribute_test_t
*table
= addattribute_data
;
5051 while (table
->clsid
)
5053 ISAXAttributes
*saxattr
;
5054 IMXAttributes
*mxattr
;
5059 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5066 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5067 &IID_IMXAttributes
, (void**)&mxattr
);
5068 EXPECT_HR(hr
, S_OK
);
5070 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5071 EXPECT_HR(hr
, S_OK
);
5073 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
5074 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5075 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5077 hr
= ISAXAttributes_getLength(saxattr
, NULL
);
5078 EXPECT_HR(hr
, E_POINTER
);
5082 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5083 EXPECT_HR(hr
, S_OK
);
5084 ok(len
== 0, "got %d\n", len
);
5086 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
5087 EXPECT_HR(hr
, E_INVALIDARG
);
5089 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
5090 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5092 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
5093 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5095 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
5096 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5098 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
5099 EXPECT_HR(hr
, E_INVALIDARG
);
5101 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
5102 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5104 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
5105 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5107 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
5108 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5110 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_(table
->uri
), _bstr_(table
->local
),
5111 _bstr_(table
->qname
), _bstr_(table
->type
), _bstr_(table
->value
));
5112 ok(hr
== table
->hr
, "%d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
5116 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
5117 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5118 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5120 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
5121 EXPECT_HR(hr
, E_POINTER
);
5123 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
5124 EXPECT_HR(hr
, E_POINTER
);
5126 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
5127 EXPECT_HR(hr
, E_POINTER
);
5129 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
5130 EXPECT_HR(hr
, E_POINTER
);
5132 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
5133 EXPECT_HR(hr
, E_POINTER
);
5135 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
5136 EXPECT_HR(hr
, E_POINTER
);
5140 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
5141 EXPECT_HR(hr
, S_OK
);
5142 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5144 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5147 value
= (void*)0xdeadbeef;
5148 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
5149 EXPECT_HR(hr
, S_OK
);
5153 ok(!lstrcmpW(_bstr_(table
->type
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5155 ok(lstrlenW(value
) == len
, "%d: got wrong type value length %d\n", i
, len
);
5159 ok(*value
== 0, "%d: got type value %s\n", i
, wine_dbgstr_w(value
));
5160 ok(len
== 0, "%d: got wrong type value length %d\n", i
, len
);
5163 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, NULL
);
5164 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5165 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5167 EXPECT_HR(hr
, E_POINTER
);
5170 EXPECT_HR(hr
, E_INVALIDARG
);
5172 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, &index
);
5173 EXPECT_HR(hr
, E_INVALIDARG
);
5176 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_("nonexistent"), 11, &index
);
5177 EXPECT_HR(hr
, E_INVALIDARG
);
5178 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5181 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), 0, &index
);
5182 EXPECT_HR(hr
, E_INVALIDARG
);
5183 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5186 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &index
);
5187 EXPECT_HR(hr
, S_OK
);
5188 ok(index
== 0, "%d: got wrong index %d\n", i
, index
);
5191 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
)-1, &index
);
5192 EXPECT_HR(hr
, E_INVALIDARG
);
5193 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5195 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes40
) ||
5196 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes60
))
5198 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
5199 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5201 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
5202 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5204 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
5205 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5207 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
5208 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5210 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
5211 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5213 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
5214 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5218 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
5219 EXPECT_HR(hr
, E_POINTER
);
5221 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
5222 EXPECT_HR(hr
, E_POINTER
);
5224 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
5225 EXPECT_HR(hr
, E_POINTER
);
5227 /* versions 4 and 6 crash */
5228 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, NULL
);
5229 EXPECT_HR(hr
, E_POINTER
);
5231 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, &len
);
5232 EXPECT_HR(hr
, E_POINTER
);
5234 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
5235 EXPECT_HR(hr
, E_POINTER
);
5237 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
5238 EXPECT_HR(hr
, E_POINTER
);
5240 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
5241 EXPECT_HR(hr
, E_POINTER
);
5243 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, &value
, NULL
);
5244 EXPECT_HR(hr
, E_POINTER
);
5246 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, NULL
, &len
);
5247 EXPECT_HR(hr
, E_POINTER
);
5249 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
), _bstr_(table
->local
),
5250 strlen(table
->local
), NULL
, NULL
);
5251 EXPECT_HR(hr
, E_POINTER
);
5254 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &value
, &len
);
5255 EXPECT_HR(hr
, S_OK
);
5256 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5258 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5261 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
),
5262 _bstr_(table
->local
), strlen(table
->local
), &value
, &len
);
5263 EXPECT_HR(hr
, S_OK
);
5264 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5266 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5271 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5272 EXPECT_HR(hr
, S_OK
);
5273 if (table
->hr
== S_OK
)
5274 ok(len
== 1, "%d: got %d length, expected 1\n", i
, len
);
5276 ok(len
== 0, "%d: got %d length, expected 0\n", i
, len
);
5278 ISAXAttributes_Release(saxattr
);
5279 IMXAttributes_Release(mxattr
);
5288 static void test_mxattr_clear(void)
5290 ISAXAttributes
*saxattr
;
5291 IMXAttributes
*mxattr
;
5296 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5297 &IID_IMXAttributes
, (void**)&mxattr
);
5298 EXPECT_HR(hr
, S_OK
);
5300 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5301 EXPECT_HR(hr
, S_OK
);
5303 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, NULL
);
5304 EXPECT_HR(hr
, E_INVALIDARG
);
5306 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5307 EXPECT_HR(hr
, E_INVALIDARG
);
5309 hr
= IMXAttributes_clear(mxattr
);
5310 EXPECT_HR(hr
, S_OK
);
5312 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("local"),
5313 _bstr_("qname"), _bstr_("type"), _bstr_("value"));
5314 EXPECT_HR(hr
, S_OK
);
5317 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5318 EXPECT_HR(hr
, S_OK
);
5319 ok(len
== 1, "got %d\n", len
);
5322 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, &len
);
5323 EXPECT_HR(hr
, E_POINTER
);
5324 ok(len
== -1, "got %d\n", len
);
5326 ptr
= (void*)0xdeadbeef;
5327 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, NULL
);
5328 EXPECT_HR(hr
, E_POINTER
);
5329 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5332 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5333 EXPECT_HR(hr
, S_OK
);
5334 ok(len
== 5, "got %d\n", len
);
5335 ok(!lstrcmpW(ptr
, _bstr_("qname")), "got %s\n", wine_dbgstr_w(ptr
));
5337 hr
= IMXAttributes_clear(mxattr
);
5338 EXPECT_HR(hr
, S_OK
);
5341 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5342 EXPECT_HR(hr
, S_OK
);
5343 ok(len
== 0, "got %d\n", len
);
5346 ptr
= (void*)0xdeadbeef;
5347 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5348 EXPECT_HR(hr
, E_INVALIDARG
);
5349 ok(len
== -1, "got %d\n", len
);
5350 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5352 IMXAttributes_Release(mxattr
);
5353 ISAXAttributes_Release(saxattr
);
5357 static void test_mxattr_dispex(void)
5359 IMXAttributes
*mxattr
;
5360 IDispatchEx
*dispex
;
5364 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5365 &IID_IMXAttributes
, (void**)&mxattr
);
5366 EXPECT_HR(hr
, S_OK
);
5368 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IDispatchEx
, (void**)&dispex
);
5369 EXPECT_HR(hr
, S_OK
);
5370 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
5371 test_obj_dispex(unk
);
5372 IUnknown_Release(unk
);
5373 IDispatchEx_Release(dispex
);
5375 IMXAttributes_Release(mxattr
);
5378 static void test_mxattr_qi(void)
5380 IVBSAXAttributes
*vbsaxattr
, *vbsaxattr2
;
5381 ISAXAttributes
*saxattr
;
5382 IMXAttributes
*mxattr
;
5385 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5386 &IID_IMXAttributes
, (void**)&mxattr
);
5387 EXPECT_HR(hr
, S_OK
);
5389 EXPECT_REF(mxattr
, 1);
5390 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5391 EXPECT_HR(hr
, S_OK
);
5393 EXPECT_REF(mxattr
, 2);
5394 EXPECT_REF(saxattr
, 2);
5396 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr
);
5397 EXPECT_HR(hr
, S_OK
);
5399 EXPECT_REF(vbsaxattr
, 3);
5400 EXPECT_REF(mxattr
, 3);
5401 EXPECT_REF(saxattr
, 3);
5403 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr2
);
5404 EXPECT_HR(hr
, S_OK
);
5406 EXPECT_REF(vbsaxattr
, 4);
5407 EXPECT_REF(mxattr
, 4);
5408 EXPECT_REF(saxattr
, 4);
5410 IMXAttributes_Release(mxattr
);
5411 ISAXAttributes_Release(saxattr
);
5412 IVBSAXAttributes_Release(vbsaxattr
);
5413 IVBSAXAttributes_Release(vbsaxattr2
);
5416 static struct msxmlsupported_data_t saxattr_support_data
[] =
5418 { &CLSID_SAXAttributes
, "SAXAttributes" },
5419 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
5420 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
5421 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
5425 static void test_mxattr_localname(void)
5427 static const WCHAR localname1W
[] = {'l','o','c','a','l','n','a','m','e','1',0};
5428 static const WCHAR localnameW
[] = {'l','o','c','a','l','n','a','m','e',0};
5429 static const WCHAR uri1W
[] = {'u','r','i','1',0};
5430 static const WCHAR uriW
[] = {'u','r','i',0};
5432 const struct msxmlsupported_data_t
*table
= saxattr_support_data
;
5434 while (table
->clsid
)
5436 ISAXAttributes
*saxattr
;
5437 IMXAttributes
*mxattr
;
5441 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5447 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5448 &IID_IMXAttributes
, (void**)&mxattr
);
5449 EXPECT_HR(hr
, S_OK
);
5451 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5452 EXPECT_HR(hr
, S_OK
);
5454 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, &index
);
5455 EXPECT_HR(hr
, E_INVALIDARG
);
5457 /* add some ambiguos attribute names */
5458 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5459 _bstr_("a:localname"), _bstr_(""), _bstr_("value"));
5460 EXPECT_HR(hr
, S_OK
);
5461 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5462 _bstr_("b:localname"), _bstr_(""), _bstr_("value"));
5463 EXPECT_HR(hr
, S_OK
);
5466 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localnameW
, lstrlenW(localnameW
), &index
);
5467 EXPECT_HR(hr
, S_OK
);
5468 ok(index
== 0, "%s: got index %d\n", table
->name
, index
);
5471 hr
= ISAXAttributes_getIndexFromName(saxattr
, uri1W
, lstrlenW(uri1W
), localnameW
, lstrlenW(localnameW
), &index
);
5472 EXPECT_HR(hr
, E_INVALIDARG
);
5473 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5476 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), &index
);
5477 EXPECT_HR(hr
, E_INVALIDARG
);
5478 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5480 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5481 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5483 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5484 EXPECT_HR(hr
, E_POINTER
);
5486 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5487 EXPECT_HR(hr
, E_POINTER
);
5491 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5492 EXPECT_HR(hr
, E_INVALIDARG
);
5494 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5495 EXPECT_HR(hr
, E_INVALIDARG
);
5498 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), NULL
, 0, &index
);
5499 EXPECT_HR(hr
, E_INVALIDARG
);
5501 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, localname1W
, lstrlenW(localname1W
), &index
);
5502 EXPECT_HR(hr
, E_INVALIDARG
);
5506 ISAXAttributes_Release(saxattr
);
5507 IMXAttributes_Release(mxattr
);
5512 static void test_mxwriter_indent(void)
5514 ISAXContentHandler
*content
;
5519 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMXWriter
, (void**)&writer
);
5520 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
5522 hr
= IMXWriter_put_indent(writer
, VARIANT_TRUE
);
5523 ok(hr
== S_OK
, "got %08x\n", hr
);
5525 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
5526 ok(hr
== S_OK
, "got %08x\n", hr
);
5528 hr
= ISAXContentHandler_startDocument(content
);
5529 ok(hr
== S_OK
, "got %08x\n", hr
);
5531 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
5532 ok(hr
== S_OK
, "got %08x\n", hr
);
5534 hr
= ISAXContentHandler_characters(content
, _bstr_(""), 0);
5535 ok(hr
== S_OK
, "got %08x\n", hr
);
5537 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("b"), -1, NULL
);
5538 ok(hr
== S_OK
, "got %08x\n", hr
);
5540 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("c"), -1, NULL
);
5541 ok(hr
== S_OK
, "got %08x\n", hr
);
5543 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("c"), -1);
5544 ok(hr
== S_OK
, "got %08x\n", hr
);
5546 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("b"), -1);
5547 ok(hr
== S_OK
, "got %08x\n", hr
);
5549 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1);
5550 ok(hr
== S_OK
, "got %08x\n", hr
);
5552 hr
= ISAXContentHandler_endDocument(content
);
5553 ok(hr
== S_OK
, "got %08x\n", hr
);
5555 V_VT(&dest
) = VT_EMPTY
;
5556 hr
= IMXWriter_get_output(writer
, &dest
);
5557 ok(hr
== S_OK
, "got %08x\n", hr
);
5558 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
5559 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n<a><b>\r\n\t\t<c/>\r\n\t</b>\r\n</a>"), V_BSTR(&dest
)),
5560 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
5561 VariantClear(&dest
);
5563 ISAXContentHandler_Release(content
);
5564 IMXWriter_Release(writer
);
5569 START_TEST(saxreader
)
5571 ISAXXMLReader
*reader
;
5574 hr
= CoInitialize(NULL
);
5575 ok(hr
== S_OK
, "failed to init com\n");
5577 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
5578 &IID_ISAXXMLReader
, (void**)&reader
);
5582 skip("Failed to create SAXXMLReader instance\n");
5586 ISAXXMLReader_Release(reader
);
5588 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
5590 get_class_support_data(reader_support_data
, &IID_ISAXXMLReader
);
5593 test_saxreader_properties();
5594 test_saxreader_features();
5595 test_saxreader_encoding();
5596 test_saxreader_dispex();
5598 /* MXXMLWriter tests */
5599 get_class_support_data(mxwriter_support_data
, &IID_IMXWriter
);
5600 if (is_clsid_supported(&CLSID_MXXMLWriter
, mxwriter_support_data
))
5602 test_mxwriter_handlers();
5603 test_mxwriter_startenddocument();
5604 test_mxwriter_startendelement();
5605 test_mxwriter_characters();
5606 test_mxwriter_comment();
5607 test_mxwriter_cdata();
5609 test_mxwriter_ignorablespaces();
5610 test_mxwriter_dtd();
5611 test_mxwriter_properties();
5612 test_mxwriter_flush();
5613 test_mxwriter_stream();
5614 test_mxwriter_encoding();
5615 test_mxwriter_dispex();
5616 test_mxwriter_indent();
5619 win_skip("MXXMLWriter not supported\n");
5621 /* SAXAttributes tests */
5622 get_class_support_data(mxattributes_support_data
, &IID_IMXAttributes
);
5623 if (is_clsid_supported(&CLSID_SAXAttributes
, mxattributes_support_data
))
5626 test_mxattr_addAttribute();
5627 test_mxattr_clear();
5628 test_mxattr_localname();
5629 test_mxattr_dispex();
5632 skip("SAXAttributes not supported\n");