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 inline void flush_sequences(struct call_sequence
**seq
, int n
)
316 for (i
= 0; i
< n
; i
++)
317 flush_sequence(seq
, i
);
320 static const char *get_event_name(CH event
)
322 return event_names
[event
];
325 static void compare_attributes(const struct call_entry
*actual
, const struct call_entry
*expected
, const char *context
,
326 BOOL todo
, const char *file
, int line
, int *failcount
)
330 /* attribute count is not stored for expected data */
331 if (expected
->attributes
)
333 struct attribute_entry
*ptr
= expected
->attributes
;
334 while (ptr
->uri
) { lenexp
++; ptr
++; };
337 /* check count first and exit earlier */
338 if (actual
->attr_count
!= lenexp
&& todo
)
342 ok_(file
, line
) (FALSE
, "%s: in event %s expecting attr count %d got %d\n",
343 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
346 ok_(file
, line
) (actual
->attr_count
== lenexp
, "%s: in event %s expecting attr count %d got %d\n",
347 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
349 if (actual
->attr_count
!= lenexp
) return;
351 /* now compare all attributes strings */
352 for (i
= 0; i
< actual
->attr_count
; i
++)
354 test_saxstr(file
, line
, actual
->attributes
[i
].uriW
, expected
->attributes
[i
].uri
, todo
, failcount
);
355 test_saxstr(file
, line
, actual
->attributes
[i
].localW
, expected
->attributes
[i
].local
, todo
, failcount
);
356 test_saxstr(file
, line
, actual
->attributes
[i
].qnameW
, expected
->attributes
[i
].qname
, todo
, failcount
);
357 test_saxstr(file
, line
, actual
->attributes
[i
].valueW
, expected
->attributes
[i
].value
, todo
, failcount
);
361 static void ok_sequence_(struct call_sequence
**seq
, int sequence_index
,
362 const struct call_entry
*expected
, const char *context
, BOOL todo
,
363 const char *file
, int line
)
365 struct call_sequence
*call_seq
= seq
[sequence_index
];
366 static const struct call_entry end_of_sequence
= { CH_ENDTEST
};
367 const struct call_entry
*actual
, *sequence
;
370 add_call(seq
, sequence_index
, &end_of_sequence
);
372 sequence
= call_seq
->sequence
;
375 while (expected
->id
!= CH_ENDTEST
&& actual
->id
!= CH_ENDTEST
)
377 if (expected
->id
== actual
->id
)
379 if (expected
->line
!= -1)
381 /* always test position data */
382 if (expected
->line
!= actual
->line
&& todo
)
387 ok_(file
, line
) (FALSE
,
388 "%s: in event %s expecting line %d got %d\n",
389 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
394 ok_(file
, line
) (expected
->line
== actual
->line
,
395 "%s: in event %s expecting line %d got %d\n",
396 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
401 if (expected
->column
!= -1)
403 if (expected
->column
!= actual
->column
&& todo
)
408 ok_(file
, line
) (FALSE
,
409 "%s: in event %s expecting column %d got %d\n",
410 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
415 ok_(file
, line
) (expected
->column
== actual
->column
,
416 "%s: in event %s expecting column %d got %d\n",
417 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
423 case CH_PUTDOCUMENTLOCATOR
:
424 case CH_STARTDOCUMENT
:
429 case CH_STARTPREFIXMAPPING
:
431 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
432 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
434 case CH_ENDPREFIXMAPPING
:
436 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
438 case CH_STARTELEMENT
:
439 /* compare attributes */
440 compare_attributes(actual
, expected
, context
, todo
, file
, line
, &failcount
);
443 /* uri, localname, qname */
444 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
445 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
446 test_saxstr(file
, line
, actual
->arg3W
, expected
->arg3
, todo
, &failcount
);
449 case CH_IGNORABLEWHITESPACE
:
451 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
453 case CH_PROCESSINGINSTRUCTION
:
455 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
456 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
458 case CH_SKIPPEDENTITY
:
460 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
463 /* test return value only */
464 if (expected
->ret
!= actual
->ret
&& todo
)
467 ok_(file
, line
) (FALSE
,
468 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
469 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
472 ok_(file
, line
) (expected
->ret
== actual
->ret
,
473 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
474 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
477 case EH_IGNORABLEWARNING
:
479 ok(0, "%s: callback not handled, %s\n", context
, get_event_name(actual
->id
));
489 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
490 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
493 flush_sequence(seq
, sequence_index
);
498 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
499 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
509 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
));
517 else if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
519 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
520 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
523 if (todo
&& !failcount
) /* succeeded yet marked todo */
527 ok_(file
, line
)(TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
531 flush_sequence(seq
, sequence_index
);
534 #define ok_sequence(seq, index, exp, contx, todo) \
535 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
537 static void init_call_sequences(struct call_sequence
**seq
, int n
)
541 for (i
= 0; i
< n
; i
++)
542 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct call_sequence
));
545 static const WCHAR szSimpleXML
[] = {
546 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
547 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
548 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
549 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
550 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
553 static const WCHAR carriage_ret_test
[] = {
554 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
555 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
556 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
557 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
558 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
561 static const WCHAR szUtf16XML
[] = {
562 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
563 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
564 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
567 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
569 static const CHAR szUtf8XML
[] =
570 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
572 static const char utf8xml2
[] =
573 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n";
575 static const char testXML
[] =
576 "<?xml version=\"1.0\" ?>\n"
578 " <Number>1234</Number>\n"
579 " <Name>Captain Ahab</Name>\n"
582 static const char test_attributes
[] =
583 "<?xml version=\"1.0\" ?>\n"
584 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
585 "<node1 xmlns:p=\"test\" />"
588 static const char test_cdata_xml
[] =
589 "<?xml version=\"1.0\" ?>"
590 "<a><![CDATA[Some \r\ntext\n\r\ndata\n\n]]></a>";
592 static const char test2_cdata_xml
[] =
593 "<?xml version=\"1.0\" ?>"
594 "<a><![CDATA[\n\r\nSome \r\ntext\n\r\ndata\n\n]]></a>";
596 static const char test3_cdata_xml
[] =
597 "<?xml version=\"1.0\" ?><a><![CDATA[Some text data]]></a>";
599 static struct call_entry content_handler_test1
[] = {
600 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
601 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
602 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
603 { CH_CHARACTERS
, 2, 14, S_OK
, "\n " },
604 { CH_STARTELEMENT
, 3, 12, S_OK
, "", "Number", "Number" },
605 { CH_CHARACTERS
, 3, 12, S_OK
, "1234" },
606 { CH_ENDELEMENT
, 3, 18, S_OK
, "", "Number", "Number" },
607 { CH_CHARACTERS
, 3, 25, S_OK
, "\n " },
608 { CH_STARTELEMENT
, 4, 10, S_OK
, "", "Name", "Name" },
609 { CH_CHARACTERS
, 4, 10, S_OK
, "Captain Ahab" },
610 { CH_ENDELEMENT
, 4, 24, S_OK
, "", "Name", "Name" },
611 { CH_CHARACTERS
, 4, 29, S_OK
, "\n" },
612 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
613 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
617 /* applies to versions 4 and 6 */
618 static struct call_entry content_handler_test1_alternate
[] = {
619 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
620 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
621 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
622 { CH_CHARACTERS
, 3, 4, S_OK
, "\n " },
623 { CH_STARTELEMENT
, 3, 11, S_OK
, "", "Number", "Number" },
624 { CH_CHARACTERS
, 3, 16, S_OK
, "1234" },
625 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "Number", "Number" },
626 { CH_CHARACTERS
, 4, 4, S_OK
, "\n " },
627 { CH_STARTELEMENT
, 4, 9, S_OK
, "", "Name", "Name" },
628 { CH_CHARACTERS
, 4, 22, S_OK
, "Captain Ahab" },
629 { CH_ENDELEMENT
, 4, 28, S_OK
, "", "Name", "Name" },
630 { CH_CHARACTERS
, 5, 1, S_OK
, "\n" },
631 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
632 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
636 static struct call_entry content_handler_test2
[] = {
637 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
638 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
639 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
640 { CH_CHARACTERS
, 2, 14, S_OK
, "\n" },
641 { CH_CHARACTERS
, 2, 16, S_OK
, "\t" },
642 { CH_STARTELEMENT
, 3, 10, S_OK
, "", "Number", "Number" },
643 { CH_CHARACTERS
, 3, 10, S_OK
, "1234" },
644 { CH_ENDELEMENT
, 3, 16, S_OK
, "", "Number", "Number" },
645 { CH_CHARACTERS
, 3, 23, S_OK
, "\n" },
646 { CH_CHARACTERS
, 3, 25, S_OK
, "\t" },
647 { CH_STARTELEMENT
, 4, 8, S_OK
, "", "Name", "Name" },
648 { CH_CHARACTERS
, 4, 8, S_OK
, "Captain Ahab" },
649 { CH_ENDELEMENT
, 4, 22, S_OK
, "", "Name", "Name" },
650 { CH_CHARACTERS
, 4, 27, S_OK
, "\n" },
651 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
652 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
656 static struct call_entry content_handler_test2_alternate
[] = {
657 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
658 { CH_STARTDOCUMENT
, 1, 21, S_OK
},
659 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
660 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
661 { CH_CHARACTERS
, 3, 2, S_OK
, "\t" },
662 { CH_STARTELEMENT
, 3, 9, S_OK
, "", "Number", "Number" },
663 { CH_CHARACTERS
, 3, 14, S_OK
, "1234" },
664 { CH_ENDELEMENT
, 3, 22, S_OK
, "", "Number", "Number" },
665 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
666 { CH_CHARACTERS
, 4, 2, S_OK
, "\t" },
667 { CH_STARTELEMENT
, 4, 7, S_OK
, "", "Name", "Name" },
668 { CH_CHARACTERS
, 4, 20, S_OK
, "Captain Ahab" },
669 { CH_ENDELEMENT
, 4, 26, S_OK
, "", "Name", "Name" },
670 { CH_CHARACTERS
, 5, 0, S_OK
, "\n" },
671 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
672 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
676 static struct call_entry content_handler_testerror
[] = {
677 { CH_PUTDOCUMENTLOCATOR
, 0, 0, E_FAIL
},
678 { EH_FATALERROR
, 0, 0, E_FAIL
},
682 static struct call_entry content_handler_testerror_alternate
[] = {
683 { CH_PUTDOCUMENTLOCATOR
, 1, 0, E_FAIL
},
684 { EH_FATALERROR
, 1, 0, E_FAIL
},
688 static struct call_entry content_handler_test_callback_rets
[] = {
689 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_FALSE
},
690 { CH_STARTDOCUMENT
, 0, 0, S_FALSE
},
691 { EH_FATALERROR
, 0, 0, S_FALSE
},
695 static struct call_entry content_handler_test_callback_rets_alt
[] = {
696 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_FALSE
},
697 { CH_STARTDOCUMENT
, 1, 22, S_FALSE
},
698 { CH_STARTELEMENT
, 2, 13, S_FALSE
, "", "BankAccount", "BankAccount" },
699 { CH_CHARACTERS
, 3, 4, S_FALSE
, "\n " },
700 { CH_STARTELEMENT
, 3, 11, S_FALSE
, "", "Number", "Number" },
701 { CH_CHARACTERS
, 3, 16, S_FALSE
, "1234" },
702 { CH_ENDELEMENT
, 3, 24, S_FALSE
, "", "Number", "Number" },
703 { CH_CHARACTERS
, 4, 4, S_FALSE
, "\n " },
704 { CH_STARTELEMENT
, 4, 9, S_FALSE
, "", "Name", "Name" },
705 { CH_CHARACTERS
, 4, 22, S_FALSE
, "Captain Ahab" },
706 { CH_ENDELEMENT
, 4, 28, S_FALSE
, "", "Name", "Name" },
707 { CH_CHARACTERS
, 5, 1, S_FALSE
, "\n" },
708 { CH_ENDELEMENT
, 5, 14, S_FALSE
, "", "BankAccount", "BankAccount" },
709 { CH_ENDDOCUMENT
, 6, 0, S_FALSE
},
713 static struct attribute_entry ch_attributes1
[] = {
714 { "", "", "xmlns:test", "prefix_test" },
715 { "", "", "xmlns", "prefix" },
716 { "prefix_test", "arg1", "test:arg1", "arg1" },
717 { "", "arg2", "arg2", "arg2" },
718 { "prefix_test", "ar3", "test:ar3", "arg3" },
722 static struct attribute_entry ch_attributes2
[] = {
723 { "", "", "xmlns:p", "test" },
727 static struct call_entry content_handler_test_attributes
[] = {
728 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
729 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
730 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
731 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
732 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes1
},
733 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
734 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
735 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
736 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
737 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
738 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
739 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
740 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
741 { CH_ENDDOCUMENT
, 0, 0 },
745 static struct attribute_entry ch_attributes_alt_4
[] = {
746 { "prefix_test", "arg1", "test:arg1", "arg1" },
747 { "", "arg2", "arg2", "arg2" },
748 { "prefix_test", "ar3", "test:ar3", "arg3" },
749 { "", "", "xmlns:test", "prefix_test" },
750 { "", "", "xmlns", "prefix" },
754 static struct call_entry content_handler_test_attributes_alternate_4
[] = {
755 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
756 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
757 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
758 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
759 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_4
},
760 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
761 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
762 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
763 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
764 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
765 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
766 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
767 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
768 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
772 /* 'namespace' feature switched off */
773 static struct attribute_entry ch_attributes_alt_no_ns
[] = {
774 { "", "", "xmlns:test", "prefix_test" },
775 { "", "", "xmlns", "prefix" },
776 { "", "", "test:arg1", "arg1" },
777 { "", "", "arg2", "arg2" },
778 { "", "", "test:ar3", "arg3" },
782 static struct call_entry content_handler_test_attributes_alt_no_ns
[] = {
783 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
784 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
785 { CH_STARTELEMENT
, 2, 95, S_OK
, "", "", "document", ch_attributes_alt_no_ns
},
786 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
787 { CH_STARTELEMENT
, 3, 24, S_OK
, "", "", "node1", ch_attributes2
},
788 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "", "node1" },
789 { CH_ENDELEMENT
, 3, 35, S_OK
, "", "", "document" },
790 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
794 static struct attribute_entry ch_attributes_alt_6
[] = {
795 { "prefix_test", "arg1", "test:arg1", "arg1" },
796 { "", "arg2", "arg2", "arg2" },
797 { "prefix_test", "ar3", "test:ar3", "arg3" },
798 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
799 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
803 static struct attribute_entry ch_attributes2_6
[] = {
804 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
808 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
809 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
810 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
811 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
812 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
813 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
814 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
815 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
816 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
817 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
818 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
819 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
820 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
821 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
822 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
826 /* 'namespaces' is on, 'namespace-prefixes' if off */
827 static struct attribute_entry ch_attributes_no_prefix
[] = {
828 { "prefix_test", "arg1", "test:arg1", "arg1" },
829 { "", "arg2", "arg2", "arg2" },
830 { "prefix_test", "ar3", "test:ar3", "arg3" },
834 static struct call_entry content_handler_test_attributes_alt_no_prefix
[] = {
835 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
836 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
837 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
838 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
839 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
840 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
841 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
842 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", NULL
},
843 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
844 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
845 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
846 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
847 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
848 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
852 static struct call_entry content_handler_test_attributes_no_prefix
[] = {
853 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
854 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
855 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
856 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
857 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
858 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
859 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
860 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", NULL
},
861 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
862 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
863 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
864 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
865 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
866 { CH_ENDDOCUMENT
, 0, 0 },
870 static struct attribute_entry xmlspace_attrs
[] = {
871 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
875 static struct call_entry xmlspaceattr_test
[] = {
876 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
877 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
878 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
879 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
880 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
881 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
885 static struct call_entry xmlspaceattr_test_alternate
[] = {
886 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
887 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
888 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
889 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
890 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
891 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
895 /* attribute value normalization test */
896 static const char attribute_normalize
[] =
897 "<?xml version=\"1.0\" ?>\n"
898 "<a attr1=\" \r \n \tattr_value A & &\t \r \n\r\n \n\"/>\n";
900 static struct attribute_entry attribute_norm_attrs
[] = {
901 { "", "attr1", "attr1", " attr_value A & & " },
905 static struct call_entry attribute_norm
[] = {
906 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
907 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
908 { CH_STARTELEMENT
, 6, 4, S_OK
, "", "a", "a", attribute_norm_attrs
},
909 { CH_ENDELEMENT
, 6, 4, S_OK
, "", "a", "a" },
910 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
914 static struct call_entry attribute_norm_alt
[] = {
915 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
916 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
917 { CH_STARTELEMENT
, 8, 3, S_OK
, "", "a", "a", attribute_norm_attrs
},
918 { CH_ENDELEMENT
, 8, 3, S_OK
, "", "a", "a" },
919 { CH_ENDDOCUMENT
, 9, 0, S_OK
},
923 static struct call_entry cdata_test
[] = {
924 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
925 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
926 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
927 { LH_STARTCDATA
, 1, 35, S_OK
},
928 { CH_CHARACTERS
, 1, 35, S_OK
, "Some \n" },
929 { CH_CHARACTERS
, 1, 42, S_OK
, "text\n\n" },
930 { CH_CHARACTERS
, 1, 49, S_OK
, "data\n\n" },
931 { LH_ENDCDATA
, 1, 49, S_OK
},
932 { CH_ENDELEMENT
, 6, 6, S_OK
, "", "a", "a" },
933 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
937 static struct call_entry cdata_test2
[] = {
938 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
939 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
940 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
941 { LH_STARTCDATA
, 1, 35, S_OK
},
942 { CH_CHARACTERS
, 1, 35, S_OK
, "\n\n" },
943 { CH_CHARACTERS
, 1, 38, S_OK
, "Some \n" },
944 { CH_CHARACTERS
, 1, 45, S_OK
, "text\n\n" },
945 { CH_CHARACTERS
, 1, 52, S_OK
, "data\n\n" },
946 { LH_ENDCDATA
, 1, 52, S_OK
},
947 { CH_ENDELEMENT
, 8, 6, S_OK
, "", "a", "a" },
948 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
952 static struct call_entry cdata_test3
[] = {
953 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
954 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
955 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
956 { LH_STARTCDATA
, 1, 35, S_OK
},
957 { CH_CHARACTERS
, 1, 35, S_OK
, "Some text data" },
958 { LH_ENDCDATA
, 1, 35, S_OK
},
959 { CH_ENDELEMENT
, 1, 54, S_OK
, "", "a", "a" },
960 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
964 /* this is what MSXML6 does */
965 static struct call_entry cdata_test_alt
[] = {
966 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
967 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
968 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
969 { LH_STARTCDATA
, 1, 34, S_OK
},
970 { CH_CHARACTERS
, 1, 40, S_OK
, "Some " },
971 { CH_CHARACTERS
, 2, 0, S_OK
, "\n" },
972 { CH_CHARACTERS
, 3, 1, S_OK
, "text\n" },
973 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
974 { CH_CHARACTERS
, 6, 3, S_OK
, "data\n\n" },
975 { LH_ENDCDATA
, 6, 3, S_OK
},
976 { CH_ENDELEMENT
, 6, 7, S_OK
, "", "a", "a" },
977 { CH_ENDDOCUMENT
, 6, 7, S_OK
},
981 static struct call_entry cdata_test2_alt
[] = {
982 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
983 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
984 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
985 { LH_STARTCDATA
, 1, 34, S_OK
},
986 { CH_CHARACTERS
, 2, 1, S_OK
, "\n" },
987 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
988 { CH_CHARACTERS
, 3, 6, S_OK
, "Some " },
989 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
990 { CH_CHARACTERS
, 5, 1, S_OK
, "text\n" },
991 { CH_CHARACTERS
, 6, 0, S_OK
, "\n" },
992 { CH_CHARACTERS
, 8, 3, S_OK
, "data\n\n" },
993 { LH_ENDCDATA
, 8, 3, S_OK
},
994 { CH_ENDELEMENT
, 8, 7, S_OK
, "", "a", "a" },
995 { CH_ENDDOCUMENT
, 8, 7, S_OK
},
999 static struct call_entry cdata_test3_alt
[] = {
1000 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
1001 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
1002 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
1003 { LH_STARTCDATA
, 1, 34, S_OK
},
1004 { CH_CHARACTERS
, 1, 51, S_OK
, "Some text data" },
1005 { LH_ENDCDATA
, 1, 51, S_OK
},
1006 { CH_ENDELEMENT
, 1, 55, S_OK
, "", "a", "a" },
1007 { CH_ENDDOCUMENT
, 1, 55, S_OK
},
1011 static struct attribute_entry read_test_attrs
[] = {
1012 { "", "attr", "attr", "val" },
1016 static struct call_entry read_test_seq
[] = {
1017 { CH_PUTDOCUMENTLOCATOR
, -1, 0, S_OK
},
1018 { CH_STARTDOCUMENT
, -1, -1, S_OK
},
1019 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1020 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1021 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1022 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1023 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1024 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1025 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1026 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1027 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1028 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1029 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1030 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1031 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1032 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1033 { CH_ENDDOCUMENT
, -1, -1, S_OK
},
1037 static const char xmlspace_attr
[] =
1038 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
1039 "<a xml:space=\"preserve\"> Some text data </a>";
1041 static struct call_entry
*expectCall
;
1042 static ISAXLocator
*locator
;
1043 static ISAXXMLReader
*g_reader
;
1046 static void set_expected_seq(struct call_entry
*expected
)
1048 expectCall
= expected
;
1051 /* to be called once on each tested callback return */
1052 static HRESULT
get_expected_ret(void)
1054 HRESULT hr
= expectCall
->ret
;
1055 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
1059 static HRESULT WINAPI
contentHandler_QueryInterface(
1060 ISAXContentHandler
* iface
,
1066 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
1072 return E_NOINTERFACE
;
1078 static ULONG WINAPI
contentHandler_AddRef(
1079 ISAXContentHandler
* iface
)
1084 static ULONG WINAPI
contentHandler_Release(
1085 ISAXContentHandler
* iface
)
1090 static HRESULT WINAPI
contentHandler_putDocumentLocator(
1091 ISAXContentHandler
* iface
,
1092 ISAXLocator
*pLocator
)
1094 struct call_entry call
;
1100 init_call_entry(locator
, &call
);
1101 call
.id
= CH_PUTDOCUMENTLOCATOR
;
1102 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1104 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXLocator
, (void**)&unk
);
1105 EXPECT_HR(hr
, E_NOINTERFACE
);
1107 if (msxml_version
>= 6) {
1108 ISAXAttributes
*attr
, *attr1
;
1109 IMXAttributes
*mxattr
;
1111 EXPECT_REF(pLocator
, 1);
1112 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
1113 EXPECT_HR(hr
, S_OK
);
1114 EXPECT_REF(pLocator
, 2);
1115 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
1116 EXPECT_HR(hr
, S_OK
);
1117 EXPECT_REF(pLocator
, 3);
1118 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
1120 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IVBSAXAttributes
, (void**)&unk
);
1121 EXPECT_HR(hr
, E_NOINTERFACE
);
1123 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXAttributes
, (void**)&unk
);
1124 EXPECT_HR(hr
, E_NOINTERFACE
);
1126 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
1127 EXPECT_HR(hr
, E_NOINTERFACE
);
1129 ISAXAttributes_Release(attr
);
1130 ISAXAttributes_Release(attr1
);
1133 return get_expected_ret();
1136 static ISAXAttributes
*test_attr_ptr
;
1137 static HRESULT WINAPI
contentHandler_startDocument(
1138 ISAXContentHandler
* iface
)
1140 struct call_entry call
;
1142 init_call_entry(locator
, &call
);
1143 call
.id
= CH_STARTDOCUMENT
;
1144 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1146 test_attr_ptr
= NULL
;
1148 return get_expected_ret();
1151 static HRESULT WINAPI
contentHandler_endDocument(
1152 ISAXContentHandler
* iface
)
1154 struct call_entry call
;
1156 init_call_entry(locator
, &call
);
1157 call
.id
= CH_ENDDOCUMENT
;
1158 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1160 return get_expected_ret();
1163 static HRESULT WINAPI
contentHandler_startPrefixMapping(
1164 ISAXContentHandler
* iface
,
1165 const WCHAR
*prefix
, int prefix_len
,
1166 const WCHAR
*uri
, int uri_len
)
1168 struct call_entry call
;
1170 init_call_entry(locator
, &call
);
1171 call
.id
= CH_STARTPREFIXMAPPING
;
1172 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
1173 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
1174 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1176 return get_expected_ret();
1179 static HRESULT WINAPI
contentHandler_endPrefixMapping(
1180 ISAXContentHandler
* iface
,
1181 const WCHAR
*prefix
, int len
)
1183 struct call_entry call
;
1185 init_call_entry(locator
, &call
);
1186 call
.id
= CH_ENDPREFIXMAPPING
;
1187 call
.arg1W
= SysAllocStringLen(prefix
, len
);
1188 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1190 return get_expected_ret();
1193 static HRESULT WINAPI
contentHandler_startElement(
1194 ISAXContentHandler
* iface
,
1195 const WCHAR
*uri
, int uri_len
,
1196 const WCHAR
*localname
, int local_len
,
1197 const WCHAR
*qname
, int qname_len
,
1198 ISAXAttributes
*saxattr
)
1200 struct call_entry call
;
1201 IMXAttributes
*mxattr
;
1205 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
1206 EXPECT_HR(hr
, E_NOINTERFACE
);
1208 init_call_entry(locator
, &call
);
1209 call
.id
= CH_STARTELEMENT
;
1210 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1211 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1212 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1215 test_attr_ptr
= saxattr
;
1216 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
1218 /* store actual attributes */
1220 hr
= ISAXAttributes_getLength(saxattr
, &len
);
1221 EXPECT_HR(hr
, S_OK
);
1228 struct attribute_entry
*attr
;
1229 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
1232 hr
= ISAXXMLReader_getFeature(g_reader
, _bstr_("http://xml.org/sax/features/namespaces"), &v
);
1233 EXPECT_HR(hr
, S_OK
);
1235 for (i
= 0; i
< len
; i
++)
1240 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
1241 &localname
, &local_len
, &qname
, &qname_len
);
1242 EXPECT_HR(hr
, S_OK
);
1244 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
1245 EXPECT_HR(hr
, S_OK
);
1247 /* if 'namespaces' switched off uri and local name contains garbage */
1248 if (v
== VARIANT_FALSE
&& msxml_version
> 0)
1250 attr
[i
].uriW
= SysAllocStringLen(NULL
, 0);
1251 attr
[i
].localW
= SysAllocStringLen(NULL
, 0);
1255 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
1256 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
1259 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
1260 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
1263 call
.attributes
= attr
;
1264 call
.attr_count
= len
;
1267 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1269 return get_expected_ret();
1272 static HRESULT WINAPI
contentHandler_endElement(
1273 ISAXContentHandler
* iface
,
1274 const WCHAR
*uri
, int uri_len
,
1275 const WCHAR
*localname
, int local_len
,
1276 const WCHAR
*qname
, int qname_len
)
1278 struct call_entry call
;
1280 init_call_entry(locator
, &call
);
1281 call
.id
= CH_ENDELEMENT
;
1282 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1283 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1284 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1285 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1287 return get_expected_ret();
1290 static HRESULT WINAPI
contentHandler_characters(
1291 ISAXContentHandler
* iface
,
1295 struct call_entry call
;
1297 init_call_entry(locator
, &call
);
1298 call
.id
= CH_CHARACTERS
;
1299 call
.arg1W
= SysAllocStringLen(chars
, len
);
1300 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1302 return get_expected_ret();
1305 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1306 ISAXContentHandler
* iface
,
1307 const WCHAR
*chars
, int len
)
1309 struct call_entry call
;
1311 init_call_entry(locator
, &call
);
1312 call
.id
= CH_IGNORABLEWHITESPACE
;
1313 call
.arg1W
= SysAllocStringLen(chars
, len
);
1314 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1316 return get_expected_ret();
1319 static HRESULT WINAPI
contentHandler_processingInstruction(
1320 ISAXContentHandler
* iface
,
1321 const WCHAR
*target
, int target_len
,
1322 const WCHAR
*data
, int data_len
)
1324 struct call_entry call
;
1326 init_call_entry(locator
, &call
);
1327 call
.id
= CH_PROCESSINGINSTRUCTION
;
1328 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1329 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1330 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1332 return get_expected_ret();
1335 static HRESULT WINAPI
contentHandler_skippedEntity(
1336 ISAXContentHandler
* iface
,
1337 const WCHAR
*name
, int len
)
1339 struct call_entry call
;
1341 init_call_entry(locator
, &call
);
1342 call
.id
= CH_SKIPPEDENTITY
;
1343 call
.arg1W
= SysAllocStringLen(name
, len
);
1344 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1346 return get_expected_ret();
1349 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1351 contentHandler_QueryInterface
,
1352 contentHandler_AddRef
,
1353 contentHandler_Release
,
1354 contentHandler_putDocumentLocator
,
1355 contentHandler_startDocument
,
1356 contentHandler_endDocument
,
1357 contentHandler_startPrefixMapping
,
1358 contentHandler_endPrefixMapping
,
1359 contentHandler_startElement
,
1360 contentHandler_endElement
,
1361 contentHandler_characters
,
1362 contentHandler_ignorableWhitespace
,
1363 contentHandler_processingInstruction
,
1364 contentHandler_skippedEntity
1367 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1369 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1370 ISAXErrorHandler
* iface
,
1376 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1382 return E_NOINTERFACE
;
1388 static ULONG WINAPI
isaxerrorHandler_AddRef(
1389 ISAXErrorHandler
* iface
)
1394 static ULONG WINAPI
isaxerrorHandler_Release(
1395 ISAXErrorHandler
* iface
)
1400 static HRESULT WINAPI
isaxerrorHandler_error(
1401 ISAXErrorHandler
* iface
,
1402 ISAXLocator
*pLocator
,
1403 const WCHAR
*pErrorMessage
,
1404 HRESULT hrErrorCode
)
1406 ok(0, "unexpected call\n");
1410 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1411 ISAXErrorHandler
* iface
,
1412 ISAXLocator
*pLocator
,
1413 const WCHAR
*message
,
1416 struct call_entry call
;
1418 init_call_entry(locator
, &call
);
1419 call
.id
= EH_FATALERROR
;
1422 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1428 static HRESULT WINAPI
isaxerrorHandler_ignorableWarning(
1429 ISAXErrorHandler
* iface
,
1430 ISAXLocator
*pLocator
,
1431 const WCHAR
*pErrorMessage
,
1432 HRESULT hrErrorCode
)
1434 ok(0, "unexpected call\n");
1438 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1440 isaxerrorHandler_QueryInterface
,
1441 isaxerrorHandler_AddRef
,
1442 isaxerrorHandler_Release
,
1443 isaxerrorHandler_error
,
1444 isaxerrorHandler_fatalError
,
1445 isaxerrorHandler_ignorableWarning
1448 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1450 static HRESULT WINAPI
isaxattributes_QueryInterface(
1451 ISAXAttributes
* iface
,
1457 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1463 return E_NOINTERFACE
;
1469 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1474 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1479 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1485 static HRESULT WINAPI
isaxattributes_getURI(
1486 ISAXAttributes
* iface
,
1491 ok(0, "unexpected call\n");
1495 static HRESULT WINAPI
isaxattributes_getLocalName(
1496 ISAXAttributes
* iface
,
1498 const WCHAR
**pLocalName
,
1499 int *pLocalNameLength
)
1501 ok(0, "unexpected call\n");
1505 static HRESULT WINAPI
isaxattributes_getQName(
1506 ISAXAttributes
* iface
,
1508 const WCHAR
**QName
,
1511 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1512 {'a','t','t','r','2','j','u','n','k',0},
1513 {'a','t','t','r','3',0}};
1514 static const int attrqnamelen
[] = {7, 5, 5};
1516 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1518 if (index
>= 0 && index
<= 2) {
1519 *QName
= attrqnamesW
[index
];
1520 *QNameLength
= attrqnamelen
[index
];
1529 static HRESULT WINAPI
isaxattributes_getName(
1530 ISAXAttributes
* iface
,
1534 const WCHAR
** pLocalName
,
1535 int * pLocalNameSize
,
1536 const WCHAR
** pQName
,
1539 ok(0, "unexpected call\n");
1543 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1544 ISAXAttributes
* iface
,
1547 const WCHAR
* pLocalName
,
1548 int cocalNameLength
,
1551 ok(0, "unexpected call\n");
1555 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1556 ISAXAttributes
* iface
,
1557 const WCHAR
* pQName
,
1561 ok(0, "unexpected call\n");
1565 static HRESULT WINAPI
isaxattributes_getType(
1566 ISAXAttributes
* iface
,
1568 const WCHAR
** pType
,
1571 ok(0, "unexpected call\n");
1575 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1576 ISAXAttributes
* iface
,
1579 const WCHAR
* pLocalName
,
1581 const WCHAR
** pType
,
1584 ok(0, "unexpected call\n");
1588 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1589 ISAXAttributes
* iface
,
1590 const WCHAR
* pQName
,
1592 const WCHAR
** pType
,
1595 ok(0, "unexpected call\n");
1599 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1600 const WCHAR
**value
, int *nValue
)
1602 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1603 {'a','2','j','u','n','k',0},
1604 {'<','&','"','>','\'',0}};
1605 static const int attrvalueslen
[] = {2, 2, 5};
1607 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1609 if (index
>= 0 && index
<= 2) {
1610 *value
= attrvaluesW
[index
];
1611 *nValue
= attrvalueslen
[index
];
1620 static HRESULT WINAPI
isaxattributes_getValueFromName(
1621 ISAXAttributes
* iface
,
1624 const WCHAR
* pLocalName
,
1626 const WCHAR
** pValue
,
1629 ok(0, "unexpected call\n");
1633 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1634 ISAXAttributes
* iface
,
1635 const WCHAR
* pQName
,
1637 const WCHAR
** pValue
,
1640 ok(0, "unexpected call\n");
1644 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1646 isaxattributes_QueryInterface
,
1647 isaxattributes_AddRef
,
1648 isaxattributes_Release
,
1649 isaxattributes_getLength
,
1650 isaxattributes_getURI
,
1651 isaxattributes_getLocalName
,
1652 isaxattributes_getQName
,
1653 isaxattributes_getName
,
1654 isaxattributes_getIndexFromName
,
1655 isaxattributes_getIndexFromQName
,
1656 isaxattributes_getType
,
1657 isaxattributes_getTypeFromName
,
1658 isaxattributes_getTypeFromQName
,
1659 isaxattributes_getValue
,
1660 isaxattributes_getValueFromName
,
1661 isaxattributes_getValueFromQName
1664 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1666 struct saxlexicalhandler
1668 ISAXLexicalHandler ISAXLexicalHandler_iface
;
1671 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1674 static inline struct saxlexicalhandler
*impl_from_ISAXLexicalHandler( ISAXLexicalHandler
*iface
)
1676 return CONTAINING_RECORD(iface
, struct saxlexicalhandler
, ISAXLexicalHandler_iface
);
1679 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **out
)
1681 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1685 if (IsEqualGUID(riid
, &IID_IUnknown
))
1688 ok(0, "got unexpected IID_IUnknown query\n");
1690 else if (IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1692 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1697 ISAXLexicalHandler_AddRef(iface
);
1699 return E_NOINTERFACE
;
1704 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1706 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1707 return InterlockedIncrement(&handler
->ref
);
1710 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1712 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1713 return InterlockedDecrement(&handler
->ref
);
1716 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1717 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1718 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1720 ok(0, "call not expected\n");
1724 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1726 ok(0, "call not expected\n");
1730 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1731 const WCHAR
* pName
, int nName
)
1733 ok(0, "call not expected\n");
1737 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1738 const WCHAR
* pName
, int nName
)
1740 ok(0, "call not expected\n");
1744 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1746 struct call_entry call
;
1748 init_call_entry(locator
, &call
);
1749 call
.id
= LH_STARTCDATA
;
1750 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1752 return get_expected_ret();
1755 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1757 struct call_entry call
;
1759 init_call_entry(locator
, &call
);
1760 call
.id
= LH_ENDCDATA
;
1761 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1763 return get_expected_ret();
1766 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1767 const WCHAR
* pChars
, int nChars
)
1769 ok(0, "call not expected\n");
1773 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1775 isaxlexical_QueryInterface
,
1777 isaxlexical_Release
,
1778 isaxlexical_startDTD
,
1780 isaxlexical_startEntity
,
1781 isaxlexical_endEntity
,
1782 isaxlexical_startCDATA
,
1783 isaxlexical_endCDATA
,
1787 static void init_saxlexicalhandler(struct saxlexicalhandler
*handler
, HRESULT hr
)
1789 handler
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1791 handler
->qi_hr
= hr
;
1794 struct saxdeclhandler
1796 ISAXDeclHandler ISAXDeclHandler_iface
;
1799 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1802 static inline struct saxdeclhandler
*impl_from_ISAXDeclHandler( ISAXDeclHandler
*iface
)
1804 return CONTAINING_RECORD(iface
, struct saxdeclhandler
, ISAXDeclHandler_iface
);
1807 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **out
)
1809 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1813 if (IsEqualGUID(riid
, &IID_IUnknown
))
1816 ok(0, "got unexpected IID_IUnknown query\n");
1818 else if (IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1820 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1825 ISAXDeclHandler_AddRef(iface
);
1827 return E_NOINTERFACE
;
1832 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1834 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1835 return InterlockedIncrement(&handler
->ref
);
1838 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1840 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1841 return InterlockedDecrement(&handler
->ref
);
1844 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1845 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1847 ok(0, "call not expected\n");
1851 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1852 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1853 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1854 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1856 ok(0, "call not expected\n");
1860 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1861 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1863 ok(0, "call not expected\n");
1867 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1868 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1869 const WCHAR
* pSystemId
, int nSystemId
)
1871 ok(0, "call not expected\n");
1875 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1877 isaxdecl_QueryInterface
,
1880 isaxdecl_elementDecl
,
1881 isaxdecl_attributeDecl
,
1882 isaxdecl_internalEntityDecl
,
1883 isaxdecl_externalEntityDecl
1886 static void init_saxdeclhandler(struct saxdeclhandler
*handler
, HRESULT hr
)
1888 handler
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1890 handler
->qi_hr
= hr
;
1893 typedef struct mxwriter_write_test_t
{
1899 } mxwriter_write_test
;
1901 typedef struct mxwriter_stream_test_t
{
1903 const char *encoding
;
1904 mxwriter_write_test expected_writes
[4];
1905 } mxwriter_stream_test
;
1907 static const mxwriter_write_test
*current_write_test
;
1908 static DWORD current_stream_test_index
;
1910 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1914 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1917 return E_NOINTERFACE
;
1922 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1927 static ULONG WINAPI
istream_Release(IStream
*iface
)
1932 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1934 ok(0, "unexpected call\n");
1938 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1940 ok(0, "unexpected call\n");
1944 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1945 ULARGE_INTEGER
*plibNewPosition
)
1947 ok(0, "unexpected call\n");
1951 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1953 ok(0, "unexpected call\n");
1957 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1958 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1960 ok(0, "unexpected call\n");
1964 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1966 ok(0, "unexpected call\n");
1970 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1972 ok(0, "unexpected call\n");
1976 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1977 ULARGE_INTEGER cb
, DWORD dwLockType
)
1979 ok(0, "unexpected call\n");
1983 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1984 ULARGE_INTEGER cb
, DWORD dwLockType
)
1986 ok(0, "unexpected call\n");
1990 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1992 ok(0, "unexpected call\n");
1996 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1998 ok(0, "unexpected call\n");
2002 static HRESULT WINAPI
mxstream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
2006 ok(pv
!= NULL
, "pv == NULL\n");
2008 if(current_write_test
->last
) {
2009 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
2013 fail
= current_write_test
->fail_write
;
2015 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
2016 current_write_test
->cb
, cb
, current_stream_test_index
);
2019 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
2021 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
2023 ++current_write_test
;
2028 return fail
? E_FAIL
: S_OK
;
2031 static const IStreamVtbl mxstreamVtbl
= {
2032 istream_QueryInterface
,
2043 istream_UnlockRegion
,
2048 static IStream mxstream
= { &mxstreamVtbl
};
2050 static int read_cnt
;
2052 static HRESULT WINAPI
instream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
2054 static const char *ret_str
;
2057 ret_str
= "<?xml version=\"1.0\" ?>\n<rootelem>";
2058 else if(read_cnt
< 5)
2059 ret_str
= "<elem attr=\"val\">text</elem>";
2060 else if(read_cnt
== 5)
2061 ret_str
= "</rootelem>\n";
2066 strcpy(pv
, ret_str
);
2067 *pcbRead
= strlen(ret_str
);
2071 static const IStreamVtbl instreamVtbl
= {
2072 istream_QueryInterface
,
2083 istream_UnlockRegion
,
2088 static IStream instream
= { &instreamVtbl
};
2090 static struct msxmlsupported_data_t reader_support_data
[] =
2092 { &CLSID_SAXXMLReader
, "SAXReader" },
2093 { &CLSID_SAXXMLReader30
, "SAXReader30" },
2094 { &CLSID_SAXXMLReader40
, "SAXReader40" },
2095 { &CLSID_SAXXMLReader60
, "SAXReader60" },
2099 static struct saxlexicalhandler lexicalhandler
;
2100 static struct saxdeclhandler declhandler
;
2102 static IStream
*create_test_stream(const char *data
, int len
)
2104 ULARGE_INTEGER size
;
2109 if (len
== -1) len
= strlen(data
);
2110 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2111 size
.QuadPart
= len
;
2112 IStream_SetSize(stream
, size
);
2113 IStream_Write(stream
, data
, len
, &written
);
2115 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2120 static void test_saxreader(void)
2122 const struct msxmlsupported_data_t
*table
= reader_support_data
;
2124 ISAXXMLReader
*reader
= NULL
;
2126 ISAXContentHandler
*content
;
2127 ISAXErrorHandler
*lpErrorHandler
;
2129 SAFEARRAYBOUND SADim
[1];
2134 static const CHAR testXmlA
[] = "test.xml";
2135 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2136 IXMLDOMDocument
*doc
;
2140 while (table
->clsid
)
2142 struct call_entry
*test_seq
;
2143 ISAXEntityResolver
*resolver
;
2146 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
2152 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2153 EXPECT_HR(hr
, S_OK
);
2156 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2158 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2163 /* crashes on old versions */
2164 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
2165 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2167 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
2168 EXPECT_HR(hr
, E_POINTER
);
2170 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
2171 EXPECT_HR(hr
, E_POINTER
);
2174 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2175 EXPECT_HR(hr
, S_OK
);
2176 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
2178 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
2179 EXPECT_HR(hr
, S_OK
);
2180 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
2182 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
2183 EXPECT_HR(hr
, S_OK
);
2185 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
2186 EXPECT_HR(hr
, S_OK
);
2188 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
2189 EXPECT_HR(hr
, S_OK
);
2191 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2192 EXPECT_HR(hr
, S_OK
);
2193 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
2195 V_VT(&var
) = VT_BSTR
;
2196 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
2198 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2199 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2200 test_seq
= content_handler_test1_alternate
;
2202 test_seq
= content_handler_test1
;
2203 set_expected_seq(test_seq
);
2204 hr
= ISAXXMLReader_parse(reader
, var
);
2205 EXPECT_HR(hr
, S_OK
);
2206 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
2210 SADim
[0].lLbound
= 0;
2211 SADim
[0].cElements
= sizeof(testXML
)-1;
2212 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
2213 SafeArrayAccessData(sa
, (void**)&ptr
);
2214 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
2215 SafeArrayUnaccessData(sa
);
2216 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
2219 set_expected_seq(test_seq
);
2220 hr
= ISAXXMLReader_parse(reader
, var
);
2221 EXPECT_HR(hr
, S_OK
);
2222 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from safe array", FALSE
);
2224 SafeArrayDestroy(sa
);
2226 stream
= create_test_stream(testXML
, -1);
2227 V_VT(&var
) = VT_UNKNOWN
;
2228 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2230 set_expected_seq(test_seq
);
2231 hr
= ISAXXMLReader_parse(reader
, var
);
2232 EXPECT_HR(hr
, S_OK
);
2233 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
2235 IStream_Release(stream
);
2237 stream
= create_test_stream(test_attributes
, -1);
2238 V_VT(&var
) = VT_UNKNOWN
;
2239 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2241 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2242 test_seq
= content_handler_test_attributes_alternate_4
;
2243 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2244 test_seq
= content_handler_test_attributes_alternate_6
;
2246 test_seq
= content_handler_test_attributes
;
2248 set_expected_seq(test_seq
);
2249 hr
= ISAXXMLReader_parse(reader
, var
);
2250 EXPECT_HR(hr
, S_OK
);
2252 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2253 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2254 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2256 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2258 IStream_Release(stream
);
2260 V_VT(&var
) = VT_UNKNOWN
;
2261 V_UNKNOWN(&var
) = (IUnknown
*)&instream
;
2263 test_seq
= read_test_seq
;
2265 set_expected_seq(test_seq
);
2266 hr
= ISAXXMLReader_parse(reader
, var
);
2267 EXPECT_HR(hr
, S_OK
);
2268 ok(read_cnt
== 7, "read_cnt = %d\n", read_cnt
);
2269 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "Read call test", FALSE
);
2271 V_VT(&var
) = VT_BSTR
;
2272 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
2274 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2275 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2276 test_seq
= content_handler_test2_alternate
;
2278 test_seq
= content_handler_test2
;
2280 set_expected_seq(test_seq
);
2281 hr
= ISAXXMLReader_parse(reader
, var
);
2282 EXPECT_HR(hr
, S_OK
);
2283 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
2288 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2289 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2290 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
2293 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2294 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2295 test_seq
= content_handler_test1_alternate
;
2297 test_seq
= content_handler_test1
;
2298 set_expected_seq(test_seq
);
2299 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2300 EXPECT_HR(hr
, S_OK
);
2301 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
2304 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2305 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2306 test_seq
= content_handler_testerror_alternate
;
2308 test_seq
= content_handler_testerror
;
2309 set_expected_seq(test_seq
);
2310 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2311 EXPECT_HR(hr
, E_FAIL
);
2312 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
2314 /* callback ret values */
2315 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2316 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2318 test_seq
= content_handler_test_callback_rets_alt
;
2319 set_expected_seq(test_seq
);
2320 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2321 EXPECT_HR(hr
, S_OK
);
2325 test_seq
= content_handler_test_callback_rets
;
2326 set_expected_seq(test_seq
);
2327 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2328 EXPECT_HR(hr
, S_FALSE
);
2330 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
2332 DeleteFileA(testXmlA
);
2334 /* parse from IXMLDOMDocument */
2335 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
2336 &IID_IXMLDOMDocument
, (void**)&doc
);
2337 EXPECT_HR(hr
, S_OK
);
2339 str
= SysAllocString(szSimpleXML
);
2340 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
2341 EXPECT_HR(hr
, S_OK
);
2344 V_VT(&var
) = VT_UNKNOWN
;
2345 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
2347 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2348 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2349 test_seq
= content_handler_test2_alternate
;
2351 test_seq
= content_handler_test2
;
2353 set_expected_seq(test_seq
);
2354 hr
= ISAXXMLReader_parse(reader
, var
);
2355 EXPECT_HR(hr
, S_OK
);
2356 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
2357 IXMLDOMDocument_Release(doc
);
2359 /* xml:space test */
2360 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2361 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2363 test_seq
= xmlspaceattr_test_alternate
;
2366 test_seq
= xmlspaceattr_test
;
2368 set_expected_seq(test_seq
);
2369 V_VT(&var
) = VT_BSTR
;
2370 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
2371 hr
= ISAXXMLReader_parse(reader
, var
);
2372 EXPECT_HR(hr
, S_OK
);
2374 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2375 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2377 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
2380 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
2382 /* switch off 'namespaces' feature */
2383 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE
);
2384 EXPECT_HR(hr
, S_OK
);
2386 stream
= create_test_stream(test_attributes
, -1);
2387 V_VT(&var
) = VT_UNKNOWN
;
2388 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2390 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2391 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2393 test_seq
= content_handler_test_attributes_alt_no_ns
;
2396 test_seq
= content_handler_test_attributes
;
2398 set_expected_seq(test_seq
);
2399 hr
= ISAXXMLReader_parse(reader
, var
);
2400 EXPECT_HR(hr
, S_OK
);
2401 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2402 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_TRUE
);
2403 EXPECT_HR(hr
, S_OK
);
2405 /* switch off 'namespace-prefixes' feature */
2406 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_FALSE
);
2407 EXPECT_HR(hr
, S_OK
);
2409 stream
= create_test_stream(test_attributes
, -1);
2410 V_VT(&var
) = VT_UNKNOWN
;
2411 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2413 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2414 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2416 test_seq
= content_handler_test_attributes_alt_no_prefix
;
2419 test_seq
= content_handler_test_attributes_no_prefix
;
2421 set_expected_seq(test_seq
);
2422 hr
= ISAXXMLReader_parse(reader
, var
);
2423 EXPECT_HR(hr
, S_OK
);
2424 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2426 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_TRUE
);
2427 EXPECT_HR(hr
, S_OK
);
2429 /* attribute normalization */
2430 stream
= create_test_stream(attribute_normalize
, -1);
2431 V_VT(&var
) = VT_UNKNOWN
;
2432 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2434 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2435 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2437 test_seq
= attribute_norm_alt
;
2440 test_seq
= attribute_norm
;
2442 set_expected_seq(test_seq
);
2443 hr
= ISAXXMLReader_parse(reader
, var
);
2444 EXPECT_HR(hr
, S_OK
);
2445 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "attribute value normalization", TRUE
);
2447 resolver
= (void*)0xdeadbeef;
2448 hr
= ISAXXMLReader_getEntityResolver(reader
, &resolver
);
2449 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2450 ok(resolver
== NULL
, "got %p\n", resolver
);
2452 hr
= ISAXXMLReader_putEntityResolver(reader
, NULL
);
2453 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "got 0x%08x\n", hr
);
2455 /* CDATA sections */
2456 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2458 V_VT(&var
) = VT_UNKNOWN
;
2459 V_UNKNOWN(&var
) = (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
;
2460 hr
= ISAXXMLReader_putProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), var
);
2461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2463 stream
= create_test_stream(test_cdata_xml
, -1);
2464 V_VT(&var
) = VT_UNKNOWN
;
2465 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2467 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2468 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2469 test_seq
= cdata_test_alt
;
2471 test_seq
= cdata_test
;
2473 set_expected_seq(test_seq
);
2474 hr
= ISAXXMLReader_parse(reader
, var
);
2475 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2476 sprintf(seqname
, "%s: cdata test", table
->name
);
2477 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2479 /* 2. CDATA sections */
2480 stream
= create_test_stream(test2_cdata_xml
, -1);
2481 V_VT(&var
) = VT_UNKNOWN
;
2482 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2484 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2485 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2486 test_seq
= cdata_test2_alt
;
2488 test_seq
= cdata_test2
;
2490 set_expected_seq(test_seq
);
2491 hr
= ISAXXMLReader_parse(reader
, var
);
2492 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2493 sprintf(seqname
, "%s: cdata test 2", table
->name
);
2494 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2496 IStream_Release(stream
);
2498 /* 3. CDATA sections */
2499 stream
= create_test_stream(test3_cdata_xml
, -1);
2500 V_VT(&var
) = VT_UNKNOWN
;
2501 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2503 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2504 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2505 test_seq
= cdata_test3_alt
;
2507 test_seq
= cdata_test3
;
2509 set_expected_seq(test_seq
);
2510 hr
= ISAXXMLReader_parse(reader
, var
);
2511 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2512 sprintf(seqname
, "%s: cdata test 3", table
->name
);
2513 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2515 IStream_Release(stream
);
2517 ISAXXMLReader_Release(reader
);
2524 struct saxreader_props_test_t
2526 const char *prop_name
;
2530 static const struct saxreader_props_test_t props_test_data
[] = {
2531 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
},
2532 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&declhandler
.ISAXDeclHandler_iface
},
2536 static void test_saxreader_properties(void)
2538 const struct saxreader_props_test_t
*ptr
= props_test_data
;
2539 ISAXXMLReader
*reader
;
2544 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2545 &IID_ISAXXMLReader
, (void**)&reader
);
2546 EXPECT_HR(hr
, S_OK
);
2548 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
2549 EXPECT_HR(hr
, E_POINTER
);
2551 while (ptr
->prop_name
)
2556 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2557 init_saxdeclhandler(&declhandler
, S_OK
);
2559 V_VT(&v
) = VT_EMPTY
;
2560 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2561 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2562 EXPECT_HR(hr
, S_OK
);
2563 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2564 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2567 V_VT(&v
) = VT_UNKNOWN
;
2568 V_UNKNOWN(&v
) = ptr
->iface
;
2569 ref
= get_refcount(ptr
->iface
);
2570 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2571 EXPECT_HR(hr
, S_OK
);
2572 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2575 V_VT(&v
) = VT_DISPATCH
;
2576 V_UNKNOWN(&v
) = ptr
->iface
;
2577 ref
= get_refcount(ptr
->iface
);
2578 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2579 EXPECT_HR(hr
, S_OK
);
2580 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2582 /* VT_VARIANT|VT_BYREF with VT_UNKNOWN in referenced variant */
2583 V_VT(&varref
) = VT_UNKNOWN
;
2584 V_UNKNOWN(&varref
) = ptr
->iface
;
2586 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2587 V_VARIANTREF(&v
) = &varref
;
2588 ref
= get_refcount(ptr
->iface
);
2589 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2590 EXPECT_HR(hr
, S_OK
);
2591 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2593 /* VT_VARIANT|VT_BYREF with VT_DISPATCH in referenced variant */
2594 V_VT(&varref
) = VT_DISPATCH
;
2595 V_UNKNOWN(&varref
) = ptr
->iface
;
2597 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2598 V_VARIANTREF(&v
) = &varref
;
2599 ref
= get_refcount(ptr
->iface
);
2600 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2601 EXPECT_HR(hr
, S_OK
);
2602 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2604 V_VT(&v
) = VT_EMPTY
;
2605 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2607 ref
= get_refcount(ptr
->iface
);
2608 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2609 EXPECT_HR(hr
, S_OK
);
2610 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2611 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2612 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2615 V_VT(&v
) = VT_EMPTY
;
2616 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2617 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2618 EXPECT_HR(hr
, S_OK
);
2620 V_VT(&v
) = VT_EMPTY
;
2621 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2622 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2623 EXPECT_HR(hr
, S_OK
);
2624 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2625 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2627 V_VT(&v
) = VT_UNKNOWN
;
2628 V_UNKNOWN(&v
) = ptr
->iface
;
2629 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2630 EXPECT_HR(hr
, S_OK
);
2632 /* only VT_EMPTY seems to be valid to reset property */
2634 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2635 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2636 EXPECT_HR(hr
, E_INVALIDARG
);
2638 V_VT(&v
) = VT_EMPTY
;
2639 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2640 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2641 EXPECT_HR(hr
, S_OK
);
2642 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2643 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2646 V_VT(&v
) = VT_UNKNOWN
;
2647 V_UNKNOWN(&v
) = NULL
;
2648 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2649 EXPECT_HR(hr
, S_OK
);
2651 V_VT(&v
) = VT_EMPTY
;
2652 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2653 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2654 EXPECT_HR(hr
, S_OK
);
2655 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2656 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2658 /* block QueryInterface on handler riid */
2659 V_VT(&v
) = VT_UNKNOWN
;
2660 V_UNKNOWN(&v
) = ptr
->iface
;
2661 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2662 EXPECT_HR(hr
, S_OK
);
2664 init_saxlexicalhandler(&lexicalhandler
, E_NOINTERFACE
);
2665 init_saxdeclhandler(&declhandler
, E_NOINTERFACE
);
2667 V_VT(&v
) = VT_UNKNOWN
;
2668 V_UNKNOWN(&v
) = ptr
->iface
;
2669 EXPECT_REF(ptr
->iface
, 1);
2670 ref
= get_refcount(ptr
->iface
);
2671 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2672 EXPECT_HR(hr
, E_NOINTERFACE
);
2673 EXPECT_REF(ptr
->iface
, 1);
2675 V_VT(&v
) = VT_EMPTY
;
2676 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2677 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2678 EXPECT_HR(hr
, S_OK
);
2679 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2680 ok(V_UNKNOWN(&v
) != NULL
, "got %p\n", V_UNKNOWN(&v
));
2686 ISAXXMLReader_Release(reader
);
2688 if (!is_clsid_supported(&CLSID_SAXXMLReader40
, reader_support_data
))
2691 hr
= CoCreateInstance(&CLSID_SAXXMLReader40
, NULL
, CLSCTX_INPROC_SERVER
,
2692 &IID_ISAXXMLReader
, (void**)&reader
);
2693 EXPECT_HR(hr
, S_OK
);
2695 /* xmldecl-version property */
2696 V_VT(&v
) = VT_EMPTY
;
2697 V_BSTR(&v
) = (void*)0xdeadbeef;
2698 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2699 EXPECT_HR(hr
, S_OK
);
2700 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2701 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2703 /* stream without declaration */
2705 V_BSTR(&v
) = _bstr_("<element></element>");
2706 hr
= ISAXXMLReader_parse(reader
, v
);
2707 EXPECT_HR(hr
, S_OK
);
2709 V_VT(&v
) = VT_EMPTY
;
2710 V_BSTR(&v
) = (void*)0xdeadbeef;
2711 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2712 EXPECT_HR(hr
, S_OK
);
2713 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2714 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2716 /* stream with declaration */
2718 V_BSTR(&v
) = _bstr_("<?xml version=\"1.0\"?><element></element>");
2719 hr
= ISAXXMLReader_parse(reader
, v
);
2720 EXPECT_HR(hr
, S_OK
);
2722 /* VT_BSTR|VT_BYREF input type */
2723 str
= _bstr_("<?xml version=\"1.0\"?><element></element>");
2724 V_VT(&v
) = VT_BSTR
|VT_BYREF
;
2725 V_BSTRREF(&v
) = &str
;
2726 hr
= ISAXXMLReader_parse(reader
, v
);
2727 EXPECT_HR(hr
, S_OK
);
2729 V_VT(&v
) = VT_EMPTY
;
2730 V_BSTR(&v
) = (void*)0xdeadbeef;
2731 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2732 EXPECT_HR(hr
, S_OK
);
2733 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2734 ok(!lstrcmpW(V_BSTR(&v
), _bstr_("1.0")), "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2737 ISAXXMLReader_Release(reader
);
2741 struct feature_ns_entry_t
{
2745 VARIANT_BOOL value2
; /* feature value after feature set to 0xc */
2748 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2749 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
, VARIANT_FALSE
},
2750 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
, VARIANT_FALSE
},
2751 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
, VARIANT_TRUE
},
2752 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
, VARIANT_TRUE
},
2756 static const char *feature_names
[] = {
2757 "http://xml.org/sax/features/namespaces",
2758 "http://xml.org/sax/features/namespace-prefixes",
2762 static void test_saxreader_features(void)
2764 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2765 ISAXXMLReader
*reader
;
2773 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2776 win_skip("can't create %s instance\n", entry
->clsid
);
2781 name
= feature_names
;
2785 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2786 EXPECT_HR(hr
, S_OK
);
2787 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2790 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), value
);
2791 EXPECT_HR(hr
, S_OK
);
2794 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2795 EXPECT_HR(hr
, S_OK
);
2796 ok(entry
->value2
== value
, "%s: got wrong value %x, expected %x\n", entry
->clsid
, value
, entry
->value2
);
2798 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_FALSE
);
2799 EXPECT_HR(hr
, S_OK
);
2801 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2802 EXPECT_HR(hr
, S_OK
);
2803 ok(value
== VARIANT_FALSE
, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry
->clsid
, value
);
2805 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_TRUE
);
2806 EXPECT_HR(hr
, S_OK
);
2808 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2809 EXPECT_HR(hr
, S_OK
);
2810 ok(value
== VARIANT_TRUE
, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry
->clsid
, value
);
2815 ISAXXMLReader_Release(reader
);
2821 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2822 static const CHAR UTF8BOMTest
[] =
2823 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2826 struct enc_test_entry_t
{
2834 static const struct enc_test_entry_t encoding_test_data
[] = {
2835 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2836 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2837 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, FALSE
},
2838 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, FALSE
},
2842 static void test_saxreader_encoding(void)
2844 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2845 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2846 static const CHAR testXmlA
[] = "test.xml";
2850 ISAXXMLReader
*reader
;
2856 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2859 win_skip("can't create %s instance\n", entry
->clsid
);
2864 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2865 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2866 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2869 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2871 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2873 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2875 DeleteFileA(testXmlA
);
2877 /* try BSTR input with no BOM or '<?xml' instruction */
2878 V_VT(&input
) = VT_BSTR
;
2879 V_BSTR(&input
) = _bstr_("<element></element>");
2880 hr
= ISAXXMLReader_parse(reader
, input
);
2881 EXPECT_HR(hr
, S_OK
);
2883 ISAXXMLReader_Release(reader
);
2890 static void test_mxwriter_handlers(void)
2896 static const REFIID riids
[] =
2898 &IID_ISAXContentHandler
,
2899 &IID_ISAXLexicalHandler
,
2900 &IID_ISAXDeclHandler
,
2901 &IID_ISAXDTDHandler
,
2902 &IID_ISAXErrorHandler
,
2903 &IID_IVBSAXDeclHandler
,
2904 &IID_IVBSAXLexicalHandler
,
2905 &IID_IVBSAXContentHandler
,
2906 &IID_IVBSAXDTDHandler
,
2907 &IID_IVBSAXErrorHandler
2910 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2911 &IID_IMXWriter
, (void**)&writer
);
2912 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2914 EXPECT_REF(writer
, 1);
2916 for (i
= 0; i
< sizeof(riids
)/sizeof(REFIID
); i
++)
2921 /* handler from IMXWriter */
2922 hr
= IMXWriter_QueryInterface(writer
, riids
[i
], (void**)&handler
);
2923 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2924 EXPECT_REF(writer
, 2);
2925 EXPECT_REF(handler
, 2);
2927 /* IMXWriter from a handler */
2928 hr
= IUnknown_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2929 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2930 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2931 EXPECT_REF(writer
, 3);
2932 EXPECT_REF(writer2
, 3);
2933 IMXWriter_Release(writer2
);
2934 IUnknown_Release(handler
);
2937 IMXWriter_Release(writer
);
2940 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2942 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2943 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2944 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2945 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2949 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2951 { &CLSID_SAXAttributes
, "SAXAttributes" },
2952 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2953 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2954 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2958 struct mxwriter_props_t
2962 VARIANT_BOOL disable_escape
;
2963 VARIANT_BOOL indent
;
2964 VARIANT_BOOL omitdecl
;
2965 VARIANT_BOOL standalone
;
2966 const char *encoding
;
2969 static const struct mxwriter_props_t mxwriter_default_props
[] =
2971 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2972 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2973 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2974 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2978 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2982 while (table
->clsid
)
2989 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2996 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2997 &IID_IMXWriter
, (void**)&writer
);
2998 EXPECT_HR(hr
, S_OK
);
3001 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
3002 EXPECT_HR(hr
, S_OK
);
3003 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
3005 b
= !table
->disable_escape
;
3006 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
3007 EXPECT_HR(hr
, S_OK
);
3008 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
3009 table
->disable_escape
);
3012 hr
= IMXWriter_get_indent(writer
, &b
);
3013 EXPECT_HR(hr
, S_OK
);
3014 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
3016 b
= !table
->omitdecl
;
3017 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
3018 EXPECT_HR(hr
, S_OK
);
3019 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
3021 b
= !table
->standalone
;
3022 hr
= IMXWriter_get_standalone(writer
, &b
);
3023 EXPECT_HR(hr
, S_OK
);
3024 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
3026 hr
= IMXWriter_get_encoding(writer
, &encoding
);
3027 EXPECT_HR(hr
, S_OK
);
3028 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
3029 i
, wine_dbgstr_w(encoding
), table
->encoding
);
3030 SysFreeString(encoding
);
3032 IMXWriter_Release(writer
);
3039 static void test_mxwriter_properties(void)
3041 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
3042 static const WCHAR testW
[] = {'t','e','s','t',0};
3043 ISAXContentHandler
*content
;
3050 test_mxwriter_default_properties(mxwriter_default_props
);
3052 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3053 &IID_IMXWriter
, (void**)&writer
);
3054 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3056 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
3057 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3059 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
3060 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3062 hr
= IMXWriter_get_indent(writer
, NULL
);
3063 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3065 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
3066 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3068 hr
= IMXWriter_get_standalone(writer
, NULL
);
3069 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3072 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
3073 ok(hr
== S_OK
, "got %08x\n", hr
);
3076 hr
= IMXWriter_get_standalone(writer
, &b
);
3077 ok(hr
== S_OK
, "got %08x\n", hr
);
3078 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
3080 hr
= IMXWriter_get_encoding(writer
, NULL
);
3081 EXPECT_HR(hr
, E_POINTER
);
3083 /* UTF-16 is a default setting apparently */
3084 str
= (void*)0xdeadbeef;
3085 hr
= IMXWriter_get_encoding(writer
, &str
);
3086 EXPECT_HR(hr
, S_OK
);
3087 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
3089 str2
= (void*)0xdeadbeef;
3090 hr
= IMXWriter_get_encoding(writer
, &str2
);
3091 ok(hr
== S_OK
, "got %08x\n", hr
);
3092 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
3094 SysFreeString(str2
);
3097 /* put empty string */
3098 str
= SysAllocString(emptyW
);
3099 hr
= IMXWriter_put_encoding(writer
, str
);
3100 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3103 str
= (void*)0xdeadbeef;
3104 hr
= IMXWriter_get_encoding(writer
, &str
);
3105 EXPECT_HR(hr
, S_OK
);
3106 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
3109 /* invalid encoding name */
3110 str
= SysAllocString(testW
);
3111 hr
= IMXWriter_put_encoding(writer
, str
);
3112 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3115 /* test case sensivity */
3116 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
3117 EXPECT_HR(hr
, S_OK
);
3118 str
= (void*)0xdeadbeef;
3119 hr
= IMXWriter_get_encoding(writer
, &str
);
3120 EXPECT_HR(hr
, S_OK
);
3121 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
3124 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
3125 EXPECT_HR(hr
, S_OK
);
3126 str
= (void*)0xdeadbeef;
3127 hr
= IMXWriter_get_encoding(writer
, &str
);
3128 EXPECT_HR(hr
, S_OK
);
3129 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
3132 /* how it affects document creation */
3133 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3134 EXPECT_HR(hr
, S_OK
);
3136 hr
= ISAXContentHandler_startDocument(content
);
3137 EXPECT_HR(hr
, S_OK
);
3138 hr
= ISAXContentHandler_endDocument(content
);
3139 EXPECT_HR(hr
, S_OK
);
3141 V_VT(&dest
) = VT_EMPTY
;
3142 hr
= IMXWriter_get_output(writer
, &dest
);
3143 EXPECT_HR(hr
, S_OK
);
3144 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3145 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
3146 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3147 VariantClear(&dest
);
3148 ISAXContentHandler_Release(content
);
3150 hr
= IMXWriter_get_version(writer
, NULL
);
3151 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3152 /* default version is 'surprisingly' 1.0 */
3153 hr
= IMXWriter_get_version(writer
, &str
);
3154 ok(hr
== S_OK
, "got %08x\n", hr
);
3155 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
3158 /* store version string as is */
3159 hr
= IMXWriter_put_version(writer
, NULL
);
3160 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3162 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
3163 ok(hr
== S_OK
, "got %08x\n", hr
);
3165 hr
= IMXWriter_put_version(writer
, _bstr_(""));
3166 ok(hr
== S_OK
, "got %08x\n", hr
);
3167 hr
= IMXWriter_get_version(writer
, &str
);
3168 ok(hr
== S_OK
, "got %08x\n", hr
);
3169 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
3172 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
3173 ok(hr
== S_OK
, "got %08x\n", hr
);
3174 hr
= IMXWriter_get_version(writer
, &str
);
3175 ok(hr
== S_OK
, "got %08x\n", hr
);
3176 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
3179 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
3180 ok(hr
== S_OK
, "got %08x\n", hr
);
3181 hr
= IMXWriter_get_version(writer
, &str
);
3182 ok(hr
== S_OK
, "got %08x\n", hr
);
3183 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
3186 IMXWriter_Release(writer
);
3190 static void test_mxwriter_flush(void)
3192 ISAXContentHandler
*content
;
3195 ULARGE_INTEGER pos2
;
3203 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3204 &IID_IMXWriter
, (void**)&writer
);
3205 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3207 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3208 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3209 EXPECT_REF(stream
, 1);
3211 /* detach when nothing was attached */
3212 V_VT(&dest
) = VT_EMPTY
;
3213 hr
= IMXWriter_put_output(writer
, dest
);
3214 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3217 V_VT(&dest
) = VT_UNKNOWN
;
3218 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3219 hr
= IMXWriter_put_output(writer
, dest
);
3220 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3221 todo_wine
EXPECT_REF(stream
, 3);
3223 /* detach setting VT_EMPTY destination */
3224 V_VT(&dest
) = VT_EMPTY
;
3225 hr
= IMXWriter_put_output(writer
, dest
);
3226 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3227 EXPECT_REF(stream
, 1);
3229 V_VT(&dest
) = VT_UNKNOWN
;
3230 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3231 hr
= IMXWriter_put_output(writer
, dest
);
3232 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3234 /* flush() doesn't detach a stream */
3235 hr
= IMXWriter_flush(writer
);
3236 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3237 todo_wine
EXPECT_REF(stream
, 3);
3240 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3241 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3242 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3244 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3245 ok(hr
== S_OK
, "got %08x\n", hr
);
3247 hr
= ISAXContentHandler_startDocument(content
);
3248 ok(hr
== S_OK
, "got %08x\n", hr
);
3251 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3252 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3253 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
3255 /* already started */
3256 hr
= ISAXContentHandler_startDocument(content
);
3257 ok(hr
== S_OK
, "got %08x\n", hr
);
3259 hr
= ISAXContentHandler_endDocument(content
);
3260 ok(hr
== S_OK
, "got %08x\n", hr
);
3262 /* flushed on endDocument() */
3264 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3265 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3266 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
3268 IStream_Release(stream
);
3270 /* auto-flush feature */
3271 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3272 EXPECT_HR(hr
, S_OK
);
3273 EXPECT_REF(stream
, 1);
3275 V_VT(&dest
) = VT_UNKNOWN
;
3276 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3277 hr
= IMXWriter_put_output(writer
, dest
);
3278 EXPECT_HR(hr
, S_OK
);
3280 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_FALSE
);
3281 EXPECT_HR(hr
, S_OK
);
3283 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3284 EXPECT_HR(hr
, S_OK
);
3286 hr
= ISAXContentHandler_startDocument(content
);
3287 EXPECT_HR(hr
, S_OK
);
3289 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3290 EXPECT_HR(hr
, S_OK
);
3292 /* internal buffer is flushed automatically on certain threshold */
3295 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3296 EXPECT_HR(hr
, S_OK
);
3297 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3300 buff
= HeapAlloc(GetProcessHeap(), 0, len
+1);
3301 memset(buff
, 'A', len
);
3303 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3304 EXPECT_HR(hr
, S_OK
);
3308 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3309 EXPECT_HR(hr
, S_OK
);
3311 ok(pos2
.QuadPart
!= 0, "unexpected stream beginning\n");
3313 hr
= IMXWriter_get_output(writer
, NULL
);
3314 EXPECT_HR(hr
, E_POINTER
);
3316 ref
= get_refcount(stream
);
3317 V_VT(&dest
) = VT_EMPTY
;
3318 hr
= IMXWriter_get_output(writer
, &dest
);
3319 EXPECT_HR(hr
, S_OK
);
3320 ok(V_VT(&dest
) == VT_UNKNOWN
, "got vt type %d\n", V_VT(&dest
));
3321 ok(V_UNKNOWN(&dest
) == (IUnknown
*)stream
, "got pointer %p\n", V_UNKNOWN(&dest
));
3322 ok(ref
+1 == get_refcount(stream
), "expected increased refcount\n");
3323 VariantClear(&dest
);
3325 hr
= ISAXContentHandler_endDocument(content
);
3326 EXPECT_HR(hr
, S_OK
);
3328 IStream_Release(stream
);
3330 /* test char count lower than threshold */
3331 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3332 EXPECT_HR(hr
, S_OK
);
3333 EXPECT_REF(stream
, 1);
3335 hr
= ISAXContentHandler_startDocument(content
);
3336 EXPECT_HR(hr
, S_OK
);
3338 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3339 EXPECT_HR(hr
, S_OK
);
3343 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3344 EXPECT_HR(hr
, S_OK
);
3345 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3347 memset(buff
, 'A', len
);
3349 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
- 8);
3350 EXPECT_HR(hr
, S_OK
);
3354 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3355 EXPECT_HR(hr
, S_OK
);
3356 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3358 hr
= ISAXContentHandler_endDocument(content
);
3359 EXPECT_HR(hr
, S_OK
);
3361 /* test auto-flush function when stream is not set */
3362 V_VT(&dest
) = VT_EMPTY
;
3363 hr
= IMXWriter_put_output(writer
, dest
);
3364 EXPECT_HR(hr
, S_OK
);
3366 hr
= ISAXContentHandler_startDocument(content
);
3367 EXPECT_HR(hr
, S_OK
);
3369 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3370 EXPECT_HR(hr
, S_OK
);
3372 memset(buff
, 'A', len
);
3374 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3375 EXPECT_HR(hr
, S_OK
);
3377 V_VT(&dest
) = VT_EMPTY
;
3378 hr
= IMXWriter_get_output(writer
, &dest
);
3379 EXPECT_HR(hr
, S_OK
);
3380 len
+= strlen("<a>");
3381 ok(SysStringLen(V_BSTR(&dest
)) == len
, "got len=%d, expected %d\n", SysStringLen(V_BSTR(&dest
)), len
);
3382 VariantClear(&dest
);
3384 HeapFree(GetProcessHeap(), 0, buff
);
3385 ISAXContentHandler_Release(content
);
3386 IStream_Release(stream
);
3387 IMXWriter_Release(writer
);
3391 static void test_mxwriter_startenddocument(void)
3393 ISAXContentHandler
*content
;
3398 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3399 &IID_IMXWriter
, (void**)&writer
);
3400 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3402 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3403 ok(hr
== S_OK
, "got %08x\n", hr
);
3405 hr
= ISAXContentHandler_startDocument(content
);
3406 ok(hr
== S_OK
, "got %08x\n", hr
);
3408 hr
= ISAXContentHandler_endDocument(content
);
3409 ok(hr
== S_OK
, "got %08x\n", hr
);
3411 V_VT(&dest
) = VT_EMPTY
;
3412 hr
= IMXWriter_get_output(writer
, &dest
);
3413 ok(hr
== S_OK
, "got %08x\n", hr
);
3414 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3415 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3416 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3417 VariantClear(&dest
);
3419 /* now try another startDocument */
3420 hr
= ISAXContentHandler_startDocument(content
);
3421 ok(hr
== S_OK
, "got %08x\n", hr
);
3422 /* and get duplicated prolog */
3423 V_VT(&dest
) = VT_EMPTY
;
3424 hr
= IMXWriter_get_output(writer
, &dest
);
3425 ok(hr
== S_OK
, "got %08x\n", hr
);
3426 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3427 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
3428 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3429 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3430 VariantClear(&dest
);
3432 ISAXContentHandler_Release(content
);
3433 IMXWriter_Release(writer
);
3435 /* now with omitted declaration */
3436 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3437 &IID_IMXWriter
, (void**)&writer
);
3438 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3440 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3441 ok(hr
== S_OK
, "got %08x\n", hr
);
3443 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3444 ok(hr
== S_OK
, "got %08x\n", hr
);
3446 hr
= ISAXContentHandler_startDocument(content
);
3447 ok(hr
== S_OK
, "got %08x\n", hr
);
3449 hr
= ISAXContentHandler_endDocument(content
);
3450 ok(hr
== S_OK
, "got %08x\n", hr
);
3452 V_VT(&dest
) = VT_EMPTY
;
3453 hr
= IMXWriter_get_output(writer
, &dest
);
3454 ok(hr
== S_OK
, "got %08x\n", hr
);
3455 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3456 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3457 VariantClear(&dest
);
3459 ISAXContentHandler_Release(content
);
3460 IMXWriter_Release(writer
);
3467 StartElement
= 0x001,
3469 StartEndElement
= 0x011,
3470 DisableEscaping
= 0x100
3473 struct writer_startendelement_t
{
3475 enum startendtype type
;
3477 const char *local_name
;
3481 ISAXAttributes
*attr
;
3484 static const char startelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\'\">";
3485 static const char startendelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\'\"/>";
3486 static const char startendelement_noescape_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&\">\'\"/>";
3488 static const struct writer_startendelement_t writer_startendelement
[] = {
3490 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3491 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3492 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3493 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
3494 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3496 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3497 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3498 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
3499 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3500 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3502 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3503 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
3504 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3505 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3506 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3508 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
3509 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3510 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3511 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3512 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3514 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3515 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3516 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3517 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
3518 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3520 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3521 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3522 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3523 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3524 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3526 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3527 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3528 /* endElement tests */
3529 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3530 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3531 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3533 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
3534 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3535 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3536 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3537 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
3539 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3540 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3541 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3542 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
3543 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3545 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3546 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3547 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
3548 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3549 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3551 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3552 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3553 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3554 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3555 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3557 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
3558 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3559 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3560 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3561 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3563 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3564 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3565 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3566 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3568 /* with attributes */
3569 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3571 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3572 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3573 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3574 /* empty elements */
3575 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3576 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3578 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3579 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3580 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
3581 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
3582 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
3584 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
3586 /* with disabled output escaping */
3587 { &CLSID_MXXMLWriter
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3588 { &CLSID_MXXMLWriter30
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3589 { &CLSID_MXXMLWriter40
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3590 { &CLSID_MXXMLWriter60
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3595 static void get_class_support_data(struct msxmlsupported_data_t
*table
, REFIID riid
)
3597 while (table
->clsid
)
3602 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, riid
, (void**)&unk
);
3603 if (hr
== S_OK
) IUnknown_Release(unk
);
3605 table
->supported
= hr
== S_OK
;
3606 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
3612 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
3616 while (table
->clsid
)
3618 ISAXContentHandler
*content
;
3622 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3629 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3630 &IID_IMXWriter
, (void**)&writer
);
3631 EXPECT_HR(hr
, S_OK
);
3633 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3634 EXPECT_HR(hr
, S_OK
);
3636 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3637 EXPECT_HR(hr
, S_OK
);
3639 hr
= ISAXContentHandler_startDocument(content
);
3640 EXPECT_HR(hr
, S_OK
);
3642 if (table
->type
& DisableEscaping
)
3644 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3645 EXPECT_HR(hr
, S_OK
);
3648 if (table
->type
& StartElement
)
3650 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), table
->uri
? strlen(table
->uri
) : 0,
3651 _bstr_(table
->local_name
), table
->local_name
? strlen(table
->local_name
) : 0, _bstr_(table
->qname
),
3652 table
->qname
? strlen(table
->qname
) : 0, table
->attr
);
3653 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3656 if (table
->type
& EndElement
)
3658 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), table
->uri
? strlen(table
->uri
) : 0,
3659 _bstr_(table
->local_name
), table
->local_name
? strlen(table
->local_name
) : 0, _bstr_(table
->qname
),
3660 table
->qname
? strlen(table
->qname
) : 0);
3661 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3669 V_VT(&dest
) = VT_EMPTY
;
3670 hr
= IMXWriter_get_output(writer
, &dest
);
3671 EXPECT_HR(hr
, S_OK
);
3672 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3673 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3674 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3675 VariantClear(&dest
);
3678 ISAXContentHandler_Release(content
);
3679 IMXWriter_Release(writer
);
3688 /* point of these test is to start/end element with different names and name lengths */
3689 struct writer_startendelement2_t
{
3691 const char *qnamestart
;
3693 const char *qnameend
;
3699 static const struct writer_startendelement2_t writer_startendelement2
[] = {
3700 { &CLSID_MXXMLWriter
, "a", -1, "b", -1, "<a/>", S_OK
},
3701 { &CLSID_MXXMLWriter30
, "a", -1, "b", -1, "<a/>", S_OK
},
3702 { &CLSID_MXXMLWriter40
, "a", -1, "b", -1, "<a/>", S_OK
},
3703 /* -1 length is not allowed for version 6 */
3704 { &CLSID_MXXMLWriter60
, "a", -1, "b", -1, "<a/>", E_INVALIDARG
},
3706 { &CLSID_MXXMLWriter
, "a", 1, "b", 1, "<a/>", S_OK
},
3707 { &CLSID_MXXMLWriter30
, "a", 1, "b", 1, "<a/>", S_OK
},
3708 { &CLSID_MXXMLWriter40
, "a", 1, "b", 1, "<a/>", S_OK
},
3709 { &CLSID_MXXMLWriter60
, "a", 1, "b", 1, "<a/>", S_OK
},
3713 static void test_mxwriter_startendelement_batch2(const struct writer_startendelement2_t
*table
)
3717 while (table
->clsid
)
3719 ISAXContentHandler
*content
;
3723 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3730 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3731 &IID_IMXWriter
, (void**)&writer
);
3732 EXPECT_HR(hr
, S_OK
);
3734 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3735 EXPECT_HR(hr
, S_OK
);
3737 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3738 EXPECT_HR(hr
, S_OK
);
3740 hr
= ISAXContentHandler_startDocument(content
);
3741 EXPECT_HR(hr
, S_OK
);
3743 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3744 _bstr_(table
->qnamestart
), table
->qnamestart_len
, NULL
);
3745 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3747 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3748 _bstr_(table
->qnameend
), table
->qnameend_len
);
3749 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3756 V_VT(&dest
) = VT_EMPTY
;
3757 hr
= IMXWriter_get_output(writer
, &dest
);
3758 EXPECT_HR(hr
, S_OK
);
3759 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3760 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3761 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3762 VariantClear(&dest
);
3765 ISAXContentHandler_Release(content
);
3766 IMXWriter_Release(writer
);
3776 static void test_mxwriter_startendelement(void)
3778 ISAXContentHandler
*content
;
3783 test_mxwriter_startendelement_batch(writer_startendelement
);
3784 test_mxwriter_startendelement_batch2(writer_startendelement2
);
3786 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3787 &IID_IMXWriter
, (void**)&writer
);
3788 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3790 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3791 ok(hr
== S_OK
, "got %08x\n", hr
);
3793 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3794 ok(hr
== S_OK
, "got %08x\n", hr
);
3796 hr
= ISAXContentHandler_startDocument(content
);
3797 ok(hr
== S_OK
, "got %08x\n", hr
);
3799 /* all string pointers should be not null */
3800 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
3801 ok(hr
== S_OK
, "got %08x\n", hr
);
3803 V_VT(&dest
) = VT_EMPTY
;
3804 hr
= IMXWriter_get_output(writer
, &dest
);
3805 ok(hr
== S_OK
, "got %08x\n", hr
);
3806 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3807 ok(!lstrcmpW(_bstr_("<>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3808 VariantClear(&dest
);
3810 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
3811 ok(hr
== S_OK
, "got %08x\n", hr
);
3813 V_VT(&dest
) = VT_EMPTY
;
3814 hr
= IMXWriter_get_output(writer
, &dest
);
3815 ok(hr
== S_OK
, "got %08x\n", hr
);
3816 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3817 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3818 VariantClear(&dest
);
3820 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
3821 EXPECT_HR(hr
, E_INVALIDARG
);
3823 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
3824 EXPECT_HR(hr
, E_INVALIDARG
);
3826 /* only local name is an error too */
3827 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
3828 EXPECT_HR(hr
, E_INVALIDARG
);
3830 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
3831 EXPECT_HR(hr
, S_OK
);
3833 V_VT(&dest
) = VT_EMPTY
;
3834 hr
= IMXWriter_get_output(writer
, &dest
);
3835 EXPECT_HR(hr
, S_OK
);
3836 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3837 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3838 VariantClear(&dest
);
3840 hr
= ISAXContentHandler_endDocument(content
);
3841 EXPECT_HR(hr
, S_OK
);
3843 V_VT(&dest
) = VT_EMPTY
;
3844 hr
= IMXWriter_put_output(writer
, dest
);
3845 EXPECT_HR(hr
, S_OK
);
3847 V_VT(&dest
) = VT_EMPTY
;
3848 hr
= IMXWriter_get_output(writer
, &dest
);
3849 EXPECT_HR(hr
, S_OK
);
3850 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3851 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3852 VariantClear(&dest
);
3854 hr
= ISAXContentHandler_startDocument(content
);
3855 EXPECT_HR(hr
, S_OK
);
3857 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
3858 EXPECT_HR(hr
, S_OK
);
3860 V_VT(&dest
) = VT_EMPTY
;
3861 hr
= IMXWriter_get_output(writer
, &dest
);
3862 EXPECT_HR(hr
, S_OK
);
3863 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3864 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3865 VariantClear(&dest
);
3867 hr
= ISAXContentHandler_endDocument(content
);
3868 EXPECT_HR(hr
, S_OK
);
3869 IMXWriter_flush(writer
);
3871 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
3872 EXPECT_HR(hr
, S_OK
);
3873 V_VT(&dest
) = VT_EMPTY
;
3874 hr
= IMXWriter_get_output(writer
, &dest
);
3875 EXPECT_HR(hr
, S_OK
);
3876 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3877 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3878 VariantClear(&dest
);
3880 V_VT(&dest
) = VT_EMPTY
;
3881 hr
= IMXWriter_put_output(writer
, dest
);
3882 EXPECT_HR(hr
, S_OK
);
3885 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), -1, NULL
);
3886 EXPECT_HR(hr
, S_OK
);
3887 V_VT(&dest
) = VT_EMPTY
;
3888 hr
= IMXWriter_get_output(writer
, &dest
);
3889 EXPECT_HR(hr
, S_OK
);
3890 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3891 ok(!lstrcmpW(_bstr_("<a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3892 VariantClear(&dest
);
3894 ISAXContentHandler_Release(content
);
3895 IMXWriter_Release(writer
);
3899 struct writer_characters_t
{
3905 static const struct writer_characters_t writer_characters
[] = {
3906 { &CLSID_MXXMLWriter
, "< > & \" \'", "< > & \" \'" },
3907 { &CLSID_MXXMLWriter30
, "< > & \" \'", "< > & \" \'" },
3908 { &CLSID_MXXMLWriter40
, "< > & \" \'", "< > & \" \'" },
3909 { &CLSID_MXXMLWriter60
, "< > & \" \'", "< > & \" \'" },
3913 static void test_mxwriter_characters(void)
3915 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
3916 const struct writer_characters_t
*table
= writer_characters
;
3917 ISAXContentHandler
*content
;
3923 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3924 &IID_IMXWriter
, (void**)&writer
);
3925 EXPECT_HR(hr
, S_OK
);
3927 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3928 EXPECT_HR(hr
, S_OK
);
3930 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3931 EXPECT_HR(hr
, S_OK
);
3933 hr
= ISAXContentHandler_startDocument(content
);
3934 EXPECT_HR(hr
, S_OK
);
3936 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
3937 EXPECT_HR(hr
, E_INVALIDARG
);
3939 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3940 EXPECT_HR(hr
, S_OK
);
3942 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
3943 EXPECT_HR(hr
, S_OK
);
3945 V_VT(&dest
) = VT_EMPTY
;
3946 hr
= IMXWriter_get_output(writer
, &dest
);
3947 EXPECT_HR(hr
, S_OK
);
3948 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3949 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3950 VariantClear(&dest
);
3952 hr
= ISAXContentHandler_endDocument(content
);
3953 EXPECT_HR(hr
, S_OK
);
3955 ISAXContentHandler_Release(content
);
3956 IMXWriter_Release(writer
);
3958 /* try empty characters data to see if element is closed */
3959 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3960 &IID_IMXWriter
, (void**)&writer
);
3961 EXPECT_HR(hr
, S_OK
);
3963 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3964 EXPECT_HR(hr
, S_OK
);
3966 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3967 EXPECT_HR(hr
, S_OK
);
3969 hr
= ISAXContentHandler_startDocument(content
);
3970 EXPECT_HR(hr
, S_OK
);
3972 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3973 EXPECT_HR(hr
, S_OK
);
3975 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3976 EXPECT_HR(hr
, S_OK
);
3978 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3979 EXPECT_HR(hr
, S_OK
);
3981 V_VT(&dest
) = VT_EMPTY
;
3982 hr
= IMXWriter_get_output(writer
, &dest
);
3983 EXPECT_HR(hr
, S_OK
);
3984 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3985 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3986 VariantClear(&dest
);
3988 ISAXContentHandler_Release(content
);
3989 IMXWriter_Release(writer
);
3992 while (table
->clsid
)
3994 ISAXContentHandler
*content
;
3999 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
4006 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4007 &IID_IMXWriter
, (void**)&writer
);
4008 EXPECT_HR(hr
, S_OK
);
4010 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4011 EXPECT_HR(hr
, S_OK
);
4013 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4014 EXPECT_HR(hr
, S_OK
);
4016 hr
= ISAXContentHandler_startDocument(content
);
4017 EXPECT_HR(hr
, S_OK
);
4019 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
4020 EXPECT_HR(hr
, S_OK
);
4025 V_VT(&dest
) = VT_EMPTY
;
4026 hr
= IMXWriter_get_output(writer
, &dest
);
4027 EXPECT_HR(hr
, S_OK
);
4028 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4029 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
4030 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
4031 VariantClear(&dest
);
4034 /* with disabled escaping */
4035 V_VT(&dest
) = VT_EMPTY
;
4036 hr
= IMXWriter_put_output(writer
, dest
);
4037 EXPECT_HR(hr
, S_OK
);
4039 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
4040 EXPECT_HR(hr
, S_OK
);
4042 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
4043 EXPECT_HR(hr
, S_OK
);
4048 V_VT(&dest
) = VT_EMPTY
;
4049 hr
= IMXWriter_get_output(writer
, &dest
);
4050 EXPECT_HR(hr
, S_OK
);
4051 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4052 ok(!lstrcmpW(_bstr_(table
->data
), V_BSTR(&dest
)),
4053 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->data
);
4054 VariantClear(&dest
);
4057 ISAXContentHandler_Release(content
);
4058 IMXWriter_Release(writer
);
4067 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
4069 VARIANT_TRUE
,"UTF-16",
4071 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
4072 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4077 VARIANT_FALSE
,"UTF-16",
4079 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4084 VARIANT_TRUE
,"UTF-8",
4086 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
4087 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
4088 * and the writer is released.
4095 VARIANT_TRUE
,"utf-8",
4097 {FALSE
,(const BYTE
*)utf8xml2
,sizeof(utf8xml2
)-1},
4098 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
4099 * and the writer is released.
4106 VARIANT_TRUE
,"UTF-16",
4108 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
4109 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4114 VARIANT_TRUE
,"UTF-16",
4116 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
4117 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4123 static void test_mxwriter_stream(void)
4126 ISAXContentHandler
*content
;
4131 ULARGE_INTEGER pos2
;
4132 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
4134 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
4135 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
4137 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4138 &IID_IMXWriter
, (void**)&writer
);
4139 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4141 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4142 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4144 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
4145 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
4147 V_VT(&dest
) = VT_UNKNOWN
;
4148 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
4149 hr
= IMXWriter_put_output(writer
, dest
);
4150 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
4151 VariantClear(&dest
);
4153 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
4154 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
4156 current_write_test
= test
->expected_writes
;
4158 hr
= ISAXContentHandler_startDocument(content
);
4159 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4161 hr
= ISAXContentHandler_endDocument(content
);
4162 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4164 ISAXContentHandler_Release(content
);
4165 IMXWriter_Release(writer
);
4167 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
4168 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
4171 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4172 &IID_IMXWriter
, (void**)&writer
);
4173 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4175 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4176 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
4178 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4179 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4181 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4182 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
4184 V_VT(&dest
) = VT_UNKNOWN
;
4185 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4186 hr
= IMXWriter_put_output(writer
, dest
);
4187 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4189 hr
= ISAXContentHandler_startDocument(content
);
4190 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4192 /* Setting output of the mxwriter causes the current output to be flushed,
4193 * and the writer to start over.
4195 V_VT(&dest
) = VT_EMPTY
;
4196 hr
= IMXWriter_put_output(writer
, dest
);
4197 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4200 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4201 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
4202 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
4204 hr
= ISAXContentHandler_startDocument(content
);
4205 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4207 hr
= ISAXContentHandler_endDocument(content
);
4208 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
4210 V_VT(&dest
) = VT_EMPTY
;
4211 hr
= IMXWriter_get_output(writer
, &dest
);
4212 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
4213 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4214 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4215 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4216 VariantClear(&dest
);
4218 /* test when BOM is written to output stream */
4219 V_VT(&dest
) = VT_EMPTY
;
4220 hr
= IMXWriter_put_output(writer
, dest
);
4221 EXPECT_HR(hr
, S_OK
);
4224 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
4225 EXPECT_HR(hr
, S_OK
);
4227 V_VT(&dest
) = VT_UNKNOWN
;
4228 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4229 hr
= IMXWriter_put_output(writer
, dest
);
4230 EXPECT_HR(hr
, S_OK
);
4232 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_TRUE
);
4233 EXPECT_HR(hr
, S_OK
);
4235 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4236 EXPECT_HR(hr
, S_OK
);
4238 hr
= ISAXContentHandler_startDocument(content
);
4239 EXPECT_HR(hr
, S_OK
);
4243 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4244 EXPECT_HR(hr
, S_OK
);
4245 ok(pos2
.QuadPart
== 2, "got wrong position\n");
4247 ISAXContentHandler_Release(content
);
4248 IMXWriter_Release(writer
);
4253 static const char *encoding_names
[] = {
4266 static void test_mxwriter_encoding(void)
4268 ISAXContentHandler
*content
;
4279 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4280 &IID_IMXWriter
, (void**)&writer
);
4281 EXPECT_HR(hr
, S_OK
);
4283 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4284 EXPECT_HR(hr
, S_OK
);
4286 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4287 EXPECT_HR(hr
, S_OK
);
4289 hr
= ISAXContentHandler_startDocument(content
);
4290 EXPECT_HR(hr
, S_OK
);
4292 hr
= ISAXContentHandler_endDocument(content
);
4293 EXPECT_HR(hr
, S_OK
);
4295 /* The content is always re-encoded to UTF-16 when the output is
4296 * retrieved as a BSTR.
4298 V_VT(&dest
) = VT_EMPTY
;
4299 hr
= IMXWriter_get_output(writer
, &dest
);
4300 EXPECT_HR(hr
, S_OK
);
4301 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4302 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4303 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4304 VariantClear(&dest
);
4306 /* switch encoding when something is written already */
4307 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4308 EXPECT_HR(hr
, S_OK
);
4310 V_VT(&dest
) = VT_UNKNOWN
;
4311 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4312 hr
= IMXWriter_put_output(writer
, dest
);
4313 EXPECT_HR(hr
, S_OK
);
4315 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4316 EXPECT_HR(hr
, S_OK
);
4318 /* write empty element */
4319 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
4320 EXPECT_HR(hr
, S_OK
);
4322 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
4323 EXPECT_HR(hr
, S_OK
);
4326 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4327 EXPECT_HR(hr
, S_OK
);
4329 hr
= IMXWriter_flush(writer
);
4330 EXPECT_HR(hr
, S_OK
);
4332 hr
= GetHGlobalFromStream(stream
, &g
);
4333 EXPECT_HR(hr
, S_OK
);
4335 ptr
= GlobalLock(g
);
4336 ok(!strncmp(ptr
, "<a/>", 4), "got %c%c%c%c\n", ptr
[0],ptr
[1],ptr
[2],ptr
[3]);
4339 /* so output is unaffected, encoding name is stored however */
4340 hr
= IMXWriter_get_encoding(writer
, &s
);
4341 EXPECT_HR(hr
, S_OK
);
4342 ok(!lstrcmpW(s
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(s
));
4345 IStream_Release(stream
);
4348 enc
= encoding_names
[i
];
4351 char expectedA
[200];
4353 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4354 EXPECT_HR(hr
, S_OK
);
4356 V_VT(&dest
) = VT_UNKNOWN
;
4357 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4358 hr
= IMXWriter_put_output(writer
, dest
);
4359 EXPECT_HR(hr
, S_OK
);
4361 hr
= IMXWriter_put_encoding(writer
, _bstr_(enc
));
4362 ok(hr
== S_OK
|| broken(hr
!= S_OK
) /* old win versions do not support certain encodings */,
4363 "%s: encoding not accepted\n", enc
);
4366 enc
= encoding_names
[++i
];
4367 IStream_Release(stream
);
4371 hr
= ISAXContentHandler_startDocument(content
);
4372 EXPECT_HR(hr
, S_OK
);
4374 hr
= ISAXContentHandler_endDocument(content
);
4375 EXPECT_HR(hr
, S_OK
);
4377 hr
= IMXWriter_flush(writer
);
4378 EXPECT_HR(hr
, S_OK
);
4380 /* prepare expected string */
4382 strcat(expectedA
, "<?xml version=\"1.0\" encoding=\"");
4383 strcat(expectedA
, enc
);
4384 strcat(expectedA
, "\" standalone=\"no\"?>\r\n");
4386 hr
= GetHGlobalFromStream(stream
, &g
);
4387 EXPECT_HR(hr
, S_OK
);
4389 ptr
= GlobalLock(g
);
4390 ok(!strncmp(ptr
, expectedA
, strlen(expectedA
)), "%s: got %s, expected %.50s\n", enc
, ptr
, expectedA
);
4393 V_VT(&dest
) = VT_EMPTY
;
4394 hr
= IMXWriter_put_output(writer
, dest
);
4395 EXPECT_HR(hr
, S_OK
);
4397 IStream_Release(stream
);
4399 enc
= encoding_names
[++i
];
4402 ISAXContentHandler_Release(content
);
4403 IMXWriter_Release(writer
);
4408 static void test_obj_dispex(IUnknown
*obj
)
4410 static const WCHAR testW
[] = {'t','e','s','t','p','r','o','p',0};
4411 static const WCHAR starW
[] = {'*',0};
4412 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
4413 IDispatchEx
*dispex
;
4421 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
4422 EXPECT_HR(hr
, S_OK
);
4423 if (FAILED(hr
)) return;
4426 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
4427 EXPECT_HR(hr
, S_OK
);
4428 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
4430 name
= SysAllocString(starW
);
4431 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
4432 EXPECT_HR(hr
, E_NOTIMPL
);
4433 SysFreeString(name
);
4435 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
4436 EXPECT_HR(hr
, E_NOTIMPL
);
4439 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
4440 EXPECT_HR(hr
, E_NOTIMPL
);
4441 ok(props
== 0, "expected 0 got %d\n", props
);
4443 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
4444 EXPECT_HR(hr
, E_NOTIMPL
);
4445 if (SUCCEEDED(hr
)) SysFreeString(name
);
4447 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
4448 EXPECT_HR(hr
, E_NOTIMPL
);
4450 unk
= (IUnknown
*)0xdeadbeef;
4451 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
4452 EXPECT_HR(hr
, E_NOTIMPL
);
4453 ok(unk
== (IUnknown
*)0xdeadbeef, "got %p\n", unk
);
4455 name
= SysAllocString(testW
);
4456 hr
= IDispatchEx_GetDispID(dispex
, name
, fdexNameEnsure
, &did
);
4457 ok(hr
== DISP_E_UNKNOWNNAME
, "got 0x%08x\n", hr
);
4458 SysFreeString(name
);
4460 IDispatchEx_Release(dispex
);
4463 static void test_saxreader_dispex(void)
4465 IVBSAXXMLReader
*vbreader
;
4466 ISAXXMLReader
*reader
;
4467 DISPPARAMS dispparams
;
4473 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
4474 &IID_ISAXXMLReader
, (void**)&reader
);
4475 EXPECT_HR(hr
, S_OK
);
4477 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
4478 EXPECT_HR(hr
, S_OK
);
4479 test_obj_dispex(unk
);
4480 IUnknown_Release(unk
);
4482 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
4483 EXPECT_HR(hr
, S_OK
);
4484 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
4485 EXPECT_HR(hr
, S_OK
);
4486 test_obj_dispex(unk
);
4487 IUnknown_Release(unk
);
4489 dispid
= DISPID_PROPERTYPUT
;
4490 dispparams
.cArgs
= 1;
4491 dispparams
.cNamedArgs
= 1;
4492 dispparams
.rgdispidNamedArgs
= &dispid
;
4493 dispparams
.rgvarg
= &arg
;
4495 V_VT(&arg
) = VT_DISPATCH
;
4496 V_DISPATCH(&arg
) = NULL
;
4498 /* propputref is callable as PROPERTYPUT and PROPERTYPUTREF */
4499 hr
= IVBSAXXMLReader_Invoke(vbreader
,
4500 DISPID_SAX_XMLREADER_CONTENTHANDLER
,
4503 DISPATCH_PROPERTYPUT
,
4508 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4510 hr
= IVBSAXXMLReader_Invoke(vbreader
,
4511 DISPID_SAX_XMLREADER_CONTENTHANDLER
,
4514 DISPATCH_PROPERTYPUTREF
,
4519 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4521 IVBSAXXMLReader_Release(vbreader
);
4522 ISAXXMLReader_Release(reader
);
4524 if (is_clsid_supported(&CLSID_SAXXMLReader60
, reader_support_data
))
4526 hr
= CoCreateInstance(&CLSID_SAXXMLReader60
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&unk
);
4527 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4528 test_obj_dispex(unk
);
4529 IUnknown_Release(unk
);
4533 static void test_mxwriter_dispex(void)
4535 IDispatchEx
*dispex
;
4540 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4541 &IID_IMXWriter
, (void**)&writer
);
4542 EXPECT_HR(hr
, S_OK
);
4544 hr
= IMXWriter_QueryInterface(writer
, &IID_IDispatchEx
, (void**)&dispex
);
4545 EXPECT_HR(hr
, S_OK
);
4546 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4547 test_obj_dispex(unk
);
4548 IUnknown_Release(unk
);
4549 IDispatchEx_Release(dispex
);
4550 IMXWriter_Release(writer
);
4552 if (is_clsid_supported(&CLSID_MXXMLWriter60
, mxwriter_support_data
))
4554 hr
= CoCreateInstance(&CLSID_MXXMLWriter60
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&unk
);
4555 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4556 test_obj_dispex(unk
);
4557 IUnknown_Release(unk
);
4561 static void test_mxwriter_comment(void)
4563 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
4564 IVBSAXLexicalHandler
*vblexical
;
4565 ISAXContentHandler
*content
;
4566 ISAXLexicalHandler
*lexical
;
4571 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4572 &IID_IMXWriter
, (void**)&writer
);
4573 EXPECT_HR(hr
, S_OK
);
4575 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4576 EXPECT_HR(hr
, S_OK
);
4578 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4579 EXPECT_HR(hr
, S_OK
);
4581 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4582 EXPECT_HR(hr
, S_OK
);
4584 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4585 EXPECT_HR(hr
, S_OK
);
4587 hr
= ISAXContentHandler_startDocument(content
);
4588 EXPECT_HR(hr
, S_OK
);
4590 hr
= ISAXLexicalHandler_comment(lexical
, NULL
, 0);
4591 EXPECT_HR(hr
, E_INVALIDARG
);
4593 hr
= IVBSAXLexicalHandler_comment(vblexical
, NULL
);
4594 EXPECT_HR(hr
, E_POINTER
);
4596 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, 0);
4597 EXPECT_HR(hr
, S_OK
);
4599 V_VT(&dest
) = VT_EMPTY
;
4600 hr
= IMXWriter_get_output(writer
, &dest
);
4601 EXPECT_HR(hr
, S_OK
);
4602 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4603 ok(!lstrcmpW(_bstr_("<!---->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4604 VariantClear(&dest
);
4606 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, sizeof(commentW
)/sizeof(WCHAR
)-1);
4607 EXPECT_HR(hr
, S_OK
);
4609 V_VT(&dest
) = VT_EMPTY
;
4610 hr
= IMXWriter_get_output(writer
, &dest
);
4611 EXPECT_HR(hr
, S_OK
);
4612 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4613 ok(!lstrcmpW(_bstr_("<!---->\r\n<!--comment-->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4614 VariantClear(&dest
);
4616 ISAXContentHandler_Release(content
);
4617 ISAXLexicalHandler_Release(lexical
);
4618 IVBSAXLexicalHandler_Release(vblexical
);
4619 IMXWriter_Release(writer
);
4623 static void test_mxwriter_cdata(void)
4625 IVBSAXLexicalHandler
*vblexical
;
4626 ISAXContentHandler
*content
;
4627 ISAXLexicalHandler
*lexical
;
4632 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4633 &IID_IMXWriter
, (void**)&writer
);
4634 EXPECT_HR(hr
, S_OK
);
4636 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4637 EXPECT_HR(hr
, S_OK
);
4639 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4640 EXPECT_HR(hr
, S_OK
);
4642 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4643 EXPECT_HR(hr
, S_OK
);
4645 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4646 EXPECT_HR(hr
, S_OK
);
4648 hr
= ISAXContentHandler_startDocument(content
);
4649 EXPECT_HR(hr
, S_OK
);
4651 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4652 EXPECT_HR(hr
, S_OK
);
4654 V_VT(&dest
) = VT_EMPTY
;
4655 hr
= IMXWriter_get_output(writer
, &dest
);
4656 EXPECT_HR(hr
, S_OK
);
4657 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4658 ok(!lstrcmpW(_bstr_("<![CDATA["), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4659 VariantClear(&dest
);
4661 hr
= IVBSAXLexicalHandler_startCDATA(vblexical
);
4662 EXPECT_HR(hr
, S_OK
);
4664 /* all these are escaped for text nodes */
4665 hr
= ISAXContentHandler_characters(content
, _bstr_("< > & \""), 7);
4666 EXPECT_HR(hr
, S_OK
);
4668 hr
= ISAXLexicalHandler_endCDATA(lexical
);
4669 EXPECT_HR(hr
, S_OK
);
4671 V_VT(&dest
) = VT_EMPTY
;
4672 hr
= IMXWriter_get_output(writer
, &dest
);
4673 EXPECT_HR(hr
, S_OK
);
4674 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4675 ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4676 VariantClear(&dest
);
4678 ISAXContentHandler_Release(content
);
4679 ISAXLexicalHandler_Release(lexical
);
4680 IVBSAXLexicalHandler_Release(vblexical
);
4681 IMXWriter_Release(writer
);
4685 static void test_mxwriter_pi(void)
4687 static const WCHAR targetW
[] = {'t','a','r','g','e','t',0};
4688 static const WCHAR dataW
[] = {'d','a','t','a',0};
4689 ISAXContentHandler
*content
;
4694 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4695 &IID_IMXWriter
, (void**)&writer
);
4696 EXPECT_HR(hr
, S_OK
);
4698 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4699 EXPECT_HR(hr
, S_OK
);
4701 hr
= ISAXContentHandler_processingInstruction(content
, NULL
, 0, NULL
, 0);
4702 EXPECT_HR(hr
, E_INVALIDARG
);
4704 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 0, NULL
, 0);
4705 EXPECT_HR(hr
, S_OK
);
4707 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, NULL
, 0);
4708 EXPECT_HR(hr
, S_OK
);
4710 V_VT(&dest
) = VT_EMPTY
;
4711 hr
= IMXWriter_get_output(writer
, &dest
);
4712 EXPECT_HR(hr
, S_OK
);
4713 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4714 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4715 VariantClear(&dest
);
4717 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 4, dataW
, 4);
4718 EXPECT_HR(hr
, S_OK
);
4720 V_VT(&dest
) = VT_EMPTY
;
4721 hr
= IMXWriter_get_output(writer
, &dest
);
4722 EXPECT_HR(hr
, S_OK
);
4723 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4724 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
)));
4725 VariantClear(&dest
);
4727 V_VT(&dest
) = VT_EMPTY
;
4728 hr
= IMXWriter_put_output(writer
, dest
);
4729 EXPECT_HR(hr
, S_OK
);
4731 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, dataW
, 0);
4732 EXPECT_HR(hr
, S_OK
);
4734 V_VT(&dest
) = VT_EMPTY
;
4735 hr
= IMXWriter_get_output(writer
, &dest
);
4736 EXPECT_HR(hr
, S_OK
);
4737 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4738 ok(!lstrcmpW(_bstr_("<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4739 VariantClear(&dest
);
4742 ISAXContentHandler_Release(content
);
4743 IMXWriter_Release(writer
);
4746 static void test_mxwriter_ignorablespaces(void)
4748 static const WCHAR dataW
[] = {'d','a','t','a',0};
4749 ISAXContentHandler
*content
;
4754 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4755 &IID_IMXWriter
, (void**)&writer
);
4756 EXPECT_HR(hr
, S_OK
);
4758 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4759 EXPECT_HR(hr
, S_OK
);
4761 hr
= ISAXContentHandler_ignorableWhitespace(content
, NULL
, 0);
4762 EXPECT_HR(hr
, E_INVALIDARG
);
4764 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 0);
4765 EXPECT_HR(hr
, S_OK
);
4767 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 4);
4768 EXPECT_HR(hr
, S_OK
);
4770 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 1);
4771 EXPECT_HR(hr
, S_OK
);
4773 V_VT(&dest
) = VT_EMPTY
;
4774 hr
= IMXWriter_get_output(writer
, &dest
);
4775 EXPECT_HR(hr
, S_OK
);
4776 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4777 ok(!lstrcmpW(_bstr_("datad"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4778 VariantClear(&dest
);
4780 ISAXContentHandler_Release(content
);
4781 IMXWriter_Release(writer
);
4784 static void test_mxwriter_dtd(void)
4786 static const WCHAR contentW
[] = {'c','o','n','t','e','n','t'};
4787 static const WCHAR nameW
[] = {'n','a','m','e'};
4788 static const WCHAR pubW
[] = {'p','u','b'};
4789 static const WCHAR sysW
[] = {'s','y','s'};
4790 IVBSAXLexicalHandler
*vblexical
;
4791 ISAXContentHandler
*content
;
4792 ISAXLexicalHandler
*lexical
;
4793 IVBSAXDeclHandler
*vbdecl
;
4794 ISAXDeclHandler
*decl
;
4799 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4800 &IID_IMXWriter
, (void**)&writer
);
4801 EXPECT_HR(hr
, S_OK
);
4803 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4804 EXPECT_HR(hr
, S_OK
);
4806 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4807 EXPECT_HR(hr
, S_OK
);
4809 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
4810 EXPECT_HR(hr
, S_OK
);
4812 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXDeclHandler
, (void**)&vbdecl
);
4813 EXPECT_HR(hr
, S_OK
);
4815 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4816 EXPECT_HR(hr
, S_OK
);
4818 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4819 EXPECT_HR(hr
, S_OK
);
4821 hr
= ISAXContentHandler_startDocument(content
);
4822 EXPECT_HR(hr
, S_OK
);
4824 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, NULL
, 0);
4825 EXPECT_HR(hr
, E_INVALIDARG
);
4827 hr
= IVBSAXLexicalHandler_startDTD(vblexical
, NULL
, NULL
, NULL
);
4828 EXPECT_HR(hr
, E_POINTER
);
4830 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4831 EXPECT_HR(hr
, E_INVALIDARG
);
4833 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4834 EXPECT_HR(hr
, E_INVALIDARG
);
4836 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4837 EXPECT_HR(hr
, E_INVALIDARG
);
4839 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0, NULL
, 0);
4840 EXPECT_HR(hr
, S_OK
);
4842 V_VT(&dest
) = VT_EMPTY
;
4843 hr
= IMXWriter_get_output(writer
, &dest
);
4844 EXPECT_HR(hr
, S_OK
);
4845 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4846 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4847 VariantClear(&dest
);
4849 /* system id is required if public is present */
4850 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4851 EXPECT_HR(hr
, E_INVALIDARG
);
4853 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
),
4854 pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4855 EXPECT_HR(hr
, S_OK
);
4857 V_VT(&dest
) = VT_EMPTY
;
4858 hr
= IMXWriter_get_output(writer
, &dest
);
4859 EXPECT_HR(hr
, S_OK
);
4860 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4861 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4862 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4863 VariantClear(&dest
);
4865 hr
= ISAXLexicalHandler_endDTD(lexical
);
4866 EXPECT_HR(hr
, S_OK
);
4868 hr
= IVBSAXLexicalHandler_endDTD(vblexical
);
4869 EXPECT_HR(hr
, S_OK
);
4871 V_VT(&dest
) = VT_EMPTY
;
4872 hr
= IMXWriter_get_output(writer
, &dest
);
4873 EXPECT_HR(hr
, S_OK
);
4874 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4875 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4876 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n"),
4877 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4878 VariantClear(&dest
);
4880 /* element declaration */
4881 V_VT(&dest
) = VT_EMPTY
;
4882 hr
= IMXWriter_put_output(writer
, dest
);
4883 EXPECT_HR(hr
, S_OK
);
4885 hr
= ISAXDeclHandler_elementDecl(decl
, NULL
, 0, NULL
, 0);
4886 EXPECT_HR(hr
, E_INVALIDARG
);
4888 hr
= IVBSAXDeclHandler_elementDecl(vbdecl
, NULL
, NULL
);
4889 EXPECT_HR(hr
, E_POINTER
);
4891 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0);
4892 EXPECT_HR(hr
, E_INVALIDARG
);
4894 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, sizeof(contentW
)/sizeof(WCHAR
));
4895 EXPECT_HR(hr
, S_OK
);
4897 V_VT(&dest
) = VT_EMPTY
;
4898 hr
= IMXWriter_get_output(writer
, &dest
);
4899 EXPECT_HR(hr
, S_OK
);
4900 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4901 ok(!lstrcmpW(_bstr_("<!ELEMENT name content>\r\n"),
4902 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4903 VariantClear(&dest
);
4905 V_VT(&dest
) = VT_EMPTY
;
4906 hr
= IMXWriter_put_output(writer
, dest
);
4907 EXPECT_HR(hr
, S_OK
);
4909 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, 0);
4910 EXPECT_HR(hr
, S_OK
);
4912 V_VT(&dest
) = VT_EMPTY
;
4913 hr
= IMXWriter_get_output(writer
, &dest
);
4914 EXPECT_HR(hr
, S_OK
);
4915 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4916 ok(!lstrcmpW(_bstr_("<!ELEMENT name >\r\n"),
4917 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4918 VariantClear(&dest
);
4920 /* attribute declaration */
4921 V_VT(&dest
) = VT_EMPTY
;
4922 hr
= IMXWriter_put_output(writer
, dest
);
4923 EXPECT_HR(hr
, S_OK
);
4925 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4926 _bstr_("attribute"), strlen("attribute"), _bstr_("CDATA"), strlen("CDATA"),
4927 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value"), strlen("value"));
4928 EXPECT_HR(hr
, S_OK
);
4930 V_VT(&dest
) = VT_EMPTY
;
4931 hr
= IMXWriter_get_output(writer
, &dest
);
4932 EXPECT_HR(hr
, S_OK
);
4933 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4934 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"),
4935 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4936 VariantClear(&dest
);
4938 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4939 _bstr_("attribute2"), strlen("attribute2"), _bstr_("CDATA"), strlen("CDATA"),
4940 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value2"), strlen("value2"));
4941 EXPECT_HR(hr
, S_OK
);
4943 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element2"), strlen("element2"),
4944 _bstr_("attribute3"), strlen("attribute3"), _bstr_("CDATA"), strlen("CDATA"),
4945 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value3"), strlen("value3"));
4946 EXPECT_HR(hr
, S_OK
);
4948 V_VT(&dest
) = VT_EMPTY
;
4949 hr
= IMXWriter_get_output(writer
, &dest
);
4950 EXPECT_HR(hr
, S_OK
);
4951 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4952 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"
4953 "<!ATTLIST element attribute2 CDATA #REQUIRED \"value2\">\r\n"
4954 "<!ATTLIST element2 attribute3 CDATA #REQUIRED \"value3\">\r\n"),
4955 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4956 VariantClear(&dest
);
4958 /* internal entities */
4959 V_VT(&dest
) = VT_EMPTY
;
4960 hr
= IMXWriter_put_output(writer
, dest
);
4961 EXPECT_HR(hr
, S_OK
);
4963 hr
= ISAXDeclHandler_internalEntityDecl(decl
, NULL
, 0, NULL
, 0);
4964 EXPECT_HR(hr
, E_INVALIDARG
);
4966 hr
= IVBSAXDeclHandler_internalEntityDecl(vbdecl
, NULL
, NULL
);
4967 EXPECT_HR(hr
, E_POINTER
);
4969 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0);
4970 EXPECT_HR(hr
, E_INVALIDARG
);
4972 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("value"), strlen("value"));
4973 EXPECT_HR(hr
, S_OK
);
4975 V_VT(&dest
) = VT_EMPTY
;
4976 hr
= IMXWriter_get_output(writer
, &dest
);
4977 EXPECT_HR(hr
, S_OK
);
4978 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4979 ok(!lstrcmpW(_bstr_("<!ENTITY name \"value\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4980 VariantClear(&dest
);
4982 /* external entities */
4983 V_VT(&dest
) = VT_EMPTY
;
4984 hr
= IMXWriter_put_output(writer
, dest
);
4985 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4987 hr
= ISAXDeclHandler_externalEntityDecl(decl
, NULL
, 0, NULL
, 0, NULL
, 0);
4988 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4990 hr
= IVBSAXDeclHandler_externalEntityDecl(vbdecl
, NULL
, NULL
, NULL
);
4991 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
4993 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0, NULL
, 0);
4994 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4996 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"),
4997 _bstr_("sysid"), strlen("sysid"));
4998 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5000 V_VT(&dest
) = VT_EMPTY
;
5001 hr
= IMXWriter_get_output(writer
, &dest
);
5002 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5003 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
5004 ok(!lstrcmpW(_bstr_("<!ENTITY name PUBLIC \"pubid\" \"sysid\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
5005 VariantClear(&dest
);
5007 ISAXContentHandler_Release(content
);
5008 ISAXLexicalHandler_Release(lexical
);
5009 IVBSAXLexicalHandler_Release(vblexical
);
5010 IVBSAXDeclHandler_Release(vbdecl
);
5011 ISAXDeclHandler_Release(decl
);
5012 IMXWriter_Release(writer
);
5024 } addattribute_test_t
;
5026 static const addattribute_test_t addattribute_data
[] = {
5027 { &CLSID_SAXAttributes
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5028 { &CLSID_SAXAttributes30
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5029 { &CLSID_SAXAttributes40
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5030 { &CLSID_SAXAttributes60
, NULL
, NULL
, "ns:qname", NULL
, "value", S_OK
},
5032 { &CLSID_SAXAttributes
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5033 { &CLSID_SAXAttributes30
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5034 { &CLSID_SAXAttributes40
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5035 { &CLSID_SAXAttributes60
, NULL
, "qname", "ns:qname", NULL
, "value", S_OK
},
5037 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5038 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5039 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5040 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", NULL
, "value", S_OK
},
5042 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5043 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5044 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5045 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5050 static void test_mxattr_addAttribute(void)
5052 const addattribute_test_t
*table
= addattribute_data
;
5055 while (table
->clsid
)
5057 ISAXAttributes
*saxattr
;
5058 IMXAttributes
*mxattr
;
5063 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5070 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5071 &IID_IMXAttributes
, (void**)&mxattr
);
5072 EXPECT_HR(hr
, S_OK
);
5074 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5075 EXPECT_HR(hr
, S_OK
);
5077 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
5078 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5079 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5081 hr
= ISAXAttributes_getLength(saxattr
, NULL
);
5082 EXPECT_HR(hr
, E_POINTER
);
5086 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5087 EXPECT_HR(hr
, S_OK
);
5088 ok(len
== 0, "got %d\n", len
);
5090 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
5091 EXPECT_HR(hr
, E_INVALIDARG
);
5093 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
5094 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5096 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
5097 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5099 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
5100 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5102 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
5103 EXPECT_HR(hr
, E_INVALIDARG
);
5105 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
5106 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5108 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
5109 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5111 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
5112 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5114 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_(table
->uri
), _bstr_(table
->local
),
5115 _bstr_(table
->qname
), _bstr_(table
->type
), _bstr_(table
->value
));
5116 ok(hr
== table
->hr
, "%d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
5120 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
5121 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5122 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5124 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
5125 EXPECT_HR(hr
, E_POINTER
);
5127 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
5128 EXPECT_HR(hr
, E_POINTER
);
5130 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
5131 EXPECT_HR(hr
, E_POINTER
);
5133 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
5134 EXPECT_HR(hr
, E_POINTER
);
5136 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
5137 EXPECT_HR(hr
, E_POINTER
);
5139 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
5140 EXPECT_HR(hr
, E_POINTER
);
5144 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
5145 EXPECT_HR(hr
, S_OK
);
5146 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5148 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5151 value
= (void*)0xdeadbeef;
5152 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
5153 EXPECT_HR(hr
, S_OK
);
5157 ok(!lstrcmpW(_bstr_(table
->type
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5159 ok(lstrlenW(value
) == len
, "%d: got wrong type value length %d\n", i
, len
);
5163 ok(*value
== 0, "%d: got type value %s\n", i
, wine_dbgstr_w(value
));
5164 ok(len
== 0, "%d: got wrong type value length %d\n", i
, len
);
5167 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, NULL
);
5168 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5169 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5171 EXPECT_HR(hr
, E_POINTER
);
5174 EXPECT_HR(hr
, E_INVALIDARG
);
5176 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, &index
);
5177 EXPECT_HR(hr
, E_INVALIDARG
);
5180 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_("nonexistent"), 11, &index
);
5181 EXPECT_HR(hr
, E_INVALIDARG
);
5182 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5185 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), 0, &index
);
5186 EXPECT_HR(hr
, E_INVALIDARG
);
5187 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5190 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &index
);
5191 EXPECT_HR(hr
, S_OK
);
5192 ok(index
== 0, "%d: got wrong index %d\n", i
, index
);
5195 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
)-1, &index
);
5196 EXPECT_HR(hr
, E_INVALIDARG
);
5197 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5199 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes40
) ||
5200 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes60
))
5202 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
5203 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5205 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
5206 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5208 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
5209 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5211 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
5212 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5214 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
5215 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5217 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
5218 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5222 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
5223 EXPECT_HR(hr
, E_POINTER
);
5225 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
5226 EXPECT_HR(hr
, E_POINTER
);
5228 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
5229 EXPECT_HR(hr
, E_POINTER
);
5231 /* versions 4 and 6 crash */
5232 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, NULL
);
5233 EXPECT_HR(hr
, E_POINTER
);
5235 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, &len
);
5236 EXPECT_HR(hr
, E_POINTER
);
5238 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
5239 EXPECT_HR(hr
, E_POINTER
);
5241 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
5242 EXPECT_HR(hr
, E_POINTER
);
5244 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
5245 EXPECT_HR(hr
, E_POINTER
);
5247 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, &value
, NULL
);
5248 EXPECT_HR(hr
, E_POINTER
);
5250 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, NULL
, &len
);
5251 EXPECT_HR(hr
, E_POINTER
);
5253 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
), _bstr_(table
->local
),
5254 strlen(table
->local
), NULL
, NULL
);
5255 EXPECT_HR(hr
, E_POINTER
);
5258 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &value
, &len
);
5259 EXPECT_HR(hr
, S_OK
);
5260 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5262 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5265 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
),
5266 _bstr_(table
->local
), strlen(table
->local
), &value
, &len
);
5267 EXPECT_HR(hr
, S_OK
);
5268 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5270 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5275 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5276 EXPECT_HR(hr
, S_OK
);
5277 if (table
->hr
== S_OK
)
5278 ok(len
== 1, "%d: got %d length, expected 1\n", i
, len
);
5280 ok(len
== 0, "%d: got %d length, expected 0\n", i
, len
);
5282 ISAXAttributes_Release(saxattr
);
5283 IMXAttributes_Release(mxattr
);
5292 static void test_mxattr_clear(void)
5294 ISAXAttributes
*saxattr
;
5295 IMXAttributes
*mxattr
;
5300 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5301 &IID_IMXAttributes
, (void**)&mxattr
);
5302 EXPECT_HR(hr
, S_OK
);
5304 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5305 EXPECT_HR(hr
, S_OK
);
5307 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, NULL
);
5308 EXPECT_HR(hr
, E_INVALIDARG
);
5310 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5311 EXPECT_HR(hr
, E_INVALIDARG
);
5313 hr
= IMXAttributes_clear(mxattr
);
5314 EXPECT_HR(hr
, S_OK
);
5316 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("local"),
5317 _bstr_("qname"), _bstr_("type"), _bstr_("value"));
5318 EXPECT_HR(hr
, S_OK
);
5321 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5322 EXPECT_HR(hr
, S_OK
);
5323 ok(len
== 1, "got %d\n", len
);
5326 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, &len
);
5327 EXPECT_HR(hr
, E_POINTER
);
5328 ok(len
== -1, "got %d\n", len
);
5330 ptr
= (void*)0xdeadbeef;
5331 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, NULL
);
5332 EXPECT_HR(hr
, E_POINTER
);
5333 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5336 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5337 EXPECT_HR(hr
, S_OK
);
5338 ok(len
== 5, "got %d\n", len
);
5339 ok(!lstrcmpW(ptr
, _bstr_("qname")), "got %s\n", wine_dbgstr_w(ptr
));
5341 hr
= IMXAttributes_clear(mxattr
);
5342 EXPECT_HR(hr
, S_OK
);
5345 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5346 EXPECT_HR(hr
, S_OK
);
5347 ok(len
== 0, "got %d\n", len
);
5350 ptr
= (void*)0xdeadbeef;
5351 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5352 EXPECT_HR(hr
, E_INVALIDARG
);
5353 ok(len
== -1, "got %d\n", len
);
5354 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5356 IMXAttributes_Release(mxattr
);
5357 ISAXAttributes_Release(saxattr
);
5361 static void test_mxattr_dispex(void)
5363 IMXAttributes
*mxattr
;
5364 IDispatchEx
*dispex
;
5368 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5369 &IID_IMXAttributes
, (void**)&mxattr
);
5370 EXPECT_HR(hr
, S_OK
);
5372 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IDispatchEx
, (void**)&dispex
);
5373 EXPECT_HR(hr
, S_OK
);
5374 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
5375 test_obj_dispex(unk
);
5376 IUnknown_Release(unk
);
5377 IDispatchEx_Release(dispex
);
5379 IMXAttributes_Release(mxattr
);
5382 static void test_mxattr_qi(void)
5384 IVBSAXAttributes
*vbsaxattr
, *vbsaxattr2
;
5385 ISAXAttributes
*saxattr
;
5386 IMXAttributes
*mxattr
;
5389 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5390 &IID_IMXAttributes
, (void**)&mxattr
);
5391 EXPECT_HR(hr
, S_OK
);
5393 EXPECT_REF(mxattr
, 1);
5394 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5395 EXPECT_HR(hr
, S_OK
);
5397 EXPECT_REF(mxattr
, 2);
5398 EXPECT_REF(saxattr
, 2);
5400 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr
);
5401 EXPECT_HR(hr
, S_OK
);
5403 EXPECT_REF(vbsaxattr
, 3);
5404 EXPECT_REF(mxattr
, 3);
5405 EXPECT_REF(saxattr
, 3);
5407 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr2
);
5408 EXPECT_HR(hr
, S_OK
);
5410 EXPECT_REF(vbsaxattr
, 4);
5411 EXPECT_REF(mxattr
, 4);
5412 EXPECT_REF(saxattr
, 4);
5414 IMXAttributes_Release(mxattr
);
5415 ISAXAttributes_Release(saxattr
);
5416 IVBSAXAttributes_Release(vbsaxattr
);
5417 IVBSAXAttributes_Release(vbsaxattr2
);
5420 static struct msxmlsupported_data_t saxattr_support_data
[] =
5422 { &CLSID_SAXAttributes
, "SAXAttributes" },
5423 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
5424 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
5425 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
5429 static void test_mxattr_localname(void)
5431 static const WCHAR localname1W
[] = {'l','o','c','a','l','n','a','m','e','1',0};
5432 static const WCHAR localnameW
[] = {'l','o','c','a','l','n','a','m','e',0};
5433 static const WCHAR uri1W
[] = {'u','r','i','1',0};
5434 static const WCHAR uriW
[] = {'u','r','i',0};
5436 const struct msxmlsupported_data_t
*table
= saxattr_support_data
;
5438 while (table
->clsid
)
5440 ISAXAttributes
*saxattr
;
5441 IMXAttributes
*mxattr
;
5445 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5451 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5452 &IID_IMXAttributes
, (void**)&mxattr
);
5453 EXPECT_HR(hr
, S_OK
);
5455 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5456 EXPECT_HR(hr
, S_OK
);
5458 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, &index
);
5459 EXPECT_HR(hr
, E_INVALIDARG
);
5461 /* add some ambiguos attribute names */
5462 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5463 _bstr_("a:localname"), _bstr_(""), _bstr_("value"));
5464 EXPECT_HR(hr
, S_OK
);
5465 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5466 _bstr_("b:localname"), _bstr_(""), _bstr_("value"));
5467 EXPECT_HR(hr
, S_OK
);
5470 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localnameW
, lstrlenW(localnameW
), &index
);
5471 EXPECT_HR(hr
, S_OK
);
5472 ok(index
== 0, "%s: got index %d\n", table
->name
, index
);
5475 hr
= ISAXAttributes_getIndexFromName(saxattr
, uri1W
, lstrlenW(uri1W
), localnameW
, lstrlenW(localnameW
), &index
);
5476 EXPECT_HR(hr
, E_INVALIDARG
);
5477 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5480 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), &index
);
5481 EXPECT_HR(hr
, E_INVALIDARG
);
5482 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5484 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5485 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5487 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5488 EXPECT_HR(hr
, E_POINTER
);
5490 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5491 EXPECT_HR(hr
, E_POINTER
);
5495 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5496 EXPECT_HR(hr
, E_INVALIDARG
);
5498 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5499 EXPECT_HR(hr
, E_INVALIDARG
);
5502 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), NULL
, 0, &index
);
5503 EXPECT_HR(hr
, E_INVALIDARG
);
5505 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, localname1W
, lstrlenW(localname1W
), &index
);
5506 EXPECT_HR(hr
, E_INVALIDARG
);
5510 ISAXAttributes_Release(saxattr
);
5511 IMXAttributes_Release(mxattr
);
5515 static void test_mxwriter_indent(void)
5517 ISAXContentHandler
*content
;
5522 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMXWriter
, (void**)&writer
);
5523 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
5525 hr
= IMXWriter_put_indent(writer
, VARIANT_TRUE
);
5526 ok(hr
== S_OK
, "got %08x\n", hr
);
5528 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
5529 ok(hr
== S_OK
, "got %08x\n", hr
);
5531 hr
= ISAXContentHandler_startDocument(content
);
5532 ok(hr
== S_OK
, "got %08x\n", hr
);
5534 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
5535 ok(hr
== S_OK
, "got %08x\n", hr
);
5537 hr
= ISAXContentHandler_characters(content
, _bstr_(""), 0);
5538 ok(hr
== S_OK
, "got %08x\n", hr
);
5540 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("b"), -1, NULL
);
5541 ok(hr
== S_OK
, "got %08x\n", hr
);
5543 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("c"), -1, NULL
);
5544 ok(hr
== S_OK
, "got %08x\n", hr
);
5546 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("c"), -1);
5547 ok(hr
== S_OK
, "got %08x\n", hr
);
5549 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("b"), -1);
5550 ok(hr
== S_OK
, "got %08x\n", hr
);
5552 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1);
5553 ok(hr
== S_OK
, "got %08x\n", hr
);
5555 hr
= ISAXContentHandler_endDocument(content
);
5556 ok(hr
== S_OK
, "got %08x\n", hr
);
5558 V_VT(&dest
) = VT_EMPTY
;
5559 hr
= IMXWriter_get_output(writer
, &dest
);
5560 ok(hr
== S_OK
, "got %08x\n", hr
);
5561 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
5562 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
)),
5563 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
5564 VariantClear(&dest
);
5566 ISAXContentHandler_Release(content
);
5567 IMXWriter_Release(writer
);
5572 START_TEST(saxreader
)
5574 ISAXXMLReader
*reader
;
5577 hr
= CoInitialize(NULL
);
5578 ok(hr
== S_OK
, "failed to init com\n");
5580 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
5581 &IID_ISAXXMLReader
, (void**)&reader
);
5585 skip("Failed to create SAXXMLReader instance\n");
5589 ISAXXMLReader_Release(reader
);
5591 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
5593 get_class_support_data(reader_support_data
, &IID_ISAXXMLReader
);
5596 test_saxreader_properties();
5597 test_saxreader_features();
5598 test_saxreader_encoding();
5599 test_saxreader_dispex();
5601 /* MXXMLWriter tests */
5602 get_class_support_data(mxwriter_support_data
, &IID_IMXWriter
);
5603 if (is_clsid_supported(&CLSID_MXXMLWriter
, mxwriter_support_data
))
5605 test_mxwriter_handlers();
5606 test_mxwriter_startenddocument();
5607 test_mxwriter_startendelement();
5608 test_mxwriter_characters();
5609 test_mxwriter_comment();
5610 test_mxwriter_cdata();
5612 test_mxwriter_ignorablespaces();
5613 test_mxwriter_dtd();
5614 test_mxwriter_properties();
5615 test_mxwriter_flush();
5616 test_mxwriter_stream();
5617 test_mxwriter_encoding();
5618 test_mxwriter_dispex();
5619 test_mxwriter_indent();
5622 win_skip("MXXMLWriter not supported\n");
5624 /* SAXAttributes tests */
5625 get_class_support_data(mxattributes_support_data
, &IID_IMXAttributes
);
5626 if (is_clsid_supported(&CLSID_SAXAttributes
, mxattributes_support_data
))
5629 test_mxattr_addAttribute();
5630 test_mxattr_clear();
5631 test_mxattr_localname();
5632 test_mxattr_dispex();
5635 skip("SAXAttributes not supported\n");