2 * SAXReader/MXWriter tests
4 * Copyright 2008 Piotr Caban
5 * Copyright 2011 Thomas Mullaly
6 * Copyright 2012 Nikolay Sivov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define WIN32_NO_STATUS
25 #define COM_NO_WINDOWS_H
33 #include <wine/test.h>
34 //#include "windows.h"
38 #include <msxml2did.h>
42 static const WCHAR emptyW
[] = {0};
44 #define EXPECT_HR(hr,hr_exp) \
45 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
47 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
48 static void _expect_ref(IUnknown
* obj
, ULONG ref
, int line
)
50 ULONG rc
= IUnknown_AddRef(obj
);
51 IUnknown_Release(obj
);
52 ok_(__FILE__
,line
)(rc
-1 == ref
, "expected refcount %d, got %d\n", ref
, rc
-1);
55 static LONG
get_refcount(void *iface
)
57 IUnknown
*unk
= iface
;
60 ref
= IUnknown_AddRef(unk
);
61 IUnknown_Release(unk
);
65 struct msxmlsupported_data_t
72 static BOOL
is_clsid_supported(const GUID
*clsid
, const struct msxmlsupported_data_t
*table
)
76 if (table
->clsid
== clsid
) return table
->supported
;
82 static BSTR
alloc_str_from_narrow(const char *str
)
84 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
85 BSTR ret
= SysAllocStringLen(NULL
, len
- 1); /* NUL character added automatically */
86 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
90 static BSTR alloced_bstrs
[512];
91 static int alloced_bstrs_count
;
93 static BSTR
_bstr_(const char *str
)
95 assert(alloced_bstrs_count
< sizeof(alloced_bstrs
)/sizeof(alloced_bstrs
[0]));
96 alloced_bstrs
[alloced_bstrs_count
] = alloc_str_from_narrow(str
);
97 return alloced_bstrs
[alloced_bstrs_count
++];
100 static void free_bstrs(void)
103 for (i
= 0; i
< alloced_bstrs_count
; i
++)
104 SysFreeString(alloced_bstrs
[i
]);
105 alloced_bstrs_count
= 0;
108 static void test_saxstr(const char *file
, unsigned line
, BSTR str
, const char *expected
, BOOL todo
, int *failcount
)
110 int len
, lenexp
, cmp
;
113 len
= SysStringLen(str
);
120 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
123 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
129 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
132 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
136 lenexp
= strlen(expected
);
137 if (lenexp
!= len
&& todo
)
141 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
144 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
146 /* exit earlier on length mismatch */
147 if (lenexp
!= len
) return;
149 MultiByteToWideChar(CP_ACP
, 0, expected
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
151 cmp
= memcmp(str
, buf
, lenexp
*sizeof(WCHAR
));
156 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
157 wine_dbgstr_wn(str
, len
), expected
);
160 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
161 wine_dbgstr_wn(str
, len
), expected
);
166 CH_PUTDOCUMENTLOCATOR
,
169 CH_STARTPREFIXMAPPING
,
174 CH_IGNORABLEWHITESPACE
,
175 CH_PROCESSINGINSTRUCTION
,
185 static const char *event_names
[EVENT_LAST
] = {
187 "putDocumentLocator",
190 "startPrefixMapping",
195 "ignorableWhitespace",
196 "processingInstruction",
205 struct attribute_entry
{
211 /* used for actual call data only, null for expected call data */
227 /* allocated once at startElement callback */
228 struct attribute_entry
*attributes
;
231 /* used for actual call data only, null for expected call data */
241 struct call_entry
*sequence
;
244 #define CONTENT_HANDLER_INDEX 0
245 #define NUM_CALL_SEQUENCES 1
246 static struct call_sequence
*sequences
[NUM_CALL_SEQUENCES
];
248 static void init_call_entry(ISAXLocator
*locator
, struct call_entry
*call
)
250 memset(call
, 0, sizeof(*call
));
251 ISAXLocator_getLineNumber(locator
, &call
->line
);
252 ISAXLocator_getColumnNumber(locator
, &call
->column
);
255 static void add_call(struct call_sequence
**seq
, int sequence_index
,
256 const struct call_entry
*call
)
258 struct call_sequence
*call_seq
= seq
[sequence_index
];
260 if (!call_seq
->sequence
)
263 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0,
264 call_seq
->size
* sizeof (struct call_entry
));
267 if (call_seq
->count
== call_seq
->size
)
270 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
272 call_seq
->size
* sizeof (struct call_entry
));
275 assert(call_seq
->sequence
);
277 call_seq
->sequence
[call_seq
->count
].id
= call
->id
;
278 call_seq
->sequence
[call_seq
->count
].line
= call
->line
;
279 call_seq
->sequence
[call_seq
->count
].column
= call
->column
;
280 call_seq
->sequence
[call_seq
->count
].arg1W
= call
->arg1W
;
281 call_seq
->sequence
[call_seq
->count
].arg2W
= call
->arg2W
;
282 call_seq
->sequence
[call_seq
->count
].arg3W
= call
->arg3W
;
283 call_seq
->sequence
[call_seq
->count
].ret
= call
->ret
;
284 call_seq
->sequence
[call_seq
->count
].attr_count
= call
->attr_count
;
285 call_seq
->sequence
[call_seq
->count
].attributes
= call
->attributes
;
290 static inline void flush_sequence(struct call_sequence
**seg
, int sequence_index
)
294 struct call_sequence
*call_seq
= seg
[sequence_index
];
296 for (i
= 0; i
< call_seq
->count
; i
++)
300 for (j
= 0; j
< call_seq
->sequence
[i
].attr_count
; j
++)
302 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].uriW
);
303 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].localW
);
304 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].qnameW
);
307 SysFreeString(call_seq
->sequence
[i
].arg1W
);
308 SysFreeString(call_seq
->sequence
[i
].arg2W
);
309 SysFreeString(call_seq
->sequence
[i
].arg3W
);
312 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
313 call_seq
->sequence
= NULL
;
314 call_seq
->count
= call_seq
->size
= 0;
317 static const char *get_event_name(CH event
)
319 return event_names
[event
];
322 static void compare_attributes(const struct call_entry
*actual
, const struct call_entry
*expected
, const char *context
,
323 BOOL todo
, const char *file
, int line
, int *failcount
)
327 /* attribute count is not stored for expected data */
328 if (expected
->attributes
)
330 struct attribute_entry
*ptr
= expected
->attributes
;
331 while (ptr
->uri
) { lenexp
++; ptr
++; };
334 /* check count first and exit earlier */
335 if (actual
->attr_count
!= lenexp
&& todo
)
339 ok_(file
, line
) (FALSE
, "%s: in event %s expecting attr count %d got %d\n",
340 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
343 ok_(file
, line
) (actual
->attr_count
== lenexp
, "%s: in event %s expecting attr count %d got %d\n",
344 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
346 if (actual
->attr_count
!= lenexp
) return;
348 /* now compare all attributes strings */
349 for (i
= 0; i
< actual
->attr_count
; i
++)
351 test_saxstr(file
, line
, actual
->attributes
[i
].uriW
, expected
->attributes
[i
].uri
, todo
, failcount
);
352 test_saxstr(file
, line
, actual
->attributes
[i
].localW
, expected
->attributes
[i
].local
, todo
, failcount
);
353 test_saxstr(file
, line
, actual
->attributes
[i
].qnameW
, expected
->attributes
[i
].qname
, todo
, failcount
);
354 test_saxstr(file
, line
, actual
->attributes
[i
].valueW
, expected
->attributes
[i
].value
, todo
, failcount
);
358 static void ok_sequence_(struct call_sequence
**seq
, int sequence_index
,
359 const struct call_entry
*expected
, const char *context
, BOOL todo
,
360 const char *file
, int line
)
362 struct call_sequence
*call_seq
= seq
[sequence_index
];
363 static const struct call_entry end_of_sequence
= { CH_ENDTEST
};
364 const struct call_entry
*actual
, *sequence
;
367 add_call(seq
, sequence_index
, &end_of_sequence
);
369 sequence
= call_seq
->sequence
;
372 while (expected
->id
!= CH_ENDTEST
&& actual
->id
!= CH_ENDTEST
)
374 if (expected
->id
== actual
->id
)
376 if (expected
->line
!= -1)
378 /* always test position data */
379 if (expected
->line
!= actual
->line
&& todo
)
384 ok_(file
, line
) (FALSE
,
385 "%s: in event %s expecting line %d got %d\n",
386 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
391 ok_(file
, line
) (expected
->line
== actual
->line
,
392 "%s: in event %s expecting line %d got %d\n",
393 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
398 if (expected
->column
!= -1)
400 if (expected
->column
!= actual
->column
&& todo
)
405 ok_(file
, line
) (FALSE
,
406 "%s: in event %s expecting column %d got %d\n",
407 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
412 ok_(file
, line
) (expected
->column
== actual
->column
,
413 "%s: in event %s expecting column %d got %d\n",
414 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
420 case CH_PUTDOCUMENTLOCATOR
:
421 case CH_STARTDOCUMENT
:
426 case CH_STARTPREFIXMAPPING
:
428 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
429 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
431 case CH_ENDPREFIXMAPPING
:
433 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
435 case CH_STARTELEMENT
:
436 /* compare attributes */
437 compare_attributes(actual
, expected
, context
, todo
, file
, line
, &failcount
);
440 /* uri, localname, qname */
441 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
442 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
443 test_saxstr(file
, line
, actual
->arg3W
, expected
->arg3
, todo
, &failcount
);
446 case CH_IGNORABLEWHITESPACE
:
448 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
450 case CH_PROCESSINGINSTRUCTION
:
452 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
453 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
455 case CH_SKIPPEDENTITY
:
457 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
460 /* test return value only */
461 if (expected
->ret
!= actual
->ret
&& todo
)
464 ok_(file
, line
) (FALSE
,
465 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
466 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
469 ok_(file
, line
) (expected
->ret
== actual
->ret
,
470 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
471 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
474 case EH_IGNORABLEWARNING
:
476 ok(0, "%s: callback not handled, %s\n", context
, get_event_name(actual
->id
));
486 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
487 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
490 flush_sequence(seq
, sequence_index
);
495 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
496 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
506 if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
509 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
510 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
514 else if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
516 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
517 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
520 if (todo
&& !failcount
) /* succeeded yet marked todo */
524 ok_(file
, line
)(TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
528 flush_sequence(seq
, sequence_index
);
531 #define ok_sequence(seq, index, exp, contx, todo) \
532 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
534 static void init_call_sequences(struct call_sequence
**seq
, int n
)
538 for (i
= 0; i
< n
; i
++)
539 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct call_sequence
));
542 static const WCHAR szSimpleXML
[] = {
543 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
544 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
545 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
546 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
547 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
550 static const WCHAR carriage_ret_test
[] = {
551 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
552 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
553 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
554 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
555 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
558 static const WCHAR szUtf16XML
[] = {
559 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
560 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
561 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
564 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
566 static const CHAR szUtf8XML
[] =
567 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
569 static const char utf8xml2
[] =
570 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n";
572 static const char testXML
[] =
573 "<?xml version=\"1.0\" ?>\n"
575 " <Number>1234</Number>\n"
576 " <Name>Captain Ahab</Name>\n"
579 static const char test_attributes
[] =
580 "<?xml version=\"1.0\" ?>\n"
581 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
582 "<node1 xmlns:p=\"test\" />"
585 static const char test_cdata_xml
[] =
586 "<?xml version=\"1.0\" ?>"
587 "<a><![CDATA[Some \r\ntext\n\r\ndata\n\n]]></a>";
589 static const char test2_cdata_xml
[] =
590 "<?xml version=\"1.0\" ?>"
591 "<a><![CDATA[\n\r\nSome \r\ntext\n\r\ndata\n\n]]></a>";
593 static const char test3_cdata_xml
[] =
594 "<?xml version=\"1.0\" ?><a><![CDATA[Some text data]]></a>";
596 static struct call_entry content_handler_test1
[] = {
597 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
598 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
599 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
600 { CH_CHARACTERS
, 2, 14, S_OK
, "\n " },
601 { CH_STARTELEMENT
, 3, 12, S_OK
, "", "Number", "Number" },
602 { CH_CHARACTERS
, 3, 12, S_OK
, "1234" },
603 { CH_ENDELEMENT
, 3, 18, S_OK
, "", "Number", "Number" },
604 { CH_CHARACTERS
, 3, 25, S_OK
, "\n " },
605 { CH_STARTELEMENT
, 4, 10, S_OK
, "", "Name", "Name" },
606 { CH_CHARACTERS
, 4, 10, S_OK
, "Captain Ahab" },
607 { CH_ENDELEMENT
, 4, 24, S_OK
, "", "Name", "Name" },
608 { CH_CHARACTERS
, 4, 29, S_OK
, "\n" },
609 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
610 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
614 /* applies to versions 4 and 6 */
615 static struct call_entry content_handler_test1_alternate
[] = {
616 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
617 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
618 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
619 { CH_CHARACTERS
, 3, 4, S_OK
, "\n " },
620 { CH_STARTELEMENT
, 3, 11, S_OK
, "", "Number", "Number" },
621 { CH_CHARACTERS
, 3, 16, S_OK
, "1234" },
622 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "Number", "Number" },
623 { CH_CHARACTERS
, 4, 4, S_OK
, "\n " },
624 { CH_STARTELEMENT
, 4, 9, S_OK
, "", "Name", "Name" },
625 { CH_CHARACTERS
, 4, 22, S_OK
, "Captain Ahab" },
626 { CH_ENDELEMENT
, 4, 28, S_OK
, "", "Name", "Name" },
627 { CH_CHARACTERS
, 5, 1, S_OK
, "\n" },
628 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
629 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
633 static struct call_entry content_handler_test2
[] = {
634 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
635 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
636 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
637 { CH_CHARACTERS
, 2, 14, S_OK
, "\n" },
638 { CH_CHARACTERS
, 2, 16, S_OK
, "\t" },
639 { CH_STARTELEMENT
, 3, 10, S_OK
, "", "Number", "Number" },
640 { CH_CHARACTERS
, 3, 10, S_OK
, "1234" },
641 { CH_ENDELEMENT
, 3, 16, S_OK
, "", "Number", "Number" },
642 { CH_CHARACTERS
, 3, 23, S_OK
, "\n" },
643 { CH_CHARACTERS
, 3, 25, S_OK
, "\t" },
644 { CH_STARTELEMENT
, 4, 8, S_OK
, "", "Name", "Name" },
645 { CH_CHARACTERS
, 4, 8, S_OK
, "Captain Ahab" },
646 { CH_ENDELEMENT
, 4, 22, S_OK
, "", "Name", "Name" },
647 { CH_CHARACTERS
, 4, 27, S_OK
, "\n" },
648 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
649 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
653 static struct call_entry content_handler_test2_alternate
[] = {
654 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
655 { CH_STARTDOCUMENT
, 1, 21, S_OK
},
656 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
657 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
658 { CH_CHARACTERS
, 3, 2, S_OK
, "\t" },
659 { CH_STARTELEMENT
, 3, 9, S_OK
, "", "Number", "Number" },
660 { CH_CHARACTERS
, 3, 14, S_OK
, "1234" },
661 { CH_ENDELEMENT
, 3, 22, S_OK
, "", "Number", "Number" },
662 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
663 { CH_CHARACTERS
, 4, 2, S_OK
, "\t" },
664 { CH_STARTELEMENT
, 4, 7, S_OK
, "", "Name", "Name" },
665 { CH_CHARACTERS
, 4, 20, S_OK
, "Captain Ahab" },
666 { CH_ENDELEMENT
, 4, 26, S_OK
, "", "Name", "Name" },
667 { CH_CHARACTERS
, 5, 0, S_OK
, "\n" },
668 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
669 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
673 static struct call_entry content_handler_testerror
[] = {
674 { CH_PUTDOCUMENTLOCATOR
, 0, 0, E_FAIL
},
675 { EH_FATALERROR
, 0, 0, E_FAIL
},
679 static struct call_entry content_handler_testerror_alternate
[] = {
680 { CH_PUTDOCUMENTLOCATOR
, 1, 0, E_FAIL
},
681 { EH_FATALERROR
, 1, 0, E_FAIL
},
685 static struct call_entry content_handler_test_callback_rets
[] = {
686 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_FALSE
},
687 { CH_STARTDOCUMENT
, 0, 0, S_FALSE
},
688 { EH_FATALERROR
, 0, 0, S_FALSE
},
692 static struct call_entry content_handler_test_callback_rets_alt
[] = {
693 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_FALSE
},
694 { CH_STARTDOCUMENT
, 1, 22, S_FALSE
},
695 { CH_STARTELEMENT
, 2, 13, S_FALSE
, "", "BankAccount", "BankAccount" },
696 { CH_CHARACTERS
, 3, 4, S_FALSE
, "\n " },
697 { CH_STARTELEMENT
, 3, 11, S_FALSE
, "", "Number", "Number" },
698 { CH_CHARACTERS
, 3, 16, S_FALSE
, "1234" },
699 { CH_ENDELEMENT
, 3, 24, S_FALSE
, "", "Number", "Number" },
700 { CH_CHARACTERS
, 4, 4, S_FALSE
, "\n " },
701 { CH_STARTELEMENT
, 4, 9, S_FALSE
, "", "Name", "Name" },
702 { CH_CHARACTERS
, 4, 22, S_FALSE
, "Captain Ahab" },
703 { CH_ENDELEMENT
, 4, 28, S_FALSE
, "", "Name", "Name" },
704 { CH_CHARACTERS
, 5, 1, S_FALSE
, "\n" },
705 { CH_ENDELEMENT
, 5, 14, S_FALSE
, "", "BankAccount", "BankAccount" },
706 { CH_ENDDOCUMENT
, 6, 0, S_FALSE
},
710 static struct attribute_entry ch_attributes1
[] = {
711 { "", "", "xmlns:test", "prefix_test" },
712 { "", "", "xmlns", "prefix" },
713 { "prefix_test", "arg1", "test:arg1", "arg1" },
714 { "", "arg2", "arg2", "arg2" },
715 { "prefix_test", "ar3", "test:ar3", "arg3" },
719 static struct attribute_entry ch_attributes2
[] = {
720 { "", "", "xmlns:p", "test" },
724 static struct call_entry content_handler_test_attributes
[] = {
725 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
726 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
727 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
728 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
729 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes1
},
730 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
731 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
732 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
733 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
734 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
735 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
736 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
737 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
738 { CH_ENDDOCUMENT
, 0, 0 },
742 static struct attribute_entry ch_attributes_alt_4
[] = {
743 { "prefix_test", "arg1", "test:arg1", "arg1" },
744 { "", "arg2", "arg2", "arg2" },
745 { "prefix_test", "ar3", "test:ar3", "arg3" },
746 { "", "", "xmlns:test", "prefix_test" },
747 { "", "", "xmlns", "prefix" },
751 static struct call_entry content_handler_test_attributes_alternate_4
[] = {
752 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
753 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
754 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
755 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
756 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_4
},
757 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
758 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
759 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
760 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
761 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
762 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
763 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
764 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
765 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
769 /* 'namespace' feature switched off */
770 static struct attribute_entry ch_attributes_alt_no_ns
[] = {
771 { "", "", "xmlns:test", "prefix_test" },
772 { "", "", "xmlns", "prefix" },
773 { "", "", "test:arg1", "arg1" },
774 { "", "", "arg2", "arg2" },
775 { "", "", "test:ar3", "arg3" },
779 static struct call_entry content_handler_test_attributes_alt_no_ns
[] = {
780 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
781 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
782 { CH_STARTELEMENT
, 2, 95, S_OK
, "", "", "document", ch_attributes_alt_no_ns
},
783 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
784 { CH_STARTELEMENT
, 3, 24, S_OK
, "", "", "node1", ch_attributes2
},
785 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "", "node1" },
786 { CH_ENDELEMENT
, 3, 35, S_OK
, "", "", "document" },
787 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
791 static struct attribute_entry ch_attributes_alt_6
[] = {
792 { "prefix_test", "arg1", "test:arg1", "arg1" },
793 { "", "arg2", "arg2", "arg2" },
794 { "prefix_test", "ar3", "test:ar3", "arg3" },
795 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
796 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
800 static struct attribute_entry ch_attributes2_6
[] = {
801 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
805 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
806 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
807 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
808 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
809 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
810 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
811 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
812 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
813 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
814 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
815 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
816 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
817 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
818 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
819 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
823 /* 'namespaces' is on, 'namespace-prefixes' if off */
824 static struct attribute_entry ch_attributes_no_prefix
[] = {
825 { "prefix_test", "arg1", "test:arg1", "arg1" },
826 { "", "arg2", "arg2", "arg2" },
827 { "prefix_test", "ar3", "test:ar3", "arg3" },
831 static struct call_entry content_handler_test_attributes_alt_no_prefix
[] = {
832 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
833 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
834 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
835 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
836 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
837 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
838 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
839 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", NULL
},
840 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
841 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
842 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
843 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
844 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
845 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
849 static struct call_entry content_handler_test_attributes_no_prefix
[] = {
850 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
851 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
852 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
853 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
854 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
855 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
856 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
857 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", NULL
},
858 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
859 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
860 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
861 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
862 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
863 { CH_ENDDOCUMENT
, 0, 0 },
867 static struct attribute_entry xmlspace_attrs
[] = {
868 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
872 static struct call_entry xmlspaceattr_test
[] = {
873 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
874 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
875 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
876 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
877 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
878 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
882 static struct call_entry xmlspaceattr_test_alternate
[] = {
883 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
884 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
885 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
886 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
887 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
888 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
892 /* attribute value normalization test */
893 static const char attribute_normalize
[] =
894 "<?xml version=\"1.0\" ?>\n"
895 "<a attr1=\" \r \n \tattr_value A & &\t \r \n\r\n \n\"/>\n";
897 static struct attribute_entry attribute_norm_attrs
[] = {
898 { "", "attr1", "attr1", " attr_value A & & " },
902 static struct call_entry attribute_norm
[] = {
903 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
904 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
905 { CH_STARTELEMENT
, 6, 4, S_OK
, "", "a", "a", attribute_norm_attrs
},
906 { CH_ENDELEMENT
, 6, 4, S_OK
, "", "a", "a" },
907 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
911 static struct call_entry attribute_norm_alt
[] = {
912 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
913 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
914 { CH_STARTELEMENT
, 8, 3, S_OK
, "", "a", "a", attribute_norm_attrs
},
915 { CH_ENDELEMENT
, 8, 3, S_OK
, "", "a", "a" },
916 { CH_ENDDOCUMENT
, 9, 0, S_OK
},
920 static struct call_entry cdata_test
[] = {
921 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
922 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
923 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
924 { LH_STARTCDATA
, 1, 35, S_OK
},
925 { CH_CHARACTERS
, 1, 35, S_OK
, "Some \n" },
926 { CH_CHARACTERS
, 1, 42, S_OK
, "text\n\n" },
927 { CH_CHARACTERS
, 1, 49, S_OK
, "data\n\n" },
928 { LH_ENDCDATA
, 1, 49, S_OK
},
929 { CH_ENDELEMENT
, 6, 6, S_OK
, "", "a", "a" },
930 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
934 static struct call_entry cdata_test2
[] = {
935 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
936 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
937 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
938 { LH_STARTCDATA
, 1, 35, S_OK
},
939 { CH_CHARACTERS
, 1, 35, S_OK
, "\n\n" },
940 { CH_CHARACTERS
, 1, 38, S_OK
, "Some \n" },
941 { CH_CHARACTERS
, 1, 45, S_OK
, "text\n\n" },
942 { CH_CHARACTERS
, 1, 52, S_OK
, "data\n\n" },
943 { LH_ENDCDATA
, 1, 52, S_OK
},
944 { CH_ENDELEMENT
, 8, 6, S_OK
, "", "a", "a" },
945 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
949 static struct call_entry cdata_test3
[] = {
950 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
951 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
952 { CH_STARTELEMENT
, 1, 26, S_OK
, "", "a", "a" },
953 { LH_STARTCDATA
, 1, 35, S_OK
},
954 { CH_CHARACTERS
, 1, 35, S_OK
, "Some text data" },
955 { LH_ENDCDATA
, 1, 35, S_OK
},
956 { CH_ENDELEMENT
, 1, 54, S_OK
, "", "a", "a" },
957 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
961 /* this is what MSXML6 does */
962 static struct call_entry cdata_test_alt
[] = {
963 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
964 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
965 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
966 { LH_STARTCDATA
, 1, 34, S_OK
},
967 { CH_CHARACTERS
, 1, 40, S_OK
, "Some " },
968 { CH_CHARACTERS
, 2, 0, S_OK
, "\n" },
969 { CH_CHARACTERS
, 3, 1, S_OK
, "text\n" },
970 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
971 { CH_CHARACTERS
, 6, 3, S_OK
, "data\n\n" },
972 { LH_ENDCDATA
, 6, 3, S_OK
},
973 { CH_ENDELEMENT
, 6, 7, S_OK
, "", "a", "a" },
974 { CH_ENDDOCUMENT
, 6, 7, S_OK
},
978 static struct call_entry cdata_test2_alt
[] = {
979 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
980 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
981 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
982 { LH_STARTCDATA
, 1, 34, S_OK
},
983 { CH_CHARACTERS
, 2, 1, S_OK
, "\n" },
984 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
985 { CH_CHARACTERS
, 3, 6, S_OK
, "Some " },
986 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
987 { CH_CHARACTERS
, 5, 1, S_OK
, "text\n" },
988 { CH_CHARACTERS
, 6, 0, S_OK
, "\n" },
989 { CH_CHARACTERS
, 8, 3, S_OK
, "data\n\n" },
990 { LH_ENDCDATA
, 8, 3, S_OK
},
991 { CH_ENDELEMENT
, 8, 7, S_OK
, "", "a", "a" },
992 { CH_ENDDOCUMENT
, 8, 7, S_OK
},
996 static struct call_entry cdata_test3_alt
[] = {
997 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
998 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
999 { CH_STARTELEMENT
, 1, 25, S_OK
, "", "a", "a" },
1000 { LH_STARTCDATA
, 1, 34, S_OK
},
1001 { CH_CHARACTERS
, 1, 51, S_OK
, "Some text data" },
1002 { LH_ENDCDATA
, 1, 51, S_OK
},
1003 { CH_ENDELEMENT
, 1, 55, S_OK
, "", "a", "a" },
1004 { CH_ENDDOCUMENT
, 1, 55, S_OK
},
1008 static struct attribute_entry read_test_attrs
[] = {
1009 { "", "attr", "attr", "val" },
1013 static struct call_entry read_test_seq
[] = {
1014 { CH_PUTDOCUMENTLOCATOR
, -1, 0, S_OK
},
1015 { CH_STARTDOCUMENT
, -1, -1, S_OK
},
1016 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1017 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1018 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1019 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1020 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1021 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1022 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1023 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1024 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1025 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1026 { CH_STARTELEMENT
, -1, -1, S_OK
, "", "elem", "elem", read_test_attrs
},
1027 { CH_CHARACTERS
, -1, -1, S_OK
, "text" },
1028 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "elem", "elem" },
1029 { CH_ENDELEMENT
, -1, -1, S_OK
, "", "rootelem", "rootelem" },
1030 { CH_ENDDOCUMENT
, -1, -1, S_OK
},
1034 static const char xmlspace_attr
[] =
1035 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
1036 "<a xml:space=\"preserve\"> Some text data </a>";
1038 static struct call_entry
*expectCall
;
1039 static ISAXLocator
*locator
;
1040 static ISAXXMLReader
*g_reader
;
1043 static void set_expected_seq(struct call_entry
*expected
)
1045 expectCall
= expected
;
1048 /* to be called once on each tested callback return */
1049 static HRESULT
get_expected_ret(void)
1051 HRESULT hr
= expectCall
->ret
;
1052 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
1056 static HRESULT WINAPI
contentHandler_QueryInterface(
1057 ISAXContentHandler
* iface
,
1063 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
1069 return E_NOINTERFACE
;
1075 static ULONG WINAPI
contentHandler_AddRef(
1076 ISAXContentHandler
* iface
)
1081 static ULONG WINAPI
contentHandler_Release(
1082 ISAXContentHandler
* iface
)
1087 static HRESULT WINAPI
contentHandler_putDocumentLocator(
1088 ISAXContentHandler
* iface
,
1089 ISAXLocator
*pLocator
)
1091 struct call_entry call
;
1097 init_call_entry(locator
, &call
);
1098 call
.id
= CH_PUTDOCUMENTLOCATOR
;
1099 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1101 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXLocator
, (void**)&unk
);
1102 EXPECT_HR(hr
, E_NOINTERFACE
);
1104 if (msxml_version
>= 6) {
1105 ISAXAttributes
*attr
, *attr1
;
1106 IMXAttributes
*mxattr
;
1108 EXPECT_REF(pLocator
, 1);
1109 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
1110 EXPECT_HR(hr
, S_OK
);
1111 EXPECT_REF(pLocator
, 2);
1112 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
1113 EXPECT_HR(hr
, S_OK
);
1114 EXPECT_REF(pLocator
, 3);
1115 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
1117 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IVBSAXAttributes
, (void**)&unk
);
1118 EXPECT_HR(hr
, E_NOINTERFACE
);
1120 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_IVBSAXAttributes
, (void**)&unk
);
1121 EXPECT_HR(hr
, E_NOINTERFACE
);
1123 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
1124 EXPECT_HR(hr
, E_NOINTERFACE
);
1126 ISAXAttributes_Release(attr
);
1127 ISAXAttributes_Release(attr1
);
1130 return get_expected_ret();
1133 static ISAXAttributes
*test_attr_ptr
;
1134 static HRESULT WINAPI
contentHandler_startDocument(
1135 ISAXContentHandler
* iface
)
1137 struct call_entry call
;
1139 init_call_entry(locator
, &call
);
1140 call
.id
= CH_STARTDOCUMENT
;
1141 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1143 test_attr_ptr
= NULL
;
1145 return get_expected_ret();
1148 static HRESULT WINAPI
contentHandler_endDocument(
1149 ISAXContentHandler
* iface
)
1151 struct call_entry call
;
1153 init_call_entry(locator
, &call
);
1154 call
.id
= CH_ENDDOCUMENT
;
1155 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1157 return get_expected_ret();
1160 static HRESULT WINAPI
contentHandler_startPrefixMapping(
1161 ISAXContentHandler
* iface
,
1162 const WCHAR
*prefix
, int prefix_len
,
1163 const WCHAR
*uri
, int uri_len
)
1165 struct call_entry call
;
1167 init_call_entry(locator
, &call
);
1168 call
.id
= CH_STARTPREFIXMAPPING
;
1169 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
1170 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
1171 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1173 return get_expected_ret();
1176 static HRESULT WINAPI
contentHandler_endPrefixMapping(
1177 ISAXContentHandler
* iface
,
1178 const WCHAR
*prefix
, int len
)
1180 struct call_entry call
;
1182 init_call_entry(locator
, &call
);
1183 call
.id
= CH_ENDPREFIXMAPPING
;
1184 call
.arg1W
= SysAllocStringLen(prefix
, len
);
1185 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1187 return get_expected_ret();
1190 static HRESULT WINAPI
contentHandler_startElement(
1191 ISAXContentHandler
* iface
,
1192 const WCHAR
*uri
, int uri_len
,
1193 const WCHAR
*localname
, int local_len
,
1194 const WCHAR
*qname
, int qname_len
,
1195 ISAXAttributes
*saxattr
)
1197 struct call_entry call
;
1198 IMXAttributes
*mxattr
;
1202 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
1203 EXPECT_HR(hr
, E_NOINTERFACE
);
1205 init_call_entry(locator
, &call
);
1206 call
.id
= CH_STARTELEMENT
;
1207 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1208 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1209 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1212 test_attr_ptr
= saxattr
;
1213 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
1215 /* store actual attributes */
1217 hr
= ISAXAttributes_getLength(saxattr
, &len
);
1218 EXPECT_HR(hr
, S_OK
);
1225 struct attribute_entry
*attr
;
1226 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
1229 hr
= ISAXXMLReader_getFeature(g_reader
, _bstr_("http://xml.org/sax/features/namespaces"), &v
);
1230 EXPECT_HR(hr
, S_OK
);
1232 for (i
= 0; i
< len
; i
++)
1237 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
1238 &localname
, &local_len
, &qname
, &qname_len
);
1239 EXPECT_HR(hr
, S_OK
);
1241 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
1242 EXPECT_HR(hr
, S_OK
);
1244 /* if 'namespaces' switched off uri and local name contains garbage */
1245 if (v
== VARIANT_FALSE
&& msxml_version
> 0)
1247 attr
[i
].uriW
= SysAllocStringLen(NULL
, 0);
1248 attr
[i
].localW
= SysAllocStringLen(NULL
, 0);
1252 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
1253 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
1256 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
1257 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
1260 call
.attributes
= attr
;
1261 call
.attr_count
= len
;
1264 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1266 return get_expected_ret();
1269 static HRESULT WINAPI
contentHandler_endElement(
1270 ISAXContentHandler
* iface
,
1271 const WCHAR
*uri
, int uri_len
,
1272 const WCHAR
*localname
, int local_len
,
1273 const WCHAR
*qname
, int qname_len
)
1275 struct call_entry call
;
1277 init_call_entry(locator
, &call
);
1278 call
.id
= CH_ENDELEMENT
;
1279 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1280 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1281 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1282 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1284 return get_expected_ret();
1287 static HRESULT WINAPI
contentHandler_characters(
1288 ISAXContentHandler
* iface
,
1292 struct call_entry call
;
1294 init_call_entry(locator
, &call
);
1295 call
.id
= CH_CHARACTERS
;
1296 call
.arg1W
= SysAllocStringLen(chars
, len
);
1297 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1299 return get_expected_ret();
1302 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1303 ISAXContentHandler
* iface
,
1304 const WCHAR
*chars
, int len
)
1306 struct call_entry call
;
1308 init_call_entry(locator
, &call
);
1309 call
.id
= CH_IGNORABLEWHITESPACE
;
1310 call
.arg1W
= SysAllocStringLen(chars
, len
);
1311 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1313 return get_expected_ret();
1316 static HRESULT WINAPI
contentHandler_processingInstruction(
1317 ISAXContentHandler
* iface
,
1318 const WCHAR
*target
, int target_len
,
1319 const WCHAR
*data
, int data_len
)
1321 struct call_entry call
;
1323 init_call_entry(locator
, &call
);
1324 call
.id
= CH_PROCESSINGINSTRUCTION
;
1325 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1326 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1327 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1329 return get_expected_ret();
1332 static HRESULT WINAPI
contentHandler_skippedEntity(
1333 ISAXContentHandler
* iface
,
1334 const WCHAR
*name
, int len
)
1336 struct call_entry call
;
1338 init_call_entry(locator
, &call
);
1339 call
.id
= CH_SKIPPEDENTITY
;
1340 call
.arg1W
= SysAllocStringLen(name
, len
);
1341 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1343 return get_expected_ret();
1346 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1348 contentHandler_QueryInterface
,
1349 contentHandler_AddRef
,
1350 contentHandler_Release
,
1351 contentHandler_putDocumentLocator
,
1352 contentHandler_startDocument
,
1353 contentHandler_endDocument
,
1354 contentHandler_startPrefixMapping
,
1355 contentHandler_endPrefixMapping
,
1356 contentHandler_startElement
,
1357 contentHandler_endElement
,
1358 contentHandler_characters
,
1359 contentHandler_ignorableWhitespace
,
1360 contentHandler_processingInstruction
,
1361 contentHandler_skippedEntity
1364 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1366 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1367 ISAXErrorHandler
* iface
,
1373 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1379 return E_NOINTERFACE
;
1385 static ULONG WINAPI
isaxerrorHandler_AddRef(
1386 ISAXErrorHandler
* iface
)
1391 static ULONG WINAPI
isaxerrorHandler_Release(
1392 ISAXErrorHandler
* iface
)
1397 static HRESULT WINAPI
isaxerrorHandler_error(
1398 ISAXErrorHandler
* iface
,
1399 ISAXLocator
*pLocator
,
1400 const WCHAR
*pErrorMessage
,
1401 HRESULT hrErrorCode
)
1403 ok(0, "unexpected call\n");
1407 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1408 ISAXErrorHandler
* iface
,
1409 ISAXLocator
*pLocator
,
1410 const WCHAR
*message
,
1413 struct call_entry call
;
1415 init_call_entry(locator
, &call
);
1416 call
.id
= EH_FATALERROR
;
1419 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1425 static HRESULT WINAPI
isaxerrorHandler_ignorableWarning(
1426 ISAXErrorHandler
* iface
,
1427 ISAXLocator
*pLocator
,
1428 const WCHAR
*pErrorMessage
,
1429 HRESULT hrErrorCode
)
1431 ok(0, "unexpected call\n");
1435 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1437 isaxerrorHandler_QueryInterface
,
1438 isaxerrorHandler_AddRef
,
1439 isaxerrorHandler_Release
,
1440 isaxerrorHandler_error
,
1441 isaxerrorHandler_fatalError
,
1442 isaxerrorHandler_ignorableWarning
1445 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1447 static HRESULT WINAPI
isaxattributes_QueryInterface(
1448 ISAXAttributes
* iface
,
1454 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1460 return E_NOINTERFACE
;
1466 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1471 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1476 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1482 static HRESULT WINAPI
isaxattributes_getURI(
1483 ISAXAttributes
* iface
,
1488 ok(0, "unexpected call\n");
1492 static HRESULT WINAPI
isaxattributes_getLocalName(
1493 ISAXAttributes
* iface
,
1495 const WCHAR
**pLocalName
,
1496 int *pLocalNameLength
)
1498 ok(0, "unexpected call\n");
1502 static HRESULT WINAPI
isaxattributes_getQName(
1503 ISAXAttributes
* iface
,
1505 const WCHAR
**QName
,
1508 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1509 {'a','t','t','r','2','j','u','n','k',0},
1510 {'a','t','t','r','3',0}};
1511 static const int attrqnamelen
[] = {7, 5, 5};
1513 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1515 if (index
>= 0 && index
<= 2) {
1516 *QName
= attrqnamesW
[index
];
1517 *QNameLength
= attrqnamelen
[index
];
1526 static HRESULT WINAPI
isaxattributes_getName(
1527 ISAXAttributes
* iface
,
1531 const WCHAR
** pLocalName
,
1532 int * pLocalNameSize
,
1533 const WCHAR
** pQName
,
1536 ok(0, "unexpected call\n");
1540 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1541 ISAXAttributes
* iface
,
1544 const WCHAR
* pLocalName
,
1545 int cocalNameLength
,
1548 ok(0, "unexpected call\n");
1552 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1553 ISAXAttributes
* iface
,
1554 const WCHAR
* pQName
,
1558 ok(0, "unexpected call\n");
1562 static HRESULT WINAPI
isaxattributes_getType(
1563 ISAXAttributes
* iface
,
1565 const WCHAR
** pType
,
1568 ok(0, "unexpected call\n");
1572 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1573 ISAXAttributes
* iface
,
1576 const WCHAR
* pLocalName
,
1578 const WCHAR
** pType
,
1581 ok(0, "unexpected call\n");
1585 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1586 ISAXAttributes
* iface
,
1587 const WCHAR
* pQName
,
1589 const WCHAR
** pType
,
1592 ok(0, "unexpected call\n");
1596 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1597 const WCHAR
**value
, int *nValue
)
1599 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1600 {'a','2','j','u','n','k',0},
1601 {'<','&','"','>','\'',0}};
1602 static const int attrvalueslen
[] = {2, 2, 5};
1604 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1606 if (index
>= 0 && index
<= 2) {
1607 *value
= attrvaluesW
[index
];
1608 *nValue
= attrvalueslen
[index
];
1617 static HRESULT WINAPI
isaxattributes_getValueFromName(
1618 ISAXAttributes
* iface
,
1621 const WCHAR
* pLocalName
,
1623 const WCHAR
** pValue
,
1626 ok(0, "unexpected call\n");
1630 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1631 ISAXAttributes
* iface
,
1632 const WCHAR
* pQName
,
1634 const WCHAR
** pValue
,
1637 ok(0, "unexpected call\n");
1641 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1643 isaxattributes_QueryInterface
,
1644 isaxattributes_AddRef
,
1645 isaxattributes_Release
,
1646 isaxattributes_getLength
,
1647 isaxattributes_getURI
,
1648 isaxattributes_getLocalName
,
1649 isaxattributes_getQName
,
1650 isaxattributes_getName
,
1651 isaxattributes_getIndexFromName
,
1652 isaxattributes_getIndexFromQName
,
1653 isaxattributes_getType
,
1654 isaxattributes_getTypeFromName
,
1655 isaxattributes_getTypeFromQName
,
1656 isaxattributes_getValue
,
1657 isaxattributes_getValueFromName
,
1658 isaxattributes_getValueFromQName
1661 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1663 struct saxlexicalhandler
1665 ISAXLexicalHandler ISAXLexicalHandler_iface
;
1668 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1671 static inline struct saxlexicalhandler
*impl_from_ISAXLexicalHandler( ISAXLexicalHandler
*iface
)
1673 return CONTAINING_RECORD(iface
, struct saxlexicalhandler
, ISAXLexicalHandler_iface
);
1676 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **out
)
1678 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1682 if (IsEqualGUID(riid
, &IID_IUnknown
))
1685 ok(0, "got unexpected IID_IUnknown query\n");
1687 else if (IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1689 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1694 ISAXLexicalHandler_AddRef(iface
);
1696 return E_NOINTERFACE
;
1701 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1703 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1704 return InterlockedIncrement(&handler
->ref
);
1707 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1709 struct saxlexicalhandler
*handler
= impl_from_ISAXLexicalHandler(iface
);
1710 return InterlockedDecrement(&handler
->ref
);
1713 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1714 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1715 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1717 ok(0, "call not expected\n");
1721 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1723 ok(0, "call not expected\n");
1727 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1728 const WCHAR
* pName
, int nName
)
1730 ok(0, "call not expected\n");
1734 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1735 const WCHAR
* pName
, int nName
)
1737 ok(0, "call not expected\n");
1741 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1743 struct call_entry call
;
1745 init_call_entry(locator
, &call
);
1746 call
.id
= LH_STARTCDATA
;
1747 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1749 return get_expected_ret();
1752 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1754 struct call_entry call
;
1756 init_call_entry(locator
, &call
);
1757 call
.id
= LH_ENDCDATA
;
1758 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1760 return get_expected_ret();
1763 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1764 const WCHAR
* pChars
, int nChars
)
1766 ok(0, "call not expected\n");
1770 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1772 isaxlexical_QueryInterface
,
1774 isaxlexical_Release
,
1775 isaxlexical_startDTD
,
1777 isaxlexical_startEntity
,
1778 isaxlexical_endEntity
,
1779 isaxlexical_startCDATA
,
1780 isaxlexical_endCDATA
,
1784 static void init_saxlexicalhandler(struct saxlexicalhandler
*handler
, HRESULT hr
)
1786 handler
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1788 handler
->qi_hr
= hr
;
1791 struct saxdeclhandler
1793 ISAXDeclHandler ISAXDeclHandler_iface
;
1796 HRESULT qi_hr
; /* ret value for QueryInterface for handler riid */
1799 static inline struct saxdeclhandler
*impl_from_ISAXDeclHandler( ISAXDeclHandler
*iface
)
1801 return CONTAINING_RECORD(iface
, struct saxdeclhandler
, ISAXDeclHandler_iface
);
1804 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **out
)
1806 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1810 if (IsEqualGUID(riid
, &IID_IUnknown
))
1813 ok(0, "got unexpected IID_IUnknown query\n");
1815 else if (IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1817 if (handler
->qi_hr
== E_NOINTERFACE
) return handler
->qi_hr
;
1822 ISAXDeclHandler_AddRef(iface
);
1824 return E_NOINTERFACE
;
1829 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1831 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1832 return InterlockedIncrement(&handler
->ref
);
1835 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1837 struct saxdeclhandler
*handler
= impl_from_ISAXDeclHandler(iface
);
1838 return InterlockedDecrement(&handler
->ref
);
1841 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1842 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1844 ok(0, "call not expected\n");
1848 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1849 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1850 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1851 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1853 ok(0, "call not expected\n");
1857 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1858 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1860 ok(0, "call not expected\n");
1864 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1865 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1866 const WCHAR
* pSystemId
, int nSystemId
)
1868 ok(0, "call not expected\n");
1872 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1874 isaxdecl_QueryInterface
,
1877 isaxdecl_elementDecl
,
1878 isaxdecl_attributeDecl
,
1879 isaxdecl_internalEntityDecl
,
1880 isaxdecl_externalEntityDecl
1883 static void init_saxdeclhandler(struct saxdeclhandler
*handler
, HRESULT hr
)
1885 handler
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1887 handler
->qi_hr
= hr
;
1890 typedef struct mxwriter_write_test_t
{
1896 } mxwriter_write_test
;
1898 typedef struct mxwriter_stream_test_t
{
1900 const char *encoding
;
1901 mxwriter_write_test expected_writes
[4];
1902 } mxwriter_stream_test
;
1904 static const mxwriter_write_test
*current_write_test
;
1905 static DWORD current_stream_test_index
;
1907 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1911 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1914 return E_NOINTERFACE
;
1919 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1924 static ULONG WINAPI
istream_Release(IStream
*iface
)
1929 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1931 ok(0, "unexpected call\n");
1935 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1937 ok(0, "unexpected call\n");
1941 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1942 ULARGE_INTEGER
*plibNewPosition
)
1944 ok(0, "unexpected call\n");
1948 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1950 ok(0, "unexpected call\n");
1954 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1955 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1957 ok(0, "unexpected call\n");
1961 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1963 ok(0, "unexpected call\n");
1967 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1969 ok(0, "unexpected call\n");
1973 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1974 ULARGE_INTEGER cb
, DWORD dwLockType
)
1976 ok(0, "unexpected call\n");
1980 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1981 ULARGE_INTEGER cb
, DWORD dwLockType
)
1983 ok(0, "unexpected call\n");
1987 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1992 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1994 ok(0, "unexpected call\n");
1998 static HRESULT WINAPI
mxstream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
2002 ok(pv
!= NULL
, "pv == NULL\n");
2004 if(current_write_test
->last
) {
2005 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
2009 fail
= current_write_test
->fail_write
;
2011 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
2012 current_write_test
->cb
, cb
, current_stream_test_index
);
2015 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
2017 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
2019 ++current_write_test
;
2024 return fail
? E_FAIL
: S_OK
;
2027 static const IStreamVtbl mxstreamVtbl
= {
2028 istream_QueryInterface
,
2039 istream_UnlockRegion
,
2044 static IStream mxstream
= { &mxstreamVtbl
};
2046 static int read_cnt
;
2048 static HRESULT WINAPI
instream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
2050 static const char *ret_str
;
2053 ret_str
= "<?xml version=\"1.0\" ?>\n<rootelem>";
2054 else if(read_cnt
< 5)
2055 ret_str
= "<elem attr=\"val\">text</elem>";
2056 else if(read_cnt
== 5)
2057 ret_str
= "</rootelem>\n";
2062 strcpy(pv
, ret_str
);
2063 *pcbRead
= strlen(ret_str
);
2067 static const IStreamVtbl instreamVtbl
= {
2068 istream_QueryInterface
,
2079 istream_UnlockRegion
,
2084 static IStream instream
= { &instreamVtbl
};
2086 static struct msxmlsupported_data_t reader_support_data
[] =
2088 { &CLSID_SAXXMLReader
, "SAXReader" },
2089 { &CLSID_SAXXMLReader30
, "SAXReader30" },
2090 { &CLSID_SAXXMLReader40
, "SAXReader40" },
2091 { &CLSID_SAXXMLReader60
, "SAXReader60" },
2095 static struct saxlexicalhandler lexicalhandler
;
2096 static struct saxdeclhandler declhandler
;
2098 static IStream
*create_test_stream(const char *data
, int len
)
2100 ULARGE_INTEGER size
;
2105 if (len
== -1) len
= strlen(data
);
2106 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2107 size
.QuadPart
= len
;
2108 IStream_SetSize(stream
, size
);
2109 IStream_Write(stream
, data
, len
, &written
);
2111 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2116 static void test_saxreader(void)
2118 const struct msxmlsupported_data_t
*table
= reader_support_data
;
2120 ISAXXMLReader
*reader
= NULL
;
2122 ISAXContentHandler
*content
;
2123 ISAXErrorHandler
*lpErrorHandler
;
2125 SAFEARRAYBOUND SADim
[1];
2130 static const CHAR testXmlA
[] = "test.xml";
2131 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2132 IXMLDOMDocument
*doc
;
2136 while (table
->clsid
)
2138 struct call_entry
*test_seq
;
2139 ISAXEntityResolver
*resolver
;
2142 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
2148 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2149 EXPECT_HR(hr
, S_OK
);
2152 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2154 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2159 /* crashes on old versions */
2160 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
2161 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2163 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
2164 EXPECT_HR(hr
, E_POINTER
);
2166 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
2167 EXPECT_HR(hr
, E_POINTER
);
2170 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2171 EXPECT_HR(hr
, S_OK
);
2172 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
2174 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
2175 EXPECT_HR(hr
, S_OK
);
2176 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
2178 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
2179 EXPECT_HR(hr
, S_OK
);
2181 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
2182 EXPECT_HR(hr
, S_OK
);
2184 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
2185 EXPECT_HR(hr
, S_OK
);
2187 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
2188 EXPECT_HR(hr
, S_OK
);
2189 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
2191 V_VT(&var
) = VT_BSTR
;
2192 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
2194 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2195 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2196 test_seq
= content_handler_test1_alternate
;
2198 test_seq
= content_handler_test1
;
2199 set_expected_seq(test_seq
);
2200 hr
= ISAXXMLReader_parse(reader
, var
);
2201 EXPECT_HR(hr
, S_OK
);
2202 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
2206 SADim
[0].lLbound
= 0;
2207 SADim
[0].cElements
= sizeof(testXML
)-1;
2208 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
2209 SafeArrayAccessData(sa
, (void**)&ptr
);
2210 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
2211 SafeArrayUnaccessData(sa
);
2212 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
2215 set_expected_seq(test_seq
);
2216 hr
= ISAXXMLReader_parse(reader
, var
);
2217 EXPECT_HR(hr
, S_OK
);
2218 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from safe array", FALSE
);
2220 SafeArrayDestroy(sa
);
2222 stream
= create_test_stream(testXML
, -1);
2223 V_VT(&var
) = VT_UNKNOWN
;
2224 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2226 set_expected_seq(test_seq
);
2227 hr
= ISAXXMLReader_parse(reader
, var
);
2228 EXPECT_HR(hr
, S_OK
);
2229 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
2231 IStream_Release(stream
);
2233 stream
= create_test_stream(test_attributes
, -1);
2234 V_VT(&var
) = VT_UNKNOWN
;
2235 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2237 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2238 test_seq
= content_handler_test_attributes_alternate_4
;
2239 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2240 test_seq
= content_handler_test_attributes_alternate_6
;
2242 test_seq
= content_handler_test_attributes
;
2244 set_expected_seq(test_seq
);
2245 hr
= ISAXXMLReader_parse(reader
, var
);
2246 EXPECT_HR(hr
, S_OK
);
2248 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2249 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2250 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2252 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2254 IStream_Release(stream
);
2256 V_VT(&var
) = VT_UNKNOWN
;
2257 V_UNKNOWN(&var
) = (IUnknown
*)&instream
;
2259 test_seq
= read_test_seq
;
2261 set_expected_seq(test_seq
);
2262 hr
= ISAXXMLReader_parse(reader
, var
);
2263 EXPECT_HR(hr
, S_OK
);
2264 ok(read_cnt
== 7, "read_cnt = %d\n", read_cnt
);
2265 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "Read call test", FALSE
);
2267 V_VT(&var
) = VT_BSTR
;
2268 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
2270 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2271 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2272 test_seq
= content_handler_test2_alternate
;
2274 test_seq
= content_handler_test2
;
2276 set_expected_seq(test_seq
);
2277 hr
= ISAXXMLReader_parse(reader
, var
);
2278 EXPECT_HR(hr
, S_OK
);
2279 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
2284 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2285 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2286 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
2289 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2290 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2291 test_seq
= content_handler_test1_alternate
;
2293 test_seq
= content_handler_test1
;
2294 set_expected_seq(test_seq
);
2295 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2296 EXPECT_HR(hr
, S_OK
);
2297 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
2300 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2301 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2302 test_seq
= content_handler_testerror_alternate
;
2304 test_seq
= content_handler_testerror
;
2305 set_expected_seq(test_seq
);
2306 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2307 EXPECT_HR(hr
, E_FAIL
);
2308 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
2310 /* callback ret values */
2311 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2312 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2314 test_seq
= content_handler_test_callback_rets_alt
;
2315 set_expected_seq(test_seq
);
2316 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2317 EXPECT_HR(hr
, S_OK
);
2321 test_seq
= content_handler_test_callback_rets
;
2322 set_expected_seq(test_seq
);
2323 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2324 EXPECT_HR(hr
, S_FALSE
);
2326 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
2328 DeleteFileA(testXmlA
);
2330 /* parse from IXMLDOMDocument */
2331 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
2332 &IID_IXMLDOMDocument
, (void**)&doc
);
2333 EXPECT_HR(hr
, S_OK
);
2335 str
= SysAllocString(szSimpleXML
);
2336 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
2337 EXPECT_HR(hr
, S_OK
);
2340 V_VT(&var
) = VT_UNKNOWN
;
2341 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
2343 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2344 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2345 test_seq
= content_handler_test2_alternate
;
2347 test_seq
= content_handler_test2
;
2349 set_expected_seq(test_seq
);
2350 hr
= ISAXXMLReader_parse(reader
, var
);
2351 EXPECT_HR(hr
, S_OK
);
2352 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
2353 IXMLDOMDocument_Release(doc
);
2355 /* xml:space test */
2356 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2357 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2359 test_seq
= xmlspaceattr_test_alternate
;
2362 test_seq
= xmlspaceattr_test
;
2364 set_expected_seq(test_seq
);
2365 V_VT(&var
) = VT_BSTR
;
2366 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
2367 hr
= ISAXXMLReader_parse(reader
, var
);
2368 EXPECT_HR(hr
, S_OK
);
2370 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2371 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2373 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
2376 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
2378 /* switch off 'namespaces' feature */
2379 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE
);
2380 EXPECT_HR(hr
, S_OK
);
2382 stream
= create_test_stream(test_attributes
, -1);
2383 V_VT(&var
) = VT_UNKNOWN
;
2384 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2386 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2387 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2389 test_seq
= content_handler_test_attributes_alt_no_ns
;
2392 test_seq
= content_handler_test_attributes
;
2394 set_expected_seq(test_seq
);
2395 hr
= ISAXXMLReader_parse(reader
, var
);
2396 EXPECT_HR(hr
, S_OK
);
2397 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2398 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_TRUE
);
2399 EXPECT_HR(hr
, S_OK
);
2401 /* switch off 'namespace-prefixes' feature */
2402 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_FALSE
);
2403 EXPECT_HR(hr
, S_OK
);
2405 stream
= create_test_stream(test_attributes
, -1);
2406 V_VT(&var
) = VT_UNKNOWN
;
2407 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2409 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2410 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2412 test_seq
= content_handler_test_attributes_alt_no_prefix
;
2415 test_seq
= content_handler_test_attributes_no_prefix
;
2417 set_expected_seq(test_seq
);
2418 hr
= ISAXXMLReader_parse(reader
, var
);
2419 EXPECT_HR(hr
, S_OK
);
2420 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2422 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_TRUE
);
2423 EXPECT_HR(hr
, S_OK
);
2425 /* attribute normalization */
2426 stream
= create_test_stream(attribute_normalize
, -1);
2427 V_VT(&var
) = VT_UNKNOWN
;
2428 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2430 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2431 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2433 test_seq
= attribute_norm_alt
;
2436 test_seq
= attribute_norm
;
2438 set_expected_seq(test_seq
);
2439 hr
= ISAXXMLReader_parse(reader
, var
);
2440 EXPECT_HR(hr
, S_OK
);
2441 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "attribute value normalization", TRUE
);
2442 IStream_Release(stream
);
2444 resolver
= (void*)0xdeadbeef;
2445 hr
= ISAXXMLReader_getEntityResolver(reader
, &resolver
);
2446 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2447 ok(resolver
== NULL
, "got %p\n", resolver
);
2449 hr
= ISAXXMLReader_putEntityResolver(reader
, NULL
);
2450 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "got 0x%08x\n", hr
);
2452 /* CDATA sections */
2453 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2455 V_VT(&var
) = VT_UNKNOWN
;
2456 V_UNKNOWN(&var
) = (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
;
2457 hr
= ISAXXMLReader_putProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), var
);
2458 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2460 stream
= create_test_stream(test_cdata_xml
, -1);
2461 V_VT(&var
) = VT_UNKNOWN
;
2462 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2464 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2465 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2466 test_seq
= cdata_test_alt
;
2468 test_seq
= cdata_test
;
2470 set_expected_seq(test_seq
);
2471 hr
= ISAXXMLReader_parse(reader
, var
);
2472 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2473 sprintf(seqname
, "%s: cdata test", table
->name
);
2474 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2476 IStream_Release(stream
);
2478 /* 2. CDATA sections */
2479 stream
= create_test_stream(test2_cdata_xml
, -1);
2480 V_VT(&var
) = VT_UNKNOWN
;
2481 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2483 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2484 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2485 test_seq
= cdata_test2_alt
;
2487 test_seq
= cdata_test2
;
2489 set_expected_seq(test_seq
);
2490 hr
= ISAXXMLReader_parse(reader
, var
);
2491 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2492 sprintf(seqname
, "%s: cdata test 2", table
->name
);
2493 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2495 IStream_Release(stream
);
2497 /* 3. CDATA sections */
2498 stream
= create_test_stream(test3_cdata_xml
, -1);
2499 V_VT(&var
) = VT_UNKNOWN
;
2500 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2502 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ||
2503 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
2504 test_seq
= cdata_test3_alt
;
2506 test_seq
= cdata_test3
;
2508 set_expected_seq(test_seq
);
2509 hr
= ISAXXMLReader_parse(reader
, var
);
2510 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2511 sprintf(seqname
, "%s: cdata test 3", table
->name
);
2512 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, seqname
, TRUE
);
2514 IStream_Release(stream
);
2516 ISAXXMLReader_Release(reader
);
2523 struct saxreader_props_test_t
2525 const char *prop_name
;
2529 static const struct saxreader_props_test_t props_test_data
[] = {
2530 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&lexicalhandler
.ISAXLexicalHandler_iface
},
2531 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&declhandler
.ISAXDeclHandler_iface
},
2535 static void test_saxreader_properties(void)
2537 const struct saxreader_props_test_t
*ptr
= props_test_data
;
2538 ISAXXMLReader
*reader
;
2543 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2544 &IID_ISAXXMLReader
, (void**)&reader
);
2545 EXPECT_HR(hr
, S_OK
);
2547 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
2548 EXPECT_HR(hr
, E_POINTER
);
2550 while (ptr
->prop_name
)
2555 init_saxlexicalhandler(&lexicalhandler
, S_OK
);
2556 init_saxdeclhandler(&declhandler
, S_OK
);
2558 V_VT(&v
) = VT_EMPTY
;
2559 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2560 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2561 EXPECT_HR(hr
, S_OK
);
2562 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2563 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2566 V_VT(&v
) = VT_UNKNOWN
;
2567 V_UNKNOWN(&v
) = ptr
->iface
;
2568 ref
= get_refcount(ptr
->iface
);
2569 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2570 EXPECT_HR(hr
, S_OK
);
2571 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2574 V_VT(&v
) = VT_DISPATCH
;
2575 V_UNKNOWN(&v
) = ptr
->iface
;
2576 ref
= get_refcount(ptr
->iface
);
2577 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2578 EXPECT_HR(hr
, S_OK
);
2579 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2581 /* VT_VARIANT|VT_BYREF with VT_UNKNOWN in referenced variant */
2582 V_VT(&varref
) = VT_UNKNOWN
;
2583 V_UNKNOWN(&varref
) = ptr
->iface
;
2585 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2586 V_VARIANTREF(&v
) = &varref
;
2587 ref
= get_refcount(ptr
->iface
);
2588 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2589 EXPECT_HR(hr
, S_OK
);
2590 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2592 /* VT_VARIANT|VT_BYREF with VT_DISPATCH in referenced variant */
2593 V_VT(&varref
) = VT_DISPATCH
;
2594 V_UNKNOWN(&varref
) = ptr
->iface
;
2596 V_VT(&v
) = VT_VARIANT
|VT_BYREF
;
2597 V_VARIANTREF(&v
) = &varref
;
2598 ref
= get_refcount(ptr
->iface
);
2599 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2600 EXPECT_HR(hr
, S_OK
);
2601 ok(ref
== get_refcount(ptr
->iface
), "got wrong refcount %d, expected %d\n", get_refcount(ptr
->iface
), ref
);
2603 V_VT(&v
) = VT_EMPTY
;
2604 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2606 ref
= get_refcount(ptr
->iface
);
2607 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2608 EXPECT_HR(hr
, S_OK
);
2609 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2610 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2611 ok(ref
< get_refcount(ptr
->iface
), "expected inreased refcount\n");
2614 V_VT(&v
) = VT_EMPTY
;
2615 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2616 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2617 EXPECT_HR(hr
, S_OK
);
2619 V_VT(&v
) = VT_EMPTY
;
2620 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2621 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2622 EXPECT_HR(hr
, S_OK
);
2623 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2624 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2626 V_VT(&v
) = VT_UNKNOWN
;
2627 V_UNKNOWN(&v
) = ptr
->iface
;
2628 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2629 EXPECT_HR(hr
, S_OK
);
2631 /* only VT_EMPTY seems to be valid to reset property */
2633 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2634 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2635 EXPECT_HR(hr
, E_INVALIDARG
);
2637 V_VT(&v
) = VT_EMPTY
;
2638 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2639 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2640 EXPECT_HR(hr
, S_OK
);
2641 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2642 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2645 V_VT(&v
) = VT_UNKNOWN
;
2646 V_UNKNOWN(&v
) = NULL
;
2647 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2648 EXPECT_HR(hr
, S_OK
);
2650 V_VT(&v
) = VT_EMPTY
;
2651 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2652 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2653 EXPECT_HR(hr
, S_OK
);
2654 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2655 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2657 /* block QueryInterface on handler riid */
2658 V_VT(&v
) = VT_UNKNOWN
;
2659 V_UNKNOWN(&v
) = ptr
->iface
;
2660 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2661 EXPECT_HR(hr
, S_OK
);
2663 init_saxlexicalhandler(&lexicalhandler
, E_NOINTERFACE
);
2664 init_saxdeclhandler(&declhandler
, E_NOINTERFACE
);
2666 V_VT(&v
) = VT_UNKNOWN
;
2667 V_UNKNOWN(&v
) = ptr
->iface
;
2668 EXPECT_REF(ptr
->iface
, 1);
2669 ref
= get_refcount(ptr
->iface
);
2670 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2671 EXPECT_HR(hr
, E_NOINTERFACE
);
2672 EXPECT_REF(ptr
->iface
, 1);
2674 V_VT(&v
) = VT_EMPTY
;
2675 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2676 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2677 EXPECT_HR(hr
, S_OK
);
2678 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2679 ok(V_UNKNOWN(&v
) != NULL
, "got %p\n", V_UNKNOWN(&v
));
2685 ISAXXMLReader_Release(reader
);
2687 if (!is_clsid_supported(&CLSID_SAXXMLReader40
, reader_support_data
))
2690 hr
= CoCreateInstance(&CLSID_SAXXMLReader40
, NULL
, CLSCTX_INPROC_SERVER
,
2691 &IID_ISAXXMLReader
, (void**)&reader
);
2692 EXPECT_HR(hr
, S_OK
);
2694 /* xmldecl-version property */
2695 V_VT(&v
) = VT_EMPTY
;
2696 V_BSTR(&v
) = (void*)0xdeadbeef;
2697 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2698 EXPECT_HR(hr
, S_OK
);
2699 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2700 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2702 /* stream without declaration */
2704 V_BSTR(&v
) = _bstr_("<element></element>");
2705 hr
= ISAXXMLReader_parse(reader
, v
);
2706 EXPECT_HR(hr
, S_OK
);
2708 V_VT(&v
) = VT_EMPTY
;
2709 V_BSTR(&v
) = (void*)0xdeadbeef;
2710 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2711 EXPECT_HR(hr
, S_OK
);
2712 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2713 ok(V_BSTR(&v
) == NULL
, "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2715 /* stream with declaration */
2717 V_BSTR(&v
) = _bstr_("<?xml version=\"1.0\"?><element></element>");
2718 hr
= ISAXXMLReader_parse(reader
, v
);
2719 EXPECT_HR(hr
, S_OK
);
2721 /* VT_BSTR|VT_BYREF input type */
2722 str
= _bstr_("<?xml version=\"1.0\"?><element></element>");
2723 V_VT(&v
) = VT_BSTR
|VT_BYREF
;
2724 V_BSTRREF(&v
) = &str
;
2725 hr
= ISAXXMLReader_parse(reader
, v
);
2726 EXPECT_HR(hr
, S_OK
);
2728 V_VT(&v
) = VT_EMPTY
;
2729 V_BSTR(&v
) = (void*)0xdeadbeef;
2730 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("xmldecl-version"), &v
);
2731 EXPECT_HR(hr
, S_OK
);
2732 ok(V_VT(&v
) == VT_BSTR
, "got %d\n", V_VT(&v
));
2733 ok(!lstrcmpW(V_BSTR(&v
), _bstr_("1.0")), "got %s\n", wine_dbgstr_w(V_BSTR(&v
)));
2736 ISAXXMLReader_Release(reader
);
2740 struct feature_ns_entry_t
{
2744 VARIANT_BOOL value2
; /* feature value after feature set to 0xc */
2747 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2748 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
, VARIANT_FALSE
},
2749 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
, VARIANT_FALSE
},
2750 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
, VARIANT_TRUE
},
2751 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
, VARIANT_TRUE
},
2755 static const char *feature_names
[] = {
2756 "http://xml.org/sax/features/namespaces",
2757 "http://xml.org/sax/features/namespace-prefixes",
2761 static void test_saxreader_features(void)
2763 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2764 ISAXXMLReader
*reader
;
2772 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2775 win_skip("can't create %s instance\n", entry
->clsid
);
2780 name
= feature_names
;
2784 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2785 EXPECT_HR(hr
, S_OK
);
2786 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2789 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), value
);
2790 EXPECT_HR(hr
, S_OK
);
2793 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2794 EXPECT_HR(hr
, S_OK
);
2795 ok(entry
->value2
== value
, "%s: got wrong value %x, expected %x\n", entry
->clsid
, value
, entry
->value2
);
2797 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_FALSE
);
2798 EXPECT_HR(hr
, S_OK
);
2800 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2801 EXPECT_HR(hr
, S_OK
);
2802 ok(value
== VARIANT_FALSE
, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry
->clsid
, value
);
2804 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_TRUE
);
2805 EXPECT_HR(hr
, S_OK
);
2807 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2808 EXPECT_HR(hr
, S_OK
);
2809 ok(value
== VARIANT_TRUE
, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry
->clsid
, value
);
2814 ISAXXMLReader_Release(reader
);
2820 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2821 static const CHAR UTF8BOMTest
[] =
2822 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2825 struct enc_test_entry_t
{
2833 static const struct enc_test_entry_t encoding_test_data
[] = {
2834 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2835 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, TRUE
},
2836 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, FALSE
},
2837 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, FALSE
},
2841 static void test_saxreader_encoding(void)
2843 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2844 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2845 static const CHAR testXmlA
[] = "test.xml";
2849 ISAXXMLReader
*reader
;
2855 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2858 win_skip("can't create %s instance\n", entry
->clsid
);
2863 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2864 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2865 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2868 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2870 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2872 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2874 DeleteFileA(testXmlA
);
2876 /* try BSTR input with no BOM or '<?xml' instruction */
2877 V_VT(&input
) = VT_BSTR
;
2878 V_BSTR(&input
) = _bstr_("<element></element>");
2879 hr
= ISAXXMLReader_parse(reader
, input
);
2880 EXPECT_HR(hr
, S_OK
);
2882 ISAXXMLReader_Release(reader
);
2889 static void test_mxwriter_handlers(void)
2895 static REFIID riids
[] =
2897 &IID_ISAXContentHandler
,
2898 &IID_ISAXLexicalHandler
,
2899 &IID_ISAXDeclHandler
,
2900 &IID_ISAXDTDHandler
,
2901 &IID_ISAXErrorHandler
,
2902 &IID_IVBSAXDeclHandler
,
2903 &IID_IVBSAXLexicalHandler
,
2904 &IID_IVBSAXContentHandler
,
2905 &IID_IVBSAXDTDHandler
,
2906 &IID_IVBSAXErrorHandler
2909 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2910 &IID_IMXWriter
, (void**)&writer
);
2911 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2913 EXPECT_REF(writer
, 1);
2915 for (i
= 0; i
< sizeof(riids
)/sizeof(REFIID
); i
++)
2920 /* handler from IMXWriter */
2921 hr
= IMXWriter_QueryInterface(writer
, riids
[i
], (void**)&handler
);
2922 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2923 EXPECT_REF(writer
, 2);
2924 EXPECT_REF(handler
, 2);
2926 /* IMXWriter from a handler */
2927 hr
= IUnknown_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2928 ok(hr
== S_OK
, "%s, expected S_OK, got %08x\n", wine_dbgstr_guid(riids
[i
]), hr
);
2929 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2930 EXPECT_REF(writer
, 3);
2931 EXPECT_REF(writer2
, 3);
2932 IMXWriter_Release(writer2
);
2933 IUnknown_Release(handler
);
2936 IMXWriter_Release(writer
);
2939 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2941 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2942 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2943 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2944 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2948 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2950 { &CLSID_SAXAttributes
, "SAXAttributes" },
2951 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2952 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2953 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2957 struct mxwriter_props_t
2961 VARIANT_BOOL disable_escape
;
2962 VARIANT_BOOL indent
;
2963 VARIANT_BOOL omitdecl
;
2964 VARIANT_BOOL standalone
;
2965 const char *encoding
;
2968 static const struct mxwriter_props_t mxwriter_default_props
[] =
2970 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2971 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2972 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2973 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2977 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2981 while (table
->clsid
)
2988 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2995 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2996 &IID_IMXWriter
, (void**)&writer
);
2997 EXPECT_HR(hr
, S_OK
);
3000 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
3001 EXPECT_HR(hr
, S_OK
);
3002 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
3004 b
= !table
->disable_escape
;
3005 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
3006 EXPECT_HR(hr
, S_OK
);
3007 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
3008 table
->disable_escape
);
3011 hr
= IMXWriter_get_indent(writer
, &b
);
3012 EXPECT_HR(hr
, S_OK
);
3013 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
3015 b
= !table
->omitdecl
;
3016 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
3017 EXPECT_HR(hr
, S_OK
);
3018 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
3020 b
= !table
->standalone
;
3021 hr
= IMXWriter_get_standalone(writer
, &b
);
3022 EXPECT_HR(hr
, S_OK
);
3023 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
3025 hr
= IMXWriter_get_encoding(writer
, &encoding
);
3026 EXPECT_HR(hr
, S_OK
);
3027 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
3028 i
, wine_dbgstr_w(encoding
), table
->encoding
);
3029 SysFreeString(encoding
);
3031 IMXWriter_Release(writer
);
3038 static void test_mxwriter_properties(void)
3040 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
3041 static const WCHAR testW
[] = {'t','e','s','t',0};
3042 ISAXContentHandler
*content
;
3049 test_mxwriter_default_properties(mxwriter_default_props
);
3051 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3052 &IID_IMXWriter
, (void**)&writer
);
3053 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3055 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
3056 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3058 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
3059 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3061 hr
= IMXWriter_get_indent(writer
, NULL
);
3062 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3064 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
3065 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3067 hr
= IMXWriter_get_standalone(writer
, NULL
);
3068 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3071 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
3072 ok(hr
== S_OK
, "got %08x\n", hr
);
3075 hr
= IMXWriter_get_standalone(writer
, &b
);
3076 ok(hr
== S_OK
, "got %08x\n", hr
);
3077 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
3079 hr
= IMXWriter_get_encoding(writer
, NULL
);
3080 EXPECT_HR(hr
, E_POINTER
);
3082 /* UTF-16 is a default setting apparently */
3083 str
= (void*)0xdeadbeef;
3084 hr
= IMXWriter_get_encoding(writer
, &str
);
3085 EXPECT_HR(hr
, S_OK
);
3086 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
3088 str2
= (void*)0xdeadbeef;
3089 hr
= IMXWriter_get_encoding(writer
, &str2
);
3090 ok(hr
== S_OK
, "got %08x\n", hr
);
3091 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
3093 SysFreeString(str2
);
3096 /* put empty string */
3097 str
= SysAllocString(emptyW
);
3098 hr
= IMXWriter_put_encoding(writer
, str
);
3099 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3102 str
= (void*)0xdeadbeef;
3103 hr
= IMXWriter_get_encoding(writer
, &str
);
3104 EXPECT_HR(hr
, S_OK
);
3105 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
3108 /* invalid encoding name */
3109 str
= SysAllocString(testW
);
3110 hr
= IMXWriter_put_encoding(writer
, str
);
3111 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3114 /* test case sensivity */
3115 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
3116 EXPECT_HR(hr
, S_OK
);
3117 str
= (void*)0xdeadbeef;
3118 hr
= IMXWriter_get_encoding(writer
, &str
);
3119 EXPECT_HR(hr
, S_OK
);
3120 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
3123 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
3124 EXPECT_HR(hr
, S_OK
);
3125 str
= (void*)0xdeadbeef;
3126 hr
= IMXWriter_get_encoding(writer
, &str
);
3127 EXPECT_HR(hr
, S_OK
);
3128 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
3131 /* how it affects document creation */
3132 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3133 EXPECT_HR(hr
, S_OK
);
3135 hr
= ISAXContentHandler_startDocument(content
);
3136 EXPECT_HR(hr
, S_OK
);
3137 hr
= ISAXContentHandler_endDocument(content
);
3138 EXPECT_HR(hr
, S_OK
);
3140 V_VT(&dest
) = VT_EMPTY
;
3141 hr
= IMXWriter_get_output(writer
, &dest
);
3142 EXPECT_HR(hr
, S_OK
);
3143 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3144 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
3145 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3146 VariantClear(&dest
);
3147 ISAXContentHandler_Release(content
);
3149 hr
= IMXWriter_get_version(writer
, NULL
);
3150 ok(hr
== E_POINTER
, "got %08x\n", hr
);
3151 /* default version is 'surprisingly' 1.0 */
3152 hr
= IMXWriter_get_version(writer
, &str
);
3153 ok(hr
== S_OK
, "got %08x\n", hr
);
3154 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
3157 /* store version string as is */
3158 hr
= IMXWriter_put_version(writer
, NULL
);
3159 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
3161 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
3162 ok(hr
== S_OK
, "got %08x\n", hr
);
3164 hr
= IMXWriter_put_version(writer
, _bstr_(""));
3165 ok(hr
== S_OK
, "got %08x\n", hr
);
3166 hr
= IMXWriter_get_version(writer
, &str
);
3167 ok(hr
== S_OK
, "got %08x\n", hr
);
3168 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
3171 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
3172 ok(hr
== S_OK
, "got %08x\n", hr
);
3173 hr
= IMXWriter_get_version(writer
, &str
);
3174 ok(hr
== S_OK
, "got %08x\n", hr
);
3175 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
3178 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
3179 ok(hr
== S_OK
, "got %08x\n", hr
);
3180 hr
= IMXWriter_get_version(writer
, &str
);
3181 ok(hr
== S_OK
, "got %08x\n", hr
);
3182 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
3185 IMXWriter_Release(writer
);
3189 static void test_mxwriter_flush(void)
3191 ISAXContentHandler
*content
;
3194 ULARGE_INTEGER pos2
;
3202 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3203 &IID_IMXWriter
, (void**)&writer
);
3204 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3206 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3207 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3208 EXPECT_REF(stream
, 1);
3210 /* detach when nothing was attached */
3211 V_VT(&dest
) = VT_EMPTY
;
3212 hr
= IMXWriter_put_output(writer
, dest
);
3213 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);