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
25 DEFINE_GUID(GUID_NULL
,0,0,0,0,0,0,0,0,0,0,0);
27 static const WCHAR emptyW
[] = {0};
29 #define EXPECT_HR(hr,hr_exp) \
30 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
32 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
33 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
37 rc
= IUnknown_Release(obj
);
38 ok_(__FILE__
, line
)(rc
== ref
, "expected refcount %d, got %d\n", ref
, rc
);
41 static LONG
get_refcount(void *iface
)
43 IUnknown
*unk
= iface
;
46 ref
= IUnknown_AddRef(unk
);
47 IUnknown_Release(unk
);
51 struct msxmlsupported_data_t
58 static BOOL
is_clsid_supported(const GUID
*clsid
, const struct msxmlsupported_data_t
*table
)
62 if (table
->clsid
== clsid
) return table
->supported
;
68 static BSTR
alloc_str_from_narrow(const char *str
)
70 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
71 BSTR ret
= SysAllocStringLen(NULL
, len
- 1); /* NUL character added automatically */
72 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
76 static BSTR alloced_bstrs
[512];
77 static int alloced_bstrs_count
;
79 static BSTR
_bstr_(const char *str
)
81 assert(alloced_bstrs_count
< sizeof(alloced_bstrs
)/sizeof(alloced_bstrs
[0]));
82 alloced_bstrs
[alloced_bstrs_count
] = alloc_str_from_narrow(str
);
83 return alloced_bstrs
[alloced_bstrs_count
++];
86 static void free_bstrs(void)
89 for (i
= 0; i
< alloced_bstrs_count
; i
++)
90 SysFreeString(alloced_bstrs
[i
]);
91 alloced_bstrs_count
= 0;
94 static void test_saxstr(const char *file
, unsigned line
, BSTR str
, const char *expected
, BOOL todo
, int *failcount
)
99 len
= SysStringLen(str
);
106 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
109 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
115 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
118 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
122 lenexp
= strlen(expected
);
123 if (lenexp
!= len
&& todo
)
127 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
130 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
132 /* exit earlier on length mismatch */
133 if (lenexp
!= len
) return;
135 MultiByteToWideChar(CP_ACP
, 0, expected
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
137 cmp
= memcmp(str
, buf
, lenexp
*sizeof(WCHAR
));
142 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
143 wine_dbgstr_wn(str
, len
), expected
);
146 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
147 wine_dbgstr_wn(str
, len
), expected
);
152 CH_PUTDOCUMENTLOCATOR
,
155 CH_STARTPREFIXMAPPING
,
160 CH_IGNORABLEWHITESPACE
,
161 CH_PROCESSINGINSTRUCTION
,
171 static const char *event_names
[EVENT_LAST
] = {
173 "putDocumentLocator",
176 "startPrefixMapping",
181 "ignorableWhitespace",
182 "processingInstruction",
191 struct attribute_entry
{
197 /* used for actual call data only, null for expected call data */
213 /* allocated once at startElement callback */
214 struct attribute_entry
*attributes
;
217 /* used for actual call data only, null for expected call data */
227 struct call_entry
*sequence
;
230 #define CONTENT_HANDLER_INDEX 0
231 #define NUM_CALL_SEQUENCES 1
232 static struct call_sequence
*sequences
[NUM_CALL_SEQUENCES
];
234 static void init_call_entry(ISAXLocator
*locator
, struct call_entry
*call
)
236 memset(call
, 0, sizeof(*call
));
237 ISAXLocator_getLineNumber(locator
, &call
->line
);
238 ISAXLocator_getColumnNumber(locator
, &call
->column
);
241 static void add_call(struct call_sequence
**seq
, int sequence_index
,
242 const struct call_entry
*call
)
244 struct call_sequence
*call_seq
= seq
[sequence_index
];
246 if (!call_seq
->sequence
)
249 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0,
250 call_seq
->size
* sizeof (struct call_entry
));
253 if (call_seq
->count
== call_seq
->size
)
256 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
258 call_seq
->size
* sizeof (struct call_entry
));
261 assert(call_seq
->sequence
);
263 call_seq
->sequence
[call_seq
->count
].id
= call
->id
;
264 call_seq
->sequence
[call_seq
->count
].line
= call
->line
;
265 call_seq
->sequence
[call_seq
->count
].column
= call
->column
;
266 call_seq
->sequence
[call_seq
->count
].arg1W
= call
->arg1W
;
267 call_seq
->sequence
[call_seq
->count
].arg2W
= call
->arg2W
;
268 call_seq
->sequence
[call_seq
->count
].arg3W
= call
->arg3W
;
269 call_seq
->sequence
[call_seq
->count
].ret
= call
->ret
;
270 call_seq
->sequence
[call_seq
->count
].attr_count
= call
->attr_count
;
271 call_seq
->sequence
[call_seq
->count
].attributes
= call
->attributes
;
276 static inline void flush_sequence(struct call_sequence
**seg
, int sequence_index
)
280 struct call_sequence
*call_seq
= seg
[sequence_index
];
282 for (i
= 0; i
< call_seq
->count
; i
++)
286 for (j
= 0; j
< call_seq
->sequence
[i
].attr_count
; j
++)
288 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].uriW
);
289 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].localW
);
290 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].qnameW
);
291 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].valueW
);
293 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
[i
].attributes
);
294 call_seq
->sequence
[i
].attr_count
= 0;
296 SysFreeString(call_seq
->sequence
[i
].arg1W
);
297 SysFreeString(call_seq
->sequence
[i
].arg2W
);
298 SysFreeString(call_seq
->sequence
[i
].arg3W
);
301 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
302 call_seq
->sequence
= NULL
;
303 call_seq
->count
= call_seq
->size
= 0;
306 static const char *get_event_name(CH event
)
308 return event_names
[event
];
311 static void compare_attributes(const struct call_entry
*actual
, const struct call_entry
*expected
, const char *context
,
312 BOOL todo
, const char *file
, int line
, int *failcount
)
316 /* attribute count is not stored for expected data */
317 if (expected
->attributes
)
319 struct attribute_entry
*ptr
= expected
->attributes
;
320 while (ptr
->uri
) { lenexp
++; ptr
++; };
323 /* check count first and exit earlier */
324 if (actual
->attr_count
!= lenexp
&& todo
)
328 ok_(file
, line
) (FALSE
, "%s: in event %s expecting attr count %d got %d\n",
329 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
332 ok_(file
, line
) (actual
->attr_count
== lenexp
, "%s: in event %s expecting attr count %d got %d\n",
333 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
335 if (actual
->attr_count
!= lenexp
) return;
337 /* now compare all attributes strings */
338 for (i
= 0; i
< actual
->attr_count
; i
++)
340 test_saxstr(file
, line
, actual
->attributes
[i
].uriW
, expected
->attributes
[i
].uri
, todo
, failcount
);
341 test_saxstr(file
, line
, actual
->attributes
[i
].localW
, expected
->attributes
[i
].local
, todo
, failcount
);
342 test_saxstr(file
, line
, actual
->attributes
[i
].qnameW
, expected
->attributes
[i
].qname
, todo
, failcount
);
343 test_saxstr(file
, line
, actual
->attributes
[i
].valueW
, expected
->attributes
[i
].value
, todo
, failcount
);
347 static void ok_sequence_(struct call_sequence
**seq
, int sequence_index
,
348 const struct call_entry
*expected
, const char *context
, BOOL todo
,
349 const char *file
, int line
)
351 struct call_sequence
*call_seq
= seq
[sequence_index
];
352 static const struct call_entry end_of_sequence
= { CH_ENDTEST
};
353 const struct call_entry
*actual
, *sequence
;
356 add_call(seq
, sequence_index
, &end_of_sequence
);
358 sequence
= call_seq
->sequence
;
361 while (expected
->id
!= CH_ENDTEST
&& actual
->id
!= CH_ENDTEST
)
363 if (expected
->id
== actual
->id
)
365 if (expected
->line
!= -1)
367 /* always test position data */
368 if (expected
->line
!= actual
->line
&& todo
)
373 ok_(file
, line
) (FALSE
,
374 "%s: in event %s expecting line %d got %d\n",
375 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
380 ok_(file
, line
) (expected
->line
== actual
->line
,
381 "%s: in event %s expecting line %d got %d\n",
382 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
387 if (expected
->column
!= -1)
389 if (expected
->column
!= actual
->column
&& todo
)
394 ok_(file
, line
) (FALSE
,
395 "%s: in event %s expecting column %d got %d\n",
396 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
401 ok_(file
, line
) (expected
->column
== actual
->column
,
402 "%s: in event %s expecting column %d got %d\n",
403 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
409 case CH_PUTDOCUMENTLOCATOR
:
410 case CH_STARTDOCUMENT
:
415 case CH_STARTPREFIXMAPPING
:
417 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
418 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
420 case CH_ENDPREFIXMAPPING
:
422 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
424 case CH_STARTELEMENT
:
425 /* compare attributes */
426 compare_attributes(actual
, expected
, context
, todo
, file
, line
, &failcount
);
429 /* uri, localname, qname */
430 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
431 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
432 test_saxstr(file
, line
, actual
->arg3W
, expected
->arg3
, todo
, &failcount
);
435 case CH_IGNORABLEWHITESPACE
:
437 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
439 case CH_PROCESSINGINSTRUCTION
:
441 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
442 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
444 case CH_SKIPPEDENTITY
:
446 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
449 /* test return value only */
450 if (expected
->ret
!= actual
->ret
&& todo
)
453 ok_(file
, line
) (FALSE
,
454 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
455 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
458 ok_(file
, line
) (expected
->ret
== actual
->ret
,
459 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
460 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
463 case EH_IGNORABLEWARNING
:
465 ok(0, "%s: callback not handled, %s\n", context
, get_event_name(actual
->id
));
475 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
476 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
479 flush_sequence(seq
, sequence_index
);
484 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
485 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
495 if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
498 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
499 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
503 else if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
505 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
506 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
509 if (todo
&& !failcount
) /* succeeded yet marked todo */
513 ok_(file
, line
)(TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
517 flush_sequence(seq
, sequence_index
);
520 #define ok_sequence(seq, index, exp, contx, todo) \
521 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
523 static void init_call_sequences(struct call_sequence
**seq
, int n
)
527 for (i
= 0; i
< n
; i
++)
528 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct call_sequence
));
531 static const WCHAR szSimpleXML
[] = {
532 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
533 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
534 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
535 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
536 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
539 static const WCHAR carriage_ret_test
[] = {
540 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
541 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
542 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
543 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
544 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
547 static const WCHAR szUtf16XML
[] = {
548 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
549 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
550 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
553 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
555 static const CHAR szUtf8XML
[] =
556 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
558 static const char utf8xml2
[] =
559 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n";
561 static const char testXML
[] =
562 "<?xml version=\"1.0\" ?>\n"
564 " <Number>1234</Number>\n"
565 " <Name>Captain Ahab</Name>\n"
568 static const char test_attributes
[] =
569 "<?xml version=\"1.0\" ?>\n"
570 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
571 "<node1 xmlns:p=\"test\" />"
574 static const char test_cdata_xml
[] =
575 "<?xml version=\"1.0\" ?>"
576 "<a><![CDATA[Some \r\ntext\n\r\ndata\n\n]]></a>";
578 static const char test2_cdata_xml
[] =
579 "<?xml version=\"1.0\" ?>"
580 "<a><![CDATA[\n\r\nSome \r\ntext\n\r\ndata\n\n]]></a>";
582 static const char test3_cdata_xml
[] =
583 "<?xml version=\"1.0\" ?><a><![CDATA[Some text data]]></a>";
585 static struct call_entry content_handler_test1
[] = {
586 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
587 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
588 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
589 { CH_CHARACTERS
, 2, 14, S_OK
, "\n " },
590 { CH_STARTELEMENT
, 3, 12, S_OK
, "", "Number", "Number" },
591 { CH_CHARACTERS
, 3, 12, S_OK
, "1234" },
592 { CH_ENDELEMENT
, 3, 18, S_OK
, "", "Number", "Number" },
593 { CH_CHARACTERS
, 3, 25, S_OK
, "\n " },
594 { CH_STARTELEMENT
, 4, 10, S_OK
, "", "Name", "Name" },
595 { CH_CHARACTERS
, 4, 10, S_OK
, "Captain Ahab" },
596 { CH_ENDELEMENT
, 4, 24, S_OK
, "", "Name", "Name" },
597 { CH_CHARACTERS
, 4, 29, S_OK
, "\n" },
598 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
599 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
603 /* applies to versions 4 and 6 */
604 static struct call_entry content_handler_test1_alternate
[] = {
605 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
606 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
607 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
608 { CH_CHARACTERS
, 3, 4, S_OK
, "\n " },
609 { CH_STARTELEMENT
, 3, 11, S_OK
, "", "Number", "Number" },
610 { CH_CHARACTERS
, 3, 16, S_OK
, "1234" },
611 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "Number", "Number" },
612 { CH_CHARACTERS
, 4, 4, S_OK
, "\n " },
613 { CH_STARTELEMENT
, 4, 9, S_OK
, "", "Name", "Name" },
614 { CH_CHARACTERS
, 4, 22, S_OK
, "Captain Ahab" },
615 { CH_ENDELEMENT
, 4, 28, S_OK
, "", "Name", "Name" },
616 { CH_CHARACTERS
, 5, 1, S_OK
, "\n" },
617 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
618 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
622 static struct call_entry content_handler_test2
[] = {
623 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
624 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
625 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
626 { CH_CHARACTERS
, 2, 14, S_OK
, "\n" },
627 { CH_CHARACTERS
, 2, 16, S_OK
, "\t" },
628 { CH_STARTELEMENT
, 3, 10, S_OK
, "", "Number", "Number" },
629 { CH_CHARACTERS
, 3, 10, S_OK
, "1234" },
630 { CH_ENDELEMENT
, 3, 16, S_OK
, "", "Number", "Number" },
631 { CH_CHARACTERS
, 3, 23, S_OK
, "\n" },
632 { CH_CHARACTERS
, 3, 25, S_OK
, "\t" },
633 { CH_STARTELEMENT
, 4, 8, S_OK
, "", "Name", "Name" },
634 { CH_CHARACTERS
, 4, 8, S_OK
, "Captain Ahab" },
635 { CH_ENDELEMENT
, 4, 22, S_OK
, "", "Name", "Name" },
636 { CH_CHARACTERS
, 4, 27, S_OK
, "\n" },
637 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
638 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
642 static struct call_entry content_handler_test2_alternate
[] = {
643 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
644 { CH_STARTDOCUMENT
, 1, 21, S_OK
},
645 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
646 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
647 { CH_CHARACTERS
, 3, 2, S_OK
, "\t" },
648 { CH_STARTELEMENT
, 3, 9, S_OK
, "", "Number", "Number" },
649 { CH_CHARACTERS
, 3, 14, S_OK
, "1234" },
650 { CH_ENDELEMENT
, 3, 22, S_OK
, "", "Number", "Number" },
651 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
652 { CH_CHARACTERS
, 4, 2, S_OK
, "\t" },
653 { CH_STARTELEMENT
, 4, 7, S_OK
, "", "Name", "Name" },
654 { CH_CHARACTERS
, 4, 20, S_OK
, "Captain Ahab" },
655 { CH_ENDELEMENT
, 4, 26, S_OK
, "", "Name", "Name" },
656 { CH_CHARACTERS
, 5, 0, S_OK
, "\n" },
657 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
658 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
662 static struct call_entry content_handler_testerror
[] = {
663 { CH_PUTDOCUMENTLOCATOR
, 0, 0, E_FAIL
},
664 { EH_FATALERROR
, 0, 0, E_FAIL
},
668 static struct call_entry content_handler_testerror_alternate
[] = {
669 { CH_PUTDOCUMENTLOCATOR
, 1, 0, E_FAIL
},
670 { EH_FATALERROR
, 1, 0, E_FAIL
},
674 static struct call_entry content_handler_test_callback_rets
[] = {
675 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_FALSE
},
676 { CH_STARTDOCUMENT
, 0, 0, S_FALSE
},
677 { EH_FATALERROR
, 0, 0, S_FALSE
},
681 static struct call_entry content_handler_test_callback_rets_alt
[] = {
682 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_FALSE
},
683 { CH_STARTDOCUMENT
, 1, 22, S_FALSE
},
684 { CH_STARTELEMENT
, 2, 13, S_FALSE
, "", "BankAccount", "BankAccount" },
685 { CH_CHARACTERS
, 3, 4, S_FALSE
, "\n " },
686 { CH_STARTELEMENT
, 3, 11, S_FALSE
, "", "Number", "Number" },
687 { CH_CHARACTERS
, 3, 16, S_FALSE
, "1234" },
688 { CH_ENDELEMENT
, 3, 24, S_FALSE
, "", "Number", "Number" },
689 { CH_CHARACTERS
, 4, 4, S_FALSE
, "\n " },
690 { CH_STARTELEMENT
, 4, 9, S_FALSE
, "", "Name", "Name" },
691 { CH_CHARACTERS
, 4, 22, S_FALSE
, "Captain Ahab" },
692 { CH_ENDELEMENT
, 4, 28, S_FALSE
, "", "Name", "Name" },
693 { CH_CHARACTERS
, 5, 1, S_FALSE
, "\n" },
694 { CH_ENDELEMENT
, 5, 14, S_FALSE
, "", "BankAccount", "BankAccount" },
695 { CH_ENDDOCUMENT
, 6, 0, S_FALSE
},
699 static struct attribute_entry ch_attributes1
[] = {
700 { "", "", "xmlns:test", "prefix_test" },
701 { "", "", "xmlns", "prefix" },
702 { "prefix_test", "arg1", "test:arg1", "arg1" },
703 { "", "arg2", "arg2", "arg2" },
704 { "prefix_test", "ar3", "test:ar3", "arg3" },
708 static struct attribute_entry ch_attributes2
[] = {
709 { "", "", "xmlns:p", "test" },
713 static struct call_entry content_handler_test_attributes
[] = {
714 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
715 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
716 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
717 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
718 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes1
},
719 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
720 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
721 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
722 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
723 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
724 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
725 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
726 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
727 { CH_ENDDOCUMENT
, 0, 0 },
731 static struct attribute_entry ch_attributes_alt_4
[] = {
732 { "prefix_test", "arg1", "test:arg1", "arg1" },
733 { "", "arg2", "arg2", "arg2" },
734 { "prefix_test", "ar3", "test:ar3", "arg3" },
735 { "", "", "xmlns:test", "prefix_test" },
736 { "", "", "xmlns", "prefix" },
740 static struct call_entry content_handler_test_attributes_alternate_4
[] = {
741 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
742 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
743 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
744 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
745 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_4
},
746 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
747 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
748 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
749 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
750 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
751 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
752 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
753 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
754 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
758 /* 'namespace' feature switched off */
759 static struct attribute_entry ch_attributes_alt_no_ns
[] = {
760 { "", "", "xmlns:test", "prefix_test" },
761 { "", "", "xmlns", "prefix" },
762 { "", "", "test:arg1", "arg1" },
763 { "", "", "arg2", "arg2" },
764 { "", "", "test:ar3", "arg3" },
768 static struct call_entry content_handler_test_attributes_alt_no_ns
[] = {
769 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
770 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
771 { CH_STARTELEMENT
, 2, 95, S_OK
, "", "", "document", ch_attributes_alt_no_ns
},
772 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
773 { CH_STARTELEMENT
, 3, 24, S_OK
, "", "", "node1", ch_attributes2
},
774 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "", "node1" },
775 { CH_ENDELEMENT
, 3, 35, S_OK
, "", "", "document" },
776 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
780 static struct attribute_entry ch_attributes_alt_6
[] = {
781 { "prefix_test", "arg1", "test:arg1", "arg1" },
782 { "", "arg2", "arg2", "arg2" },
783 { "prefix_test", "ar3", "test:ar3", "arg3" },
784 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
785 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
789 static struct attribute_entry ch_attributes2_6
[] = {
790 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
794 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
795 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
796 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
797 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
798 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
799 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
800 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
801 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
802 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
803 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
804 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
805 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
806 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
807 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
808 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
812 /* 'namespaces' is on, 'namespace-prefixes' if off */
813 static struct attribute_entry ch_attributes_no_prefix
[] = {
814 { "prefix_test", "arg1", "test:arg1", "arg1" },
815 { "", "arg2", "arg2", "arg2" },
816 { "prefix_test", "ar3", "test:ar3", "arg3" },
820 static struct call_entry content_handler_test_attributes_alt_no_prefix
[] = {
821 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
822 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
823 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
824 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
825 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
826 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
827 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
828 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", NULL
},
829 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
830 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
831 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
832 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
833 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
834 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
838 static struct call_entry content_handler_test_attributes_no_prefix
[] = {
839 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
840 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
841 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
842 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
843 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
844 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
845 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
846 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", NULL
},
847 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
848 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
849 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
850 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
851 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
852 { CH_ENDDOCUMENT
, 0, 0 },
856 static struct attribute_entry xmlspace_attrs
[] = {
857 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
861 static struct call_entry xmlspaceattr_test
[] = {
862 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
863 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
864 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
865 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
866 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
867 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
871 static struct call_entry xmlspaceattr_test_alternate
[] = {
872 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
873 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
874 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
875 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
876 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
877 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
881 /* attribute value normalization test */
882 static const char attribute_normalize
[] =
883 "<?xml version=\"1.0\" ?>\n"
884 "<a attr1=\" \r \n \tattr_value A & &\t \r \n\r\n \n\"/>\n";
886 static struct attribute_entry attribute_norm_attrs
[] = {
887 { "", "attr1", "attr1", " attr_value A & & " },
891 static struct call_entry attribute_norm
[] = {
892 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
893 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
894 { CH_STARTELEMENT
, 6, 4, S_OK
, "", "a", "a", attribute_norm_attrs
},
895 { CH_ENDELEMENT
, 6, 4, S_OK
, "", "a", "a" },
896 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
900 static struct call_entry attribute_norm_alt
[] = {
901 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
902 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
903 { CH_STARTELEMENT
, 8, 3, S_OK
, "", "a", "a", attribute_norm_attrs
},
904 { CH_ENDELEMENT
, 8, 3, S_OK
, "", "a", "a" },
905 { CH_ENDDOCUMENT
, 9, 0, S_OK
},
909 static struct call_entry cdata_test
[] = {
910 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
911 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
912 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
913 { LH_STARTCDATA
, 1, 35, S_OK
},
914 { CH_CHARACTERS
, 1, 35, S_OK
, "Some \n" },
915 { CH_CHARACTERS
, 1, 42, S_OK
, "text\n\n" },
916 { CH_CHARACTERS
, 1, 49, S_OK
, "data\n\n" },
917 { LH_ENDCDATA
, 1, 49, S_OK
},
918 { CH_ENDELEMENT
, 6, 6, S_OK
, "", "a", "a" },
919 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
923 static struct call_entry cdata_test2
[] = {
924 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
925 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
926 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
927 { LH_STARTCDATA
, 1, 35, S_OK
},
928 { CH_CHARACTERS
, 1, 35, S_OK
, "\n\n" },
929 { CH_CHARACTERS
, 1, 38, S_OK
, "Some \n" },
930 { CH_CHARACTERS
, 1, 45, S_OK
, "text\n\n" },
931 { CH_CHARACTERS
, 1, 52, S_OK
, "data\n\n" },
932 { LH_ENDCDATA
, 1, 52, S_OK
},
933 { CH_ENDELEMENT
, 8, 6, S_OK
, "", "a", "a" },
934 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
938 static struct call_entry cdata_test3
[] = {
939 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
940 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
941 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
942 { LH_STARTCDATA
, 1, 35, S_OK
},
943 { CH_CHARACTERS
, 1, 35, S_OK
, "Some text data" },
944 { LH_ENDCDATA
, 1, 35, S_OK
},
945 { CH_ENDELEMENT
, 1, 54, S_OK
, "", "a", "a" },
946 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
950 /* this is what MSXML6 does */
951 static struct call_entry cdata_test_alt
[] = {
952 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
953 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
954 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
955 { LH_STARTCDATA
, 1, 34, S_OK
},
956 { CH_CHARACTERS
, 1, 40, S_OK
, "Some " },
957 { CH_CHARACTERS
, 2, 0, S_OK
, "\n" },
958 { CH_CHARACTERS
, 3, 1, S_OK
, "text\n" },
959 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
960 { CH_CHARACTERS
, 6, 3, S_OK
, "data\n\n" },
961 { LH_ENDCDATA
, 6, 3, S_OK
},
962 { CH_ENDELEMENT
, 6, 7, S_OK
, "", "a", "a" },
963 { CH_ENDDOCUMENT
, 6, 7, S_OK
},
967 static struct call_entry cdata_test2_alt
[] = {
968 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
969 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
970 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
971 { LH_STARTCDATA
, 1, 34, S_OK
},
972 { CH_CHARACTERS
, 2, 1, S_OK
, "\n" },
973 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
974 { CH_CHARACTERS
, 3, 6, S_OK
, "Some " },
975 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
976 { CH_CHARACTERS
, 5, 1, S_OK
, "text\n" },
977 { CH_CHARACTERS
, 6, 0, S_OK
, "\n" },
978 { CH_CHARACTERS
, 8, 3, S_OK
, "data\n\n" },
979 { LH_ENDCDATA
, 8, 3, S_OK
},
980 { CH_ENDELEMENT
, 8, 7, S_OK
, "", "a", "a" },
981 { CH_ENDDOCUMENT
, 8, 7, S_OK
},
985 static struct call_entry cdata_test3_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
, 1, 51, S_OK
, "Some text data" },
991 { LH_ENDCDATA
, 1, 51, S_OK
},
992 { CH_ENDELEMENT
, 1, 55, S_OK
, "", "a", "a" },
993 { CH_ENDDOCUMENT
, 1, 55, S_OK
},
997 static struct attribute_entry read_test_attrs
[] = {
998 { "", "attr", "attr", "val" },
1002 static struct call_entry read_test_seq
[] = {
1003 { CH_PUTDOCUMENTLOCATOR
, -1, 0, S_OK
},
1004 { CH_STARTDOCUMENT
, -1, -1, S_OK
},
1005 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1006 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1007 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1008 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1009 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1010 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1011 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1012 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1013 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1014 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1015 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1016 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1017 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1018 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1019 { CH_ENDDOCUMENT
, -1, -1, S_OK
},
1023 static const char xmlspace_attr
[] =
1024 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
1025 "<a xml:space=\"preserve\"> Some text data </a>";
1027 static struct call_entry
*expectCall
;
1028 static ISAXLocator
*locator
;
1029 static ISAXXMLReader
*g_reader
;
1032 static void set_expected_seq(struct call_entry
*expected
)
1034 expectCall
= expected
;
1037 /* to be called once on each tested callback return */
1038 static HRESULT
get_expected_ret(void)
1040 HRESULT hr
= expectCall
->ret
;
1041 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
1045 static HRESULT WINAPI
contentHandler_QueryInterface(
1046 ISAXContentHandler
* iface
,
1052 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
1058 return E_NOINTERFACE
;
1064 static ULONG WINAPI
contentHandler_AddRef(
1065 ISAXContentHandler
* iface
)
1070 static ULONG WINAPI
contentHandler_Release(
1071 ISAXContentHandler
* iface
)
1076 static HRESULT WINAPI
contentHandler_putDocumentLocator(
1077 ISAXContentHandler
* iface
,
1078 ISAXLocator
*pLocator
)
1080 struct call_entry call
;
1086 init_call_entry(locator
, &call
);
1087 call
.id
= CH_PUTDOCUMENTLOCATOR
;
1088 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1090 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXLocator
, (void**)&unk
);
1091 EXPECT_HR(hr
, E_NOINTERFACE
);
1093 if (msxml_version
>= 6) {
1094 ISAXAttributes
*attr
, *attr1
;
1095 IMXAttributes
*mxattr
;
1097 EXPECT_REF(pLocator
, 1);
1098 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
1099 EXPECT_HR(hr
, S_OK
);
1100 EXPECT_REF(pLocator
, 2);
1101 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
1102 EXPECT_HR(hr
, S_OK
);
1103 EXPECT_REF(pLocator
, 3);
1104 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
1106 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IVBSAXAttributes
, (void**)&unk
);
1107 EXPECT_HR(hr
, E_NOINTERFACE
);
1109 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXAttributes
, (void**)&unk
);
1110 EXPECT_HR(hr
, E_NOINTERFACE
);
1112 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
1113 EXPECT_HR(hr
, E_NOINTERFACE
);
1115 ISAXAttributes_Release(attr
);
1116 ISAXAttributes_Release(attr1
);
1119 return get_expected_ret();
1122 static ISAXAttributes
*test_attr_ptr
;
1123 static HRESULT WINAPI
contentHandler_startDocument(
1124 ISAXContentHandler
* iface
)
1126 struct call_entry call
;
1128 init_call_entry(locator
, &call
);
1129 call
.id
= CH_STARTDOCUMENT
;
1130 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1132 test_attr_ptr
= NULL
;
1134 return get_expected_ret();
1137 static HRESULT WINAPI
contentHandler_endDocument(
1138 ISAXContentHandler
* iface
)
1140 struct call_entry call
;
1142 init_call_entry(locator
, &call
);
1143 call
.id
= CH_ENDDOCUMENT
;
1144 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1146 return get_expected_ret();
1149 static HRESULT WINAPI
contentHandler_startPrefixMapping(
1150 ISAXContentHandler
* iface
,
1151 const WCHAR
*prefix
, int prefix_len
,
1152 const WCHAR
*uri
, int uri_len
)
1154 struct call_entry call
;
1156 init_call_entry(locator
, &call
);
1157 call
.id
= CH_STARTPREFIXMAPPING
;
1158 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
1159 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
1160 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1162 return get_expected_ret();
1165 static HRESULT WINAPI
contentHandler_endPrefixMapping(
1166 ISAXContentHandler
* iface
,
1167 const WCHAR
*prefix
, int len
)
1169 struct call_entry call
;
1171 init_call_entry(locator
, &call
);
1172 call
.id
= CH_ENDPREFIXMAPPING
;
1173 call
.arg1W
= SysAllocStringLen(prefix
, len
);
1174 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1176 return get_expected_ret();
1179 static HRESULT WINAPI
contentHandler_startElement(
1180 ISAXContentHandler
* iface
,
1181 const WCHAR
*uri
, int uri_len
,
1182 const WCHAR
*localname
, int local_len
,
1183 const WCHAR
*qname
, int qname_len
,
1184 ISAXAttributes
*saxattr
)
1186 struct call_entry call
;
1187 IMXAttributes
*mxattr
;
1191 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
1192 EXPECT_HR(hr
, E_NOINTERFACE
);
1194 init_call_entry(locator
, &call
);
1195 call
.id
= CH_STARTELEMENT
;
1196 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1197 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1198 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1201 test_attr_ptr
= saxattr
;
1202 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
1204 /* store actual attributes */
1206 hr
= ISAXAttributes_getLength(saxattr
, &len
);
1207 EXPECT_HR(hr
, S_OK
);
1214 struct attribute_entry
*attr
;
1215 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
1218 hr
= ISAXXMLReader_getFeature(g_reader
, _bstr_("http://xml.org/sax/features/namespaces"), &v
);
1219 EXPECT_HR(hr
, S_OK
);
1221 for (i
= 0; i
< len
; i
++)
1226 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
1227 &localname
, &local_len
, &qname
, &qname_len
);
1228 EXPECT_HR(hr
, S_OK
);
1230 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
1231 EXPECT_HR(hr
, S_OK
);
1233 /* if 'namespaces' switched off uri and local name contains garbage */
1234 if (v
== VARIANT_FALSE
&& msxml_version
> 0)
1236 attr
[i
].uriW
= SysAllocStringLen(NULL
, 0);
1237 attr
[i
].localW
= SysAllocStringLen(NULL
, 0);
1241 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
1242 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
1245 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
1246 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
1249 call
.attributes
= attr
;
1250 call
.attr_count
= len
;
1253 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1255 return get_expected_ret();
1258 static HRESULT WINAPI
contentHandler_endElement(
1259 ISAXContentHandler
* iface
,
1260 const WCHAR
*uri
, int uri_len
,
1261 const WCHAR
*localname
, int local_len
,
1262 const WCHAR
*qname
, int qname_len
)
1264 struct call_entry call
;
1266 init_call_entry(locator
, &call
);
1267 call
.id
= CH_ENDELEMENT
;
1268 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1269 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1270 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1271 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1273 return get_expected_ret();
1276 static HRESULT WINAPI
contentHandler_characters(
1277 ISAXContentHandler
* iface
,
1281 struct call_entry call
;
1283 init_call_entry(locator
, &call
);
1284 call
.id
= CH_CHARACTERS
;
1285 call
.arg1W
= SysAllocStringLen(chars
, len
);
1286 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1288 return get_expected_ret();
1291 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1292 ISAXContentHandler
* iface
,
1293 const WCHAR
*chars
, int len
)
1295 struct call_entry call
;
1297 init_call_entry(locator
, &call
);
1298 call
.id
= CH_IGNORABLEWHITESPACE
;
1299 call
.arg1W
= SysAllocStringLen(chars
, len
);
1300 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1302 return get_expected_ret();
1305 static HRESULT WINAPI
contentHandler_processingInstruction(
1306 ISAXContentHandler
* iface
,
1307 const WCHAR
*target
, int target_len
,
1308 const WCHAR
*data
, int data_len
)
1310 struct call_entry call
;
1312 init_call_entry(locator
, &call
);
1313 call
.id
= CH_PROCESSINGINSTRUCTION
;
1314 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1315 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1316 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1318 return get_expected_ret();
1321 static HRESULT WINAPI
contentHandler_skippedEntity(
1322 ISAXContentHandler
* iface
,
1323 const WCHAR
*name
, int len
)
1325 struct call_entry call
;
1327 init_call_entry(locator
, &call
);
1328 call
.id
= CH_SKIPPEDENTITY
;
1329 call
.arg1W
= SysAllocStringLen(name
, len
);
1330 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1332 return get_expected_ret();
1335 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1337 contentHandler_QueryInterface
,
1338 contentHandler_AddRef
,
1339 contentHandler_Release
,
1340 contentHandler_putDocumentLocator
,
1341 contentHandler_startDocument
,
1342 contentHandler_endDocument
,
1343 contentHandler_startPrefixMapping
,
1344 contentHandler_endPrefixMapping
,
1345 contentHandler_startElement
,
1346 contentHandler_endElement
,
1347 contentHandler_characters
,
1348 contentHandler_ignorableWhitespace
,
1349 contentHandler_processingInstruction
,
1350 contentHandler_skippedEntity
1353 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1355 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1356 ISAXErrorHandler
* iface
,
1362 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1368 return E_NOINTERFACE
;
1374 static ULONG WINAPI
isaxerrorHandler_AddRef(
1375 ISAXErrorHandler
* iface
)
1380 static ULONG WINAPI
isaxerrorHandler_Release(
1381 ISAXErrorHandler
* iface
)
1386 static HRESULT WINAPI
isaxerrorHandler_error(
1387 ISAXErrorHandler
* iface
,
1388 ISAXLocator
*pLocator
,
1389 const WCHAR
*pErrorMessage
,
1390 HRESULT hrErrorCode
)
1392 ok(0, "unexpected call\n");
1396 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1397 ISAXErrorHandler
* iface
,
1398 ISAXLocator
*pLocator
,
1399 const WCHAR
*message
,
1402 struct call_entry call
;
1404 init_call_entry(locator
, &call
);
1405 call
.id
= EH_FATALERROR
;
1408 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1414 static HRESULT WINAPI
isaxerrorHandler_ignorableWarning(
1415 ISAXErrorHandler
* iface
,
1416 ISAXLocator
*pLocator
,
1417 const WCHAR
*pErrorMessage
,
1418 HRESULT hrErrorCode
)
1420 ok(0, "unexpected call\n");
1424 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1426 isaxerrorHandler_QueryInterface
,
1427 isaxerrorHandler_AddRef
,
1428 isaxerrorHandler_Release
,
1429 isaxerrorHandler_error
,
1430 isaxerrorHandler_fatalError
,
1431 isaxerrorHandler_ignorableWarning
1434 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1436 static HRESULT WINAPI
isaxattributes_QueryInterface(
1437 ISAXAttributes
* iface
,
1443 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1449 return E_NOINTERFACE
;
1455 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1460 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1465 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1471 static HRESULT WINAPI
isaxattributes_getURI(
1472 ISAXAttributes
* iface
,
1477 ok(0, "unexpected call\n");
1481 static HRESULT WINAPI
isaxattributes_getLocalName(
1482 ISAXAttributes
* iface
,
1484 const WCHAR
**pLocalName
,
1485 int *pLocalNameLength
)
1487 ok(0, "unexpected call\n");
1491 static HRESULT WINAPI
isaxattributes_getQName(
1492 ISAXAttributes
* iface
,
1494 const WCHAR
**QName
,
1497 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1498 {'a','t','t','r','2','j','u','n','k',0},
1499 {'a','t','t','r','3',0}};
1500 static const int attrqnamelen
[] = {7, 5, 5};
1502 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1504 if (index
>= 0 && index
<= 2) {
1505 *QName
= attrqnamesW
[index
];
1506 *QNameLength
= attrqnamelen
[index
];
1515 static HRESULT WINAPI
isaxattributes_getName(
1516 ISAXAttributes
* iface
,
1520 const WCHAR
** pLocalName
,
1521 int * pLocalNameSize
,
1522 const WCHAR
** pQName
,
1525 ok(0, "unexpected call\n");
1529 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1530 ISAXAttributes
* iface
,
1533 const WCHAR
* pLocalName
,
1534 int cocalNameLength
,
1537 ok(0, "unexpected call\n");
1541 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1542 ISAXAttributes
* iface
,
1543 const WCHAR
* pQName
,
1547 ok(0, "unexpected call\n");
1551 static HRESULT WINAPI
isaxattributes_getType(
1552 ISAXAttributes
* iface
,
1554 const WCHAR
** pType
,
1557 ok(0, "unexpected call\n");
1561 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1562 ISAXAttributes
* iface
,
1565 const WCHAR
* pLocalName
,
1567 const WCHAR
** pType
,
1570 ok(0, "unexpected call\n");
1574 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1575 ISAXAttributes
* iface
,
1576 const WCHAR
* pQName
,
1578 const WCHAR
** pType
,
1581 ok(0, "unexpected call\n");
1585 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1586 const WCHAR
**value
, int *nValue
)
1588 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1589 {'a','2','j','u','n','k',0},
1590 {'<','&','"','>','\'',0}};
1591 static const int attrvalueslen
[] = {2, 2, 5};
1593 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1595 if (index
>= 0 && index
<= 2) {
1596 *value
= attrvaluesW
[index
];
1597 *nValue
= attrvalueslen
[index
];
1606 static HRESULT WINAPI
isaxattributes_getValueFromName(
1607 ISAXAttributes
* iface
,
1610 const WCHAR
* pLocalName
,
1612 const WCHAR
** pValue
,
1615 ok(0, "unexpected call\n");
1619 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1620 ISAXAttributes
* iface
,
1621 const WCHAR
* pQName
,
1623 const WCHAR
** pValue
,
1626 ok(0, "unexpected call\n");
1630 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1632 isaxattributes_QueryInterface
,
1633 isaxattributes_AddRef
,
1634 isaxattributes_Release
,
1635 isaxattributes_getLength
,
1636 isaxattributes_getURI
,
1637 isaxattributes_getLocalName
,
1638 isaxattributes_getQName
,
1639 isaxattributes_getName
,
1640 isaxattributes_getIndexFromName
,
1641 isaxattributes_getIndexFromQName
,
1642 isaxattributes_getType
,
1643 isaxattributes_getTypeFromName
,
1644 isaxattributes_getTypeFromQName
,
1645 isaxattributes_getValue
,
1646 isaxattributes_getValueFromName
,
1647 isaxattributes_getValueFromQName
1650 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1652 struct saxlexicalhandler
1654 ISAXLexicalHandler ISAXLexicalHandler_iface
;
1657 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1660 static inline struct saxlexicalhandler
*impl_from_ISAXLexicalHandler( ISAXLexicalHandler
*iface
)
1662 return CONTAINING_RECORD(iface
, struct saxlexicalhandler
, ISAXLexicalHandler_iface
);
1665 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **out
)
1667 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1671 if (IsEqualGUID(riid
, &IID_IUnknown
))
1674 ok(0, "got unexpected IID_IUnknown query\n");
1676 else if (IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1678 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1683 ISAXLexicalHandler_AddRef(iface
);
1685 return E_NOINTERFACE
;
1690 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1692 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1693 return InterlockedIncrement(&handler
->ref
);
1696 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1698 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1699 return InterlockedDecrement(&handler
->ref
);
1702 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1703 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1704 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1706 ok(0, "call not expected\n");
1710 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1712 ok(0, "call not expected\n");
1716 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1717 const WCHAR
* pName
, int nName
)
1719 ok(0, "call not expected\n");
1723 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1724 const WCHAR
* pName
, int nName
)
1726 ok(0, "call not expected\n");
1730 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1732 struct call_entry call
;
1734 init_call_entry(locator
, &call
);
1735 call
.id
= LH_STARTCDATA
;
1736 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1738 return get_expected_ret();
1741 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1743 struct call_entry call
;
1745 init_call_entry(locator
, &call
);
1746 call
.id
= LH_ENDCDATA
;
1747 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1749 return get_expected_ret();
1752 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1753 const WCHAR
* pChars
, int nChars
)
1755 ok(0, "call not expected\n");
1759 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1761 isaxlexical_QueryInterface
,
1763 isaxlexical_Release
,
1764 isaxlexical_startDTD
,
1766 isaxlexical_startEntity
,
1767 isaxlexical_endEntity
,
1768 isaxlexical_startCDATA
,
1769 isaxlexical_endCDATA
,
1773 static void init_saxlexicalhandler(struct saxlexicalhandler
*handler
, HRESULT hr
)
1775 handler
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1777 handler
->qi_hr
= hr
;
1780 struct saxdeclhandler
1782 ISAXDeclHandler ISAXDeclHandler_iface
;
1785 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1788 static inline struct saxdeclhandler
*impl_from_ISAXDeclHandler( ISAXDeclHandler
*iface
)
1790 return CONTAINING_RECORD(iface
, struct saxdeclhandler
, ISAXDeclHandler_iface
);
1793 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **out
)
1795 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1799 if (IsEqualGUID(riid
, &IID_IUnknown
))
1802 ok(0, "got unexpected IID_IUnknown query\n");
1804 else if (IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1806 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1811 ISAXDeclHandler_AddRef(iface
);
1813 return E_NOINTERFACE
;
1818 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1820 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1821 return InterlockedIncrement(&handler
->ref
);
1824 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1826 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1827 return InterlockedDecrement(&handler
->ref
);
1830 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1831 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1833 ok(0, "call not expected\n");
1837 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1838 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1839 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1840 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1842 ok(0, "call not expected\n");
1846 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1847 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1849 ok(0, "call not expected\n");
1853 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1854 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1855 const WCHAR
* pSystemId
, int nSystemId
)
1857 ok(0, "call not expected\n");
1861 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1863 isaxdecl_QueryInterface
,
1866 isaxdecl_elementDecl
,
1867 isaxdecl_attributeDecl
,
1868 isaxdecl_internalEntityDecl
,
1869 isaxdecl_externalEntityDecl
1872 static void init_saxdeclhandler(struct saxdeclhandler
*handler
, HRESULT hr
)
1874 handler
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1876 handler
->qi_hr
= hr
;
1879 typedef struct mxwriter_write_test_t
{
1885 } mxwriter_write_test
;
1887 typedef struct mxwriter_stream_test_t
{
1889 const char *encoding
;
1890 mxwriter_write_test expected_writes
[4];
1891 } mxwriter_stream_test
;
1893 static const mxwriter_write_test
*current_write_test
;
1894 static DWORD current_stream_test_index
;
1896 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1900 ok(!IsEqualGUID(riid
, &IID_IPersistStream
), "Did not expect QI for IPersistStream\n");
1902 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1905 return E_NOINTERFACE
;
1910 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1915 static ULONG WINAPI
istream_Release(IStream
*iface
)
1920 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1922 ok(0, "unexpected call\n");
1926 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1928 ok(0, "unexpected call\n");
1932 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1933 ULARGE_INTEGER
*plibNewPosition
)
1935 ok(0, "unexpected call\n");
1939 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1941 ok(0, "unexpected call\n");
1945 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1946 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1948 ok(0, "unexpected call\n");
1952 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1954 ok(0, "unexpected call\n");
1958 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1960 ok(0, "unexpected call\n");
1964 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1965 ULARGE_INTEGER cb
, DWORD dwLockType
)
1967 ok(0, "unexpected call\n");
1971 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1972 ULARGE_INTEGER cb
, DWORD dwLockType
)
1974 ok(0, "unexpected call\n");
1978 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1983 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1985 ok(0, "unexpected call\n");
1989 static HRESULT WINAPI
mxstream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1993 ok(pv
!= NULL
, "pv == NULL\n");
1995 if(current_write_test
->last
) {
1996 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
2000 fail
= current_write_test
->fail_write
;
2002 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
2003 current_write_test
->cb
, cb
, current_stream_test_index
);
2006 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
2008 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
2010 ++current_write_test
;
2015 return fail
? E_FAIL
: S_OK
;
2018 static const IStreamVtbl mxstreamVtbl
= {
2019 istream_QueryInterface
,
2030 istream_UnlockRegion
,
2035 static IStream mxstream
= { &mxstreamVtbl
};
2037 static int read_cnt
;
2039 static HRESULT WINAPI
instream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
2041 static const char *ret_str
;
2044 ret_str
= "<?xml version=\"1.0\" ?>\n<rootelem>";
2045 else if(read_cnt
< 5)
2046 ret_str
= "<elem attr=\"val\">text</elem>";
2047 else if(read_cnt
== 5)
2048 ret_str
= "</rootelem>\n";
2053 strcpy(pv
, ret_str
);
2054 *pcbRead
= strlen(ret_str
);
2058 static const IStreamVtbl instreamVtbl
= {
2059 istream_QueryInterface
,
2070 istream_UnlockRegion
,
2075 static IStream instream
= { &instreamVtbl
};
2077 static struct msxmlsupported_data_t reader_support_data
[] =
2079 { &CLSID_SAXXMLReader
, "SAXReader" },
2080 { &CLSID_SAXXMLReader30
, "SAXReader30" },
2081 { &CLSID_SAXXMLReader40
, "SAXReader40" },
2082 { &CLSID_SAXXMLReader60
, "SAXReader60" },
2086 static struct saxlexicalhandler lexicalhandler
;
2087 static struct saxdeclhandler declhandler
;
2089 static IStream
*create_test_stream(const char *data
, int len
)
2091 ULARGE_INTEGER size
;
2096 if (len
== -1) len
= strlen(data
);
2097 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2098 size
.QuadPart
= len
;
2099 IStream_SetSize(stream
, size
);
2100 IStream_Write(stream
, data
, len
, &written
);
2102 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2107 static void test_saxreader(void)
2109 const struct msxmlsupported_data_t
*table
= reader_support_data
;
2111 ISAXXMLReader
*reader
= NULL
;
2113 ISAXContentHandler
*content
;
2114 ISAXErrorHandler
*lpErrorHandler
;
2116 SAFEARRAYBOUND SADim
[1];
2121 static const CHAR testXmlA
[] = "test.xml";
2122 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2123 IXMLDOMDocument
*doc
;
2127 while (table
->clsid
)
2129 struct call_entry
*test_seq
;
2130 ISAXEntityResolver
*resolver
;
2133 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
2139 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2140 EXPECT_HR(hr
, S_OK
);
2143 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2145 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2150 /* crashes on old versions */
2151 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
2152 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2154 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
2155 EXPECT_HR(hr
, E_POINTER
);
2157 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
2158 EXPECT_HR(hr
, E_POINTER
);
2161 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2162 EXPECT_HR(hr
, S_OK
);
2163 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
2165 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
2166 EXPECT_HR(hr
, S_OK
);
2167 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
2169 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
2170 EXPECT_HR(hr
, S_OK
);
2172 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
2173 EXPECT_HR(hr
, S_OK
);
2175 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
2176 EXPECT_HR(hr
, S_OK
);
2178 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2179 EXPECT_HR(hr
, S_OK
);
2180 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
2182 V_VT(&var
) = VT_BSTR
;
2183 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
2185 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2186 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2187 test_seq
= content_handler_test1_alternate
;
2189 test_seq
= content_handler_test1
;
2190 set_expected_seq(test_seq
);
2191 hr
= ISAXXMLReader_parse(reader
, var
);
2192 EXPECT_HR(hr
, S_OK
);
2193 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
2197 SADim
[0].lLbound
= 0;
2198 SADim
[0].cElements
= sizeof(testXML
)-1;
2199 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
2200 SafeArrayAccessData(sa
, (void**)&ptr
);
2201 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
2202 SafeArrayUnaccessData(sa
);
2203 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
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: from safe array", FALSE
);
2211 SafeArrayDestroy(sa
);
2213 V_VT(&var
) = VT_UNKNOWN
;
2214 V_UNKNOWN(&var
) = NULL
;
2215 hr
= ISAXXMLReader_parse(reader
, var
);
2216 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
2218 V_VT(&var
) = VT_DISPATCH
;
2219 V_DISPATCH(&var
) = NULL
;
2220 hr
= ISAXXMLReader_parse(reader
, var
);
2221 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
2223 stream
= create_test_stream(testXML
, -1);
2224 V_VT(&var
) = VT_UNKNOWN
;
2225 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2227 set_expected_seq(test_seq
);
2228 hr
= ISAXXMLReader_parse(reader
, var
);
2229 EXPECT_HR(hr
, S_OK
);
2230 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
2232 IStream_Release(stream
);
2234 stream
= create_test_stream(test_attributes
, -1);
2235 V_VT(&var
) = VT_UNKNOWN
;
2236 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2238 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2239 test_seq
= content_handler_test_attributes_alternate_4
;
2240 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2241 test_seq
= content_handler_test_attributes_alternate_6
;
2243 test_seq
= content_handler_test_attributes
;
2245 set_expected_seq(test_seq
);
2246 hr
= ISAXXMLReader_parse(reader
, var
);
2247 EXPECT_HR(hr
, S_OK
);
2249 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2250 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2251 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2253 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2255 IStream_Release(stream
);
2257 V_VT(&var
) = VT_UNKNOWN
;
2258 V_UNKNOWN(&var
) = (IUnknown
*)&instream
;
2260 test_seq
= read_test_seq
;
2262 set_expected_seq(test_seq
);
2263 hr
= ISAXXMLReader_parse(reader
, var
);
2264 EXPECT_HR(hr
, S_OK
);
2265 ok(read_cnt
== 7, "read_cnt = %d\n", read_cnt
);
2266 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "Read call test", FALSE
);
2268 V_VT(&var
) = VT_BSTR
;
2269 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
2271 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2272 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2273 test_seq
= content_handler_test2_alternate
;
2275 test_seq
= content_handler_test2
;
2277 set_expected_seq(test_seq
);
2278 hr
= ISAXXMLReader_parse(reader
, var
);
2279 EXPECT_HR(hr
, S_OK
);
2280 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
2285 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2286 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2287 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
2290 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2291 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2292 test_seq
= content_handler_test1_alternate
;
2294 test_seq
= content_handler_test1
;
2295 set_expected_seq(test_seq
);
2296 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2297 EXPECT_HR(hr
, S_OK
);
2298 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
2301 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2302 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2303 test_seq
= content_handler_testerror_alternate
;
2305 test_seq
= content_handler_testerror
;
2306 set_expected_seq(test_seq
);
2307 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2308 EXPECT_HR(hr
, E_FAIL
);
2309 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
2311 /* callback ret values */
2312 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2313 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2315 test_seq
= content_handler_test_callback_rets_alt
;
2316 set_expected_seq(test_seq
);
2317 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2318 EXPECT_HR(hr
, S_OK
);
2322 test_seq
= content_handler_test_callback_rets
;
2323 set_expected_seq(test_seq
);
2324 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2325 EXPECT_HR(hr
, S_FALSE
);
2327 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
2329 DeleteFileA(testXmlA
);
2331 /* parse from IXMLDOMDocument */
2332 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
2333 &IID_IXMLDOMDocument
, (void**)&doc
);
2334 EXPECT_HR(hr
, S_OK
);
2336 str
= SysAllocString(szSimpleXML
);
2337 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
2338 EXPECT_HR(hr
, S_OK
);
2341 V_VT(&var
) = VT_UNKNOWN
;
2342 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
2344 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2345 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2346 test_seq
= content_handler_test2_alternate
;
2348 test_seq
= content_handler_test2
;
2350 set_expected_seq(test_seq
);
2351 hr
= ISAXXMLReader_parse(reader
, var
);
2352 EXPECT_HR(hr
, S_OK
);
2353 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
2354 IXMLDOMDocument_Release(doc
);
2356 /* xml:space test */
2357 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2358 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2360 test_seq
= xmlspaceattr_test_alternate
;
2363 test_seq
= xmlspaceattr_test
;
2365 set_expected_seq(test_seq
);
2366 V_VT(&var
) = VT_BSTR
;
2367 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
2368 hr
= ISAXXMLReader_parse(reader
, var
);
2369 EXPECT_HR(hr
, S_OK
);
2371 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2372 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2374 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
2377 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
2379 /* switch off 'namespaces' feature */
2380 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE
);
2381 EXPECT_HR(hr
, S_OK
);
2383 stream
= create_test_stream(test_attributes
, -1);
2384 V_VT(&var
) = VT_UNKNOWN
;
2385 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2387 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2388 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2390 test_seq
= content_handler_test_attributes_alt_no_ns
;
2393 test_seq
= content_handler_test_attributes
;
2395 set_expected_seq(test_seq
);
2396 hr
= ISAXXMLReader_parse(reader
, var
);
2397 EXPECT_HR(hr
, S_OK
);
2398 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2399 IStream_Release(stream
);
2400 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_TRUE
);
2401 EXPECT_HR(hr
, S_OK
);
2403 /* switch off 'namespace-prefixes' feature */
2404 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_FALSE
);
2405 EXPECT_HR(hr
, S_OK
);
2407 stream
= create_test_stream(test_attributes
, -1);
2408 V_VT(&var
) = VT_UNKNOWN
;
2409 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2411 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2412 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2414 test_seq
= content_handler_test_attributes_alt_no_prefix
;
2417 test_seq
= content_handler_test_attributes_no_prefix
;
2419 set_expected_seq(test_seq
);
2420 hr
= ISAXXMLReader_parse(reader
, var
);
2421 EXPECT_HR(hr
, S_OK
);
2422 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2423 IStream_Release(stream
);
2425 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_TRUE
);
2426 EXPECT_HR(hr
, S_OK
);
2428 /* attribute normalization */
2429 stream
= create_test_stream(attribute_normalize
, -1);
2430 V_VT(&var
) = VT_UNKNOWN
;
2431 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2433 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2434 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2436 test_seq
= attribute_norm_alt
;
2439 test_seq
= attribute_norm
;
2441 set_expected_seq(test_seq
);
2442 hr
= ISAXXMLReader_parse(reader
, var
);
2443 EXPECT_HR(hr
, S_OK
);
2444 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "attribute value normalization", TRUE
);
2445 IStream_Release(stream
);
2447 resolver
= (void*)0xdeadbeef;
2448 hr
= ISAXXMLReader_getEntityResolver(reader
, &resolver
);
2449 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2450 ok(resolver
== NULL
, "got %p\n", resolver
);
2452 hr
= ISAXXMLReader_putEntityResolver(reader
, NULL
);
2453 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "got 0x%08x\n", hr
);
2455 /* CDATA sections */
2456 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2458 V_VT(&var
) = VT_UNKNOWN
;
2459 V_UNKNOWN(&var
) = (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
;
2460 hr
= ISAXXMLReader_putProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), var
);
2461 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2463 stream
= create_test_stream(test_cdata_xml
, -1);
2464 V_VT(&var
) = VT_UNKNOWN
;
2465 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2467 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2468 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2469 test_seq
= cdata_test_alt
;
2471 test_seq
= cdata_test
;
2473 set_expected_seq(test_seq
);
2474 hr
= ISAXXMLReader_parse(reader
, var
);
2475 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2476 sprintf(seqname
, "%s: cdata test", table
->name
);
2477 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2479 IStream_Release(stream
);
2481 /* 2. CDATA sections */
2482 stream
= create_test_stream(test2_cdata_xml
, -1);
2483 V_VT(&var
) = VT_UNKNOWN
;
2484 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2486 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2487 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2488 test_seq
= cdata_test2_alt
;
2490 test_seq
= cdata_test2
;
2492 set_expected_seq(test_seq
);
2493 hr
= ISAXXMLReader_parse(reader
, var
);
2494 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2495 sprintf(seqname
, "%s: cdata test 2", table
->name
);
2496 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2498 IStream_Release(stream
);
2500 /* 3. CDATA sections */
2501 stream
= create_test_stream(test3_cdata_xml
, -1);
2502 V_VT(&var
) = VT_UNKNOWN
;
2503 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2505 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2506 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2507 test_seq
= cdata_test3_alt
;
2509 test_seq
= cdata_test3
;
2511 set_expected_seq(test_seq
);
2512 hr
= ISAXXMLReader_parse(reader
, var
);
2513 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2514 sprintf(seqname
, "%s: cdata test 3", table
->name
);
2515 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2517 IStream_Release(stream
);
2519 ISAXXMLReader_Release(reader
);
2526 struct saxreader_props_test_t
2528 const char *prop_name
;
2532 static const struct saxreader_props_test_t props_test_data
[] = {
2533 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
},
2534 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&declhandler
.ISAXDeclHandler_iface
},
2538 static void test_saxreader_properties(void)
2540 const struct saxreader_props_test_t
*ptr
= props_test_data
;
2541 ISAXXMLReader
*reader
;
2546 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2547 &IID_ISAXXMLReader
, (void**)&reader
);
2548 EXPECT_HR(hr
, S_OK
);
2550 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
2551 EXPECT_HR(hr
, E_POINTER
);
2553 while (ptr
->prop_name
)
2558 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2559 init_saxdeclhandler(&declhandler
, S_OK
);
2561 V_VT(&v
) = VT_EMPTY
;
2562 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2563 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2564 EXPECT_HR(hr
, S_OK
);
2565 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2566 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2569 V_VT(&v
) = VT_UNKNOWN
;
2570 V_UNKNOWN(&v
) = ptr
->iface
;
2571 ref
= get_refcount(ptr
->iface
);
2572 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2573 EXPECT_HR(hr
, S_OK
);
2574 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2577 V_VT(&v
) = VT_DISPATCH
;
2578 V_UNKNOWN(&v
) = ptr
->iface
;
2579 ref
= get_refcount(ptr
->iface
);
2580 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2581 EXPECT_HR(hr
, S_OK
);
2582 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2584 /* VT_VARIANT|VT_BYREF with VT_UNKNOWN in referenced variant */
2585 V_VT(&varref
) = VT_UNKNOWN
;
2586 V_UNKNOWN(&varref
) = ptr
->iface
;
2588 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2589 V_VARIANTREF(&v
) = &varref
;
2590 ref
= get_refcount(ptr
->iface
);
2591 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2592 EXPECT_HR(hr
, S_OK
);
2593 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2595 /* VT_VARIANT|VT_BYREF with VT_DISPATCH in referenced variant */
2596 V_VT(&varref
) = VT_DISPATCH
;
2597 V_UNKNOWN(&varref
) = ptr
->iface
;
2599 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2600 V_VARIANTREF(&v
) = &varref
;
2601 ref
= get_refcount(ptr
->iface
);
2602 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2603 EXPECT_HR(hr
, S_OK
);
2604 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2606 V_VT(&v
) = VT_EMPTY
;
2607 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2609 ref
= get_refcount(ptr
->iface
);
2610 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2611 EXPECT_HR(hr
, S_OK
);
2612 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2613 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2614 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2617 V_VT(&v
) = VT_EMPTY
;
2618 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2619 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2620 EXPECT_HR(hr
, S_OK
);
2622 V_VT(&v
) = VT_EMPTY
;
2623 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2624 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2625 EXPECT_HR(hr
, S_OK
);
2626 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2627 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2629 V_VT(&v
) = VT_UNKNOWN
;
2630 V_UNKNOWN(&v
) = ptr
->iface
;
2631 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2632 EXPECT_HR(hr
, S_OK
);
2634 /* only VT_EMPTY seems to be valid to reset property */
2636 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2637 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2638 EXPECT_HR(hr
, E_INVALIDARG
);
2640 V_VT(&v
) = VT_EMPTY
;
2641 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2642 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2643 EXPECT_HR(hr
, S_OK
);
2644 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2645 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2648 V_VT(&v
) = VT_UNKNOWN
;
2649 V_UNKNOWN(&v
) = NULL
;
2650 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2651 EXPECT_HR(hr
, S_OK
);
2653 V_VT(&v
) = VT_EMPTY
;
2654 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2655 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2656 EXPECT_HR(hr
, S_OK
);
2657 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2658 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2660 /* block QueryInterface on handler riid */
2661 V_VT(&v
) = VT_UNKNOWN
;
2662 V_UNKNOWN(&v
) = ptr
->iface
;
2663 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2664 EXPECT_HR(hr
, S_OK
);
2666 init_saxlexicalhandler(&lexicalhandler
, E_NOINTERFACE
);
2667 init_saxdeclhandler(&declhandler
, E_NOINTERFACE
);
2669 V_VT(&v
) = VT_UNKNOWN
;
2670 V_UNKNOWN(&v
) = ptr
->iface
;
2671 EXPECT_REF(ptr
->iface
, 1);
2672 ref
= get_refcount(ptr
->iface
);
2673 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2674 EXPECT_HR(hr
, E_NOINTERFACE
);
2675 EXPECT_REF(ptr
->iface
, 1);
2677 V_VT(&v
) = VT_EMPTY
;
2678 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2679 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2680 EXPECT_HR(hr
, S_OK
);
2681 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2682 ok(V_UNKNOWN(&v
) != NULL
, "got %p\n", V_UNKNOWN(&v
));
2688 ISAXXMLReader_Release(reader
);
2690 if (!is_clsid_supported(&CLSID_SAXXMLReader40
, reader_support_data
))
2693 hr
= CoCreateInstance(&CLSID_SAXXMLReader40
, NULL
, CLSCTX_INPROC_SERVER
,
2694 &IID_ISAXXMLReader
, (void**)&reader
);
2695 EXPECT_HR(hr
, S_OK
);
2697 /* xmldecl-version property */
2698 V_VT(&v
) = VT_EMPTY
;
2699 V_BSTR(&v
) = (void*)0xdeadbeef;
2700 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2701 EXPECT_HR(hr
, S_OK
);
2702 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2703 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2705 /* stream without declaration */
2707 V_BSTR(&v
) = _bstr_("<element></element>");
2708 hr
= ISAXXMLReader_parse(reader
, v
);
2709 EXPECT_HR(hr
, S_OK
);
2711 V_VT(&v
) = VT_EMPTY
;
2712 V_BSTR(&v
) = (void*)0xdeadbeef;
2713 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2714 EXPECT_HR(hr
, S_OK
);
2715 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2716 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2718 /* stream with declaration */
2720 V_BSTR(&v
) = _bstr_("<?xml version=\"1.0\"?><element></element>");
2721 hr
= ISAXXMLReader_parse(reader
, v
);
2722 EXPECT_HR(hr
, S_OK
);
2724 /* VT_BSTR|VT_BYREF input type */
2725 str
= _bstr_("<?xml version=\"1.0\"?><element></element>");
2726 V_VT(&v
) = VT_BSTR
|VT_BYREF
;
2727 V_BSTRREF(&v
) = &str
;
2728 hr
= ISAXXMLReader_parse(reader
, v
);
2729 EXPECT_HR(hr
, S_OK
);
2731 V_VT(&v
) = VT_EMPTY
;
2732 V_BSTR(&v
) = (void*)0xdeadbeef;
2733 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2734 EXPECT_HR(hr
, S_OK
);
2735 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2736 ok(!lstrcmpW(V_BSTR(&v
), _bstr_("1.0")), "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2739 ISAXXMLReader_Release(reader
);
2743 struct feature_ns_entry_t
{
2747 VARIANT_BOOL value2
; /* feature value after feature set to 0xc */
2750 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2751 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
, VARIANT_FALSE
},
2752 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
, VARIANT_FALSE
},
2753 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
, VARIANT_TRUE
},
2754 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
, VARIANT_TRUE
},
2758 static const char *feature_names
[] = {
2759 "http://xml.org/sax/features/namespaces",
2760 "http://xml.org/sax/features/namespace-prefixes",
2764 static void test_saxreader_features(void)
2766 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2767 ISAXXMLReader
*reader
;
2775 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2778 win_skip("can't create %s instance\n", entry
->clsid
);
2783 name
= feature_names
;
2787 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2788 EXPECT_HR(hr
, S_OK
);
2789 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2792 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), value
);
2793 EXPECT_HR(hr
, S_OK
);
2796 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2797 EXPECT_HR(hr
, S_OK
);
2798 ok(entry
->value2
== value
, "%s: got wrong value %x, expected %x\n", entry
->clsid
, value
, entry
->value2
);
2800 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_FALSE
);
2801 EXPECT_HR(hr
, S_OK
);
2803 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2804 EXPECT_HR(hr
, S_OK
);
2805 ok(value
== VARIANT_FALSE
, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry
->clsid
, value
);
2807 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_TRUE
);
2808 EXPECT_HR(hr
, S_OK
);
2810 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2811 EXPECT_HR(hr
, S_OK
);
2812 ok(value
== VARIANT_TRUE
, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry
->clsid
, value
);
2817 ISAXXMLReader_Release(reader
);
2823 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2824 static const CHAR UTF8BOMTest
[] =
2825 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2828 struct enc_test_entry_t
{
2836 static const struct enc_test_entry_t encoding_test_data
[] = {
2837 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2838 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2839 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, FALSE
},
2840 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, FALSE
},
2844 static void test_saxreader_encoding(void)
2846 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2847 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2848 static const CHAR testXmlA
[] = "test.xml";
2852 ISAXXMLReader
*reader
;
2858 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2861 win_skip("can't create %s instance\n", entry
->clsid
);
2866 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2867 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2868 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2871 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2872 todo_wine_if(entry
->todo
)
2873 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2875 DeleteFileA(testXmlA
);
2877 /* try BSTR input with no BOM or '<?xml' instruction */
2878 V_VT(&input
) = VT_BSTR
;
2879 V_BSTR(&input
) = _bstr_("<element></element>");
2880 hr
= ISAXXMLReader_parse(reader
, input
);
2881 EXPECT_HR(hr
, S_OK
);
2883 ISAXXMLReader_Release(reader
);
2890 static void test_mxwriter_handlers(void)
2896 static REFIID riids
[] =
2898 &IID_ISAXContentHandler
,
2899 &IID_ISAXLexicalHandler
,
2900 &IID_ISAXDeclHandler
,
2901 &IID_ISAXDTDHandler
,
2902 &IID_ISAXErrorHandler
,
2903 &IID_IVBSAXDeclHandler
,
2904 &IID_IVBSAXLexicalHandler
,
2905 &IID_IVBSAXContentHandler
,
2906 &IID_IVBSAXDTDHandler
,
2907 &IID_IVBSAXErrorHandler
2910 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2911 &IID_IMXWriter
, (void**)&writer
);
2912 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2914 EXPECT_REF(writer
, 1);
2916 for (i
= 0; i
< sizeof(riids
)/sizeof(REFIID
); i
++)
2921 /* handler from IMXWriter */
2922 hr
= IMXWriter_QueryInterface(writer
, riids
[i
], (void**)&handler
);
2923 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2924 EXPECT_REF(writer
, 2);
2925 EXPECT_REF(handler
, 2);
2927 /* IMXWriter from a handler */
2928 hr
= IUnknown_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2929 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2930 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2931 EXPECT_REF(writer
, 3);
2932 IMXWriter_Release(writer2
);
2933 IUnknown_Release(handler
);
2936 IMXWriter_Release(writer
);
2939 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2941 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2942 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2943 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2944 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2948 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2950 { &CLSID_SAXAttributes
, "SAXAttributes" },
2951 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2952 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2953 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2957 struct mxwriter_props_t
2961 VARIANT_BOOL disable_escape
;
2962 VARIANT_BOOL indent
;
2963 VARIANT_BOOL omitdecl
;
2964 VARIANT_BOOL standalone
;
2965 const char *encoding
;
2968 static const struct mxwriter_props_t mxwriter_default_props
[] =
2970 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2971 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2972 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2973 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2977 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2981 while (table
->clsid
)
2988 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2995 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2996 &IID_IMXWriter
, (void**)&writer
);
2997 EXPECT_HR(hr
, S_OK
);
3000 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
3001 EXPECT_HR(hr
, S_OK
);
3002 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
3004 b
= !table
->disable_escape
;
3005 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
3006 EXPECT_HR(hr
, S_OK
);
3007 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
3008 table
->disable_escape
);
3011 hr
= IMXWriter_get_indent(writer
, &b
);
3012 EXPECT_HR(hr
, S_OK
);
3013 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
3015 b
= !table
->omitdecl
;
3016 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
3017 EXPECT_HR(hr
, S_OK
);
3018 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
3020 b
= !table
->standalone
;
3021 hr
= IMXWriter_get_standalone(writer
, &b
);
3022 EXPECT_HR(hr
, S_OK
);
3023 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
3025 hr
= IMXWriter_get_encoding(writer
, &encoding
);
3026 EXPECT_HR(hr
, S_OK
);
3027 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
3028 i
, wine_dbgstr_w(encoding
), table
->encoding
);
3029 SysFreeString(encoding
);
3031 IMXWriter_Release(writer
);
3038 static void test_mxwriter_properties(void)
3040 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
3041 static const WCHAR testW
[] = {'t','e','s','t',0};
3042 ISAXContentHandler
*content
;
3049 test_mxwriter_default_properties(mxwriter_default_props
);
3051 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3052 &IID_IMXWriter
, (void**)&writer
);
3053 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3055 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
3056 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3058 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
3059 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3061 hr
= IMXWriter_get_indent(writer
, NULL
);
3062 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3064 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
3065 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3067 hr
= IMXWriter_get_standalone(writer
, NULL
);
3068 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3071 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
3072 ok(hr
== S_OK
, "got %08x\n", hr
);
3075 hr
= IMXWriter_get_standalone(writer
, &b
);
3076 ok(hr
== S_OK
, "got %08x\n", hr
);
3077 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
3079 hr
= IMXWriter_get_encoding(writer
, NULL
);
3080 EXPECT_HR(hr
, E_POINTER
);
3082 /* UTF-16 is a default setting apparently */
3083 str
= (void*)0xdeadbeef;
3084 hr
= IMXWriter_get_encoding(writer
, &str
);
3085 EXPECT_HR(hr
, S_OK
);
3086 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
3088 str2
= (void*)0xdeadbeef;
3089 hr
= IMXWriter_get_encoding(writer
, &str2
);
3090 ok(hr
== S_OK
, "got %08x\n", hr
);
3091 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
3093 SysFreeString(str2
);
3096 /* put empty string */
3097 str
= SysAllocString(emptyW
);
3098 hr
= IMXWriter_put_encoding(writer
, str
);
3099 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3102 str
= (void*)0xdeadbeef;
3103 hr
= IMXWriter_get_encoding(writer
, &str
);
3104 EXPECT_HR(hr
, S_OK
);
3105 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
3108 /* invalid encoding name */
3109 str
= SysAllocString(testW
);
3110 hr
= IMXWriter_put_encoding(writer
, str
);
3111 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3114 /* test case sensivity */
3115 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
3116 EXPECT_HR(hr
, S_OK
);
3117 str
= (void*)0xdeadbeef;
3118 hr
= IMXWriter_get_encoding(writer
, &str
);
3119 EXPECT_HR(hr
, S_OK
);
3120 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
3123 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
3124 EXPECT_HR(hr
, S_OK
);
3125 str
= (void*)0xdeadbeef;
3126 hr
= IMXWriter_get_encoding(writer
, &str
);
3127 EXPECT_HR(hr
, S_OK
);
3128 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
3131 /* how it affects document creation */
3132 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3133 EXPECT_HR(hr
, S_OK
);
3135 hr
= ISAXContentHandler_startDocument(content
);
3136 EXPECT_HR(hr
, S_OK
);
3137 hr
= ISAXContentHandler_endDocument(content
);
3138 EXPECT_HR(hr
, S_OK
);
3140 V_VT(&dest
) = VT_EMPTY
;
3141 hr
= IMXWriter_get_output(writer
, &dest
);
3142 EXPECT_HR(hr
, S_OK
);
3143 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3144 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
3145 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3146 VariantClear(&dest
);
3147 ISAXContentHandler_Release(content
);
3149 hr
= IMXWriter_get_version(writer
, NULL
);
3150 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3151 /* default version is 'surprisingly' 1.0 */
3152 hr
= IMXWriter_get_version(writer
, &str
);
3153 ok(hr
== S_OK
, "got %08x\n", hr
);
3154 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
3157 /* store version string as is */
3158 hr
= IMXWriter_put_version(writer
, NULL
);
3159 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3161 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
3162 ok(hr
== S_OK
, "got %08x\n", hr
);
3164 hr
= IMXWriter_put_version(writer
, _bstr_(""));
3165 ok(hr
== S_OK
, "got %08x\n", hr
);
3166 hr
= IMXWriter_get_version(writer
, &str
);
3167 ok(hr
== S_OK
, "got %08x\n", hr
);
3168 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
3171 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
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_("a.b")), "got %s\n", wine_dbgstr_w(str
));
3178 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
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_("2.0")), "got %s\n", wine_dbgstr_w(str
));
3185 IMXWriter_Release(writer
);
3189 static void test_mxwriter_flush(void)
3191 ISAXContentHandler
*content
;
3194 ULARGE_INTEGER pos2
;
3202 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3203 &IID_IMXWriter
, (void**)&writer
);
3204 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3206 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3207 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3208 EXPECT_REF(stream
, 1);
3210 /* detach when nothing was attached */
3211 V_VT(&dest
) = VT_EMPTY
;
3212 hr
= IMXWriter_put_output(writer
, dest
);
3213 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3216 V_VT(&dest
) = VT_UNKNOWN
;
3217 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3218 hr
= IMXWriter_put_output(writer
, dest
);
3219 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3220 todo_wine
EXPECT_REF(stream
, 3);
3222 /* detach setting VT_EMPTY destination */
3223 V_VT(&dest
) = VT_EMPTY
;
3224 hr
= IMXWriter_put_output(writer
, dest
);
3225 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3226 EXPECT_REF(stream
, 1);
3228 V_VT(&dest
) = VT_UNKNOWN
;
3229 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3230 hr
= IMXWriter_put_output(writer
, dest
);
3231 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3233 /* flush() doesn't detach a stream */
3234 hr
= IMXWriter_flush(writer
);
3235 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3236 todo_wine
EXPECT_REF(stream
, 3);
3239 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3240 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3241 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3243 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3244 ok(hr
== S_OK
, "got %08x\n", hr
);
3246 hr
= ISAXContentHandler_startDocument(content
);
3247 ok(hr
== S_OK
, "got %08x\n", hr
);
3250 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3251 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3252 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
3254 /* already started */
3255 hr
= ISAXContentHandler_startDocument(content
);
3256 ok(hr
== S_OK
, "got %08x\n", hr
);
3258 hr
= ISAXContentHandler_endDocument(content
);
3259 ok(hr
== S_OK
, "got %08x\n", hr
);
3261 /* flushed on endDocument() */
3263 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3264 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3265 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
3267 IStream_Release(stream
);
3269 /* auto-flush feature */
3270 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3271 EXPECT_HR(hr
, S_OK
);
3272 EXPECT_REF(stream
, 1);
3274 V_VT(&dest
) = VT_UNKNOWN
;
3275 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3276 hr
= IMXWriter_put_output(writer
, dest
);
3277 EXPECT_HR(hr
, S_OK
);
3279 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_FALSE
);
3280 EXPECT_HR(hr
, S_OK
);
3282 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3283 EXPECT_HR(hr
, S_OK
);
3285 hr
= ISAXContentHandler_startDocument(content
);
3286 EXPECT_HR(hr
, S_OK
);
3288 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3289 EXPECT_HR(hr
, S_OK
);
3291 /* internal buffer is flushed automatically on certain threshold */
3294 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3295 EXPECT_HR(hr
, S_OK
);
3296 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3299 buff
= HeapAlloc(GetProcessHeap(), 0, len
+1);
3300 memset(buff
, 'A', len
);
3302 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3303 EXPECT_HR(hr
, S_OK
);
3307 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3308 EXPECT_HR(hr
, S_OK
);
3309 ok(pos2
.QuadPart
!= 0, "unexpected stream beginning\n");
3311 hr
= IMXWriter_get_output(writer
, NULL
);
3312 EXPECT_HR(hr
, E_POINTER
);
3314 ref
= get_refcount(stream
);
3315 V_VT(&dest
) = VT_EMPTY
;
3316 hr
= IMXWriter_get_output(writer
, &dest
);
3317 EXPECT_HR(hr
, S_OK
);
3318 ok(V_VT(&dest
) == VT_UNKNOWN
, "got vt type %d\n", V_VT(&dest
));
3319 ok(V_UNKNOWN(&dest
) == (IUnknown
*)stream
, "got pointer %p\n", V_UNKNOWN(&dest
));
3320 ok(ref
+1 == get_refcount(stream
), "expected increased refcount\n");
3321 VariantClear(&dest
);
3323 hr
= ISAXContentHandler_endDocument(content
);
3324 EXPECT_HR(hr
, S_OK
);
3326 IStream_Release(stream
);
3328 /* test char count lower than threshold */
3329 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3330 EXPECT_HR(hr
, S_OK
);
3331 EXPECT_REF(stream
, 1);
3333 hr
= ISAXContentHandler_startDocument(content
);
3334 EXPECT_HR(hr
, S_OK
);
3336 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3337 EXPECT_HR(hr
, S_OK
);
3341 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3342 EXPECT_HR(hr
, S_OK
);
3343 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3345 memset(buff
, 'A', len
);
3347 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
- 8);
3348 EXPECT_HR(hr
, S_OK
);
3352 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3353 EXPECT_HR(hr
, S_OK
);
3354 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3356 hr
= ISAXContentHandler_endDocument(content
);
3357 EXPECT_HR(hr
, S_OK
);
3359 /* test auto-flush function when stream is not set */
3360 V_VT(&dest
) = VT_EMPTY
;
3361 hr
= IMXWriter_put_output(writer
, dest
);
3362 EXPECT_HR(hr
, S_OK
);
3364 hr
= ISAXContentHandler_startDocument(content
);
3365 EXPECT_HR(hr
, S_OK
);
3367 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3368 EXPECT_HR(hr
, S_OK
);
3370 memset(buff
, 'A', len
);
3372 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3373 EXPECT_HR(hr
, S_OK
);
3375 V_VT(&dest
) = VT_EMPTY
;
3376 hr
= IMXWriter_get_output(writer
, &dest
);
3377 EXPECT_HR(hr
, S_OK
);
3378 len
+= strlen("<a>");
3379 ok(SysStringLen(V_BSTR(&dest
)) == len
, "got len=%d, expected %d\n", SysStringLen(V_BSTR(&dest
)), len
);
3380 VariantClear(&dest
);
3382 HeapFree(GetProcessHeap(), 0, buff
);
3383 ISAXContentHandler_Release(content
);
3384 IStream_Release(stream
);
3385 IMXWriter_Release(writer
);
3389 static void test_mxwriter_startenddocument(void)
3391 ISAXContentHandler
*content
;
3396 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3397 &IID_IMXWriter
, (void**)&writer
);
3398 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3400 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3401 ok(hr
== S_OK
, "got %08x\n", hr
);
3403 hr
= ISAXContentHandler_startDocument(content
);
3404 ok(hr
== S_OK
, "got %08x\n", hr
);
3406 hr
= ISAXContentHandler_endDocument(content
);
3407 ok(hr
== S_OK
, "got %08x\n", hr
);
3409 V_VT(&dest
) = VT_EMPTY
;
3410 hr
= IMXWriter_get_output(writer
, &dest
);
3411 ok(hr
== S_OK
, "got %08x\n", hr
);
3412 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3413 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3414 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3415 VariantClear(&dest
);
3417 /* now try another startDocument */
3418 hr
= ISAXContentHandler_startDocument(content
);
3419 ok(hr
== S_OK
, "got %08x\n", hr
);
3420 /* and get duplicated prolog */
3421 V_VT(&dest
) = VT_EMPTY
;
3422 hr
= IMXWriter_get_output(writer
, &dest
);
3423 ok(hr
== S_OK
, "got %08x\n", hr
);
3424 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3425 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
3426 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3427 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3428 VariantClear(&dest
);
3430 ISAXContentHandler_Release(content
);
3431 IMXWriter_Release(writer
);
3433 /* now with omitted declaration */
3434 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3435 &IID_IMXWriter
, (void**)&writer
);
3436 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3438 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3439 ok(hr
== S_OK
, "got %08x\n", hr
);
3441 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3442 ok(hr
== S_OK
, "got %08x\n", hr
);
3444 hr
= ISAXContentHandler_startDocument(content
);
3445 ok(hr
== S_OK
, "got %08x\n", hr
);
3447 hr
= ISAXContentHandler_endDocument(content
);
3448 ok(hr
== S_OK
, "got %08x\n", hr
);
3450 V_VT(&dest
) = VT_EMPTY
;
3451 hr
= IMXWriter_get_output(writer
, &dest
);
3452 ok(hr
== S_OK
, "got %08x\n", hr
);
3453 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3454 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3455 VariantClear(&dest
);
3457 ISAXContentHandler_Release(content
);
3458 IMXWriter_Release(writer
);
3465 StartElement
= 0x001,
3467 StartEndElement
= 0x011,
3468 DisableEscaping
= 0x100
3471 struct writer_startendelement_t
{
3473 enum startendtype type
;
3475 const char *local_name
;
3479 ISAXAttributes
*attr
;
3482 static const char startelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\'\">";
3483 static const char startendelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\'\"/>";
3484 static const char startendelement_noescape_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&\">\'\"/>";
3486 static const struct writer_startendelement_t writer_startendelement
[] = {
3488 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3489 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3490 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3491 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
3492 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3494 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3495 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3496 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
3497 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3498 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3500 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3501 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
3502 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3503 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3504 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3506 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
3507 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3508 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3509 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3510 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3512 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3513 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3514 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3515 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
3516 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3518 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3519 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3520 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3521 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3522 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3524 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3525 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3526 /* endElement tests */
3527 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3528 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3529 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3531 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
3532 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3533 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3534 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3535 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
3537 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3538 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3539 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3540 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
3541 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3543 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3544 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3545 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
3546 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3547 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3549 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3550 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3551 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3552 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3553 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3555 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
3556 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3557 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3558 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3559 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3561 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3562 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3563 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3564 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3566 /* with attributes */
3567 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3569 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3570 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3571 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3572 /* empty elements */
3573 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3574 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3576 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3577 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3578 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
3579 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
3580 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
3582 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
3584 /* with disabled output escaping */
3585 { &CLSID_MXXMLWriter
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3586 { &CLSID_MXXMLWriter30
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3587 { &CLSID_MXXMLWriter40
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3588 { &CLSID_MXXMLWriter60
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3593 static void get_class_support_data(struct msxmlsupported_data_t
*table
, REFIID riid
)
3595 while (table
->clsid
)
3600 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, riid
, (void**)&unk
);
3601 if (hr
== S_OK
) IUnknown_Release(unk
);
3603 table
->supported
= hr
== S_OK
;
3604 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
3610 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
3614 while (table
->clsid
)
3616 ISAXContentHandler
*content
;
3620 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3627 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3628 &IID_IMXWriter
, (void**)&writer
);
3629 EXPECT_HR(hr
, S_OK
);
3631 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3632 EXPECT_HR(hr
, S_OK
);
3634 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3635 EXPECT_HR(hr
, S_OK
);
3637 hr
= ISAXContentHandler_startDocument(content
);
3638 EXPECT_HR(hr
, S_OK
);
3640 if (table
->type
& DisableEscaping
)
3642 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3643 EXPECT_HR(hr
, S_OK
);
3646 if (table
->type
& StartElement
)
3648 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), table
->uri
? strlen(table
->uri
) : 0,
3649 _bstr_(table
->local_name
), table
->local_name
? strlen(table
->local_name
) : 0, _bstr_(table
->qname
),
3650 table
->qname
? strlen(table
->qname
) : 0, table
->attr
);
3651 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3654 if (table
->type
& EndElement
)
3656 hr
= ISAXContentHandler_endElement(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);
3659 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3667 V_VT(&dest
) = VT_EMPTY
;
3668 hr
= IMXWriter_get_output(writer
, &dest
);
3669 EXPECT_HR(hr
, S_OK
);
3670 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3671 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3672 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3673 VariantClear(&dest
);
3676 ISAXContentHandler_Release(content
);
3677 IMXWriter_Release(writer
);
3686 /* point of these test is to start/end element with different names and name lengths */
3687 struct writer_startendelement2_t
{
3689 const char *qnamestart
;
3691 const char *qnameend
;
3697 static const struct writer_startendelement2_t writer_startendelement2
[] = {
3698 { &CLSID_MXXMLWriter
, "a", -1, "b", -1, "<a/>", S_OK
},
3699 { &CLSID_MXXMLWriter30
, "a", -1, "b", -1, "<a/>", S_OK
},
3700 { &CLSID_MXXMLWriter40
, "a", -1, "b", -1, "<a/>", S_OK
},
3701 /* -1 length is not allowed for version 6 */
3702 { &CLSID_MXXMLWriter60
, "a", -1, "b", -1, "<a/>", E_INVALIDARG
},
3704 { &CLSID_MXXMLWriter
, "a", 1, "b", 1, "<a/>", S_OK
},
3705 { &CLSID_MXXMLWriter30
, "a", 1, "b", 1, "<a/>", S_OK
},
3706 { &CLSID_MXXMLWriter40
, "a", 1, "b", 1, "<a/>", S_OK
},
3707 { &CLSID_MXXMLWriter60
, "a", 1, "b", 1, "<a/>", S_OK
},
3711 static void test_mxwriter_startendelement_batch2(const struct writer_startendelement2_t
*table
)
3715 while (table
->clsid
)
3717 ISAXContentHandler
*content
;
3721 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3728 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3729 &IID_IMXWriter
, (void**)&writer
);
3730 EXPECT_HR(hr
, S_OK
);
3732 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3733 EXPECT_HR(hr
, S_OK
);
3735 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3736 EXPECT_HR(hr
, S_OK
);
3738 hr
= ISAXContentHandler_startDocument(content
);
3739 EXPECT_HR(hr
, S_OK
);
3741 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3742 _bstr_(table
->qnamestart
), table
->qnamestart_len
, NULL
);
3743 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3745 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3746 _bstr_(table
->qnameend
), table
->qnameend_len
);
3747 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3754 V_VT(&dest
) = VT_EMPTY
;
3755 hr
= IMXWriter_get_output(writer
, &dest
);
3756 EXPECT_HR(hr
, S_OK
);
3757 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3758 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3759 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3760 VariantClear(&dest
);
3763 ISAXContentHandler_Release(content
);
3764 IMXWriter_Release(writer
);
3774 static void test_mxwriter_startendelement(void)
3776 ISAXContentHandler
*content
;
3781 test_mxwriter_startendelement_batch(writer_startendelement
);
3782 test_mxwriter_startendelement_batch2(writer_startendelement2
);
3784 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3785 &IID_IMXWriter
, (void**)&writer
);
3786 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3788 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3789 ok(hr
== S_OK
, "got %08x\n", hr
);
3791 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3792 ok(hr
== S_OK
, "got %08x\n", hr
);
3794 hr
= ISAXContentHandler_startDocument(content
);
3795 ok(hr
== S_OK
, "got %08x\n", hr
);
3797 /* all string pointers should be not null */
3798 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
3799 ok(hr
== S_OK
, "got %08x\n", hr
);
3801 V_VT(&dest
) = VT_EMPTY
;
3802 hr
= IMXWriter_get_output(writer
, &dest
);
3803 ok(hr
== S_OK
, "got %08x\n", hr
);
3804 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3805 ok(!lstrcmpW(_bstr_("<>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3806 VariantClear(&dest
);
3808 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
3809 ok(hr
== S_OK
, "got %08x\n", hr
);
3811 V_VT(&dest
) = VT_EMPTY
;
3812 hr
= IMXWriter_get_output(writer
, &dest
);
3813 ok(hr
== S_OK
, "got %08x\n", hr
);
3814 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3815 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3816 VariantClear(&dest
);
3818 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
3819 EXPECT_HR(hr
, E_INVALIDARG
);
3821 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
3822 EXPECT_HR(hr
, E_INVALIDARG
);
3824 /* only local name is an error too */
3825 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
3826 EXPECT_HR(hr
, E_INVALIDARG
);
3828 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
3829 EXPECT_HR(hr
, S_OK
);
3831 V_VT(&dest
) = VT_EMPTY
;
3832 hr
= IMXWriter_get_output(writer
, &dest
);
3833 EXPECT_HR(hr
, S_OK
);
3834 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3835 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3836 VariantClear(&dest
);
3838 hr
= ISAXContentHandler_endDocument(content
);
3839 EXPECT_HR(hr
, S_OK
);
3841 V_VT(&dest
) = VT_EMPTY
;
3842 hr
= IMXWriter_put_output(writer
, dest
);
3843 EXPECT_HR(hr
, S_OK
);
3845 V_VT(&dest
) = VT_EMPTY
;
3846 hr
= IMXWriter_get_output(writer
, &dest
);
3847 EXPECT_HR(hr
, S_OK
);
3848 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3849 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3850 VariantClear(&dest
);
3852 hr
= ISAXContentHandler_startDocument(content
);
3853 EXPECT_HR(hr
, S_OK
);
3855 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
3856 EXPECT_HR(hr
, S_OK
);
3858 V_VT(&dest
) = VT_EMPTY
;
3859 hr
= IMXWriter_get_output(writer
, &dest
);
3860 EXPECT_HR(hr
, S_OK
);
3861 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3862 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3863 VariantClear(&dest
);
3865 hr
= ISAXContentHandler_endDocument(content
);
3866 EXPECT_HR(hr
, S_OK
);
3867 IMXWriter_flush(writer
);
3869 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
3870 EXPECT_HR(hr
, S_OK
);
3871 V_VT(&dest
) = VT_EMPTY
;
3872 hr
= IMXWriter_get_output(writer
, &dest
);
3873 EXPECT_HR(hr
, S_OK
);
3874 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3875 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3876 VariantClear(&dest
);
3878 V_VT(&dest
) = VT_EMPTY
;
3879 hr
= IMXWriter_put_output(writer
, dest
);
3880 EXPECT_HR(hr
, S_OK
);
3883 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), -1, NULL
);
3884 EXPECT_HR(hr
, S_OK
);
3885 V_VT(&dest
) = VT_EMPTY
;
3886 hr
= IMXWriter_get_output(writer
, &dest
);
3887 EXPECT_HR(hr
, S_OK
);
3888 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3889 ok(!lstrcmpW(_bstr_("<a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3890 VariantClear(&dest
);
3892 ISAXContentHandler_Release(content
);
3893 IMXWriter_Release(writer
);
3897 struct writer_characters_t
{
3903 static const struct writer_characters_t writer_characters
[] = {
3904 { &CLSID_MXXMLWriter
, "< > & \" \'", "< > & \" \'" },
3905 { &CLSID_MXXMLWriter30
, "< > & \" \'", "< > & \" \'" },
3906 { &CLSID_MXXMLWriter40
, "< > & \" \'", "< > & \" \'" },
3907 { &CLSID_MXXMLWriter60
, "< > & \" \'", "< > & \" \'" },
3911 static void test_mxwriter_characters(void)
3913 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
3914 const struct writer_characters_t
*table
= writer_characters
;
3915 ISAXContentHandler
*content
;
3921 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3922 &IID_IMXWriter
, (void**)&writer
);
3923 EXPECT_HR(hr
, S_OK
);
3925 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3926 EXPECT_HR(hr
, S_OK
);
3928 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3929 EXPECT_HR(hr
, S_OK
);
3931 hr
= ISAXContentHandler_startDocument(content
);
3932 EXPECT_HR(hr
, S_OK
);
3934 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
3935 EXPECT_HR(hr
, E_INVALIDARG
);
3937 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3938 EXPECT_HR(hr
, S_OK
);
3940 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
3941 EXPECT_HR(hr
, S_OK
);
3943 V_VT(&dest
) = VT_EMPTY
;
3944 hr
= IMXWriter_get_output(writer
, &dest
);
3945 EXPECT_HR(hr
, S_OK
);
3946 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3947 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3948 VariantClear(&dest
);
3950 hr
= ISAXContentHandler_endDocument(content
);
3951 EXPECT_HR(hr
, S_OK
);
3953 ISAXContentHandler_Release(content
);
3954 IMXWriter_Release(writer
);
3956 /* try empty characters data to see if element is closed */
3957 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3958 &IID_IMXWriter
, (void**)&writer
);
3959 EXPECT_HR(hr
, S_OK
);
3961 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3962 EXPECT_HR(hr
, S_OK
);
3964 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3965 EXPECT_HR(hr
, S_OK
);
3967 hr
= ISAXContentHandler_startDocument(content
);
3968 EXPECT_HR(hr
, S_OK
);
3970 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3971 EXPECT_HR(hr
, S_OK
);
3973 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3974 EXPECT_HR(hr
, S_OK
);
3976 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3977 EXPECT_HR(hr
, S_OK
);
3979 V_VT(&dest
) = VT_EMPTY
;
3980 hr
= IMXWriter_get_output(writer
, &dest
);
3981 EXPECT_HR(hr
, S_OK
);
3982 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3983 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3984 VariantClear(&dest
);
3986 ISAXContentHandler_Release(content
);
3987 IMXWriter_Release(writer
);
3990 while (table
->clsid
)
3992 ISAXContentHandler
*content
;
3997 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
4004 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4005 &IID_IMXWriter
, (void**)&writer
);
4006 EXPECT_HR(hr
, S_OK
);
4008 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4009 EXPECT_HR(hr
, S_OK
);
4011 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4012 EXPECT_HR(hr
, S_OK
);
4014 hr
= ISAXContentHandler_startDocument(content
);
4015 EXPECT_HR(hr
, S_OK
);
4017 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
4018 EXPECT_HR(hr
, S_OK
);
4023 V_VT(&dest
) = VT_EMPTY
;
4024 hr
= IMXWriter_get_output(writer
, &dest
);
4025 EXPECT_HR(hr
, S_OK
);
4026 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4027 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
4028 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
4029 VariantClear(&dest
);
4032 /* with disabled escaping */
4033 V_VT(&dest
) = VT_EMPTY
;
4034 hr
= IMXWriter_put_output(writer
, dest
);
4035 EXPECT_HR(hr
, S_OK
);
4037 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
4038 EXPECT_HR(hr
, S_OK
);
4040 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
4041 EXPECT_HR(hr
, S_OK
);
4046 V_VT(&dest
) = VT_EMPTY
;
4047 hr
= IMXWriter_get_output(writer
, &dest
);
4048 EXPECT_HR(hr
, S_OK
);
4049 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4050 ok(!lstrcmpW(_bstr_(table
->data
), V_BSTR(&dest
)),
4051 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->data
);
4052 VariantClear(&dest
);
4055 ISAXContentHandler_Release(content
);
4056 IMXWriter_Release(writer
);
4065 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
4067 VARIANT_TRUE
,"UTF-16",
4069 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
4070 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4075 VARIANT_FALSE
,"UTF-16",
4077 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4082 VARIANT_TRUE
,"UTF-8",
4084 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
4085 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
4086 * and the writer is released.
4093 VARIANT_TRUE
,"utf-8",
4095 {FALSE
,(const BYTE
*)utf8xml2
,sizeof(utf8xml2
)-1},
4096 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
4097 * and the writer is released.
4104 VARIANT_TRUE
,"UTF-16",
4106 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
4107 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4112 VARIANT_TRUE
,"UTF-16",
4114 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
4115 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
4121 static void test_mxwriter_stream(void)
4124 ISAXContentHandler
*content
;
4129 ULARGE_INTEGER pos2
;
4130 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
4132 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
4133 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
4135 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4136 &IID_IMXWriter
, (void**)&writer
);
4137 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4139 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4140 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4142 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
4143 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
4145 V_VT(&dest
) = VT_UNKNOWN
;
4146 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
4147 hr
= IMXWriter_put_output(writer
, dest
);
4148 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
4150 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
4151 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
4153 current_write_test
= test
->expected_writes
;
4155 hr
= ISAXContentHandler_startDocument(content
);
4156 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4158 hr
= ISAXContentHandler_endDocument(content
);
4159 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4161 ISAXContentHandler_Release(content
);
4162 IMXWriter_Release(writer
);
4164 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
4165 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
4168 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4169 &IID_IMXWriter
, (void**)&writer
);
4170 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4172 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4173 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
4175 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4176 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4178 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4179 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
4181 V_VT(&dest
) = VT_UNKNOWN
;
4182 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4183 hr
= IMXWriter_put_output(writer
, dest
);
4184 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4186 hr
= ISAXContentHandler_startDocument(content
);
4187 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4189 /* Setting output of the mxwriter causes the current output to be flushed,
4190 * and the writer to start over.
4192 V_VT(&dest
) = VT_EMPTY
;
4193 hr
= IMXWriter_put_output(writer
, dest
);
4194 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4197 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4198 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
4199 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
4201 hr
= ISAXContentHandler_startDocument(content
);
4202 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4204 hr
= ISAXContentHandler_endDocument(content
);
4205 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
4207 V_VT(&dest
) = VT_EMPTY
;
4208 hr
= IMXWriter_get_output(writer
, &dest
);
4209 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
4210 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4211 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4212 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4213 VariantClear(&dest
);
4215 /* test when BOM is written to output stream */
4216 V_VT(&dest
) = VT_EMPTY
;
4217 hr
= IMXWriter_put_output(writer
, dest
);
4218 EXPECT_HR(hr
, S_OK
);
4221 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
4222 EXPECT_HR(hr
, S_OK
);
4224 V_VT(&dest
) = VT_UNKNOWN
;
4225 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4226 hr
= IMXWriter_put_output(writer
, dest
);
4227 EXPECT_HR(hr
, S_OK
);
4229 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_TRUE
);
4230 EXPECT_HR(hr
, S_OK
);
4232 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4233 EXPECT_HR(hr
, S_OK
);
4235 hr
= ISAXContentHandler_startDocument(content
);
4236 EXPECT_HR(hr
, S_OK
);
4240 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4241 EXPECT_HR(hr
, S_OK
);
4242 ok(pos2
.QuadPart
== 2, "got wrong position\n");
4244 IStream_Release(stream
);
4245 ISAXContentHandler_Release(content
);
4246 IMXWriter_Release(writer
);
4251 static const char *encoding_names
[] = {
4264 static void test_mxwriter_encoding(void)
4266 ISAXContentHandler
*content
;
4277 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4278 &IID_IMXWriter
, (void**)&writer
);
4279 EXPECT_HR(hr
, S_OK
);
4281 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4282 EXPECT_HR(hr
, S_OK
);
4284 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4285 EXPECT_HR(hr
, S_OK
);
4287 hr
= ISAXContentHandler_startDocument(content
);
4288 EXPECT_HR(hr
, S_OK
);
4290 hr
= ISAXContentHandler_endDocument(content
);
4291 EXPECT_HR(hr
, S_OK
);
4293 /* The content is always re-encoded to UTF-16 when the output is
4294 * retrieved as a BSTR.
4296 V_VT(&dest
) = VT_EMPTY
;
4297 hr
= IMXWriter_get_output(writer
, &dest
);
4298 EXPECT_HR(hr
, S_OK
);
4299 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4300 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4301 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4302 VariantClear(&dest
);
4304 /* switch encoding when something is written already */
4305 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4306 EXPECT_HR(hr
, S_OK
);
4308 V_VT(&dest
) = VT_UNKNOWN
;
4309 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4310 hr
= IMXWriter_put_output(writer
, dest
);
4311 EXPECT_HR(hr
, S_OK
);
4313 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4314 EXPECT_HR(hr
, S_OK
);
4316 /* write empty element */
4317 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
4318 EXPECT_HR(hr
, S_OK
);
4320 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
4321 EXPECT_HR(hr
, S_OK
);
4324 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4325 EXPECT_HR(hr
, S_OK
);
4327 hr
= IMXWriter_flush(writer
);
4328 EXPECT_HR(hr
, S_OK
);
4330 hr
= GetHGlobalFromStream(stream
, &g
);
4331 EXPECT_HR(hr
, S_OK
);
4333 ptr
= GlobalLock(g
);
4334 ok(!strncmp(ptr
, "<a/>", 4), "got %c%c%c%c\n", ptr
[0],ptr
[1],ptr
[2],ptr
[3]);
4337 /* so output is unaffected, encoding name is stored however */
4338 hr
= IMXWriter_get_encoding(writer
, &s
);
4339 EXPECT_HR(hr
, S_OK
);
4340 ok(!lstrcmpW(s
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(s
));
4343 IStream_Release(stream
);
4346 enc
= encoding_names
[i
];
4349 char expectedA
[200];
4351 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4352 EXPECT_HR(hr
, S_OK
);
4354 V_VT(&dest
) = VT_UNKNOWN
;
4355 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4356 hr
= IMXWriter_put_output(writer
, dest
);
4357 EXPECT_HR(hr
, S_OK
);
4359 hr
= IMXWriter_put_encoding(writer
, _bstr_(enc
));
4360 ok(hr
== S_OK
|| broken(hr
!= S_OK
) /* old win versions do not support certain encodings */,
4361 "%s: encoding not accepted\n", enc
);
4364 enc
= encoding_names
[++i
];
4365 IStream_Release(stream
);
4369 hr
= ISAXContentHandler_startDocument(content
);
4370 EXPECT_HR(hr
, S_OK
);
4372 hr
= ISAXContentHandler_endDocument(content
);
4373 EXPECT_HR(hr
, S_OK
);
4375 hr
= IMXWriter_flush(writer
);
4376 EXPECT_HR(hr
, S_OK
);
4378 /* prepare expected string */
4380 strcat(expectedA
, "<?xml version=\"1.0\" encoding=\"");
4381 strcat(expectedA
, enc
);
4382 strcat(expectedA
, "\" standalone=\"no\"?>\r\n");
4384 hr
= GetHGlobalFromStream(stream
, &g
);
4385 EXPECT_HR(hr
, S_OK
);
4387 ptr
= GlobalLock(g
);
4388 ok(!strncmp(ptr
, expectedA
, strlen(expectedA
)), "%s: got %s, expected %.50s\n", enc
, ptr
, expectedA
);
4391 V_VT(&dest
) = VT_EMPTY
;
4392 hr
= IMXWriter_put_output(writer
, dest
);
4393 EXPECT_HR(hr
, S_OK
);
4395 IStream_Release(stream
);
4397 enc
= encoding_names
[++i
];
4400 ISAXContentHandler_Release(content
);
4401 IMXWriter_Release(writer
);
4406 static void test_obj_dispex(IUnknown
*obj
)
4408 static const WCHAR testW
[] = {'t','e','s','t','p','r','o','p',0};
4409 static const WCHAR starW
[] = {'*',0};
4410 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
4411 IDispatchEx
*dispex
;
4419 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
4420 EXPECT_HR(hr
, S_OK
);
4421 if (FAILED(hr
)) return;
4424 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
4425 EXPECT_HR(hr
, S_OK
);
4426 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
4428 name
= SysAllocString(starW
);
4429 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
4430 EXPECT_HR(hr
, E_NOTIMPL
);
4431 SysFreeString(name
);
4433 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
4434 EXPECT_HR(hr
, E_NOTIMPL
);
4437 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
4438 EXPECT_HR(hr
, E_NOTIMPL
);
4439 ok(props
== 0, "expected 0 got %d\n", props
);
4441 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
4442 EXPECT_HR(hr
, E_NOTIMPL
);
4443 if (SUCCEEDED(hr
)) SysFreeString(name
);
4445 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
4446 EXPECT_HR(hr
, E_NOTIMPL
);
4448 unk
= (IUnknown
*)0xdeadbeef;
4449 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
4450 EXPECT_HR(hr
, E_NOTIMPL
);
4451 ok(unk
== (IUnknown
*)0xdeadbeef, "got %p\n", unk
);
4453 name
= SysAllocString(testW
);
4454 hr
= IDispatchEx_GetDispID(dispex
, name
, fdexNameEnsure
, &did
);
4455 ok(hr
== DISP_E_UNKNOWNNAME
, "got 0x%08x\n", hr
);
4456 SysFreeString(name
);
4458 IDispatchEx_Release(dispex
);
4461 static void test_saxreader_dispex(void)
4463 IVBSAXXMLReader
*vbreader
;
4464 ISAXXMLReader
*reader
;
4465 DISPPARAMS dispparams
;
4471 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
4472 &IID_ISAXXMLReader
, (void**)&reader
);
4473 EXPECT_HR(hr
, S_OK
);
4475 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
4476 EXPECT_HR(hr
, S_OK
);
4477 test_obj_dispex(unk
);
4478 IUnknown_Release(unk
);
4480 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
4481 EXPECT_HR(hr
, S_OK
);
4482 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
4483 EXPECT_HR(hr
, S_OK
);
4484 test_obj_dispex(unk
);
4485 IUnknown_Release(unk
);
4487 dispid
= DISPID_PROPERTYPUT
;
4488 dispparams
.cArgs
= 1;
4489 dispparams
.cNamedArgs
= 1;
4490 dispparams
.rgdispidNamedArgs
= &dispid
;
4491 dispparams
.rgvarg
= &arg
;
4493 V_VT(&arg
) = VT_DISPATCH
;
4494 V_DISPATCH(&arg
) = NULL
;
4496 /* propputref is callable as PROPERTYPUT and PROPERTYPUTREF */
4497 hr
= IVBSAXXMLReader_Invoke(vbreader
,
4498 DISPID_SAX_XMLREADER_CONTENTHANDLER
,
4501 DISPATCH_PROPERTYPUT
,
4506 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4508 hr
= IVBSAXXMLReader_Invoke(vbreader
,
4509 DISPID_SAX_XMLREADER_CONTENTHANDLER
,
4512 DISPATCH_PROPERTYPUTREF
,
4517 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4519 IVBSAXXMLReader_Release(vbreader
);
4520 ISAXXMLReader_Release(reader
);
4522 if (is_clsid_supported(&CLSID_SAXXMLReader60
, reader_support_data
))
4524 hr
= CoCreateInstance(&CLSID_SAXXMLReader60
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&unk
);
4525 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4526 test_obj_dispex(unk
);
4527 IUnknown_Release(unk
);
4531 static void test_mxwriter_dispex(void)
4533 IDispatchEx
*dispex
;
4538 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4539 &IID_IMXWriter
, (void**)&writer
);
4540 EXPECT_HR(hr
, S_OK
);
4542 hr
= IMXWriter_QueryInterface(writer
, &IID_IDispatchEx
, (void**)&dispex
);
4543 EXPECT_HR(hr
, S_OK
);
4544 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4545 test_obj_dispex(unk
);
4546 IUnknown_Release(unk
);
4547 IDispatchEx_Release(dispex
);
4548 IMXWriter_Release(writer
);
4550 if (is_clsid_supported(&CLSID_MXXMLWriter60
, mxwriter_support_data
))
4552 hr
= CoCreateInstance(&CLSID_MXXMLWriter60
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&unk
);
4553 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4554 test_obj_dispex(unk
);
4555 IUnknown_Release(unk
);
4559 static void test_mxwriter_comment(void)
4561 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
4562 IVBSAXLexicalHandler
*vblexical
;
4563 ISAXContentHandler
*content
;
4564 ISAXLexicalHandler
*lexical
;
4569 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4570 &IID_IMXWriter
, (void**)&writer
);
4571 EXPECT_HR(hr
, S_OK
);
4573 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4574 EXPECT_HR(hr
, S_OK
);
4576 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4577 EXPECT_HR(hr
, S_OK
);
4579 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4580 EXPECT_HR(hr
, S_OK
);
4582 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4583 EXPECT_HR(hr
, S_OK
);
4585 hr
= ISAXContentHandler_startDocument(content
);
4586 EXPECT_HR(hr
, S_OK
);
4588 hr
= ISAXLexicalHandler_comment(lexical
, NULL
, 0);
4589 EXPECT_HR(hr
, E_INVALIDARG
);
4591 hr
= IVBSAXLexicalHandler_comment(vblexical
, NULL
);
4592 EXPECT_HR(hr
, E_POINTER
);
4594 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, 0);
4595 EXPECT_HR(hr
, S_OK
);
4597 V_VT(&dest
) = VT_EMPTY
;
4598 hr
= IMXWriter_get_output(writer
, &dest
);
4599 EXPECT_HR(hr
, S_OK
);
4600 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4601 ok(!lstrcmpW(_bstr_("<!---->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4602 VariantClear(&dest
);
4604 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, sizeof(commentW
)/sizeof(WCHAR
)-1);
4605 EXPECT_HR(hr
, S_OK
);
4607 V_VT(&dest
) = VT_EMPTY
;
4608 hr
= IMXWriter_get_output(writer
, &dest
);
4609 EXPECT_HR(hr
, S_OK
);
4610 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4611 ok(!lstrcmpW(_bstr_("<!---->\r\n<!--comment-->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4612 VariantClear(&dest
);
4614 ISAXContentHandler_Release(content
);
4615 ISAXLexicalHandler_Release(lexical
);
4616 IVBSAXLexicalHandler_Release(vblexical
);
4617 IMXWriter_Release(writer
);
4621 static void test_mxwriter_cdata(void)
4623 IVBSAXLexicalHandler
*vblexical
;
4624 ISAXContentHandler
*content
;
4625 ISAXLexicalHandler
*lexical
;
4630 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4631 &IID_IMXWriter
, (void**)&writer
);
4632 EXPECT_HR(hr
, S_OK
);
4634 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4635 EXPECT_HR(hr
, S_OK
);
4637 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4638 EXPECT_HR(hr
, S_OK
);
4640 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4641 EXPECT_HR(hr
, S_OK
);
4643 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4644 EXPECT_HR(hr
, S_OK
);
4646 hr
= ISAXContentHandler_startDocument(content
);
4647 EXPECT_HR(hr
, S_OK
);
4649 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4650 EXPECT_HR(hr
, S_OK
);
4652 V_VT(&dest
) = VT_EMPTY
;
4653 hr
= IMXWriter_get_output(writer
, &dest
);
4654 EXPECT_HR(hr
, S_OK
);
4655 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4656 ok(!lstrcmpW(_bstr_("<![CDATA["), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4657 VariantClear(&dest
);
4659 hr
= IVBSAXLexicalHandler_startCDATA(vblexical
);
4660 EXPECT_HR(hr
, S_OK
);
4662 /* all these are escaped for text nodes */
4663 hr
= ISAXContentHandler_characters(content
, _bstr_("< > & \""), 7);
4664 EXPECT_HR(hr
, S_OK
);
4666 hr
= ISAXLexicalHandler_endCDATA(lexical
);
4667 EXPECT_HR(hr
, S_OK
);
4669 V_VT(&dest
) = VT_EMPTY
;
4670 hr
= IMXWriter_get_output(writer
, &dest
);
4671 EXPECT_HR(hr
, S_OK
);
4672 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4673 ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4674 VariantClear(&dest
);
4676 ISAXContentHandler_Release(content
);
4677 ISAXLexicalHandler_Release(lexical
);
4678 IVBSAXLexicalHandler_Release(vblexical
);
4679 IMXWriter_Release(writer
);
4683 static void test_mxwriter_pi(void)
4685 static const WCHAR targetW
[] = {'t','a','r','g','e','t',0};
4686 static const WCHAR dataW
[] = {'d','a','t','a',0};
4687 ISAXContentHandler
*content
;
4692 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4693 &IID_IMXWriter
, (void**)&writer
);
4694 EXPECT_HR(hr
, S_OK
);
4696 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4697 EXPECT_HR(hr
, S_OK
);
4699 hr
= ISAXContentHandler_processingInstruction(content
, NULL
, 0, NULL
, 0);
4700 EXPECT_HR(hr
, E_INVALIDARG
);
4702 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 0, NULL
, 0);
4703 EXPECT_HR(hr
, S_OK
);
4705 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, NULL
, 0);
4706 EXPECT_HR(hr
, S_OK
);
4708 V_VT(&dest
) = VT_EMPTY
;
4709 hr
= IMXWriter_get_output(writer
, &dest
);
4710 EXPECT_HR(hr
, S_OK
);
4711 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4712 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4713 VariantClear(&dest
);
4715 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 4, dataW
, 4);
4716 EXPECT_HR(hr
, S_OK
);
4718 V_VT(&dest
) = VT_EMPTY
;
4719 hr
= IMXWriter_get_output(writer
, &dest
);
4720 EXPECT_HR(hr
, S_OK
);
4721 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4722 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
)));
4723 VariantClear(&dest
);
4725 V_VT(&dest
) = VT_EMPTY
;
4726 hr
= IMXWriter_put_output(writer
, dest
);
4727 EXPECT_HR(hr
, S_OK
);
4729 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, dataW
, 0);
4730 EXPECT_HR(hr
, S_OK
);
4732 V_VT(&dest
) = VT_EMPTY
;
4733 hr
= IMXWriter_get_output(writer
, &dest
);
4734 EXPECT_HR(hr
, S_OK
);
4735 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4736 ok(!lstrcmpW(_bstr_("<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4737 VariantClear(&dest
);
4740 ISAXContentHandler_Release(content
);
4741 IMXWriter_Release(writer
);
4744 static void test_mxwriter_ignorablespaces(void)
4746 static const WCHAR dataW
[] = {'d','a','t','a',0};
4747 ISAXContentHandler
*content
;
4752 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4753 &IID_IMXWriter
, (void**)&writer
);
4754 EXPECT_HR(hr
, S_OK
);
4756 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4757 EXPECT_HR(hr
, S_OK
);
4759 hr
= ISAXContentHandler_ignorableWhitespace(content
, NULL
, 0);
4760 EXPECT_HR(hr
, E_INVALIDARG
);
4762 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 0);
4763 EXPECT_HR(hr
, S_OK
);
4765 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 4);
4766 EXPECT_HR(hr
, S_OK
);
4768 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 1);
4769 EXPECT_HR(hr
, S_OK
);
4771 V_VT(&dest
) = VT_EMPTY
;
4772 hr
= IMXWriter_get_output(writer
, &dest
);
4773 EXPECT_HR(hr
, S_OK
);
4774 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4775 ok(!lstrcmpW(_bstr_("datad"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4776 VariantClear(&dest
);
4778 ISAXContentHandler_Release(content
);
4779 IMXWriter_Release(writer
);
4782 static void test_mxwriter_dtd(void)
4784 static const WCHAR contentW
[] = {'c','o','n','t','e','n','t'};
4785 static const WCHAR nameW
[] = {'n','a','m','e'};
4786 static const WCHAR pubW
[] = {'p','u','b'};
4787 static const WCHAR sysW
[] = {'s','y','s'};
4788 IVBSAXLexicalHandler
*vblexical
;
4789 ISAXContentHandler
*content
;
4790 ISAXLexicalHandler
*lexical
;
4791 IVBSAXDeclHandler
*vbdecl
;
4792 ISAXDeclHandler
*decl
;
4793 ISAXDTDHandler
*dtd
;
4798 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4799 &IID_IMXWriter
, (void**)&writer
);
4800 EXPECT_HR(hr
, S_OK
);
4802 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4803 EXPECT_HR(hr
, S_OK
);
4805 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4806 EXPECT_HR(hr
, S_OK
);
4808 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
4809 EXPECT_HR(hr
, S_OK
);
4811 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXDeclHandler
, (void**)&vbdecl
);
4812 EXPECT_HR(hr
, S_OK
);
4814 hr
= IMXWriter_QueryInterface(writer
, &IID_IVBSAXLexicalHandler
, (void**)&vblexical
);
4815 EXPECT_HR(hr
, S_OK
);
4817 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4818 EXPECT_HR(hr
, S_OK
);
4820 hr
= ISAXContentHandler_startDocument(content
);
4821 EXPECT_HR(hr
, S_OK
);
4823 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, NULL
, 0);
4824 EXPECT_HR(hr
, E_INVALIDARG
);
4826 hr
= IVBSAXLexicalHandler_startDTD(vblexical
, NULL
, NULL
, NULL
);
4827 EXPECT_HR(hr
, E_POINTER
);
4829 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4830 EXPECT_HR(hr
, E_INVALIDARG
);
4832 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4833 EXPECT_HR(hr
, E_INVALIDARG
);
4835 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4836 EXPECT_HR(hr
, E_INVALIDARG
);
4838 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0, NULL
, 0);
4839 EXPECT_HR(hr
, S_OK
);
4841 V_VT(&dest
) = VT_EMPTY
;
4842 hr
= IMXWriter_get_output(writer
, &dest
);
4843 EXPECT_HR(hr
, S_OK
);
4844 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4845 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4846 VariantClear(&dest
);
4848 /* system id is required if public is present */
4849 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4850 EXPECT_HR(hr
, E_INVALIDARG
);
4852 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
),
4853 pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4854 EXPECT_HR(hr
, S_OK
);
4856 V_VT(&dest
) = VT_EMPTY
;
4857 hr
= IMXWriter_get_output(writer
, &dest
);
4858 EXPECT_HR(hr
, S_OK
);
4859 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4860 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4861 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4862 VariantClear(&dest
);
4864 hr
= ISAXLexicalHandler_endDTD(lexical
);
4865 EXPECT_HR(hr
, S_OK
);
4867 hr
= IVBSAXLexicalHandler_endDTD(vblexical
);
4868 EXPECT_HR(hr
, S_OK
);
4870 V_VT(&dest
) = VT_EMPTY
;
4871 hr
= IMXWriter_get_output(writer
, &dest
);
4872 EXPECT_HR(hr
, S_OK
);
4873 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4874 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4875 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n"),
4876 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4877 VariantClear(&dest
);
4879 /* element declaration */
4880 V_VT(&dest
) = VT_EMPTY
;
4881 hr
= IMXWriter_put_output(writer
, dest
);
4882 EXPECT_HR(hr
, S_OK
);
4884 hr
= ISAXDeclHandler_elementDecl(decl
, NULL
, 0, NULL
, 0);
4885 EXPECT_HR(hr
, E_INVALIDARG
);
4887 hr
= IVBSAXDeclHandler_elementDecl(vbdecl
, NULL
, NULL
);
4888 EXPECT_HR(hr
, E_POINTER
);
4890 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0);
4891 EXPECT_HR(hr
, E_INVALIDARG
);
4893 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, sizeof(contentW
)/sizeof(WCHAR
));
4894 EXPECT_HR(hr
, S_OK
);
4896 V_VT(&dest
) = VT_EMPTY
;
4897 hr
= IMXWriter_get_output(writer
, &dest
);
4898 EXPECT_HR(hr
, S_OK
);
4899 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4900 ok(!lstrcmpW(_bstr_("<!ELEMENT name content>\r\n"),
4901 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4902 VariantClear(&dest
);
4904 V_VT(&dest
) = VT_EMPTY
;
4905 hr
= IMXWriter_put_output(writer
, dest
);
4906 EXPECT_HR(hr
, S_OK
);
4908 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, 0);
4909 EXPECT_HR(hr
, S_OK
);
4911 V_VT(&dest
) = VT_EMPTY
;
4912 hr
= IMXWriter_get_output(writer
, &dest
);
4913 EXPECT_HR(hr
, S_OK
);
4914 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4915 ok(!lstrcmpW(_bstr_("<!ELEMENT name >\r\n"),
4916 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4917 VariantClear(&dest
);
4919 /* attribute declaration */
4920 V_VT(&dest
) = VT_EMPTY
;
4921 hr
= IMXWriter_put_output(writer
, dest
);
4922 EXPECT_HR(hr
, S_OK
);
4924 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4925 _bstr_("attribute"), strlen("attribute"), _bstr_("CDATA"), strlen("CDATA"),
4926 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value"), strlen("value"));
4927 EXPECT_HR(hr
, S_OK
);
4929 V_VT(&dest
) = VT_EMPTY
;
4930 hr
= IMXWriter_get_output(writer
, &dest
);
4931 EXPECT_HR(hr
, S_OK
);
4932 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4933 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"),
4934 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4935 VariantClear(&dest
);
4937 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4938 _bstr_("attribute2"), strlen("attribute2"), _bstr_("CDATA"), strlen("CDATA"),
4939 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value2"), strlen("value2"));
4940 EXPECT_HR(hr
, S_OK
);
4942 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element2"), strlen("element2"),
4943 _bstr_("attribute3"), strlen("attribute3"), _bstr_("CDATA"), strlen("CDATA"),
4944 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value3"), strlen("value3"));
4945 EXPECT_HR(hr
, S_OK
);
4947 V_VT(&dest
) = VT_EMPTY
;
4948 hr
= IMXWriter_get_output(writer
, &dest
);
4949 EXPECT_HR(hr
, S_OK
);
4950 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4951 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"
4952 "<!ATTLIST element attribute2 CDATA #REQUIRED \"value2\">\r\n"
4953 "<!ATTLIST element2 attribute3 CDATA #REQUIRED \"value3\">\r\n"),
4954 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4955 VariantClear(&dest
);
4957 /* internal entities */
4958 V_VT(&dest
) = VT_EMPTY
;
4959 hr
= IMXWriter_put_output(writer
, dest
);
4960 EXPECT_HR(hr
, S_OK
);
4962 hr
= ISAXDeclHandler_internalEntityDecl(decl
, NULL
, 0, NULL
, 0);
4963 EXPECT_HR(hr
, E_INVALIDARG
);
4965 hr
= IVBSAXDeclHandler_internalEntityDecl(vbdecl
, NULL
, NULL
);
4966 EXPECT_HR(hr
, E_POINTER
);
4968 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0);
4969 EXPECT_HR(hr
, E_INVALIDARG
);
4971 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("value"), strlen("value"));
4972 EXPECT_HR(hr
, S_OK
);
4974 V_VT(&dest
) = VT_EMPTY
;
4975 hr
= IMXWriter_get_output(writer
, &dest
);
4976 EXPECT_HR(hr
, S_OK
);
4977 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4978 ok(!lstrcmpW(_bstr_("<!ENTITY name \"value\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4979 VariantClear(&dest
);
4981 /* external entities */
4982 V_VT(&dest
) = VT_EMPTY
;
4983 hr
= IMXWriter_put_output(writer
, dest
);
4984 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
4986 hr
= ISAXDeclHandler_externalEntityDecl(decl
, NULL
, 0, NULL
, 0, NULL
, 0);
4987 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4989 hr
= IVBSAXDeclHandler_externalEntityDecl(vbdecl
, NULL
, NULL
, NULL
);
4990 ok(hr
== E_POINTER
, "got 0x%08x\n", hr
);
4992 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), 0, NULL
, 0, NULL
, 0);
4993 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4995 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0, NULL
, 0);
4996 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
4998 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"),
4999 _bstr_("sysid"), strlen("sysid"));
5000 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5002 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), strlen("name"), NULL
, 0, _bstr_("sysid"), strlen("sysid"));
5003 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5005 hr
= ISAXDeclHandler_externalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"),
5007 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5009 V_VT(&dest
) = VT_EMPTY
;
5010 hr
= IMXWriter_get_output(writer
, &dest
);
5011 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5012 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
5013 ok(!lstrcmpW(_bstr_(
5014 "<!ENTITY name PUBLIC \"pubid\" \"sysid\">\r\n"
5015 "<!ENTITY name SYSTEM \"sysid\">\r\n"),
5016 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
5018 VariantClear(&dest
);
5020 /* notation declaration */
5021 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDTDHandler
, (void**)&dtd
);
5022 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5024 V_VT(&dest
) = VT_EMPTY
;
5025 hr
= IMXWriter_put_output(writer
, dest
);
5026 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5028 hr
= ISAXDTDHandler_notationDecl(dtd
, NULL
, 0, NULL
, 0, NULL
, 0);
5029 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5031 hr
= ISAXDTDHandler_notationDecl(dtd
, _bstr_("name"), strlen("name"), NULL
, 0, NULL
, 0);
5032 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5034 hr
= ISAXDTDHandler_notationDecl(dtd
, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"), NULL
, 0);
5035 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5037 hr
= ISAXDTDHandler_notationDecl(dtd
, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"), _bstr_("sysid"), strlen("sysid"));
5038 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5040 hr
= ISAXDTDHandler_notationDecl(dtd
, _bstr_("name"), strlen("name"), NULL
, 0, _bstr_("sysid"), strlen("sysid"));
5041 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5043 hr
= IMXWriter_get_output(writer
, &dest
);
5044 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
5045 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
5046 ok(!lstrcmpW(_bstr_(
5048 "<!NOTATION name PUBLIC \"pubid\">\r\n"
5049 "<!NOTATION name PUBLIC \"pubid\" \"sysid\">\r\n"
5050 "<!NOTATION name SYSTEM \"sysid\">\r\n"),
5051 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
5053 VariantClear(&dest
);
5055 ISAXDTDHandler_Release(dtd
);
5057 ISAXContentHandler_Release(content
);
5058 ISAXLexicalHandler_Release(lexical
);
5059 IVBSAXLexicalHandler_Release(vblexical
);
5060 IVBSAXDeclHandler_Release(vbdecl
);
5061 ISAXDeclHandler_Release(decl
);
5062 IMXWriter_Release(writer
);
5074 } addattribute_test_t
;
5076 static const addattribute_test_t addattribute_data
[] = {
5077 { &CLSID_SAXAttributes
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5078 { &CLSID_SAXAttributes30
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5079 { &CLSID_SAXAttributes40
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
5080 { &CLSID_SAXAttributes60
, NULL
, NULL
, "ns:qname", NULL
, "value", S_OK
},
5082 { &CLSID_SAXAttributes
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5083 { &CLSID_SAXAttributes30
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5084 { &CLSID_SAXAttributes40
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5085 { &CLSID_SAXAttributes60
, NULL
, "qname", "ns:qname", NULL
, "value", S_OK
},
5087 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5088 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5089 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
5090 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", NULL
, "value", S_OK
},
5092 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5093 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5094 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5095 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
5100 static void test_mxattr_addAttribute(void)
5102 const addattribute_test_t
*table
= addattribute_data
;
5105 while (table
->clsid
)
5107 ISAXAttributes
*saxattr
;
5108 IMXAttributes
*mxattr
;
5113 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5120 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5121 &IID_IMXAttributes
, (void**)&mxattr
);
5122 EXPECT_HR(hr
, S_OK
);
5124 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5125 EXPECT_HR(hr
, S_OK
);
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_getLength(saxattr
, NULL
);
5132 EXPECT_HR(hr
, E_POINTER
);
5136 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5137 EXPECT_HR(hr
, S_OK
);
5138 ok(len
== 0, "got %d\n", len
);
5140 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
5141 EXPECT_HR(hr
, E_INVALIDARG
);
5143 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
5144 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5146 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
5147 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5149 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
5150 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5152 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
5153 EXPECT_HR(hr
, E_INVALIDARG
);
5155 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
5156 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5158 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
5159 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5161 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
5162 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5164 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_(table
->uri
), _bstr_(table
->local
),
5165 _bstr_(table
->qname
), _bstr_(table
->type
), _bstr_(table
->value
));
5166 ok(hr
== table
->hr
, "%d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
5170 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
5171 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5172 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5174 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
5175 EXPECT_HR(hr
, E_POINTER
);
5177 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
5178 EXPECT_HR(hr
, E_POINTER
);
5180 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
5181 EXPECT_HR(hr
, E_POINTER
);
5183 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
5184 EXPECT_HR(hr
, E_POINTER
);
5186 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
5187 EXPECT_HR(hr
, E_POINTER
);
5189 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
5190 EXPECT_HR(hr
, E_POINTER
);
5194 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
5195 EXPECT_HR(hr
, S_OK
);
5196 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5198 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5201 value
= (void*)0xdeadbeef;
5202 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
5203 EXPECT_HR(hr
, S_OK
);
5207 ok(!lstrcmpW(_bstr_(table
->type
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5209 ok(lstrlenW(value
) == len
, "%d: got wrong type value length %d\n", i
, len
);
5213 ok(*value
== 0, "%d: got type value %s\n", i
, wine_dbgstr_w(value
));
5214 ok(len
== 0, "%d: got wrong type value length %d\n", i
, len
);
5217 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, NULL
);
5218 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5219 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5221 EXPECT_HR(hr
, E_POINTER
);
5224 EXPECT_HR(hr
, E_INVALIDARG
);
5226 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, &index
);
5227 EXPECT_HR(hr
, E_INVALIDARG
);
5230 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_("nonexistent"), 11, &index
);
5231 EXPECT_HR(hr
, E_INVALIDARG
);
5232 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5235 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), 0, &index
);
5236 EXPECT_HR(hr
, E_INVALIDARG
);
5237 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5240 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &index
);
5241 EXPECT_HR(hr
, S_OK
);
5242 ok(index
== 0, "%d: got wrong index %d\n", i
, index
);
5245 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
)-1, &index
);
5246 EXPECT_HR(hr
, E_INVALIDARG
);
5247 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
5249 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes40
) ||
5250 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes60
))
5252 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
5253 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5255 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
5256 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5258 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
5259 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5261 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
5262 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5264 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
5265 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5267 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
5268 ok(hr
== E_POINTER
/* win8 */ || hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
5272 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
5273 EXPECT_HR(hr
, E_POINTER
);
5275 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
5276 EXPECT_HR(hr
, E_POINTER
);
5278 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
5279 EXPECT_HR(hr
, E_POINTER
);
5281 /* versions 4 and 6 crash */
5282 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, NULL
);
5283 EXPECT_HR(hr
, E_POINTER
);
5285 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, &len
);
5286 EXPECT_HR(hr
, E_POINTER
);
5288 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
5289 EXPECT_HR(hr
, E_POINTER
);
5291 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
5292 EXPECT_HR(hr
, E_POINTER
);
5294 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
5295 EXPECT_HR(hr
, E_POINTER
);
5297 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, &value
, NULL
);
5298 EXPECT_HR(hr
, E_POINTER
);
5300 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, NULL
, &len
);
5301 EXPECT_HR(hr
, E_POINTER
);
5303 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
), _bstr_(table
->local
),
5304 strlen(table
->local
), NULL
, NULL
);
5305 EXPECT_HR(hr
, E_POINTER
);
5308 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &value
, &len
);
5309 EXPECT_HR(hr
, S_OK
);
5310 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5312 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5315 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
),
5316 _bstr_(table
->local
), strlen(table
->local
), &value
, &len
);
5317 EXPECT_HR(hr
, S_OK
);
5318 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5320 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5325 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5326 EXPECT_HR(hr
, S_OK
);
5327 if (table
->hr
== S_OK
)
5328 ok(len
== 1, "%d: got %d length, expected 1\n", i
, len
);
5330 ok(len
== 0, "%d: got %d length, expected 0\n", i
, len
);
5332 ISAXAttributes_Release(saxattr
);
5333 IMXAttributes_Release(mxattr
);
5342 static void test_mxattr_clear(void)
5344 ISAXAttributes
*saxattr
;
5345 IMXAttributes
*mxattr
;
5350 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5351 &IID_IMXAttributes
, (void**)&mxattr
);
5352 EXPECT_HR(hr
, S_OK
);
5354 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5355 EXPECT_HR(hr
, S_OK
);
5357 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, NULL
);
5358 EXPECT_HR(hr
, E_INVALIDARG
);
5360 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5361 EXPECT_HR(hr
, E_INVALIDARG
);
5363 hr
= IMXAttributes_clear(mxattr
);
5364 EXPECT_HR(hr
, S_OK
);
5366 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("local"),
5367 _bstr_("qname"), _bstr_("type"), _bstr_("value"));
5368 EXPECT_HR(hr
, S_OK
);
5371 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5372 EXPECT_HR(hr
, S_OK
);
5373 ok(len
== 1, "got %d\n", len
);
5376 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, &len
);
5377 EXPECT_HR(hr
, E_POINTER
);
5378 ok(len
== -1, "got %d\n", len
);
5380 ptr
= (void*)0xdeadbeef;
5381 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, NULL
);
5382 EXPECT_HR(hr
, E_POINTER
);
5383 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5386 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5387 EXPECT_HR(hr
, S_OK
);
5388 ok(len
== 5, "got %d\n", len
);
5389 ok(!lstrcmpW(ptr
, _bstr_("qname")), "got %s\n", wine_dbgstr_w(ptr
));
5391 hr
= IMXAttributes_clear(mxattr
);
5392 EXPECT_HR(hr
, S_OK
);
5395 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5396 EXPECT_HR(hr
, S_OK
);
5397 ok(len
== 0, "got %d\n", len
);
5400 ptr
= (void*)0xdeadbeef;
5401 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5402 EXPECT_HR(hr
, E_INVALIDARG
);
5403 ok(len
== -1, "got %d\n", len
);
5404 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5406 IMXAttributes_Release(mxattr
);
5407 ISAXAttributes_Release(saxattr
);
5411 static void test_mxattr_dispex(void)
5413 IMXAttributes
*mxattr
;
5414 IDispatchEx
*dispex
;
5418 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5419 &IID_IMXAttributes
, (void**)&mxattr
);
5420 EXPECT_HR(hr
, S_OK
);
5422 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IDispatchEx
, (void**)&dispex
);
5423 EXPECT_HR(hr
, S_OK
);
5424 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
5425 test_obj_dispex(unk
);
5426 IUnknown_Release(unk
);
5427 IDispatchEx_Release(dispex
);
5429 IMXAttributes_Release(mxattr
);
5432 static void test_mxattr_qi(void)
5434 IVBSAXAttributes
*vbsaxattr
, *vbsaxattr2
;
5435 ISAXAttributes
*saxattr
;
5436 IMXAttributes
*mxattr
;
5439 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5440 &IID_IMXAttributes
, (void**)&mxattr
);
5441 EXPECT_HR(hr
, S_OK
);
5443 EXPECT_REF(mxattr
, 1);
5444 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5445 EXPECT_HR(hr
, S_OK
);
5447 EXPECT_REF(mxattr
, 2);
5448 EXPECT_REF(saxattr
, 2);
5450 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr
);
5451 EXPECT_HR(hr
, S_OK
);
5453 EXPECT_REF(vbsaxattr
, 3);
5454 EXPECT_REF(mxattr
, 3);
5455 EXPECT_REF(saxattr
, 3);
5457 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr2
);
5458 EXPECT_HR(hr
, S_OK
);
5460 EXPECT_REF(vbsaxattr
, 4);
5461 EXPECT_REF(mxattr
, 4);
5462 EXPECT_REF(saxattr
, 4);
5464 IMXAttributes_Release(mxattr
);
5465 ISAXAttributes_Release(saxattr
);
5466 IVBSAXAttributes_Release(vbsaxattr
);
5467 IVBSAXAttributes_Release(vbsaxattr2
);
5470 static struct msxmlsupported_data_t saxattr_support_data
[] =
5472 { &CLSID_SAXAttributes
, "SAXAttributes" },
5473 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
5474 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
5475 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
5479 static void test_mxattr_localname(void)
5481 static const WCHAR localname1W
[] = {'l','o','c','a','l','n','a','m','e','1',0};
5482 static const WCHAR localnameW
[] = {'l','o','c','a','l','n','a','m','e',0};
5483 static const WCHAR uri1W
[] = {'u','r','i','1',0};
5484 static const WCHAR uriW
[] = {'u','r','i',0};
5486 const struct msxmlsupported_data_t
*table
= saxattr_support_data
;
5488 while (table
->clsid
)
5490 ISAXAttributes
*saxattr
;
5491 IMXAttributes
*mxattr
;
5495 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5501 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5502 &IID_IMXAttributes
, (void**)&mxattr
);
5503 EXPECT_HR(hr
, S_OK
);
5505 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5506 EXPECT_HR(hr
, S_OK
);
5508 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, &index
);
5509 EXPECT_HR(hr
, E_INVALIDARG
);
5511 /* add some ambiguos attribute names */
5512 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5513 _bstr_("a:localname"), _bstr_(""), _bstr_("value"));
5514 EXPECT_HR(hr
, S_OK
);
5515 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5516 _bstr_("b:localname"), _bstr_(""), _bstr_("value"));
5517 EXPECT_HR(hr
, S_OK
);
5520 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localnameW
, lstrlenW(localnameW
), &index
);
5521 EXPECT_HR(hr
, S_OK
);
5522 ok(index
== 0, "%s: got index %d\n", table
->name
, index
);
5525 hr
= ISAXAttributes_getIndexFromName(saxattr
, uri1W
, lstrlenW(uri1W
), localnameW
, lstrlenW(localnameW
), &index
);
5526 EXPECT_HR(hr
, E_INVALIDARG
);
5527 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5530 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), &index
);
5531 EXPECT_HR(hr
, E_INVALIDARG
);
5532 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5534 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5535 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5537 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5538 EXPECT_HR(hr
, E_POINTER
);
5540 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5541 EXPECT_HR(hr
, E_POINTER
);
5545 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5546 EXPECT_HR(hr
, E_INVALIDARG
);
5548 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5549 EXPECT_HR(hr
, E_INVALIDARG
);
5552 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), NULL
, 0, &index
);
5553 EXPECT_HR(hr
, E_INVALIDARG
);
5555 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, localname1W
, lstrlenW(localname1W
), &index
);
5556 EXPECT_HR(hr
, E_INVALIDARG
);
5560 ISAXAttributes_Release(saxattr
);
5561 IMXAttributes_Release(mxattr
);
5566 static void test_mxwriter_indent(void)
5568 ISAXContentHandler
*content
;
5573 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMXWriter
, (void**)&writer
);
5574 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
5576 hr
= IMXWriter_put_indent(writer
, VARIANT_TRUE
);
5577 ok(hr
== S_OK
, "got %08x\n", hr
);
5579 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
5580 ok(hr
== S_OK
, "got %08x\n", hr
);
5582 hr
= ISAXContentHandler_startDocument(content
);
5583 ok(hr
== S_OK
, "got %08x\n", hr
);
5585 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
5586 ok(hr
== S_OK
, "got %08x\n", hr
);
5588 hr
= ISAXContentHandler_characters(content
, _bstr_(""), 0);
5589 ok(hr
== S_OK
, "got %08x\n", hr
);
5591 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("b"), -1, NULL
);
5592 ok(hr
== S_OK
, "got %08x\n", hr
);
5594 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("c"), -1, NULL
);
5595 ok(hr
== S_OK
, "got %08x\n", hr
);
5597 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("c"), -1);
5598 ok(hr
== S_OK
, "got %08x\n", hr
);
5600 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("b"), -1);
5601 ok(hr
== S_OK
, "got %08x\n", hr
);
5603 hr
= ISAXContentHandler_endElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1);
5604 ok(hr
== S_OK
, "got %08x\n", hr
);
5606 hr
= ISAXContentHandler_endDocument(content
);
5607 ok(hr
== S_OK
, "got %08x\n", hr
);
5609 V_VT(&dest
) = VT_EMPTY
;
5610 hr
= IMXWriter_get_output(writer
, &dest
);
5611 ok(hr
== S_OK
, "got %08x\n", hr
);
5612 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
5613 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
)),
5614 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
5615 VariantClear(&dest
);
5617 ISAXContentHandler_Release(content
);
5618 IMXWriter_Release(writer
);
5623 START_TEST(saxreader
)
5625 ISAXXMLReader
*reader
;
5628 hr
= CoInitialize(NULL
);
5629 ok(hr
== S_OK
, "failed to init com\n");
5631 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
5632 &IID_ISAXXMLReader
, (void**)&reader
);
5636 win_skip("Failed to create SAXXMLReader instance\n");
5640 ISAXXMLReader_Release(reader
);
5642 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
5644 get_class_support_data(reader_support_data
, &IID_ISAXXMLReader
);
5647 test_saxreader_properties();
5648 test_saxreader_features();
5649 test_saxreader_encoding();
5650 test_saxreader_dispex();
5652 /* MXXMLWriter tests */
5653 get_class_support_data(mxwriter_support_data
, &IID_IMXWriter
);
5654 if (is_clsid_supported(&CLSID_MXXMLWriter
, mxwriter_support_data
))
5656 test_mxwriter_handlers();
5657 test_mxwriter_startenddocument();
5658 test_mxwriter_startendelement();
5659 test_mxwriter_characters();
5660 test_mxwriter_comment();
5661 test_mxwriter_cdata();
5663 test_mxwriter_ignorablespaces();
5664 test_mxwriter_dtd();
5665 test_mxwriter_properties();
5666 test_mxwriter_flush();
5667 test_mxwriter_stream();
5668 test_mxwriter_encoding();
5669 test_mxwriter_dispex();
5670 test_mxwriter_indent();
5673 win_skip("MXXMLWriter not supported\n");
5675 /* SAXAttributes tests */
5676 get_class_support_data(mxattributes_support_data
, &IID_IMXAttributes
);
5677 if (is_clsid_supported(&CLSID_SAXAttributes
, mxattributes_support_data
))
5680 test_mxattr_addAttribute();
5681 test_mxattr_clear();
5682 test_mxattr_localname();
5683 test_mxattr_dispex();
5686 win_skip("SAXAttributes not supported\n");