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
,
177 static const char *event_names
[EVENT_LAST
] = {
179 "putDocumentLocator",
182 "startPrefixMapping",
187 "ignorableWhitespace",
188 "processingInstruction",
195 struct attribute_entry
{
201 /* used for actual call data only, null for expected call data */
217 /* allocated once at startElement callback */
218 struct attribute_entry
*attributes
;
221 /* used for actual call data only, null for expected call data */
231 struct call_entry
*sequence
;
234 #define CONTENT_HANDLER_INDEX 0
235 #define NUM_CALL_SEQUENCES 1
236 static struct call_sequence
*sequences
[NUM_CALL_SEQUENCES
];
238 static void init_call_entry(ISAXLocator
*locator
, struct call_entry
*call
)
240 memset(call
, 0, sizeof(*call
));
241 ISAXLocator_getLineNumber(locator
, &call
->line
);
242 ISAXLocator_getColumnNumber(locator
, &call
->column
);
245 static void add_call(struct call_sequence
**seq
, int sequence_index
,
246 const struct call_entry
*call
)
248 struct call_sequence
*call_seq
= seq
[sequence_index
];
250 if (!call_seq
->sequence
)
253 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0,
254 call_seq
->size
* sizeof (struct call_entry
));
257 if (call_seq
->count
== call_seq
->size
)
260 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
262 call_seq
->size
* sizeof (struct call_entry
));
265 assert(call_seq
->sequence
);
267 call_seq
->sequence
[call_seq
->count
].id
= call
->id
;
268 call_seq
->sequence
[call_seq
->count
].line
= call
->line
;
269 call_seq
->sequence
[call_seq
->count
].column
= call
->column
;
270 call_seq
->sequence
[call_seq
->count
].arg1W
= call
->arg1W
;
271 call_seq
->sequence
[call_seq
->count
].arg2W
= call
->arg2W
;
272 call_seq
->sequence
[call_seq
->count
].arg3W
= call
->arg3W
;
273 call_seq
->sequence
[call_seq
->count
].ret
= call
->ret
;
274 call_seq
->sequence
[call_seq
->count
].attr_count
= call
->attr_count
;
275 call_seq
->sequence
[call_seq
->count
].attributes
= call
->attributes
;
280 static inline void flush_sequence(struct call_sequence
**seg
, int sequence_index
)
284 struct call_sequence
*call_seq
= seg
[sequence_index
];
286 for (i
= 0; i
< call_seq
->count
; i
++)
290 for (j
= 0; j
< call_seq
->sequence
[i
].attr_count
; j
++)
292 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].uriW
);
293 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].localW
);
294 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].qnameW
);
297 SysFreeString(call_seq
->sequence
[i
].arg1W
);
298 SysFreeString(call_seq
->sequence
[i
].arg2W
);
299 SysFreeString(call_seq
->sequence
[i
].arg3W
);
302 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
303 call_seq
->sequence
= NULL
;
304 call_seq
->count
= call_seq
->size
= 0;
307 static inline void flush_sequences(struct call_sequence
**seq
, int n
)
310 for (i
= 0; i
< n
; i
++)
311 flush_sequence(seq
, i
);
314 static const char *get_event_name(CH event
)
316 return event_names
[event
];
319 static void compare_attributes(const struct call_entry
*actual
, const struct call_entry
*expected
, const char *context
,
320 int todo
, const char *file
, int line
, int *failcount
)
324 /* attribute count is not stored for expected data */
325 if (expected
->attributes
)
327 struct attribute_entry
*ptr
= expected
->attributes
;
328 while (ptr
->uri
) { lenexp
++; ptr
++; };
331 /* check count first and exit earlier */
332 if (actual
->attr_count
!= lenexp
&& todo
)
336 ok_(file
, line
) (FALSE
, "%s: in event %s expecting attr count %d got %d\n",
337 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
340 ok_(file
, line
) (actual
->attr_count
== lenexp
, "%s: in event %s expecting attr count %d got %d\n",
341 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
343 if (actual
->attr_count
!= lenexp
) return;
345 /* now compare all attributes strings */
346 for (i
= 0; i
< actual
->attr_count
; i
++)
348 test_saxstr(file
, line
, actual
->attributes
[i
].uriW
, expected
->attributes
[i
].uri
, todo
, failcount
);
349 test_saxstr(file
, line
, actual
->attributes
[i
].localW
, expected
->attributes
[i
].local
, todo
, failcount
);
350 test_saxstr(file
, line
, actual
->attributes
[i
].qnameW
, expected
->attributes
[i
].qname
, todo
, failcount
);
351 test_saxstr(file
, line
, actual
->attributes
[i
].valueW
, expected
->attributes
[i
].value
, todo
, failcount
);
355 static void ok_sequence_(struct call_sequence
**seq
, int sequence_index
,
356 const struct call_entry
*expected
, const char *context
, int todo
,
357 const char *file
, int line
)
359 struct call_sequence
*call_seq
= seq
[sequence_index
];
360 static const struct call_entry end_of_sequence
= { CH_ENDTEST
};
361 const struct call_entry
*actual
, *sequence
;
364 add_call(seq
, sequence_index
, &end_of_sequence
);
366 sequence
= call_seq
->sequence
;
369 while (expected
->id
!= CH_ENDTEST
&& actual
->id
!= CH_ENDTEST
)
371 if (expected
->id
== actual
->id
)
373 /* always test position data */
374 if (expected
->line
!= actual
->line
&& todo
)
379 ok_(file
, line
) (FALSE
,
380 "%s: in event %s expecting line %d got %d\n",
381 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
386 ok_(file
, line
) (expected
->line
== actual
->line
,
387 "%s: in event %s expecting line %d got %d\n",
388 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
391 if (expected
->column
!= actual
->column
&& todo
)
396 ok_(file
, line
) (FALSE
,
397 "%s: in event %s expecting column %d got %d\n",
398 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
403 ok_(file
, line
) (expected
->column
== actual
->column
,
404 "%s: in event %s expecting column %d got %d\n",
405 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
410 case CH_PUTDOCUMENTLOCATOR
:
411 case CH_STARTDOCUMENT
:
414 case CH_STARTPREFIXMAPPING
:
416 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
417 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
419 case CH_ENDPREFIXMAPPING
:
421 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
423 case CH_STARTELEMENT
:
424 /* compare attributes */
425 compare_attributes(actual
, expected
, context
, todo
, file
, line
, &failcount
);
428 /* uri, localname, qname */
429 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
430 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
431 test_saxstr(file
, line
, actual
->arg3W
, expected
->arg3
, todo
, &failcount
);
434 case CH_IGNORABLEWHITESPACE
:
436 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
438 case CH_PROCESSINGINSTRUCTION
:
440 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
441 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
443 case CH_SKIPPEDENTITY
:
445 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
448 /* test return value only */
449 if (expected
->ret
!= actual
->ret
&& todo
)
452 ok_(file
, line
) (FALSE
,
453 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
454 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
457 ok_(file
, line
) (expected
->ret
== actual
->ret
,
458 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
459 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
462 case EG_IGNORABLEWARNING
:
464 ok(0, "%s: callback not handled, %s\n", context
, get_event_name(actual
->id
));
474 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
475 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
478 flush_sequence(seq
, sequence_index
);
483 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
484 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
494 if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
497 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
498 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
502 else if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
504 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
505 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
508 if (todo
&& !failcount
) /* succeeded yet marked todo */
512 ok_(file
, line
)(TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
516 flush_sequence(seq
, sequence_index
);
519 #define ok_sequence(seq, index, exp, contx, todo) \
520 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
522 static void init_call_sequences(struct call_sequence
**seq
, int n
)
526 for (i
= 0; i
< n
; i
++)
527 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct call_sequence
));
530 static const WCHAR szSimpleXML
[] = {
531 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
532 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
533 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
534 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
535 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
538 static const WCHAR carriage_ret_test
[] = {
539 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
540 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
541 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
542 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
543 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
546 static const WCHAR szUtf16XML
[] = {
547 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
548 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
549 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
552 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
554 static const CHAR szUtf8XML
[] =
555 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
557 static const char utf8xml2
[] =
558 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n";
560 static const CHAR testXML
[] =
561 "<?xml version=\"1.0\" ?>\n"
563 " <Number>1234</Number>\n"
564 " <Name>Captain Ahab</Name>\n"
567 static const char test_attributes
[] =
568 "<?xml version=\"1.0\" ?>\n"
569 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
570 "<node1 xmlns:p=\"test\" />"
573 static struct call_entry content_handler_test1
[] = {
574 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
575 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
576 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
577 { CH_CHARACTERS
, 2, 14, S_OK
, "\n " },
578 { CH_STARTELEMENT
, 3, 12, S_OK
, "", "Number", "Number" },
579 { CH_CHARACTERS
, 3, 12, S_OK
, "1234" },
580 { CH_ENDELEMENT
, 3, 18, S_OK
, "", "Number", "Number" },
581 { CH_CHARACTERS
, 3, 25, S_OK
, "\n " },
582 { CH_STARTELEMENT
, 4, 10, S_OK
, "", "Name", "Name" },
583 { CH_CHARACTERS
, 4, 10, S_OK
, "Captain Ahab" },
584 { CH_ENDELEMENT
, 4, 24, S_OK
, "", "Name", "Name" },
585 { CH_CHARACTERS
, 4, 29, S_OK
, "\n" },
586 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
587 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
591 /* applies to versions 4 and 6 */
592 static struct call_entry content_handler_test1_alternate
[] = {
593 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
594 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
595 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
596 { CH_CHARACTERS
, 3, 4, S_OK
, "\n " },
597 { CH_STARTELEMENT
, 3, 11, S_OK
, "", "Number", "Number" },
598 { CH_CHARACTERS
, 3, 16, S_OK
, "1234" },
599 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "Number", "Number" },
600 { CH_CHARACTERS
, 4, 4, S_OK
, "\n " },
601 { CH_STARTELEMENT
, 4, 9, S_OK
, "", "Name", "Name" },
602 { CH_CHARACTERS
, 4, 22, S_OK
, "Captain Ahab" },
603 { CH_ENDELEMENT
, 4, 28, S_OK
, "", "Name", "Name" },
604 { CH_CHARACTERS
, 5, 1, S_OK
, "\n" },
605 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
606 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
610 static struct call_entry content_handler_test2
[] = {
611 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
612 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
613 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
614 { CH_CHARACTERS
, 2, 14, S_OK
, "\n" },
615 { CH_CHARACTERS
, 2, 16, S_OK
, "\t" },
616 { CH_STARTELEMENT
, 3, 10, S_OK
, "", "Number", "Number" },
617 { CH_CHARACTERS
, 3, 10, S_OK
, "1234" },
618 { CH_ENDELEMENT
, 3, 16, S_OK
, "", "Number", "Number" },
619 { CH_CHARACTERS
, 3, 23, S_OK
, "\n" },
620 { CH_CHARACTERS
, 3, 25, S_OK
, "\t" },
621 { CH_STARTELEMENT
, 4, 8, S_OK
, "", "Name", "Name" },
622 { CH_CHARACTERS
, 4, 8, S_OK
, "Captain Ahab" },
623 { CH_ENDELEMENT
, 4, 22, S_OK
, "", "Name", "Name" },
624 { CH_CHARACTERS
, 4, 27, S_OK
, "\n" },
625 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
626 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
630 static struct call_entry content_handler_test2_alternate
[] = {
631 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
632 { CH_STARTDOCUMENT
, 1, 21, S_OK
},
633 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
634 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
635 { CH_CHARACTERS
, 3, 2, S_OK
, "\t" },
636 { CH_STARTELEMENT
, 3, 9, S_OK
, "", "Number", "Number" },
637 { CH_CHARACTERS
, 3, 14, S_OK
, "1234" },
638 { CH_ENDELEMENT
, 3, 22, S_OK
, "", "Number", "Number" },
639 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
640 { CH_CHARACTERS
, 4, 2, S_OK
, "\t" },
641 { CH_STARTELEMENT
, 4, 7, S_OK
, "", "Name", "Name" },
642 { CH_CHARACTERS
, 4, 20, S_OK
, "Captain Ahab" },
643 { CH_ENDELEMENT
, 4, 26, S_OK
, "", "Name", "Name" },
644 { CH_CHARACTERS
, 5, 0, S_OK
, "\n" },
645 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
646 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
650 static struct call_entry content_handler_testerror
[] = {
651 { CH_PUTDOCUMENTLOCATOR
, 0, 0, E_FAIL
},
652 { EH_FATALERROR
, 0, 0, E_FAIL
},
656 static struct call_entry content_handler_testerror_alternate
[] = {
657 { CH_PUTDOCUMENTLOCATOR
, 1, 0, E_FAIL
},
658 { EH_FATALERROR
, 1, 0, E_FAIL
},
662 static struct call_entry content_handler_test_callback_rets
[] = {
663 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_FALSE
},
664 { CH_STARTDOCUMENT
, 0, 0, S_FALSE
},
665 { EH_FATALERROR
, 0, 0, S_FALSE
},
669 static struct call_entry content_handler_test_callback_rets_alt
[] = {
670 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_FALSE
},
671 { CH_STARTDOCUMENT
, 1, 22, S_FALSE
},
672 { CH_STARTELEMENT
, 2, 13, S_FALSE
, "", "BankAccount", "BankAccount" },
673 { CH_CHARACTERS
, 3, 4, S_FALSE
, "\n " },
674 { CH_STARTELEMENT
, 3, 11, S_FALSE
, "", "Number", "Number" },
675 { CH_CHARACTERS
, 3, 16, S_FALSE
, "1234" },
676 { CH_ENDELEMENT
, 3, 24, S_FALSE
, "", "Number", "Number" },
677 { CH_CHARACTERS
, 4, 4, S_FALSE
, "\n " },
678 { CH_STARTELEMENT
, 4, 9, S_FALSE
, "", "Name", "Name" },
679 { CH_CHARACTERS
, 4, 22, S_FALSE
, "Captain Ahab" },
680 { CH_ENDELEMENT
, 4, 28, S_FALSE
, "", "Name", "Name" },
681 { CH_CHARACTERS
, 5, 1, S_FALSE
, "\n" },
682 { CH_ENDELEMENT
, 5, 14, S_FALSE
, "", "BankAccount", "BankAccount" },
683 { CH_ENDDOCUMENT
, 6, 0, S_FALSE
},
687 static struct attribute_entry ch_attributes1
[] = {
688 { "", "", "xmlns:test", "prefix_test" },
689 { "", "", "xmlns", "prefix" },
690 { "prefix_test", "arg1", "test:arg1", "arg1" },
691 { "", "arg2", "arg2", "arg2" },
692 { "prefix_test", "ar3", "test:ar3", "arg3" },
696 static struct attribute_entry ch_attributes2
[] = {
697 { "", "", "xmlns:p", "test" },
701 static struct call_entry content_handler_test_attributes
[] = {
702 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
703 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
704 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
705 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
706 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes1
},
707 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
708 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
709 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
710 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
711 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
712 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
713 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
714 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
715 { CH_ENDDOCUMENT
, 0, 0 },
719 static struct attribute_entry ch_attributes_alt_4
[] = {
720 { "prefix_test", "arg1", "test:arg1", "arg1" },
721 { "", "arg2", "arg2", "arg2" },
722 { "prefix_test", "ar3", "test:ar3", "arg3" },
723 { "", "", "xmlns:test", "prefix_test" },
724 { "", "", "xmlns", "prefix" },
728 static struct call_entry content_handler_test_attributes_alternate_4
[] = {
729 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
730 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
731 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
732 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
733 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_4
},
734 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
735 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
736 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
737 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
738 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
739 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
740 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
741 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
742 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
746 /* 'namespace' feature switched off */
747 static struct attribute_entry ch_attributes_alt_no_ns
[] = {
748 { "", "", "xmlns:test", "prefix_test" },
749 { "", "", "xmlns", "prefix" },
750 { "", "", "test:arg1", "arg1" },
751 { "", "", "arg2", "arg2" },
752 { "", "", "test:ar3", "arg3" },
756 static struct call_entry content_handler_test_attributes_alt_no_ns
[] = {
757 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
758 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
759 { CH_STARTELEMENT
, 2, 95, S_OK
, "", "", "document", ch_attributes_alt_no_ns
},
760 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
761 { CH_STARTELEMENT
, 3, 24, S_OK
, "", "", "node1", ch_attributes2
},
762 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "", "node1" },
763 { CH_ENDELEMENT
, 3, 35, S_OK
, "", "", "document" },
764 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
768 static struct attribute_entry ch_attributes_alt_6
[] = {
769 { "prefix_test", "arg1", "test:arg1", "arg1" },
770 { "", "arg2", "arg2", "arg2" },
771 { "prefix_test", "ar3", "test:ar3", "arg3" },
772 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
773 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
777 static struct attribute_entry ch_attributes2_6
[] = {
778 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
782 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
783 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
784 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
785 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
786 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
787 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
788 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
789 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
790 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
791 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
792 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
793 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
794 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
795 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
796 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
800 /* 'namespaces' is on, 'namespace-prefixes' if off */
801 static struct attribute_entry ch_attributes_no_prefix
[] = {
802 { "prefix_test", "arg1", "test:arg1", "arg1" },
803 { "", "arg2", "arg2", "arg2" },
804 { "prefix_test", "ar3", "test:ar3", "arg3" },
808 static struct call_entry content_handler_test_attributes_alt_no_prefix
[] = {
809 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
810 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
811 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
812 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
813 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
814 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
815 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
816 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", NULL
},
817 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
818 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
819 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
820 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
821 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
822 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
826 static struct call_entry content_handler_test_attributes_no_prefix
[] = {
827 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
828 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
829 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
830 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
831 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
832 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
833 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
834 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", NULL
},
835 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
836 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
837 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
838 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
839 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
840 { CH_ENDDOCUMENT
, 0, 0 },
844 static struct attribute_entry xmlspace_attrs
[] = {
845 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
849 static struct call_entry xmlspaceattr_test
[] = {
850 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
851 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
852 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
853 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
854 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
855 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
859 static struct call_entry xmlspaceattr_test_alternate
[] = {
860 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
861 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
862 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
863 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
864 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
865 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
869 /* attribute value normalization test */
870 static const char attribute_normalize
[] =
871 "<?xml version=\"1.0\" ?>\n"
872 "<a attr1=\" \r \n \tattr_value A \t \r \n\r\n \n\"/>\n";
874 static struct attribute_entry attribute_norm_attrs
[] = {
875 { "", "attr1", "attr1", " attr_value A " },
879 static struct call_entry attribute_norm
[] = {
880 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
881 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
882 { CH_STARTELEMENT
, 6, 4, S_OK
, "", "a", "a", attribute_norm_attrs
},
883 { CH_ENDELEMENT
, 6, 4, S_OK
, "", "a", "a" },
884 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
888 static struct call_entry attribute_norm_alt
[] = {
889 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
890 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
891 { CH_STARTELEMENT
, 8, 3, S_OK
, "", "a", "a", attribute_norm_attrs
},
892 { CH_ENDELEMENT
, 8, 3, S_OK
, "", "a", "a" },
893 { CH_ENDDOCUMENT
, 9, 0, S_OK
},
897 static const char xmlspace_attr
[] =
898 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
899 "<a xml:space=\"preserve\"> Some text data </a>";
901 static struct call_entry
*expectCall
;
902 static ISAXLocator
*locator
;
903 static ISAXXMLReader
*g_reader
;
906 static void set_expected_seq(struct call_entry
*expected
)
908 expectCall
= expected
;
911 /* to be called once on each tested callback return */
912 static HRESULT
get_expected_ret(void)
914 HRESULT hr
= expectCall
->ret
;
915 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
919 static HRESULT WINAPI
contentHandler_QueryInterface(
920 ISAXContentHandler
* iface
,
926 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
932 return E_NOINTERFACE
;
938 static ULONG WINAPI
contentHandler_AddRef(
939 ISAXContentHandler
* iface
)
944 static ULONG WINAPI
contentHandler_Release(
945 ISAXContentHandler
* iface
)
950 static HRESULT WINAPI
contentHandler_putDocumentLocator(
951 ISAXContentHandler
* iface
,
952 ISAXLocator
*pLocator
)
954 struct call_entry call
;
959 init_call_entry(locator
, &call
);
960 call
.id
= CH_PUTDOCUMENTLOCATOR
;
961 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
963 if (msxml_version
>= 6) {
964 ISAXAttributes
*attr
, *attr1
;
965 IMXAttributes
*mxattr
;
967 EXPECT_REF(pLocator
, 1);
968 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
970 EXPECT_REF(pLocator
, 2);
971 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
973 EXPECT_REF(pLocator
, 3);
974 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
976 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
977 EXPECT_HR(hr
, E_NOINTERFACE
);
979 ISAXAttributes_Release(attr
);
980 ISAXAttributes_Release(attr1
);
983 return get_expected_ret();
986 static ISAXAttributes
*test_attr_ptr
;
987 static HRESULT WINAPI
contentHandler_startDocument(
988 ISAXContentHandler
* iface
)
990 struct call_entry call
;
992 init_call_entry(locator
, &call
);
993 call
.id
= CH_STARTDOCUMENT
;
994 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
996 test_attr_ptr
= NULL
;
998 return get_expected_ret();
1001 static HRESULT WINAPI
contentHandler_endDocument(
1002 ISAXContentHandler
* iface
)
1004 struct call_entry call
;
1006 init_call_entry(locator
, &call
);
1007 call
.id
= CH_ENDDOCUMENT
;
1008 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1010 return get_expected_ret();
1013 static HRESULT WINAPI
contentHandler_startPrefixMapping(
1014 ISAXContentHandler
* iface
,
1015 const WCHAR
*prefix
, int prefix_len
,
1016 const WCHAR
*uri
, int uri_len
)
1018 struct call_entry call
;
1020 init_call_entry(locator
, &call
);
1021 call
.id
= CH_STARTPREFIXMAPPING
;
1022 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
1023 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
1024 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1026 return get_expected_ret();
1029 static HRESULT WINAPI
contentHandler_endPrefixMapping(
1030 ISAXContentHandler
* iface
,
1031 const WCHAR
*prefix
, int len
)
1033 struct call_entry call
;
1035 init_call_entry(locator
, &call
);
1036 call
.id
= CH_ENDPREFIXMAPPING
;
1037 call
.arg1W
= SysAllocStringLen(prefix
, len
);
1038 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1040 return get_expected_ret();
1043 static HRESULT WINAPI
contentHandler_startElement(
1044 ISAXContentHandler
* iface
,
1045 const WCHAR
*uri
, int uri_len
,
1046 const WCHAR
*localname
, int local_len
,
1047 const WCHAR
*qname
, int qname_len
,
1048 ISAXAttributes
*saxattr
)
1050 struct call_entry call
;
1051 IMXAttributes
*mxattr
;
1055 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
1056 EXPECT_HR(hr
, E_NOINTERFACE
);
1058 init_call_entry(locator
, &call
);
1059 call
.id
= CH_STARTELEMENT
;
1060 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1061 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1062 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1065 test_attr_ptr
= saxattr
;
1066 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
1068 /* store actual attributes */
1070 hr
= ISAXAttributes_getLength(saxattr
, &len
);
1071 EXPECT_HR(hr
, S_OK
);
1078 struct attribute_entry
*attr
;
1079 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
1082 hr
= ISAXXMLReader_getFeature(g_reader
, _bstr_("http://xml.org/sax/features/namespaces"), &v
);
1083 EXPECT_HR(hr
, S_OK
);
1085 for (i
= 0; i
< len
; i
++)
1090 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
1091 &localname
, &local_len
, &qname
, &qname_len
);
1092 EXPECT_HR(hr
, S_OK
);
1094 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
1095 EXPECT_HR(hr
, S_OK
);
1097 /* if 'namespaces' switched off uri and local name contains garbage */
1098 if (v
== VARIANT_FALSE
&& msxml_version
> 0)
1100 attr
[i
].uriW
= SysAllocStringLen(NULL
, 0);
1101 attr
[i
].localW
= SysAllocStringLen(NULL
, 0);
1105 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
1106 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
1109 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
1110 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
1113 call
.attributes
= attr
;
1114 call
.attr_count
= len
;
1117 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1119 return get_expected_ret();
1122 static HRESULT WINAPI
contentHandler_endElement(
1123 ISAXContentHandler
* iface
,
1124 const WCHAR
*uri
, int uri_len
,
1125 const WCHAR
*localname
, int local_len
,
1126 const WCHAR
*qname
, int qname_len
)
1128 struct call_entry call
;
1130 init_call_entry(locator
, &call
);
1131 call
.id
= CH_ENDELEMENT
;
1132 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1133 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1134 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1135 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1137 return get_expected_ret();
1140 static HRESULT WINAPI
contentHandler_characters(
1141 ISAXContentHandler
* iface
,
1145 struct call_entry call
;
1147 init_call_entry(locator
, &call
);
1148 call
.id
= CH_CHARACTERS
;
1149 call
.arg1W
= SysAllocStringLen(chars
, len
);
1150 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1152 return get_expected_ret();
1155 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1156 ISAXContentHandler
* iface
,
1157 const WCHAR
*chars
, int len
)
1159 struct call_entry call
;
1161 init_call_entry(locator
, &call
);
1162 call
.id
= CH_IGNORABLEWHITESPACE
;
1163 call
.arg1W
= SysAllocStringLen(chars
, len
);
1164 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1166 return get_expected_ret();
1169 static HRESULT WINAPI
contentHandler_processingInstruction(
1170 ISAXContentHandler
* iface
,
1171 const WCHAR
*target
, int target_len
,
1172 const WCHAR
*data
, int data_len
)
1174 struct call_entry call
;
1176 init_call_entry(locator
, &call
);
1177 call
.id
= CH_PROCESSINGINSTRUCTION
;
1178 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1179 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1180 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1182 return get_expected_ret();
1185 static HRESULT WINAPI
contentHandler_skippedEntity(
1186 ISAXContentHandler
* iface
,
1187 const WCHAR
*name
, int len
)
1189 struct call_entry call
;
1191 init_call_entry(locator
, &call
);
1192 call
.id
= CH_SKIPPEDENTITY
;
1193 call
.arg1W
= SysAllocStringLen(name
, len
);
1195 return get_expected_ret();
1198 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1200 contentHandler_QueryInterface
,
1201 contentHandler_AddRef
,
1202 contentHandler_Release
,
1203 contentHandler_putDocumentLocator
,
1204 contentHandler_startDocument
,
1205 contentHandler_endDocument
,
1206 contentHandler_startPrefixMapping
,
1207 contentHandler_endPrefixMapping
,
1208 contentHandler_startElement
,
1209 contentHandler_endElement
,
1210 contentHandler_characters
,
1211 contentHandler_ignorableWhitespace
,
1212 contentHandler_processingInstruction
,
1213 contentHandler_skippedEntity
1216 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1218 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1219 ISAXErrorHandler
* iface
,
1225 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1231 return E_NOINTERFACE
;
1237 static ULONG WINAPI
isaxerrorHandler_AddRef(
1238 ISAXErrorHandler
* iface
)
1243 static ULONG WINAPI
isaxerrorHandler_Release(
1244 ISAXErrorHandler
* iface
)
1249 static HRESULT WINAPI
isaxerrorHandler_error(
1250 ISAXErrorHandler
* iface
,
1251 ISAXLocator
*pLocator
,
1252 const WCHAR
*pErrorMessage
,
1253 HRESULT hrErrorCode
)
1255 ok(0, "unexpected call\n");
1259 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1260 ISAXErrorHandler
* iface
,
1261 ISAXLocator
*pLocator
,
1262 const WCHAR
*message
,
1265 struct call_entry call
;
1267 init_call_entry(locator
, &call
);
1268 call
.id
= EH_FATALERROR
;
1271 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1277 static HRESULT WINAPI
isaxerrorHanddler_ignorableWarning(
1278 ISAXErrorHandler
* iface
,
1279 ISAXLocator
*pLocator
,
1280 const WCHAR
*pErrorMessage
,
1281 HRESULT hrErrorCode
)
1283 ok(0, "unexpected call\n");
1287 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1289 isaxerrorHandler_QueryInterface
,
1290 isaxerrorHandler_AddRef
,
1291 isaxerrorHandler_Release
,
1292 isaxerrorHandler_error
,
1293 isaxerrorHandler_fatalError
,
1294 isaxerrorHanddler_ignorableWarning
1297 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1299 static HRESULT WINAPI
isaxattributes_QueryInterface(
1300 ISAXAttributes
* iface
,
1306 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1312 return E_NOINTERFACE
;
1318 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1323 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1328 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1334 static HRESULT WINAPI
isaxattributes_getURI(
1335 ISAXAttributes
* iface
,
1340 ok(0, "unexpected call\n");
1344 static HRESULT WINAPI
isaxattributes_getLocalName(
1345 ISAXAttributes
* iface
,
1347 const WCHAR
**pLocalName
,
1348 int *pLocalNameLength
)
1350 ok(0, "unexpected call\n");
1354 static HRESULT WINAPI
isaxattributes_getQName(
1355 ISAXAttributes
* iface
,
1357 const WCHAR
**QName
,
1360 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1361 {'a','t','t','r','2','j','u','n','k',0},
1362 {'a','t','t','r','3',0}};
1363 static const int attrqnamelen
[] = {7, 5, 5};
1365 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1367 *QName
= attrqnamesW
[index
];
1368 *QNameLength
= attrqnamelen
[index
];
1373 static HRESULT WINAPI
isaxattributes_getName(
1374 ISAXAttributes
* iface
,
1378 const WCHAR
** pLocalName
,
1379 int * pLocalNameSize
,
1380 const WCHAR
** pQName
,
1383 ok(0, "unexpected call\n");
1387 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1388 ISAXAttributes
* iface
,
1391 const WCHAR
* pLocalName
,
1392 int cocalNameLength
,
1395 ok(0, "unexpected call\n");
1399 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1400 ISAXAttributes
* iface
,
1401 const WCHAR
* pQName
,
1405 ok(0, "unexpected call\n");
1409 static HRESULT WINAPI
isaxattributes_getType(
1410 ISAXAttributes
* iface
,
1412 const WCHAR
** pType
,
1415 ok(0, "unexpected call\n");
1419 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1420 ISAXAttributes
* iface
,
1423 const WCHAR
* pLocalName
,
1425 const WCHAR
** pType
,
1428 ok(0, "unexpected call\n");
1432 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1433 ISAXAttributes
* iface
,
1434 const WCHAR
* pQName
,
1436 const WCHAR
** pType
,
1439 ok(0, "unexpected call\n");
1443 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1444 const WCHAR
**value
, int *nValue
)
1446 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1447 {'a','2','j','u','n','k',0},
1448 {'<','&','"','>',0}};
1449 static const int attrvalueslen
[] = {2, 2, 4};
1451 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1453 *value
= attrvaluesW
[index
];
1454 *nValue
= attrvalueslen
[index
];
1459 static HRESULT WINAPI
isaxattributes_getValueFromName(
1460 ISAXAttributes
* iface
,
1463 const WCHAR
* pLocalName
,
1465 const WCHAR
** pValue
,
1468 ok(0, "unexpected call\n");
1472 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1473 ISAXAttributes
* iface
,
1474 const WCHAR
* pQName
,
1476 const WCHAR
** pValue
,
1479 ok(0, "unexpected call\n");
1483 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1485 isaxattributes_QueryInterface
,
1486 isaxattributes_AddRef
,
1487 isaxattributes_Release
,
1488 isaxattributes_getLength
,
1489 isaxattributes_getURI
,
1490 isaxattributes_getLocalName
,
1491 isaxattributes_getQName
,
1492 isaxattributes_getName
,
1493 isaxattributes_getIndexFromName
,
1494 isaxattributes_getIndexFromQName
,
1495 isaxattributes_getType
,
1496 isaxattributes_getTypeFromName
,
1497 isaxattributes_getTypeFromQName
,
1498 isaxattributes_getValue
,
1499 isaxattributes_getValueFromName
,
1500 isaxattributes_getValueFromQName
1503 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1505 struct saxlexicalhandler
1507 ISAXLexicalHandler ISAXLexicalHandler_iface
;
1510 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1513 static inline struct saxlexicalhandler
*impl_from_ISAXLexicalHandler( ISAXLexicalHandler
*iface
)
1515 return CONTAINING_RECORD(iface
, struct saxlexicalhandler
, ISAXLexicalHandler_iface
);
1518 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **out
)
1520 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1524 if (IsEqualGUID(riid
, &IID_IUnknown
))
1527 ok(0, "got unexpected IID_IUnknown query\n");
1529 else if (IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1531 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1536 ISAXLexicalHandler_AddRef(iface
);
1538 return E_NOINTERFACE
;
1543 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1545 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1546 return InterlockedIncrement(&handler
->ref
);
1549 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1551 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1552 return InterlockedDecrement(&handler
->ref
);
1555 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1556 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1557 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1559 ok(0, "call not expected\n");
1563 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1565 ok(0, "call not expected\n");
1569 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1570 const WCHAR
* pName
, int nName
)
1572 ok(0, "call not expected\n");
1576 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1577 const WCHAR
* pName
, int nName
)
1579 ok(0, "call not expected\n");
1583 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1585 ok(0, "call not expected\n");
1589 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1591 ok(0, "call not expected\n");
1595 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1596 const WCHAR
* pChars
, int nChars
)
1598 ok(0, "call not expected\n");
1602 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1604 isaxlexical_QueryInterface
,
1606 isaxlexical_Release
,
1607 isaxlexical_startDTD
,
1609 isaxlexical_startEntity
,
1610 isaxlexical_endEntity
,
1611 isaxlexical_startCDATA
,
1612 isaxlexical_endCDATA
,
1616 static void init_saxlexicalhandler(struct saxlexicalhandler
*handler
, HRESULT hr
)
1618 handler
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1620 handler
->qi_hr
= hr
;
1623 struct saxdeclhandler
1625 ISAXDeclHandler ISAXDeclHandler_iface
;
1628 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1631 static inline struct saxdeclhandler
*impl_from_ISAXDeclHandler( ISAXDeclHandler
*iface
)
1633 return CONTAINING_RECORD(iface
, struct saxdeclhandler
, ISAXDeclHandler_iface
);
1636 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **out
)
1638 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1642 if (IsEqualGUID(riid
, &IID_IUnknown
))
1645 ok(0, "got unexpected IID_IUnknown query\n");
1647 else if (IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1649 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1654 ISAXDeclHandler_AddRef(iface
);
1656 return E_NOINTERFACE
;
1661 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1663 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1664 return InterlockedIncrement(&handler
->ref
);
1667 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1669 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1670 return InterlockedDecrement(&handler
->ref
);
1673 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1674 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1676 ok(0, "call not expected\n");
1680 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1681 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1682 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1683 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1685 ok(0, "call not expected\n");
1689 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1690 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1692 ok(0, "call not expected\n");
1696 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1697 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1698 const WCHAR
* pSystemId
, int nSystemId
)
1700 ok(0, "call not expected\n");
1704 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1706 isaxdecl_QueryInterface
,
1709 isaxdecl_elementDecl
,
1710 isaxdecl_attributeDecl
,
1711 isaxdecl_internalEntityDecl
,
1712 isaxdecl_externalEntityDecl
1715 static void init_saxdeclhandler(struct saxdeclhandler
*handler
, HRESULT hr
)
1717 handler
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1719 handler
->qi_hr
= hr
;
1722 typedef struct mxwriter_write_test_t
{
1728 } mxwriter_write_test
;
1730 typedef struct mxwriter_stream_test_t
{
1732 const char *encoding
;
1733 mxwriter_write_test expected_writes
[4];
1734 } mxwriter_stream_test
;
1736 static const mxwriter_write_test
*current_write_test
;
1737 static DWORD current_stream_test_index
;
1739 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1743 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1746 return E_NOINTERFACE
;
1751 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1756 static ULONG WINAPI
istream_Release(IStream
*iface
)
1761 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1763 ok(0, "unexpected call\n");
1767 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1771 ok(pv
!= NULL
, "pv == NULL\n");
1773 if(current_write_test
->last
) {
1774 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
1778 fail
= current_write_test
->fail_write
;
1780 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
1781 current_write_test
->cb
, cb
, current_stream_test_index
);
1784 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
1786 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
1788 ++current_write_test
;
1793 return fail
? E_FAIL
: S_OK
;
1796 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1797 ULARGE_INTEGER
*plibNewPosition
)
1799 ok(0, "unexpected call\n");
1803 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1805 ok(0, "unexpected call\n");
1809 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1810 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1812 ok(0, "unexpected call\n");
1816 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1818 ok(0, "unexpected call\n");
1822 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1824 ok(0, "unexpected call\n");
1828 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1829 ULARGE_INTEGER cb
, DWORD dwLockType
)
1831 ok(0, "unexpected call\n");
1835 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1836 ULARGE_INTEGER cb
, DWORD dwLockType
)
1838 ok(0, "unexpected call\n");
1842 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1844 ok(0, "unexpected call\n");
1848 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1850 ok(0, "unexpected call\n");
1854 static const IStreamVtbl StreamVtbl
= {
1855 istream_QueryInterface
,
1866 istream_UnlockRegion
,
1871 static IStream mxstream
= { &StreamVtbl
};
1873 static struct msxmlsupported_data_t reader_support_data
[] =
1875 { &CLSID_SAXXMLReader
, "SAXReader" },
1876 { &CLSID_SAXXMLReader30
, "SAXReader30" },
1877 { &CLSID_SAXXMLReader40
, "SAXReader40" },
1878 { &CLSID_SAXXMLReader60
, "SAXReader60" },
1882 static void test_saxreader(void)
1884 const struct msxmlsupported_data_t
*table
= reader_support_data
;
1886 ISAXXMLReader
*reader
= NULL
;
1888 ISAXContentHandler
*content
;
1889 ISAXErrorHandler
*lpErrorHandler
;
1891 SAFEARRAYBOUND SADim
[1];
1894 ULARGE_INTEGER size
;
1898 static const CHAR testXmlA
[] = "test.xml";
1899 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
1900 IXMLDOMDocument
*doc
;
1903 while (table
->clsid
)
1905 struct call_entry
*test_seq
;
1908 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
1914 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
1915 EXPECT_HR(hr
, S_OK
);
1918 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
1920 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1925 /* crashes on old versions */
1926 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
1927 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1929 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
1930 EXPECT_HR(hr
, E_POINTER
);
1932 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
1933 EXPECT_HR(hr
, E_POINTER
);
1936 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
1937 EXPECT_HR(hr
, S_OK
);
1938 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
1940 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
1941 EXPECT_HR(hr
, S_OK
);
1942 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
1944 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
1945 EXPECT_HR(hr
, S_OK
);
1947 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
1948 EXPECT_HR(hr
, S_OK
);
1950 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
1951 EXPECT_HR(hr
, S_OK
);
1953 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
1954 EXPECT_HR(hr
, S_OK
);
1955 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
1957 V_VT(&var
) = VT_BSTR
;
1958 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
1960 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1961 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1962 test_seq
= content_handler_test1_alternate
;
1964 test_seq
= content_handler_test1
;
1965 set_expected_seq(test_seq
);
1966 hr
= ISAXXMLReader_parse(reader
, var
);
1967 EXPECT_HR(hr
, S_OK
);
1968 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
1972 SADim
[0].lLbound
= 0;
1973 SADim
[0].cElements
= sizeof(testXML
)-1;
1974 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
1975 SafeArrayAccessData(sa
, (void**)&ptr
);
1976 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
1977 SafeArrayUnaccessData(sa
);
1978 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
1981 set_expected_seq(test_seq
);
1982 hr
= ISAXXMLReader_parse(reader
, var
);
1983 EXPECT_HR(hr
, S_OK
);
1984 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from safe array", FALSE
);
1986 SafeArrayDestroy(sa
);
1988 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1989 size
.QuadPart
= strlen(testXML
);
1990 IStream_SetSize(stream
, size
);
1991 IStream_Write(stream
, testXML
, strlen(testXML
), &written
);
1993 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
1994 V_VT(&var
) = VT_UNKNOWN
;
1995 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
1997 set_expected_seq(test_seq
);
1998 hr
= ISAXXMLReader_parse(reader
, var
);
1999 EXPECT_HR(hr
, S_OK
);
2000 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
2002 IStream_Release(stream
);
2004 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2005 size
.QuadPart
= strlen(test_attributes
);
2006 IStream_SetSize(stream
, size
);
2007 IStream_Write(stream
, test_attributes
, strlen(test_attributes
), &written
);
2009 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2010 V_VT(&var
) = VT_UNKNOWN
;
2011 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2013 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2014 test_seq
= content_handler_test_attributes_alternate_4
;
2015 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2016 test_seq
= content_handler_test_attributes_alternate_6
;
2018 test_seq
= content_handler_test_attributes
;
2020 set_expected_seq(test_seq
);
2021 hr
= ISAXXMLReader_parse(reader
, var
);
2022 EXPECT_HR(hr
, S_OK
);
2024 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2025 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2026 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2028 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2030 IStream_Release(stream
);
2032 V_VT(&var
) = VT_BSTR
;
2033 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
2035 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2036 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2037 test_seq
= content_handler_test2_alternate
;
2039 test_seq
= content_handler_test2
;
2041 set_expected_seq(test_seq
);
2042 hr
= ISAXXMLReader_parse(reader
, var
);
2043 EXPECT_HR(hr
, S_OK
);
2044 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
2049 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2050 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2051 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
2054 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2055 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2056 test_seq
= content_handler_test1_alternate
;
2058 test_seq
= content_handler_test1
;
2059 set_expected_seq(test_seq
);
2060 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2061 EXPECT_HR(hr
, S_OK
);
2062 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
2065 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2066 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2067 test_seq
= content_handler_testerror_alternate
;
2069 test_seq
= content_handler_testerror
;
2070 set_expected_seq(test_seq
);
2071 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2072 EXPECT_HR(hr
, E_FAIL
);
2073 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
2075 /* callback ret values */
2076 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2077 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2079 test_seq
= content_handler_test_callback_rets_alt
;
2080 set_expected_seq(test_seq
);
2081 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2082 EXPECT_HR(hr
, S_OK
);
2086 test_seq
= content_handler_test_callback_rets
;
2087 set_expected_seq(test_seq
);
2088 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2089 EXPECT_HR(hr
, S_FALSE
);
2091 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
2093 DeleteFileA(testXmlA
);
2095 /* parse from IXMLDOMDocument */
2096 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
2097 &IID_IXMLDOMDocument
, (void**)&doc
);
2098 EXPECT_HR(hr
, S_OK
);
2100 str
= SysAllocString(szSimpleXML
);
2101 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
2102 EXPECT_HR(hr
, S_OK
);
2105 V_VT(&var
) = VT_UNKNOWN
;
2106 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
2108 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2109 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2110 test_seq
= content_handler_test2_alternate
;
2112 test_seq
= content_handler_test2
;
2114 set_expected_seq(test_seq
);
2115 hr
= ISAXXMLReader_parse(reader
, var
);
2116 EXPECT_HR(hr
, S_OK
);
2117 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
2118 IXMLDOMDocument_Release(doc
);
2120 /* xml:space test */
2121 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2122 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2124 test_seq
= xmlspaceattr_test_alternate
;
2127 test_seq
= xmlspaceattr_test
;
2129 set_expected_seq(test_seq
);
2130 V_VT(&var
) = VT_BSTR
;
2131 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
2132 hr
= ISAXXMLReader_parse(reader
, var
);
2133 EXPECT_HR(hr
, S_OK
);
2135 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2136 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2138 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
2141 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
2143 /* switch off 'namespaces' feature */
2144 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE
);
2145 EXPECT_HR(hr
, S_OK
);
2147 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2148 size
.QuadPart
= strlen(test_attributes
);
2149 IStream_SetSize(stream
, size
);
2150 IStream_Write(stream
, test_attributes
, strlen(test_attributes
), &written
);
2152 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2153 V_VT(&var
) = VT_UNKNOWN
;
2154 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2156 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2157 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2159 test_seq
= content_handler_test_attributes_alt_no_ns
;
2162 test_seq
= content_handler_test_attributes
;
2164 set_expected_seq(test_seq
);
2165 hr
= ISAXXMLReader_parse(reader
, var
);
2166 EXPECT_HR(hr
, S_OK
);
2167 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2168 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_TRUE
);
2169 EXPECT_HR(hr
, S_OK
);
2171 /* switch off 'namespace-prefixes' feature */
2172 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_FALSE
);
2173 EXPECT_HR(hr
, S_OK
);
2175 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2176 size
.QuadPart
= strlen(test_attributes
);
2177 IStream_SetSize(stream
, size
);
2178 IStream_Write(stream
, test_attributes
, strlen(test_attributes
), &written
);
2180 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2181 V_VT(&var
) = VT_UNKNOWN
;
2182 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2184 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2185 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2187 test_seq
= content_handler_test_attributes_alt_no_prefix
;
2190 test_seq
= content_handler_test_attributes_no_prefix
;
2192 set_expected_seq(test_seq
);
2193 hr
= ISAXXMLReader_parse(reader
, var
);
2194 EXPECT_HR(hr
, S_OK
);
2195 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2197 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_TRUE
);
2198 EXPECT_HR(hr
, S_OK
);
2200 /* attribute normalization */
2201 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2202 size
.QuadPart
= strlen(attribute_normalize
);
2203 IStream_SetSize(stream
, size
);
2204 IStream_Write(stream
, attribute_normalize
, strlen(attribute_normalize
), &written
);
2206 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2207 V_VT(&var
) = VT_UNKNOWN
;
2208 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2210 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2211 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2213 test_seq
= attribute_norm_alt
;
2216 test_seq
= attribute_norm
;
2218 set_expected_seq(test_seq
);
2219 hr
= ISAXXMLReader_parse(reader
, var
);
2220 EXPECT_HR(hr
, S_OK
);
2221 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "attribute value normalization", TRUE
);
2223 ISAXXMLReader_Release(reader
);
2230 struct saxreader_props_test_t
2232 const char *prop_name
;
2236 static struct saxlexicalhandler lexicalhandler
;
2237 static struct saxdeclhandler declhandler
;
2239 static const struct saxreader_props_test_t props_test_data
[] = {
2240 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
},
2241 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&declhandler
.ISAXDeclHandler_iface
},
2245 static void test_saxreader_properties(void)
2247 const struct saxreader_props_test_t
*ptr
= props_test_data
;
2248 ISAXXMLReader
*reader
;
2251 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2252 &IID_ISAXXMLReader
, (void**)&reader
);
2253 EXPECT_HR(hr
, S_OK
);
2255 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
2256 EXPECT_HR(hr
, E_POINTER
);
2258 while (ptr
->prop_name
)
2263 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2264 init_saxdeclhandler(&declhandler
, S_OK
);
2266 V_VT(&v
) = VT_EMPTY
;
2267 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2268 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2269 EXPECT_HR(hr
, S_OK
);
2270 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2271 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2273 V_VT(&v
) = VT_UNKNOWN
;
2274 V_UNKNOWN(&v
) = ptr
->iface
;
2275 ref
= get_refcount(ptr
->iface
);
2276 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2277 EXPECT_HR(hr
, S_OK
);
2278 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2280 V_VT(&v
) = VT_EMPTY
;
2281 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2283 ref
= get_refcount(ptr
->iface
);
2284 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2285 EXPECT_HR(hr
, S_OK
);
2286 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2287 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2288 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2291 V_VT(&v
) = VT_EMPTY
;
2292 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2293 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2294 EXPECT_HR(hr
, S_OK
);
2296 V_VT(&v
) = VT_EMPTY
;
2297 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2298 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2299 EXPECT_HR(hr
, S_OK
);
2300 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2301 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2303 V_VT(&v
) = VT_UNKNOWN
;
2304 V_UNKNOWN(&v
) = ptr
->iface
;
2305 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2306 EXPECT_HR(hr
, S_OK
);
2308 /* only VT_EMPTY seems to be valid to reset property */
2310 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2311 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2312 EXPECT_HR(hr
, E_INVALIDARG
);
2314 V_VT(&v
) = VT_EMPTY
;
2315 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2316 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2317 EXPECT_HR(hr
, S_OK
);
2318 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2319 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2322 V_VT(&v
) = VT_UNKNOWN
;
2323 V_UNKNOWN(&v
) = NULL
;
2324 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2325 EXPECT_HR(hr
, S_OK
);
2327 V_VT(&v
) = VT_EMPTY
;
2328 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2329 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2330 EXPECT_HR(hr
, S_OK
);
2331 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2332 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2334 /* block QueryInterface on handler riid */
2335 init_saxlexicalhandler(&lexicalhandler
, E_NOINTERFACE
);
2336 init_saxdeclhandler(&declhandler
, E_NOINTERFACE
);
2338 V_VT(&v
) = VT_UNKNOWN
;
2339 V_UNKNOWN(&v
) = ptr
->iface
;
2340 EXPECT_REF(ptr
->iface
, 1);
2341 ref
= get_refcount(ptr
->iface
);
2342 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2343 EXPECT_HR(hr
, E_NOINTERFACE
);
2344 EXPECT_REF(ptr
->iface
, 1);
2349 ISAXXMLReader_Release(reader
);
2353 struct feature_ns_entry_t
{
2357 VARIANT_BOOL value2
; /* feature value after feature set to 0xc */
2360 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2361 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
, VARIANT_FALSE
},
2362 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
, VARIANT_FALSE
},
2363 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
, VARIANT_TRUE
},
2364 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
, VARIANT_TRUE
},
2368 static const char *feature_names
[] = {
2369 "http://xml.org/sax/features/namespaces",
2370 "http://xml.org/sax/features/namespace-prefixes",
2374 static void test_saxreader_features(void)
2376 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2377 ISAXXMLReader
*reader
;
2385 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2388 win_skip("can't create %s instance\n", entry
->clsid
);
2393 name
= feature_names
;
2397 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2398 EXPECT_HR(hr
, S_OK
);
2399 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2402 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), value
);
2403 EXPECT_HR(hr
, S_OK
);
2406 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2407 EXPECT_HR(hr
, S_OK
);
2408 ok(entry
->value2
== value
, "%s: got wrong value %x, expected %x\n", entry
->clsid
, value
, entry
->value2
);
2410 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_FALSE
);
2411 EXPECT_HR(hr
, S_OK
);
2413 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2414 EXPECT_HR(hr
, S_OK
);
2415 ok(value
== VARIANT_FALSE
, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry
->clsid
, value
);
2417 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_TRUE
);
2418 EXPECT_HR(hr
, S_OK
);
2420 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2421 EXPECT_HR(hr
, S_OK
);
2422 ok(value
== VARIANT_TRUE
, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry
->clsid
, value
);
2427 ISAXXMLReader_Release(reader
);
2433 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2434 static const CHAR UTF8BOMTest
[] =
2435 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2438 struct enc_test_entry_t
{
2446 static const struct enc_test_entry_t encoding_test_data
[] = {
2447 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, 1 },
2448 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, 1 },
2449 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, 0 },
2450 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, 0 },
2454 static void test_saxreader_encoding(void)
2456 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2457 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2458 static const CHAR testXmlA
[] = "test.xml";
2462 ISAXXMLReader
*reader
;
2468 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2471 win_skip("can't create %s instance\n", entry
->clsid
);
2476 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2477 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2478 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2481 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2483 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2485 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2487 DeleteFileA(testXmlA
);
2489 /* try BSTR input with no BOM or '<?xml' instruction */
2490 V_VT(&input
) = VT_BSTR
;
2491 V_BSTR(&input
) = _bstr_("<element></element>");
2492 hr
= ISAXXMLReader_parse(reader
, input
);
2493 EXPECT_HR(hr
, S_OK
);
2495 ISAXXMLReader_Release(reader
);
2502 static void test_mxwriter_handlers(void)
2504 ISAXContentHandler
*handler
;
2505 IMXWriter
*writer
, *writer2
;
2506 ISAXDeclHandler
*decl
;
2507 ISAXLexicalHandler
*lh
;
2510 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2511 &IID_IMXWriter
, (void**)&writer
);
2512 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2514 EXPECT_REF(writer
, 1);
2516 /* ISAXContentHandler */
2517 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&handler
);
2518 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2519 EXPECT_REF(writer
, 2);
2520 EXPECT_REF(handler
, 2);
2522 hr
= ISAXContentHandler_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2523 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2524 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2525 EXPECT_REF(writer
, 3);
2526 EXPECT_REF(writer2
, 3);
2527 IMXWriter_Release(writer2
);
2528 ISAXContentHandler_Release(handler
);
2530 /* ISAXLexicalHandler */
2531 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lh
);
2532 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2533 EXPECT_REF(writer
, 2);
2536 hr
= ISAXLexicalHandler_QueryInterface(lh
, &IID_IMXWriter
, (void**)&writer2
);
2537 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2538 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2539 EXPECT_REF(writer
, 3);
2540 EXPECT_REF(writer2
, 3);
2541 IMXWriter_Release(writer2
);
2542 ISAXLexicalHandler_Release(lh
);
2544 /* ISAXDeclHandler */
2545 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
2546 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2547 EXPECT_REF(writer
, 2);
2550 hr
= ISAXDeclHandler_QueryInterface(decl
, &IID_IMXWriter
, (void**)&writer2
);
2551 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2552 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2553 EXPECT_REF(writer
, 3);
2554 EXPECT_REF(writer2
, 3);
2555 IMXWriter_Release(writer2
);
2556 ISAXDeclHandler_Release(decl
);
2558 IMXWriter_Release(writer
);
2562 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2564 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2565 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2566 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2567 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2571 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2573 { &CLSID_SAXAttributes
, "SAXAttributes" },
2574 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2575 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2576 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2580 struct mxwriter_props_t
2584 VARIANT_BOOL disable_escape
;
2585 VARIANT_BOOL indent
;
2586 VARIANT_BOOL omitdecl
;
2587 VARIANT_BOOL standalone
;
2588 const char *encoding
;
2591 static const struct mxwriter_props_t mxwriter_default_props
[] =
2593 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2594 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2595 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2596 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2600 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2604 while (table
->clsid
)
2611 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2618 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2619 &IID_IMXWriter
, (void**)&writer
);
2620 EXPECT_HR(hr
, S_OK
);
2623 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
2624 EXPECT_HR(hr
, S_OK
);
2625 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
2627 b
= !table
->disable_escape
;
2628 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
2629 EXPECT_HR(hr
, S_OK
);
2630 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
2631 table
->disable_escape
);
2634 hr
= IMXWriter_get_indent(writer
, &b
);
2635 EXPECT_HR(hr
, S_OK
);
2636 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
2638 b
= !table
->omitdecl
;
2639 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
2640 EXPECT_HR(hr
, S_OK
);
2641 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
2643 b
= !table
->standalone
;
2644 hr
= IMXWriter_get_standalone(writer
, &b
);
2645 EXPECT_HR(hr
, S_OK
);
2646 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
2648 hr
= IMXWriter_get_encoding(writer
, &encoding
);
2649 EXPECT_HR(hr
, S_OK
);
2650 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
2651 i
, wine_dbgstr_w(encoding
), table
->encoding
);
2652 SysFreeString(encoding
);
2654 IMXWriter_Release(writer
);
2661 static void test_mxwriter_properties(void)
2663 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
2664 static const WCHAR emptyW
[] = {0};
2665 static const WCHAR testW
[] = {'t','e','s','t',0};
2666 ISAXContentHandler
*content
;
2673 test_mxwriter_default_properties(mxwriter_default_props
);
2675 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2676 &IID_IMXWriter
, (void**)&writer
);
2677 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2679 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
2680 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2682 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
2683 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2685 hr
= IMXWriter_get_indent(writer
, NULL
);
2686 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2688 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
2689 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2691 hr
= IMXWriter_get_standalone(writer
, NULL
);
2692 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2695 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
2696 ok(hr
== S_OK
, "got %08x\n", hr
);
2699 hr
= IMXWriter_get_standalone(writer
, &b
);
2700 ok(hr
== S_OK
, "got %08x\n", hr
);
2701 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
2703 hr
= IMXWriter_get_encoding(writer
, NULL
);
2704 EXPECT_HR(hr
, E_POINTER
);
2706 /* UTF-16 is a default setting apparently */
2707 str
= (void*)0xdeadbeef;
2708 hr
= IMXWriter_get_encoding(writer
, &str
);
2709 EXPECT_HR(hr
, S_OK
);
2710 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
2712 str2
= (void*)0xdeadbeef;
2713 hr
= IMXWriter_get_encoding(writer
, &str2
);
2714 ok(hr
== S_OK
, "got %08x\n", hr
);
2715 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
2717 SysFreeString(str2
);
2720 /* put empty string */
2721 str
= SysAllocString(emptyW
);
2722 hr
= IMXWriter_put_encoding(writer
, str
);
2723 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2726 str
= (void*)0xdeadbeef;
2727 hr
= IMXWriter_get_encoding(writer
, &str
);
2728 EXPECT_HR(hr
, S_OK
);
2729 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
2732 /* invalid encoding name */
2733 str
= SysAllocString(testW
);
2734 hr
= IMXWriter_put_encoding(writer
, str
);
2735 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2738 /* test case sensivity */
2739 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
2740 EXPECT_HR(hr
, S_OK
);
2741 str
= (void*)0xdeadbeef;
2742 hr
= IMXWriter_get_encoding(writer
, &str
);
2743 EXPECT_HR(hr
, S_OK
);
2744 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
2747 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
2748 EXPECT_HR(hr
, S_OK
);
2749 str
= (void*)0xdeadbeef;
2750 hr
= IMXWriter_get_encoding(writer
, &str
);
2751 EXPECT_HR(hr
, S_OK
);
2752 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
2755 /* how it affects document creation */
2756 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2757 EXPECT_HR(hr
, S_OK
);
2759 hr
= ISAXContentHandler_startDocument(content
);
2760 EXPECT_HR(hr
, S_OK
);
2761 hr
= ISAXContentHandler_endDocument(content
);
2762 EXPECT_HR(hr
, S_OK
);
2764 V_VT(&dest
) = VT_EMPTY
;
2765 hr
= IMXWriter_get_output(writer
, &dest
);
2766 EXPECT_HR(hr
, S_OK
);
2767 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2768 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
2769 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2770 VariantClear(&dest
);
2771 ISAXContentHandler_Release(content
);
2773 hr
= IMXWriter_get_version(writer
, NULL
);
2774 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2775 /* default version is 'surprisingly' 1.0 */
2776 hr
= IMXWriter_get_version(writer
, &str
);
2777 ok(hr
== S_OK
, "got %08x\n", hr
);
2778 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
2781 /* store version string as is */
2782 hr
= IMXWriter_put_version(writer
, NULL
);
2783 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2785 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
2786 ok(hr
== S_OK
, "got %08x\n", hr
);
2788 hr
= IMXWriter_put_version(writer
, _bstr_(""));
2789 ok(hr
== S_OK
, "got %08x\n", hr
);
2790 hr
= IMXWriter_get_version(writer
, &str
);
2791 ok(hr
== S_OK
, "got %08x\n", hr
);
2792 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
2795 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
2796 ok(hr
== S_OK
, "got %08x\n", hr
);
2797 hr
= IMXWriter_get_version(writer
, &str
);
2798 ok(hr
== S_OK
, "got %08x\n", hr
);
2799 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
2802 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
2803 ok(hr
== S_OK
, "got %08x\n", hr
);
2804 hr
= IMXWriter_get_version(writer
, &str
);
2805 ok(hr
== S_OK
, "got %08x\n", hr
);
2806 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
2809 IMXWriter_Release(writer
);
2813 static void test_mxwriter_flush(void)
2815 static const WCHAR emptyW
[] = {0};
2816 ISAXContentHandler
*content
;
2819 ULARGE_INTEGER pos2
;
2827 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2828 &IID_IMXWriter
, (void**)&writer
);
2829 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2831 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2832 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2833 EXPECT_REF(stream
, 1);
2835 /* detach when nothing was attached */
2836 V_VT(&dest
) = VT_EMPTY
;
2837 hr
= IMXWriter_put_output(writer
, dest
);
2838 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2841 V_VT(&dest
) = VT_UNKNOWN
;
2842 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
2843 hr
= IMXWriter_put_output(writer
, dest
);
2844 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2845 todo_wine
EXPECT_REF(stream
, 3);
2847 /* detach setting VT_EMPTY destination */
2848 V_VT(&dest
) = VT_EMPTY
;
2849 hr
= IMXWriter_put_output(writer
, dest
);
2850 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2851 EXPECT_REF(stream
, 1);
2853 V_VT(&dest
) = VT_UNKNOWN
;
2854 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
2855 hr
= IMXWriter_put_output(writer
, dest
);
2856 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2858 /* flush() doesn't detach a stream */
2859 hr
= IMXWriter_flush(writer
);
2860 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2861 todo_wine
EXPECT_REF(stream
, 3);
2864 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2865 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2866 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
2868 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2869 ok(hr
== S_OK
, "got %08x\n", hr
);
2871 hr
= ISAXContentHandler_startDocument(content
);
2872 ok(hr
== S_OK
, "got %08x\n", hr
);
2875 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2876 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2877 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
2879 /* already started */
2880 hr
= ISAXContentHandler_startDocument(content
);
2881 ok(hr
== S_OK
, "got %08x\n", hr
);
2883 hr
= ISAXContentHandler_endDocument(content
);
2884 ok(hr
== S_OK
, "got %08x\n", hr
);
2886 /* flushed on endDocument() */
2888 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2889 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2890 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
2892 IStream_Release(stream
);
2894 /* auto-flush feature */
2895 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2896 EXPECT_HR(hr
, S_OK
);
2897 EXPECT_REF(stream
, 1);
2899 V_VT(&dest
) = VT_UNKNOWN
;
2900 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
2901 hr
= IMXWriter_put_output(writer
, dest
);
2902 EXPECT_HR(hr
, S_OK
);
2904 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_FALSE
);
2905 EXPECT_HR(hr
, S_OK
);
2907 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2908 EXPECT_HR(hr
, S_OK
);
2910 hr
= ISAXContentHandler_startDocument(content
);
2911 EXPECT_HR(hr
, S_OK
);
2913 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
2914 EXPECT_HR(hr
, S_OK
);
2916 /* internal buffer is flushed automatically on certain threshold */
2919 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2920 EXPECT_HR(hr
, S_OK
);
2921 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
2924 buff
= HeapAlloc(GetProcessHeap(), 0, len
);
2925 memset(buff
, 'A', len
);
2926 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
2927 EXPECT_HR(hr
, S_OK
);
2931 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2932 EXPECT_HR(hr
, S_OK
);
2934 ok(pos2
.QuadPart
!= 0, "unexpected stream beginning\n");
2936 hr
= IMXWriter_get_output(writer
, NULL
);
2937 EXPECT_HR(hr
, E_POINTER
);
2939 ref
= get_refcount(stream
);
2940 V_VT(&dest
) = VT_EMPTY
;
2941 hr
= IMXWriter_get_output(writer
, &dest
);
2942 EXPECT_HR(hr
, S_OK
);
2943 ok(V_VT(&dest
) == VT_UNKNOWN
, "got vt type %d\n", V_VT(&dest
));
2944 ok(V_UNKNOWN(&dest
) == (IUnknown
*)stream
, "got pointer %p\n", V_UNKNOWN(&dest
));
2945 ok(ref
+1 == get_refcount(stream
), "expected increased refcount\n");
2946 VariantClear(&dest
);
2948 hr
= ISAXContentHandler_endDocument(content
);
2949 EXPECT_HR(hr
, S_OK
);
2951 IStream_Release(stream
);
2953 /* test char count lower than threshold */
2954 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2955 EXPECT_HR(hr
, S_OK
);
2956 EXPECT_REF(stream
, 1);
2958 hr
= ISAXContentHandler_startDocument(content
);
2959 EXPECT_HR(hr
, S_OK
);
2961 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
2962 EXPECT_HR(hr
, S_OK
);
2966 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2967 EXPECT_HR(hr
, S_OK
);
2968 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
2970 memset(buff
, 'A', len
);
2971 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
- 8);
2972 EXPECT_HR(hr
, S_OK
);
2976 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2977 EXPECT_HR(hr
, S_OK
);
2978 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
2980 hr
= ISAXContentHandler_endDocument(content
);
2981 EXPECT_HR(hr
, S_OK
);
2983 /* test auto-flush function when stream is not set */
2984 V_VT(&dest
) = VT_EMPTY
;
2985 hr
= IMXWriter_put_output(writer
, dest
);
2986 EXPECT_HR(hr
, S_OK
);
2988 hr
= ISAXContentHandler_startDocument(content
);
2989 EXPECT_HR(hr
, S_OK
);
2991 hr
= ISAXContentHandler_startElement(content
, emptyW
, 0, emptyW
, 0, _bstr_("a"), -1, NULL
);
2992 EXPECT_HR(hr
, S_OK
);
2994 memset(buff
, 'A', len
);
2995 hr
= ISAXContentHandler_characters(content
, _bstr_(buff
), len
);
2996 EXPECT_HR(hr
, S_OK
);
2998 V_VT(&dest
) = VT_EMPTY
;
2999 hr
= IMXWriter_get_output(writer
, &dest
);
3000 EXPECT_HR(hr
, S_OK
);
3001 len
+= strlen("<a>");
3002 ok(SysStringLen(V_BSTR(&dest
)) == len
, "got len=%d, expected %d\n", SysStringLen(V_BSTR(&dest
)), len
);
3003 VariantClear(&dest
);
3005 HeapFree(GetProcessHeap(), 0, buff
);
3006 ISAXContentHandler_Release(content
);
3007 IStream_Release(stream
);
3008 IMXWriter_Release(writer
);
3012 static void test_mxwriter_startenddocument(void)
3014 ISAXContentHandler
*content
;
3019 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3020 &IID_IMXWriter
, (void**)&writer
);
3021 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3023 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3024 ok(hr
== S_OK
, "got %08x\n", hr
);
3026 hr
= ISAXContentHandler_startDocument(content
);
3027 ok(hr
== S_OK
, "got %08x\n", hr
);
3029 hr
= ISAXContentHandler_endDocument(content
);
3030 ok(hr
== S_OK
, "got %08x\n", hr
);
3032 V_VT(&dest
) = VT_EMPTY
;
3033 hr
= IMXWriter_get_output(writer
, &dest
);
3034 ok(hr
== S_OK
, "got %08x\n", hr
);
3035 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3036 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3037 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3038 VariantClear(&dest
);
3040 /* now try another startDocument */
3041 hr
= ISAXContentHandler_startDocument(content
);
3042 ok(hr
== S_OK
, "got %08x\n", hr
);
3043 /* and get duplicated prolog */
3044 V_VT(&dest
) = VT_EMPTY
;
3045 hr
= IMXWriter_get_output(writer
, &dest
);
3046 ok(hr
== S_OK
, "got %08x\n", hr
);
3047 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3048 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
3049 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3050 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3051 VariantClear(&dest
);
3053 ISAXContentHandler_Release(content
);
3054 IMXWriter_Release(writer
);
3056 /* now with omitted declaration */
3057 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3058 &IID_IMXWriter
, (void**)&writer
);
3059 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3061 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3062 ok(hr
== S_OK
, "got %08x\n", hr
);
3064 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3065 ok(hr
== S_OK
, "got %08x\n", hr
);
3067 hr
= ISAXContentHandler_startDocument(content
);
3068 ok(hr
== S_OK
, "got %08x\n", hr
);
3070 hr
= ISAXContentHandler_endDocument(content
);
3071 ok(hr
== S_OK
, "got %08x\n", hr
);
3073 V_VT(&dest
) = VT_EMPTY
;
3074 hr
= IMXWriter_get_output(writer
, &dest
);
3075 ok(hr
== S_OK
, "got %08x\n", hr
);
3076 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3077 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3078 VariantClear(&dest
);
3080 ISAXContentHandler_Release(content
);
3081 IMXWriter_Release(writer
);
3088 StartElement
= 0x001,
3090 StartEndElement
= 0x011,
3091 DisableEscaping
= 0x100
3094 struct writer_startendelement_t
{
3096 enum startendtype type
;
3098 const char *local_name
;
3102 ISAXAttributes
*attr
;
3105 static const char startelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\">";
3106 static const char startendelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\"/>";
3107 static const char startendelement_noescape_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&\">\"/>";
3109 static const struct writer_startendelement_t writer_startendelement
[] = {
3111 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3112 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3113 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3114 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
3115 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3117 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3118 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3119 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
3120 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3121 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3123 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3124 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
3125 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3126 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3127 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3129 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
3130 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3131 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3132 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3133 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
3135 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3136 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3137 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3138 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
3139 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3141 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3142 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3143 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
3144 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3145 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3147 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3148 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
3149 /* endElement tests */
3150 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3151 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3152 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
3154 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
3155 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3156 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3157 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
3158 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
3160 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3161 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3162 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
3163 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
3164 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3166 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3167 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
3168 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
3169 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3170 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3172 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3173 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
3174 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3175 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3176 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
3178 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
3179 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3180 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3181 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3182 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
3184 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3185 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3186 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3187 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
3189 /* with attributes */
3190 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3192 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3193 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3194 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
3195 /* empty elements */
3196 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3197 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3199 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3200 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3201 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
3202 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
3203 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
3205 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
3207 /* with disabled output escaping */
3208 { &CLSID_MXXMLWriter
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3209 { &CLSID_MXXMLWriter30
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_noescape_xml
, S_OK
, &saxattributes
},
3210 { &CLSID_MXXMLWriter40
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3211 { &CLSID_MXXMLWriter60
, StartEndElement
| DisableEscaping
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
3216 static void get_class_support_data(struct msxmlsupported_data_t
*table
, REFIID riid
)
3218 while (table
->clsid
)
3223 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, riid
, (void**)&unk
);
3224 if (hr
== S_OK
) IUnknown_Release(unk
);
3226 table
->supported
= hr
== S_OK
;
3227 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
3233 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
3237 while (table
->clsid
)
3239 ISAXContentHandler
*content
;
3243 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3250 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3251 &IID_IMXWriter
, (void**)&writer
);
3252 EXPECT_HR(hr
, S_OK
);
3254 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3255 EXPECT_HR(hr
, S_OK
);
3257 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3258 EXPECT_HR(hr
, S_OK
);
3260 hr
= ISAXContentHandler_startDocument(content
);
3261 EXPECT_HR(hr
, S_OK
);
3263 if (table
->type
& DisableEscaping
)
3265 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3266 EXPECT_HR(hr
, S_OK
);
3269 if (table
->type
& StartElement
)
3271 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3272 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
), table
->attr
);
3273 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3276 if (table
->type
& EndElement
)
3278 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3279 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
));
3280 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3288 V_VT(&dest
) = VT_EMPTY
;
3289 hr
= IMXWriter_get_output(writer
, &dest
);
3290 EXPECT_HR(hr
, S_OK
);
3291 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3292 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3293 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3294 VariantClear(&dest
);
3297 ISAXContentHandler_Release(content
);
3298 IMXWriter_Release(writer
);
3307 /* point of these test is to start/end element with different names and name lengths */
3308 struct writer_startendelement2_t
{
3310 const char *qnamestart
;
3312 const char *qnameend
;
3318 static const struct writer_startendelement2_t writer_startendelement2
[] = {
3319 { &CLSID_MXXMLWriter
, "a", -1, "b", -1, "<a/>", S_OK
},
3320 { &CLSID_MXXMLWriter30
, "a", -1, "b", -1, "<a/>", S_OK
},
3321 { &CLSID_MXXMLWriter40
, "a", -1, "b", -1, "<a/>", S_OK
},
3322 /* -1 length is not allowed for version 6 */
3323 { &CLSID_MXXMLWriter60
, "a", -1, "b", -1, "<a/>", E_INVALIDARG
},
3325 { &CLSID_MXXMLWriter
, "a", 1, "b", 1, "<a/>", S_OK
},
3326 { &CLSID_MXXMLWriter30
, "a", 1, "b", 1, "<a/>", S_OK
},
3327 { &CLSID_MXXMLWriter40
, "a", 1, "b", 1, "<a/>", S_OK
},
3328 { &CLSID_MXXMLWriter60
, "a", 1, "b", 1, "<a/>", S_OK
},
3332 static void test_mxwriter_startendelement_batch2(const struct writer_startendelement2_t
*table
)
3336 while (table
->clsid
)
3338 ISAXContentHandler
*content
;
3342 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3349 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3350 &IID_IMXWriter
, (void**)&writer
);
3351 EXPECT_HR(hr
, S_OK
);
3353 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3354 EXPECT_HR(hr
, S_OK
);
3356 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3357 EXPECT_HR(hr
, S_OK
);
3359 hr
= ISAXContentHandler_startDocument(content
);
3360 EXPECT_HR(hr
, S_OK
);
3362 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3363 _bstr_(table
->qnamestart
), table
->qnamestart_len
, NULL
);
3364 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3366 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0,
3367 _bstr_(table
->qnameend
), table
->qnameend_len
);
3368 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3375 V_VT(&dest
) = VT_EMPTY
;
3376 hr
= IMXWriter_get_output(writer
, &dest
);
3377 EXPECT_HR(hr
, S_OK
);
3378 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3379 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3380 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3381 VariantClear(&dest
);
3384 ISAXContentHandler_Release(content
);
3385 IMXWriter_Release(writer
);
3395 static void test_mxwriter_startendelement(void)
3397 ISAXContentHandler
*content
;
3402 test_mxwriter_startendelement_batch(writer_startendelement
);
3403 test_mxwriter_startendelement_batch2(writer_startendelement2
);
3405 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3406 &IID_IMXWriter
, (void**)&writer
);
3407 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3409 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3410 ok(hr
== S_OK
, "got %08x\n", hr
);
3412 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3413 ok(hr
== S_OK
, "got %08x\n", hr
);
3415 hr
= ISAXContentHandler_startDocument(content
);
3416 ok(hr
== S_OK
, "got %08x\n", hr
);
3418 /* all string pointers should be not null */
3419 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
3420 ok(hr
== S_OK
, "got %08x\n", hr
);
3422 V_VT(&dest
) = VT_EMPTY
;
3423 hr
= IMXWriter_get_output(writer
, &dest
);
3424 ok(hr
== S_OK
, "got %08x\n", hr
);
3425 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3426 ok(!lstrcmpW(_bstr_("<>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3427 VariantClear(&dest
);
3429 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
3430 ok(hr
== S_OK
, "got %08x\n", hr
);
3432 V_VT(&dest
) = VT_EMPTY
;
3433 hr
= IMXWriter_get_output(writer
, &dest
);
3434 ok(hr
== S_OK
, "got %08x\n", hr
);
3435 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3436 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3437 VariantClear(&dest
);
3439 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
3440 EXPECT_HR(hr
, E_INVALIDARG
);
3442 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
3443 EXPECT_HR(hr
, E_INVALIDARG
);
3445 /* only local name is an error too */
3446 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
3447 EXPECT_HR(hr
, E_INVALIDARG
);
3449 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
3450 EXPECT_HR(hr
, S_OK
);
3452 V_VT(&dest
) = VT_EMPTY
;
3453 hr
= IMXWriter_get_output(writer
, &dest
);
3454 EXPECT_HR(hr
, S_OK
);
3455 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3456 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3457 VariantClear(&dest
);
3459 hr
= ISAXContentHandler_endDocument(content
);
3460 EXPECT_HR(hr
, S_OK
);
3462 V_VT(&dest
) = VT_EMPTY
;
3463 hr
= IMXWriter_put_output(writer
, dest
);
3464 EXPECT_HR(hr
, S_OK
);
3466 V_VT(&dest
) = VT_EMPTY
;
3467 hr
= IMXWriter_get_output(writer
, &dest
);
3468 EXPECT_HR(hr
, S_OK
);
3469 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3470 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3471 VariantClear(&dest
);
3473 hr
= ISAXContentHandler_startDocument(content
);
3474 EXPECT_HR(hr
, S_OK
);
3476 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
3477 EXPECT_HR(hr
, S_OK
);
3479 V_VT(&dest
) = VT_EMPTY
;
3480 hr
= IMXWriter_get_output(writer
, &dest
);
3481 EXPECT_HR(hr
, S_OK
);
3482 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3483 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3484 VariantClear(&dest
);
3486 ISAXContentHandler_endDocument(content
);
3487 IMXWriter_flush(writer
);
3489 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
3490 EXPECT_HR(hr
, S_OK
);
3491 V_VT(&dest
) = VT_EMPTY
;
3492 hr
= IMXWriter_get_output(writer
, &dest
);
3493 EXPECT_HR(hr
, S_OK
);
3494 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3495 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3496 VariantClear(&dest
);
3498 V_VT(&dest
) = VT_EMPTY
;
3499 hr
= IMXWriter_put_output(writer
, dest
);
3500 EXPECT_HR(hr
, S_OK
);
3503 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), -1, NULL
);
3504 EXPECT_HR(hr
, S_OK
);
3505 V_VT(&dest
) = VT_EMPTY
;
3506 hr
= IMXWriter_get_output(writer
, &dest
);
3507 EXPECT_HR(hr
, S_OK
);
3508 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3509 ok(!lstrcmpW(_bstr_("<a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3510 VariantClear(&dest
);
3512 ISAXContentHandler_Release(content
);
3513 IMXWriter_Release(writer
);
3517 struct writer_characters_t
{
3523 static const struct writer_characters_t writer_characters
[] = {
3524 { &CLSID_MXXMLWriter
, "< > & \"", "< > & \"" },
3525 { &CLSID_MXXMLWriter30
, "< > & \"", "< > & \"" },
3526 { &CLSID_MXXMLWriter40
, "< > & \"", "< > & \"" },
3527 { &CLSID_MXXMLWriter60
, "< > & \"", "< > & \"" },
3531 static void test_mxwriter_characters(void)
3533 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
3534 const struct writer_characters_t
*table
= writer_characters
;
3535 ISAXContentHandler
*content
;
3541 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3542 &IID_IMXWriter
, (void**)&writer
);
3543 EXPECT_HR(hr
, S_OK
);
3545 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3546 EXPECT_HR(hr
, S_OK
);
3548 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3549 EXPECT_HR(hr
, S_OK
);
3551 hr
= ISAXContentHandler_startDocument(content
);
3552 EXPECT_HR(hr
, S_OK
);
3554 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
3555 EXPECT_HR(hr
, E_INVALIDARG
);
3557 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3558 EXPECT_HR(hr
, S_OK
);
3560 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
3561 EXPECT_HR(hr
, S_OK
);
3563 V_VT(&dest
) = VT_EMPTY
;
3564 hr
= IMXWriter_get_output(writer
, &dest
);
3565 EXPECT_HR(hr
, S_OK
);
3566 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3567 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3568 VariantClear(&dest
);
3570 hr
= ISAXContentHandler_endDocument(content
);
3571 EXPECT_HR(hr
, S_OK
);
3573 ISAXContentHandler_Release(content
);
3574 IMXWriter_Release(writer
);
3576 /* try empty characters data to see if element is closed */
3577 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3578 &IID_IMXWriter
, (void**)&writer
);
3579 EXPECT_HR(hr
, S_OK
);
3581 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3582 EXPECT_HR(hr
, S_OK
);
3584 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3585 EXPECT_HR(hr
, S_OK
);
3587 hr
= ISAXContentHandler_startDocument(content
);
3588 EXPECT_HR(hr
, S_OK
);
3590 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3591 EXPECT_HR(hr
, S_OK
);
3593 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3594 EXPECT_HR(hr
, S_OK
);
3596 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3597 EXPECT_HR(hr
, S_OK
);
3599 V_VT(&dest
) = VT_EMPTY
;
3600 hr
= IMXWriter_get_output(writer
, &dest
);
3601 EXPECT_HR(hr
, S_OK
);
3602 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3603 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3604 VariantClear(&dest
);
3606 ISAXContentHandler_Release(content
);
3607 IMXWriter_Release(writer
);
3610 while (table
->clsid
)
3612 ISAXContentHandler
*content
;
3617 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3624 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3625 &IID_IMXWriter
, (void**)&writer
);
3626 EXPECT_HR(hr
, S_OK
);
3628 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3629 EXPECT_HR(hr
, S_OK
);
3631 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3632 EXPECT_HR(hr
, S_OK
);
3634 hr
= ISAXContentHandler_startDocument(content
);
3635 EXPECT_HR(hr
, S_OK
);
3637 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
3638 EXPECT_HR(hr
, S_OK
);
3643 V_VT(&dest
) = VT_EMPTY
;
3644 hr
= IMXWriter_get_output(writer
, &dest
);
3645 EXPECT_HR(hr
, S_OK
);
3646 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3647 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3648 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3649 VariantClear(&dest
);
3652 /* with disabled escaping */
3653 V_VT(&dest
) = VT_EMPTY
;
3654 hr
= IMXWriter_put_output(writer
, dest
);
3655 EXPECT_HR(hr
, S_OK
);
3657 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3658 EXPECT_HR(hr
, S_OK
);
3660 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
3661 EXPECT_HR(hr
, S_OK
);
3666 V_VT(&dest
) = VT_EMPTY
;
3667 hr
= IMXWriter_get_output(writer
, &dest
);
3668 EXPECT_HR(hr
, S_OK
);
3669 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3670 ok(!lstrcmpW(_bstr_(table
->data
), V_BSTR(&dest
)),
3671 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->data
);
3672 VariantClear(&dest
);
3675 ISAXContentHandler_Release(content
);
3676 IMXWriter_Release(writer
);
3685 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
3687 VARIANT_TRUE
,"UTF-16",
3689 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3690 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3695 VARIANT_FALSE
,"UTF-16",
3697 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3702 VARIANT_TRUE
,"UTF-8",
3704 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
3705 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3706 * and the writer is released.
3713 VARIANT_TRUE
,"utf-8",
3715 {FALSE
,(const BYTE
*)utf8xml2
,sizeof(utf8xml2
)-1},
3716 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3717 * and the writer is released.
3724 VARIANT_TRUE
,"UTF-16",
3726 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3727 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3732 VARIANT_TRUE
,"UTF-16",
3734 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
3735 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3741 static void test_mxwriter_stream(void)
3744 ISAXContentHandler
*content
;
3749 ULARGE_INTEGER pos2
;
3750 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
3752 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
3753 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
3755 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3756 &IID_IMXWriter
, (void**)&writer
);
3757 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
3759 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3760 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
3762 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
3763 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
3765 V_VT(&dest
) = VT_UNKNOWN
;
3766 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
3767 hr
= IMXWriter_put_output(writer
, dest
);
3768 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
3769 VariantClear(&dest
);
3771 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
3772 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
3774 current_write_test
= test
->expected_writes
;
3776 hr
= ISAXContentHandler_startDocument(content
);
3777 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
3779 hr
= ISAXContentHandler_endDocument(content
);
3780 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
3782 ISAXContentHandler_Release(content
);
3783 IMXWriter_Release(writer
);
3785 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
3786 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
3789 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3790 &IID_IMXWriter
, (void**)&writer
);
3791 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
3793 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3794 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
3796 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3797 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
3799 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
3800 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
3802 V_VT(&dest
) = VT_UNKNOWN
;
3803 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3804 hr
= IMXWriter_put_output(writer
, dest
);
3805 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
3807 hr
= ISAXContentHandler_startDocument(content
);
3808 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
3810 /* Setting output of the mxwriter causes the current output to be flushed,
3811 * and the writer to start over.
3813 V_VT(&dest
) = VT_EMPTY
;
3814 hr
= IMXWriter_put_output(writer
, dest
);
3815 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
3818 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3819 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
3820 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
3822 hr
= ISAXContentHandler_startDocument(content
);
3823 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
3825 hr
= ISAXContentHandler_endDocument(content
);
3826 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
3828 V_VT(&dest
) = VT_EMPTY
;
3829 hr
= IMXWriter_get_output(writer
, &dest
);
3830 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
3831 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
3832 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3833 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3834 VariantClear(&dest
);
3836 /* test when BOM is written to output stream */
3837 V_VT(&dest
) = VT_EMPTY
;
3838 hr
= IMXWriter_put_output(writer
, dest
);
3839 EXPECT_HR(hr
, S_OK
);
3842 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
3843 EXPECT_HR(hr
, S_OK
);
3845 V_VT(&dest
) = VT_UNKNOWN
;
3846 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3847 hr
= IMXWriter_put_output(writer
, dest
);
3848 EXPECT_HR(hr
, S_OK
);
3850 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_TRUE
);
3851 EXPECT_HR(hr
, S_OK
);
3853 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
3854 EXPECT_HR(hr
, S_OK
);
3856 hr
= ISAXContentHandler_startDocument(content
);
3857 EXPECT_HR(hr
, S_OK
);
3861 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3862 EXPECT_HR(hr
, S_OK
);
3863 ok(pos2
.QuadPart
== 2, "got wrong position\n");
3865 ISAXContentHandler_Release(content
);
3866 IMXWriter_Release(writer
);
3871 static const char *encoding_names
[] = {
3884 static void test_mxwriter_encoding(void)
3886 ISAXContentHandler
*content
;
3897 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3898 &IID_IMXWriter
, (void**)&writer
);
3899 EXPECT_HR(hr
, S_OK
);
3901 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3902 EXPECT_HR(hr
, S_OK
);
3904 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
3905 EXPECT_HR(hr
, S_OK
);
3907 hr
= ISAXContentHandler_startDocument(content
);
3908 EXPECT_HR(hr
, S_OK
);
3910 hr
= ISAXContentHandler_endDocument(content
);
3911 EXPECT_HR(hr
, S_OK
);
3913 /* The content is always re-encoded to UTF-16 when the output is
3914 * retrieved as a BSTR.
3916 V_VT(&dest
) = VT_EMPTY
;
3917 hr
= IMXWriter_get_output(writer
, &dest
);
3918 EXPECT_HR(hr
, S_OK
);
3919 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
3920 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3921 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3922 VariantClear(&dest
);
3924 /* switch encoding when something is written already */
3925 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3926 EXPECT_HR(hr
, S_OK
);
3928 V_VT(&dest
) = VT_UNKNOWN
;
3929 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3930 hr
= IMXWriter_put_output(writer
, dest
);
3931 EXPECT_HR(hr
, S_OK
);
3933 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
3934 EXPECT_HR(hr
, S_OK
);
3936 /* write empty element */
3937 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3938 EXPECT_HR(hr
, S_OK
);
3940 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3941 EXPECT_HR(hr
, S_OK
);
3944 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
3945 EXPECT_HR(hr
, S_OK
);
3947 hr
= IMXWriter_flush(writer
);
3948 EXPECT_HR(hr
, S_OK
);
3950 hr
= GetHGlobalFromStream(stream
, &g
);
3951 EXPECT_HR(hr
, S_OK
);
3953 ptr
= GlobalLock(g
);
3954 ok(!strncmp(ptr
, "<a/>", 4), "got %c%c%c%c\n", ptr
[0],ptr
[1],ptr
[2],ptr
[3]);
3957 /* so output is unaffected, encoding name is stored however */
3958 hr
= IMXWriter_get_encoding(writer
, &s
);
3959 EXPECT_HR(hr
, S_OK
);
3960 ok(!lstrcmpW(s
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(s
));
3963 IStream_Release(stream
);
3966 enc
= encoding_names
[i
];
3969 char expectedA
[200];
3971 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3972 EXPECT_HR(hr
, S_OK
);
3974 V_VT(&dest
) = VT_UNKNOWN
;
3975 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3976 hr
= IMXWriter_put_output(writer
, dest
);
3977 EXPECT_HR(hr
, S_OK
);
3979 hr
= IMXWriter_put_encoding(writer
, _bstr_(enc
));
3980 ok(hr
== S_OK
|| broken(hr
!= S_OK
) /* old win versions do not support certain encodings */,
3981 "%s: encoding not accepted\n", enc
);
3984 enc
= encoding_names
[++i
];
3985 IStream_Release(stream
);
3989 hr
= ISAXContentHandler_startDocument(content
);
3990 EXPECT_HR(hr
, S_OK
);
3992 hr
= ISAXContentHandler_endDocument(content
);
3993 EXPECT_HR(hr
, S_OK
);
3995 hr
= IMXWriter_flush(writer
);
3996 EXPECT_HR(hr
, S_OK
);
3998 /* prepare expected string */
4000 strcat(expectedA
, "<?xml version=\"1.0\" encoding=\"");
4001 strcat(expectedA
, enc
);
4002 strcat(expectedA
, "\" standalone=\"no\"?>\r\n");
4004 hr
= GetHGlobalFromStream(stream
, &g
);
4005 EXPECT_HR(hr
, S_OK
);
4007 ptr
= GlobalLock(g
);
4008 ok(!strncmp(ptr
, expectedA
, strlen(expectedA
)), "%s: got %s, expected %.50s\n", enc
, ptr
, expectedA
);
4011 V_VT(&dest
) = VT_EMPTY
;
4012 hr
= IMXWriter_put_output(writer
, dest
);
4013 EXPECT_HR(hr
, S_OK
);
4015 IStream_Release(stream
);
4017 enc
= encoding_names
[++i
];
4020 ISAXContentHandler_Release(content
);
4021 IMXWriter_Release(writer
);
4026 static void test_obj_dispex(IUnknown
*obj
)
4028 static const WCHAR starW
[] = {'*',0};
4029 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
4030 IDispatchEx
*dispex
;
4037 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
4038 EXPECT_HR(hr
, S_OK
);
4039 if (FAILED(hr
)) return;
4042 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
4043 EXPECT_HR(hr
, S_OK
);
4044 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
4046 name
= SysAllocString(starW
);
4047 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
4048 EXPECT_HR(hr
, E_NOTIMPL
);
4049 SysFreeString(name
);
4051 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
4052 EXPECT_HR(hr
, E_NOTIMPL
);
4055 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
4056 EXPECT_HR(hr
, E_NOTIMPL
);
4057 ok(props
== 0, "expected 0 got %d\n", props
);
4059 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
4060 EXPECT_HR(hr
, E_NOTIMPL
);
4061 if (SUCCEEDED(hr
)) SysFreeString(name
);
4063 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
4064 EXPECT_HR(hr
, E_NOTIMPL
);
4066 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
4067 EXPECT_HR(hr
, E_NOTIMPL
);
4068 if (hr
== S_OK
&& unk
) IUnknown_Release(unk
);
4070 IDispatchEx_Release(dispex
);
4073 static void test_dispex(void)
4075 IVBSAXXMLReader
*vbreader
;
4076 ISAXXMLReader
*reader
;
4080 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
4081 &IID_ISAXXMLReader
, (void**)&reader
);
4082 EXPECT_HR(hr
, S_OK
);
4084 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
4085 EXPECT_HR(hr
, S_OK
);
4086 test_obj_dispex(unk
);
4087 IUnknown_Release(unk
);
4089 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
4090 EXPECT_HR(hr
, S_OK
);
4091 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
4092 EXPECT_HR(hr
, S_OK
);
4093 test_obj_dispex(unk
);
4094 IUnknown_Release(unk
);
4095 IVBSAXXMLReader_Release(vbreader
);
4097 ISAXXMLReader_Release(reader
);
4100 static void test_mxwriter_dispex(void)
4102 IDispatchEx
*dispex
;
4107 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4108 &IID_IMXWriter
, (void**)&writer
);
4109 EXPECT_HR(hr
, S_OK
);
4111 hr
= IMXWriter_QueryInterface(writer
, &IID_IDispatchEx
, (void**)&dispex
);
4112 EXPECT_HR(hr
, S_OK
);
4113 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4114 test_obj_dispex(unk
);
4115 IUnknown_Release(unk
);
4116 IDispatchEx_Release(dispex
);
4118 IMXWriter_Release(writer
);
4121 static void test_mxwriter_comment(void)
4123 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
4124 ISAXContentHandler
*content
;
4125 ISAXLexicalHandler
*lexical
;
4130 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4131 &IID_IMXWriter
, (void**)&writer
);
4132 EXPECT_HR(hr
, S_OK
);
4134 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4135 EXPECT_HR(hr
, S_OK
);
4137 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4138 EXPECT_HR(hr
, S_OK
);
4140 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4141 EXPECT_HR(hr
, S_OK
);
4143 hr
= ISAXContentHandler_startDocument(content
);
4144 EXPECT_HR(hr
, S_OK
);
4146 hr
= ISAXLexicalHandler_comment(lexical
, NULL
, 0);
4147 EXPECT_HR(hr
, E_INVALIDARG
);
4149 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, 0);
4150 EXPECT_HR(hr
, S_OK
);
4152 V_VT(&dest
) = VT_EMPTY
;
4153 hr
= IMXWriter_get_output(writer
, &dest
);
4154 EXPECT_HR(hr
, S_OK
);
4155 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4156 ok(!lstrcmpW(_bstr_("<!---->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4157 VariantClear(&dest
);
4159 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, sizeof(commentW
)/sizeof(WCHAR
)-1);
4160 EXPECT_HR(hr
, S_OK
);
4162 V_VT(&dest
) = VT_EMPTY
;
4163 hr
= IMXWriter_get_output(writer
, &dest
);
4164 EXPECT_HR(hr
, S_OK
);
4165 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4166 ok(!lstrcmpW(_bstr_("<!---->\r\n<!--comment-->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4167 VariantClear(&dest
);
4169 ISAXContentHandler_Release(content
);
4170 ISAXLexicalHandler_Release(lexical
);
4171 IMXWriter_Release(writer
);
4175 static void test_mxwriter_cdata(void)
4177 ISAXContentHandler
*content
;
4178 ISAXLexicalHandler
*lexical
;
4183 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4184 &IID_IMXWriter
, (void**)&writer
);
4185 EXPECT_HR(hr
, S_OK
);
4187 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4188 EXPECT_HR(hr
, S_OK
);
4190 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4191 EXPECT_HR(hr
, S_OK
);
4193 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4194 EXPECT_HR(hr
, S_OK
);
4196 hr
= ISAXContentHandler_startDocument(content
);
4197 EXPECT_HR(hr
, S_OK
);
4199 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4200 EXPECT_HR(hr
, S_OK
);
4202 V_VT(&dest
) = VT_EMPTY
;
4203 hr
= IMXWriter_get_output(writer
, &dest
);
4204 EXPECT_HR(hr
, S_OK
);
4205 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4206 ok(!lstrcmpW(_bstr_("<![CDATA["), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4207 VariantClear(&dest
);
4209 hr
= ISAXLexicalHandler_startCDATA(lexical
);
4210 EXPECT_HR(hr
, S_OK
);
4212 /* all these are escaped for text nodes */
4213 hr
= ISAXContentHandler_characters(content
, _bstr_("< > & \""), 7);
4214 EXPECT_HR(hr
, S_OK
);
4216 hr
= ISAXLexicalHandler_endCDATA(lexical
);
4217 EXPECT_HR(hr
, S_OK
);
4219 V_VT(&dest
) = VT_EMPTY
;
4220 hr
= IMXWriter_get_output(writer
, &dest
);
4221 EXPECT_HR(hr
, S_OK
);
4222 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4223 ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4224 VariantClear(&dest
);
4226 ISAXContentHandler_Release(content
);
4227 ISAXLexicalHandler_Release(lexical
);
4228 IMXWriter_Release(writer
);
4232 static void test_mxwriter_pi(void)
4234 static const WCHAR targetW
[] = {'t','a','r','g','e','t',0};
4235 static const WCHAR dataW
[] = {'d','a','t','a',0};
4236 ISAXContentHandler
*content
;
4241 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4242 &IID_IMXWriter
, (void**)&writer
);
4243 EXPECT_HR(hr
, S_OK
);
4245 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4246 EXPECT_HR(hr
, S_OK
);
4248 hr
= ISAXContentHandler_processingInstruction(content
, NULL
, 0, NULL
, 0);
4249 EXPECT_HR(hr
, E_INVALIDARG
);
4251 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 0, NULL
, 0);
4252 EXPECT_HR(hr
, S_OK
);
4254 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, NULL
, 0);
4255 EXPECT_HR(hr
, S_OK
);
4257 V_VT(&dest
) = VT_EMPTY
;
4258 hr
= IMXWriter_get_output(writer
, &dest
);
4259 EXPECT_HR(hr
, S_OK
);
4260 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4261 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4262 VariantClear(&dest
);
4264 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 4, dataW
, 4);
4265 EXPECT_HR(hr
, S_OK
);
4267 V_VT(&dest
) = VT_EMPTY
;
4268 hr
= IMXWriter_get_output(writer
, &dest
);
4269 EXPECT_HR(hr
, S_OK
);
4270 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4271 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
)));
4272 VariantClear(&dest
);
4274 V_VT(&dest
) = VT_EMPTY
;
4275 hr
= IMXWriter_put_output(writer
, dest
);
4276 EXPECT_HR(hr
, S_OK
);
4278 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, dataW
, 0);
4279 EXPECT_HR(hr
, S_OK
);
4281 V_VT(&dest
) = VT_EMPTY
;
4282 hr
= IMXWriter_get_output(writer
, &dest
);
4283 EXPECT_HR(hr
, S_OK
);
4284 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4285 ok(!lstrcmpW(_bstr_("<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4286 VariantClear(&dest
);
4289 ISAXContentHandler_Release(content
);
4290 IMXWriter_Release(writer
);
4293 static void test_mxwriter_ignorablespaces(void)
4295 static const WCHAR dataW
[] = {'d','a','t','a',0};
4296 ISAXContentHandler
*content
;
4301 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4302 &IID_IMXWriter
, (void**)&writer
);
4303 EXPECT_HR(hr
, S_OK
);
4305 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4306 EXPECT_HR(hr
, S_OK
);
4308 hr
= ISAXContentHandler_ignorableWhitespace(content
, NULL
, 0);
4309 EXPECT_HR(hr
, E_INVALIDARG
);
4311 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 0);
4312 EXPECT_HR(hr
, S_OK
);
4314 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 4);
4315 EXPECT_HR(hr
, S_OK
);
4317 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 1);
4318 EXPECT_HR(hr
, S_OK
);
4320 V_VT(&dest
) = VT_EMPTY
;
4321 hr
= IMXWriter_get_output(writer
, &dest
);
4322 EXPECT_HR(hr
, S_OK
);
4323 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4324 ok(!lstrcmpW(_bstr_("datad"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4325 VariantClear(&dest
);
4327 ISAXContentHandler_Release(content
);
4328 IMXWriter_Release(writer
);
4331 static void test_mxwriter_dtd(void)
4333 static const WCHAR contentW
[] = {'c','o','n','t','e','n','t'};
4334 static const WCHAR nameW
[] = {'n','a','m','e'};
4335 static const WCHAR pubW
[] = {'p','u','b'};
4336 static const WCHAR sysW
[] = {'s','y','s'};
4337 ISAXContentHandler
*content
;
4338 ISAXLexicalHandler
*lexical
;
4339 ISAXDeclHandler
*decl
;
4344 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
4345 &IID_IMXWriter
, (void**)&writer
);
4346 EXPECT_HR(hr
, S_OK
);
4348 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
4349 EXPECT_HR(hr
, S_OK
);
4351 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
4352 EXPECT_HR(hr
, S_OK
);
4354 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
4355 EXPECT_HR(hr
, S_OK
);
4357 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
4358 EXPECT_HR(hr
, S_OK
);
4360 hr
= ISAXContentHandler_startDocument(content
);
4361 EXPECT_HR(hr
, S_OK
);
4363 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, NULL
, 0);
4364 EXPECT_HR(hr
, E_INVALIDARG
);
4366 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4367 EXPECT_HR(hr
, E_INVALIDARG
);
4369 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4370 EXPECT_HR(hr
, E_INVALIDARG
);
4372 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4373 EXPECT_HR(hr
, E_INVALIDARG
);
4375 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0, NULL
, 0);
4376 EXPECT_HR(hr
, S_OK
);
4378 V_VT(&dest
) = VT_EMPTY
;
4379 hr
= IMXWriter_get_output(writer
, &dest
);
4380 EXPECT_HR(hr
, S_OK
);
4381 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4382 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4383 VariantClear(&dest
);
4385 /* system id is required if public is present */
4386 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
4387 EXPECT_HR(hr
, E_INVALIDARG
);
4389 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
),
4390 pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
4391 EXPECT_HR(hr
, S_OK
);
4393 V_VT(&dest
) = VT_EMPTY
;
4394 hr
= IMXWriter_get_output(writer
, &dest
);
4395 EXPECT_HR(hr
, S_OK
);
4396 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4397 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4398 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4399 VariantClear(&dest
);
4401 hr
= ISAXLexicalHandler_endDTD(lexical
);
4402 EXPECT_HR(hr
, S_OK
);
4404 hr
= ISAXLexicalHandler_endDTD(lexical
);
4405 EXPECT_HR(hr
, S_OK
);
4407 V_VT(&dest
) = VT_EMPTY
;
4408 hr
= IMXWriter_get_output(writer
, &dest
);
4409 EXPECT_HR(hr
, S_OK
);
4410 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4411 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
4412 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n"),
4413 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4414 VariantClear(&dest
);
4416 /* element declaration */
4417 V_VT(&dest
) = VT_EMPTY
;
4418 hr
= IMXWriter_put_output(writer
, dest
);
4419 EXPECT_HR(hr
, S_OK
);
4421 hr
= ISAXDeclHandler_elementDecl(decl
, NULL
, 0, NULL
, 0);
4422 EXPECT_HR(hr
, E_INVALIDARG
);
4424 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0);
4425 EXPECT_HR(hr
, E_INVALIDARG
);
4427 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, sizeof(contentW
)/sizeof(WCHAR
));
4428 EXPECT_HR(hr
, S_OK
);
4430 V_VT(&dest
) = VT_EMPTY
;
4431 hr
= IMXWriter_get_output(writer
, &dest
);
4432 EXPECT_HR(hr
, S_OK
);
4433 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4434 ok(!lstrcmpW(_bstr_("<!ELEMENT name content>\r\n"),
4435 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4436 VariantClear(&dest
);
4438 V_VT(&dest
) = VT_EMPTY
;
4439 hr
= IMXWriter_put_output(writer
, dest
);
4440 EXPECT_HR(hr
, S_OK
);
4442 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, 0);
4443 EXPECT_HR(hr
, S_OK
);
4445 V_VT(&dest
) = VT_EMPTY
;
4446 hr
= IMXWriter_get_output(writer
, &dest
);
4447 EXPECT_HR(hr
, S_OK
);
4448 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4449 ok(!lstrcmpW(_bstr_("<!ELEMENT name >\r\n"),
4450 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4451 VariantClear(&dest
);
4453 /* attribute declaration */
4454 V_VT(&dest
) = VT_EMPTY
;
4455 hr
= IMXWriter_put_output(writer
, dest
);
4456 EXPECT_HR(hr
, S_OK
);
4458 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4459 _bstr_("attribute"), strlen("attribute"), _bstr_("CDATA"), strlen("CDATA"),
4460 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value"), strlen("value"));
4461 EXPECT_HR(hr
, S_OK
);
4463 V_VT(&dest
) = VT_EMPTY
;
4464 hr
= IMXWriter_get_output(writer
, &dest
);
4465 EXPECT_HR(hr
, S_OK
);
4466 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4467 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"),
4468 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4469 VariantClear(&dest
);
4471 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element"), strlen("element"),
4472 _bstr_("attribute2"), strlen("attribute2"), _bstr_("CDATA"), strlen("CDATA"),
4473 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value2"), strlen("value2"));
4474 EXPECT_HR(hr
, S_OK
);
4476 hr
= ISAXDeclHandler_attributeDecl(decl
, _bstr_("element2"), strlen("element2"),
4477 _bstr_("attribute3"), strlen("attribute3"), _bstr_("CDATA"), strlen("CDATA"),
4478 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value3"), strlen("value3"));
4479 EXPECT_HR(hr
, S_OK
);
4481 V_VT(&dest
) = VT_EMPTY
;
4482 hr
= IMXWriter_get_output(writer
, &dest
);
4483 EXPECT_HR(hr
, S_OK
);
4484 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4485 ok(!lstrcmpW(_bstr_("<!ATTLIST element attribute CDATA #REQUIRED \"value\">\r\n"
4486 "<!ATTLIST element attribute2 CDATA #REQUIRED \"value2\">\r\n"
4487 "<!ATTLIST element2 attribute3 CDATA #REQUIRED \"value3\">\r\n"),
4488 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4489 VariantClear(&dest
);
4491 /* internal entities */
4492 V_VT(&dest
) = VT_EMPTY
;
4493 hr
= IMXWriter_put_output(writer
, dest
);
4494 EXPECT_HR(hr
, S_OK
);
4496 hr
= ISAXDeclHandler_internalEntityDecl(decl
, NULL
, 0, NULL
, 0);
4497 EXPECT_HR(hr
, E_INVALIDARG
);
4499 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), -1, NULL
, 0);
4500 EXPECT_HR(hr
, E_INVALIDARG
);
4502 hr
= ISAXDeclHandler_internalEntityDecl(decl
, _bstr_("name"), strlen("name"), _bstr_("value"), strlen("value"));
4503 EXPECT_HR(hr
, S_OK
);
4505 V_VT(&dest
) = VT_EMPTY
;
4506 hr
= IMXWriter_get_output(writer
, &dest
);
4507 EXPECT_HR(hr
, S_OK
);
4508 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4509 ok(!lstrcmpW(_bstr_("<!ENTITY name \"value\">\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4510 VariantClear(&dest
);
4512 ISAXContentHandler_Release(content
);
4513 ISAXLexicalHandler_Release(lexical
);
4514 ISAXDeclHandler_Release(decl
);
4515 IMXWriter_Release(writer
);
4527 } addattribute_test_t
;
4529 static const addattribute_test_t addattribute_data
[] = {
4530 { &CLSID_SAXAttributes
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4531 { &CLSID_SAXAttributes30
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4532 { &CLSID_SAXAttributes40
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4533 { &CLSID_SAXAttributes60
, NULL
, NULL
, "ns:qname", NULL
, "value", S_OK
},
4535 { &CLSID_SAXAttributes
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4536 { &CLSID_SAXAttributes30
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4537 { &CLSID_SAXAttributes40
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4538 { &CLSID_SAXAttributes60
, NULL
, "qname", "ns:qname", NULL
, "value", S_OK
},
4540 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4541 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4542 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4543 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", NULL
, "value", S_OK
},
4545 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4546 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4547 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4548 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4553 static void test_mxattr_addAttribute(void)
4555 const addattribute_test_t
*table
= addattribute_data
;
4558 while (table
->clsid
)
4560 ISAXAttributes
*saxattr
;
4561 IMXAttributes
*mxattr
;
4566 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
4573 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4574 &IID_IMXAttributes
, (void**)&mxattr
);
4575 EXPECT_HR(hr
, S_OK
);
4577 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4578 EXPECT_HR(hr
, S_OK
);
4580 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
4581 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4582 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4584 hr
= ISAXAttributes_getLength(saxattr
, NULL
);
4585 EXPECT_HR(hr
, E_POINTER
);
4589 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4590 EXPECT_HR(hr
, S_OK
);
4591 ok(len
== 0, "got %d\n", len
);
4593 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
4594 EXPECT_HR(hr
, E_INVALIDARG
);
4596 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
4597 EXPECT_HR(hr
, E_INVALIDARG
);
4599 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
4600 EXPECT_HR(hr
, E_INVALIDARG
);
4602 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
4603 EXPECT_HR(hr
, E_INVALIDARG
);
4605 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
4606 EXPECT_HR(hr
, E_INVALIDARG
);
4608 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
4609 EXPECT_HR(hr
, E_INVALIDARG
);
4611 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
4612 EXPECT_HR(hr
, E_INVALIDARG
);
4614 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
4615 EXPECT_HR(hr
, E_INVALIDARG
);
4617 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_(table
->uri
), _bstr_(table
->local
),
4618 _bstr_(table
->qname
), _bstr_(table
->type
), _bstr_(table
->value
));
4619 ok(hr
== table
->hr
, "%d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
4623 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
4624 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4625 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4627 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
4628 EXPECT_HR(hr
, E_POINTER
);
4630 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
4631 EXPECT_HR(hr
, E_POINTER
);
4633 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
4634 EXPECT_HR(hr
, E_POINTER
);
4636 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
4637 EXPECT_HR(hr
, E_POINTER
);
4639 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
4640 EXPECT_HR(hr
, E_POINTER
);
4642 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
4643 EXPECT_HR(hr
, E_POINTER
);
4647 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
4648 EXPECT_HR(hr
, S_OK
);
4649 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4651 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
4654 value
= (void*)0xdeadbeef;
4655 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
4656 EXPECT_HR(hr
, S_OK
);
4660 ok(!lstrcmpW(_bstr_(table
->type
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4662 ok(lstrlenW(value
) == len
, "%d: got wrong type value length %d\n", i
, len
);
4666 ok(*value
== 0, "%d: got type value %s\n", i
, wine_dbgstr_w(value
));
4667 ok(len
== 0, "%d: got wrong type value length %d\n", i
, len
);
4670 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, NULL
);
4671 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4672 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4674 EXPECT_HR(hr
, E_POINTER
);
4677 EXPECT_HR(hr
, E_INVALIDARG
);
4679 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, &index
);
4680 EXPECT_HR(hr
, E_INVALIDARG
);
4683 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_("nonexistent"), 11, &index
);
4684 EXPECT_HR(hr
, E_INVALIDARG
);
4685 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4688 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), 0, &index
);
4689 EXPECT_HR(hr
, E_INVALIDARG
);
4690 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4693 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &index
);
4694 EXPECT_HR(hr
, S_OK
);
4695 ok(index
== 0, "%d: got wrong index %d\n", i
, index
);
4698 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
)-1, &index
);
4699 EXPECT_HR(hr
, E_INVALIDARG
);
4700 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4702 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes40
) ||
4703 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes60
))
4705 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4706 EXPECT_HR(hr
, E_INVALIDARG
);
4708 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4709 EXPECT_HR(hr
, E_INVALIDARG
);
4711 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4712 EXPECT_HR(hr
, E_INVALIDARG
);
4714 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
4715 EXPECT_HR(hr
, E_INVALIDARG
);
4717 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
4718 EXPECT_HR(hr
, E_INVALIDARG
);
4720 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
4721 EXPECT_HR(hr
, E_INVALIDARG
);
4725 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4726 EXPECT_HR(hr
, E_POINTER
);
4728 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4729 EXPECT_HR(hr
, E_POINTER
);
4731 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4732 EXPECT_HR(hr
, E_POINTER
);
4734 /* versions 4 and 6 crash */
4735 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, NULL
);
4736 EXPECT_HR(hr
, E_POINTER
);
4738 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, &len
);
4739 EXPECT_HR(hr
, E_POINTER
);
4741 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
4742 EXPECT_HR(hr
, E_POINTER
);
4744 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
4745 EXPECT_HR(hr
, E_POINTER
);
4747 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
4748 EXPECT_HR(hr
, E_POINTER
);
4750 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, &value
, NULL
);
4751 EXPECT_HR(hr
, E_POINTER
);
4753 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, NULL
, &len
);
4754 EXPECT_HR(hr
, E_POINTER
);
4756 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
), _bstr_(table
->local
),
4757 strlen(table
->local
), NULL
, NULL
);
4758 EXPECT_HR(hr
, E_POINTER
);
4761 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &value
, &len
);
4762 EXPECT_HR(hr
, S_OK
);
4763 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4765 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
4768 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
),
4769 _bstr_(table
->local
), strlen(table
->local
), &value
, &len
);
4770 EXPECT_HR(hr
, S_OK
);
4771 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4773 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
4778 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4779 EXPECT_HR(hr
, S_OK
);
4780 if (table
->hr
== S_OK
)
4781 ok(len
== 1, "%d: got %d length, expected 1\n", i
, len
);
4783 ok(len
== 0, "%d: got %d length, expected 0\n", i
, len
);
4785 ISAXAttributes_Release(saxattr
);
4786 IMXAttributes_Release(mxattr
);
4795 static void test_mxattr_clear(void)
4797 ISAXAttributes
*saxattr
;
4798 IMXAttributes
*mxattr
;
4803 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
4804 &IID_IMXAttributes
, (void**)&mxattr
);
4805 EXPECT_HR(hr
, S_OK
);
4807 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4808 EXPECT_HR(hr
, S_OK
);
4810 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, NULL
);
4811 EXPECT_HR(hr
, E_INVALIDARG
);
4813 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
4814 EXPECT_HR(hr
, E_INVALIDARG
);
4816 hr
= IMXAttributes_clear(mxattr
);
4817 EXPECT_HR(hr
, S_OK
);
4819 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("local"),
4820 _bstr_("qname"), _bstr_("type"), _bstr_("value"));
4821 EXPECT_HR(hr
, S_OK
);
4824 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4825 EXPECT_HR(hr
, S_OK
);
4826 ok(len
== 1, "got %d\n", len
);
4829 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, &len
);
4830 EXPECT_HR(hr
, E_POINTER
);
4831 ok(len
== -1, "got %d\n", len
);
4833 ptr
= (void*)0xdeadbeef;
4834 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, NULL
);
4835 EXPECT_HR(hr
, E_POINTER
);
4836 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
4839 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
4840 EXPECT_HR(hr
, S_OK
);
4841 ok(len
== 5, "got %d\n", len
);
4842 ok(!lstrcmpW(ptr
, _bstr_("qname")), "got %s\n", wine_dbgstr_w(ptr
));
4844 hr
= IMXAttributes_clear(mxattr
);
4845 EXPECT_HR(hr
, S_OK
);
4848 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4849 EXPECT_HR(hr
, S_OK
);
4850 ok(len
== 0, "got %d\n", len
);
4853 ptr
= (void*)0xdeadbeef;
4854 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
4855 EXPECT_HR(hr
, E_INVALIDARG
);
4856 ok(len
== -1, "got %d\n", len
);
4857 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
4859 IMXAttributes_Release(mxattr
);
4860 ISAXAttributes_Release(saxattr
);
4864 static void test_mxattr_dispex(void)
4866 IMXAttributes
*mxattr
;
4867 IDispatchEx
*dispex
;
4871 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
4872 &IID_IMXAttributes
, (void**)&mxattr
);
4873 EXPECT_HR(hr
, S_OK
);
4875 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IDispatchEx
, (void**)&dispex
);
4876 EXPECT_HR(hr
, S_OK
);
4877 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4878 test_obj_dispex(unk
);
4879 IUnknown_Release(unk
);
4880 IDispatchEx_Release(dispex
);
4882 IMXAttributes_Release(mxattr
);
4885 static void test_mxattr_qi(void)
4887 IVBSAXAttributes
*vbsaxattr
, *vbsaxattr2
;
4888 ISAXAttributes
*saxattr
;
4889 IMXAttributes
*mxattr
;
4892 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
4893 &IID_IMXAttributes
, (void**)&mxattr
);
4894 EXPECT_HR(hr
, S_OK
);
4896 EXPECT_REF(mxattr
, 1);
4897 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4898 EXPECT_HR(hr
, S_OK
);
4900 EXPECT_REF(mxattr
, 2);
4901 EXPECT_REF(saxattr
, 2);
4903 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr
);
4904 EXPECT_HR(hr
, S_OK
);
4906 EXPECT_REF(vbsaxattr
, 3);
4907 EXPECT_REF(mxattr
, 3);
4908 EXPECT_REF(saxattr
, 3);
4910 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr2
);
4911 EXPECT_HR(hr
, S_OK
);
4913 EXPECT_REF(vbsaxattr
, 4);
4914 EXPECT_REF(mxattr
, 4);
4915 EXPECT_REF(saxattr
, 4);
4917 IMXAttributes_Release(mxattr
);
4918 ISAXAttributes_Release(saxattr
);
4919 IVBSAXAttributes_Release(vbsaxattr
);
4920 IVBSAXAttributes_Release(vbsaxattr2
);
4923 static struct msxmlsupported_data_t saxattr_support_data
[] =
4925 { &CLSID_SAXAttributes
, "SAXAttributes" },
4926 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
4927 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
4928 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
4932 static void test_mxattr_localname(void)
4934 static const WCHAR localname1W
[] = {'l','o','c','a','l','n','a','m','e','1',0};
4935 static const WCHAR localnameW
[] = {'l','o','c','a','l','n','a','m','e',0};
4936 static const WCHAR uri1W
[] = {'u','r','i','1',0};
4937 static const WCHAR uriW
[] = {'u','r','i',0};
4939 const struct msxmlsupported_data_t
*table
= saxattr_support_data
;
4941 while (table
->clsid
)
4943 ISAXAttributes
*saxattr
;
4944 IMXAttributes
*mxattr
;
4948 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
4954 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4955 &IID_IMXAttributes
, (void**)&mxattr
);
4956 EXPECT_HR(hr
, S_OK
);
4958 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4959 EXPECT_HR(hr
, S_OK
);
4961 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, &index
);
4962 EXPECT_HR(hr
, E_INVALIDARG
);
4964 /* add some ambiguos attribute names */
4965 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
4966 _bstr_("a:localname"), _bstr_(""), _bstr_("value"));
4967 EXPECT_HR(hr
, S_OK
);
4968 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
4969 _bstr_("b:localname"), _bstr_(""), _bstr_("value"));
4970 EXPECT_HR(hr
, S_OK
);
4973 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localnameW
, lstrlenW(localnameW
), &index
);
4974 EXPECT_HR(hr
, S_OK
);
4975 ok(index
== 0, "%s: got index %d\n", table
->name
, index
);
4978 hr
= ISAXAttributes_getIndexFromName(saxattr
, uri1W
, lstrlenW(uri1W
), localnameW
, lstrlenW(localnameW
), &index
);
4979 EXPECT_HR(hr
, E_INVALIDARG
);
4980 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
4983 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), &index
);
4984 EXPECT_HR(hr
, E_INVALIDARG
);
4985 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
4987 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4988 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4990 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
4991 EXPECT_HR(hr
, E_POINTER
);
4993 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
4994 EXPECT_HR(hr
, E_POINTER
);
4998 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
4999 EXPECT_HR(hr
, E_INVALIDARG
);
5001 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
5002 EXPECT_HR(hr
, E_INVALIDARG
);
5005 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), NULL
, 0, &index
);
5006 EXPECT_HR(hr
, E_INVALIDARG
);
5008 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, localname1W
, lstrlenW(localname1W
), &index
);
5009 EXPECT_HR(hr
, E_INVALIDARG
);
5013 ISAXAttributes_Release(saxattr
);
5014 IMXAttributes_Release(mxattr
);
5018 START_TEST(saxreader
)
5020 ISAXXMLReader
*reader
;
5023 hr
= CoInitialize(NULL
);
5024 ok(hr
== S_OK
, "failed to init com\n");
5026 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
5027 &IID_ISAXXMLReader
, (void**)&reader
);
5031 skip("Failed to create SAXXMLReader instance\n");
5035 ISAXXMLReader_Release(reader
);
5037 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
5039 get_class_support_data(reader_support_data
, &IID_ISAXXMLReader
);
5042 test_saxreader_properties();
5043 test_saxreader_features();
5044 test_saxreader_encoding();
5047 /* MXXMLWriter tests */
5048 get_class_support_data(mxwriter_support_data
, &IID_IMXWriter
);
5049 if (is_clsid_supported(&CLSID_MXXMLWriter
, mxwriter_support_data
))
5051 test_mxwriter_handlers();
5052 test_mxwriter_startenddocument();
5053 test_mxwriter_startendelement();
5054 test_mxwriter_characters();
5055 test_mxwriter_comment();
5056 test_mxwriter_cdata();
5058 test_mxwriter_ignorablespaces();
5059 test_mxwriter_dtd();
5060 test_mxwriter_properties();
5061 test_mxwriter_flush();
5062 test_mxwriter_stream();
5063 test_mxwriter_encoding();
5064 test_mxwriter_dispex();
5067 win_skip("MXXMLWriter not supported\n");
5069 /* SAXAttributes tests */
5070 get_class_support_data(mxattributes_support_data
, &IID_IMXAttributes
);
5071 if (is_clsid_supported(&CLSID_SAXAttributes
, mxattributes_support_data
))
5074 test_mxattr_addAttribute();
5075 test_mxattr_clear();
5076 test_mxattr_localname();
5077 test_mxattr_dispex();
5080 skip("SAXAttributes not supported\n");