2 * SAXReader/MXWriter tests
4 * Copyright 2008 Piotr Caban
5 * Copyright 2011 Thomas Mullaly
6 * Copyright 2012 Nikolay Sivov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define WIN32_NO_STATUS
25 #define COM_NO_WINDOWS_H
33 #include <wine/test.h>
34 //#include "windows.h"
38 #include <msxml2did.h>
42 static const WCHAR emptyW
[] = {0};
44 #define EXPECT_HR(hr,hr_exp) \
45 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
47 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
48 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
50 ULONG rc
= IUnknown_AddRef(obj
);
51 IUnknown_Release(obj
);
52 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
55 static LONG
get_refcount(void *iface
)
57 IUnknown
*unk
= iface
;
60 ref
= IUnknown_AddRef(unk
);
61 IUnknown_Release(unk
);
65 struct msxmlsupported_data_t
72 static BOOL
is_clsid_supported(const GUID
*clsid
, const struct msxmlsupported_data_t
*table
)
76 if (table
->clsid
== clsid
) return table
->supported
;
82 static BSTR
alloc_str_from_narrow(const char *str
)
84 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
85 BSTR ret
= SysAllocStringLen(NULL
, len
- 1); /* NUL character added automatically */
86 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
90 static BSTR alloced_bstrs
[512];
91 static int alloced_bstrs_count
;
93 static BSTR
_bstr_(const char *str
)
95 assert(alloced_bstrs_count
< sizeof(alloced_bstrs
)/sizeof(alloced_bstrs
[0]));
96 alloced_bstrs
[alloced_bstrs_count
] = alloc_str_from_narrow(str
);
97 return alloced_bstrs
[alloced_bstrs_count
++];
100 static void free_bstrs(void)
103 for (i
= 0; i
< alloced_bstrs_count
; i
++)
104 SysFreeString(alloced_bstrs
[i
]);
105 alloced_bstrs_count
= 0;
108 static void test_saxstr(const char *file
, unsigned line
, BSTR str
, const char *expected
, BOOL todo
, int *failcount
)
110 int len
, lenexp
, cmp
;
113 len
= SysStringLen(str
);
120 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
123 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
129 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
132 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
136 lenexp
= strlen(expected
);
137 if (lenexp
!= len
&& todo
)
141 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
144 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
146 /* exit earlier on length mismatch */
147 if (lenexp
!= len
) return;
149 MultiByteToWideChar(CP_ACP
, 0, expected
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
151 cmp
= memcmp(str
, buf
, lenexp
*sizeof(WCHAR
));
156 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
157 wine_dbgstr_wn(str
, len
), expected
);
160 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
161 wine_dbgstr_wn(str
, len
), expected
);
166 CH_PUTDOCUMENTLOCATOR
,
169 CH_STARTPREFIXMAPPING
,
174 CH_IGNORABLEWHITESPACE
,
175 CH_PROCESSINGINSTRUCTION
,
185 static const char *event_names
[EVENT_LAST
] = {
187 "putDocumentLocator",
190 "startPrefixMapping",
195 "ignorableWhitespace",
196 "processingInstruction",
205 struct attribute_entry
{
211 /* used for actual call data only, null for expected call data */
227 /* allocated once at startElement callback */
228 struct attribute_entry
*attributes
;
231 /* used for actual call data only, null for expected call data */
241 struct call_entry
*sequence
;
244 #define CONTENT_HANDLER_INDEX 0
245 #define NUM_CALL_SEQUENCES 1
246 static struct call_sequence
*sequences
[NUM_CALL_SEQUENCES
];
248 static void init_call_entry(ISAXLocator
*locator
, struct call_entry
*call
)
250 memset(call
, 0, sizeof(*call
));
251 ISAXLocator_getLineNumber(locator
, &call
->line
);
252 ISAXLocator_getColumnNumber(locator
, &call
->column
);
255 static void add_call(struct call_sequence
**seq
, int sequence_index
,
256 const struct call_entry
*call
)
258 struct call_sequence
*call_seq
= seq
[sequence_index
];
260 if (!call_seq
->sequence
)
263 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0,
264 call_seq
->size
* sizeof (struct call_entry
));
267 if (call_seq
->count
== call_seq
->size
)
270 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
272 call_seq
->size
* sizeof (struct call_entry
));
275 assert(call_seq
->sequence
);
277 call_seq
->sequence
[call_seq
->count
].id
= call
->id
;
278 call_seq
->sequence
[call_seq
->count
].line
= call
->line
;
279 call_seq
->sequence
[call_seq
->count
].column
= call
->column
;
280 call_seq
->sequence
[call_seq
->count
].arg1W
= call
->arg1W
;
281 call_seq
->sequence
[call_seq
->count
].arg2W
= call
->arg2W
;
282 call_seq
->sequence
[call_seq
->count
].arg3W
= call
->arg3W
;
283 call_seq
->sequence
[call_seq
->count
].ret
= call
->ret
;
284 call_seq
->sequence
[call_seq
->count
].attr_count
= call
->attr_count
;
285 call_seq
->sequence
[call_seq
->count
].attributes
= call
->attributes
;
290 static inline void flush_sequence(struct call_sequence
**seg
, int sequence_index
)
294 struct call_sequence
*call_seq
= seg
[sequence_index
];
296 for (i
= 0; i
< call_seq
->count
; i
++)
300 for (j
= 0; j
< call_seq
->sequence
[i
].attr_count
; j
++)
302 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].uriW
);
303 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].localW
);
304 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].qnameW
);
307 SysFreeString(call_seq
->sequence
[i
].arg1W
);
308 SysFreeString(call_seq
->sequence
[i
].arg2W
);
309 SysFreeString(call_seq
->sequence
[i
].arg3W
);
312 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
313 call_seq
->sequence
= NULL
;
314 call_seq
->count
= call_seq
->size
= 0;
317 static inline void flush_sequences(struct call_sequence
**seq
, int n
)
320 for (i
= 0; i
< n
; i
++)
321 flush_sequence(seq
, i
);
324 static const char *get_event_name(CH event
)
326 return event_names
[event
];
329 static void compare_attributes(const struct call_entry
*actual
, const struct call_entry
*expected
, const char *context
,
330 BOOL todo
, const char *file
, int line
, int *failcount
)
334 /* attribute count is not stored for expected data */
335 if (expected
->attributes
)
337 struct attribute_entry
*ptr
= expected
->attributes
;
338 while (ptr
->uri
) { lenexp
++; ptr
++; };
341 /* check count first and exit earlier */
342 if (actual
->attr_count
!= lenexp
&& todo
)
346 ok_(file
, line
) (FALSE
, "%s: in event %s expecting attr count %d got %d\n",
347 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
350 ok_(file
, line
) (actual
->attr_count
== lenexp
, "%s: in event %s expecting attr count %d got %d\n",
351 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
353 if (actual
->attr_count
!= lenexp
) return;
355 /* now compare all attributes strings */
356 for (i
= 0; i
< actual
->attr_count
; i
++)
358 test_saxstr(file
, line
, actual
->attributes
[i
].uriW
, expected
->attributes
[i
].uri
, todo
, failcount
);
359 test_saxstr(file
, line
, actual
->attributes
[i
].localW
, expected
->attributes
[i
].local
, todo
, failcount
);
360 test_saxstr(file
, line
, actual
->attributes
[i
].qnameW
, expected
->attributes
[i
].qname
, todo
, failcount
);
361 test_saxstr(file
, line
, actual
->attributes
[i
].valueW
, expected
->attributes
[i
].value
, todo
, failcount
);
365 static void ok_sequence_(struct call_sequence
**seq
, int sequence_index
,
366 const struct call_entry
*expected
, const char *context
, BOOL todo
,
367 const char *file
, int line
)
369 struct call_sequence
*call_seq
= seq
[sequence_index
];
370 static const struct call_entry end_of_sequence
= { CH_ENDTEST
};
371 const struct call_entry
*actual
, *sequence
;
374 add_call(seq
, sequence_index
, &end_of_sequence
);
376 sequence
= call_seq
->sequence
;
379 while (expected
->id
!= CH_ENDTEST
&& actual
->id
!= CH_ENDTEST
)
381 if (expected
->id
== actual
->id
)
383 if (expected
->line
!= -1)
385 /* always test position data */
386 if (expected
->line
!= actual
->line
&& todo
)
391 ok_(file
, line
) (FALSE
,
392 "%s: in event %s expecting line %d got %d\n",
393 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
398 ok_(file
, line
) (expected
->line
== actual
->line
,
399 "%s: in event %s expecting line %d got %d\n",
400 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
405 if (expected
->column
!= -1)
407 if (expected
->column
!= actual
->column
&& todo
)
412 ok_(file
, line
) (FALSE
,
413 "%s: in event %s expecting column %d got %d\n",
414 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
419 ok_(file
, line
) (expected
->column
== actual
->column
,
420 "%s: in event %s expecting column %d got %d\n",
421 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
427 case CH_PUTDOCUMENTLOCATOR
:
428 case CH_STARTDOCUMENT
:
433 case CH_STARTPREFIXMAPPING
:
435 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
436 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
438 case CH_ENDPREFIXMAPPING
:
440 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
442 case CH_STARTELEMENT
:
443 /* compare attributes */
444 compare_attributes(actual
, expected
, context
, todo
, file
, line
, &failcount
);
447 /* uri, localname, qname */
448 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
449 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
450 test_saxstr(file
, line
, actual
->arg3W
, expected
->arg3
, todo
, &failcount
);
453 case CH_IGNORABLEWHITESPACE
:
455 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
457 case CH_PROCESSINGINSTRUCTION
:
459 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
460 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
462 case CH_SKIPPEDENTITY
:
464 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
467 /* test return value only */
468 if (expected
->ret
!= actual
->ret
&& todo
)
471 ok_(file
, line
) (FALSE
,
472 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
473 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
476 ok_(file
, line
) (expected
->ret
== actual
->ret
,
477 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
478 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
481 case EH_IGNORABLEWARNING
:
483 ok(0, "%s: callback not handled, %s\n", context
, get_event_name(actual
->id
));
493 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
494 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
497 flush_sequence(seq
, sequence_index
);
502 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
503 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
513 if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
516 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
517 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
521 else if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
523 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
524 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
527 if (todo
&& !failcount
) /* succeeded yet marked todo */
531 ok_(file
, line
)(TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
535 flush_sequence(seq
, sequence_index
);
538 #define ok_sequence(seq, index, exp, contx, todo) \
539 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
541 static void init_call_sequences(struct call_sequence
**seq
, int n
)
545 for (i
= 0; i
< n
; i
++)
546 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct call_sequence
));
549 static const WCHAR szSimpleXML
[] = {
550 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
551 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
552 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
553 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
554 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
557 static const WCHAR carriage_ret_test
[] = {
558 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
559 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
560 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
561 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
562 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
565 static const WCHAR szUtf16XML
[] = {
566 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
567 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
568 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
571 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
573 static const CHAR szUtf8XML
[] =
574 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
576 static const char utf8xml2
[] =
577 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n";
579 static const char testXML
[] =
580 "<?xml version=\"1.0\" ?>\n"
582 " <Number>1234</Number>\n"
583 " <Name>Captain Ahab</Name>\n"
586 static const char test_attributes
[] =
587 "<?xml version=\"1.0\" ?>\n"
588 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
589 "<node1 xmlns:p=\"test\" />"
592 static const char test_cdata_xml
[] =
593 "<?xml version=\"1.0\" ?>"
594 "<a><![CDATA[Some \r\ntext\n\r\ndata\n\n]]></a>";
596 static const char test2_cdata_xml
[] =
597 "<?xml version=\"1.0\" ?>"
598 "<a><![CDATA[\n\r\nSome \r\ntext\n\r\ndata\n\n]]></a>";
600 static const char test3_cdata_xml
[] =
601 "<?xml version=\"1.0\" ?><a><![CDATA[Some text data]]></a>";
603 static struct call_entry content_handler_test1
[] = {
604 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
605 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
606 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
607 { CH_CHARACTERS
, 2, 14, S_OK
, "\n " },
608 { CH_STARTELEMENT
, 3, 12, S_OK
, "", "Number", "Number" },
609 { CH_CHARACTERS
, 3, 12, S_OK
, "1234" },
610 { CH_ENDELEMENT
, 3, 18, S_OK
, "", "Number", "Number" },
611 { CH_CHARACTERS
, 3, 25, S_OK
, "\n " },
612 { CH_STARTELEMENT
, 4, 10, S_OK
, "", "Name", "Name" },
613 { CH_CHARACTERS
, 4, 10, S_OK
, "Captain Ahab" },
614 { CH_ENDELEMENT
, 4, 24, S_OK
, "", "Name", "Name" },
615 { CH_CHARACTERS
, 4, 29, S_OK
, "\n" },
616 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
617 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
621 /* applies to versions 4 and 6 */
622 static struct call_entry content_handler_test1_alternate
[] = {
623 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
624 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
625 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
626 { CH_CHARACTERS
, 3, 4, S_OK
, "\n " },
627 { CH_STARTELEMENT
, 3, 11, S_OK
, "", "Number", "Number" },
628 { CH_CHARACTERS
, 3, 16, S_OK
, "1234" },
629 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "Number", "Number" },
630 { CH_CHARACTERS
, 4, 4, S_OK
, "\n " },
631 { CH_STARTELEMENT
, 4, 9, S_OK
, "", "Name", "Name" },
632 { CH_CHARACTERS
, 4, 22, S_OK
, "Captain Ahab" },
633 { CH_ENDELEMENT
, 4, 28, S_OK
, "", "Name", "Name" },
634 { CH_CHARACTERS
, 5, 1, S_OK
, "\n" },
635 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
636 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
640 static struct call_entry content_handler_test2
[] = {
641 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
642 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
643 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
644 { CH_CHARACTERS
, 2, 14, S_OK
, "\n" },
645 { CH_CHARACTERS
, 2, 16, S_OK
, "\t" },
646 { CH_STARTELEMENT
, 3, 10, S_OK
, "", "Number", "Number" },
647 { CH_CHARACTERS
, 3, 10, S_OK
, "1234" },
648 { CH_ENDELEMENT
, 3, 16, S_OK
, "", "Number", "Number" },
649 { CH_CHARACTERS
, 3, 23, S_OK
, "\n" },
650 { CH_CHARACTERS
, 3, 25, S_OK
, "\t" },
651 { CH_STARTELEMENT
, 4, 8, S_OK
, "", "Name", "Name" },
652 { CH_CHARACTERS
, 4, 8, S_OK
, "Captain Ahab" },
653 { CH_ENDELEMENT
, 4, 22, S_OK
, "", "Name", "Name" },
654 { CH_CHARACTERS
, 4, 27, S_OK
, "\n" },
655 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
656 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
660 static struct call_entry content_handler_test2_alternate
[] = {
661 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
662 { CH_STARTDOCUMENT
, 1, 21, S_OK
},
663 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
664 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
665 { CH_CHARACTERS
, 3, 2, S_OK
, "\t" },
666 { CH_STARTELEMENT
, 3, 9, S_OK
, "", "Number", "Number" },
667 { CH_CHARACTERS
, 3, 14, S_OK
, "1234" },
668 { CH_ENDELEMENT
, 3, 22, S_OK
, "", "Number", "Number" },
669 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
670 { CH_CHARACTERS
, 4, 2, S_OK
, "\t" },
671 { CH_STARTELEMENT
, 4, 7, S_OK
, "", "Name", "Name" },
672 { CH_CHARACTERS
, 4, 20, S_OK
, "Captain Ahab" },
673 { CH_ENDELEMENT
, 4, 26, S_OK
, "", "Name", "Name" },
674 { CH_CHARACTERS
, 5, 0, S_OK
, "\n" },
675 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
676 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
680 static struct call_entry content_handler_testerror
[] = {
681 { CH_PUTDOCUMENTLOCATOR
, 0, 0, E_FAIL
},
682 { EH_FATALERROR
, 0, 0, E_FAIL
},
686 static struct call_entry content_handler_testerror_alternate
[] = {
687 { CH_PUTDOCUMENTLOCATOR
, 1, 0, E_FAIL
},
688 { EH_FATALERROR
, 1, 0, E_FAIL
},
692 static struct call_entry content_handler_test_callback_rets
[] = {
693 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_FALSE
},
694 { CH_STARTDOCUMENT
, 0, 0, S_FALSE
},
695 { EH_FATALERROR
, 0, 0, S_FALSE
},
699 static struct call_entry content_handler_test_callback_rets_alt
[] = {
700 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_FALSE
},
701 { CH_STARTDOCUMENT
, 1, 22, S_FALSE
},
702 { CH_STARTELEMENT
, 2, 13, S_FALSE
, "", "BankAccount", "BankAccount" },
703 { CH_CHARACTERS
, 3, 4, S_FALSE
, "\n " },
704 { CH_STARTELEMENT
, 3, 11, S_FALSE
, "", "Number", "Number" },
705 { CH_CHARACTERS
, 3, 16, S_FALSE
, "1234" },
706 { CH_ENDELEMENT
, 3, 24, S_FALSE
, "", "Number", "Number" },
707 { CH_CHARACTERS
, 4, 4, S_FALSE
, "\n " },
708 { CH_STARTELEMENT
, 4, 9, S_FALSE
, "", "Name", "Name" },
709 { CH_CHARACTERS
, 4, 22, S_FALSE
, "Captain Ahab" },
710 { CH_ENDELEMENT
, 4, 28, S_FALSE
, "", "Name", "Name" },
711 { CH_CHARACTERS
, 5, 1, S_FALSE
, "\n" },
712 { CH_ENDELEMENT
, 5, 14, S_FALSE
, "", "BankAccount", "BankAccount" },
713 { CH_ENDDOCUMENT
, 6, 0, S_FALSE
},
717 static struct attribute_entry ch_attributes1
[] = {
718 { "", "", "xmlns:test", "prefix_test" },
719 { "", "", "xmlns", "prefix" },
720 { "prefix_test", "arg1", "test:arg1", "arg1" },
721 { "", "arg2", "arg2", "arg2" },
722 { "prefix_test", "ar3", "test:ar3", "arg3" },
726 static struct attribute_entry ch_attributes2
[] = {
727 { "", "", "xmlns:p", "test" },
731 static struct call_entry content_handler_test_attributes
[] = {
732 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
733 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
734 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
735 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
736 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes1
},
737 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
738 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
739 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
740 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
741 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
742 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
743 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
744 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
745 { CH_ENDDOCUMENT
, 0, 0 },
749 static struct attribute_entry ch_attributes_alt_4
[] = {
750 { "prefix_test", "arg1", "test:arg1", "arg1" },
751 { "", "arg2", "arg2", "arg2" },
752 { "prefix_test", "ar3", "test:ar3", "arg3" },
753 { "", "", "xmlns:test", "prefix_test" },
754 { "", "", "xmlns", "prefix" },
758 static struct call_entry content_handler_test_attributes_alternate_4
[] = {
759 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
760 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
761 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
762 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
763 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_4
},
764 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
765 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
766 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
767 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
768 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
769 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
770 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
771 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
772 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
776 /* 'namespace' feature switched off */
777 static struct attribute_entry ch_attributes_alt_no_ns
[] = {
778 { "", "", "xmlns:test", "prefix_test" },
779 { "", "", "xmlns", "prefix" },
780 { "", "", "test:arg1", "arg1" },
781 { "", "", "arg2", "arg2" },
782 { "", "", "test:ar3", "arg3" },
786 static struct call_entry content_handler_test_attributes_alt_no_ns
[] = {
787 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
788 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
789 { CH_STARTELEMENT
, 2, 95, S_OK
, "", "", "document", ch_attributes_alt_no_ns
},
790 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
791 { CH_STARTELEMENT
, 3, 24, S_OK
, "", "", "node1", ch_attributes2
},
792 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "", "node1" },
793 { CH_ENDELEMENT
, 3, 35, S_OK
, "", "", "document" },
794 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
798 static struct attribute_entry ch_attributes_alt_6
[] = {
799 { "prefix_test", "arg1", "test:arg1", "arg1" },
800 { "", "arg2", "arg2", "arg2" },
801 { "prefix_test", "ar3", "test:ar3", "arg3" },
802 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
803 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
807 static struct attribute_entry ch_attributes2_6
[] = {
808 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
812 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
813 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
814 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
815 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
816 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
817 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
818 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
819 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
820 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
821 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
822 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
823 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
824 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
825 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
826 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
830 /* 'namespaces' is on, 'namespace-prefixes' if off */
831 static struct attribute_entry ch_attributes_no_prefix
[] = {
832 { "prefix_test", "arg1", "test:arg1", "arg1" },
833 { "", "arg2", "arg2", "arg2" },
834 { "prefix_test", "ar3", "test:ar3", "arg3" },
838 static struct call_entry content_handler_test_attributes_alt_no_prefix
[] = {
839 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
840 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
841 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
842 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
843 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
844 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
845 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
846 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", NULL
},
847 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
848 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
849 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
850 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
851 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
852 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
856 static struct call_entry content_handler_test_attributes_no_prefix
[] = {
857 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
858 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
859 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
860 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
861 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
862 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
863 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
864 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", NULL
},
865 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
866 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
867 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
868 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
869 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
870 { CH_ENDDOCUMENT
, 0, 0 },
874 static struct attribute_entry xmlspace_attrs
[] = {
875 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
879 static struct call_entry xmlspaceattr_test
[] = {
880 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
881 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
882 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
883 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
884 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
885 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
889 static struct call_entry xmlspaceattr_test_alternate
[] = {
890 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
891 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
892 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
893 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
894 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
895 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
899 /* attribute value normalization test */
900 static const char attribute_normalize
[] =
901 "<?xml version=\"1.0\" ?>\n"
902 "<a attr1=\" \r \n \tattr_value A & &\t \r \n\r\n \n\"/>\n";
904 static struct attribute_entry attribute_norm_attrs
[] = {
905 { "", "attr1", "attr1", " attr_value A & & " },
909 static struct call_entry attribute_norm
[] = {
910 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
911 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
912 { CH_STARTELEMENT
, 6, 4, S_OK
, "", "a", "a", attribute_norm_attrs
},
913 { CH_ENDELEMENT
, 6, 4, S_OK
, "", "a", "a" },
914 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
918 static struct call_entry attribute_norm_alt
[] = {
919 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
920 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
921 { CH_STARTELEMENT
, 8, 3, S_OK
, "", "a", "a", attribute_norm_attrs
},
922 { CH_ENDELEMENT
, 8, 3, S_OK
, "", "a", "a" },
923 { CH_ENDDOCUMENT
, 9, 0, S_OK
},
927 static struct call_entry cdata_test
[] = {
928 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
929 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
930 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
931 { LH_STARTCDATA
, 1, 35, S_OK
},
932 { CH_CHARACTERS
, 1, 35, S_OK
, "Some \n" },
933 { CH_CHARACTERS
, 1, 42, S_OK
, "text\n\n" },
934 { CH_CHARACTERS
, 1, 49, S_OK
, "data\n\n" },
935 { LH_ENDCDATA
, 1, 49, S_OK
},
936 { CH_ENDELEMENT
, 6, 6, S_OK
, "", "a", "a" },
937 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
941 static struct call_entry cdata_test2
[] = {
942 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
943 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
944 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
945 { LH_STARTCDATA
, 1, 35, S_OK
},
946 { CH_CHARACTERS
, 1, 35, S_OK
, "\n\n" },
947 { CH_CHARACTERS
, 1, 38, S_OK
, "Some \n" },
948 { CH_CHARACTERS
, 1, 45, S_OK
, "text\n\n" },
949 { CH_CHARACTERS
, 1, 52, S_OK
, "data\n\n" },
950 { LH_ENDCDATA
, 1, 52, S_OK
},
951 { CH_ENDELEMENT
, 8, 6, S_OK
, "", "a", "a" },
952 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
956 static struct call_entry cdata_test3
[] = {
957 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
958 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
959 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
960 { LH_STARTCDATA
, 1, 35, S_OK
},
961 { CH_CHARACTERS
, 1, 35, S_OK
, "Some text data" },
962 { LH_ENDCDATA
, 1, 35, S_OK
},
963 { CH_ENDELEMENT
, 1, 54, S_OK
, "", "a", "a" },
964 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
968 /* this is what MSXML6 does */
969 static struct call_entry cdata_test_alt
[] = {
970 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
971 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
972 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
973 { LH_STARTCDATA
, 1, 34, S_OK
},
974 { CH_CHARACTERS
, 1, 40, S_OK
, "Some " },
975 { CH_CHARACTERS
, 2, 0, S_OK
, "\n" },
976 { CH_CHARACTERS
, 3, 1, S_OK
, "text\n" },
977 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
978 { CH_CHARACTERS
, 6, 3, S_OK
, "data\n\n" },
979 { LH_ENDCDATA
, 6, 3, S_OK
},
980 { CH_ENDELEMENT
, 6, 7, S_OK
, "", "a", "a" },
981 { CH_ENDDOCUMENT
, 6, 7, S_OK
},
985 static struct call_entry cdata_test2_alt
[] = {
986 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
987 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
988 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
989 { LH_STARTCDATA
, 1, 34, S_OK
},
990 { CH_CHARACTERS
, 2, 1, S_OK
, "\n" },
991 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
992 { CH_CHARACTERS
, 3, 6, S_OK
, "Some " },
993 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
994 { CH_CHARACTERS
, 5, 1, S_OK
, "text\n" },
995 { CH_CHARACTERS
, 6, 0, S_OK
, "\n" },
996 { CH_CHARACTERS
, 8, 3, S_OK
, "data\n\n" },
997 { LH_ENDCDATA
, 8, 3, S_OK
},
998 { CH_ENDELEMENT
, 8, 7, S_OK
, "", "a", "a" },
999 { CH_ENDDOCUMENT
, 8, 7, S_OK
},
1003 static struct call_entry cdata_test3_alt
[] = {
1004 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
1005 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
1006 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
1007 { LH_STARTCDATA
, 1, 34, S_OK
},
1008 { CH_CHARACTERS
, 1, 51, S_OK
, "Some text data" },
1009 { LH_ENDCDATA
, 1, 51, S_OK
},
1010 { CH_ENDELEMENT
, 1, 55, S_OK
, "", "a", "a" },
1011 { CH_ENDDOCUMENT
, 1, 55, S_OK
},
1015 static struct attribute_entry read_test_attrs
[] = {
1016 { "", "attr", "attr", "val" },
1020 static struct call_entry read_test_seq
[] = {
1021 { CH_PUTDOCUMENTLOCATOR
, -1, 0, S_OK
},
1022 { CH_STARTDOCUMENT
, -1, -1, S_OK
},
1023 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1024 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1025 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1026 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1027 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1028 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1029 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1030 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1031 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1032 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1033 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1034 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1035 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1036 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1037 { CH_ENDDOCUMENT
, -1, -1, S_OK
},
1041 static const char xmlspace_attr
[] =
1042 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
1043 "<a xml:space=\"preserve\"> Some text data </a>";
1045 static struct call_entry
*expectCall
;
1046 static ISAXLocator
*locator
;
1047 static ISAXXMLReader
*g_reader
;
1050 static void set_expected_seq(struct call_entry
*expected
)
1052 expectCall
= expected
;
1055 /* to be called once on each tested callback return */
1056 static HRESULT
get_expected_ret(void)
1058 HRESULT hr
= expectCall
->ret
;
1059 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
1063 static HRESULT WINAPI
contentHandler_QueryInterface(
1064 ISAXContentHandler
* iface
,
1070 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
1076 return E_NOINTERFACE
;
1082 static ULONG WINAPI
contentHandler_AddRef(
1083 ISAXContentHandler
* iface
)
1088 static ULONG WINAPI
contentHandler_Release(
1089 ISAXContentHandler
* iface
)
1094 static HRESULT WINAPI
contentHandler_putDocumentLocator(
1095 ISAXContentHandler
* iface
,
1096 ISAXLocator
*pLocator
)
1098 struct call_entry call
;
1104 init_call_entry(locator
, &call
);
1105 call
.id
= CH_PUTDOCUMENTLOCATOR
;
1106 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1108 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXLocator
, (void**)&unk
);
1109 EXPECT_HR(hr
, E_NOINTERFACE
);
1111 if (msxml_version
>= 6) {
1112 ISAXAttributes
*attr
, *attr1
;
1113 IMXAttributes
*mxattr
;
1115 EXPECT_REF(pLocator
, 1);
1116 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
1117 EXPECT_HR(hr
, S_OK
);
1118 EXPECT_REF(pLocator
, 2);
1119 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
1120 EXPECT_HR(hr
, S_OK
);
1121 EXPECT_REF(pLocator
, 3);
1122 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
1124 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IVBSAXAttributes
, (void**)&unk
);
1125 EXPECT_HR(hr
, E_NOINTERFACE
);
1127 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXAttributes
, (void**)&unk
);
1128 EXPECT_HR(hr
, E_NOINTERFACE
);
1130 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
1131 EXPECT_HR(hr
, E_NOINTERFACE
);
1133 ISAXAttributes_Release(attr
);
1134 ISAXAttributes_Release(attr1
);
1137 return get_expected_ret();
1140 static ISAXAttributes
*test_attr_ptr
;
1141 static HRESULT WINAPI
contentHandler_startDocument(
1142 ISAXContentHandler
* iface
)
1144 struct call_entry call
;
1146 init_call_entry(locator
, &call
);
1147 call
.id
= CH_STARTDOCUMENT
;
1148 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1150 test_attr_ptr
= NULL
;
1152 return get_expected_ret();
1155 static HRESULT WINAPI
contentHandler_endDocument(
1156 ISAXContentHandler
* iface
)
1158 struct call_entry call
;
1160 init_call_entry(locator
, &call
);
1161 call
.id
= CH_ENDDOCUMENT
;
1162 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1164 return get_expected_ret();
1167 static HRESULT WINAPI
contentHandler_startPrefixMapping(
1168 ISAXContentHandler
* iface
,
1169 const WCHAR
*prefix
, int prefix_len
,
1170 const WCHAR
*uri
, int uri_len
)
1172 struct call_entry call
;
1174 init_call_entry(locator
, &call
);
1175 call
.id
= CH_STARTPREFIXMAPPING
;
1176 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
1177 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
1178 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1180 return get_expected_ret();
1183 static HRESULT WINAPI
contentHandler_endPrefixMapping(
1184 ISAXContentHandler
* iface
,
1185 const WCHAR
*prefix
, int len
)
1187 struct call_entry call
;
1189 init_call_entry(locator
, &call
);
1190 call
.id
= CH_ENDPREFIXMAPPING
;
1191 call
.arg1W
= SysAllocStringLen(prefix
, len
);
1192 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1194 return get_expected_ret();
1197 static HRESULT WINAPI
contentHandler_startElement(
1198 ISAXContentHandler
* iface
,
1199 const WCHAR
*uri
, int uri_len
,
1200 const WCHAR
*localname
, int local_len
,
1201 const WCHAR
*qname
, int qname_len
,
1202 ISAXAttributes
*saxattr
)
1204 struct call_entry call
;
1205 IMXAttributes
*mxattr
;
1209 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
1210 EXPECT_HR(hr
, E_NOINTERFACE
);
1212 init_call_entry(locator
, &call
);
1213 call
.id
= CH_STARTELEMENT
;
1214 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1215 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1216 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1219 test_attr_ptr
= saxattr
;
1220 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
1222 /* store actual attributes */
1224 hr
= ISAXAttributes_getLength(saxattr
, &len
);
1225 EXPECT_HR(hr
, S_OK
);
1232 struct attribute_entry
*attr
;
1233 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
1236 hr
= ISAXXMLReader_getFeature(g_reader
, _bstr_("http://xml.org/sax/features/namespaces"), &v
);
1237 EXPECT_HR(hr
, S_OK
);
1239 for (i
= 0; i
< len
; i
++)
1244 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
1245 &localname
, &local_len
, &qname
, &qname_len
);
1246 EXPECT_HR(hr
, S_OK
);
1248 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
1249 EXPECT_HR(hr
, S_OK
);
1251 /* if 'namespaces' switched off uri and local name contains garbage */
1252 if (v
== VARIANT_FALSE
&& msxml_version
> 0)
1254 attr
[i
].uriW
= SysAllocStringLen(NULL
, 0);
1255 attr
[i
].localW
= SysAllocStringLen(NULL
, 0);
1259 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
1260 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
1263 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
1264 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
1267 call
.attributes
= attr
;
1268 call
.attr_count
= len
;
1271 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1273 return get_expected_ret();
1276 static HRESULT WINAPI
contentHandler_endElement(
1277 ISAXContentHandler
* iface
,
1278 const WCHAR
*uri
, int uri_len
,
1279 const WCHAR
*localname
, int local_len
,
1280 const WCHAR
*qname
, int qname_len
)
1282 struct call_entry call
;
1284 init_call_entry(locator
, &call
);
1285 call
.id
= CH_ENDELEMENT
;
1286 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1287 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1288 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1289 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1291 return get_expected_ret();
1294 static HRESULT WINAPI
contentHandler_characters(
1295 ISAXContentHandler
* iface
,
1299 struct call_entry call
;
1301 init_call_entry(locator
, &call
);
1302 call
.id
= CH_CHARACTERS
;
1303 call
.arg1W
= SysAllocStringLen(chars
, len
);
1304 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1306 return get_expected_ret();
1309 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1310 ISAXContentHandler
* iface
,
1311 const WCHAR
*chars
, int len
)
1313 struct call_entry call
;
1315 init_call_entry(locator
, &call
);
1316 call
.id
= CH_IGNORABLEWHITESPACE
;
1317 call
.arg1W
= SysAllocStringLen(chars
, len
);
1318 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1320 return get_expected_ret();
1323 static HRESULT WINAPI
contentHandler_processingInstruction(
1324 ISAXContentHandler
* iface
,
1325 const WCHAR
*target
, int target_len
,
1326 const WCHAR
*data
, int data_len
)
1328 struct call_entry call
;
1330 init_call_entry(locator
, &call
);
1331 call
.id
= CH_PROCESSINGINSTRUCTION
;
1332 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1333 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1334 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1336 return get_expected_ret();
1339 static HRESULT WINAPI
contentHandler_skippedEntity(
1340 ISAXContentHandler
* iface
,
1341 const WCHAR
*name
, int len
)
1343 struct call_entry call
;
1345 init_call_entry(locator
, &call
);
1346 call
.id
= CH_SKIPPEDENTITY
;
1347 call
.arg1W
= SysAllocStringLen(name
, len
);
1348 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1350 return get_expected_ret();
1353 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1355 contentHandler_QueryInterface
,
1356 contentHandler_AddRef
,
1357 contentHandler_Release
,
1358 contentHandler_putDocumentLocator
,
1359 contentHandler_startDocument
,
1360 contentHandler_endDocument
,
1361 contentHandler_startPrefixMapping
,
1362 contentHandler_endPrefixMapping
,
1363 contentHandler_startElement
,
1364 contentHandler_endElement
,
1365 contentHandler_characters
,
1366 contentHandler_ignorableWhitespace
,
1367 contentHandler_processingInstruction
,
1368 contentHandler_skippedEntity
1371 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1373 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1374 ISAXErrorHandler
* iface
,
1380 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1386 return E_NOINTERFACE
;
1392 static ULONG WINAPI
isaxerrorHandler_AddRef(
1393 ISAXErrorHandler
* iface
)
1398 static ULONG WINAPI
isaxerrorHandler_Release(
1399 ISAXErrorHandler
* iface
)
1404 static HRESULT WINAPI
isaxerrorHandler_error(
1405 ISAXErrorHandler
* iface
,
1406 ISAXLocator
*pLocator
,
1407 const WCHAR
*pErrorMessage
,
1408 HRESULT hrErrorCode
)
1410 ok(0, "unexpected call\n");
1414 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1415 ISAXErrorHandler
* iface
,
1416 ISAXLocator
*pLocator
,
1417 const WCHAR
*message
,
1420 struct call_entry call
;
1422 init_call_entry(locator
, &call
);
1423 call
.id
= EH_FATALERROR
;
1426 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1432 static HRESULT WINAPI
isaxerrorHandler_ignorableWarning(
1433 ISAXErrorHandler
* iface
,
1434 ISAXLocator
*pLocator
,
1435 const WCHAR
*pErrorMessage
,
1436 HRESULT hrErrorCode
)
1438 ok(0, "unexpected call\n");
1442 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1444 isaxerrorHandler_QueryInterface
,
1445 isaxerrorHandler_AddRef
,
1446 isaxerrorHandler_Release
,
1447 isaxerrorHandler_error
,
1448 isaxerrorHandler_fatalError
,
1449 isaxerrorHandler_ignorableWarning
1452 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1454 static HRESULT WINAPI
isaxattributes_QueryInterface(
1455 ISAXAttributes
* iface
,
1461 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1467 return E_NOINTERFACE
;
1473 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1478 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1483 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1489 static HRESULT WINAPI
isaxattributes_getURI(
1490 ISAXAttributes
* iface
,
1495 ok(0, "unexpected call\n");
1499 static HRESULT WINAPI
isaxattributes_getLocalName(
1500 ISAXAttributes
* iface
,
1502 const WCHAR
**pLocalName
,
1503 int *pLocalNameLength
)
1505 ok(0, "unexpected call\n");
1509 static HRESULT WINAPI
isaxattributes_getQName(
1510 ISAXAttributes
* iface
,
1512 const WCHAR
**QName
,
1515 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1516 {'a','t','t','r','2','j','u','n','k',0},
1517 {'a','t','t','r','3',0}};
1518 static const int attrqnamelen
[] = {7, 5, 5};
1520 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1522 if (index
>= 0 && index
<= 2) {
1523 *QName
= attrqnamesW
[index
];
1524 *QNameLength
= attrqnamelen
[index
];
1533 static HRESULT WINAPI
isaxattributes_getName(
1534 ISAXAttributes
* iface
,
1538 const WCHAR
** pLocalName
,
1539 int * pLocalNameSize
,
1540 const WCHAR
** pQName
,
1543 ok(0, "unexpected call\n");
1547 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1548 ISAXAttributes
* iface
,
1551 const WCHAR
* pLocalName
,
1552 int cocalNameLength
,
1555 ok(0, "unexpected call\n");
1559 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1560 ISAXAttributes
* iface
,
1561 const WCHAR
* pQName
,
1565 ok(0, "unexpected call\n");
1569 static HRESULT WINAPI
isaxattributes_getType(
1570 ISAXAttributes
* iface
,
1572 const WCHAR
** pType
,
1575 ok(0, "unexpected call\n");
1579 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1580 ISAXAttributes
* iface
,
1583 const WCHAR
* pLocalName
,
1585 const WCHAR
** pType
,
1588 ok(0, "unexpected call\n");
1592 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1593 ISAXAttributes
* iface
,
1594 const WCHAR
* pQName
,
1596 const WCHAR
** pType
,
1599 ok(0, "unexpected call\n");
1603 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1604 const WCHAR
**value
, int *nValue
)
1606 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1607 {'a','2','j','u','n','k',0},
1608 {'<','&','"','>','\'',0}};
1609 static const int attrvalueslen
[] = {2, 2, 5};
1611 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1613 if (index
>= 0 && index
<= 2) {
1614 *value
= attrvaluesW
[index
];
1615 *nValue
= attrvalueslen
[index
];
1624 static HRESULT WINAPI
isaxattributes_getValueFromName(
1625 ISAXAttributes
* iface
,
1628 const WCHAR
* pLocalName
,
1630 const WCHAR
** pValue
,
1633 ok(0, "unexpected call\n");
1637 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1638 ISAXAttributes
* iface
,
1639 const WCHAR
* pQName
,
1641 const WCHAR
** pValue
,
1644 ok(0, "unexpected call\n");
1648 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1650 isaxattributes_QueryInterface
,
1651 isaxattributes_AddRef
,
1652 isaxattributes_Release
,
1653 isaxattributes_getLength
,
1654 isaxattributes_getURI
,
1655 isaxattributes_getLocalName
,
1656 isaxattributes_getQName
,
1657 isaxattributes_getName
,
1658 isaxattributes_getIndexFromName
,
1659 isaxattributes_getIndexFromQName
,
1660 isaxattributes_getType
,
1661 isaxattributes_getTypeFromName
,
1662 isaxattributes_getTypeFromQName
,
1663 isaxattributes_getValue
,
1664 isaxattributes_getValueFromName
,
1665 isaxattributes_getValueFromQName
1668 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1670 struct saxlexicalhandler
1672 ISAXLexicalHandler ISAXLexicalHandler_iface
;
1675 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1678 static inline struct saxlexicalhandler
*impl_from_ISAXLexicalHandler( ISAXLexicalHandler
*iface
)
1680 return CONTAINING_RECORD(iface
, struct saxlexicalhandler
, ISAXLexicalHandler_iface
);
1683 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **out
)
1685 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1689 if (IsEqualGUID(riid
, &IID_IUnknown
))
1692 ok(0, "got unexpected IID_IUnknown query\n");
1694 else if (IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1696 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1701 ISAXLexicalHandler_AddRef(iface
);
1703 return E_NOINTERFACE
;
1708 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1710 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1711 return InterlockedIncrement(&handler
->ref
);
1714 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1716 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1717 return InterlockedDecrement(&handler
->ref
);
1720 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1721 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1722 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1724 ok(0, "call not expected\n");
1728 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1730 ok(0, "call not expected\n");
1734 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1735 const WCHAR
* pName
, int nName
)
1737 ok(0, "call not expected\n");
1741 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1742 const WCHAR
* pName
, int nName
)
1744 ok(0, "call not expected\n");
1748 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1750 struct call_entry call
;
1752 init_call_entry(locator
, &call
);
1753 call
.id
= LH_STARTCDATA
;
1754 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1756 return get_expected_ret();
1759 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1761 struct call_entry call
;
1763 init_call_entry(locator
, &call
);
1764 call
.id
= LH_ENDCDATA
;
1765 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1767 return get_expected_ret();
1770 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1771 const WCHAR
* pChars
, int nChars
)
1773 ok(0, "call not expected\n");
1777 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1779 isaxlexical_QueryInterface
,
1781 isaxlexical_Release
,
1782 isaxlexical_startDTD
,
1784 isaxlexical_startEntity
,
1785 isaxlexical_endEntity
,
1786 isaxlexical_startCDATA
,
1787 isaxlexical_endCDATA
,
1791 static void init_saxlexicalhandler(struct saxlexicalhandler
*handler
, HRESULT hr
)
1793 handler
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1795 handler
->qi_hr
= hr
;
1798 struct saxdeclhandler
1800 ISAXDeclHandler ISAXDeclHandler_iface
;
1803 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1806 static inline struct saxdeclhandler
*impl_from_ISAXDeclHandler( ISAXDeclHandler
*iface
)
1808 return CONTAINING_RECORD(iface
, struct saxdeclhandler
, ISAXDeclHandler_iface
);
1811 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **out
)
1813 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1817 if (IsEqualGUID(riid
, &IID_IUnknown
))
1820 ok(0, "got unexpected IID_IUnknown query\n");
1822 else if (IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1824 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1829 ISAXDeclHandler_AddRef(iface
);
1831 return E_NOINTERFACE
;
1836 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1838 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1839 return InterlockedIncrement(&handler
->ref
);
1842 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1844 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1845 return InterlockedDecrement(&handler
->ref
);
1848 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1849 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1851 ok(0, "call not expected\n");
1855 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1856 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1857 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1858 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1860 ok(0, "call not expected\n");
1864 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1865 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1867 ok(0, "call not expected\n");
1871 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1872 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1873 const WCHAR
* pSystemId
, int nSystemId
)
1875 ok(0, "call not expected\n");
1879 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1881 isaxdecl_QueryInterface
,
1884 isaxdecl_elementDecl
,
1885 isaxdecl_attributeDecl
,
1886 isaxdecl_internalEntityDecl
,
1887 isaxdecl_externalEntityDecl
1890 static void init_saxdeclhandler(struct saxdeclhandler
*handler
, HRESULT hr
)
1892 handler
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1894 handler
->qi_hr
= hr
;
1897 typedef struct mxwriter_write_test_t
{
1903 } mxwriter_write_test
;
1905 typedef struct mxwriter_stream_test_t
{
1907 const char *encoding
;
1908 mxwriter_write_test expected_writes
[4];
1909 } mxwriter_stream_test
;
1911 static const mxwriter_write_test
*current_write_test
;
1912 static DWORD current_stream_test_index
;
1914 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1918 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1921 return E_NOINTERFACE
;
1926 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1931 static ULONG WINAPI
istream_Release(IStream
*iface
)
1936 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1938 ok(0, "unexpected call\n");
1942 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1944 ok(0, "unexpected call\n");
1948 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1949 ULARGE_INTEGER
*plibNewPosition
)
1951 ok(0, "unexpected call\n");
1955 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1957 ok(0, "unexpected call\n");
1961 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1962 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1964 ok(0, "unexpected call\n");
1968 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1970 ok(0, "unexpected call\n");
1974 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1976 ok(0, "unexpected call\n");
1980 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1981 ULARGE_INTEGER cb
, DWORD dwLockType
)
1983 ok(0, "unexpected call\n");
1987 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1988 ULARGE_INTEGER cb
, DWORD dwLockType
)
1990 ok(0, "unexpected call\n");
1994 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1999 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
2001 ok(0, "unexpected call\n");
2005 static HRESULT WINAPI
mxstream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
2009 ok(pv
!= NULL
, "pv == NULL\n");
2011 if(current_write_test
->last
) {
2012 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
2016 fail
= current_write_test
->fail_write
;
2018 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
2019 current_write_test
->cb
, cb
, current_stream_test_index
);
2022 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
2024 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
2026 ++current_write_test
;
2031 return fail
? E_FAIL
: S_OK
;
2034 static const IStreamVtbl mxstreamVtbl
= {
2035 istream_QueryInterface
,
2046 istream_UnlockRegion
,
2051 static IStream mxstream
= { &mxstreamVtbl
};
2053 static int read_cnt
;
2055 static HRESULT WINAPI
instream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
2057 static const char *ret_str
;
2060 ret_str
= "<?xml version=\"1.0\" ?>\n<rootelem>";
2061 else if(read_cnt
< 5)
2062 ret_str
= "<elem attr=\"val\">text</elem>";
2063 else if(read_cnt
== 5)
2064 ret_str
= "</rootelem>\n";
2069 strcpy(pv
, ret_str
);
2070 *pcbRead
= strlen(ret_str
);
2074 static const IStreamVtbl instreamVtbl
= {
2075 istream_QueryInterface
,
2086 istream_UnlockRegion
,
2091 static IStream instream
= { &instreamVtbl
};
2093 static struct msxmlsupported_data_t reader_support_data
[] =
2095 { &CLSID_SAXXMLReader
, "SAXReader" },
2096 { &CLSID_SAXXMLReader30
, "SAXReader30" },
2097 { &CLSID_SAXXMLReader40
, "SAXReader40" },
2098 { &CLSID_SAXXMLReader60
, "SAXReader60" },
2102 static struct saxlexicalhandler lexicalhandler
;
2103 static struct saxdeclhandler declhandler
;
2105 static IStream
*create_test_stream(const char *data
, int len
)
2107 ULARGE_INTEGER size
;
2112 if (len
== -1) len
= strlen(data
);
2113 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2114 size
.QuadPart
= len
;
2115 IStream_SetSize(stream
, size
);
2116 IStream_Write(stream
, data
, len
, &written
);
2118 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2123 static void test_saxreader(void)
2125 const struct msxmlsupported_data_t
*table
= reader_support_data
;
2127 ISAXXMLReader
*reader
= NULL
;
2129 ISAXContentHandler
*content
;
2130 ISAXErrorHandler
*lpErrorHandler
;
2132 SAFEARRAYBOUND SADim
[1];
2137 static const CHAR testXmlA
[] = "test.xml";
2138 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2139 IXMLDOMDocument
*doc
;
2143 while (table
->clsid
)
2145 struct call_entry
*test_seq
;
2146 ISAXEntityResolver
*resolver
;
2149 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
2155 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2156 EXPECT_HR(hr
, S_OK
);
2159 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2161 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2166 /* crashes on old versions */
2167 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
2168 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2170 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
2171 EXPECT_HR(hr
, E_POINTER
);
2173 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
2174 EXPECT_HR(hr
, E_POINTER
);
2177 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2178 EXPECT_HR(hr
, S_OK
);
2179 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
2181 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
2182 EXPECT_HR(hr
, S_OK
);
2183 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
2185 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
2186 EXPECT_HR(hr
, S_OK
);
2188 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
2189 EXPECT_HR(hr
, S_OK
);
2191 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
2192 EXPECT_HR(hr
, S_OK
);
2194 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2195 EXPECT_HR(hr
, S_OK
);
2196 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
2198 V_VT(&var
) = VT_BSTR
;
2199 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
2201 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2202 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2203 test_seq
= content_handler_test1_alternate
;
2205 test_seq
= content_handler_test1
;
2206 set_expected_seq(test_seq
);
2207 hr
= ISAXXMLReader_parse(reader
, var
);
2208 EXPECT_HR(hr
, S_OK
);
2209 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
2213 SADim
[0].lLbound
= 0;
2214 SADim
[0].cElements
= sizeof(testXML
)-1;
2215 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
2216 SafeArrayAccessData(sa
, (void**)&ptr
);
2217 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
2218 SafeArrayUnaccessData(sa
);
2219 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
2222 set_expected_seq(test_seq
);
2223 hr
= ISAXXMLReader_parse(reader
, var
);
2224 EXPECT_HR(hr
, S_OK
);
2225 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from safe array", FALSE
);
2227 SafeArrayDestroy(sa
);
2229 stream
= create_test_stream(testXML
, -1);
2230 V_VT(&var
) = VT_UNKNOWN
;
2231 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2233 set_expected_seq(test_seq
);
2234 hr
= ISAXXMLReader_parse(reader
, var
);
2235 EXPECT_HR(hr
, S_OK
);
2236 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
2238 IStream_Release(stream
);
2240 stream
= create_test_stream(test_attributes
, -1);
2241 V_VT(&var
) = VT_UNKNOWN
;
2242 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2244 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2245 test_seq
= content_handler_test_attributes_alternate_4
;
2246 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2247 test_seq
= content_handler_test_attributes_alternate_6
;
2249 test_seq
= content_handler_test_attributes
;
2251 set_expected_seq(test_seq
);
2252 hr
= ISAXXMLReader_parse(reader
, var
);
2253 EXPECT_HR(hr
, S_OK
);
2255 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2256 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2257 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2259 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2261 IStream_Release(stream
);
2263 V_VT(&var
) = VT_UNKNOWN
;
2264 V_UNKNOWN(&var
) = (IUnknown
*)&instream
;
2266 test_seq
= read_test_seq
;
2268 set_expected_seq(test_seq
);
2269 hr
= ISAXXMLReader_parse(reader
, var
);
2270 EXPECT_HR(hr
, S_OK
);
2271 ok(read_cnt
== 7, "read_cnt = %d\n", read_cnt
);
2272 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "Read call test", FALSE
);
2274 V_VT(&var
) = VT_BSTR
;
2275 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
2277 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2278 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2279 test_seq
= content_handler_test2_alternate
;
2281 test_seq
= content_handler_test2
;
2283 set_expected_seq(test_seq
);
2284 hr
= ISAXXMLReader_parse(reader
, var
);
2285 EXPECT_HR(hr
, S_OK
);
2286 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
2291 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2292 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2293 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
2296 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2297 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2298 test_seq
= content_handler_test1_alternate
;
2300 test_seq
= content_handler_test1
;
2301 set_expected_seq(test_seq
);
2302 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2303 EXPECT_HR(hr
, S_OK
);
2304 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
2307 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2308 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2309 test_seq
= content_handler_testerror_alternate
;
2311 test_seq
= content_handler_testerror
;
2312 set_expected_seq(test_seq
);
2313 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2314 EXPECT_HR(hr
, E_FAIL
);
2315 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
2317 /* callback ret values */
2318 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2319 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2321 test_seq
= content_handler_test_callback_rets_alt
;
2322 set_expected_seq(test_seq
);
2323 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2324 EXPECT_HR(hr
, S_OK
);
2328 test_seq
= content_handler_test_callback_rets
;
2329 set_expected_seq(test_seq
);
2330 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2331 EXPECT_HR(hr
, S_FALSE
);
2333 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
2335 DeleteFileA(testXmlA
);
2337 /* parse from IXMLDOMDocument */
2338 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
2339 &IID_IXMLDOMDocument
, (void**)&doc
);
2340 EXPECT_HR(hr
, S_OK
);
2342 str
= SysAllocString(szSimpleXML
);
2343 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
2344 EXPECT_HR(hr
, S_OK
);
2347 V_VT(&var
) = VT_UNKNOWN
;
2348 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
2350 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2351 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2352 test_seq
= content_handler_test2_alternate
;
2354 test_seq
= content_handler_test2
;
2356 set_expected_seq(test_seq
);
2357 hr
= ISAXXMLReader_parse(reader
, var
);
2358 EXPECT_HR(hr
, S_OK
);
2359 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
2360 IXMLDOMDocument_Release(doc
);
2362 /* xml:space test */
2363 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2364 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2366 test_seq
= xmlspaceattr_test_alternate
;
2369 test_seq
= xmlspaceattr_test
;
2371 set_expected_seq(test_seq
);
2372 V_VT(&var
) = VT_BSTR
;
2373 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
2374 hr
= ISAXXMLReader_parse(reader
, var
);
2375 EXPECT_HR(hr
, S_OK
);
2377 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2378 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2380 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
2383 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
2385 /* switch off 'namespaces' feature */
2386 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE
);
2387 EXPECT_HR(hr
, S_OK
);
2389 stream
= create_test_stream(test_attributes
, -1);
2390 V_VT(&var
) = VT_UNKNOWN
;
2391 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2393 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2394 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2396 test_seq
= content_handler_test_attributes_alt_no_ns
;
2399 test_seq
= content_handler_test_attributes
;
2401 set_expected_seq(test_seq
);
2402 hr
= ISAXXMLReader_parse(reader
, var
);
2403 EXPECT_HR(hr
, S_OK
);
2404 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2405 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_TRUE
);
2406 EXPECT_HR(hr
, S_OK
);
2408 /* switch off 'namespace-prefixes' feature */
2409 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_FALSE
);
2410 EXPECT_HR(hr
, S_OK
);
2412 stream
= create_test_stream(test_attributes
, -1);
2413 V_VT(&var
) = VT_UNKNOWN
;
2414 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2416 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2417 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2419 test_seq
= content_handler_test_attributes_alt_no_prefix
;
2422 test_seq
= content_handler_test_attributes_no_prefix
;
2424 set_expected_seq(test_seq
);
2425 hr
= ISAXXMLReader_parse(reader
, var
);
2426 EXPECT_HR(hr
, S_OK
);
2427 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2429 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_TRUE
);
2430 EXPECT_HR(hr
, S_OK
);
2432 /* attribute normalization */
2433 stream
= create_test_stream(attribute_normalize
, -1);
2434 V_VT(&var
) = VT_UNKNOWN
;
2435 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2437 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2438 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2440 test_seq
= attribute_norm_alt
;
2443 test_seq
= attribute_norm
;
2445 set_expected_seq(test_seq
);
2446 hr
= ISAXXMLReader_parse(reader
, var
);
2447 EXPECT_HR(hr
, S_OK
);
2448 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "attribute value normalization", TRUE
);
2449 IStream_Release(stream
);
2451 resolver
= (void*)0xdeadbeef;
2452 hr
= ISAXXMLReader_getEntityResolver(reader
, &resolver
);
2453 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2454 ok(resolver
== NULL
, "got %p\n", resolver
);
2456 hr
= ISAXXMLReader_putEntityResolver(reader
, NULL
);
2457 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "got 0x%08x\n", hr
);
2459 /* CDATA sections */
2460 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2462 V_VT(&var
) = VT_UNKNOWN
;
2463 V_UNKNOWN(&var
) = (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
;
2464 hr
= ISAXXMLReader_putProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), var
);
2465 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2467 stream
= create_test_stream(test_cdata_xml
, -1);
2468 V_VT(&var
) = VT_UNKNOWN
;
2469 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2471 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2472 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2473 test_seq
= cdata_test_alt
;
2475 test_seq
= cdata_test
;
2477 set_expected_seq(test_seq
);
2478 hr
= ISAXXMLReader_parse(reader
, var
);
2479 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2480 sprintf(seqname
, "%s: cdata test", table
->name
);
2481 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2483 IStream_Release(stream
);
2485 /* 2. CDATA sections */
2486 stream
= create_test_stream(test2_cdata_xml
, -1);
2487 V_VT(&var
) = VT_UNKNOWN
;
2488 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2490 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2491 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2492 test_seq
= cdata_test2_alt
;
2494 test_seq
= cdata_test2
;
2496 set_expected_seq(test_seq
);
2497 hr
= ISAXXMLReader_parse(reader
, var
);
2498 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2499 sprintf(seqname
, "%s: cdata test 2", table
->name
);
2500 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2502 IStream_Release(stream
);
2504 /* 3. CDATA sections */
2505 stream
= create_test_stream(test3_cdata_xml
, -1);
2506 V_VT(&var
) = VT_UNKNOWN
;
2507 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2509 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2510 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2511 test_seq
= cdata_test3_alt
;
2513 test_seq
= cdata_test3
;
2515 set_expected_seq(test_seq
);
2516 hr
= ISAXXMLReader_parse(reader
, var
);
2517 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2518 sprintf(seqname
, "%s: cdata test 3", table
->name
);
2519 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2521 IStream_Release(stream
);
2523 ISAXXMLReader_Release(reader
);
2530 struct saxreader_props_test_t
2532 const char *prop_name
;
2536 static const struct saxreader_props_test_t props_test_data
[] = {
2537 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
},
2538 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&declhandler
.ISAXDeclHandler_iface
},
2542 static void test_saxreader_properties(void)
2544 const struct saxreader_props_test_t
*ptr
= props_test_data
;
2545 ISAXXMLReader
*reader
;
2550 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2551 &IID_ISAXXMLReader
, (void**)&reader
);
2552 EXPECT_HR(hr
, S_OK
);
2554 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
2555 EXPECT_HR(hr
, E_POINTER
);
2557 while (ptr
->prop_name
)
2562 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2563 init_saxdeclhandler(&declhandler
, S_OK
);
2565 V_VT(&v
) = VT_EMPTY
;
2566 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2567 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2568 EXPECT_HR(hr
, S_OK
);
2569 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2570 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2573 V_VT(&v
) = VT_UNKNOWN
;
2574 V_UNKNOWN(&v
) = ptr
->iface
;
2575 ref
= get_refcount(ptr
->iface
);
2576 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2577 EXPECT_HR(hr
, S_OK
);
2578 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2581 V_VT(&v
) = VT_DISPATCH
;
2582 V_UNKNOWN(&v
) = ptr
->iface
;
2583 ref
= get_refcount(ptr
->iface
);
2584 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2585 EXPECT_HR(hr
, S_OK
);
2586 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2588 /* VT_VARIANT|VT_BYREF with VT_UNKNOWN in referenced variant */
2589 V_VT(&varref
) = VT_UNKNOWN
;
2590 V_UNKNOWN(&varref
) = ptr
->iface
;
2592 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2593 V_VARIANTREF(&v
) = &varref
;
2594 ref
= get_refcount(ptr
->iface
);
2595 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2596 EXPECT_HR(hr
, S_OK
);
2597 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2599 /* VT_VARIANT|VT_BYREF with VT_DISPATCH in referenced variant */
2600 V_VT(&varref
) = VT_DISPATCH
;
2601 V_UNKNOWN(&varref
) = ptr
->iface
;
2603 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2604 V_VARIANTREF(&v
) = &varref
;
2605 ref
= get_refcount(ptr
->iface
);
2606 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2607 EXPECT_HR(hr
, S_OK
);
2608 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2610 V_VT(&v
) = VT_EMPTY
;
2611 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2613 ref
= get_refcount(ptr
->iface
);
2614 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2615 EXPECT_HR(hr
, S_OK
);
2616 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2617 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2618 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2621 V_VT(&v
) = VT_EMPTY
;
2622 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2623 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2624 EXPECT_HR(hr
, S_OK
);
2626 V_VT(&v
) = VT_EMPTY
;
2627 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2628 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2629 EXPECT_HR(hr
, S_OK
);
2630 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2631 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2633 V_VT(&v
) = VT_UNKNOWN
;
2634 V_UNKNOWN(&v
) = ptr
->iface
;
2635 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2636 EXPECT_HR(hr
, S_OK
);
2638 /* only VT_EMPTY seems to be valid to reset property */
2640 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2641 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2642 EXPECT_HR(hr
, E_INVALIDARG
);
2644 V_VT(&v
) = VT_EMPTY
;
2645 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2646 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2647 EXPECT_HR(hr
, S_OK
);
2648 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2649 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2652 V_VT(&v
) = VT_UNKNOWN
;
2653 V_UNKNOWN(&v
) = NULL
;
2654 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2655 EXPECT_HR(hr
, S_OK
);
2657 V_VT(&v
) = VT_EMPTY
;
2658 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2659 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2660 EXPECT_HR(hr
, S_OK
);
2661 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2662 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2664 /* block QueryInterface on handler riid */
2665 V_VT(&v
) = VT_UNKNOWN
;
2666 V_UNKNOWN(&v
) = ptr
->iface
;
2667 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2668 EXPECT_HR(hr
, S_OK
);
2670 init_saxlexicalhandler(&lexicalhandler
, E_NOINTERFACE
);
2671 init_saxdeclhandler(&declhandler
, E_NOINTERFACE
);
2673 V_VT(&v
) = VT_UNKNOWN
;
2674 V_UNKNOWN(&v
) = ptr
->iface
;
2675 EXPECT_REF(ptr
->iface
, 1);
2676 ref
= get_refcount(ptr
->iface
);
2677 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2678 EXPECT_HR(hr
, E_NOINTERFACE
);
2679 EXPECT_REF(ptr
->iface
, 1);
2681 V_VT(&v
) = VT_EMPTY
;
2682 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2683 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2684 EXPECT_HR(hr
, S_OK
);
2685 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2686 ok(V_UNKNOWN(&v
) != NULL
, "got %p\n", V_UNKNOWN(&v
));
2692 ISAXXMLReader_Release(reader
);
2694 if (!is_clsid_supported(&CLSID_SAXXMLReader40
, reader_support_data
))
2697 hr
= CoCreateInstance(&CLSID_SAXXMLReader40
, NULL
, CLSCTX_INPROC_SERVER
,
2698 &IID_ISAXXMLReader
, (void**)&reader
);
2699 EXPECT_HR(hr
, S_OK
);
2701 /* xmldecl-version property */
2702 V_VT(&v
) = VT_EMPTY
;
2703 V_BSTR(&v
) = (void*)0xdeadbeef;
2704 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2705 EXPECT_HR(hr
, S_OK
);
2706 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2707 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2709 /* stream without declaration */
2711 V_BSTR(&v
) = _bstr_("<element></element>");
2712 hr
= ISAXXMLReader_parse(reader
, v
);
2713 EXPECT_HR(hr
, S_OK
);
2715 V_VT(&v
) = VT_EMPTY
;
2716 V_BSTR(&v
) = (void*)0xdeadbeef;
2717 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2718 EXPECT_HR(hr
, S_OK
);
2719 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2720 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2722 /* stream with declaration */
2724 V_BSTR(&v
) = _bstr_("<?xml version=\"1.0\"?><element></element>");
2725 hr
= ISAXXMLReader_parse(reader
, v
);
2726 EXPECT_HR(hr
, S_OK
);
2728 /* VT_BSTR|VT_BYREF input type */
2729 str
= _bstr_("<?xml version=\"1.0\"?><element></element>");
2730 V_VT(&v
) = VT_BSTR
|VT_BYREF
;
2731 V_BSTRREF(&v
) = &str
;
2732 hr
= ISAXXMLReader_parse(reader
, v
);
2733 EXPECT_HR(hr
, S_OK
);
2735 V_VT(&v
) = VT_EMPTY
;
2736 V_BSTR(&v
) = (void*)0xdeadbeef;
2737 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2738 EXPECT_HR(hr
, S_OK
);
2739 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2740 ok(!lstrcmpW(V_BSTR(&v
), _bstr_("1.0")), "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2743 ISAXXMLReader_Release(reader
);
2747 struct feature_ns_entry_t
{
2751 VARIANT_BOOL value2
; /* feature value after feature set to 0xc */
2754 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2755 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
, VARIANT_FALSE
},
2756 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
, VARIANT_FALSE
},
2757 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
, VARIANT_TRUE
},
2758 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
, VARIANT_TRUE
},
2762 static const char *feature_names
[] = {
2763 "http://xml.org/sax/features/namespaces",
2764 "http://xml.org/sax/features/namespace-prefixes",
2768 static void test_saxreader_features(void)
2770 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2771 ISAXXMLReader
*reader
;
2779 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2782 win_skip("can't create %s instance\n", entry
->clsid
);
2787 name
= feature_names
;
2791 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2792 EXPECT_HR(hr
, S_OK
);
2793 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2796 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), value
);
2797 EXPECT_HR(hr
, S_OK
);
2800 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2801 EXPECT_HR(hr
, S_OK
);
2802 ok(entry
->value2
== value
, "%s: got wrong value %x, expected %x\n", entry
->clsid
, value
, entry
->value2
);
2804 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_FALSE
);
2805 EXPECT_HR(hr
, S_OK
);
2807 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2808 EXPECT_HR(hr
, S_OK
);
2809 ok(value
== VARIANT_FALSE
, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry
->clsid
, value
);
2811 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_TRUE
);
2812 EXPECT_HR(hr
, S_OK
);
2814 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2815 EXPECT_HR(hr
, S_OK
);
2816 ok(value
== VARIANT_TRUE
, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry
->clsid
, value
);
2821 ISAXXMLReader_Release(reader
);
2827 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2828 static const CHAR UTF8BOMTest
[] =
2829 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2832 struct enc_test_entry_t
{
2840 static const struct enc_test_entry_t encoding_test_data
[] = {
2841 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2842 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2843 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, FALSE
},
2844 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, FALSE
},
2848 static void test_saxreader_encoding(void)
2850 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2851 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2852 static const CHAR testXmlA
[] = "test.xml";
2856 ISAXXMLReader
*reader
;
2862 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2865 win_skip("can't create %s instance\n", entry
->clsid
);
2870 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2871 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2872 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2875 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2877 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2879 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2881 DeleteFileA(testXmlA
);
2883 /* try BSTR input with no BOM or '<?xml' instruction */
2884 V_VT(&input
) = VT_BSTR
;
2885 V_BSTR(&input
) = _bstr_("<element></element>");
2886 hr
= ISAXXMLReader_parse(reader
, input
);
2887 EXPECT_HR(hr
, S_OK
);
2889 ISAXXMLReader_Release(reader
);
2896 static void test_mxwriter_handlers(void)
2902 static const REFIID riids
[] =
2904 &IID_ISAXContentHandler
,
2905 &IID_ISAXLexicalHandler
,
2906 &IID_ISAXDeclHandler
,
2907 &IID_ISAXDTDHandler
,
2908 &IID_ISAXErrorHandler
,
2909 &IID_IVBSAXDeclHandler
,
2910 &IID_IVBSAXLexicalHandler
,
2911 &IID_IVBSAXContentHandler
,
2912 &IID_IVBSAXDTDHandler
,
2913 &IID_IVBSAXErrorHandler
2916 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2917 &IID_IMXWriter
, (void**)&writer
);
2918 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2920 EXPECT_REF(writer
, 1);
2922 for (i
= 0; i
< sizeof(riids
)/sizeof(REFIID
); i
++)
2927 /* handler from IMXWriter */
2928 hr
= IMXWriter_QueryInterface(writer
, riids
[i
], (void**)&handler
);
2929 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2930 EXPECT_REF(writer
, 2);
2931 EXPECT_REF(handler
, 2);
2933 /* IMXWriter from a handler */
2934 hr
= IUnknown_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2935 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2936 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2937 EXPECT_REF(writer
, 3);
2938 EXPECT_REF(writer2
, 3);
2939 IMXWriter_Release(writer2
);
2940 IUnknown_Release(handler
);
2943 IMXWriter_Release(writer
);
2946 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2948 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2949 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2950 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2951 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2955 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2957 { &CLSID_SAXAttributes
, "SAXAttributes" },
2958 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2959 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2960 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2964 struct mxwriter_props_t
2968 VARIANT_BOOL disable_escape
;
2969 VARIANT_BOOL indent
;
2970 VARIANT_BOOL omitdecl
;
2971 VARIANT_BOOL standalone
;
2972 const char *encoding
;
2975 static const struct mxwriter_props_t mxwriter_default_props
[] =
2977 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2978 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2979 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2980 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2984 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2988 while (table
->clsid
)
2995 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3002 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3003 &IID_IMXWriter
, (void**)&writer
);
3004 EXPECT_HR(hr
, S_OK
);
3007 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
3008 EXPECT_HR(hr
, S_OK
);
3009 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
3011 b
= !table
->disable_escape
;
3012 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
3013 EXPECT_HR(hr
, S_OK
);
3014 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
3015 table
->disable_escape
);
3018 hr
= IMXWriter_get_indent(writer
, &b
);
3019 EXPECT_HR(hr
, S_OK
);
3020 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
3022 b
= !table
->omitdecl
;
3023 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
3024 EXPECT_HR(hr
, S_OK
);
3025 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
3027 b
= !table
->standalone
;
3028 hr
= IMXWriter_get_standalone(writer
, &b
);
3029 EXPECT_HR(hr
, S_OK
);
3030 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
3032 hr
= IMXWriter_get_encoding(writer
, &encoding
);
3033 EXPECT_HR(hr
, S_OK
);
3034 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
3035 i
, wine_dbgstr_w(encoding
), table
->encoding
);
3036 SysFreeString(encoding
);
3038 IMXWriter_Release(writer
);
3045 static void test_mxwriter_properties(void)
3047 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
3048 static const WCHAR testW
[] = {'t','e','s','t',0};
3049 ISAXContentHandler
*content
;
3056 test_mxwriter_default_properties(mxwriter_default_props
);
3058 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3059 &IID_IMXWriter
, (void**)&writer
);
3060 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3062 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
3063 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3065 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
3066 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3068 hr
= IMXWriter_get_indent(writer
, NULL
);
3069 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3071 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
3072 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3074 hr
= IMXWriter_get_standalone(writer
, NULL
);
3075 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3078 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
3079 ok(hr
== S_OK
, "got %08x\n", hr
);
3082 hr
= IMXWriter_get_standalone(writer
, &b
);
3083 ok(hr
== S_OK
, "got %08x\n", hr
);
3084 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
3086 hr
= IMXWriter_get_encoding(writer
, NULL
);
3087 EXPECT_HR(hr
, E_POINTER
);
3089 /* UTF-16 is a default setting apparently */
3090 str
= (void*)0xdeadbeef;
3091 hr
= IMXWriter_get_encoding(writer
, &str
);
3092 EXPECT_HR(hr
, S_OK
);
3093 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
3095 str2
= (void*)0xdeadbeef;
3096 hr
= IMXWriter_get_encoding(writer
, &str2
);
3097 ok(hr
== S_OK
, "got %08x\n", hr
);
3098 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
3100 SysFreeString(str2
);
3103 /* put empty string */
3104 str
= SysAllocString(emptyW
);
3105 hr
= IMXWriter_put_encoding(writer
, str
);
3106 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3109 str
= (void*)0xdeadbeef;
3110 hr
= IMXWriter_get_encoding(writer
, &str
);
3111 EXPECT_HR(hr
, S_OK
);
3112 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
3115 /* invalid encoding name */
3116 str
= SysAllocString(testW
);
3117 hr
= IMXWriter_put_encoding(writer
, str
);
3118 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3121 /* test case sensivity */
3122 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
3123 EXPECT_HR(hr
, S_OK
);
3124 str
= (void*)0xdeadbeef;
3125 hr
= IMXWriter_get_encoding(writer
, &str
);
3126 EXPECT_HR(hr
, S_OK
);
3127 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
3130 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
3131 EXPECT_HR(hr
, S_OK
);
3132 str
= (void*)0xdeadbeef;
3133 hr
= IMXWriter_get_encoding(writer
, &str
);
3134 EXPECT_HR(hr
, S_OK
);
3135 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
3138 /* how it affects document creation */
3139 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3140 EXPECT_HR(hr
, S_OK
);
3142 hr
= ISAXContentHandler_startDocument(content
);
3143 EXPECT_HR(hr
, S_OK
);
3144 hr
= ISAXContentHandler_endDocument(content
);
3145 EXPECT_HR(hr
, S_OK
);
3147 V_VT(&dest
) = VT_EMPTY
;
3148 hr
= IMXWriter_get_output(writer
, &dest
);
3149 EXPECT_HR(hr
, S_OK
);
3150 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3151 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
3152 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3153 VariantClear(&dest
);
3154 ISAXContentHandler_Release(content
);
3156 hr
= IMXWriter_get_version(writer
, NULL
);
3157 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3158 /* default version is 'surprisingly' 1.0 */
3159 hr
= IMXWriter_get_version(writer
, &str
);
3160 ok(hr
== S_OK
, "got %08x\n", hr
);
3161 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
3164 /* store version string as is */
3165 hr
= IMXWriter_put_version(writer
, NULL
);
3166 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3168 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
3169 ok(hr
== S_OK
, "got %08x\n", hr
);
3171 hr
= IMXWriter_put_version(writer
, _bstr_(""));
3172 ok(hr
== S_OK
, "got %08x\n", hr
);
3173 hr
= IMXWriter_get_version(writer
, &str
);
3174 ok(hr
== S_OK
, "got %08x\n", hr
);
3175 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
3178 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
3179 ok(hr
== S_OK
, "got %08x\n", hr
);
3180 hr
= IMXWriter_get_version(writer
, &str
);
3181 ok(hr
== S_OK
, "got %08x\n", hr
);
3182 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
3185 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
3186 ok(hr
== S_OK
, "got %08x\n", hr
);
3187 hr
= IMXWriter_get_version(writer
, &str
);
3188 ok(hr
== S_OK
, "got %08x\n", hr
);
3189 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
3192 IMXWriter_Release(writer
);
3196 static void test_mxwriter_flush(void)
3198 ISAXContentHandler
*content
;
3201 ULARGE_INTEGER pos2
;
3209 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3210 &IID_IMXWriter
, (void**)&writer
);
3211 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3213 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3214 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3215 EXPECT_REF(stream
, 1);
3217 /* detach when nothing was attached */
3218 V_VT(&dest
) = VT_EMPTY
;
3219 hr
= IMXWriter_put_output(writer
, dest
);
3220 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3223 V_VT(&dest
) = VT_UNKNOWN
;
3224 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3225 hr
= IMXWriter_put_output(writer
, dest
);
3226 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3227 todo_wine
EXPECT_REF(stream
, 3);
3229 /* detach setting VT_EMPTY destination */
3230 V_VT(&dest
) = VT_EMPTY
;
3231 hr
= IMXWriter_put_output(writer
, dest
);
3232 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3233 EXPECT_REF(stream
, 1);
3235 V_VT(&dest
) = VT_UNKNOWN
;
3236 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3237 hr
= IMXWriter_put_output(writer
, dest
);
3238 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3240 /* flush() doesn't detach a stream */
3241 hr
= IMXWriter_flush(writer
);
3242 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3243 todo_wine
EXPECT_REF(stream
, 3);
3246 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3247 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3248 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3250 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3251 ok(hr
== S_OK
, "got %08x\n", hr
);
3253 hr
= ISAXContentHandler_startDocument(content
);
3254 ok(hr
== S_OK
, "got %08x\n", hr
);
3257 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3258 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3259 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
3261 /* already started */
3262 hr
= ISAXContentHandler_startDocument(content
);
3263 ok(hr
== S_OK
, "got %08x\n", hr
);
3265 hr
= ISAXContentHandler_endDocument(content
);
3266 ok(hr
== S_OK
, "got %08x\n", hr
);
3268 /* flushed on endDocument() */
3270 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3271 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3272 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
3274 IStream_Release(stream
);
3276 /* auto-flush feature */
3277 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3278 EXPECT_HR(hr
, S_OK
);
3279 EXPECT_REF(stream
, 1);
3281 V_VT(&dest
) = VT_UNKNOWN
;
3282 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3283 hr
= IMXWriter_put_output(writer
, dest
);
3284 EXPECT_HR(hr
, S_OK
);
3286 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_FALSE
);
3287 EXPECT_HR(hr
, S_OK
);
3289 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3290 EXPECT_HR(hr
, S_OK
);
3292 hr
= ISAXContentHandler_startDocument(content
);
3293 EXPECT_HR(hr
, S_OK
);
3295 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3296 EXPECT_HR(hr
, S_OK
);
3298 /* internal buffer is flushed automatically on certain threshold */
3301 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3302 EXPECT_HR(hr
, S_OK
);
3303 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3306 buff
= HeapAlloc(GetProcessHeap(), 0, len
+1);
3307 memset(buff
, 'A', len
);
3309 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3310 EXPECT_HR(hr
, S_OK
);
3314 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3315 EXPECT_HR(hr
, S_OK
);
3317 ok(pos2
.QuadPart
!= 0, "unexpected stream beginning\n");
3319 hr
= IMXWriter_get_output(writer
, NULL
);
3320 EXPECT_HR(hr
, E_POINTER
);
3322 ref
= get_refcount(stream
);
3323 V_VT(&dest
) = VT_EMPTY
;
3324 hr
= IMXWriter_get_output(writer
, &dest
);
3325 EXPECT_HR(hr
, S_OK
);
3326 ok(V_VT(&dest
) == VT_UNKNOWN
, "got vt type %d\n", V_VT(&dest
));
3327 ok(V_UNKNOWN(&dest
) == (IUnknown
*)stream
, "got pointer %p\n", V_UNKNOWN(&dest
));
3328 ok(ref
+1 == get_refcount(stream
), "expected increased refcount\n");
3329 VariantClear(&dest
);
3331 hr
= ISAXContentHandler_endDocument(content
);
3332 EXPECT_HR(hr
, S_OK
);
3334 IStream_Release(stream
);
3336 /* test char count lower than threshold */
3337 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3338 EXPECT_HR(hr
, S_OK
);
3339 EXPECT_REF(stream
, 1);
3341 hr
= ISAXContentHandler_startDocument(content
);
3342 EXPECT_HR(hr
, S_OK
);
3344 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3345 EXPECT_HR(hr
, S_OK
);
3349 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3350 EXPECT_HR(hr
, S_OK
);
3351 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3353 memset(buff
, 'A', len
);
3355 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
- 8);
3356 EXPECT_HR(hr
, S_OK
);
3360 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3361 EXPECT_HR(hr
, S_OK
);
3362 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3364 hr
= ISAXContentHandler_endDocument(content
);
3365 EXPECT_HR(hr
, S_OK
);
3367 /* test auto-flush function when stream is not set */
3368 V_VT(&dest
) = VT_EMPTY
;
3369 hr
= IMXWriter_put_output(writer
, dest
);
3370 EXPECT_HR(hr
, S_OK
);
3372 hr
= ISAXContentHandler_startDocument(content
);
3373 EXPECT_HR(hr
, S_OK
);
3375 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3376 EXPECT_HR(hr
, S_OK
);
3378 memset(buff
, 'A', len
);
3380 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3381 EXPECT_HR(hr
, S_OK
);
3383 V_VT(&dest
) = VT_EMPTY
;
3384 hr
= IMXWriter_get_output(writer
, &dest
);
3385 EXPECT_HR(hr
, S_OK
);
3386 len
+= strlen("<a>");
3387 ok(SysStringLen(V_BSTR(&dest
)) == len
, "got len=%d, expected %d\n", SysStringLen(V_BSTR(&dest
)), len
);
3388 VariantClear(&dest
);
3390 HeapFree(GetProcessHeap(), 0, buff
);
3391 ISAXContentHandler_Release(content
);
3392 IStream_Release(stream
);
3393 IMXWriter_Release(writer
);
3397 static void test_mxwriter_startenddocument(void)
3399 ISAXContentHandler
*content
;
3404 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3405 &IID_IMXWriter
, (void**)&writer
);
3406 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3408 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3409 ok(hr
== S_OK
, "got %08x\n", hr
);
3411 hr
= ISAXContentHandler_startDocument(content
);
3412 ok(hr
== S_OK
, "got %08x\n", hr
);
3414 hr
= ISAXContentHandler_endDocument(content
);
3415 ok(hr
== S_OK
, "got %08x\n", hr
);
3417 V_VT(&dest
) = VT_EMPTY
;
3418 hr
= IMXWriter_get_output(writer
, &dest
);
3419 ok(hr
== S_OK
, "got %08x\n", hr
);
3420 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3421 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3422 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3423 VariantClear(&dest
);
3425 /* now try another startDocument */
3426 hr
= ISAXContentHandler_startDocument(content
);
3427 ok(hr
== S_OK
, "got %08x\n", hr
);
3428 /* and get duplicated prolog */
3429 V_VT(&dest
) = VT_EMPTY
;
3430 hr
= IMXWriter_get_output(writer
, &dest
);
3431 ok(hr
== S_OK
, "got %08x\n", hr
);
3432 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3433 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
3434 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3435 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3436 VariantClear(&dest
);
3438 ISAXContentHandler_Release(content
);
3439 IMXWriter_Release(writer
);
3441 /* now with omitted declaration */
3442 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3443 &IID_IMXWriter
, (void**)&writer
);
3444 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3446 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3447 ok(hr
== S_OK
, "got %08x\n", hr
);
3449 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3450 ok(hr
== S_OK
, "got %08x\n", hr
);
3452 hr
= ISAXContentHandler_startDocument(content
);
3453 ok(hr
== S_OK
, "got %08x\n", hr
);
3455 hr
= ISAXContentHandler_endDocument(content
);
3456 ok(hr
== S_OK
, "got %08x\n", hr
);
3458 V_VT(&dest
) = VT_EMPTY
;
3459 hr
= IMXWriter_get_output(writer
, &dest
);
3460 ok(hr
== S_OK
, "got %08x\n", hr
);
3461 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3462 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3463 VariantClear(&dest
);
3465 ISAXContentHandler_Release(content
);
3466 IMXWriter_Release(writer
);
3473 StartElement
= 0x001,
3475 StartEndElement
= 0x011,
3476 DisableEscaping
= 0x100
3479 struct writer_startendelement_t
{
3481 enum startendtype type
;
3483 const char *local_name
;
3487 ISAXAttributes
*attr
;
3490 static const char startelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\'\">";
3491 static const char startendelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\'\"/>";
3492 static const char startendelement_noescape_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&\">\'\"/>";
3494 static const struct writer_startendelement_t writer_startendelement
[] = {
3496 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3497 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3498 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3499 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
3500 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3502 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3503 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3504 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
3505 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3506 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3508 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3509 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
3510 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3511 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3512 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3514 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
3515 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3516 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3517 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3518 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3520 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3521 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3522 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3523 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
3524 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3526 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3527 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3528 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3529 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3530 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3532 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3533 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3534 /* endElement tests */
3535 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3536 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3537 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3539 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
3540 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3541 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3542 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3543 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
3545 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3546 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3547 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3548 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
3549 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3551 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3552 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3553 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
3554 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3555 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3557 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3558 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3559 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3560 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3561 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3563 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
3564 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3565 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3566 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3567 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3569 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3570 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3571 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3572 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3574 /* with attributes */
3575 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3577 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3578 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3579 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3580 /* empty elements */
3581 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3582 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3584 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3585 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3586 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
3587 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
3588 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
3590 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
3592 /* with disabled output escaping */
3593 { &CLSID_MXXMLWriter
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3594 { &CLSID_MXXMLWriter30
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3595 { &CLSID_MXXMLWriter40
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3596 { &CLSID_MXXMLWriter60
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3601 static void get_class_support_data(struct msxmlsupported_data_t
*table
, REFIID riid
)
3603 while (table
->clsid
)
3608 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, riid
, (void**)&unk
);
3609 if (hr
== S_OK
) IUnknown_Release(unk
);
3611 table
->supported
= hr
== S_OK
;
3612 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
3618 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
3622 while (table
->clsid
)
3624 ISAXContentHandler
*content
;
3628 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3635 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3636 &IID_IMXWriter
, (void**)&writer
);
3637 EXPECT_HR(hr
, S_OK
);
3639 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3640 EXPECT_HR(hr
, S_OK
);
3642 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3643 EXPECT_HR(hr
, S_OK
);
3645 hr
= ISAXContentHandler_startDocument(content
);
3646 EXPECT_HR(hr
, S_OK
);
3648 if (table
->type
& DisableEscaping
)
3650 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3651 EXPECT_HR(hr
, S_OK
);
3654 if (table
->type
& StartElement
)
3656 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), table
->uri
? strlen(table
->uri
) : 0,
3657 _bstr_(table
->local_name
), table
->local_name
? strlen(table
->local_name
) : 0, _bstr_(table
->qname
),
3658 table
->qname
? strlen(table
->qname
) : 0, table
->attr
);
3659 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3662 if (table
->type
& EndElement
)
3664 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), table
->uri
? strlen(table
->uri
) : 0,
3665 _bstr_(table
->local_name
), table
->local_name
? strlen(table
->local_name
) : 0, _bstr_(table
->qname
),
3666 table
->qname
? strlen(table
->qname
) : 0);
3667 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3675 V_VT(&dest
) = VT_EMPTY
;
3676 hr
= IMXWriter_get_output(writer
, &dest
);
3677 EXPECT_HR(hr
, S_OK
);
3678 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3679 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3680 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3681 VariantClear(&dest
);
3684 ISAXContentHandler_Release(content
);
3685 IMXWriter_Release(writer
);
3694 /* point of these test is to start/end element with different names and name lengths */
3695 struct writer_startendelement2_t
{
3697 const char *qnamestart
;
3699 const char *qnameend
;
3705 static const struct writer_startendelement2_t writer_startendelement2
[] = {
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 /* -1 length is not allowed for version 6 */
3710 { &CLSID_MXXMLWriter60
, "a", -1, "b", -1, "<a/>", E_INVALIDARG
},
3712 { &CLSID_MXXMLWriter
, "a", 1, "b", 1, "<a/>", S_OK
},
3713 { &CLSID_MXXMLWriter30
, "a", 1, "b", 1, "<a/>", S_OK
},
3714 { &CLSID_MXXMLWriter40
, "a", 1, "b", 1, "<a/>", S_OK
},
3715 { &CLSID_MXXMLWriter60
, "a", 1, "b", 1, "<a/>", S_OK
},
3719 static void test_mxwriter_startendelement_batch2(const struct writer_startendelement2_t
*table
)
3723 while (table
->clsid
)
3725 ISAXContentHandler
*content
;
3729 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3736 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3737 &IID_IMXWriter
, (void**)&writer
);
3738 EXPECT_HR(hr
, S_OK
);
3740 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3741 EXPECT_HR(hr
, S_OK
);
3743 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3744 EXPECT_HR(hr
, S_OK
);
3746 hr
= ISAXContentHandler_startDocument(content
);
3747 EXPECT_HR(hr
, S_OK
);
3749 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3750 _bstr_(table
->qnamestart
), table
->qnamestart_len
, NULL
);
3751 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3753 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3754 _bstr_(table
->qnameend
), table
->qnameend_len
);
3755 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3762 V_VT(&dest
) = VT_EMPTY
;
3763 hr
= IMXWriter_get_output(writer
, &dest
);
3764 EXPECT_HR(hr
, S_OK
);
3765 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3766 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3767 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3768 VariantClear(&dest
);
3771 ISAXContentHandler_Release(content
);
3772 IMXWriter_Release(writer
);
3782 static void test_mxwriter_startendelement(void)
3784 ISAXContentHandler
*content
;
3789 test_mxwriter_startendelement_batch(writer_startendelement
);
3790 test_mxwriter_startendelement_batch2(writer_startendelement2
);
3792 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3793 &IID_IMXWriter
, (void**)&writer
);
3794 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3796 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3797 ok(hr
== S_OK
, "got %08x\n", hr
);
3799 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3800 ok(hr
== S_OK
, "got %08x\n", hr
);
3802 hr
= ISAXContentHandler_startDocument(content
);
3803 ok(hr
== S_OK
, "got %08x\n", hr
);
3805 /* all string pointers should be not null */
3806 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
3807 ok(hr
== S_OK
, "got %08x\n", hr
);
3809 V_VT(&dest
) = VT_EMPTY
;
3810 hr
= IMXWriter_get_output(writer
, &dest
);
3811 ok(hr
== S_OK
, "got %08x\n", hr
);
3812 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3813 ok(!lstrcmpW(_bstr_("<>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3814 VariantClear(&dest
);
3816 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
3817 ok(hr
== S_OK
, "got %08x\n", hr
);
3819 V_VT(&dest
) = VT_EMPTY
;
3820 hr
= IMXWriter_get_output(writer
, &dest
);
3821 ok(hr
== S_OK
, "got %08x\n", hr
);
3822 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3823 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3824 VariantClear(&dest
);
3826 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
3827 EXPECT_HR(hr
, E_INVALIDARG
);
3829 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
3830 EXPECT_HR(hr
, E_INVALIDARG
);
3832 /* only local name is an error too */
3833 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
3834 EXPECT_HR(hr
, E_INVALIDARG
);
3836 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
3837 EXPECT_HR(hr
, S_OK
);
3839 V_VT(&dest
) = VT_EMPTY
;
3840 hr
= IMXWriter_get_output(writer
, &dest
);
3841 EXPECT_HR(hr
, S_OK
);
3842 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3843 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3844 VariantClear(&dest
);
3846 hr
= ISAXContentHandler_endDocument(content
);
3847 EXPECT_HR(hr
, S_OK
);
3849 V_VT(&dest
) = VT_EMPTY
;
3850 hr
= IMXWriter_put_output(writer
, dest
);
3851 EXPECT_HR(hr
, S_OK
);
3853 V_VT(&dest
) = VT_EMPTY
;
3854 hr
= IMXWriter_get_output(writer
, &dest
);
3855 EXPECT_HR(hr
, S_OK
);
3856 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3857 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3858 VariantClear(&dest
);
3860 hr
= ISAXContentHandler_startDocument(content
);
3861 EXPECT_HR(hr
, S_OK
);
3863 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
3864 EXPECT_HR(hr
, S_OK
);
3866 V_VT(&dest
) = VT_EMPTY
;
3867 hr
= IMXWriter_get_output(writer
, &dest
);
3868 EXPECT_HR(hr
, S_OK
);
3869 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3870 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3871 VariantClear(&dest
);
3873 hr
= ISAXContentHandler_endDocument(content
);
3874 EXPECT_HR(hr
, S_OK
);
3875 IMXWriter_flush(writer
);
3877 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
3878 EXPECT_HR(hr
, S_OK
);
3879 V_VT(&dest
) = VT_EMPTY
;
3880 hr
= IMXWriter_get_output(writer
, &dest
);
3881 EXPECT_HR(hr
, S_OK
);
3882 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3883 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3884 VariantClear(&dest
);
3886 V_VT(&dest
) = VT_EMPTY
;
3887 hr
= IMXWriter_put_output(writer
, dest
);
3888 EXPECT_HR(hr
, S_OK
);
3891 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), -1, NULL
);
3892 EXPECT_HR(hr
, S_OK
);
3893 V_VT(&dest
) = VT_EMPTY
;
3894 hr
= IMXWriter_get_output(writer
, &dest
);
3895 EXPECT_HR(hr
, S_OK
);
3896 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3897 ok(!lstrcmpW(_bstr_("<a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3898 VariantClear(&dest
);
3900 ISAXContentHandler_Release(content
);
3901 IMXWriter_Release(writer
);
3905 struct writer_characters_t
{
3911 static const struct writer_characters_t writer_characters
[] = {
3912 { &CLSID_MXXMLWriter
, "< > & \" \'", "< > & \" \'" },
3913 { &CLSID_MXXMLWriter30
, "< > & \" \'", "< > & \" \'" },
3914 { &CLSID_MXXMLWriter40
, "< > & \" \'", "< > & \" \'" },
3915 { &CLSID_MXXMLWriter60
, "< > & \" \'", "< > & \" \'" },
3919 static void test_mxwriter_characters(void)
3921 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
3922 const struct writer_characters_t
*table
= writer_characters
;
3923 ISAXContentHandler
*content
;
3929 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3930 &IID_IMXWriter
, (void**)&writer
);
3931 EXPECT_HR(hr
, S_OK
);
3933 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3934 EXPECT_HR(hr
, S_OK
);
3936 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3937 EXPECT_HR(hr
, S_OK
);
3939 hr
= ISAXContentHandler_startDocument(content
);
3940 EXPECT_HR(hr
, S_OK
);
3942 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
3943 EXPECT_HR(hr
, E_INVALIDARG
);
3945 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3946 EXPECT_HR(hr
, S_OK
);
3948 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
3949 EXPECT_HR(hr
, S_OK
);
3951 V_VT(&dest
) = VT_EMPTY
;
3952 hr
= IMXWriter_get_output(writer
, &dest
);
3953 EXPECT_HR(hr
, S_OK
);
3954 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3955 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3956 VariantClear(&dest
);
3958 hr
= ISAXContentHandler_endDocument(content
);
3959 EXPECT_HR(hr
, S_OK
);
3961 ISAXContentHandler_Release(content
);
3962 IMXWriter_Release(writer
);
3964 /* try empty characters data to see if element is closed */
3965 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3966 &IID_IMXWriter
, (void**)&writer
);
3967 EXPECT_HR(hr
, S_OK
);
3969 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3970 EXPECT_HR(hr
, S_OK
);
3972 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3973 EXPECT_HR(hr
, S_OK
);
3975 hr
= ISAXContentHandler_startDocument(content
);
3976 EXPECT_HR(hr
, S_OK
);
3978 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3979 EXPECT_HR(hr
, S_OK
);
3981 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3982 EXPECT_HR(hr
, S_OK
);
3984 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3985 EXPECT_HR(hr
, S_OK
);
3987 V_VT(&dest
) = VT_EMPTY
;
3988 hr
= IMXWriter_get_output(writer
, &dest
);
3989 EXPECT_HR(hr
, S_OK
);
3990 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3991 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3992 VariantClear(&dest
);
3994 ISAXContentHandler_Release(content
);
3995 IMXWriter_Release(writer
);
3998 while (table
->clsid
)
4000 ISAXContentHandler
*content
;
4005 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
4012 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4013 &IID_IMXWriter
, (void**)&writer
);
4014 EXPECT_HR(hr
, S_OK
);
4016 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4017 EXPECT_HR(hr
, S_OK
);
4019 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4020 EXPECT_HR(hr
, S_OK
);
4022 hr
= ISAXContentHandler_startDocument(content
);
4023 EXPECT_HR(hr
, S_OK
);
4025 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
4026 EXPECT_HR(hr
, S_OK
);
4031 V_VT(&dest
) = VT_EMPTY
;
4032 hr
= IMXWriter_get_output(writer
, &dest
);
4033 EXPECT_HR(hr
, S_OK
);
4034 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4035 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
4036 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
4037 VariantClear(&dest
);
4040 /* with disabled escaping */
4041 V_VT(&dest
) = VT_EMPTY
;
4042 hr
= IMXWriter_put_output(writer
, dest
);
4043 EXPECT_HR(hr
, S_OK
);
4045 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
4046 EXPECT_HR(hr
, S_OK
);
4048 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
4049 EXPECT_HR(hr
, S_OK
);
4054 V_VT(&dest
) = VT_EMPTY
;
4055 hr
= IMXWriter_get_output(writer
, &dest
);
4056 EXPECT_HR(hr
, S_OK
);
4057 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4058 ok(!lstrcmpW(_bstr_(table
->data
), V_BSTR(&dest
)),
4059 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->data
);
4060 VariantClear(&dest
);
4063 ISAXContentHandler_Release(content
);
4064 IMXWriter_Release(writer
);
4073 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
4075 VARIANT_TRUE
,"UTF-16",
4077 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
4078 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4083 VARIANT_FALSE
,"UTF-16",
4085 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4090 VARIANT_TRUE
,"UTF-8",
4092 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
4093 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
4094 * and the writer is released.
4101 VARIANT_TRUE
,"utf-8",
4103 {FALSE
,(const BYTE
*)utf8xml2
,sizeof(utf8xml2
)-1},
4104 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
4105 * and the writer is released.
4112 VARIANT_TRUE
,"UTF-16",
4114 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
4115 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4120 VARIANT_TRUE
,"UTF-16",
4122 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
4123 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4129 static void test_mxwriter_stream(void)
4132 ISAXContentHandler
*content
;
4137 ULARGE_INTEGER pos2
;
4138 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
4140 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
4141 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
4143 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4144 &IID_IMXWriter
, (void**)&writer
);
4145 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4147 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4148 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4150 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
4151 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
4153 V_VT(&dest
) = VT_UNKNOWN
;
4154 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
4155 hr
= IMXWriter_put_output(writer
, dest
);
4156 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
4157 VariantClear(&dest
);
4159 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
4160 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
4162 current_write_test
= test
->expected_writes
;
4164 hr
= ISAXContentHandler_startDocument(content
);
4165 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4167 hr
= ISAXContentHandler_endDocument(content
);
4168 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4170 ISAXContentHandler_Release(content
);
4171 IMXWriter_Release(writer
);
4173 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
4174 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
4177 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4178 &IID_IMXWriter
, (void**)&writer
);
4179 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4181 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4182 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
4184 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4185 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4187 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4188 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
4190 V_VT(&dest
) = VT_UNKNOWN
;
4191 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4192 hr
= IMXWriter_put_output(writer
, dest
);
4193 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4195 hr
= ISAXContentHandler_startDocument(content
);
4196 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4198 /* Setting output of the mxwriter causes the current output to be flushed,
4199 * and the writer to start over.
4201 V_VT(&dest
) = VT_EMPTY
;
4202 hr
= IMXWriter_put_output(writer
, dest
);
4203 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4206 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4207 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
4208 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
4210 hr
= ISAXContentHandler_startDocument(content
);
4211 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4213 hr
= ISAXContentHandler_endDocument(content
);
4214 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
4216 V_VT(&dest
) = VT_EMPTY
;
4217 hr
= IMXWriter_get_output(writer
, &dest
);
4218 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
4219 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4220 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4221 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4222 VariantClear(&dest
);
4224 /* test when BOM is written to output stream */
4225 V_VT(&dest
) = VT_EMPTY
;
4226 hr
= IMXWriter_put_output(writer
, dest
);
4227 EXPECT_HR(hr
, S_OK
);
4230 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
4231 EXPECT_HR(hr
, S_OK
);
4233 V_VT(&dest
) = VT_UNKNOWN
;
4234 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4235 hr
= IMXWriter_put_output(writer
, dest
);
4236 EXPECT_HR(hr
, S_OK
);
4238 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_TRUE
);
4239 EXPECT_HR(hr
, S_OK
);
4241 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4242 EXPECT_HR(hr
, S_OK
);
4244 hr
= ISAXContentHandler_startDocument(content
);
4245 EXPECT_HR(hr
, S_OK
);
4249 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4250 EXPECT_HR(hr
, S_OK
);
4251 ok(pos2
.QuadPart
== 2, "got wrong position\n");
4253 IStream_Release(stream
);
4254 ISAXContentHandler_Release(content
);
4255 IMXWriter_Release(writer
);
4260 static const char *encoding_names
[] = {
4273 static void test_mxwriter_encoding(void)
4275 ISAXContentHandler
*content
;
4286 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4287 &IID_IMXWriter
, (void**)&writer
);
4288 EXPECT_HR(hr
, S_OK
);
4290 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4291 EXPECT_HR(hr
, S_OK
);
4293 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4294 EXPECT_HR(hr
, S_OK
);
4296 hr
= ISAXContentHandler_startDocument(content
);
4297 EXPECT_HR(hr
, S_OK
);
4299 hr
= ISAXContentHandler_endDocument(content
);
4300 EXPECT_HR(hr
, S_OK
);
4302 /* The content is always re-encoded to UTF-16 when the output is
4303 * retrieved as a BSTR.
4305 V_VT(&dest
) = VT_EMPTY
;
4306 hr
= IMXWriter_get_output(writer
, &dest
);
4307 EXPECT_HR(hr
, S_OK
);
4308 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4309 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4310 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4311 VariantClear(&dest
);
4313 /* switch encoding when something is written already */
4314 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4315 EXPECT_HR(hr
, S_OK
);
4317 V_VT(&dest
) = VT_UNKNOWN
;
4318 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4319 hr
= IMXWriter_put_output(writer
, dest
);
4320 EXPECT_HR(hr
, S_OK
);
4322 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4323 EXPECT_HR(hr
, S_OK
);
4325 /* write empty element */
4326 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
4327 EXPECT_HR(hr
, S_OK
);
4329 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
4330 EXPECT_HR(hr
, S_OK
);
4333 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4334 EXPECT_HR(hr
, S_OK
);
4336 hr
= IMXWriter_flush(writer
);
4337 EXPECT_HR(hr
, S_OK
);
4339 hr
= GetHGlobalFromStream(stream
, &g
);
4340 EXPECT_HR(hr
, S_OK
);
4342 ptr
= GlobalLock(g
);
4343 ok(!strncmp(ptr
, "<a/>", 4), "got %c%c%c%c\n", ptr
[0],ptr
[1],ptr
[2],ptr
[3]);
4346 /* so output is unaffected, encoding name is stored however */
4347 hr
= IMXWriter_get_encoding(writer
, &s
);
4348 EXPECT_HR(hr
, S_OK
);
4349 ok(!lstrcmpW(s
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(s
));
4352 IStream_Release(stream
);
4355 enc
= encoding_names
[i
];
4358 char expectedA
[200];
4360 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4361 EXPECT_HR(hr
, S_OK
);
4363 V_VT(&dest
) = VT_UNKNOWN
;
4364 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4365 hr
= IMXWriter_put_output(writer
, dest
);
4366 EXPECT_HR(hr
, S_OK
);
4368 hr
= IMXWriter_put_encoding(writer
, _bstr_(enc
));
4369 ok(hr
== S_OK
|| broken(hr
!= S_OK
) /* old win versions do not support certain encodings */,
4370 "%s: encoding not accepted\n", enc
);
4373 enc
= encoding_names
[++i
];
4374 IStream_Release(stream
);
4378 hr
= ISAXContentHandler_startDocument(content
);
4379 EXPECT_HR(hr
, S_OK
);
4381 hr
= ISAXContentHandler_endDocument(content
);
4382 EXPECT_HR(hr
, S_OK
);
4384 hr
= IMXWriter_flush(writer
);
4385 EXPECT_HR(hr
, S_OK
);
4387 /* prepare expected string */
4389 strcat(expectedA
, "<?xml version=\"1.0\" encoding=\"");
4390 strcat(expectedA
, enc
);
4391 strcat(expectedA
, "\" standalone=\"no\"?>\r\n");
4393 hr
= GetHGlobalFromStream(stream
, &g
);
4394 EXPECT_HR(hr
, S_OK
);
4396 ptr
= GlobalLock(g
);
4397 ok(!strncmp(ptr
, expectedA
, strlen(expectedA
)), "%s: got %s, expected %.50s\n", enc
, ptr
, expectedA
);
4400 V_VT(&dest
) = VT_EMPTY
;
4401 hr
= IMXWriter_put_output(writer
, dest
);
4402 EXPECT_HR(hr
, S_OK
);
4404 IStream_Release(stream
);
4406 enc
= encoding_names
[++i
];
4409 ISAXContentHandler_Release(content
);
4410 IMXWriter_Release(writer
);
4415 static void test_obj_dispex(IUnknown
*obj
)
4417 static const WCHAR testW
[] = {'t','e','s','t','p','r','o','p',0};
4418 static const WCHAR starW
[] = {'*',0};
4419 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
4420 IDispatchEx
*dispex
;
4428 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
4429 EXPECT_HR(hr
, S_OK
);
4430 if (FAILED(hr
)) return;
4433 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
4434 EXPECT_HR(hr
, S_OK
);
4435 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
4437 name
= SysAllocString(starW
);
4438 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
4439 EXPECT_HR(hr
, E_NOTIMPL
);
4440 SysFreeString(name
);
4442 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
4443 EXPECT_HR(hr
, E_NOTIMPL
);
4446 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
4447 EXPECT_HR(hr
, E_NOTIMPL
);
4448 ok(props
== 0, "expected 0 got %d\n", props
);
4450 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
4451 EXPECT_HR(hr
, E_NOTIMPL
);
4452 if (SUCCEEDED(hr
)) SysFreeString(name
);
4454 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
4455 EXPECT_HR(hr
, E_NOTIMPL
);
4457 unk
= (IUnknown
*)0xdeadbeef;
4458 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
4459 EXPECT_HR(hr
, E_NOTIMPL
);
4460 ok(unk
== (IUnknown
*)0xdeadbeef, "got %p\n", unk
);
4462 name
= SysAllocString(testW
);
4463 hr
= IDispatchEx_GetDispID(dispex
, name
, fdexNameEnsure
, &did
);
4464 ok(hr
== DISP_E_UNKNOWNNAME
, "got 0x%08x\n", hr
);
4465 SysFreeString(name
);
4467 IDispatchEx_Release(dispex
);
4470 static void test_saxreader_dispex(void)
4472 IVBSAXXMLReader
*vbreader
;
4473 ISAXXMLReader
*reader
;
4474 DISPPARAMS dispparams
;
4480 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
4481 &IID_ISAXXMLReader
, (void**)&reader
);
4482 EXPECT_HR(hr
, S_OK
);
4484 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
4485 EXPECT_HR(hr
, S_OK
);
4486 test_obj_dispex(unk
);
4487 IUnknown_Release(unk
);
4489 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
4490 EXPECT_HR(hr
, S_OK
);
4491 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
4492 EXPECT_HR(hr
, S_OK
);
4493 test_obj_dispex(unk
);
4494 IUnknown_Release(unk
);
4496 dispid
= DISPID_PROPERTYPUT
;
4497 dispparams
.cArgs
= 1;
4498 dispparams
.cNamedArgs
= 1;
4499 dispparams
.rgdispidNamedArgs
= &dispid
;
4500 dispparams
.rgvarg
= &arg
;
4502 V_VT(&arg
) = VT_DISPATCH
;
4503 V_DISPATCH(&arg
) = NULL
;
4505 /* propputref is callable as PROPERTYPUT and PROPERTYPUTREF */
4506 hr
= IVBSAXXMLReader_Invoke(vbreader
,
4507 DISPID_SAX_XMLREADER_CONTENTHANDLER
,
4510 DISPATCH_PROPERTYPUT
,
4515 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4517 hr
= IVBSAXXMLReader_Invoke(vbreader
,
4518 DISPID_SAX_XMLREADER_CONTENTHANDLER
,
4521 DISPATCH_PROPERTYPUTREF
,
4526 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4528 IVBSAXXMLReader_Release(vbreader
);
4529 ISAXXMLReader_Release(reader
);
4531 if (is_clsid_supported(&CLSID_SAXXMLReader60
, reader_support_data
))
4533 hr
= CoCreateInstance(&CLSID_SAXXMLReader60
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&unk
);
4534 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4535 test_obj_dispex(unk
);
4536 IUnknown_Release(unk
);
4540 static void test_mxwriter_dispex(void)
4542 IDispatchEx
*dispex
;
4547 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4548 &IID_IMXWriter
, (void**)&writer
);
4549 EXPECT_HR(hr
, S_OK
);
4551 hr
= IMXWriter_QueryInterface(writer
, &IID_IDispatchEx
, (void**)&dispex
);
4552 EXPECT_HR(hr
, S_OK
);
4553 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4554 test_obj_dispex(unk
);
4555 IUnknown_Release(unk
);
4556 IDispatchEx_Release(dispex
);
4557 IMXWriter_Release(writer
);
4559 if (is_clsid_supported(&CLSID_MXXMLWriter60
, mxwriter_support_data
))
4561 hr
= CoCreateInstance(&CLSID_MXXMLWriter60
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&unk
);
4562 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4563 test_obj_dispex(unk
);
4564 IUnknown_Release(unk
);
4568 static void test_mxwriter_comment(void)
4570 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
4571 IVBSAXLexicalHandler
*vblexical
;
4572 ISAXContentHandler
*content
;
4573 ISAXLexicalHandler
*lexical
;
4578 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4579 &IID_IMXWriter
, (void**)&writer
);
4580 EXPECT_HR(hr
, S_OK
);
4582 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4583 EXPECT_HR(hr
, S_OK
);
4585 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4586 EXPECT_HR(hr
, S_OK
);
4588 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4589 EXPECT_HR(hr
, S_OK
);
4591 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4592 EXPECT_HR(hr
, S_OK
);
4594 hr
= ISAXContentHandler_startDocument(content
);
4595 EXPECT_HR(hr
, S_OK
);
4597 hr
= ISAXLexicalHandler_comment(lexical
, NULL
, 0);
4598 EXPECT_HR(hr
, E_INVALIDARG
);
4600 hr
= IVBSAXLexicalHandler_comment(vblexical
, NULL
);
4601 EXPECT_HR(hr
, E_POINTER
);
4603 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, 0);
4604 EXPECT_HR(hr
, S_OK
);
4606 V_VT(&dest
) = VT_EMPTY
;
4607 hr
= IMXWriter_get_output(writer
, &dest
);
4608 EXPECT_HR(hr
, S_OK
);
4609 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4610 ok(!lstrcmpW(_bstr_("<!---->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4611 VariantClear(&dest
);
4613 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, sizeof(commentW
)/sizeof(WCHAR
)-1);
4614 EXPECT_HR(hr
, S_OK
);
4616 V_VT(&dest
) = VT_EMPTY
;
4617 hr
= IMXWriter_get_output(writer
, &dest
);
4618 EXPECT_HR(hr
, S_OK
);
4619 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4620 ok(!lstrcmpW(_bstr_("<!---->\r\n<!--comment-->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4621 VariantClear(&dest
);
4623 ISAXContentHandler_Release(content
);
4624 ISAXLexicalHandler_Release(lexical
);
4625 IVBSAXLexicalHandler_Release(vblexical
);
4626 IMXWriter_Release(writer
);
4630 static void test_mxwriter_cdata(void)
4632 IVBSAXLexicalHandler
*vblexical
;
4633 ISAXContentHandler
*content
;
4634 ISAXLexicalHandler
*lexical
;
4639 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4640 &IID_IMXWriter
, (void**)&writer
);
4641 EXPECT_HR(hr
, S_OK
);
4643 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4644 EXPECT_HR(hr
, S_OK
);
4646 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4647 EXPECT_HR(hr
, S_OK
);
4649 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4650 EXPECT_HR(hr
, S_OK
);
4652 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4653 EXPECT_HR(hr
, S_OK
);
4655 hr
= ISAXContentHandler_startDocument(content
);
4656 EXPECT_HR(hr
, S_OK
);
4658 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4659 EXPECT_HR(hr
, S_OK
);
4661 V_VT(&dest
) = VT_EMPTY
;
4662 hr
= IMXWriter_get_output(writer
, &dest
);
4663 EXPECT_HR(hr
, S_OK
);
4664 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4665 ok(!lstrcmpW(_bstr_("<![CDATA["), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4666 VariantClear(&dest
);
4668 hr
= IVBSAXLexicalHandler_startCDATA(vblexical
);
4669 EXPECT_HR(hr
, S_OK
);
4671 /* all these are escaped for text nodes */
4672 hr
= ISAXContentHandler_characters(content
, _bstr_("< > & \""), 7);
4673 EXPECT_HR(hr
, S_OK
);
4675 hr
= ISAXLexicalHandler_endCDATA(lexical
);
4676 EXPECT_HR(hr
, S_OK
);
4678 V_VT(&dest
) = VT_EMPTY
;
4679 hr
= IMXWriter_get_output(writer
, &dest
);
4680 EXPECT_HR(hr
, S_OK
);
4681 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4682 ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4683 VariantClear(&dest
);
4685 ISAXContentHandler_Release(content
);
4686 ISAXLexicalHandler_Release(lexical
);
4687 IVBSAXLexicalHandler_Release(vblexical
);
4688 IMXWriter_Release(writer
);
4692 static void test_mxwriter_pi(void)
4694 static const WCHAR targetW
[] = {'t','a','r','g','e','t',0};
4695 static const WCHAR dataW
[] = {'d','a','t','a',0};
4696 ISAXContentHandler
*content
;
4701 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4702 &IID_IMXWriter
, (void**)&writer
);
4703 EXPECT_HR(hr
, S_OK
);
4705 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4706 EXPECT_HR(hr
, S_OK
);
4708 hr
= ISAXContentHandler_processingInstruction(content
, NULL
, 0, NULL
, 0);
4709 EXPECT_HR(hr
, E_INVALIDARG
);
4711 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 0, NULL
, 0);
4712 EXPECT_HR(hr
, S_OK
);
4714 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, NULL
, 0);
4715 EXPECT_HR(hr
, S_OK
);
4717 V_VT(&dest
) = VT_EMPTY
;
4718 hr
= IMXWriter_get_output(writer
, &dest
);
4719 EXPECT_HR(hr
, S_OK
);
4720 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4721 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4722 VariantClear(&dest
);
4724 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 4, dataW
, 4);
4725 EXPECT_HR(hr
, S_OK
);
4727 V_VT(&dest
) = VT_EMPTY
;
4728 hr
= IMXWriter_get_output(writer
, &dest
);
4729 EXPECT_HR(hr
, S_OK
);
4730 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4731 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
)));
4732 VariantClear(&dest
);
4734 V_VT(&dest
) = VT_EMPTY
;
4735 hr
= IMXWriter_put_output(writer
, dest
);
4736 EXPECT_HR(hr
, S_OK
);
4738 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, dataW
, 0);
4739 EXPECT_HR(hr
, S_OK
);
4741 V_VT(&dest
) = VT_EMPTY
;
4742 hr
= IMXWriter_get_output(writer
, &dest
);
4743 EXPECT_HR(hr
, S_OK
);
4744 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4745 ok(!lstrcmpW(_bstr_("<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4746 VariantClear(&dest
);
4749 ISAXContentHandler_Release(content
);
4750 IMXWriter_Release(writer
);
4753 static void test_mxwriter_ignorablespaces(void)
4755 static const WCHAR dataW
[] = {'d','a','t','a',0};
4756 ISAXContentHandler
*content
;
4761 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4762 &IID_IMXWriter
, (void**)&writer
);
4763 EXPECT_HR(hr
, S_OK
);
4765 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4766 EXPECT_HR(hr
, S_OK
);
4768 hr
= ISAXContentHandler_ignorableWhitespace(content
, NULL
, 0);
4769 EXPECT_HR(hr
, E_INVALIDARG
);
4771 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 0);
4772 EXPECT_HR(hr
, S_OK
);
4774 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 4);
4775 EXPECT_HR(hr
, S_OK
);
4777 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 1);
4778 EXPECT_HR(hr
, S_OK
);
4780 V_VT(&dest
) = VT_EMPTY
;
4781 hr
= IMXWriter_get_output(writer
, &dest
);
4782 EXPECT_HR(hr
, S_OK
);
4783 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4784 ok(!lstrcmpW(_bstr_("datad"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4785 VariantClear(&dest
);
4787 ISAXContentHandler_Release(content
);
4788 IMXWriter_Release(writer
);
4791 static void test_mxwriter_dtd(void)
4793 static const WCHAR contentW
[] = {'c','o','n','t','e','n','t'};
4794 static const WCHAR nameW
[] = {'n','a','m','e'};
4795 static const WCHAR pubW
[] = {'p','u','b'};
4796 static const WCHAR sysW
[] = {'s','y','s'};
4797 IVBSAXLexicalHandler
*vblexical
;
4798 ISAXContentHandler
*content
;
4799 ISAXLexicalHandler
*lexical
;
4800 IVBSAXDeclHandler
*vbdecl
;
4801 ISAXDeclHandler
*decl
;
4806 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4807 &IID_IMXWriter
, (void**)&writer
);
4808 EXPECT_HR(hr
, S_OK
);
4810 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4811 EXPECT_HR(hr
, S_OK
);
4813 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4814 EXPECT_HR(hr
, S_OK
);
4816 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
4817 EXPECT_HR(hr
, S_OK
);
4819 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXDeclHandler
, (void**)&vbdecl
);
4820 EXPECT_HR(hr
, S_OK
);
4822 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4823 EXPECT_HR(hr
, S_OK
);
4825 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4826 EXPECT_HR(hr
, S_OK
);
4828 hr
= ISAXContentHandler_startDocument(content
);
4829 EXPECT_HR(hr
, S_OK
);
4831 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, NULL
, 0);
4832 EXPECT_HR(hr
, E_INVALIDARG
);
4834 hr
= IVBSAXLexicalHandler_startDTD(vblexical
, NULL
, NULL
, NULL
);
4835 EXPECT_HR(hr
, E_POINTER
);
4837 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4838 EXPECT_HR(hr
, E_INVALIDARG
);
4840 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4841 EXPECT_HR(hr
, E_INVALIDARG
);
4843 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4844 EXPECT_HR(hr
, E_INVALIDARG
);
4846 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0, NULL
, 0);
4847 EXPECT_HR(hr
, S_OK
);
4849 V_VT(&dest
) = VT_EMPTY
;
4850 hr
= IMXWriter_get_output(writer
, &dest
);
4851 EXPECT_HR(hr
, S_OK
);
4852 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4853 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4854 VariantClear(&dest
);
4856 /* system id is required if public is present */
4857 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4858 EXPECT_HR(hr
, E_INVALIDARG
);
4860 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
),
4861 pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4862 EXPECT_HR(hr
, S_OK
);
4864 V_VT(&dest
) = VT_EMPTY
;
4865 hr
= IMXWriter_get_output(writer
, &dest
);
4866 EXPECT_HR(hr
, S_OK
);
4867 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4868 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4869 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4870 VariantClear(&dest
);
4872 hr
= ISAXLexicalHandler_endDTD(lexical
);
4873 EXPECT_HR(hr
, S_OK
);
4875 hr
= IVBSAXLexicalHandler_endDTD(vblexical
);
4876 EXPECT_HR(hr
, S_OK
);
4878 V_VT(&dest
) = VT_EMPTY
;
4879 hr
= IMXWriter_get_output(writer
, &dest
);
4880 EXPECT_HR(hr
, S_OK
);
4881 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4882 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4883 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n"),
4884 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4885 VariantClear(&dest
);
4887 /* element declaration */
4888 V_VT(&dest
) = VT_EMPTY
;
4889 hr
= IMXWriter_put_output(writer
, dest
);
4890 EXPECT_HR(hr
, S_OK
);
4892 hr
= ISAXDeclHandler_elementDecl(decl
, NULL
, 0, NULL
, 0);
4893 EXPECT_HR(hr
, E_INVALIDARG
);
4895 hr
= IVBSAXDeclHandler_elementDecl(vbdecl
, NULL
, NULL
);
4896 EXPECT_HR(hr
, E_POINTER
);
4898 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0);
4899 EXPECT_HR(hr
, E_INVALIDARG
);
4901 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, sizeof(contentW
)/sizeof(WCHAR
));
4902 EXPECT_HR(hr
, S_OK
);
4904 V_VT(&dest
) = VT_EMPTY
;
4905 hr
= IMXWriter_get_output(writer
, &dest
);
4906 EXPECT_HR(hr
, S_OK
);
4907 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4908 ok(!lstrcmpW(_bstr_("<!ELEMENT name content>\r\n"),
4909 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4910 VariantClear(&dest
);
4912 V_VT(&dest
) = VT_EMPTY
;
4913 hr
= IMXWriter_put_output(writer
, dest
);
4914 EXPECT_HR(hr
, S_OK
);
4916 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, 0);
4917 EXPECT_HR(hr
, S_OK
);
4919 V_VT(&dest
) = VT_EMPTY
;
4920 hr
= IMXWriter_get_output(writer
, &dest
);
4921 EXPECT_HR(hr
, S_OK
);
4922 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4923 ok(!lstrcmpW(_bstr_("<!ELEMENT name >\r\n"),
4924 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4925 VariantClear(&dest
);
4927 /* attribute declaration */
4928 V_VT(&dest
) = VT_EMPTY
;
4929 hr
= IMXWriter_put_output(writer
, dest
);
4930 EXPECT_HR(hr
, S_OK
);
4932 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4933 _bstr_("attribute"), strlen("attribute"), _bstr_("CDATA"), strlen("CDATA"),
4934 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value"), strlen("value"));
4935 EXPECT_HR(hr
, S_OK
);
4937 V_VT(&dest
) = VT_EMPTY
;
4938 hr
= IMXWriter_get_output(writer
, &dest
);
4939 EXPECT_HR(hr
, S_OK
);
4940 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4941 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"),
4942 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4943 VariantClear(&dest
);
4945 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4946 _bstr_("attribute2"), strlen("attribute2"), _bstr_("CDATA"), strlen("CDATA"),
4947 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value2"), strlen("value2"));
4948 EXPECT_HR(hr
, S_OK
);
4950 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element2"), strlen("element2"),
4951 _bstr_("attribute3"), strlen("attribute3"), _bstr_("CDATA"), strlen("CDATA"),
4952 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value3"), strlen("value3"));
4953 EXPECT_HR(hr
, S_OK
);
4955 V_VT(&dest
) = VT_EMPTY
;
4956 hr
= IMXWriter_get_output(writer
, &dest
);
4957 EXPECT_HR(hr
, S_OK
);
4958 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4959 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"
4960 "<!ATTLIST element attribute2 CDATA #REQUIRED \"value2\">\r\n"
4961 "<!ATTLIST element2 attribute3 CDATA #REQUIRED \"value3\">\r\n"),
4962 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4963 VariantClear(&dest
);
4965 /* internal entities */
4966 V_VT(&dest
) = VT_EMPTY
;
4967 hr
= IMXWriter_put_output(writer
, dest
);
4968 EXPECT_HR(hr
, S_OK
);
4970 hr
= ISAXDeclHandler_internalEntityDecl(decl
, NULL
, 0, NULL
, 0);
4971 EXPECT_HR(hr
, E_INVALIDARG
);
4973 hr
= IVBSAXDeclHandler_internalEntityDecl(vbdecl
, NULL
, NULL
);
4974 EXPECT_HR(hr
, E_POINTER
);
4976 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0);
4977 EXPECT_HR(hr
, E_INVALIDARG
);
4979 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("value"), strlen("value"));
4980 EXPECT_HR(hr
, S_OK
);
4982 V_VT(&dest
) = VT_EMPTY
;
4983 hr
= IMXWriter_get_output(writer
, &dest
);
4984 EXPECT_HR(hr
, S_OK
);
4985 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4986 ok(!lstrcmpW(_bstr_("<!ENTITY name \"value\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4987 VariantClear(&dest
);
4989 /* external entities */
4990 V_VT(&dest
) = VT_EMPTY
;
4991 hr
= IMXWriter_put_output(writer
, dest
);
4992 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4994 hr
= ISAXDeclHandler_externalEntityDecl(decl
, NULL
, 0, NULL
, 0, NULL
, 0);
4995 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4997 hr
= IVBSAXDeclHandler_externalEntityDecl(vbdecl
, NULL
, NULL
, NULL
);
4998 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
5000 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0, NULL
, 0);
5001 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5003 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"),
5004 _bstr_("sysid"), strlen("sysid"));
5005 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5007 V_VT(&dest
) = VT_EMPTY
;
5008 hr
= IMXWriter_get_output(writer
, &dest
);
5009 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5010 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
5011 ok(!lstrcmpW(_bstr_("<!ENTITY name PUBLIC \"pubid\" \"sysid\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
5012 VariantClear(&dest
);
5014 ISAXContentHandler_Release(content
);
5015 ISAXLexicalHandler_Release(lexical
);
5016 IVBSAXLexicalHandler_Release(vblexical
);
5017 IVBSAXDeclHandler_Release(vbdecl
);
5018 ISAXDeclHandler_Release(decl
);
5019 IMXWriter_Release(writer
);
5031 } addattribute_test_t
;
5033 static const addattribute_test_t addattribute_data
[] = {
5034 { &CLSID_SAXAttributes
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5035 { &CLSID_SAXAttributes30
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5036 { &CLSID_SAXAttributes40
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5037 { &CLSID_SAXAttributes60
, NULL
, NULL
, "ns:qname", NULL
, "value", S_OK
},
5039 { &CLSID_SAXAttributes
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5040 { &CLSID_SAXAttributes30
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5041 { &CLSID_SAXAttributes40
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5042 { &CLSID_SAXAttributes60
, NULL
, "qname", "ns:qname", NULL
, "value", S_OK
},
5044 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5045 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5046 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5047 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", NULL
, "value", S_OK
},
5049 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5050 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5051 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5052 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5057 static void test_mxattr_addAttribute(void)
5059 const addattribute_test_t
*table
= addattribute_data
;
5062 while (table
->clsid
)
5064 ISAXAttributes
*saxattr
;
5065 IMXAttributes
*mxattr
;
5070 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5077 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5078 &IID_IMXAttributes
, (void**)&mxattr
);
5079 EXPECT_HR(hr
, S_OK
);
5081 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5082 EXPECT_HR(hr
, S_OK
);
5084 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
5085 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5086 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5088 hr
= ISAXAttributes_getLength(saxattr
, NULL
);
5089 EXPECT_HR(hr
, E_POINTER
);
5093 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5094 EXPECT_HR(hr
, S_OK
);
5095 ok(len
== 0, "got %d\n", len
);
5097 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
5098 EXPECT_HR(hr
, E_INVALIDARG
);
5100 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
5101 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5103 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
5104 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5106 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
5107 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5109 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
5110 EXPECT_HR(hr
, E_INVALIDARG
);
5112 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
5113 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5115 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
5116 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5118 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
5119 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5121 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_(table
->uri
), _bstr_(table
->local
),
5122 _bstr_(table
->qname
), _bstr_(table
->type
), _bstr_(table
->value
));
5123 ok(hr
== table
->hr
, "%d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
5127 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
5128 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5129 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5131 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
5132 EXPECT_HR(hr
, E_POINTER
);
5134 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
5135 EXPECT_HR(hr
, E_POINTER
);
5137 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
5138 EXPECT_HR(hr
, E_POINTER
);
5140 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
5141 EXPECT_HR(hr
, E_POINTER
);
5143 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
5144 EXPECT_HR(hr
, E_POINTER
);
5146 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
5147 EXPECT_HR(hr
, E_POINTER
);
5151 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
5152 EXPECT_HR(hr
, S_OK
);
5153 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5155 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5158 value
= (void*)0xdeadbeef;
5159 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
5160 EXPECT_HR(hr
, S_OK
);
5164 ok(!lstrcmpW(_bstr_(table
->type
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5166 ok(lstrlenW(value
) == len
, "%d: got wrong type value length %d\n", i
, len
);
5170 ok(*value
== 0, "%d: got type value %s\n", i
, wine_dbgstr_w(value
));
5171 ok(len
== 0, "%d: got wrong type value length %d\n", i
, len
);
5174 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, NULL
);
5175 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5176 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5178 EXPECT_HR(hr
, E_POINTER
);
5181 EXPECT_HR(hr
, E_INVALIDARG
);
5183 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, &index
);
5184 EXPECT_HR(hr
, E_INVALIDARG
);
5187 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_("nonexistent"), 11, &index
);
5188 EXPECT_HR(hr
, E_INVALIDARG
);
5189 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5192 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), 0, &index
);
5193 EXPECT_HR(hr
, E_INVALIDARG
);
5194 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5197 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &index
);
5198 EXPECT_HR(hr
, S_OK
);
5199 ok(index
== 0, "%d: got wrong index %d\n", i
, index
);
5202 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
)-1, &index
);
5203 EXPECT_HR(hr
, E_INVALIDARG
);
5204 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5206 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes40
) ||
5207 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes60
))
5209 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
5210 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5212 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
5213 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5215 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
5216 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5218 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
5219 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5221 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
5222 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5224 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
5225 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5229 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
5230 EXPECT_HR(hr
, E_POINTER
);
5232 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
5233 EXPECT_HR(hr
, E_POINTER
);
5235 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
5236 EXPECT_HR(hr
, E_POINTER
);
5238 /* versions 4 and 6 crash */
5239 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, NULL
);
5240 EXPECT_HR(hr
, E_POINTER
);
5242 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, &len
);
5243 EXPECT_HR(hr
, E_POINTER
);
5245 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
5246 EXPECT_HR(hr
, E_POINTER
);
5248 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
5249 EXPECT_HR(hr
, E_POINTER
);
5251 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
5252 EXPECT_HR(hr
, E_POINTER
);
5254 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, &value
, NULL
);
5255 EXPECT_HR(hr
, E_POINTER
);
5257 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, NULL
, &len
);
5258 EXPECT_HR(hr
, E_POINTER
);
5260 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
), _bstr_(table
->local
),
5261 strlen(table
->local
), NULL
, NULL
);
5262 EXPECT_HR(hr
, E_POINTER
);
5265 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &value
, &len
);
5266 EXPECT_HR(hr
, S_OK
);
5267 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5269 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5272 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
),
5273 _bstr_(table
->local
), strlen(table
->local
), &value
, &len
);
5274 EXPECT_HR(hr
, S_OK
);
5275 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5277 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5282 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5283 EXPECT_HR(hr
, S_OK
);
5284 if (table
->hr
== S_OK
)
5285 ok(len
== 1, "%d: got %d length, expected 1\n", i
, len
);
5287 ok(len
== 0, "%d: got %d length, expected 0\n", i
, len
);
5289 ISAXAttributes_Release(saxattr
);
5290 IMXAttributes_Release(mxattr
);
5299 static void test_mxattr_clear(void)
5301 ISAXAttributes
*saxattr
;
5302 IMXAttributes
*mxattr
;
5307 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5308 &IID_IMXAttributes
, (void**)&mxattr
);
5309 EXPECT_HR(hr
, S_OK
);
5311 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5312 EXPECT_HR(hr
, S_OK
);
5314 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, NULL
);
5315 EXPECT_HR(hr
, E_INVALIDARG
);
5317 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5318 EXPECT_HR(hr
, E_INVALIDARG
);
5320 hr
= IMXAttributes_clear(mxattr
);
5321 EXPECT_HR(hr
, S_OK
);
5323 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("local"),
5324 _bstr_("qname"), _bstr_("type"), _bstr_("value"));
5325 EXPECT_HR(hr
, S_OK
);
5328 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5329 EXPECT_HR(hr
, S_OK
);
5330 ok(len
== 1, "got %d\n", len
);
5333 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, &len
);
5334 EXPECT_HR(hr
, E_POINTER
);
5335 ok(len
== -1, "got %d\n", len
);
5337 ptr
= (void*)0xdeadbeef;
5338 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, NULL
);
5339 EXPECT_HR(hr
, E_POINTER
);
5340 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5343 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5344 EXPECT_HR(hr
, S_OK
);
5345 ok(len
== 5, "got %d\n", len
);
5346 ok(!lstrcmpW(ptr
, _bstr_("qname")), "got %s\n", wine_dbgstr_w(ptr
));
5348 hr
= IMXAttributes_clear(mxattr
);
5349 EXPECT_HR(hr
, S_OK
);
5352 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5353 EXPECT_HR(hr
, S_OK
);
5354 ok(len
== 0, "got %d\n", len
);
5357 ptr
= (void*)0xdeadbeef;
5358 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5359 EXPECT_HR(hr
, E_INVALIDARG
);
5360 ok(len
== -1, "got %d\n", len
);
5361 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5363 IMXAttributes_Release(mxattr
);
5364 ISAXAttributes_Release(saxattr
);
5368 static void test_mxattr_dispex(void)
5370 IMXAttributes
*mxattr
;
5371 IDispatchEx
*dispex
;
5375 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5376 &IID_IMXAttributes
, (void**)&mxattr
);
5377 EXPECT_HR(hr
, S_OK
);
5379 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IDispatchEx
, (void**)&dispex
);
5380 EXPECT_HR(hr
, S_OK
);
5381 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
5382 test_obj_dispex(unk
);
5383 IUnknown_Release(unk
);
5384 IDispatchEx_Release(dispex
);
5386 IMXAttributes_Release(mxattr
);
5389 static void test_mxattr_qi(void)
5391 IVBSAXAttributes
*vbsaxattr
, *vbsaxattr2
;
5392 ISAXAttributes
*saxattr
;
5393 IMXAttributes
*mxattr
;
5396 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5397 &IID_IMXAttributes
, (void**)&mxattr
);
5398 EXPECT_HR(hr
, S_OK
);
5400 EXPECT_REF(mxattr
, 1);
5401 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5402 EXPECT_HR(hr
, S_OK
);
5404 EXPECT_REF(mxattr
, 2);
5405 EXPECT_REF(saxattr
, 2);
5407 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr
);
5408 EXPECT_HR(hr
, S_OK
);
5410 EXPECT_REF(vbsaxattr
, 3);
5411 EXPECT_REF(mxattr
, 3);
5412 EXPECT_REF(saxattr
, 3);
5414 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr2
);
5415 EXPECT_HR(hr
, S_OK
);
5417 EXPECT_REF(vbsaxattr
, 4);
5418 EXPECT_REF(mxattr
, 4);
5419 EXPECT_REF(saxattr
, 4);
5421 IMXAttributes_Release(mxattr
);
5422 ISAXAttributes_Release(saxattr
);
5423 IVBSAXAttributes_Release(vbsaxattr
);
5424 IVBSAXAttributes_Release(vbsaxattr2
);
5427 static struct msxmlsupported_data_t saxattr_support_data
[] =
5429 { &CLSID_SAXAttributes
, "SAXAttributes" },
5430 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
5431 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
5432 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
5436 static void test_mxattr_localname(void)
5438 static const WCHAR localname1W
[] = {'l','o','c','a','l','n','a','m','e','1',0};
5439 static const WCHAR localnameW
[] = {'l','o','c','a','l','n','a','m','e',0};
5440 static const WCHAR uri1W
[] = {'u','r','i','1',0};
5441 static const WCHAR uriW
[] = {'u','r','i',0};
5443 const struct msxmlsupported_data_t
*table
= saxattr_support_data
;
5445 while (table
->clsid
)
5447 ISAXAttributes
*saxattr
;
5448 IMXAttributes
*mxattr
;
5452 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5458 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5459 &IID_IMXAttributes
, (void**)&mxattr
);
5460 EXPECT_HR(hr
, S_OK
);
5462 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5463 EXPECT_HR(hr
, S_OK
);
5465 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, &index
);
5466 EXPECT_HR(hr
, E_INVALIDARG
);
5468 /* add some ambiguos attribute names */
5469 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5470 _bstr_("a:localname"), _bstr_(""), _bstr_("value"));
5471 EXPECT_HR(hr
, S_OK
);
5472 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5473 _bstr_("b:localname"), _bstr_(""), _bstr_("value"));
5474 EXPECT_HR(hr
, S_OK
);
5477 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localnameW
, lstrlenW(localnameW
), &index
);
5478 EXPECT_HR(hr
, S_OK
);
5479 ok(index
== 0, "%s: got index %d\n", table
->name
, index
);
5482 hr
= ISAXAttributes_getIndexFromName(saxattr
, uri1W
, lstrlenW(uri1W
), localnameW
, lstrlenW(localnameW
), &index
);
5483 EXPECT_HR(hr
, E_INVALIDARG
);
5484 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5487 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), &index
);
5488 EXPECT_HR(hr
, E_INVALIDARG
);
5489 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5491 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5492 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5494 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5495 EXPECT_HR(hr
, E_POINTER
);
5497 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5498 EXPECT_HR(hr
, E_POINTER
);
5502 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5503 EXPECT_HR(hr
, E_INVALIDARG
);
5505 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5506 EXPECT_HR(hr
, E_INVALIDARG
);
5509 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), NULL
, 0, &index
);
5510 EXPECT_HR(hr
, E_INVALIDARG
);
5512 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, localname1W
, lstrlenW(localname1W
), &index
);
5513 EXPECT_HR(hr
, E_INVALIDARG
);
5517 ISAXAttributes_Release(saxattr
);
5518 IMXAttributes_Release(mxattr
);
5523 static void test_mxwriter_indent(void)
5525 ISAXContentHandler
*content
;
5530 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMXWriter
, (void**)&writer
);
5531 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
5533 hr
= IMXWriter_put_indent(writer
, VARIANT_TRUE
);
5534 ok(hr
== S_OK
, "got %08x\n", hr
);
5536 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
5537 ok(hr
== S_OK
, "got %08x\n", hr
);
5539 hr
= ISAXContentHandler_startDocument(content
);
5540 ok(hr
== S_OK
, "got %08x\n", hr
);
5542 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
5543 ok(hr
== S_OK
, "got %08x\n", hr
);
5545 hr
= ISAXContentHandler_characters(content
, _bstr_(""), 0);
5546 ok(hr
== S_OK
, "got %08x\n", hr
);
5548 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("b"), -1, NULL
);
5549 ok(hr
== S_OK
, "got %08x\n", hr
);
5551 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("c"), -1, NULL
);
5552 ok(hr
== S_OK
, "got %08x\n", hr
);
5554 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("c"), -1);
5555 ok(hr
== S_OK
, "got %08x\n", hr
);
5557 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("b"), -1);
5558 ok(hr
== S_OK
, "got %08x\n", hr
);
5560 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1);
5561 ok(hr
== S_OK
, "got %08x\n", hr
);
5563 hr
= ISAXContentHandler_endDocument(content
);
5564 ok(hr
== S_OK
, "got %08x\n", hr
);
5566 V_VT(&dest
) = VT_EMPTY
;
5567 hr
= IMXWriter_get_output(writer
, &dest
);
5568 ok(hr
== S_OK
, "got %08x\n", hr
);
5569 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
5570 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
)),
5571 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
5572 VariantClear(&dest
);
5574 ISAXContentHandler_Release(content
);
5575 IMXWriter_Release(writer
);
5580 START_TEST(saxreader
)
5582 ISAXXMLReader
*reader
;
5585 hr
= CoInitialize(NULL
);
5586 ok(hr
== S_OK
, "failed to init com\n");
5588 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
5589 &IID_ISAXXMLReader
, (void**)&reader
);
5593 skip("Failed to create SAXXMLReader instance\n");
5597 ISAXXMLReader_Release(reader
);
5599 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
5601 get_class_support_data(reader_support_data
, &IID_ISAXXMLReader
);
5604 test_saxreader_properties();
5605 test_saxreader_features();
5606 test_saxreader_encoding();
5607 test_saxreader_dispex();
5609 /* MXXMLWriter tests */
5610 get_class_support_data(mxwriter_support_data
, &IID_IMXWriter
);
5611 if (is_clsid_supported(&CLSID_MXXMLWriter
, mxwriter_support_data
))
5613 test_mxwriter_handlers();
5614 test_mxwriter_startenddocument();
5615 test_mxwriter_startendelement();
5616 test_mxwriter_characters();
5617 test_mxwriter_comment();
5618 test_mxwriter_cdata();
5620 test_mxwriter_ignorablespaces();
5621 test_mxwriter_dtd();
5622 test_mxwriter_properties();
5623 test_mxwriter_flush();
5624 test_mxwriter_stream();
5625 test_mxwriter_encoding();
5626 test_mxwriter_dispex();
5627 test_mxwriter_indent();
5630 win_skip("MXXMLWriter not supported\n");
5632 /* SAXAttributes tests */
5633 get_class_support_data(mxattributes_support_data
, &IID_IMXAttributes
);
5634 if (is_clsid_supported(&CLSID_SAXAttributes
, mxattributes_support_data
))
5637 test_mxattr_addAttribute();
5638 test_mxattr_clear();
5639 test_mxattr_localname();
5640 test_mxattr_dispex();
5643 skip("SAXAttributes not supported\n");