2 * SAXReader/MXWriter tests
4 * Copyright 2008 Piotr Caban
5 * Copyright 2011 Thomas Mullaly
6 * Copyright 2012 Nikolay Sivov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "msxml2did.h"
36 #include "wine/test.h"
38 #define EXPECT_HR(hr,hr_exp) \
39 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
41 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
42 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
44 ULONG rc
= IUnknown_AddRef(obj
);
45 IUnknown_Release(obj
);
46 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
49 static LONG
get_refcount(void *iface
)
51 IUnknown
*unk
= iface
;
54 ref
= IUnknown_AddRef(unk
);
55 IUnknown_Release(unk
);
59 struct msxmlsupported_data_t
66 static BOOL
is_clsid_supported(const GUID
*clsid
, const struct msxmlsupported_data_t
*table
)
70 if (table
->clsid
== clsid
) return table
->supported
;
76 static BSTR
alloc_str_from_narrow(const char *str
)
78 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
79 BSTR ret
= SysAllocStringLen(NULL
, len
- 1); /* NUL character added automatically */
80 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
84 static BSTR alloced_bstrs
[512];
85 static int alloced_bstrs_count
;
87 static BSTR
_bstr_(const char *str
)
89 assert(alloced_bstrs_count
< sizeof(alloced_bstrs
)/sizeof(alloced_bstrs
[0]));
90 alloced_bstrs
[alloced_bstrs_count
] = alloc_str_from_narrow(str
);
91 return alloced_bstrs
[alloced_bstrs_count
++];
94 static void free_bstrs(void)
97 for (i
= 0; i
< alloced_bstrs_count
; i
++)
98 SysFreeString(alloced_bstrs
[i
]);
99 alloced_bstrs_count
= 0;
102 static void test_saxstr(const char *file
, unsigned line
, BSTR str
, const char *expected
, int todo
, int *failcount
)
104 int len
, lenexp
, cmp
;
107 len
= SysStringLen(str
);
114 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
117 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
123 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
126 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
130 lenexp
= strlen(expected
);
131 if (lenexp
!= len
&& todo
)
135 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
138 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
140 /* exit earlier on length mismatch */
141 if (lenexp
!= len
) return;
143 MultiByteToWideChar(CP_ACP
, 0, expected
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
145 cmp
= memcmp(str
, buf
, lenexp
*sizeof(WCHAR
));
150 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
151 wine_dbgstr_wn(str
, len
), expected
);
154 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
155 wine_dbgstr_wn(str
, len
), expected
);
160 CH_PUTDOCUMENTLOCATOR
,
163 CH_STARTPREFIXMAPPING
,
168 CH_IGNORABLEWHITESPACE
,
169 CH_PROCESSINGINSTRUCTION
,
179 static const char *event_names
[EVENT_LAST
] = {
181 "putDocumentLocator",
184 "startPrefixMapping",
189 "ignorableWhitespace",
190 "processingInstruction",
199 struct attribute_entry
{
205 /* used for actual call data only, null for expected call data */
221 /* allocated once at startElement callback */
222 struct attribute_entry
*attributes
;
225 /* used for actual call data only, null for expected call data */
235 struct call_entry
*sequence
;
238 #define CONTENT_HANDLER_INDEX 0
239 #define NUM_CALL_SEQUENCES 1
240 static struct call_sequence
*sequences
[NUM_CALL_SEQUENCES
];
242 static void init_call_entry(ISAXLocator
*locator
, struct call_entry
*call
)
244 memset(call
, 0, sizeof(*call
));
245 ISAXLocator_getLineNumber(locator
, &call
->line
);
246 ISAXLocator_getColumnNumber(locator
, &call
->column
);
249 static void add_call(struct call_sequence
**seq
, int sequence_index
,
250 const struct call_entry
*call
)
252 struct call_sequence
*call_seq
= seq
[sequence_index
];
254 if (!call_seq
->sequence
)
257 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0,
258 call_seq
->size
* sizeof (struct call_entry
));
261 if (call_seq
->count
== call_seq
->size
)
264 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
266 call_seq
->size
* sizeof (struct call_entry
));
269 assert(call_seq
->sequence
);
271 call_seq
->sequence
[call_seq
->count
].id
= call
->id
;
272 call_seq
->sequence
[call_seq
->count
].line
= call
->line
;
273 call_seq
->sequence
[call_seq
->count
].column
= call
->column
;
274 call_seq
->sequence
[call_seq
->count
].arg1W
= call
->arg1W
;
275 call_seq
->sequence
[call_seq
->count
].arg2W
= call
->arg2W
;
276 call_seq
->sequence
[call_seq
->count
].arg3W
= call
->arg3W
;
277 call_seq
->sequence
[call_seq
->count
].ret
= call
->ret
;
278 call_seq
->sequence
[call_seq
->count
].attr_count
= call
->attr_count
;
279 call_seq
->sequence
[call_seq
->count
].attributes
= call
->attributes
;
284 static inline void flush_sequence(struct call_sequence
**seg
, int sequence_index
)
288 struct call_sequence
*call_seq
= seg
[sequence_index
];
290 for (i
= 0; i
< call_seq
->count
; i
++)
294 for (j
= 0; j
< call_seq
->sequence
[i
].attr_count
; j
++)
296 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].uriW
);
297 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].localW
);
298 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].qnameW
);
301 SysFreeString(call_seq
->sequence
[i
].arg1W
);
302 SysFreeString(call_seq
->sequence
[i
].arg2W
);
303 SysFreeString(call_seq
->sequence
[i
].arg3W
);
306 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
307 call_seq
->sequence
= NULL
;
308 call_seq
->count
= call_seq
->size
= 0;
311 static inline void flush_sequences(struct call_sequence
**seq
, int n
)
314 for (i
= 0; i
< n
; i
++)
315 flush_sequence(seq
, i
);
318 static const char *get_event_name(CH event
)
320 return event_names
[event
];
323 static void compare_attributes(const struct call_entry
*actual
, const struct call_entry
*expected
, const char *context
,
324 int todo
, const char *file
, int line
, int *failcount
)
328 /* attribute count is not stored for expected data */
329 if (expected
->attributes
)
331 struct attribute_entry
*ptr
= expected
->attributes
;
332 while (ptr
->uri
) { lenexp
++; ptr
++; };
335 /* check count first and exit earlier */
336 if (actual
->attr_count
!= lenexp
&& todo
)
340 ok_(file
, line
) (FALSE
, "%s: in event %s expecting attr count %d got %d\n",
341 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
344 ok_(file
, line
) (actual
->attr_count
== lenexp
, "%s: in event %s expecting attr count %d got %d\n",
345 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
347 if (actual
->attr_count
!= lenexp
) return;
349 /* now compare all attributes strings */
350 for (i
= 0; i
< actual
->attr_count
; i
++)
352 test_saxstr(file
, line
, actual
->attributes
[i
].uriW
, expected
->attributes
[i
].uri
, todo
, failcount
);
353 test_saxstr(file
, line
, actual
->attributes
[i
].localW
, expected
->attributes
[i
].local
, todo
, failcount
);
354 test_saxstr(file
, line
, actual
->attributes
[i
].qnameW
, expected
->attributes
[i
].qname
, todo
, failcount
);
355 test_saxstr(file
, line
, actual
->attributes
[i
].valueW
, expected
->attributes
[i
].value
, todo
, failcount
);
359 static void ok_sequence_(struct call_sequence
**seq
, int sequence_index
,
360 const struct call_entry
*expected
, const char *context
, int todo
,
361 const char *file
, int line
)
363 struct call_sequence
*call_seq
= seq
[sequence_index
];
364 static const struct call_entry end_of_sequence
= { CH_ENDTEST
};
365 const struct call_entry
*actual
, *sequence
;
368 add_call(seq
, sequence_index
, &end_of_sequence
);
370 sequence
= call_seq
->sequence
;
373 while (expected
->id
!= CH_ENDTEST
&& actual
->id
!= CH_ENDTEST
)
375 if (expected
->id
== actual
->id
)
377 /* always test position data */
378 if (expected
->line
!= actual
->line
&& todo
)
383 ok_(file
, line
) (FALSE
,
384 "%s: in event %s expecting line %d got %d\n",
385 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
390 ok_(file
, line
) (expected
->line
== actual
->line
,
391 "%s: in event %s expecting line %d got %d\n",
392 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
395 if (expected
->column
!= actual
->column
&& todo
)
400 ok_(file
, line
) (FALSE
,
401 "%s: in event %s expecting column %d got %d\n",
402 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
407 ok_(file
, line
) (expected
->column
== actual
->column
,
408 "%s: in event %s expecting column %d got %d\n",
409 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
414 case CH_PUTDOCUMENTLOCATOR
:
415 case CH_STARTDOCUMENT
:
420 case CH_STARTPREFIXMAPPING
:
422 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
423 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
425 case CH_ENDPREFIXMAPPING
:
427 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
429 case CH_STARTELEMENT
:
430 /* compare attributes */
431 compare_attributes(actual
, expected
, context
, todo
, file
, line
, &failcount
);
434 /* uri, localname, qname */
435 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
436 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
437 test_saxstr(file
, line
, actual
->arg3W
, expected
->arg3
, todo
, &failcount
);
440 case CH_IGNORABLEWHITESPACE
:
442 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
444 case CH_PROCESSINGINSTRUCTION
:
446 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
447 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
449 case CH_SKIPPEDENTITY
:
451 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
454 /* test return value only */
455 if (expected
->ret
!= actual
->ret
&& todo
)
458 ok_(file
, line
) (FALSE
,
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 ok_(file
, line
) (expected
->ret
== actual
->ret
,
464 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
465 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
468 case EH_IGNORABLEWARNING
:
470 ok(0, "%s: callback not handled, %s\n", context
, get_event_name(actual
->id
));
480 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
481 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
484 flush_sequence(seq
, sequence_index
);
489 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
490 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
500 if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
503 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
504 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
508 else if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
510 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
511 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
514 if (todo
&& !failcount
) /* succeeded yet marked todo */
518 ok_(file
, line
)(TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
522 flush_sequence(seq
, sequence_index
);
525 #define ok_sequence(seq, index, exp, contx, todo) \
526 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
528 static void init_call_sequences(struct call_sequence
**seq
, int n
)
532 for (i
= 0; i
< n
; i
++)
533 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct call_sequence
));
536 static const WCHAR szSimpleXML
[] = {
537 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
538 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
539 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
540 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
541 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
544 static const WCHAR carriage_ret_test
[] = {
545 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
546 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
547 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
548 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
549 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
552 static const WCHAR szUtf16XML
[] = {
553 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
554 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
555 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
558 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
560 static const CHAR szUtf8XML
[] =
561 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
563 static const char utf8xml2
[] =
564 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n";
566 static const char testXML
[] =
567 "<?xml version=\"1.0\" ?>\n"
569 " <Number>1234</Number>\n"
570 " <Name>Captain Ahab</Name>\n"
573 static const char test_attributes
[] =
574 "<?xml version=\"1.0\" ?>\n"
575 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
576 "<node1 xmlns:p=\"test\" />"
579 static const char test_cdata_xml
[] =
580 "<?xml version=\"1.0\" ?>"
581 "<a><![CDATA[Some \r\ntext\n\r\ndata\n\n]]></a>";
583 static const char test2_cdata_xml
[] =
584 "<?xml version=\"1.0\" ?>"
585 "<a><![CDATA[\n\r\nSome \r\ntext\n\r\ndata\n\n]]></a>";
587 static const char test3_cdata_xml
[] =
588 "<?xml version=\"1.0\" ?><a><![CDATA[Some text data]]></a>";
590 static struct call_entry content_handler_test1
[] = {
591 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
592 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
593 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
594 { CH_CHARACTERS
, 2, 14, S_OK
, "\n " },
595 { CH_STARTELEMENT
, 3, 12, S_OK
, "", "Number", "Number" },
596 { CH_CHARACTERS
, 3, 12, S_OK
, "1234" },
597 { CH_ENDELEMENT
, 3, 18, S_OK
, "", "Number", "Number" },
598 { CH_CHARACTERS
, 3, 25, S_OK
, "\n " },
599 { CH_STARTELEMENT
, 4, 10, S_OK
, "", "Name", "Name" },
600 { CH_CHARACTERS
, 4, 10, S_OK
, "Captain Ahab" },
601 { CH_ENDELEMENT
, 4, 24, S_OK
, "", "Name", "Name" },
602 { CH_CHARACTERS
, 4, 29, S_OK
, "\n" },
603 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
604 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
608 /* applies to versions 4 and 6 */
609 static struct call_entry content_handler_test1_alternate
[] = {
610 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
611 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
612 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
613 { CH_CHARACTERS
, 3, 4, S_OK
, "\n " },
614 { CH_STARTELEMENT
, 3, 11, S_OK
, "", "Number", "Number" },
615 { CH_CHARACTERS
, 3, 16, S_OK
, "1234" },
616 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "Number", "Number" },
617 { CH_CHARACTERS
, 4, 4, S_OK
, "\n " },
618 { CH_STARTELEMENT
, 4, 9, S_OK
, "", "Name", "Name" },
619 { CH_CHARACTERS
, 4, 22, S_OK
, "Captain Ahab" },
620 { CH_ENDELEMENT
, 4, 28, S_OK
, "", "Name", "Name" },
621 { CH_CHARACTERS
, 5, 1, S_OK
, "\n" },
622 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
623 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
627 static struct call_entry content_handler_test2
[] = {
628 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
629 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
630 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
631 { CH_CHARACTERS
, 2, 14, S_OK
, "\n" },
632 { CH_CHARACTERS
, 2, 16, S_OK
, "\t" },
633 { CH_STARTELEMENT
, 3, 10, S_OK
, "", "Number", "Number" },
634 { CH_CHARACTERS
, 3, 10, S_OK
, "1234" },
635 { CH_ENDELEMENT
, 3, 16, S_OK
, "", "Number", "Number" },
636 { CH_CHARACTERS
, 3, 23, S_OK
, "\n" },
637 { CH_CHARACTERS
, 3, 25, S_OK
, "\t" },
638 { CH_STARTELEMENT
, 4, 8, S_OK
, "", "Name", "Name" },
639 { CH_CHARACTERS
, 4, 8, S_OK
, "Captain Ahab" },
640 { CH_ENDELEMENT
, 4, 22, S_OK
, "", "Name", "Name" },
641 { CH_CHARACTERS
, 4, 27, S_OK
, "\n" },
642 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
643 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
647 static struct call_entry content_handler_test2_alternate
[] = {
648 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
649 { CH_STARTDOCUMENT
, 1, 21, S_OK
},
650 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
651 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
652 { CH_CHARACTERS
, 3, 2, S_OK
, "\t" },
653 { CH_STARTELEMENT
, 3, 9, S_OK
, "", "Number", "Number" },
654 { CH_CHARACTERS
, 3, 14, S_OK
, "1234" },
655 { CH_ENDELEMENT
, 3, 22, S_OK
, "", "Number", "Number" },
656 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
657 { CH_CHARACTERS
, 4, 2, S_OK
, "\t" },
658 { CH_STARTELEMENT
, 4, 7, S_OK
, "", "Name", "Name" },
659 { CH_CHARACTERS
, 4, 20, S_OK
, "Captain Ahab" },
660 { CH_ENDELEMENT
, 4, 26, S_OK
, "", "Name", "Name" },
661 { CH_CHARACTERS
, 5, 0, S_OK
, "\n" },
662 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
663 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
667 static struct call_entry content_handler_testerror
[] = {
668 { CH_PUTDOCUMENTLOCATOR
, 0, 0, E_FAIL
},
669 { EH_FATALERROR
, 0, 0, E_FAIL
},
673 static struct call_entry content_handler_testerror_alternate
[] = {
674 { CH_PUTDOCUMENTLOCATOR
, 1, 0, E_FAIL
},
675 { EH_FATALERROR
, 1, 0, E_FAIL
},
679 static struct call_entry content_handler_test_callback_rets
[] = {
680 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_FALSE
},
681 { CH_STARTDOCUMENT
, 0, 0, S_FALSE
},
682 { EH_FATALERROR
, 0, 0, S_FALSE
},
686 static struct call_entry content_handler_test_callback_rets_alt
[] = {
687 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_FALSE
},
688 { CH_STARTDOCUMENT
, 1, 22, S_FALSE
},
689 { CH_STARTELEMENT
, 2, 13, S_FALSE
, "", "BankAccount", "BankAccount" },
690 { CH_CHARACTERS
, 3, 4, S_FALSE
, "\n " },
691 { CH_STARTELEMENT
, 3, 11, S_FALSE
, "", "Number", "Number" },
692 { CH_CHARACTERS
, 3, 16, S_FALSE
, "1234" },
693 { CH_ENDELEMENT
, 3, 24, S_FALSE
, "", "Number", "Number" },
694 { CH_CHARACTERS
, 4, 4, S_FALSE
, "\n " },
695 { CH_STARTELEMENT
, 4, 9, S_FALSE
, "", "Name", "Name" },
696 { CH_CHARACTERS
, 4, 22, S_FALSE
, "Captain Ahab" },
697 { CH_ENDELEMENT
, 4, 28, S_FALSE
, "", "Name", "Name" },
698 { CH_CHARACTERS
, 5, 1, S_FALSE
, "\n" },
699 { CH_ENDELEMENT
, 5, 14, S_FALSE
, "", "BankAccount", "BankAccount" },
700 { CH_ENDDOCUMENT
, 6, 0, S_FALSE
},
704 static struct attribute_entry ch_attributes1
[] = {
705 { "", "", "xmlns:test", "prefix_test" },
706 { "", "", "xmlns", "prefix" },
707 { "prefix_test", "arg1", "test:arg1", "arg1" },
708 { "", "arg2", "arg2", "arg2" },
709 { "prefix_test", "ar3", "test:ar3", "arg3" },
713 static struct attribute_entry ch_attributes2
[] = {
714 { "", "", "xmlns:p", "test" },
718 static struct call_entry content_handler_test_attributes
[] = {
719 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
720 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
721 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
722 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
723 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes1
},
724 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
725 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
726 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
727 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
728 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
729 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
730 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
731 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
732 { CH_ENDDOCUMENT
, 0, 0 },
736 static struct attribute_entry ch_attributes_alt_4
[] = {
737 { "prefix_test", "arg1", "test:arg1", "arg1" },
738 { "", "arg2", "arg2", "arg2" },
739 { "prefix_test", "ar3", "test:ar3", "arg3" },
740 { "", "", "xmlns:test", "prefix_test" },
741 { "", "", "xmlns", "prefix" },
745 static struct call_entry content_handler_test_attributes_alternate_4
[] = {
746 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
747 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
748 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
749 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
750 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_4
},
751 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
752 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
753 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
754 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
755 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
756 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
757 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
758 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
759 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
763 /* 'namespace' feature switched off */
764 static struct attribute_entry ch_attributes_alt_no_ns
[] = {
765 { "", "", "xmlns:test", "prefix_test" },
766 { "", "", "xmlns", "prefix" },
767 { "", "", "test:arg1", "arg1" },
768 { "", "", "arg2", "arg2" },
769 { "", "", "test:ar3", "arg3" },
773 static struct call_entry content_handler_test_attributes_alt_no_ns
[] = {
774 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
775 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
776 { CH_STARTELEMENT
, 2, 95, S_OK
, "", "", "document", ch_attributes_alt_no_ns
},
777 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
778 { CH_STARTELEMENT
, 3, 24, S_OK
, "", "", "node1", ch_attributes2
},
779 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "", "node1" },
780 { CH_ENDELEMENT
, 3, 35, S_OK
, "", "", "document" },
781 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
785 static struct attribute_entry ch_attributes_alt_6
[] = {
786 { "prefix_test", "arg1", "test:arg1", "arg1" },
787 { "", "arg2", "arg2", "arg2" },
788 { "prefix_test", "ar3", "test:ar3", "arg3" },
789 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
790 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
794 static struct attribute_entry ch_attributes2_6
[] = {
795 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
799 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
800 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
801 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
802 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
803 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
804 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
805 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
806 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
807 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
808 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
809 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
810 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
811 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
812 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
813 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
817 /* 'namespaces' is on, 'namespace-prefixes' if off */
818 static struct attribute_entry ch_attributes_no_prefix
[] = {
819 { "prefix_test", "arg1", "test:arg1", "arg1" },
820 { "", "arg2", "arg2", "arg2" },
821 { "prefix_test", "ar3", "test:ar3", "arg3" },
825 static struct call_entry content_handler_test_attributes_alt_no_prefix
[] = {
826 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
827 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
828 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
829 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
830 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
831 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
832 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
833 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", NULL
},
834 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
835 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
836 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
837 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
838 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
839 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
843 static struct call_entry content_handler_test_attributes_no_prefix
[] = {
844 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
845 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
846 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
847 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
848 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
849 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
850 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
851 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", NULL
},
852 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
853 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
854 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
855 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
856 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
857 { CH_ENDDOCUMENT
, 0, 0 },
861 static struct attribute_entry xmlspace_attrs
[] = {
862 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
866 static struct call_entry xmlspaceattr_test
[] = {
867 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
868 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
869 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
870 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
871 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
872 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
876 static struct call_entry xmlspaceattr_test_alternate
[] = {
877 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
878 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
879 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
880 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
881 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
882 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
886 /* attribute value normalization test */
887 static const char attribute_normalize
[] =
888 "<?xml version=\"1.0\" ?>\n"
889 "<a attr1=\" \r \n \tattr_value A \t \r \n\r\n \n\"/>\n";
891 static struct attribute_entry attribute_norm_attrs
[] = {
892 { "", "attr1", "attr1", " attr_value A " },
896 static struct call_entry attribute_norm
[] = {
897 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
898 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
899 { CH_STARTELEMENT
, 6, 4, S_OK
, "", "a", "a", attribute_norm_attrs
},
900 { CH_ENDELEMENT
, 6, 4, S_OK
, "", "a", "a" },
901 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
905 static struct call_entry attribute_norm_alt
[] = {
906 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
907 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
908 { CH_STARTELEMENT
, 8, 3, S_OK
, "", "a", "a", attribute_norm_attrs
},
909 { CH_ENDELEMENT
, 8, 3, S_OK
, "", "a", "a" },
910 { CH_ENDDOCUMENT
, 9, 0, S_OK
},
914 static struct call_entry cdata_test
[] = {
915 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
916 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
917 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
918 { LH_STARTCDATA
, 1, 35, S_OK
},
919 { CH_CHARACTERS
, 1, 35, S_OK
, "Some \n" },
920 { CH_CHARACTERS
, 1, 42, S_OK
, "text\n\n" },
921 { CH_CHARACTERS
, 1, 49, S_OK
, "data\n\n" },
922 { LH_ENDCDATA
, 1, 49, S_OK
},
923 { CH_ENDELEMENT
, 6, 6, S_OK
, "", "a", "a" },
924 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
928 static struct call_entry cdata_test2
[] = {
929 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
930 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
931 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
932 { LH_STARTCDATA
, 1, 35, S_OK
},
933 { CH_CHARACTERS
, 1, 35, S_OK
, "\n\n" },
934 { CH_CHARACTERS
, 1, 38, S_OK
, "Some \n" },
935 { CH_CHARACTERS
, 1, 45, S_OK
, "text\n\n" },
936 { CH_CHARACTERS
, 1, 52, S_OK
, "data\n\n" },
937 { LH_ENDCDATA
, 1, 52, S_OK
},
938 { CH_ENDELEMENT
, 8, 6, S_OK
, "", "a", "a" },
939 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
943 static struct call_entry cdata_test3
[] = {
944 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
945 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
946 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
947 { LH_STARTCDATA
, 1, 35, S_OK
},
948 { CH_CHARACTERS
, 1, 35, S_OK
, "Some text data" },
949 { LH_ENDCDATA
, 1, 35, S_OK
},
950 { CH_ENDELEMENT
, 1, 54, S_OK
, "", "a", "a" },
951 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
955 /* this is what MSXML6 does */
956 static struct call_entry cdata_test_alt
[] = {
957 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
958 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
959 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
960 { LH_STARTCDATA
, 1, 34, S_OK
},
961 { CH_CHARACTERS
, 1, 40, S_OK
, "Some " },
962 { CH_CHARACTERS
, 2, 0, S_OK
, "\n" },
963 { CH_CHARACTERS
, 3, 1, S_OK
, "text\n" },
964 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
965 { CH_CHARACTERS
, 6, 3, S_OK
, "data\n\n" },
966 { LH_ENDCDATA
, 6, 3, S_OK
},
967 { CH_ENDELEMENT
, 6, 7, S_OK
, "", "a", "a" },
968 { CH_ENDDOCUMENT
, 6, 7, S_OK
},
972 static struct call_entry cdata_test2_alt
[] = {
973 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
974 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
975 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
976 { LH_STARTCDATA
, 1, 34, S_OK
},
977 { CH_CHARACTERS
, 2, 1, S_OK
, "\n" },
978 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
979 { CH_CHARACTERS
, 3, 6, S_OK
, "Some " },
980 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
981 { CH_CHARACTERS
, 5, 1, S_OK
, "text\n" },
982 { CH_CHARACTERS
, 6, 0, S_OK
, "\n" },
983 { CH_CHARACTERS
, 8, 3, S_OK
, "data\n\n" },
984 { LH_ENDCDATA
, 8, 3, S_OK
},
985 { CH_ENDELEMENT
, 8, 7, S_OK
, "", "a", "a" },
986 { CH_ENDDOCUMENT
, 8, 7, S_OK
},
990 static struct call_entry cdata_test3_alt
[] = {
991 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
992 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
993 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
994 { LH_STARTCDATA
, 1, 34, S_OK
},
995 { CH_CHARACTERS
, 1, 51, S_OK
, "Some text data" },
996 { LH_ENDCDATA
, 1, 51, S_OK
},
997 { CH_ENDELEMENT
, 1, 55, S_OK
, "", "a", "a" },
998 { CH_ENDDOCUMENT
, 1, 55, S_OK
},
1002 static const char xmlspace_attr
[] =
1003 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
1004 "<a xml:space=\"preserve\"> Some text data </a>";
1006 static struct call_entry
*expectCall
;
1007 static ISAXLocator
*locator
;
1008 static ISAXXMLReader
*g_reader
;
1011 static void set_expected_seq(struct call_entry
*expected
)
1013 expectCall
= expected
;
1016 /* to be called once on each tested callback return */
1017 static HRESULT
get_expected_ret(void)
1019 HRESULT hr
= expectCall
->ret
;
1020 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
1024 static HRESULT WINAPI
contentHandler_QueryInterface(
1025 ISAXContentHandler
* iface
,
1031 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
1037 return E_NOINTERFACE
;
1043 static ULONG WINAPI
contentHandler_AddRef(
1044 ISAXContentHandler
* iface
)
1049 static ULONG WINAPI
contentHandler_Release(
1050 ISAXContentHandler
* iface
)
1055 static HRESULT WINAPI
contentHandler_putDocumentLocator(
1056 ISAXContentHandler
* iface
,
1057 ISAXLocator
*pLocator
)
1059 struct call_entry call
;
1064 init_call_entry(locator
, &call
);
1065 call
.id
= CH_PUTDOCUMENTLOCATOR
;
1066 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1068 if (msxml_version
>= 6) {
1069 ISAXAttributes
*attr
, *attr1
;
1070 IMXAttributes
*mxattr
;
1072 EXPECT_REF(pLocator
, 1);
1073 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
1074 EXPECT_HR(hr
, S_OK
);
1075 EXPECT_REF(pLocator
, 2);
1076 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
1077 EXPECT_HR(hr
, S_OK
);
1078 EXPECT_REF(pLocator
, 3);
1079 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
1081 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
1082 EXPECT_HR(hr
, E_NOINTERFACE
);
1084 ISAXAttributes_Release(attr
);
1085 ISAXAttributes_Release(attr1
);
1088 return get_expected_ret();
1091 static ISAXAttributes
*test_attr_ptr
;
1092 static HRESULT WINAPI
contentHandler_startDocument(
1093 ISAXContentHandler
* iface
)
1095 struct call_entry call
;
1097 init_call_entry(locator
, &call
);
1098 call
.id
= CH_STARTDOCUMENT
;
1099 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1101 test_attr_ptr
= NULL
;
1103 return get_expected_ret();
1106 static HRESULT WINAPI
contentHandler_endDocument(
1107 ISAXContentHandler
* iface
)
1109 struct call_entry call
;
1111 init_call_entry(locator
, &call
);
1112 call
.id
= CH_ENDDOCUMENT
;
1113 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1115 return get_expected_ret();
1118 static HRESULT WINAPI
contentHandler_startPrefixMapping(
1119 ISAXContentHandler
* iface
,
1120 const WCHAR
*prefix
, int prefix_len
,
1121 const WCHAR
*uri
, int uri_len
)
1123 struct call_entry call
;
1125 init_call_entry(locator
, &call
);
1126 call
.id
= CH_STARTPREFIXMAPPING
;
1127 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
1128 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
1129 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1131 return get_expected_ret();
1134 static HRESULT WINAPI
contentHandler_endPrefixMapping(
1135 ISAXContentHandler
* iface
,
1136 const WCHAR
*prefix
, int len
)
1138 struct call_entry call
;
1140 init_call_entry(locator
, &call
);
1141 call
.id
= CH_ENDPREFIXMAPPING
;
1142 call
.arg1W
= SysAllocStringLen(prefix
, len
);
1143 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1145 return get_expected_ret();
1148 static HRESULT WINAPI
contentHandler_startElement(
1149 ISAXContentHandler
* iface
,
1150 const WCHAR
*uri
, int uri_len
,
1151 const WCHAR
*localname
, int local_len
,
1152 const WCHAR
*qname
, int qname_len
,
1153 ISAXAttributes
*saxattr
)
1155 struct call_entry call
;
1156 IMXAttributes
*mxattr
;
1160 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
1161 EXPECT_HR(hr
, E_NOINTERFACE
);
1163 init_call_entry(locator
, &call
);
1164 call
.id
= CH_STARTELEMENT
;
1165 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1166 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1167 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1170 test_attr_ptr
= saxattr
;
1171 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
1173 /* store actual attributes */
1175 hr
= ISAXAttributes_getLength(saxattr
, &len
);
1176 EXPECT_HR(hr
, S_OK
);
1183 struct attribute_entry
*attr
;
1184 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
1187 hr
= ISAXXMLReader_getFeature(g_reader
, _bstr_("http://xml.org/sax/features/namespaces"), &v
);
1188 EXPECT_HR(hr
, S_OK
);
1190 for (i
= 0; i
< len
; i
++)
1195 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
1196 &localname
, &local_len
, &qname
, &qname_len
);
1197 EXPECT_HR(hr
, S_OK
);
1199 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
1200 EXPECT_HR(hr
, S_OK
);
1202 /* if 'namespaces' switched off uri and local name contains garbage */
1203 if (v
== VARIANT_FALSE
&& msxml_version
> 0)
1205 attr
[i
].uriW
= SysAllocStringLen(NULL
, 0);
1206 attr
[i
].localW
= SysAllocStringLen(NULL
, 0);
1210 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
1211 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
1214 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
1215 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
1218 call
.attributes
= attr
;
1219 call
.attr_count
= len
;
1222 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1224 return get_expected_ret();
1227 static HRESULT WINAPI
contentHandler_endElement(
1228 ISAXContentHandler
* iface
,
1229 const WCHAR
*uri
, int uri_len
,
1230 const WCHAR
*localname
, int local_len
,
1231 const WCHAR
*qname
, int qname_len
)
1233 struct call_entry call
;
1235 init_call_entry(locator
, &call
);
1236 call
.id
= CH_ENDELEMENT
;
1237 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1238 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1239 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1240 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1242 return get_expected_ret();
1245 static HRESULT WINAPI
contentHandler_characters(
1246 ISAXContentHandler
* iface
,
1250 struct call_entry call
;
1252 init_call_entry(locator
, &call
);
1253 call
.id
= CH_CHARACTERS
;
1254 call
.arg1W
= SysAllocStringLen(chars
, len
);
1255 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1257 return get_expected_ret();
1260 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1261 ISAXContentHandler
* iface
,
1262 const WCHAR
*chars
, int len
)
1264 struct call_entry call
;
1266 init_call_entry(locator
, &call
);
1267 call
.id
= CH_IGNORABLEWHITESPACE
;
1268 call
.arg1W
= SysAllocStringLen(chars
, len
);
1269 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1271 return get_expected_ret();
1274 static HRESULT WINAPI
contentHandler_processingInstruction(
1275 ISAXContentHandler
* iface
,
1276 const WCHAR
*target
, int target_len
,
1277 const WCHAR
*data
, int data_len
)
1279 struct call_entry call
;
1281 init_call_entry(locator
, &call
);
1282 call
.id
= CH_PROCESSINGINSTRUCTION
;
1283 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1284 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1285 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1287 return get_expected_ret();
1290 static HRESULT WINAPI
contentHandler_skippedEntity(
1291 ISAXContentHandler
* iface
,
1292 const WCHAR
*name
, int len
)
1294 struct call_entry call
;
1296 init_call_entry(locator
, &call
);
1297 call
.id
= CH_SKIPPEDENTITY
;
1298 call
.arg1W
= SysAllocStringLen(name
, len
);
1299 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1301 return get_expected_ret();
1304 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1306 contentHandler_QueryInterface
,
1307 contentHandler_AddRef
,
1308 contentHandler_Release
,
1309 contentHandler_putDocumentLocator
,
1310 contentHandler_startDocument
,
1311 contentHandler_endDocument
,
1312 contentHandler_startPrefixMapping
,
1313 contentHandler_endPrefixMapping
,
1314 contentHandler_startElement
,
1315 contentHandler_endElement
,
1316 contentHandler_characters
,
1317 contentHandler_ignorableWhitespace
,
1318 contentHandler_processingInstruction
,
1319 contentHandler_skippedEntity
1322 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1324 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1325 ISAXErrorHandler
* iface
,
1331 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1337 return E_NOINTERFACE
;
1343 static ULONG WINAPI
isaxerrorHandler_AddRef(
1344 ISAXErrorHandler
* iface
)
1349 static ULONG WINAPI
isaxerrorHandler_Release(
1350 ISAXErrorHandler
* iface
)
1355 static HRESULT WINAPI
isaxerrorHandler_error(
1356 ISAXErrorHandler
* iface
,
1357 ISAXLocator
*pLocator
,
1358 const WCHAR
*pErrorMessage
,
1359 HRESULT hrErrorCode
)
1361 ok(0, "unexpected call\n");
1365 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1366 ISAXErrorHandler
* iface
,
1367 ISAXLocator
*pLocator
,
1368 const WCHAR
*message
,
1371 struct call_entry call
;
1373 init_call_entry(locator
, &call
);
1374 call
.id
= EH_FATALERROR
;
1377 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1383 static HRESULT WINAPI
isaxerrorHandler_ignorableWarning(
1384 ISAXErrorHandler
* iface
,
1385 ISAXLocator
*pLocator
,
1386 const WCHAR
*pErrorMessage
,
1387 HRESULT hrErrorCode
)
1389 ok(0, "unexpected call\n");
1393 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1395 isaxerrorHandler_QueryInterface
,
1396 isaxerrorHandler_AddRef
,
1397 isaxerrorHandler_Release
,
1398 isaxerrorHandler_error
,
1399 isaxerrorHandler_fatalError
,
1400 isaxerrorHandler_ignorableWarning
1403 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1405 static HRESULT WINAPI
isaxattributes_QueryInterface(
1406 ISAXAttributes
* iface
,
1412 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1418 return E_NOINTERFACE
;
1424 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1429 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1434 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1440 static HRESULT WINAPI
isaxattributes_getURI(
1441 ISAXAttributes
* iface
,
1446 ok(0, "unexpected call\n");
1450 static HRESULT WINAPI
isaxattributes_getLocalName(
1451 ISAXAttributes
* iface
,
1453 const WCHAR
**pLocalName
,
1454 int *pLocalNameLength
)
1456 ok(0, "unexpected call\n");
1460 static HRESULT WINAPI
isaxattributes_getQName(
1461 ISAXAttributes
* iface
,
1463 const WCHAR
**QName
,
1466 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1467 {'a','t','t','r','2','j','u','n','k',0},
1468 {'a','t','t','r','3',0}};
1469 static const int attrqnamelen
[] = {7, 5, 5};
1471 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1473 *QName
= attrqnamesW
[index
];
1474 *QNameLength
= attrqnamelen
[index
];
1479 static HRESULT WINAPI
isaxattributes_getName(
1480 ISAXAttributes
* iface
,
1484 const WCHAR
** pLocalName
,
1485 int * pLocalNameSize
,
1486 const WCHAR
** pQName
,
1489 ok(0, "unexpected call\n");
1493 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1494 ISAXAttributes
* iface
,
1497 const WCHAR
* pLocalName
,
1498 int cocalNameLength
,
1501 ok(0, "unexpected call\n");
1505 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1506 ISAXAttributes
* iface
,
1507 const WCHAR
* pQName
,
1511 ok(0, "unexpected call\n");
1515 static HRESULT WINAPI
isaxattributes_getType(
1516 ISAXAttributes
* iface
,
1518 const WCHAR
** pType
,
1521 ok(0, "unexpected call\n");
1525 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1526 ISAXAttributes
* iface
,
1529 const WCHAR
* pLocalName
,
1531 const WCHAR
** pType
,
1534 ok(0, "unexpected call\n");
1538 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1539 ISAXAttributes
* iface
,
1540 const WCHAR
* pQName
,
1542 const WCHAR
** pType
,
1545 ok(0, "unexpected call\n");
1549 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1550 const WCHAR
**value
, int *nValue
)
1552 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1553 {'a','2','j','u','n','k',0},
1554 {'<','&','"','>',0}};
1555 static const int attrvalueslen
[] = {2, 2, 4};
1557 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1559 *value
= attrvaluesW
[index
];
1560 *nValue
= attrvalueslen
[index
];
1565 static HRESULT WINAPI
isaxattributes_getValueFromName(
1566 ISAXAttributes
* iface
,
1569 const WCHAR
* pLocalName
,
1571 const WCHAR
** pValue
,
1574 ok(0, "unexpected call\n");
1578 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1579 ISAXAttributes
* iface
,
1580 const WCHAR
* pQName
,
1582 const WCHAR
** pValue
,
1585 ok(0, "unexpected call\n");
1589 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1591 isaxattributes_QueryInterface
,
1592 isaxattributes_AddRef
,
1593 isaxattributes_Release
,
1594 isaxattributes_getLength
,
1595 isaxattributes_getURI
,
1596 isaxattributes_getLocalName
,
1597 isaxattributes_getQName
,
1598 isaxattributes_getName
,
1599 isaxattributes_getIndexFromName
,
1600 isaxattributes_getIndexFromQName
,
1601 isaxattributes_getType
,
1602 isaxattributes_getTypeFromName
,
1603 isaxattributes_getTypeFromQName
,
1604 isaxattributes_getValue
,
1605 isaxattributes_getValueFromName
,
1606 isaxattributes_getValueFromQName
1609 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1611 struct saxlexicalhandler
1613 ISAXLexicalHandler ISAXLexicalHandler_iface
;
1616 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1619 static inline struct saxlexicalhandler
*impl_from_ISAXLexicalHandler( ISAXLexicalHandler
*iface
)
1621 return CONTAINING_RECORD(iface
, struct saxlexicalhandler
, ISAXLexicalHandler_iface
);
1624 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **out
)
1626 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1630 if (IsEqualGUID(riid
, &IID_IUnknown
))
1633 ok(0, "got unexpected IID_IUnknown query\n");
1635 else if (IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1637 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1642 ISAXLexicalHandler_AddRef(iface
);
1644 return E_NOINTERFACE
;
1649 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1651 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1652 return InterlockedIncrement(&handler
->ref
);
1655 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1657 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1658 return InterlockedDecrement(&handler
->ref
);
1661 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1662 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1663 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1665 ok(0, "call not expected\n");
1669 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1671 ok(0, "call not expected\n");
1675 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1676 const WCHAR
* pName
, int nName
)
1678 ok(0, "call not expected\n");
1682 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1683 const WCHAR
* pName
, int nName
)
1685 ok(0, "call not expected\n");
1689 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1691 struct call_entry call
;
1693 init_call_entry(locator
, &call
);
1694 call
.id
= LH_STARTCDATA
;
1695 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1697 return get_expected_ret();
1700 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1702 struct call_entry call
;
1704 init_call_entry(locator
, &call
);
1705 call
.id
= LH_ENDCDATA
;
1706 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1708 return get_expected_ret();
1711 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1712 const WCHAR
* pChars
, int nChars
)
1714 ok(0, "call not expected\n");
1718 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1720 isaxlexical_QueryInterface
,
1722 isaxlexical_Release
,
1723 isaxlexical_startDTD
,
1725 isaxlexical_startEntity
,
1726 isaxlexical_endEntity
,
1727 isaxlexical_startCDATA
,
1728 isaxlexical_endCDATA
,
1732 static void init_saxlexicalhandler(struct saxlexicalhandler
*handler
, HRESULT hr
)
1734 handler
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1736 handler
->qi_hr
= hr
;
1739 struct saxdeclhandler
1741 ISAXDeclHandler ISAXDeclHandler_iface
;
1744 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1747 static inline struct saxdeclhandler
*impl_from_ISAXDeclHandler( ISAXDeclHandler
*iface
)
1749 return CONTAINING_RECORD(iface
, struct saxdeclhandler
, ISAXDeclHandler_iface
);
1752 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **out
)
1754 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1758 if (IsEqualGUID(riid
, &IID_IUnknown
))
1761 ok(0, "got unexpected IID_IUnknown query\n");
1763 else if (IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1765 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1770 ISAXDeclHandler_AddRef(iface
);
1772 return E_NOINTERFACE
;
1777 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1779 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1780 return InterlockedIncrement(&handler
->ref
);
1783 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1785 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1786 return InterlockedDecrement(&handler
->ref
);
1789 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1790 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1792 ok(0, "call not expected\n");
1796 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1797 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1798 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1799 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1801 ok(0, "call not expected\n");
1805 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1806 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1808 ok(0, "call not expected\n");
1812 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1813 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1814 const WCHAR
* pSystemId
, int nSystemId
)
1816 ok(0, "call not expected\n");
1820 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1822 isaxdecl_QueryInterface
,
1825 isaxdecl_elementDecl
,
1826 isaxdecl_attributeDecl
,
1827 isaxdecl_internalEntityDecl
,
1828 isaxdecl_externalEntityDecl
1831 static void init_saxdeclhandler(struct saxdeclhandler
*handler
, HRESULT hr
)
1833 handler
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1835 handler
->qi_hr
= hr
;
1838 typedef struct mxwriter_write_test_t
{
1844 } mxwriter_write_test
;
1846 typedef struct mxwriter_stream_test_t
{
1848 const char *encoding
;
1849 mxwriter_write_test expected_writes
[4];
1850 } mxwriter_stream_test
;
1852 static const mxwriter_write_test
*current_write_test
;
1853 static DWORD current_stream_test_index
;
1855 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1859 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1862 return E_NOINTERFACE
;
1867 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1872 static ULONG WINAPI
istream_Release(IStream
*iface
)
1877 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1879 ok(0, "unexpected call\n");
1883 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1887 ok(pv
!= NULL
, "pv == NULL\n");
1889 if(current_write_test
->last
) {
1890 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
1894 fail
= current_write_test
->fail_write
;
1896 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
1897 current_write_test
->cb
, cb
, current_stream_test_index
);
1900 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
1902 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
1904 ++current_write_test
;
1909 return fail
? E_FAIL
: S_OK
;
1912 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1913 ULARGE_INTEGER
*plibNewPosition
)
1915 ok(0, "unexpected call\n");
1919 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1921 ok(0, "unexpected call\n");
1925 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1926 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1928 ok(0, "unexpected call\n");
1932 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1934 ok(0, "unexpected call\n");
1938 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1940 ok(0, "unexpected call\n");
1944 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1945 ULARGE_INTEGER cb
, DWORD dwLockType
)
1947 ok(0, "unexpected call\n");
1951 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1952 ULARGE_INTEGER cb
, DWORD dwLockType
)
1954 ok(0, "unexpected call\n");
1958 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1960 ok(0, "unexpected call\n");
1964 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1966 ok(0, "unexpected call\n");
1970 static const IStreamVtbl StreamVtbl
= {
1971 istream_QueryInterface
,
1982 istream_UnlockRegion
,
1987 static IStream mxstream
= { &StreamVtbl
};
1989 static struct msxmlsupported_data_t reader_support_data
[] =
1991 { &CLSID_SAXXMLReader
, "SAXReader" },
1992 { &CLSID_SAXXMLReader30
, "SAXReader30" },
1993 { &CLSID_SAXXMLReader40
, "SAXReader40" },
1994 { &CLSID_SAXXMLReader60
, "SAXReader60" },
1998 static struct saxlexicalhandler lexicalhandler
;
1999 static struct saxdeclhandler declhandler
;
2001 static IStream
*create_test_stream(const char *data
, int len
)
2003 ULARGE_INTEGER size
;
2008 if (len
== -1) len
= strlen(data
);
2009 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2010 size
.QuadPart
= len
;
2011 IStream_SetSize(stream
, size
);
2012 IStream_Write(stream
, data
, len
, &written
);
2014 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2019 static void test_saxreader(void)
2021 const struct msxmlsupported_data_t
*table
= reader_support_data
;
2023 ISAXXMLReader
*reader
= NULL
;
2025 ISAXContentHandler
*content
;
2026 ISAXErrorHandler
*lpErrorHandler
;
2028 SAFEARRAYBOUND SADim
[1];
2033 static const CHAR testXmlA
[] = "test.xml";
2034 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2035 IXMLDOMDocument
*doc
;
2038 while (table
->clsid
)
2040 struct call_entry
*test_seq
;
2041 ISAXEntityResolver
*resolver
;
2044 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
2050 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2051 EXPECT_HR(hr
, S_OK
);
2054 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2056 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2061 /* crashes on old versions */
2062 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
2063 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2065 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
2066 EXPECT_HR(hr
, E_POINTER
);
2068 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
2069 EXPECT_HR(hr
, E_POINTER
);
2072 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2073 EXPECT_HR(hr
, S_OK
);
2074 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
2076 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
2077 EXPECT_HR(hr
, S_OK
);
2078 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
2080 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
2081 EXPECT_HR(hr
, S_OK
);
2083 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
2084 EXPECT_HR(hr
, S_OK
);
2086 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
2087 EXPECT_HR(hr
, S_OK
);
2089 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2090 EXPECT_HR(hr
, S_OK
);
2091 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
2093 V_VT(&var
) = VT_BSTR
;
2094 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
2096 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2097 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2098 test_seq
= content_handler_test1_alternate
;
2100 test_seq
= content_handler_test1
;
2101 set_expected_seq(test_seq
);
2102 hr
= ISAXXMLReader_parse(reader
, var
);
2103 EXPECT_HR(hr
, S_OK
);
2104 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
2108 SADim
[0].lLbound
= 0;
2109 SADim
[0].cElements
= sizeof(testXML
)-1;
2110 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
2111 SafeArrayAccessData(sa
, (void**)&ptr
);
2112 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
2113 SafeArrayUnaccessData(sa
);
2114 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
2117 set_expected_seq(test_seq
);
2118 hr
= ISAXXMLReader_parse(reader
, var
);
2119 EXPECT_HR(hr
, S_OK
);
2120 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from safe array", FALSE
);
2122 SafeArrayDestroy(sa
);
2124 stream
= create_test_stream(testXML
, -1);
2125 V_VT(&var
) = VT_UNKNOWN
;
2126 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2128 set_expected_seq(test_seq
);
2129 hr
= ISAXXMLReader_parse(reader
, var
);
2130 EXPECT_HR(hr
, S_OK
);
2131 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
2133 IStream_Release(stream
);
2135 stream
= create_test_stream(test_attributes
, -1);
2136 V_VT(&var
) = VT_UNKNOWN
;
2137 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2139 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2140 test_seq
= content_handler_test_attributes_alternate_4
;
2141 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2142 test_seq
= content_handler_test_attributes_alternate_6
;
2144 test_seq
= content_handler_test_attributes
;
2146 set_expected_seq(test_seq
);
2147 hr
= ISAXXMLReader_parse(reader
, var
);
2148 EXPECT_HR(hr
, S_OK
);
2150 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2151 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2152 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2154 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2156 IStream_Release(stream
);
2158 V_VT(&var
) = VT_BSTR
;
2159 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
2161 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2162 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2163 test_seq
= content_handler_test2_alternate
;
2165 test_seq
= content_handler_test2
;
2167 set_expected_seq(test_seq
);
2168 hr
= ISAXXMLReader_parse(reader
, var
);
2169 EXPECT_HR(hr
, S_OK
);
2170 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
2175 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2176 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2177 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
2180 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2181 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2182 test_seq
= content_handler_test1_alternate
;
2184 test_seq
= content_handler_test1
;
2185 set_expected_seq(test_seq
);
2186 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2187 EXPECT_HR(hr
, S_OK
);
2188 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
2191 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2192 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2193 test_seq
= content_handler_testerror_alternate
;
2195 test_seq
= content_handler_testerror
;
2196 set_expected_seq(test_seq
);
2197 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2198 EXPECT_HR(hr
, E_FAIL
);
2199 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
2201 /* callback ret values */
2202 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2203 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2205 test_seq
= content_handler_test_callback_rets_alt
;
2206 set_expected_seq(test_seq
);
2207 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2208 EXPECT_HR(hr
, S_OK
);
2212 test_seq
= content_handler_test_callback_rets
;
2213 set_expected_seq(test_seq
);
2214 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2215 EXPECT_HR(hr
, S_FALSE
);
2217 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
2219 DeleteFileA(testXmlA
);
2221 /* parse from IXMLDOMDocument */
2222 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
2223 &IID_IXMLDOMDocument
, (void**)&doc
);
2224 EXPECT_HR(hr
, S_OK
);
2226 str
= SysAllocString(szSimpleXML
);
2227 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
2228 EXPECT_HR(hr
, S_OK
);
2231 V_VT(&var
) = VT_UNKNOWN
;
2232 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
2234 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2235 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2236 test_seq
= content_handler_test2_alternate
;
2238 test_seq
= content_handler_test2
;
2240 set_expected_seq(test_seq
);
2241 hr
= ISAXXMLReader_parse(reader
, var
);
2242 EXPECT_HR(hr
, S_OK
);
2243 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
2244 IXMLDOMDocument_Release(doc
);
2246 /* xml:space test */
2247 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2248 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2250 test_seq
= xmlspaceattr_test_alternate
;
2253 test_seq
= xmlspaceattr_test
;
2255 set_expected_seq(test_seq
);
2256 V_VT(&var
) = VT_BSTR
;
2257 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
2258 hr
= ISAXXMLReader_parse(reader
, var
);
2259 EXPECT_HR(hr
, S_OK
);
2261 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2262 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2264 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
2267 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
2269 /* switch off 'namespaces' feature */
2270 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE
);
2271 EXPECT_HR(hr
, S_OK
);
2273 stream
= create_test_stream(test_attributes
, -1);
2274 V_VT(&var
) = VT_UNKNOWN
;
2275 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2277 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2278 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2280 test_seq
= content_handler_test_attributes_alt_no_ns
;
2283 test_seq
= content_handler_test_attributes
;
2285 set_expected_seq(test_seq
);
2286 hr
= ISAXXMLReader_parse(reader
, var
);
2287 EXPECT_HR(hr
, S_OK
);
2288 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2289 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_TRUE
);
2290 EXPECT_HR(hr
, S_OK
);
2292 /* switch off 'namespace-prefixes' feature */
2293 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_FALSE
);
2294 EXPECT_HR(hr
, S_OK
);
2296 stream
= create_test_stream(test_attributes
, -1);
2297 V_VT(&var
) = VT_UNKNOWN
;
2298 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2300 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2301 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2303 test_seq
= content_handler_test_attributes_alt_no_prefix
;
2306 test_seq
= content_handler_test_attributes_no_prefix
;
2308 set_expected_seq(test_seq
);
2309 hr
= ISAXXMLReader_parse(reader
, var
);
2310 EXPECT_HR(hr
, S_OK
);
2311 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2313 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_TRUE
);
2314 EXPECT_HR(hr
, S_OK
);
2316 /* attribute normalization */
2317 stream
= create_test_stream(attribute_normalize
, -1);
2318 V_VT(&var
) = VT_UNKNOWN
;
2319 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2321 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2322 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2324 test_seq
= attribute_norm_alt
;
2327 test_seq
= attribute_norm
;
2329 set_expected_seq(test_seq
);
2330 hr
= ISAXXMLReader_parse(reader
, var
);
2331 EXPECT_HR(hr
, S_OK
);
2332 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "attribute value normalization", TRUE
);
2334 resolver
= (void*)0xdeadbeef;
2335 hr
= ISAXXMLReader_getEntityResolver(reader
, &resolver
);
2336 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2337 ok(resolver
== NULL
, "got %p\n", resolver
);
2339 hr
= ISAXXMLReader_putEntityResolver(reader
, NULL
);
2340 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "got 0x%08x\n", hr
);
2342 /* CDATA sections */
2343 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2345 V_VT(&var
) = VT_UNKNOWN
;
2346 V_UNKNOWN(&var
) = (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
;
2347 hr
= ISAXXMLReader_putProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), var
);
2348 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2350 stream
= create_test_stream(test_cdata_xml
, -1);
2351 V_VT(&var
) = VT_UNKNOWN
;
2352 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2354 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2355 test_seq
= cdata_test_alt
;
2357 test_seq
= cdata_test
;
2359 set_expected_seq(test_seq
);
2360 hr
= ISAXXMLReader_parse(reader
, var
);
2361 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2362 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "cdata test", TRUE
);
2364 /* 2. CDATA sections */
2365 stream
= create_test_stream(test2_cdata_xml
, -1);
2366 V_VT(&var
) = VT_UNKNOWN
;
2367 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2369 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2370 test_seq
= cdata_test2_alt
;
2372 test_seq
= cdata_test2
;
2374 set_expected_seq(test_seq
);
2375 hr
= ISAXXMLReader_parse(reader
, var
);
2376 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2377 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "cdata test 2", TRUE
);
2379 IStream_Release(stream
);
2381 /* 3. CDATA sections */
2382 stream
= create_test_stream(test3_cdata_xml
, -1);
2383 V_VT(&var
) = VT_UNKNOWN
;
2384 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2386 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2387 test_seq
= cdata_test3_alt
;
2389 test_seq
= cdata_test3
;
2391 set_expected_seq(test_seq
);
2392 hr
= ISAXXMLReader_parse(reader
, var
);
2393 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2394 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "cdata test 3", TRUE
);
2396 IStream_Release(stream
);
2398 ISAXXMLReader_Release(reader
);
2405 struct saxreader_props_test_t
2407 const char *prop_name
;
2411 static const struct saxreader_props_test_t props_test_data
[] = {
2412 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
},
2413 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&declhandler
.ISAXDeclHandler_iface
},
2417 static void test_saxreader_properties(void)
2419 const struct saxreader_props_test_t
*ptr
= props_test_data
;
2420 ISAXXMLReader
*reader
;
2424 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2425 &IID_ISAXXMLReader
, (void**)&reader
);
2426 EXPECT_HR(hr
, S_OK
);
2428 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
2429 EXPECT_HR(hr
, E_POINTER
);
2431 while (ptr
->prop_name
)
2435 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2436 init_saxdeclhandler(&declhandler
, S_OK
);
2438 V_VT(&v
) = VT_EMPTY
;
2439 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2440 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2441 EXPECT_HR(hr
, S_OK
);
2442 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2443 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2445 V_VT(&v
) = VT_UNKNOWN
;
2446 V_UNKNOWN(&v
) = ptr
->iface
;
2447 ref
= get_refcount(ptr
->iface
);
2448 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2449 EXPECT_HR(hr
, S_OK
);
2450 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2452 V_VT(&v
) = VT_EMPTY
;
2453 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2455 ref
= get_refcount(ptr
->iface
);
2456 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2457 EXPECT_HR(hr
, S_OK
);
2458 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2459 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2460 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2463 V_VT(&v
) = VT_EMPTY
;
2464 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2465 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2466 EXPECT_HR(hr
, S_OK
);
2468 V_VT(&v
) = VT_EMPTY
;
2469 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2470 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2471 EXPECT_HR(hr
, S_OK
);
2472 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2473 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2475 V_VT(&v
) = VT_UNKNOWN
;
2476 V_UNKNOWN(&v
) = ptr
->iface
;
2477 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2478 EXPECT_HR(hr
, S_OK
);
2480 /* only VT_EMPTY seems to be valid to reset property */
2482 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2483 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2484 EXPECT_HR(hr
, E_INVALIDARG
);
2486 V_VT(&v
) = VT_EMPTY
;
2487 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2488 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2489 EXPECT_HR(hr
, S_OK
);
2490 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2491 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2494 V_VT(&v
) = VT_UNKNOWN
;
2495 V_UNKNOWN(&v
) = NULL
;
2496 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2497 EXPECT_HR(hr
, S_OK
);
2499 V_VT(&v
) = VT_EMPTY
;
2500 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2501 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2502 EXPECT_HR(hr
, S_OK
);
2503 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2504 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2506 /* block QueryInterface on handler riid */
2507 V_VT(&v
) = VT_UNKNOWN
;
2508 V_UNKNOWN(&v
) = ptr
->iface
;
2509 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2510 EXPECT_HR(hr
, S_OK
);
2512 init_saxlexicalhandler(&lexicalhandler
, E_NOINTERFACE
);
2513 init_saxdeclhandler(&declhandler
, E_NOINTERFACE
);
2515 V_VT(&v
) = VT_UNKNOWN
;
2516 V_UNKNOWN(&v
) = ptr
->iface
;
2517 EXPECT_REF(ptr
->iface
, 1);
2518 ref
= get_refcount(ptr
->iface
);
2519 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2520 EXPECT_HR(hr
, E_NOINTERFACE
);
2521 EXPECT_REF(ptr
->iface
, 1);
2523 V_VT(&v
) = VT_EMPTY
;
2524 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2525 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2526 EXPECT_HR(hr
, S_OK
);
2527 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2528 ok(V_UNKNOWN(&v
) != NULL
, "got %p\n", V_UNKNOWN(&v
));
2534 ISAXXMLReader_Release(reader
);
2536 if (!is_clsid_supported(&CLSID_SAXXMLReader40
, reader_support_data
))
2539 hr
= CoCreateInstance(&CLSID_SAXXMLReader40
, NULL
, CLSCTX_INPROC_SERVER
,
2540 &IID_ISAXXMLReader
, (void**)&reader
);
2541 EXPECT_HR(hr
, S_OK
);
2543 /* xmldecl-version property */
2544 V_VT(&v
) = VT_EMPTY
;
2545 V_BSTR(&v
) = (void*)0xdeadbeef;
2546 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2547 EXPECT_HR(hr
, S_OK
);
2548 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2549 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2551 /* stream without declaration */
2553 V_BSTR(&v
) = _bstr_("<element></element>");
2554 hr
= ISAXXMLReader_parse(reader
, v
);
2555 EXPECT_HR(hr
, S_OK
);
2557 V_VT(&v
) = VT_EMPTY
;
2558 V_BSTR(&v
) = (void*)0xdeadbeef;
2559 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2560 EXPECT_HR(hr
, S_OK
);
2561 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2562 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2564 /* stream with declaration */
2566 V_BSTR(&v
) = _bstr_("<?xml version=\"1.0\"?><element></element>");
2567 hr
= ISAXXMLReader_parse(reader
, v
);
2568 EXPECT_HR(hr
, S_OK
);
2570 V_VT(&v
) = VT_EMPTY
;
2571 V_BSTR(&v
) = (void*)0xdeadbeef;
2572 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2573 EXPECT_HR(hr
, S_OK
);
2574 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2575 ok(!lstrcmpW(V_BSTR(&v
), _bstr_("1.0")), "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2578 ISAXXMLReader_Release(reader
);
2582 struct feature_ns_entry_t
{
2586 VARIANT_BOOL value2
; /* feature value after feature set to 0xc */
2589 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2590 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
, VARIANT_FALSE
},
2591 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
, VARIANT_FALSE
},
2592 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
, VARIANT_TRUE
},
2593 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
, VARIANT_TRUE
},
2597 static const char *feature_names
[] = {
2598 "http://xml.org/sax/features/namespaces",
2599 "http://xml.org/sax/features/namespace-prefixes",
2603 static void test_saxreader_features(void)
2605 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2606 ISAXXMLReader
*reader
;
2614 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2617 win_skip("can't create %s instance\n", entry
->clsid
);
2622 name
= feature_names
;
2626 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2627 EXPECT_HR(hr
, S_OK
);
2628 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2631 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), value
);
2632 EXPECT_HR(hr
, S_OK
);
2635 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2636 EXPECT_HR(hr
, S_OK
);
2637 ok(entry
->value2
== value
, "%s: got wrong value %x, expected %x\n", entry
->clsid
, value
, entry
->value2
);
2639 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_FALSE
);
2640 EXPECT_HR(hr
, S_OK
);
2642 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2643 EXPECT_HR(hr
, S_OK
);
2644 ok(value
== VARIANT_FALSE
, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry
->clsid
, value
);
2646 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_TRUE
);
2647 EXPECT_HR(hr
, S_OK
);
2649 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2650 EXPECT_HR(hr
, S_OK
);
2651 ok(value
== VARIANT_TRUE
, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry
->clsid
, value
);
2656 ISAXXMLReader_Release(reader
);
2662 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2663 static const CHAR UTF8BOMTest
[] =
2664 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2667 struct enc_test_entry_t
{
2675 static const struct enc_test_entry_t encoding_test_data
[] = {
2676 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, 1 },
2677 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, 1 },
2678 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, 0 },
2679 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, 0 },
2683 static void test_saxreader_encoding(void)
2685 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2686 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2687 static const CHAR testXmlA
[] = "test.xml";
2691 ISAXXMLReader
*reader
;
2697 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2700 win_skip("can't create %s instance\n", entry
->clsid
);
2705 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2706 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2707 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2710 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2712 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2714 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2716 DeleteFileA(testXmlA
);
2718 /* try BSTR input with no BOM or '<?xml' instruction */
2719 V_VT(&input
) = VT_BSTR
;
2720 V_BSTR(&input
) = _bstr_("<element></element>");
2721 hr
= ISAXXMLReader_parse(reader
, input
);
2722 EXPECT_HR(hr
, S_OK
);
2724 ISAXXMLReader_Release(reader
);
2731 static void test_mxwriter_handlers(void)
2733 ISAXContentHandler
*handler
;
2734 IMXWriter
*writer
, *writer2
;
2735 ISAXDeclHandler
*decl
;
2736 ISAXLexicalHandler
*lh
;
2739 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2740 &IID_IMXWriter
, (void**)&writer
);
2741 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2743 EXPECT_REF(writer
, 1);
2745 /* ISAXContentHandler */
2746 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&handler
);
2747 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2748 EXPECT_REF(writer
, 2);
2749 EXPECT_REF(handler
, 2);
2751 hr
= ISAXContentHandler_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2752 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2753 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2754 EXPECT_REF(writer
, 3);
2755 EXPECT_REF(writer2
, 3);
2756 IMXWriter_Release(writer2
);
2757 ISAXContentHandler_Release(handler
);
2759 /* ISAXLexicalHandler */
2760 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lh
);
2761 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2762 EXPECT_REF(writer
, 2);
2765 hr
= ISAXLexicalHandler_QueryInterface(lh
, &IID_IMXWriter
, (void**)&writer2
);
2766 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2767 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2768 EXPECT_REF(writer
, 3);
2769 EXPECT_REF(writer2
, 3);
2770 IMXWriter_Release(writer2
);
2771 ISAXLexicalHandler_Release(lh
);
2773 /* ISAXDeclHandler */
2774 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
2775 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2776 EXPECT_REF(writer
, 2);
2779 hr
= ISAXDeclHandler_QueryInterface(decl
, &IID_IMXWriter
, (void**)&writer2
);
2780 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2781 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2782 EXPECT_REF(writer
, 3);
2783 EXPECT_REF(writer2
, 3);
2784 IMXWriter_Release(writer2
);
2785 ISAXDeclHandler_Release(decl
);
2787 IMXWriter_Release(writer
);
2791 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2793 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2794 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2795 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2796 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2800 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2802 { &CLSID_SAXAttributes
, "SAXAttributes" },
2803 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2804 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2805 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2809 struct mxwriter_props_t
2813 VARIANT_BOOL disable_escape
;
2814 VARIANT_BOOL indent
;
2815 VARIANT_BOOL omitdecl
;
2816 VARIANT_BOOL standalone
;
2817 const char *encoding
;
2820 static const struct mxwriter_props_t mxwriter_default_props
[] =
2822 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2823 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2824 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2825 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2829 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2833 while (table
->clsid
)
2840 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2847 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2848 &IID_IMXWriter
, (void**)&writer
);
2849 EXPECT_HR(hr
, S_OK
);
2852 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
2853 EXPECT_HR(hr
, S_OK
);
2854 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
2856 b
= !table
->disable_escape
;
2857 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
2858 EXPECT_HR(hr
, S_OK
);
2859 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
2860 table
->disable_escape
);
2863 hr
= IMXWriter_get_indent(writer
, &b
);
2864 EXPECT_HR(hr
, S_OK
);
2865 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
2867 b
= !table
->omitdecl
;
2868 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
2869 EXPECT_HR(hr
, S_OK
);
2870 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
2872 b
= !table
->standalone
;
2873 hr
= IMXWriter_get_standalone(writer
, &b
);
2874 EXPECT_HR(hr
, S_OK
);
2875 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
2877 hr
= IMXWriter_get_encoding(writer
, &encoding
);
2878 EXPECT_HR(hr
, S_OK
);
2879 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
2880 i
, wine_dbgstr_w(encoding
), table
->encoding
);
2881 SysFreeString(encoding
);
2883 IMXWriter_Release(writer
);
2890 static void test_mxwriter_properties(void)
2892 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
2893 static const WCHAR emptyW
[] = {0};
2894 static const WCHAR testW
[] = {'t','e','s','t',0};
2895 ISAXContentHandler
*content
;
2902 test_mxwriter_default_properties(mxwriter_default_props
);
2904 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2905 &IID_IMXWriter
, (void**)&writer
);
2906 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2908 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
2909 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2911 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
2912 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2914 hr
= IMXWriter_get_indent(writer
, NULL
);
2915 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2917 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
2918 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2920 hr
= IMXWriter_get_standalone(writer
, NULL
);
2921 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2924 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
2925 ok(hr
== S_OK
, "got %08x\n", hr
);
2928 hr
= IMXWriter_get_standalone(writer
, &b
);
2929 ok(hr
== S_OK
, "got %08x\n", hr
);
2930 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
2932 hr
= IMXWriter_get_encoding(writer
, NULL
);
2933 EXPECT_HR(hr
, E_POINTER
);
2935 /* UTF-16 is a default setting apparently */
2936 str
= (void*)0xdeadbeef;
2937 hr
= IMXWriter_get_encoding(writer
, &str
);
2938 EXPECT_HR(hr
, S_OK
);
2939 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
2941 str2
= (void*)0xdeadbeef;
2942 hr
= IMXWriter_get_encoding(writer
, &str2
);
2943 ok(hr
== S_OK
, "got %08x\n", hr
);
2944 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
2946 SysFreeString(str2
);
2949 /* put empty string */
2950 str
= SysAllocString(emptyW
);
2951 hr
= IMXWriter_put_encoding(writer
, str
);
2952 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2955 str
= (void*)0xdeadbeef;
2956 hr
= IMXWriter_get_encoding(writer
, &str
);
2957 EXPECT_HR(hr
, S_OK
);
2958 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
2961 /* invalid encoding name */
2962 str
= SysAllocString(testW
);
2963 hr
= IMXWriter_put_encoding(writer
, str
);
2964 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2967 /* test case sensivity */
2968 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
2969 EXPECT_HR(hr
, S_OK
);
2970 str
= (void*)0xdeadbeef;
2971 hr
= IMXWriter_get_encoding(writer
, &str
);
2972 EXPECT_HR(hr
, S_OK
);
2973 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
2976 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
2977 EXPECT_HR(hr
, S_OK
);
2978 str
= (void*)0xdeadbeef;
2979 hr
= IMXWriter_get_encoding(writer
, &str
);
2980 EXPECT_HR(hr
, S_OK
);
2981 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
2984 /* how it affects document creation */
2985 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2986 EXPECT_HR(hr
, S_OK
);
2988 hr
= ISAXContentHandler_startDocument(content
);
2989 EXPECT_HR(hr
, S_OK
);
2990 hr
= ISAXContentHandler_endDocument(content
);
2991 EXPECT_HR(hr
, S_OK
);
2993 V_VT(&dest
) = VT_EMPTY
;
2994 hr
= IMXWriter_get_output(writer
, &dest
);
2995 EXPECT_HR(hr
, S_OK
);
2996 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2997 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
2998 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2999 VariantClear(&dest
);
3000 ISAXContentHandler_Release(content
);
3002 hr
= IMXWriter_get_version(writer
, NULL
);
3003 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3004 /* default version is 'surprisingly' 1.0 */
3005 hr
= IMXWriter_get_version(writer
, &str
);
3006 ok(hr
== S_OK
, "got %08x\n", hr
);
3007 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
3010 /* store version string as is */
3011 hr
= IMXWriter_put_version(writer
, NULL
);
3012 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3014 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
3015 ok(hr
== S_OK
, "got %08x\n", hr
);
3017 hr
= IMXWriter_put_version(writer
, _bstr_(""));
3018 ok(hr
== S_OK
, "got %08x\n", hr
);
3019 hr
= IMXWriter_get_version(writer
, &str
);
3020 ok(hr
== S_OK
, "got %08x\n", hr
);
3021 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
3024 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
3025 ok(hr
== S_OK
, "got %08x\n", hr
);
3026 hr
= IMXWriter_get_version(writer
, &str
);
3027 ok(hr
== S_OK
, "got %08x\n", hr
);
3028 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
3031 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
3032 ok(hr
== S_OK
, "got %08x\n", hr
);
3033 hr
= IMXWriter_get_version(writer
, &str
);
3034 ok(hr
== S_OK
, "got %08x\n", hr
);
3035 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
3038 IMXWriter_Release(writer
);
3042 static void test_mxwriter_flush(void)
3044 static const WCHAR emptyW
[] = {0};
3045 ISAXContentHandler
*content
;
3048 ULARGE_INTEGER pos2
;
3056 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3057 &IID_IMXWriter
, (void**)&writer
);
3058 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3060 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3061 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3062 EXPECT_REF(stream
, 1);
3064 /* detach when nothing was attached */
3065 V_VT(&dest
) = VT_EMPTY
;
3066 hr
= IMXWriter_put_output(writer
, dest
);
3067 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3070 V_VT(&dest
) = VT_UNKNOWN
;
3071 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3072 hr
= IMXWriter_put_output(writer
, dest
);
3073 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3074 todo_wine
EXPECT_REF(stream
, 3);
3076 /* detach setting VT_EMPTY destination */
3077 V_VT(&dest
) = VT_EMPTY
;
3078 hr
= IMXWriter_put_output(writer
, dest
);
3079 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3080 EXPECT_REF(stream
, 1);
3082 V_VT(&dest
) = VT_UNKNOWN
;
3083 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3084 hr
= IMXWriter_put_output(writer
, dest
);
3085 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3087 /* flush() doesn't detach a stream */
3088 hr
= IMXWriter_flush(writer
);
3089 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3090 todo_wine
EXPECT_REF(stream
, 3);
3093 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3094 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3095 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3097 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3098 ok(hr
== S_OK
, "got %08x\n", hr
);
3100 hr
= ISAXContentHandler_startDocument(content
);
3101 ok(hr
== S_OK
, "got %08x\n", hr
);
3104 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3105 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3106 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
3108 /* already started */
3109 hr
= ISAXContentHandler_startDocument(content
);
3110 ok(hr
== S_OK
, "got %08x\n", hr
);
3112 hr
= ISAXContentHandler_endDocument(content
);
3113 ok(hr
== S_OK
, "got %08x\n", hr
);
3115 /* flushed on endDocument() */
3117 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3118 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3119 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
3121 IStream_Release(stream
);
3123 /* auto-flush feature */
3124 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3125 EXPECT_HR(hr
, S_OK
);
3126 EXPECT_REF(stream
, 1);
3128 V_VT(&dest
) = VT_UNKNOWN
;
3129 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3130 hr
= IMXWriter_put_output(writer
, dest
);
3131 EXPECT_HR(hr
, S_OK
);
3133 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_FALSE
);
3134 EXPECT_HR(hr
, S_OK
);
3136 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3137 EXPECT_HR(hr
, S_OK
);
3139 hr
= ISAXContentHandler_startDocument(content
);
3140 EXPECT_HR(hr
, S_OK
);
3142 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3143 EXPECT_HR(hr
, S_OK
);
3145 /* internal buffer is flushed automatically on certain threshold */
3148 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3149 EXPECT_HR(hr
, S_OK
);
3150 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3153 buff
= HeapAlloc(GetProcessHeap(), 0, len
);
3154 memset(buff
, 'A', len
);
3155 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3156 EXPECT_HR(hr
, S_OK
);
3160 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3161 EXPECT_HR(hr
, S_OK
);
3163 ok(pos2
.QuadPart
!= 0, "unexpected stream beginning\n");
3165 hr
= IMXWriter_get_output(writer
, NULL
);
3166 EXPECT_HR(hr
, E_POINTER
);
3168 ref
= get_refcount(stream
);
3169 V_VT(&dest
) = VT_EMPTY
;
3170 hr
= IMXWriter_get_output(writer
, &dest
);
3171 EXPECT_HR(hr
, S_OK
);
3172 ok(V_VT(&dest
) == VT_UNKNOWN
, "got vt type %d\n", V_VT(&dest
));
3173 ok(V_UNKNOWN(&dest
) == (IUnknown
*)stream
, "got pointer %p\n", V_UNKNOWN(&dest
));
3174 ok(ref
+1 == get_refcount(stream
), "expected increased refcount\n");
3175 VariantClear(&dest
);
3177 hr
= ISAXContentHandler_endDocument(content
);
3178 EXPECT_HR(hr
, S_OK
);
3180 IStream_Release(stream
);
3182 /* test char count lower than threshold */
3183 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3184 EXPECT_HR(hr
, S_OK
);
3185 EXPECT_REF(stream
, 1);
3187 hr
= ISAXContentHandler_startDocument(content
);
3188 EXPECT_HR(hr
, S_OK
);
3190 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3191 EXPECT_HR(hr
, S_OK
);
3195 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3196 EXPECT_HR(hr
, S_OK
);
3197 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3199 memset(buff
, 'A', len
);
3200 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
- 8);
3201 EXPECT_HR(hr
, S_OK
);
3205 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3206 EXPECT_HR(hr
, S_OK
);
3207 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
3209 hr
= ISAXContentHandler_endDocument(content
);
3210 EXPECT_HR(hr
, S_OK
);
3212 /* test auto-flush function when stream is not set */
3213 V_VT(&dest
) = VT_EMPTY
;
3214 hr
= IMXWriter_put_output(writer
, dest
);
3215 EXPECT_HR(hr
, S_OK
);
3217 hr
= ISAXContentHandler_startDocument(content
);
3218 EXPECT_HR(hr
, S_OK
);
3220 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
3221 EXPECT_HR(hr
, S_OK
);
3223 memset(buff
, 'A', len
);
3224 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
3225 EXPECT_HR(hr
, S_OK
);
3227 V_VT(&dest
) = VT_EMPTY
;
3228 hr
= IMXWriter_get_output(writer
, &dest
);
3229 EXPECT_HR(hr
, S_OK
);
3230 len
+= strlen("<a>");
3231 ok(SysStringLen(V_BSTR(&dest
)) == len
, "got len=%d, expected %d\n", SysStringLen(V_BSTR(&dest
)), len
);
3232 VariantClear(&dest
);
3234 HeapFree(GetProcessHeap(), 0, buff
);
3235 ISAXContentHandler_Release(content
);
3236 IStream_Release(stream
);
3237 IMXWriter_Release(writer
);
3241 static void test_mxwriter_startenddocument(void)
3243 ISAXContentHandler
*content
;
3248 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3249 &IID_IMXWriter
, (void**)&writer
);
3250 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3252 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3253 ok(hr
== S_OK
, "got %08x\n", hr
);
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 V_VT(&dest
) = VT_EMPTY
;
3262 hr
= IMXWriter_get_output(writer
, &dest
);
3263 ok(hr
== S_OK
, "got %08x\n", hr
);
3264 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3265 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3266 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3267 VariantClear(&dest
);
3269 /* now try another startDocument */
3270 hr
= ISAXContentHandler_startDocument(content
);
3271 ok(hr
== S_OK
, "got %08x\n", hr
);
3272 /* and get duplicated prolog */
3273 V_VT(&dest
) = VT_EMPTY
;
3274 hr
= IMXWriter_get_output(writer
, &dest
);
3275 ok(hr
== S_OK
, "got %08x\n", hr
);
3276 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3277 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
3278 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3279 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3280 VariantClear(&dest
);
3282 ISAXContentHandler_Release(content
);
3283 IMXWriter_Release(writer
);
3285 /* now with omitted declaration */
3286 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3287 &IID_IMXWriter
, (void**)&writer
);
3288 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3290 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3291 ok(hr
== S_OK
, "got %08x\n", hr
);
3293 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3294 ok(hr
== S_OK
, "got %08x\n", hr
);
3296 hr
= ISAXContentHandler_startDocument(content
);
3297 ok(hr
== S_OK
, "got %08x\n", hr
);
3299 hr
= ISAXContentHandler_endDocument(content
);
3300 ok(hr
== S_OK
, "got %08x\n", hr
);
3302 V_VT(&dest
) = VT_EMPTY
;
3303 hr
= IMXWriter_get_output(writer
, &dest
);
3304 ok(hr
== S_OK
, "got %08x\n", hr
);
3305 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3306 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3307 VariantClear(&dest
);
3309 ISAXContentHandler_Release(content
);
3310 IMXWriter_Release(writer
);
3317 StartElement
= 0x001,
3319 StartEndElement
= 0x011,
3320 DisableEscaping
= 0x100
3323 struct writer_startendelement_t
{
3325 enum startendtype type
;
3327 const char *local_name
;
3331 ISAXAttributes
*attr
;
3334 static const char startelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\">";
3335 static const char startendelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\"/>";
3336 static const char startendelement_noescape_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&\">\"/>";
3338 static const struct writer_startendelement_t writer_startendelement
[] = {
3340 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3341 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3342 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3343 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
3344 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3346 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3347 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3348 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
3349 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3350 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3352 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3353 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
3354 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3355 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3356 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3358 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
3359 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3360 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3361 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3362 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3364 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3365 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3366 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3367 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
3368 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3370 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3371 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3372 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3373 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3374 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3376 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3377 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3378 /* endElement tests */
3379 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3380 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3381 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3383 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
3384 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3385 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3386 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3387 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
3389 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3390 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3391 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3392 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
3393 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3395 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3396 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3397 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
3398 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3399 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3401 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3402 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3403 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3404 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3405 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3407 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
3408 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3409 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3410 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3411 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3413 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3414 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3415 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3416 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3418 /* with attributes */
3419 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3421 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3422 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3423 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3424 /* empty elements */
3425 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3426 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3428 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3429 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3430 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
3431 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
3432 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
3434 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
3436 /* with disabled output escaping */
3437 { &CLSID_MXXMLWriter
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3438 { &CLSID_MXXMLWriter30
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3439 { &CLSID_MXXMLWriter40
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3440 { &CLSID_MXXMLWriter60
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3445 static void get_class_support_data(struct msxmlsupported_data_t
*table
, REFIID riid
)
3447 while (table
->clsid
)
3452 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, riid
, (void**)&unk
);
3453 if (hr
== S_OK
) IUnknown_Release(unk
);
3455 table
->supported
= hr
== S_OK
;
3456 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
3462 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
3466 while (table
->clsid
)
3468 ISAXContentHandler
*content
;
3472 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3479 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3480 &IID_IMXWriter
, (void**)&writer
);
3481 EXPECT_HR(hr
, S_OK
);
3483 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3484 EXPECT_HR(hr
, S_OK
);
3486 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3487 EXPECT_HR(hr
, S_OK
);
3489 hr
= ISAXContentHandler_startDocument(content
);
3490 EXPECT_HR(hr
, S_OK
);
3492 if (table
->type
& DisableEscaping
)
3494 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3495 EXPECT_HR(hr
, S_OK
);
3498 if (table
->type
& StartElement
)
3500 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3501 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
), table
->attr
);
3502 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3505 if (table
->type
& EndElement
)
3507 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3508 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
));
3509 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3517 V_VT(&dest
) = VT_EMPTY
;
3518 hr
= IMXWriter_get_output(writer
, &dest
);
3519 EXPECT_HR(hr
, S_OK
);
3520 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3521 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3522 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3523 VariantClear(&dest
);
3526 ISAXContentHandler_Release(content
);
3527 IMXWriter_Release(writer
);
3536 /* point of these test is to start/end element with different names and name lengths */
3537 struct writer_startendelement2_t
{
3539 const char *qnamestart
;
3541 const char *qnameend
;
3547 static const struct writer_startendelement2_t writer_startendelement2
[] = {
3548 { &CLSID_MXXMLWriter
, "a", -1, "b", -1, "<a/>", S_OK
},
3549 { &CLSID_MXXMLWriter30
, "a", -1, "b", -1, "<a/>", S_OK
},
3550 { &CLSID_MXXMLWriter40
, "a", -1, "b", -1, "<a/>", S_OK
},
3551 /* -1 length is not allowed for version 6 */
3552 { &CLSID_MXXMLWriter60
, "a", -1, "b", -1, "<a/>", E_INVALIDARG
},
3554 { &CLSID_MXXMLWriter
, "a", 1, "b", 1, "<a/>", S_OK
},
3555 { &CLSID_MXXMLWriter30
, "a", 1, "b", 1, "<a/>", S_OK
},
3556 { &CLSID_MXXMLWriter40
, "a", 1, "b", 1, "<a/>", S_OK
},
3557 { &CLSID_MXXMLWriter60
, "a", 1, "b", 1, "<a/>", S_OK
},
3561 static void test_mxwriter_startendelement_batch2(const struct writer_startendelement2_t
*table
)
3565 while (table
->clsid
)
3567 ISAXContentHandler
*content
;
3571 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3578 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3579 &IID_IMXWriter
, (void**)&writer
);
3580 EXPECT_HR(hr
, S_OK
);
3582 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3583 EXPECT_HR(hr
, S_OK
);
3585 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3586 EXPECT_HR(hr
, S_OK
);
3588 hr
= ISAXContentHandler_startDocument(content
);
3589 EXPECT_HR(hr
, S_OK
);
3591 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3592 _bstr_(table
->qnamestart
), table
->qnamestart_len
, NULL
);
3593 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3595 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3596 _bstr_(table
->qnameend
), table
->qnameend_len
);
3597 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3604 V_VT(&dest
) = VT_EMPTY
;
3605 hr
= IMXWriter_get_output(writer
, &dest
);
3606 EXPECT_HR(hr
, S_OK
);
3607 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3608 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3609 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3610 VariantClear(&dest
);
3613 ISAXContentHandler_Release(content
);
3614 IMXWriter_Release(writer
);
3624 static void test_mxwriter_startendelement(void)
3626 ISAXContentHandler
*content
;
3631 test_mxwriter_startendelement_batch(writer_startendelement
);
3632 test_mxwriter_startendelement_batch2(writer_startendelement2
);
3634 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3635 &IID_IMXWriter
, (void**)&writer
);
3636 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3638 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3639 ok(hr
== S_OK
, "got %08x\n", hr
);
3641 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3642 ok(hr
== S_OK
, "got %08x\n", hr
);
3644 hr
= ISAXContentHandler_startDocument(content
);
3645 ok(hr
== S_OK
, "got %08x\n", hr
);
3647 /* all string pointers should be not null */
3648 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
3649 ok(hr
== S_OK
, "got %08x\n", hr
);
3651 V_VT(&dest
) = VT_EMPTY
;
3652 hr
= IMXWriter_get_output(writer
, &dest
);
3653 ok(hr
== S_OK
, "got %08x\n", hr
);
3654 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3655 ok(!lstrcmpW(_bstr_("<>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3656 VariantClear(&dest
);
3658 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
3659 ok(hr
== S_OK
, "got %08x\n", hr
);
3661 V_VT(&dest
) = VT_EMPTY
;
3662 hr
= IMXWriter_get_output(writer
, &dest
);
3663 ok(hr
== S_OK
, "got %08x\n", hr
);
3664 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3665 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3666 VariantClear(&dest
);
3668 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
3669 EXPECT_HR(hr
, E_INVALIDARG
);
3671 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
3672 EXPECT_HR(hr
, E_INVALIDARG
);
3674 /* only local name is an error too */
3675 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
3676 EXPECT_HR(hr
, E_INVALIDARG
);
3678 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
3679 EXPECT_HR(hr
, S_OK
);
3681 V_VT(&dest
) = VT_EMPTY
;
3682 hr
= IMXWriter_get_output(writer
, &dest
);
3683 EXPECT_HR(hr
, S_OK
);
3684 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3685 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3686 VariantClear(&dest
);
3688 hr
= ISAXContentHandler_endDocument(content
);
3689 EXPECT_HR(hr
, S_OK
);
3691 V_VT(&dest
) = VT_EMPTY
;
3692 hr
= IMXWriter_put_output(writer
, dest
);
3693 EXPECT_HR(hr
, S_OK
);
3695 V_VT(&dest
) = VT_EMPTY
;
3696 hr
= IMXWriter_get_output(writer
, &dest
);
3697 EXPECT_HR(hr
, S_OK
);
3698 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3699 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3700 VariantClear(&dest
);
3702 hr
= ISAXContentHandler_startDocument(content
);
3703 EXPECT_HR(hr
, S_OK
);
3705 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
3706 EXPECT_HR(hr
, S_OK
);
3708 V_VT(&dest
) = VT_EMPTY
;
3709 hr
= IMXWriter_get_output(writer
, &dest
);
3710 EXPECT_HR(hr
, S_OK
);
3711 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3712 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3713 VariantClear(&dest
);
3715 ISAXContentHandler_endDocument(content
);
3716 IMXWriter_flush(writer
);
3718 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
3719 EXPECT_HR(hr
, S_OK
);
3720 V_VT(&dest
) = VT_EMPTY
;
3721 hr
= IMXWriter_get_output(writer
, &dest
);
3722 EXPECT_HR(hr
, S_OK
);
3723 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3724 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3725 VariantClear(&dest
);
3727 V_VT(&dest
) = VT_EMPTY
;
3728 hr
= IMXWriter_put_output(writer
, dest
);
3729 EXPECT_HR(hr
, S_OK
);
3732 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), -1, NULL
);
3733 EXPECT_HR(hr
, S_OK
);
3734 V_VT(&dest
) = VT_EMPTY
;
3735 hr
= IMXWriter_get_output(writer
, &dest
);
3736 EXPECT_HR(hr
, S_OK
);
3737 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3738 ok(!lstrcmpW(_bstr_("<a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3739 VariantClear(&dest
);
3741 ISAXContentHandler_Release(content
);
3742 IMXWriter_Release(writer
);
3746 struct writer_characters_t
{
3752 static const struct writer_characters_t writer_characters
[] = {
3753 { &CLSID_MXXMLWriter
, "< > & \"", "< > & \"" },
3754 { &CLSID_MXXMLWriter30
, "< > & \"", "< > & \"" },
3755 { &CLSID_MXXMLWriter40
, "< > & \"", "< > & \"" },
3756 { &CLSID_MXXMLWriter60
, "< > & \"", "< > & \"" },
3760 static void test_mxwriter_characters(void)
3762 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
3763 const struct writer_characters_t
*table
= writer_characters
;
3764 ISAXContentHandler
*content
;
3770 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3771 &IID_IMXWriter
, (void**)&writer
);
3772 EXPECT_HR(hr
, S_OK
);
3774 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3775 EXPECT_HR(hr
, S_OK
);
3777 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3778 EXPECT_HR(hr
, S_OK
);
3780 hr
= ISAXContentHandler_startDocument(content
);
3781 EXPECT_HR(hr
, S_OK
);
3783 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
3784 EXPECT_HR(hr
, E_INVALIDARG
);
3786 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3787 EXPECT_HR(hr
, S_OK
);
3789 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
3790 EXPECT_HR(hr
, S_OK
);
3792 V_VT(&dest
) = VT_EMPTY
;
3793 hr
= IMXWriter_get_output(writer
, &dest
);
3794 EXPECT_HR(hr
, S_OK
);
3795 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3796 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3797 VariantClear(&dest
);
3799 hr
= ISAXContentHandler_endDocument(content
);
3800 EXPECT_HR(hr
, S_OK
);
3802 ISAXContentHandler_Release(content
);
3803 IMXWriter_Release(writer
);
3805 /* try empty characters data to see if element is closed */
3806 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3807 &IID_IMXWriter
, (void**)&writer
);
3808 EXPECT_HR(hr
, S_OK
);
3810 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3811 EXPECT_HR(hr
, S_OK
);
3813 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3814 EXPECT_HR(hr
, S_OK
);
3816 hr
= ISAXContentHandler_startDocument(content
);
3817 EXPECT_HR(hr
, S_OK
);
3819 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3820 EXPECT_HR(hr
, S_OK
);
3822 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3823 EXPECT_HR(hr
, S_OK
);
3825 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3826 EXPECT_HR(hr
, S_OK
);
3828 V_VT(&dest
) = VT_EMPTY
;
3829 hr
= IMXWriter_get_output(writer
, &dest
);
3830 EXPECT_HR(hr
, S_OK
);
3831 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3832 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3833 VariantClear(&dest
);
3835 ISAXContentHandler_Release(content
);
3836 IMXWriter_Release(writer
);
3839 while (table
->clsid
)
3841 ISAXContentHandler
*content
;
3846 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3853 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3854 &IID_IMXWriter
, (void**)&writer
);
3855 EXPECT_HR(hr
, S_OK
);
3857 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3858 EXPECT_HR(hr
, S_OK
);
3860 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3861 EXPECT_HR(hr
, S_OK
);
3863 hr
= ISAXContentHandler_startDocument(content
);
3864 EXPECT_HR(hr
, S_OK
);
3866 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
3867 EXPECT_HR(hr
, S_OK
);
3872 V_VT(&dest
) = VT_EMPTY
;
3873 hr
= IMXWriter_get_output(writer
, &dest
);
3874 EXPECT_HR(hr
, S_OK
);
3875 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3876 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3877 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3878 VariantClear(&dest
);
3881 /* with disabled escaping */
3882 V_VT(&dest
) = VT_EMPTY
;
3883 hr
= IMXWriter_put_output(writer
, dest
);
3884 EXPECT_HR(hr
, S_OK
);
3886 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3887 EXPECT_HR(hr
, S_OK
);
3889 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
3890 EXPECT_HR(hr
, S_OK
);
3895 V_VT(&dest
) = VT_EMPTY
;
3896 hr
= IMXWriter_get_output(writer
, &dest
);
3897 EXPECT_HR(hr
, S_OK
);
3898 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3899 ok(!lstrcmpW(_bstr_(table
->data
), V_BSTR(&dest
)),
3900 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->data
);
3901 VariantClear(&dest
);
3904 ISAXContentHandler_Release(content
);
3905 IMXWriter_Release(writer
);
3914 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
3916 VARIANT_TRUE
,"UTF-16",
3918 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3919 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3924 VARIANT_FALSE
,"UTF-16",
3926 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3931 VARIANT_TRUE
,"UTF-8",
3933 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
3934 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3935 * and the writer is released.
3942 VARIANT_TRUE
,"utf-8",
3944 {FALSE
,(const BYTE
*)utf8xml2
,sizeof(utf8xml2
)-1},
3945 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3946 * and the writer is released.
3953 VARIANT_TRUE
,"UTF-16",
3955 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3956 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3961 VARIANT_TRUE
,"UTF-16",
3963 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
3964 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3970 static void test_mxwriter_stream(void)
3973 ISAXContentHandler
*content
;
3978 ULARGE_INTEGER pos2
;
3979 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
3981 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
3982 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
3984 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3985 &IID_IMXWriter
, (void**)&writer
);
3986 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
3988 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3989 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
3991 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
3992 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
3994 V_VT(&dest
) = VT_UNKNOWN
;
3995 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
3996 hr
= IMXWriter_put_output(writer
, dest
);
3997 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
3998 VariantClear(&dest
);
4000 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
4001 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
4003 current_write_test
= test
->expected_writes
;
4005 hr
= ISAXContentHandler_startDocument(content
);
4006 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4008 hr
= ISAXContentHandler_endDocument(content
);
4009 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
4011 ISAXContentHandler_Release(content
);
4012 IMXWriter_Release(writer
);
4014 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
4015 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
4018 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4019 &IID_IMXWriter
, (void**)&writer
);
4020 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
4022 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4023 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
4025 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4026 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
4028 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4029 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
4031 V_VT(&dest
) = VT_UNKNOWN
;
4032 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4033 hr
= IMXWriter_put_output(writer
, dest
);
4034 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4036 hr
= ISAXContentHandler_startDocument(content
);
4037 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4039 /* Setting output of the mxwriter causes the current output to be flushed,
4040 * and the writer to start over.
4042 V_VT(&dest
) = VT_EMPTY
;
4043 hr
= IMXWriter_put_output(writer
, dest
);
4044 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
4047 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4048 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
4049 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
4051 hr
= ISAXContentHandler_startDocument(content
);
4052 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
4054 hr
= ISAXContentHandler_endDocument(content
);
4055 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
4057 V_VT(&dest
) = VT_EMPTY
;
4058 hr
= IMXWriter_get_output(writer
, &dest
);
4059 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
4060 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4061 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4062 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4063 VariantClear(&dest
);
4065 /* test when BOM is written to output stream */
4066 V_VT(&dest
) = VT_EMPTY
;
4067 hr
= IMXWriter_put_output(writer
, dest
);
4068 EXPECT_HR(hr
, S_OK
);
4071 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
4072 EXPECT_HR(hr
, S_OK
);
4074 V_VT(&dest
) = VT_UNKNOWN
;
4075 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4076 hr
= IMXWriter_put_output(writer
, dest
);
4077 EXPECT_HR(hr
, S_OK
);
4079 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_TRUE
);
4080 EXPECT_HR(hr
, S_OK
);
4082 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4083 EXPECT_HR(hr
, S_OK
);
4085 hr
= ISAXContentHandler_startDocument(content
);
4086 EXPECT_HR(hr
, S_OK
);
4090 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
4091 EXPECT_HR(hr
, S_OK
);
4092 ok(pos2
.QuadPart
== 2, "got wrong position\n");
4094 ISAXContentHandler_Release(content
);
4095 IMXWriter_Release(writer
);
4100 static const char *encoding_names
[] = {
4113 static void test_mxwriter_encoding(void)
4115 ISAXContentHandler
*content
;
4126 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4127 &IID_IMXWriter
, (void**)&writer
);
4128 EXPECT_HR(hr
, S_OK
);
4130 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4131 EXPECT_HR(hr
, S_OK
);
4133 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4134 EXPECT_HR(hr
, S_OK
);
4136 hr
= ISAXContentHandler_startDocument(content
);
4137 EXPECT_HR(hr
, S_OK
);
4139 hr
= ISAXContentHandler_endDocument(content
);
4140 EXPECT_HR(hr
, S_OK
);
4142 /* The content is always re-encoded to UTF-16 when the output is
4143 * retrieved as a BSTR.
4145 V_VT(&dest
) = VT_EMPTY
;
4146 hr
= IMXWriter_get_output(writer
, &dest
);
4147 EXPECT_HR(hr
, S_OK
);
4148 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
4149 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
4150 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4151 VariantClear(&dest
);
4153 /* switch encoding when something is written already */
4154 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4155 EXPECT_HR(hr
, S_OK
);
4157 V_VT(&dest
) = VT_UNKNOWN
;
4158 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4159 hr
= IMXWriter_put_output(writer
, dest
);
4160 EXPECT_HR(hr
, S_OK
);
4162 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
4163 EXPECT_HR(hr
, S_OK
);
4165 /* write empty element */
4166 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
4167 EXPECT_HR(hr
, S_OK
);
4169 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
4170 EXPECT_HR(hr
, S_OK
);
4173 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
4174 EXPECT_HR(hr
, S_OK
);
4176 hr
= IMXWriter_flush(writer
);
4177 EXPECT_HR(hr
, S_OK
);
4179 hr
= GetHGlobalFromStream(stream
, &g
);
4180 EXPECT_HR(hr
, S_OK
);
4182 ptr
= GlobalLock(g
);
4183 ok(!strncmp(ptr
, "<a/>", 4), "got %c%c%c%c\n", ptr
[0],ptr
[1],ptr
[2],ptr
[3]);
4186 /* so output is unaffected, encoding name is stored however */
4187 hr
= IMXWriter_get_encoding(writer
, &s
);
4188 EXPECT_HR(hr
, S_OK
);
4189 ok(!lstrcmpW(s
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(s
));
4192 IStream_Release(stream
);
4195 enc
= encoding_names
[i
];
4198 char expectedA
[200];
4200 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4201 EXPECT_HR(hr
, S_OK
);
4203 V_VT(&dest
) = VT_UNKNOWN
;
4204 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
4205 hr
= IMXWriter_put_output(writer
, dest
);
4206 EXPECT_HR(hr
, S_OK
);
4208 hr
= IMXWriter_put_encoding(writer
, _bstr_(enc
));
4209 ok(hr
== S_OK
|| broken(hr
!= S_OK
) /* old win versions do not support certain encodings */,
4210 "%s: encoding not accepted\n", enc
);
4213 enc
= encoding_names
[++i
];
4214 IStream_Release(stream
);
4218 hr
= ISAXContentHandler_startDocument(content
);
4219 EXPECT_HR(hr
, S_OK
);
4221 hr
= ISAXContentHandler_endDocument(content
);
4222 EXPECT_HR(hr
, S_OK
);
4224 hr
= IMXWriter_flush(writer
);
4225 EXPECT_HR(hr
, S_OK
);
4227 /* prepare expected string */
4229 strcat(expectedA
, "<?xml version=\"1.0\" encoding=\"");
4230 strcat(expectedA
, enc
);
4231 strcat(expectedA
, "\" standalone=\"no\"?>\r\n");
4233 hr
= GetHGlobalFromStream(stream
, &g
);
4234 EXPECT_HR(hr
, S_OK
);
4236 ptr
= GlobalLock(g
);
4237 ok(!strncmp(ptr
, expectedA
, strlen(expectedA
)), "%s: got %s, expected %.50s\n", enc
, ptr
, expectedA
);
4240 V_VT(&dest
) = VT_EMPTY
;
4241 hr
= IMXWriter_put_output(writer
, dest
);
4242 EXPECT_HR(hr
, S_OK
);
4244 IStream_Release(stream
);
4246 enc
= encoding_names
[++i
];
4249 ISAXContentHandler_Release(content
);
4250 IMXWriter_Release(writer
);
4255 static void test_obj_dispex(IUnknown
*obj
)
4257 static const WCHAR starW
[] = {'*',0};
4258 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
4259 IDispatchEx
*dispex
;
4266 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
4267 EXPECT_HR(hr
, S_OK
);
4268 if (FAILED(hr
)) return;
4271 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
4272 EXPECT_HR(hr
, S_OK
);
4273 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
4275 name
= SysAllocString(starW
);
4276 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
4277 EXPECT_HR(hr
, E_NOTIMPL
);
4278 SysFreeString(name
);
4280 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
4281 EXPECT_HR(hr
, E_NOTIMPL
);
4284 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
4285 EXPECT_HR(hr
, E_NOTIMPL
);
4286 ok(props
== 0, "expected 0 got %d\n", props
);
4288 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
4289 EXPECT_HR(hr
, E_NOTIMPL
);
4290 if (SUCCEEDED(hr
)) SysFreeString(name
);
4292 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
4293 EXPECT_HR(hr
, E_NOTIMPL
);
4295 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
4296 EXPECT_HR(hr
, E_NOTIMPL
);
4297 if (hr
== S_OK
&& unk
) IUnknown_Release(unk
);
4299 IDispatchEx_Release(dispex
);
4302 static void test_dispex(void)
4304 IVBSAXXMLReader
*vbreader
;
4305 ISAXXMLReader
*reader
;
4309 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
4310 &IID_ISAXXMLReader
, (void**)&reader
);
4311 EXPECT_HR(hr
, S_OK
);
4313 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
4314 EXPECT_HR(hr
, S_OK
);
4315 test_obj_dispex(unk
);
4316 IUnknown_Release(unk
);
4318 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
4319 EXPECT_HR(hr
, S_OK
);
4320 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
4321 EXPECT_HR(hr
, S_OK
);
4322 test_obj_dispex(unk
);
4323 IUnknown_Release(unk
);
4324 IVBSAXXMLReader_Release(vbreader
);
4326 ISAXXMLReader_Release(reader
);
4329 static void test_mxwriter_dispex(void)
4331 IDispatchEx
*dispex
;
4336 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4337 &IID_IMXWriter
, (void**)&writer
);
4338 EXPECT_HR(hr
, S_OK
);
4340 hr
= IMXWriter_QueryInterface(writer
, &IID_IDispatchEx
, (void**)&dispex
);
4341 EXPECT_HR(hr
, S_OK
);
4342 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4343 test_obj_dispex(unk
);
4344 IUnknown_Release(unk
);
4345 IDispatchEx_Release(dispex
);
4347 IMXWriter_Release(writer
);
4350 static void test_mxwriter_comment(void)
4352 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
4353 ISAXContentHandler
*content
;
4354 ISAXLexicalHandler
*lexical
;
4359 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4360 &IID_IMXWriter
, (void**)&writer
);
4361 EXPECT_HR(hr
, S_OK
);
4363 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4364 EXPECT_HR(hr
, S_OK
);
4366 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4367 EXPECT_HR(hr
, S_OK
);
4369 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4370 EXPECT_HR(hr
, S_OK
);
4372 hr
= ISAXContentHandler_startDocument(content
);
4373 EXPECT_HR(hr
, S_OK
);
4375 hr
= ISAXLexicalHandler_comment(lexical
, NULL
, 0);
4376 EXPECT_HR(hr
, E_INVALIDARG
);
4378 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, 0);
4379 EXPECT_HR(hr
, S_OK
);
4381 V_VT(&dest
) = VT_EMPTY
;
4382 hr
= IMXWriter_get_output(writer
, &dest
);
4383 EXPECT_HR(hr
, S_OK
);
4384 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4385 ok(!lstrcmpW(_bstr_("<!---->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4386 VariantClear(&dest
);
4388 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, sizeof(commentW
)/sizeof(WCHAR
)-1);
4389 EXPECT_HR(hr
, S_OK
);
4391 V_VT(&dest
) = VT_EMPTY
;
4392 hr
= IMXWriter_get_output(writer
, &dest
);
4393 EXPECT_HR(hr
, S_OK
);
4394 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4395 ok(!lstrcmpW(_bstr_("<!---->\r\n<!--comment-->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4396 VariantClear(&dest
);
4398 ISAXContentHandler_Release(content
);
4399 ISAXLexicalHandler_Release(lexical
);
4400 IMXWriter_Release(writer
);
4404 static void test_mxwriter_cdata(void)
4406 ISAXContentHandler
*content
;
4407 ISAXLexicalHandler
*lexical
;
4412 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4413 &IID_IMXWriter
, (void**)&writer
);
4414 EXPECT_HR(hr
, S_OK
);
4416 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4417 EXPECT_HR(hr
, S_OK
);
4419 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4420 EXPECT_HR(hr
, S_OK
);
4422 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4423 EXPECT_HR(hr
, S_OK
);
4425 hr
= ISAXContentHandler_startDocument(content
);
4426 EXPECT_HR(hr
, S_OK
);
4428 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4429 EXPECT_HR(hr
, S_OK
);
4431 V_VT(&dest
) = VT_EMPTY
;
4432 hr
= IMXWriter_get_output(writer
, &dest
);
4433 EXPECT_HR(hr
, S_OK
);
4434 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4435 ok(!lstrcmpW(_bstr_("<![CDATA["), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4436 VariantClear(&dest
);
4438 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4439 EXPECT_HR(hr
, S_OK
);
4441 /* all these are escaped for text nodes */
4442 hr
= ISAXContentHandler_characters(content
, _bstr_("< > & \""), 7);
4443 EXPECT_HR(hr
, S_OK
);
4445 hr
= ISAXLexicalHandler_endCDATA(lexical
);
4446 EXPECT_HR(hr
, S_OK
);
4448 V_VT(&dest
) = VT_EMPTY
;
4449 hr
= IMXWriter_get_output(writer
, &dest
);
4450 EXPECT_HR(hr
, S_OK
);
4451 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4452 ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4453 VariantClear(&dest
);
4455 ISAXContentHandler_Release(content
);
4456 ISAXLexicalHandler_Release(lexical
);
4457 IMXWriter_Release(writer
);
4461 static void test_mxwriter_pi(void)
4463 static const WCHAR targetW
[] = {'t','a','r','g','e','t',0};
4464 static const WCHAR dataW
[] = {'d','a','t','a',0};
4465 ISAXContentHandler
*content
;
4470 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4471 &IID_IMXWriter
, (void**)&writer
);
4472 EXPECT_HR(hr
, S_OK
);
4474 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4475 EXPECT_HR(hr
, S_OK
);
4477 hr
= ISAXContentHandler_processingInstruction(content
, NULL
, 0, NULL
, 0);
4478 EXPECT_HR(hr
, E_INVALIDARG
);
4480 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 0, NULL
, 0);
4481 EXPECT_HR(hr
, S_OK
);
4483 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, NULL
, 0);
4484 EXPECT_HR(hr
, S_OK
);
4486 V_VT(&dest
) = VT_EMPTY
;
4487 hr
= IMXWriter_get_output(writer
, &dest
);
4488 EXPECT_HR(hr
, S_OK
);
4489 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4490 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4491 VariantClear(&dest
);
4493 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 4, dataW
, 4);
4494 EXPECT_HR(hr
, S_OK
);
4496 V_VT(&dest
) = VT_EMPTY
;
4497 hr
= IMXWriter_get_output(writer
, &dest
);
4498 EXPECT_HR(hr
, S_OK
);
4499 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4500 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
)));
4501 VariantClear(&dest
);
4503 V_VT(&dest
) = VT_EMPTY
;
4504 hr
= IMXWriter_put_output(writer
, dest
);
4505 EXPECT_HR(hr
, S_OK
);
4507 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, dataW
, 0);
4508 EXPECT_HR(hr
, S_OK
);
4510 V_VT(&dest
) = VT_EMPTY
;
4511 hr
= IMXWriter_get_output(writer
, &dest
);
4512 EXPECT_HR(hr
, S_OK
);
4513 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4514 ok(!lstrcmpW(_bstr_("<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4515 VariantClear(&dest
);
4518 ISAXContentHandler_Release(content
);
4519 IMXWriter_Release(writer
);
4522 static void test_mxwriter_ignorablespaces(void)
4524 static const WCHAR dataW
[] = {'d','a','t','a',0};
4525 ISAXContentHandler
*content
;
4530 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4531 &IID_IMXWriter
, (void**)&writer
);
4532 EXPECT_HR(hr
, S_OK
);
4534 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4535 EXPECT_HR(hr
, S_OK
);
4537 hr
= ISAXContentHandler_ignorableWhitespace(content
, NULL
, 0);
4538 EXPECT_HR(hr
, E_INVALIDARG
);
4540 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 0);
4541 EXPECT_HR(hr
, S_OK
);
4543 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 4);
4544 EXPECT_HR(hr
, S_OK
);
4546 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 1);
4547 EXPECT_HR(hr
, S_OK
);
4549 V_VT(&dest
) = VT_EMPTY
;
4550 hr
= IMXWriter_get_output(writer
, &dest
);
4551 EXPECT_HR(hr
, S_OK
);
4552 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4553 ok(!lstrcmpW(_bstr_("datad"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4554 VariantClear(&dest
);
4556 ISAXContentHandler_Release(content
);
4557 IMXWriter_Release(writer
);
4560 static void test_mxwriter_dtd(void)
4562 static const WCHAR contentW
[] = {'c','o','n','t','e','n','t'};
4563 static const WCHAR nameW
[] = {'n','a','m','e'};
4564 static const WCHAR pubW
[] = {'p','u','b'};
4565 static const WCHAR sysW
[] = {'s','y','s'};
4566 ISAXContentHandler
*content
;
4567 ISAXLexicalHandler
*lexical
;
4568 ISAXDeclHandler
*decl
;
4573 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4574 &IID_IMXWriter
, (void**)&writer
);
4575 EXPECT_HR(hr
, S_OK
);
4577 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4578 EXPECT_HR(hr
, S_OK
);
4580 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4581 EXPECT_HR(hr
, S_OK
);
4583 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
4584 EXPECT_HR(hr
, S_OK
);
4586 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4587 EXPECT_HR(hr
, S_OK
);
4589 hr
= ISAXContentHandler_startDocument(content
);
4590 EXPECT_HR(hr
, S_OK
);
4592 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, NULL
, 0);
4593 EXPECT_HR(hr
, E_INVALIDARG
);
4595 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4596 EXPECT_HR(hr
, E_INVALIDARG
);
4598 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4599 EXPECT_HR(hr
, E_INVALIDARG
);
4601 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4602 EXPECT_HR(hr
, E_INVALIDARG
);
4604 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0, NULL
, 0);
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_("<!DOCTYPE name [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4612 VariantClear(&dest
);
4614 /* system id is required if public is present */
4615 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4616 EXPECT_HR(hr
, E_INVALIDARG
);
4618 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
),
4619 pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4620 EXPECT_HR(hr
, S_OK
);
4622 V_VT(&dest
) = VT_EMPTY
;
4623 hr
= IMXWriter_get_output(writer
, &dest
);
4624 EXPECT_HR(hr
, S_OK
);
4625 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4626 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4627 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4628 VariantClear(&dest
);
4630 hr
= ISAXLexicalHandler_endDTD(lexical
);
4631 EXPECT_HR(hr
, S_OK
);
4633 hr
= ISAXLexicalHandler_endDTD(lexical
);
4634 EXPECT_HR(hr
, S_OK
);
4636 V_VT(&dest
) = VT_EMPTY
;
4637 hr
= IMXWriter_get_output(writer
, &dest
);
4638 EXPECT_HR(hr
, S_OK
);
4639 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4640 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4641 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n"),
4642 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4643 VariantClear(&dest
);
4645 /* element declaration */
4646 V_VT(&dest
) = VT_EMPTY
;
4647 hr
= IMXWriter_put_output(writer
, dest
);
4648 EXPECT_HR(hr
, S_OK
);
4650 hr
= ISAXDeclHandler_elementDecl(decl
, NULL
, 0, NULL
, 0);
4651 EXPECT_HR(hr
, E_INVALIDARG
);
4653 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0);
4654 EXPECT_HR(hr
, E_INVALIDARG
);
4656 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, sizeof(contentW
)/sizeof(WCHAR
));
4657 EXPECT_HR(hr
, S_OK
);
4659 V_VT(&dest
) = VT_EMPTY
;
4660 hr
= IMXWriter_get_output(writer
, &dest
);
4661 EXPECT_HR(hr
, S_OK
);
4662 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4663 ok(!lstrcmpW(_bstr_("<!ELEMENT name content>\r\n"),
4664 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4665 VariantClear(&dest
);
4667 V_VT(&dest
) = VT_EMPTY
;
4668 hr
= IMXWriter_put_output(writer
, dest
);
4669 EXPECT_HR(hr
, S_OK
);
4671 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, 0);
4672 EXPECT_HR(hr
, S_OK
);
4674 V_VT(&dest
) = VT_EMPTY
;
4675 hr
= IMXWriter_get_output(writer
, &dest
);
4676 EXPECT_HR(hr
, S_OK
);
4677 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4678 ok(!lstrcmpW(_bstr_("<!ELEMENT name >\r\n"),
4679 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4680 VariantClear(&dest
);
4682 /* attribute declaration */
4683 V_VT(&dest
) = VT_EMPTY
;
4684 hr
= IMXWriter_put_output(writer
, dest
);
4685 EXPECT_HR(hr
, S_OK
);
4687 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4688 _bstr_("attribute"), strlen("attribute"), _bstr_("CDATA"), strlen("CDATA"),
4689 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value"), strlen("value"));
4690 EXPECT_HR(hr
, S_OK
);
4692 V_VT(&dest
) = VT_EMPTY
;
4693 hr
= IMXWriter_get_output(writer
, &dest
);
4694 EXPECT_HR(hr
, S_OK
);
4695 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4696 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"),
4697 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4698 VariantClear(&dest
);
4700 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4701 _bstr_("attribute2"), strlen("attribute2"), _bstr_("CDATA"), strlen("CDATA"),
4702 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value2"), strlen("value2"));
4703 EXPECT_HR(hr
, S_OK
);
4705 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element2"), strlen("element2"),
4706 _bstr_("attribute3"), strlen("attribute3"), _bstr_("CDATA"), strlen("CDATA"),
4707 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value3"), strlen("value3"));
4708 EXPECT_HR(hr
, S_OK
);
4710 V_VT(&dest
) = VT_EMPTY
;
4711 hr
= IMXWriter_get_output(writer
, &dest
);
4712 EXPECT_HR(hr
, S_OK
);
4713 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4714 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"
4715 "<!ATTLIST element attribute2 CDATA #REQUIRED \"value2\">\r\n"
4716 "<!ATTLIST element2 attribute3 CDATA #REQUIRED \"value3\">\r\n"),
4717 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4718 VariantClear(&dest
);
4720 /* internal entities */
4721 V_VT(&dest
) = VT_EMPTY
;
4722 hr
= IMXWriter_put_output(writer
, dest
);
4723 EXPECT_HR(hr
, S_OK
);
4725 hr
= ISAXDeclHandler_internalEntityDecl(decl
, NULL
, 0, NULL
, 0);
4726 EXPECT_HR(hr
, E_INVALIDARG
);
4728 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0);
4729 EXPECT_HR(hr
, E_INVALIDARG
);
4731 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("value"), strlen("value"));
4732 EXPECT_HR(hr
, S_OK
);
4734 V_VT(&dest
) = VT_EMPTY
;
4735 hr
= IMXWriter_get_output(writer
, &dest
);
4736 EXPECT_HR(hr
, S_OK
);
4737 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4738 ok(!lstrcmpW(_bstr_("<!ENTITY name \"value\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4739 VariantClear(&dest
);
4741 ISAXContentHandler_Release(content
);
4742 ISAXLexicalHandler_Release(lexical
);
4743 ISAXDeclHandler_Release(decl
);
4744 IMXWriter_Release(writer
);
4756 } addattribute_test_t
;
4758 static const addattribute_test_t addattribute_data
[] = {
4759 { &CLSID_SAXAttributes
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4760 { &CLSID_SAXAttributes30
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4761 { &CLSID_SAXAttributes40
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4762 { &CLSID_SAXAttributes60
, NULL
, NULL
, "ns:qname", NULL
, "value", S_OK
},
4764 { &CLSID_SAXAttributes
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4765 { &CLSID_SAXAttributes30
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4766 { &CLSID_SAXAttributes40
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4767 { &CLSID_SAXAttributes60
, NULL
, "qname", "ns:qname", NULL
, "value", S_OK
},
4769 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4770 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4771 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4772 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", NULL
, "value", S_OK
},
4774 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4775 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4776 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4777 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4782 static void test_mxattr_addAttribute(void)
4784 const addattribute_test_t
*table
= addattribute_data
;
4787 while (table
->clsid
)
4789 ISAXAttributes
*saxattr
;
4790 IMXAttributes
*mxattr
;
4795 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
4802 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4803 &IID_IMXAttributes
, (void**)&mxattr
);
4804 EXPECT_HR(hr
, S_OK
);
4806 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4807 EXPECT_HR(hr
, S_OK
);
4809 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
4810 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4811 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4813 hr
= ISAXAttributes_getLength(saxattr
, NULL
);
4814 EXPECT_HR(hr
, E_POINTER
);
4818 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4819 EXPECT_HR(hr
, S_OK
);
4820 ok(len
== 0, "got %d\n", len
);
4822 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
4823 EXPECT_HR(hr
, E_INVALIDARG
);
4825 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
4826 EXPECT_HR(hr
, E_INVALIDARG
);
4828 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
4829 EXPECT_HR(hr
, E_INVALIDARG
);
4831 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
4832 EXPECT_HR(hr
, E_INVALIDARG
);
4834 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
4835 EXPECT_HR(hr
, E_INVALIDARG
);
4837 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
4838 EXPECT_HR(hr
, E_INVALIDARG
);
4840 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
4841 EXPECT_HR(hr
, E_INVALIDARG
);
4843 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
4844 EXPECT_HR(hr
, E_INVALIDARG
);
4846 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_(table
->uri
), _bstr_(table
->local
),
4847 _bstr_(table
->qname
), _bstr_(table
->type
), _bstr_(table
->value
));
4848 ok(hr
== table
->hr
, "%d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
4852 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
4853 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4854 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4856 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
4857 EXPECT_HR(hr
, E_POINTER
);
4859 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
4860 EXPECT_HR(hr
, E_POINTER
);
4862 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
4863 EXPECT_HR(hr
, E_POINTER
);
4865 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
4866 EXPECT_HR(hr
, E_POINTER
);
4868 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
4869 EXPECT_HR(hr
, E_POINTER
);
4871 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
4872 EXPECT_HR(hr
, E_POINTER
);
4876 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
4877 EXPECT_HR(hr
, S_OK
);
4878 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4880 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
4883 value
= (void*)0xdeadbeef;
4884 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
4885 EXPECT_HR(hr
, S_OK
);
4889 ok(!lstrcmpW(_bstr_(table
->type
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4891 ok(lstrlenW(value
) == len
, "%d: got wrong type value length %d\n", i
, len
);
4895 ok(*value
== 0, "%d: got type value %s\n", i
, wine_dbgstr_w(value
));
4896 ok(len
== 0, "%d: got wrong type value length %d\n", i
, len
);
4899 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, NULL
);
4900 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4901 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4903 EXPECT_HR(hr
, E_POINTER
);
4906 EXPECT_HR(hr
, E_INVALIDARG
);
4908 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, &index
);
4909 EXPECT_HR(hr
, E_INVALIDARG
);
4912 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_("nonexistent"), 11, &index
);
4913 EXPECT_HR(hr
, E_INVALIDARG
);
4914 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4917 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), 0, &index
);
4918 EXPECT_HR(hr
, E_INVALIDARG
);
4919 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4922 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &index
);
4923 EXPECT_HR(hr
, S_OK
);
4924 ok(index
== 0, "%d: got wrong index %d\n", i
, index
);
4927 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
)-1, &index
);
4928 EXPECT_HR(hr
, E_INVALIDARG
);
4929 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4931 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes40
) ||
4932 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes60
))
4934 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4935 EXPECT_HR(hr
, E_INVALIDARG
);
4937 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4938 EXPECT_HR(hr
, E_INVALIDARG
);
4940 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4941 EXPECT_HR(hr
, E_INVALIDARG
);
4943 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
4944 EXPECT_HR(hr
, E_INVALIDARG
);
4946 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
4947 EXPECT_HR(hr
, E_INVALIDARG
);
4949 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
4950 EXPECT_HR(hr
, E_INVALIDARG
);
4954 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4955 EXPECT_HR(hr
, E_POINTER
);
4957 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4958 EXPECT_HR(hr
, E_POINTER
);
4960 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4961 EXPECT_HR(hr
, E_POINTER
);
4963 /* versions 4 and 6 crash */
4964 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, NULL
);
4965 EXPECT_HR(hr
, E_POINTER
);
4967 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, &len
);
4968 EXPECT_HR(hr
, E_POINTER
);
4970 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
4971 EXPECT_HR(hr
, E_POINTER
);
4973 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
4974 EXPECT_HR(hr
, E_POINTER
);
4976 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
4977 EXPECT_HR(hr
, E_POINTER
);
4979 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, &value
, NULL
);
4980 EXPECT_HR(hr
, E_POINTER
);
4982 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, NULL
, &len
);
4983 EXPECT_HR(hr
, E_POINTER
);
4985 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
), _bstr_(table
->local
),
4986 strlen(table
->local
), NULL
, NULL
);
4987 EXPECT_HR(hr
, E_POINTER
);
4990 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &value
, &len
);
4991 EXPECT_HR(hr
, S_OK
);
4992 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4994 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
4997 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
),
4998 _bstr_(table
->local
), strlen(table
->local
), &value
, &len
);
4999 EXPECT_HR(hr
, S_OK
);
5000 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
5002 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
5007 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5008 EXPECT_HR(hr
, S_OK
);
5009 if (table
->hr
== S_OK
)
5010 ok(len
== 1, "%d: got %d length, expected 1\n", i
, len
);
5012 ok(len
== 0, "%d: got %d length, expected 0\n", i
, len
);
5014 ISAXAttributes_Release(saxattr
);
5015 IMXAttributes_Release(mxattr
);
5024 static void test_mxattr_clear(void)
5026 ISAXAttributes
*saxattr
;
5027 IMXAttributes
*mxattr
;
5032 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5033 &IID_IMXAttributes
, (void**)&mxattr
);
5034 EXPECT_HR(hr
, S_OK
);
5036 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5037 EXPECT_HR(hr
, S_OK
);
5039 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, NULL
);
5040 EXPECT_HR(hr
, E_INVALIDARG
);
5042 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5043 EXPECT_HR(hr
, E_INVALIDARG
);
5045 hr
= IMXAttributes_clear(mxattr
);
5046 EXPECT_HR(hr
, S_OK
);
5048 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("local"),
5049 _bstr_("qname"), _bstr_("type"), _bstr_("value"));
5050 EXPECT_HR(hr
, S_OK
);
5053 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5054 EXPECT_HR(hr
, S_OK
);
5055 ok(len
== 1, "got %d\n", len
);
5058 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, &len
);
5059 EXPECT_HR(hr
, E_POINTER
);
5060 ok(len
== -1, "got %d\n", len
);
5062 ptr
= (void*)0xdeadbeef;
5063 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, NULL
);
5064 EXPECT_HR(hr
, E_POINTER
);
5065 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5068 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5069 EXPECT_HR(hr
, S_OK
);
5070 ok(len
== 5, "got %d\n", len
);
5071 ok(!lstrcmpW(ptr
, _bstr_("qname")), "got %s\n", wine_dbgstr_w(ptr
));
5073 hr
= IMXAttributes_clear(mxattr
);
5074 EXPECT_HR(hr
, S_OK
);
5077 hr
= ISAXAttributes_getLength(saxattr
, &len
);
5078 EXPECT_HR(hr
, S_OK
);
5079 ok(len
== 0, "got %d\n", len
);
5082 ptr
= (void*)0xdeadbeef;
5083 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
5084 EXPECT_HR(hr
, E_INVALIDARG
);
5085 ok(len
== -1, "got %d\n", len
);
5086 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
5088 IMXAttributes_Release(mxattr
);
5089 ISAXAttributes_Release(saxattr
);
5093 static void test_mxattr_dispex(void)
5095 IMXAttributes
*mxattr
;
5096 IDispatchEx
*dispex
;
5100 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5101 &IID_IMXAttributes
, (void**)&mxattr
);
5102 EXPECT_HR(hr
, S_OK
);
5104 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IDispatchEx
, (void**)&dispex
);
5105 EXPECT_HR(hr
, S_OK
);
5106 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
5107 test_obj_dispex(unk
);
5108 IUnknown_Release(unk
);
5109 IDispatchEx_Release(dispex
);
5111 IMXAttributes_Release(mxattr
);
5114 static void test_mxattr_qi(void)
5116 IVBSAXAttributes
*vbsaxattr
, *vbsaxattr2
;
5117 ISAXAttributes
*saxattr
;
5118 IMXAttributes
*mxattr
;
5121 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
5122 &IID_IMXAttributes
, (void**)&mxattr
);
5123 EXPECT_HR(hr
, S_OK
);
5125 EXPECT_REF(mxattr
, 1);
5126 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5127 EXPECT_HR(hr
, S_OK
);
5129 EXPECT_REF(mxattr
, 2);
5130 EXPECT_REF(saxattr
, 2);
5132 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr
);
5133 EXPECT_HR(hr
, S_OK
);
5135 EXPECT_REF(vbsaxattr
, 3);
5136 EXPECT_REF(mxattr
, 3);
5137 EXPECT_REF(saxattr
, 3);
5139 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr2
);
5140 EXPECT_HR(hr
, S_OK
);
5142 EXPECT_REF(vbsaxattr
, 4);
5143 EXPECT_REF(mxattr
, 4);
5144 EXPECT_REF(saxattr
, 4);
5146 IMXAttributes_Release(mxattr
);
5147 ISAXAttributes_Release(saxattr
);
5148 IVBSAXAttributes_Release(vbsaxattr
);
5149 IVBSAXAttributes_Release(vbsaxattr2
);
5152 static struct msxmlsupported_data_t saxattr_support_data
[] =
5154 { &CLSID_SAXAttributes
, "SAXAttributes" },
5155 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
5156 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
5157 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
5161 static void test_mxattr_localname(void)
5163 static const WCHAR localname1W
[] = {'l','o','c','a','l','n','a','m','e','1',0};
5164 static const WCHAR localnameW
[] = {'l','o','c','a','l','n','a','m','e',0};
5165 static const WCHAR uri1W
[] = {'u','r','i','1',0};
5166 static const WCHAR uriW
[] = {'u','r','i',0};
5168 const struct msxmlsupported_data_t
*table
= saxattr_support_data
;
5170 while (table
->clsid
)
5172 ISAXAttributes
*saxattr
;
5173 IMXAttributes
*mxattr
;
5177 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
5183 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
5184 &IID_IMXAttributes
, (void**)&mxattr
);
5185 EXPECT_HR(hr
, S_OK
);
5187 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
5188 EXPECT_HR(hr
, S_OK
);
5190 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, &index
);
5191 EXPECT_HR(hr
, E_INVALIDARG
);
5193 /* add some ambiguos attribute names */
5194 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5195 _bstr_("a:localname"), _bstr_(""), _bstr_("value"));
5196 EXPECT_HR(hr
, S_OK
);
5197 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
5198 _bstr_("b:localname"), _bstr_(""), _bstr_("value"));
5199 EXPECT_HR(hr
, S_OK
);
5202 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localnameW
, lstrlenW(localnameW
), &index
);
5203 EXPECT_HR(hr
, S_OK
);
5204 ok(index
== 0, "%s: got index %d\n", table
->name
, index
);
5207 hr
= ISAXAttributes_getIndexFromName(saxattr
, uri1W
, lstrlenW(uri1W
), localnameW
, lstrlenW(localnameW
), &index
);
5208 EXPECT_HR(hr
, E_INVALIDARG
);
5209 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5212 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), &index
);
5213 EXPECT_HR(hr
, E_INVALIDARG
);
5214 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
5216 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
5217 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
5219 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5220 EXPECT_HR(hr
, E_POINTER
);
5222 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5223 EXPECT_HR(hr
, E_POINTER
);
5227 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
5228 EXPECT_HR(hr
, E_INVALIDARG
);
5230 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5231 EXPECT_HR(hr
, E_INVALIDARG
);
5234 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), NULL
, 0, &index
);
5235 EXPECT_HR(hr
, E_INVALIDARG
);
5237 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, localname1W
, lstrlenW(localname1W
), &index
);
5238 EXPECT_HR(hr
, E_INVALIDARG
);
5242 ISAXAttributes_Release(saxattr
);
5243 IMXAttributes_Release(mxattr
);
5247 START_TEST(saxreader
)
5249 ISAXXMLReader
*reader
;
5252 hr
= CoInitialize(NULL
);
5253 ok(hr
== S_OK
, "failed to init com\n");
5255 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
5256 &IID_ISAXXMLReader
, (void**)&reader
);
5260 skip("Failed to create SAXXMLReader instance\n");
5264 ISAXXMLReader_Release(reader
);
5266 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
5268 get_class_support_data(reader_support_data
, &IID_ISAXXMLReader
);
5271 test_saxreader_properties();
5272 test_saxreader_features();
5273 test_saxreader_encoding();
5276 /* MXXMLWriter tests */
5277 get_class_support_data(mxwriter_support_data
, &IID_IMXWriter
);
5278 if (is_clsid_supported(&CLSID_MXXMLWriter
, mxwriter_support_data
))
5280 test_mxwriter_handlers();
5281 test_mxwriter_startenddocument();
5282 test_mxwriter_startendelement();
5283 test_mxwriter_characters();
5284 test_mxwriter_comment();
5285 test_mxwriter_cdata();
5287 test_mxwriter_ignorablespaces();
5288 test_mxwriter_dtd();
5289 test_mxwriter_properties();
5290 test_mxwriter_flush();
5291 test_mxwriter_stream();
5292 test_mxwriter_encoding();
5293 test_mxwriter_dispex();
5296 win_skip("MXXMLWriter not supported\n");
5298 /* SAXAttributes tests */
5299 get_class_support_data(mxattributes_support_data
, &IID_IMXAttributes
);
5300 if (is_clsid_supported(&CLSID_SAXAttributes
, mxattributes_support_data
))
5303 test_mxattr_addAttribute();
5304 test_mxattr_clear();
5305 test_mxattr_localname();
5306 test_mxattr_dispex();
5309 skip("SAXAttributes not supported\n");