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 struct msxmlsupported_data_t
56 static BOOL
is_clsid_supported(const GUID
*clsid
, const struct msxmlsupported_data_t
*table
)
60 if (table
->clsid
== clsid
) return table
->supported
;
66 static BSTR
alloc_str_from_narrow(const char *str
)
68 int len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
69 BSTR ret
= SysAllocStringLen(NULL
, len
- 1); /* NUL character added automatically */
70 MultiByteToWideChar(CP_ACP
, 0, str
, -1, ret
, len
);
74 static BSTR alloced_bstrs
[512];
75 static int alloced_bstrs_count
;
77 static BSTR
_bstr_(const char *str
)
79 assert(alloced_bstrs_count
< sizeof(alloced_bstrs
)/sizeof(alloced_bstrs
[0]));
80 alloced_bstrs
[alloced_bstrs_count
] = alloc_str_from_narrow(str
);
81 return alloced_bstrs
[alloced_bstrs_count
++];
84 static void free_bstrs(void)
87 for (i
= 0; i
< alloced_bstrs_count
; i
++)
88 SysFreeString(alloced_bstrs
[i
]);
89 alloced_bstrs_count
= 0;
92 static void test_saxstr(const char *file
, unsigned line
, BSTR str
, const char *expected
, int todo
, int *failcount
)
97 len
= SysStringLen(str
);
104 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
107 ok_(file
, line
) (!str
, "got %p, expected null str\n", str
);
113 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
116 ok_(file
, line
) (len
== 0, "got len %d, expected 0\n", len
);
120 lenexp
= strlen(expected
);
121 if (lenexp
!= len
&& todo
)
125 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
128 ok_(file
, line
) (lenexp
== len
, "len %d (%s), expected %d (%s)\n", len
, wine_dbgstr_wn(str
, len
), lenexp
, expected
);
130 /* exit earlier on length mismatch */
131 if (lenexp
!= len
) return;
133 MultiByteToWideChar(CP_ACP
, 0, expected
, -1, buf
, sizeof(buf
)/sizeof(WCHAR
));
135 cmp
= memcmp(str
, buf
, lenexp
*sizeof(WCHAR
));
140 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
141 wine_dbgstr_wn(str
, len
), expected
);
144 ok_(file
, line
) (!cmp
, "unexpected str %s, expected %s\n",
145 wine_dbgstr_wn(str
, len
), expected
);
150 CH_PUTDOCUMENTLOCATOR
,
153 CH_STARTPREFIXMAPPING
,
158 CH_IGNORABLEWHITESPACE
,
159 CH_PROCESSINGINSTRUCTION
,
167 static const char *event_names
[EVENT_LAST
] = {
169 "putDocumentLocator",
172 "startPrefixMapping",
177 "ignorableWhitespace",
178 "processingIntruction",
185 struct attribute_entry
{
191 /* used for actual call data only, null for expected call data */
207 /* allocated once at startElement callback */
208 struct attribute_entry
*attributes
;
211 /* used for actual call data only, null for expected call data */
221 struct call_entry
*sequence
;
224 #define CONTENT_HANDLER_INDEX 0
225 #define NUM_CALL_SEQUENCES 1
226 static struct call_sequence
*sequences
[NUM_CALL_SEQUENCES
];
228 static void init_call_entry(ISAXLocator
*locator
, struct call_entry
*call
)
230 memset(call
, 0, sizeof(*call
));
231 ISAXLocator_getLineNumber(locator
, &call
->line
);
232 ISAXLocator_getColumnNumber(locator
, &call
->column
);
235 static void add_call(struct call_sequence
**seq
, int sequence_index
,
236 const struct call_entry
*call
)
238 struct call_sequence
*call_seq
= seq
[sequence_index
];
240 if (!call_seq
->sequence
)
243 call_seq
->sequence
= HeapAlloc(GetProcessHeap(), 0,
244 call_seq
->size
* sizeof (struct call_entry
));
247 if (call_seq
->count
== call_seq
->size
)
250 call_seq
->sequence
= HeapReAlloc(GetProcessHeap(), 0,
252 call_seq
->size
* sizeof (struct call_entry
));
255 assert(call_seq
->sequence
);
257 call_seq
->sequence
[call_seq
->count
].id
= call
->id
;
258 call_seq
->sequence
[call_seq
->count
].line
= call
->line
;
259 call_seq
->sequence
[call_seq
->count
].column
= call
->column
;
260 call_seq
->sequence
[call_seq
->count
].arg1W
= call
->arg1W
;
261 call_seq
->sequence
[call_seq
->count
].arg2W
= call
->arg2W
;
262 call_seq
->sequence
[call_seq
->count
].arg3W
= call
->arg3W
;
263 call_seq
->sequence
[call_seq
->count
].ret
= call
->ret
;
264 call_seq
->sequence
[call_seq
->count
].attr_count
= call
->attr_count
;
265 call_seq
->sequence
[call_seq
->count
].attributes
= call
->attributes
;
270 static inline void flush_sequence(struct call_sequence
**seg
, int sequence_index
)
274 struct call_sequence
*call_seq
= seg
[sequence_index
];
276 for (i
= 0; i
< call_seq
->count
; i
++)
280 for (j
= 0; j
< call_seq
->sequence
[i
].attr_count
; j
++)
282 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].uriW
);
283 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].localW
);
284 SysFreeString(call_seq
->sequence
[i
].attributes
[j
].qnameW
);
287 SysFreeString(call_seq
->sequence
[i
].arg1W
);
288 SysFreeString(call_seq
->sequence
[i
].arg2W
);
289 SysFreeString(call_seq
->sequence
[i
].arg3W
);
292 HeapFree(GetProcessHeap(), 0, call_seq
->sequence
);
293 call_seq
->sequence
= NULL
;
294 call_seq
->count
= call_seq
->size
= 0;
297 static inline void flush_sequences(struct call_sequence
**seq
, int n
)
300 for (i
= 0; i
< n
; i
++)
301 flush_sequence(seq
, i
);
304 static const char *get_event_name(CH event
)
306 return event_names
[event
];
309 static void compare_attributes(const struct call_entry
*actual
, const struct call_entry
*expected
, const char *context
,
310 int todo
, const char *file
, int line
, int *failcount
)
314 /* attribute count is not stored for expected data */
315 if (expected
->attributes
)
317 struct attribute_entry
*ptr
= expected
->attributes
;
318 while (ptr
->uri
) { lenexp
++; ptr
++; };
321 /* check count first and exit earlier */
322 if (actual
->attr_count
!= lenexp
&& todo
)
326 ok_(file
, line
) (FALSE
, "%s: in event %s expecting attr count %d got %d\n",
327 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
330 ok_(file
, line
) (actual
->attr_count
== lenexp
, "%s: in event %s expecting attr count %d got %d\n",
331 context
, get_event_name(actual
->id
), lenexp
, actual
->attr_count
);
333 if (actual
->attr_count
!= lenexp
) return;
335 /* now compare all attributes strings */
336 for (i
= 0; i
< actual
->attr_count
; i
++)
338 test_saxstr(file
, line
, actual
->attributes
[i
].uriW
, expected
->attributes
[i
].uri
, todo
, failcount
);
339 test_saxstr(file
, line
, actual
->attributes
[i
].localW
, expected
->attributes
[i
].local
, todo
, failcount
);
340 test_saxstr(file
, line
, actual
->attributes
[i
].qnameW
, expected
->attributes
[i
].qname
, todo
, failcount
);
341 test_saxstr(file
, line
, actual
->attributes
[i
].valueW
, expected
->attributes
[i
].value
, todo
, failcount
);
345 static void ok_sequence_(struct call_sequence
**seq
, int sequence_index
,
346 const struct call_entry
*expected
, const char *context
, int todo
,
347 const char *file
, int line
)
349 struct call_sequence
*call_seq
= seq
[sequence_index
];
350 static const struct call_entry end_of_sequence
= { CH_ENDTEST
};
351 const struct call_entry
*actual
, *sequence
;
354 add_call(seq
, sequence_index
, &end_of_sequence
);
356 sequence
= call_seq
->sequence
;
359 while (expected
->id
!= CH_ENDTEST
&& actual
->id
!= CH_ENDTEST
)
361 if (expected
->id
== actual
->id
)
363 /* always test position data */
364 if (expected
->line
!= actual
->line
&& todo
)
369 ok_(file
, line
) (FALSE
,
370 "%s: in event %s expecting line %d got %d\n",
371 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
376 ok_(file
, line
) (expected
->line
== actual
->line
,
377 "%s: in event %s expecting line %d got %d\n",
378 context
, get_event_name(actual
->id
), expected
->line
, actual
->line
);
381 if (expected
->column
!= actual
->column
&& todo
)
386 ok_(file
, line
) (FALSE
,
387 "%s: in event %s expecting column %d got %d\n",
388 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
393 ok_(file
, line
) (expected
->column
== actual
->column
,
394 "%s: in event %s expecting column %d got %d\n",
395 context
, get_event_name(actual
->id
), expected
->column
, actual
->column
);
400 case CH_PUTDOCUMENTLOCATOR
:
401 case CH_STARTDOCUMENT
:
404 case CH_STARTPREFIXMAPPING
:
406 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
407 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
409 case CH_ENDPREFIXMAPPING
:
411 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
413 case CH_STARTELEMENT
:
414 /* compare attributes */
415 compare_attributes(actual
, expected
, context
, todo
, file
, line
, &failcount
);
418 /* uri, localname, qname */
419 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
420 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
421 test_saxstr(file
, line
, actual
->arg3W
, expected
->arg3
, todo
, &failcount
);
424 case CH_IGNORABLEWHITESPACE
:
426 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
428 case CH_PROCESSINGINSTRUCTION
:
430 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
431 test_saxstr(file
, line
, actual
->arg2W
, expected
->arg2
, todo
, &failcount
);
433 case CH_SKIPPEDENTITY
:
435 test_saxstr(file
, line
, actual
->arg1W
, expected
->arg1
, todo
, &failcount
);
438 /* test return value only */
439 if (expected
->ret
!= actual
->ret
&& todo
)
442 ok_(file
, line
) (FALSE
,
443 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
444 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
447 ok_(file
, line
) (expected
->ret
== actual
->ret
,
448 "%s: in event %s expecting ret 0x%08x got 0x%08x\n",
449 context
, get_event_name(actual
->id
), expected
->ret
, actual
->ret
);
452 case EG_IGNORABLEWARNING
:
454 ok(0, "%s: callback not handled, %s\n", context
, get_event_name(actual
->id
));
464 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
465 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
468 flush_sequence(seq
, sequence_index
);
473 ok_(file
, line
) (FALSE
, "%s: call %s was expected, but got call %s instead\n",
474 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
484 if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
487 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
488 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
492 else if (expected
->id
!= CH_ENDTEST
|| actual
->id
!= CH_ENDTEST
)
494 ok_(file
, line
) (FALSE
, "%s: the call sequence is not complete: expected %s - actual %s\n",
495 context
, get_event_name(expected
->id
), get_event_name(actual
->id
));
498 if (todo
&& !failcount
) /* succeeded yet marked todo */
502 ok_(file
, line
)(TRUE
, "%s: marked \"todo_wine\" but succeeds\n", context
);
506 flush_sequence(seq
, sequence_index
);
509 #define ok_sequence(seq, index, exp, contx, todo) \
510 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
512 static void init_call_sequences(struct call_sequence
**seq
, int n
)
516 for (i
= 0; i
< n
; i
++)
517 seq
[i
] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct call_sequence
));
520 static const WCHAR szSimpleXML
[] = {
521 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\"','1','.','0','\"',' ','?','>','\n',
522 '<','B','a','n','k','A','c','c','o','u','n','t','>','\n',
523 ' ',' ',' ','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\n',
524 ' ',' ',' ','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\n',
525 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\n','\0'
528 static const WCHAR carriage_ret_test
[] = {
529 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"','?','>','\r','\n',
530 '<','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n',
531 '\t','<','N','u','m','b','e','r','>','1','2','3','4','<','/','N','u','m','b','e','r','>','\r','\n',
532 '\t','<','N','a','m','e','>','C','a','p','t','a','i','n',' ','A','h','a','b','<','/','N','a','m','e','>','\r','\n',
533 '<','/','B','a','n','k','A','c','c','o','u','n','t','>','\r','\n','\0'
536 static const WCHAR szUtf16XML
[] = {
537 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"',' ',
538 'e','n','c','o','d','i','n','g','=','"','U','T','F','-','1','6','"',' ',
539 's','t','a','n','d','a','l','o','n','e','=','"','n','o','"','?','>','\r','\n'
542 static const CHAR szUtf16BOM
[] = {0xff, 0xfe};
544 static const CHAR szUtf8XML
[] =
545 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n";
547 static const char utf8xml2
[] =
548 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\r\n";
550 static const CHAR testXML
[] =
551 "<?xml version=\"1.0\" ?>\n"
553 " <Number>1234</Number>\n"
554 " <Name>Captain Ahab</Name>\n"
557 static const char test_attributes
[] =
558 "<?xml version=\"1.0\" ?>\n"
559 "<document xmlns:test=\"prefix_test\" xmlns=\"prefix\" test:arg1=\"arg1\" arg2=\"arg2\" test:ar3=\"arg3\">\n"
560 "<node1 xmlns:p=\"test\" />"
563 static struct call_entry content_handler_test1
[] = {
564 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
565 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
566 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
567 { CH_CHARACTERS
, 2, 14, S_OK
, "\n " },
568 { CH_STARTELEMENT
, 3, 12, S_OK
, "", "Number", "Number" },
569 { CH_CHARACTERS
, 3, 12, S_OK
, "1234" },
570 { CH_ENDELEMENT
, 3, 18, S_OK
, "", "Number", "Number" },
571 { CH_CHARACTERS
, 3, 25, S_OK
, "\n " },
572 { CH_STARTELEMENT
, 4, 10, S_OK
, "", "Name", "Name" },
573 { CH_CHARACTERS
, 4, 10, S_OK
, "Captain Ahab" },
574 { CH_ENDELEMENT
, 4, 24, S_OK
, "", "Name", "Name" },
575 { CH_CHARACTERS
, 4, 29, S_OK
, "\n" },
576 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
577 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
581 /* applies to versions 4 and 6 */
582 static struct call_entry content_handler_test1_alternate
[] = {
583 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
584 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
585 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
586 { CH_CHARACTERS
, 3, 4, S_OK
, "\n " },
587 { CH_STARTELEMENT
, 3, 11, S_OK
, "", "Number", "Number" },
588 { CH_CHARACTERS
, 3, 16, S_OK
, "1234" },
589 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "Number", "Number" },
590 { CH_CHARACTERS
, 4, 4, S_OK
, "\n " },
591 { CH_STARTELEMENT
, 4, 9, S_OK
, "", "Name", "Name" },
592 { CH_CHARACTERS
, 4, 22, S_OK
, "Captain Ahab" },
593 { CH_ENDELEMENT
, 4, 28, S_OK
, "", "Name", "Name" },
594 { CH_CHARACTERS
, 5, 1, S_OK
, "\n" },
595 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
596 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
600 static struct call_entry content_handler_test2
[] = {
601 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
602 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
603 { CH_STARTELEMENT
, 2, 14, S_OK
, "", "BankAccount", "BankAccount" },
604 { CH_CHARACTERS
, 2, 14, S_OK
, "\n" },
605 { CH_CHARACTERS
, 2, 16, S_OK
, "\t" },
606 { CH_STARTELEMENT
, 3, 10, S_OK
, "", "Number", "Number" },
607 { CH_CHARACTERS
, 3, 10, S_OK
, "1234" },
608 { CH_ENDELEMENT
, 3, 16, S_OK
, "", "Number", "Number" },
609 { CH_CHARACTERS
, 3, 23, S_OK
, "\n" },
610 { CH_CHARACTERS
, 3, 25, S_OK
, "\t" },
611 { CH_STARTELEMENT
, 4, 8, S_OK
, "", "Name", "Name" },
612 { CH_CHARACTERS
, 4, 8, S_OK
, "Captain Ahab" },
613 { CH_ENDELEMENT
, 4, 22, S_OK
, "", "Name", "Name" },
614 { CH_CHARACTERS
, 4, 27, S_OK
, "\n" },
615 { CH_ENDELEMENT
, 5, 3, S_OK
, "", "BankAccount", "BankAccount" },
616 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
620 static struct call_entry content_handler_test2_alternate
[] = {
621 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
622 { CH_STARTDOCUMENT
, 1, 21, S_OK
},
623 { CH_STARTELEMENT
, 2, 13, S_OK
, "", "BankAccount", "BankAccount" },
624 { CH_CHARACTERS
, 3, 0, S_OK
, "\n" },
625 { CH_CHARACTERS
, 3, 2, S_OK
, "\t" },
626 { CH_STARTELEMENT
, 3, 9, S_OK
, "", "Number", "Number" },
627 { CH_CHARACTERS
, 3, 14, S_OK
, "1234" },
628 { CH_ENDELEMENT
, 3, 22, S_OK
, "", "Number", "Number" },
629 { CH_CHARACTERS
, 4, 0, S_OK
, "\n" },
630 { CH_CHARACTERS
, 4, 2, S_OK
, "\t" },
631 { CH_STARTELEMENT
, 4, 7, S_OK
, "", "Name", "Name" },
632 { CH_CHARACTERS
, 4, 20, S_OK
, "Captain Ahab" },
633 { CH_ENDELEMENT
, 4, 26, S_OK
, "", "Name", "Name" },
634 { CH_CHARACTERS
, 5, 0, S_OK
, "\n" },
635 { CH_ENDELEMENT
, 5, 14, S_OK
, "", "BankAccount", "BankAccount" },
636 { CH_ENDDOCUMENT
, 6, 0, S_OK
},
640 static struct call_entry content_handler_testerror
[] = {
641 { CH_PUTDOCUMENTLOCATOR
, 0, 0, E_FAIL
},
642 { EH_FATALERROR
, 0, 0, E_FAIL
},
646 static struct call_entry content_handler_testerror_alternate
[] = {
647 { CH_PUTDOCUMENTLOCATOR
, 1, 0, E_FAIL
},
648 { EH_FATALERROR
, 1, 0, E_FAIL
},
652 static struct call_entry content_handler_test_callback_rets
[] = {
653 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_FALSE
},
654 { CH_STARTDOCUMENT
, 0, 0, S_FALSE
},
655 { EH_FATALERROR
, 0, 0, S_FALSE
},
659 static struct call_entry content_handler_test_callback_rets_alt
[] = {
660 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_FALSE
},
661 { CH_STARTDOCUMENT
, 1, 22, S_FALSE
},
662 { CH_STARTELEMENT
, 2, 13, S_FALSE
, "", "BankAccount", "BankAccount" },
663 { CH_CHARACTERS
, 3, 4, S_FALSE
, "\n " },
664 { CH_STARTELEMENT
, 3, 11, S_FALSE
, "", "Number", "Number" },
665 { CH_CHARACTERS
, 3, 16, S_FALSE
, "1234" },
666 { CH_ENDELEMENT
, 3, 24, S_FALSE
, "", "Number", "Number" },
667 { CH_CHARACTERS
, 4, 4, S_FALSE
, "\n " },
668 { CH_STARTELEMENT
, 4, 9, S_FALSE
, "", "Name", "Name" },
669 { CH_CHARACTERS
, 4, 22, S_FALSE
, "Captain Ahab" },
670 { CH_ENDELEMENT
, 4, 28, S_FALSE
, "", "Name", "Name" },
671 { CH_CHARACTERS
, 5, 1, S_FALSE
, "\n" },
672 { CH_ENDELEMENT
, 5, 14, S_FALSE
, "", "BankAccount", "BankAccount" },
673 { CH_ENDDOCUMENT
, 6, 0, S_FALSE
},
677 static struct attribute_entry ch_attributes1
[] = {
678 { "", "", "xmlns:test", "prefix_test" },
679 { "", "", "xmlns", "prefix" },
680 { "prefix_test", "arg1", "test:arg1", "arg1" },
681 { "", "arg2", "arg2", "arg2" },
682 { "prefix_test", "ar3", "test:ar3", "arg3" },
686 static struct attribute_entry ch_attributes2
[] = {
687 { "", "", "xmlns:p", "test" },
691 static struct call_entry content_handler_test_attributes
[] = {
692 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
693 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
694 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
695 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
696 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes1
},
697 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
698 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
699 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
700 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
701 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
702 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
703 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
704 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
705 { CH_ENDDOCUMENT
, 0, 0 },
709 static struct attribute_entry ch_attributes_alt_4
[] = {
710 { "prefix_test", "arg1", "test:arg1", "arg1" },
711 { "", "arg2", "arg2", "arg2" },
712 { "prefix_test", "ar3", "test:ar3", "arg3" },
713 { "", "", "xmlns:test", "prefix_test" },
714 { "", "", "xmlns", "prefix" },
718 static struct call_entry content_handler_test_attributes_alternate_4
[] = {
719 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
720 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
721 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
722 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
723 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_4
},
724 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
725 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
726 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2
},
727 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
728 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
729 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
730 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
731 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
732 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
736 /* 'namespace' feature switched off */
737 static struct attribute_entry ch_attributes_alt_no_ns
[] = {
738 { "", "", "xmlns:test", "prefix_test" },
739 { "", "", "xmlns", "prefix" },
740 { "", "", "test:arg1", "arg1" },
741 { "", "", "arg2", "arg2" },
742 { "", "", "test:ar3", "arg3" },
746 static struct call_entry content_handler_test_attributes_alt_no_ns
[] = {
747 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
748 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
749 { CH_STARTELEMENT
, 2, 95, S_OK
, "", "", "document", ch_attributes_alt_no_ns
},
750 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
751 { CH_STARTELEMENT
, 3, 24, S_OK
, "", "", "node1", ch_attributes2
},
752 { CH_ENDELEMENT
, 3, 24, S_OK
, "", "", "node1" },
753 { CH_ENDELEMENT
, 3, 35, S_OK
, "", "", "document" },
754 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
758 static struct attribute_entry ch_attributes_alt_6
[] = {
759 { "prefix_test", "arg1", "test:arg1", "arg1" },
760 { "", "arg2", "arg2", "arg2" },
761 { "prefix_test", "ar3", "test:ar3", "arg3" },
762 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
763 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
767 static struct attribute_entry ch_attributes2_6
[] = {
768 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
772 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
773 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
774 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
775 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
776 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
777 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
778 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
779 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
780 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
781 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
782 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
783 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
784 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
785 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
786 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
790 /* 'namespaces' is on, 'namespace-prefixes' if off */
791 static struct attribute_entry ch_attributes_no_prefix
[] = {
792 { "prefix_test", "arg1", "test:arg1", "arg1" },
793 { "", "arg2", "arg2", "arg2" },
794 { "prefix_test", "ar3", "test:ar3", "arg3" },
798 static struct call_entry content_handler_test_attributes_alt_no_prefix
[] = {
799 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
800 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
801 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
802 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
803 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
804 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
805 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
806 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", NULL
},
807 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
808 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
809 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
810 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
811 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
812 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
816 static struct call_entry content_handler_test_attributes_no_prefix
[] = {
817 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
818 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
819 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "test", "prefix_test" },
820 { CH_STARTPREFIXMAPPING
, 2, 96, S_OK
, "", "prefix" },
821 { CH_STARTELEMENT
, 2, 96, S_OK
, "prefix", "document", "document", ch_attributes_no_prefix
},
822 { CH_CHARACTERS
, 2, 96, S_OK
, "\n" },
823 { CH_STARTPREFIXMAPPING
, 3, 25, S_OK
, "p", "test" },
824 { CH_STARTELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1", NULL
},
825 { CH_ENDELEMENT
, 3, 25, S_OK
, "prefix", "node1", "node1" },
826 { CH_ENDPREFIXMAPPING
, 3, 25, S_OK
, "p" },
827 { CH_ENDELEMENT
, 3, 27, S_OK
, "prefix", "document", "document" },
828 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "" },
829 { CH_ENDPREFIXMAPPING
, 3, 27, S_OK
, "test" },
830 { CH_ENDDOCUMENT
, 0, 0 },
834 static struct attribute_entry xmlspace_attrs
[] = {
835 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
839 static struct call_entry xmlspaceattr_test
[] = {
840 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
841 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
842 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
843 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
844 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
845 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
849 static struct call_entry xmlspaceattr_test_alternate
[] = {
850 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
851 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
852 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
853 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
854 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
855 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
859 static const char xmlspace_attr
[] =
860 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
861 "<a xml:space=\"preserve\"> Some text data </a>";
863 static struct call_entry
*expectCall
;
864 static ISAXLocator
*locator
;
865 static ISAXXMLReader
*g_reader
;
868 static void set_expected_seq(struct call_entry
*expected
)
870 expectCall
= expected
;
873 /* to be called once on each tested callback return */
874 static HRESULT
get_expected_ret(void)
876 HRESULT hr
= expectCall
->ret
;
877 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
881 static HRESULT WINAPI
contentHandler_QueryInterface(
882 ISAXContentHandler
* iface
,
888 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
894 return E_NOINTERFACE
;
900 static ULONG WINAPI
contentHandler_AddRef(
901 ISAXContentHandler
* iface
)
906 static ULONG WINAPI
contentHandler_Release(
907 ISAXContentHandler
* iface
)
912 static HRESULT WINAPI
contentHandler_putDocumentLocator(
913 ISAXContentHandler
* iface
,
914 ISAXLocator
*pLocator
)
916 struct call_entry call
;
921 memset(&call
, 0, sizeof(call
));
922 init_call_entry(locator
, &call
);
923 call
.id
= CH_PUTDOCUMENTLOCATOR
;
924 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
926 if (msxml_version
>= 6) {
927 ISAXAttributes
*attr
, *attr1
;
928 IMXAttributes
*mxattr
;
930 EXPECT_REF(pLocator
, 1);
931 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
933 EXPECT_REF(pLocator
, 2);
934 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
936 EXPECT_REF(pLocator
, 3);
937 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
939 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
940 EXPECT_HR(hr
, E_NOINTERFACE
);
942 ISAXAttributes_Release(attr
);
943 ISAXAttributes_Release(attr1
);
946 return get_expected_ret();
949 static ISAXAttributes
*test_attr_ptr
;
950 static HRESULT WINAPI
contentHandler_startDocument(
951 ISAXContentHandler
* iface
)
953 struct call_entry call
;
955 init_call_entry(locator
, &call
);
956 call
.id
= CH_STARTDOCUMENT
;
957 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
959 test_attr_ptr
= NULL
;
961 return get_expected_ret();
964 static HRESULT WINAPI
contentHandler_endDocument(
965 ISAXContentHandler
* iface
)
967 struct call_entry call
;
969 init_call_entry(locator
, &call
);
970 call
.id
= CH_ENDDOCUMENT
;
971 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
973 return get_expected_ret();
976 static HRESULT WINAPI
contentHandler_startPrefixMapping(
977 ISAXContentHandler
* iface
,
978 const WCHAR
*prefix
, int prefix_len
,
979 const WCHAR
*uri
, int uri_len
)
981 struct call_entry call
;
983 init_call_entry(locator
, &call
);
984 call
.id
= CH_STARTPREFIXMAPPING
;
985 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
986 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
987 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
989 return get_expected_ret();
992 static HRESULT WINAPI
contentHandler_endPrefixMapping(
993 ISAXContentHandler
* iface
,
994 const WCHAR
*prefix
, int len
)
996 struct call_entry call
;
998 init_call_entry(locator
, &call
);
999 call
.id
= CH_ENDPREFIXMAPPING
;
1000 call
.arg1W
= SysAllocStringLen(prefix
, len
);
1001 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1003 return get_expected_ret();
1006 static HRESULT WINAPI
contentHandler_startElement(
1007 ISAXContentHandler
* iface
,
1008 const WCHAR
*uri
, int uri_len
,
1009 const WCHAR
*localname
, int local_len
,
1010 const WCHAR
*qname
, int qname_len
,
1011 ISAXAttributes
*saxattr
)
1013 struct call_entry call
;
1014 IMXAttributes
*mxattr
;
1018 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
1019 EXPECT_HR(hr
, E_NOINTERFACE
);
1021 init_call_entry(locator
, &call
);
1022 call
.id
= CH_STARTELEMENT
;
1023 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1024 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1025 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1028 test_attr_ptr
= saxattr
;
1029 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
1031 /* store actual attributes */
1033 hr
= ISAXAttributes_getLength(saxattr
, &len
);
1034 EXPECT_HR(hr
, S_OK
);
1041 struct attribute_entry
*attr
;
1042 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
1045 hr
= ISAXXMLReader_getFeature(g_reader
, _bstr_("http://xml.org/sax/features/namespaces"), &v
);
1046 EXPECT_HR(hr
, S_OK
);
1048 for (i
= 0; i
< len
; i
++)
1053 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
1054 &localname
, &local_len
, &qname
, &qname_len
);
1055 EXPECT_HR(hr
, S_OK
);
1057 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
1058 EXPECT_HR(hr
, S_OK
);
1060 /* if 'namespaces' switched off uri and local name contains garbage */
1061 if (v
== VARIANT_FALSE
&& msxml_version
> 0)
1063 attr
[i
].uriW
= SysAllocStringLen(NULL
, 0);
1064 attr
[i
].localW
= SysAllocStringLen(NULL
, 0);
1068 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
1069 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
1072 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
1073 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
1076 call
.attributes
= attr
;
1077 call
.attr_count
= len
;
1080 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1082 return get_expected_ret();
1085 static HRESULT WINAPI
contentHandler_endElement(
1086 ISAXContentHandler
* iface
,
1087 const WCHAR
*uri
, int uri_len
,
1088 const WCHAR
*localname
, int local_len
,
1089 const WCHAR
*qname
, int qname_len
)
1091 struct call_entry call
;
1093 init_call_entry(locator
, &call
);
1094 call
.id
= CH_ENDELEMENT
;
1095 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1096 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1097 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1098 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1100 return get_expected_ret();
1103 static HRESULT WINAPI
contentHandler_characters(
1104 ISAXContentHandler
* iface
,
1108 struct call_entry call
;
1110 init_call_entry(locator
, &call
);
1111 call
.id
= CH_CHARACTERS
;
1112 call
.arg1W
= SysAllocStringLen(chars
, len
);
1113 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1115 return get_expected_ret();
1118 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1119 ISAXContentHandler
* iface
,
1120 const WCHAR
*chars
, int len
)
1122 struct call_entry call
;
1124 init_call_entry(locator
, &call
);
1125 call
.id
= CH_IGNORABLEWHITESPACE
;
1126 call
.arg1W
= SysAllocStringLen(chars
, len
);
1127 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1129 return get_expected_ret();
1132 static HRESULT WINAPI
contentHandler_processingInstruction(
1133 ISAXContentHandler
* iface
,
1134 const WCHAR
*target
, int target_len
,
1135 const WCHAR
*data
, int data_len
)
1137 struct call_entry call
;
1139 init_call_entry(locator
, &call
);
1140 call
.id
= CH_PROCESSINGINSTRUCTION
;
1141 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1142 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1143 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1145 return get_expected_ret();
1148 static HRESULT WINAPI
contentHandler_skippedEntity(
1149 ISAXContentHandler
* iface
,
1150 const WCHAR
*name
, int len
)
1152 struct call_entry call
;
1154 init_call_entry(locator
, &call
);
1155 call
.id
= CH_SKIPPEDENTITY
;
1156 call
.arg1W
= SysAllocStringLen(name
, len
);
1158 return get_expected_ret();
1161 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1163 contentHandler_QueryInterface
,
1164 contentHandler_AddRef
,
1165 contentHandler_Release
,
1166 contentHandler_putDocumentLocator
,
1167 contentHandler_startDocument
,
1168 contentHandler_endDocument
,
1169 contentHandler_startPrefixMapping
,
1170 contentHandler_endPrefixMapping
,
1171 contentHandler_startElement
,
1172 contentHandler_endElement
,
1173 contentHandler_characters
,
1174 contentHandler_ignorableWhitespace
,
1175 contentHandler_processingInstruction
,
1176 contentHandler_skippedEntity
1179 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1181 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1182 ISAXErrorHandler
* iface
,
1188 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1194 return E_NOINTERFACE
;
1200 static ULONG WINAPI
isaxerrorHandler_AddRef(
1201 ISAXErrorHandler
* iface
)
1206 static ULONG WINAPI
isaxerrorHandler_Release(
1207 ISAXErrorHandler
* iface
)
1212 static HRESULT WINAPI
isaxerrorHandler_error(
1213 ISAXErrorHandler
* iface
,
1214 ISAXLocator
*pLocator
,
1215 const WCHAR
*pErrorMessage
,
1216 HRESULT hrErrorCode
)
1218 ok(0, "unexpected call\n");
1222 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1223 ISAXErrorHandler
* iface
,
1224 ISAXLocator
*pLocator
,
1225 const WCHAR
*message
,
1228 struct call_entry call
;
1230 init_call_entry(locator
, &call
);
1231 call
.id
= EH_FATALERROR
;
1234 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1240 static HRESULT WINAPI
isaxerrorHanddler_ignorableWarning(
1241 ISAXErrorHandler
* iface
,
1242 ISAXLocator
*pLocator
,
1243 const WCHAR
*pErrorMessage
,
1244 HRESULT hrErrorCode
)
1246 ok(0, "unexpected call\n");
1250 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1252 isaxerrorHandler_QueryInterface
,
1253 isaxerrorHandler_AddRef
,
1254 isaxerrorHandler_Release
,
1255 isaxerrorHandler_error
,
1256 isaxerrorHandler_fatalError
,
1257 isaxerrorHanddler_ignorableWarning
1260 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1262 static HRESULT WINAPI
isaxattributes_QueryInterface(
1263 ISAXAttributes
* iface
,
1269 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1275 return E_NOINTERFACE
;
1281 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1286 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1291 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1297 static HRESULT WINAPI
isaxattributes_getURI(
1298 ISAXAttributes
* iface
,
1303 ok(0, "unexpected call\n");
1307 static HRESULT WINAPI
isaxattributes_getLocalName(
1308 ISAXAttributes
* iface
,
1310 const WCHAR
**pLocalName
,
1311 int *pLocalNameLength
)
1313 ok(0, "unexpected call\n");
1317 static HRESULT WINAPI
isaxattributes_getQName(
1318 ISAXAttributes
* iface
,
1320 const WCHAR
**QName
,
1323 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1324 {'a','t','t','r','2','j','u','n','k',0},
1325 {'a','t','t','r','3',0}};
1326 static const int attrqnamelen
[] = {7, 5, 5};
1328 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1330 *QName
= attrqnamesW
[index
];
1331 *QNameLength
= attrqnamelen
[index
];
1336 static HRESULT WINAPI
isaxattributes_getName(
1337 ISAXAttributes
* iface
,
1341 const WCHAR
** pLocalName
,
1342 int * pLocalNameSize
,
1343 const WCHAR
** pQName
,
1346 ok(0, "unexpected call\n");
1350 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1351 ISAXAttributes
* iface
,
1354 const WCHAR
* pLocalName
,
1355 int cocalNameLength
,
1358 ok(0, "unexpected call\n");
1362 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1363 ISAXAttributes
* iface
,
1364 const WCHAR
* pQName
,
1368 ok(0, "unexpected call\n");
1372 static HRESULT WINAPI
isaxattributes_getType(
1373 ISAXAttributes
* iface
,
1375 const WCHAR
** pType
,
1378 ok(0, "unexpected call\n");
1382 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1383 ISAXAttributes
* iface
,
1386 const WCHAR
* pLocalName
,
1388 const WCHAR
** pType
,
1391 ok(0, "unexpected call\n");
1395 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1396 ISAXAttributes
* iface
,
1397 const WCHAR
* pQName
,
1399 const WCHAR
** pType
,
1402 ok(0, "unexpected call\n");
1406 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1407 const WCHAR
**value
, int *nValue
)
1409 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1410 {'a','2','j','u','n','k',0},
1411 {'<','&','"','>',0}};
1412 static const int attrvalueslen
[] = {2, 2, 4};
1414 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1416 *value
= attrvaluesW
[index
];
1417 *nValue
= attrvalueslen
[index
];
1422 static HRESULT WINAPI
isaxattributes_getValueFromName(
1423 ISAXAttributes
* iface
,
1426 const WCHAR
* pLocalName
,
1428 const WCHAR
** pValue
,
1431 ok(0, "unexpected call\n");
1435 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1436 ISAXAttributes
* iface
,
1437 const WCHAR
* pQName
,
1439 const WCHAR
** pValue
,
1442 ok(0, "unexpected call\n");
1446 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1448 isaxattributes_QueryInterface
,
1449 isaxattributes_AddRef
,
1450 isaxattributes_Release
,
1451 isaxattributes_getLength
,
1452 isaxattributes_getURI
,
1453 isaxattributes_getLocalName
,
1454 isaxattributes_getQName
,
1455 isaxattributes_getName
,
1456 isaxattributes_getIndexFromName
,
1457 isaxattributes_getIndexFromQName
,
1458 isaxattributes_getType
,
1459 isaxattributes_getTypeFromName
,
1460 isaxattributes_getTypeFromQName
,
1461 isaxattributes_getValue
,
1462 isaxattributes_getValueFromName
,
1463 isaxattributes_getValueFromQName
1466 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1468 static int handler_addrefcalled
;
1470 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **ppvObject
)
1474 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
1475 IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1481 return E_NOINTERFACE
;
1487 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1489 handler_addrefcalled
++;
1493 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1498 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1499 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1500 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1502 ok(0, "call not expected\n");
1506 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1508 ok(0, "call not expected\n");
1512 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1513 const WCHAR
* pName
, int nName
)
1515 ok(0, "call not expected\n");
1519 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1520 const WCHAR
* pName
, int nName
)
1522 ok(0, "call not expected\n");
1526 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1528 ok(0, "call not expected\n");
1532 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1534 ok(0, "call not expected\n");
1538 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1539 const WCHAR
* pChars
, int nChars
)
1541 ok(0, "call not expected\n");
1545 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1547 isaxlexical_QueryInterface
,
1549 isaxlexical_Release
,
1550 isaxlexical_startDTD
,
1552 isaxlexical_startEntity
,
1553 isaxlexical_endEntity
,
1554 isaxlexical_startCDATA
,
1555 isaxlexical_endCDATA
,
1559 static ISAXLexicalHandler saxlexicalhandler
= { &SAXLexicalHandlerVtbl
};
1561 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **ppvObject
)
1565 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
1566 IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1572 return E_NOINTERFACE
;
1578 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1580 handler_addrefcalled
++;
1584 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1589 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1590 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1592 ok(0, "call not expected\n");
1596 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1597 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1598 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1599 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1601 ok(0, "call not expected\n");
1605 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1606 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1608 ok(0, "call not expected\n");
1612 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1613 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1614 const WCHAR
* pSystemId
, int nSystemId
)
1616 ok(0, "call not expected\n");
1620 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1622 isaxdecl_QueryInterface
,
1625 isaxdecl_elementDecl
,
1626 isaxdecl_attributeDecl
,
1627 isaxdecl_internalEntityDecl
,
1628 isaxdecl_externalEntityDecl
1631 static ISAXDeclHandler saxdeclhandler
= { &SAXDeclHandlerVtbl
};
1633 typedef struct mxwriter_write_test_t
{
1639 } mxwriter_write_test
;
1641 typedef struct mxwriter_stream_test_t
{
1643 const char *encoding
;
1644 mxwriter_write_test expected_writes
[4];
1645 } mxwriter_stream_test
;
1647 static const mxwriter_write_test
*current_write_test
;
1648 static DWORD current_stream_test_index
;
1650 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1654 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1657 return E_NOINTERFACE
;
1662 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1667 static ULONG WINAPI
istream_Release(IStream
*iface
)
1672 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1674 ok(0, "unexpected call\n");
1678 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1682 ok(pv
!= NULL
, "pv == NULL\n");
1684 if(current_write_test
->last
) {
1685 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
1689 fail
= current_write_test
->fail_write
;
1691 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
1692 current_write_test
->cb
, cb
, current_stream_test_index
);
1695 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
1697 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
1699 ++current_write_test
;
1704 return fail
? E_FAIL
: S_OK
;
1707 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1708 ULARGE_INTEGER
*plibNewPosition
)
1710 ok(0, "unexpected call\n");
1714 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1716 ok(0, "unexpected call\n");
1720 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1721 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1723 ok(0, "unexpected call\n");
1727 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1729 ok(0, "unexpected call\n");
1733 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1735 ok(0, "unexpected call\n");
1739 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1740 ULARGE_INTEGER cb
, DWORD dwLockType
)
1742 ok(0, "unexpected call\n");
1746 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1747 ULARGE_INTEGER cb
, DWORD dwLockType
)
1749 ok(0, "unexpected call\n");
1753 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1755 ok(0, "unexpected call\n");
1759 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1761 ok(0, "unexpected call\n");
1765 static const IStreamVtbl StreamVtbl
= {
1766 istream_QueryInterface
,
1777 istream_UnlockRegion
,
1782 static IStream mxstream
= { &StreamVtbl
};
1784 static struct msxmlsupported_data_t reader_support_data
[] =
1786 { &CLSID_SAXXMLReader
, "SAXReader" },
1787 { &CLSID_SAXXMLReader30
, "SAXReader30" },
1788 { &CLSID_SAXXMLReader40
, "SAXReader40" },
1789 { &CLSID_SAXXMLReader60
, "SAXReader60" },
1793 static void test_saxreader(void)
1795 const struct msxmlsupported_data_t
*table
= reader_support_data
;
1797 ISAXXMLReader
*reader
= NULL
;
1799 ISAXContentHandler
*content
;
1800 ISAXErrorHandler
*lpErrorHandler
;
1802 SAFEARRAYBOUND SADim
[1];
1805 ULARGE_INTEGER size
;
1809 static const CHAR testXmlA
[] = "test.xml";
1810 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
1811 IXMLDOMDocument
*doc
;
1814 while (table
->clsid
)
1816 struct call_entry
*test_seq
;
1819 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
1825 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
1826 EXPECT_HR(hr
, S_OK
);
1829 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
1831 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1836 /* crashes on old versions */
1837 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
1838 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1840 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
1841 EXPECT_HR(hr
, E_POINTER
);
1843 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
1844 EXPECT_HR(hr
, E_POINTER
);
1847 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
1848 EXPECT_HR(hr
, S_OK
);
1849 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
1851 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
1852 EXPECT_HR(hr
, S_OK
);
1853 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
1855 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
1856 EXPECT_HR(hr
, S_OK
);
1858 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
1859 EXPECT_HR(hr
, S_OK
);
1861 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
1862 EXPECT_HR(hr
, S_OK
);
1864 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
1865 EXPECT_HR(hr
, S_OK
);
1866 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
1868 V_VT(&var
) = VT_BSTR
;
1869 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
1871 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1872 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1873 test_seq
= content_handler_test1_alternate
;
1875 test_seq
= content_handler_test1
;
1876 set_expected_seq(test_seq
);
1877 hr
= ISAXXMLReader_parse(reader
, var
);
1878 EXPECT_HR(hr
, S_OK
);
1879 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
1883 SADim
[0].lLbound
= 0;
1884 SADim
[0].cElements
= sizeof(testXML
)-1;
1885 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
1886 SafeArrayAccessData(sa
, (void**)&ptr
);
1887 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
1888 SafeArrayUnaccessData(sa
);
1889 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
1892 set_expected_seq(test_seq
);
1893 hr
= ISAXXMLReader_parse(reader
, var
);
1894 EXPECT_HR(hr
, S_OK
);
1895 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from safe array", FALSE
);
1897 SafeArrayDestroy(sa
);
1899 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1900 size
.QuadPart
= strlen(testXML
);
1901 IStream_SetSize(stream
, size
);
1902 IStream_Write(stream
, testXML
, strlen(testXML
), &written
);
1904 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
1905 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
1906 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
1908 set_expected_seq(test_seq
);
1909 hr
= ISAXXMLReader_parse(reader
, var
);
1910 EXPECT_HR(hr
, S_OK
);
1911 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
1913 IStream_Release(stream
);
1915 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1916 size
.QuadPart
= strlen(test_attributes
);
1917 IStream_SetSize(stream
, size
);
1918 IStream_Write(stream
, test_attributes
, strlen(test_attributes
), &written
);
1920 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
1921 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
1922 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
1924 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
1925 test_seq
= content_handler_test_attributes_alternate_4
;
1926 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1927 test_seq
= content_handler_test_attributes_alternate_6
;
1929 test_seq
= content_handler_test_attributes
;
1931 set_expected_seq(test_seq
);
1932 hr
= ISAXXMLReader_parse(reader
, var
);
1933 EXPECT_HR(hr
, S_OK
);
1935 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1936 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1937 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
1939 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
1941 IStream_Release(stream
);
1943 V_VT(&var
) = VT_BSTR
;
1944 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
1946 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1947 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1948 test_seq
= content_handler_test2_alternate
;
1950 test_seq
= content_handler_test2
;
1952 set_expected_seq(test_seq
);
1953 hr
= ISAXXMLReader_parse(reader
, var
);
1954 EXPECT_HR(hr
, S_OK
);
1955 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
1960 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1961 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
1962 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
1965 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1966 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1967 test_seq
= content_handler_test1_alternate
;
1969 test_seq
= content_handler_test1
;
1970 set_expected_seq(test_seq
);
1971 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1972 EXPECT_HR(hr
, S_OK
);
1973 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
1976 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1977 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1978 test_seq
= content_handler_testerror_alternate
;
1980 test_seq
= content_handler_testerror
;
1981 set_expected_seq(test_seq
);
1982 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1983 EXPECT_HR(hr
, E_FAIL
);
1984 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
1986 /* callback ret values */
1987 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1988 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1990 test_seq
= content_handler_test_callback_rets_alt
;
1991 set_expected_seq(test_seq
);
1992 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1993 EXPECT_HR(hr
, S_OK
);
1997 test_seq
= content_handler_test_callback_rets
;
1998 set_expected_seq(test_seq
);
1999 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2000 EXPECT_HR(hr
, S_FALSE
);
2002 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
2004 DeleteFileA(testXmlA
);
2006 /* parse from IXMLDOMDocument */
2007 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
2008 &IID_IXMLDOMDocument
, (void**)&doc
);
2009 EXPECT_HR(hr
, S_OK
);
2011 str
= SysAllocString(szSimpleXML
);
2012 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
2013 EXPECT_HR(hr
, S_OK
);
2016 V_VT(&var
) = VT_UNKNOWN
;
2017 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
2019 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2020 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2021 test_seq
= content_handler_test2_alternate
;
2023 test_seq
= content_handler_test2
;
2025 set_expected_seq(test_seq
);
2026 hr
= ISAXXMLReader_parse(reader
, var
);
2027 EXPECT_HR(hr
, S_OK
);
2028 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
2029 IXMLDOMDocument_Release(doc
);
2031 /* xml:space test */
2032 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2033 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2035 test_seq
= xmlspaceattr_test_alternate
;
2038 test_seq
= xmlspaceattr_test
;
2040 set_expected_seq(test_seq
);
2041 V_VT(&var
) = VT_BSTR
;
2042 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
2043 hr
= ISAXXMLReader_parse(reader
, var
);
2044 EXPECT_HR(hr
, S_OK
);
2046 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2047 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2049 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
2052 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
2054 /* switch off 'namespaces' feature */
2055 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_FALSE
);
2056 EXPECT_HR(hr
, S_OK
);
2058 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2059 size
.QuadPart
= strlen(test_attributes
);
2060 IStream_SetSize(stream
, size
);
2061 IStream_Write(stream
, test_attributes
, strlen(test_attributes
), &written
);
2063 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2064 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
2065 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2067 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2068 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2070 test_seq
= content_handler_test_attributes_alt_no_ns
;
2073 test_seq
= content_handler_test_attributes
;
2075 set_expected_seq(test_seq
);
2076 hr
= ISAXXMLReader_parse(reader
, var
);
2077 EXPECT_HR(hr
, S_OK
);
2078 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
2079 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), VARIANT_TRUE
);
2080 EXPECT_HR(hr
, S_OK
);
2082 /* switch off 'namespace-prefixes' feature */
2083 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_FALSE
);
2084 EXPECT_HR(hr
, S_OK
);
2086 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2087 size
.QuadPart
= strlen(test_attributes
);
2088 IStream_SetSize(stream
, size
);
2089 IStream_Write(stream
, test_attributes
, strlen(test_attributes
), &written
);
2091 IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
2092 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
2093 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
2095 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
2096 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
2098 test_seq
= content_handler_test_attributes_alt_no_prefix
;
2101 test_seq
= content_handler_test_attributes_no_prefix
;
2103 set_expected_seq(test_seq
);
2104 hr
= ISAXXMLReader_parse(reader
, var
);
2105 EXPECT_HR(hr
, S_OK
);
2106 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
2108 hr
= ISAXXMLReader_putFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), VARIANT_TRUE
);
2109 EXPECT_HR(hr
, S_OK
);
2111 ISAXXMLReader_Release(reader
);
2118 struct saxreader_props_test_t
2120 const char *prop_name
;
2124 static const struct saxreader_props_test_t props_test_data
[] = {
2125 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&saxlexicalhandler
},
2126 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&saxdeclhandler
},
2130 static void test_saxreader_properties(void)
2132 const struct saxreader_props_test_t
*ptr
= props_test_data
;
2133 ISAXXMLReader
*reader
;
2136 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
2137 &IID_ISAXXMLReader
, (void**)&reader
);
2138 EXPECT_HR(hr
, S_OK
);
2140 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
2141 EXPECT_HR(hr
, E_POINTER
);
2143 while (ptr
->prop_name
)
2147 V_VT(&v
) = VT_EMPTY
;
2148 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2149 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2150 EXPECT_HR(hr
, S_OK
);
2151 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2152 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2154 V_VT(&v
) = VT_UNKNOWN
;
2155 V_UNKNOWN(&v
) = ptr
->iface
;
2156 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2157 EXPECT_HR(hr
, S_OK
);
2159 V_VT(&v
) = VT_EMPTY
;
2160 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2161 handler_addrefcalled
= 0;
2162 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2163 EXPECT_HR(hr
, S_OK
);
2164 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2165 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2166 ok(handler_addrefcalled
== 1, "AddRef called %d times\n", handler_addrefcalled
);
2169 V_VT(&v
) = VT_EMPTY
;
2170 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2171 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2172 EXPECT_HR(hr
, S_OK
);
2174 V_VT(&v
) = VT_EMPTY
;
2175 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2176 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2177 EXPECT_HR(hr
, S_OK
);
2178 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2179 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2181 V_VT(&v
) = VT_UNKNOWN
;
2182 V_UNKNOWN(&v
) = ptr
->iface
;
2183 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2184 EXPECT_HR(hr
, S_OK
);
2186 /* only VT_EMPTY seems to be valid to reset property */
2188 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2189 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2190 EXPECT_HR(hr
, E_INVALIDARG
);
2192 V_VT(&v
) = VT_EMPTY
;
2193 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2194 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2195 EXPECT_HR(hr
, S_OK
);
2196 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2197 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2200 V_VT(&v
) = VT_UNKNOWN
;
2201 V_UNKNOWN(&v
) = NULL
;
2202 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2203 EXPECT_HR(hr
, S_OK
);
2205 V_VT(&v
) = VT_EMPTY
;
2206 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2207 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2208 EXPECT_HR(hr
, S_OK
);
2209 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2210 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2215 ISAXXMLReader_Release(reader
);
2219 struct feature_ns_entry_t
{
2223 VARIANT_BOOL value2
; /* feature value after feature set to 0xc */
2226 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2227 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
, VARIANT_FALSE
},
2228 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
, VARIANT_FALSE
},
2229 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
, VARIANT_TRUE
},
2230 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
, VARIANT_TRUE
},
2234 static const char *feature_names
[] = {
2235 "http://xml.org/sax/features/namespaces",
2236 "http://xml.org/sax/features/namespace-prefixes",
2240 static void test_saxreader_features(void)
2242 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2243 ISAXXMLReader
*reader
;
2251 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2254 win_skip("can't create %s instance\n", entry
->clsid
);
2259 name
= feature_names
;
2263 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2264 EXPECT_HR(hr
, S_OK
);
2265 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2268 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), value
);
2269 EXPECT_HR(hr
, S_OK
);
2272 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2273 EXPECT_HR(hr
, S_OK
);
2274 ok(entry
->value2
== value
, "%s: got wrong value %x, expected %x\n", entry
->clsid
, value
, entry
->value2
);
2276 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_FALSE
);
2277 EXPECT_HR(hr
, S_OK
);
2279 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2280 EXPECT_HR(hr
, S_OK
);
2281 ok(value
== VARIANT_FALSE
, "%s: got wrong value %x, expected VARIANT_FALSE\n", entry
->clsid
, value
);
2283 hr
= ISAXXMLReader_putFeature(reader
, _bstr_(*name
), VARIANT_TRUE
);
2284 EXPECT_HR(hr
, S_OK
);
2286 hr
= ISAXXMLReader_getFeature(reader
, _bstr_(*name
), &value
);
2287 EXPECT_HR(hr
, S_OK
);
2288 ok(value
== VARIANT_TRUE
, "%s: got wrong value %x, expected VARIANT_TRUE\n", entry
->clsid
, value
);
2293 ISAXXMLReader_Release(reader
);
2299 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2300 static const CHAR UTF8BOMTest
[] =
2301 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2304 struct enc_test_entry_t
{
2312 static const struct enc_test_entry_t encoding_test_data
[] = {
2313 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, 1 },
2314 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, 1 },
2315 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, 0 },
2316 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, 0 },
2320 static void test_saxreader_encoding(void)
2322 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2323 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2324 static const CHAR testXmlA
[] = "test.xml";
2328 ISAXXMLReader
*reader
;
2334 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2337 win_skip("can't create %s instance\n", entry
->clsid
);
2342 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2343 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2344 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2347 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2349 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2351 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2353 DeleteFileA(testXmlA
);
2355 /* try BSTR input with no BOM or '<?xml' instruction */
2356 V_VT(&input
) = VT_BSTR
;
2357 V_BSTR(&input
) = _bstr_("<element></element>");
2358 hr
= ISAXXMLReader_parse(reader
, input
);
2359 EXPECT_HR(hr
, S_OK
);
2361 ISAXXMLReader_Release(reader
);
2368 static void test_mxwriter_handlers(void)
2370 ISAXContentHandler
*handler
;
2371 IMXWriter
*writer
, *writer2
;
2372 ISAXDeclHandler
*decl
;
2373 ISAXLexicalHandler
*lh
;
2376 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2377 &IID_IMXWriter
, (void**)&writer
);
2378 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2380 EXPECT_REF(writer
, 1);
2382 /* ISAXContentHandler */
2383 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&handler
);
2384 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2385 EXPECT_REF(writer
, 2);
2386 EXPECT_REF(handler
, 2);
2388 hr
= ISAXContentHandler_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2389 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2390 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2391 EXPECT_REF(writer
, 3);
2392 EXPECT_REF(writer2
, 3);
2393 IMXWriter_Release(writer2
);
2394 ISAXContentHandler_Release(handler
);
2396 /* ISAXLexicalHandler */
2397 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lh
);
2398 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2399 EXPECT_REF(writer
, 2);
2402 hr
= ISAXLexicalHandler_QueryInterface(lh
, &IID_IMXWriter
, (void**)&writer2
);
2403 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2404 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2405 EXPECT_REF(writer
, 3);
2406 EXPECT_REF(writer2
, 3);
2407 IMXWriter_Release(writer2
);
2408 ISAXLexicalHandler_Release(lh
);
2410 /* ISAXDeclHandler */
2411 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
2412 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2413 EXPECT_REF(writer
, 2);
2416 hr
= ISAXDeclHandler_QueryInterface(decl
, &IID_IMXWriter
, (void**)&writer2
);
2417 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2418 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2419 EXPECT_REF(writer
, 3);
2420 EXPECT_REF(writer2
, 3);
2421 IMXWriter_Release(writer2
);
2422 ISAXDeclHandler_Release(decl
);
2424 IMXWriter_Release(writer
);
2428 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2430 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2431 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2432 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2433 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2437 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2439 { &CLSID_SAXAttributes
, "SAXAttributes" },
2440 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2441 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2442 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2446 struct mxwriter_props_t
2450 VARIANT_BOOL disable_escape
;
2451 VARIANT_BOOL indent
;
2452 VARIANT_BOOL omitdecl
;
2453 VARIANT_BOOL standalone
;
2454 const char *encoding
;
2457 static const struct mxwriter_props_t mxwriter_default_props
[] =
2459 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2460 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2461 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2462 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2466 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2470 while (table
->clsid
)
2477 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2484 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2485 &IID_IMXWriter
, (void**)&writer
);
2486 EXPECT_HR(hr
, S_OK
);
2489 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
2490 EXPECT_HR(hr
, S_OK
);
2491 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
2493 b
= !table
->disable_escape
;
2494 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
2495 EXPECT_HR(hr
, S_OK
);
2496 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
2497 table
->disable_escape
);
2500 hr
= IMXWriter_get_indent(writer
, &b
);
2501 EXPECT_HR(hr
, S_OK
);
2502 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
2504 b
= !table
->omitdecl
;
2505 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
2506 EXPECT_HR(hr
, S_OK
);
2507 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
2509 b
= !table
->standalone
;
2510 hr
= IMXWriter_get_standalone(writer
, &b
);
2511 EXPECT_HR(hr
, S_OK
);
2512 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
2514 hr
= IMXWriter_get_encoding(writer
, &encoding
);
2515 EXPECT_HR(hr
, S_OK
);
2516 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
2517 i
, wine_dbgstr_w(encoding
), table
->encoding
);
2518 SysFreeString(encoding
);
2520 IMXWriter_Release(writer
);
2527 static void test_mxwriter_properties(void)
2529 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
2530 static const WCHAR emptyW
[] = {0};
2531 static const WCHAR testW
[] = {'t','e','s','t',0};
2532 ISAXContentHandler
*content
;
2539 test_mxwriter_default_properties(mxwriter_default_props
);
2541 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2542 &IID_IMXWriter
, (void**)&writer
);
2543 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2545 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
2546 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2548 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
2549 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2551 hr
= IMXWriter_get_indent(writer
, NULL
);
2552 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2554 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
2555 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2557 hr
= IMXWriter_get_standalone(writer
, NULL
);
2558 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2561 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
2562 ok(hr
== S_OK
, "got %08x\n", hr
);
2565 hr
= IMXWriter_get_standalone(writer
, &b
);
2566 ok(hr
== S_OK
, "got %08x\n", hr
);
2567 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
2569 hr
= IMXWriter_get_encoding(writer
, NULL
);
2570 EXPECT_HR(hr
, E_POINTER
);
2572 /* UTF-16 is a default setting apparently */
2573 str
= (void*)0xdeadbeef;
2574 hr
= IMXWriter_get_encoding(writer
, &str
);
2575 EXPECT_HR(hr
, S_OK
);
2576 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
2578 str2
= (void*)0xdeadbeef;
2579 hr
= IMXWriter_get_encoding(writer
, &str2
);
2580 ok(hr
== S_OK
, "got %08x\n", hr
);
2581 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
2583 SysFreeString(str2
);
2586 /* put empty string */
2587 str
= SysAllocString(emptyW
);
2588 hr
= IMXWriter_put_encoding(writer
, str
);
2589 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2592 str
= (void*)0xdeadbeef;
2593 hr
= IMXWriter_get_encoding(writer
, &str
);
2594 EXPECT_HR(hr
, S_OK
);
2595 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
2598 /* invalid encoding name */
2599 str
= SysAllocString(testW
);
2600 hr
= IMXWriter_put_encoding(writer
, str
);
2601 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2604 /* test case sensivity */
2605 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
2606 EXPECT_HR(hr
, S_OK
);
2607 str
= (void*)0xdeadbeef;
2608 hr
= IMXWriter_get_encoding(writer
, &str
);
2609 EXPECT_HR(hr
, S_OK
);
2610 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
2613 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
2614 EXPECT_HR(hr
, S_OK
);
2615 str
= (void*)0xdeadbeef;
2616 hr
= IMXWriter_get_encoding(writer
, &str
);
2617 EXPECT_HR(hr
, S_OK
);
2618 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
2621 /* how it affects document creation */
2622 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2623 EXPECT_HR(hr
, S_OK
);
2625 hr
= ISAXContentHandler_startDocument(content
);
2626 EXPECT_HR(hr
, S_OK
);
2627 hr
= ISAXContentHandler_endDocument(content
);
2628 EXPECT_HR(hr
, S_OK
);
2630 V_VT(&dest
) = VT_EMPTY
;
2631 hr
= IMXWriter_get_output(writer
, &dest
);
2632 EXPECT_HR(hr
, S_OK
);
2633 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2634 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
2635 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2636 VariantClear(&dest
);
2637 ISAXContentHandler_Release(content
);
2639 hr
= IMXWriter_get_version(writer
, NULL
);
2640 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2641 /* default version is 'surprisingly' 1.0 */
2642 hr
= IMXWriter_get_version(writer
, &str
);
2643 ok(hr
== S_OK
, "got %08x\n", hr
);
2644 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
2647 /* store version string as is */
2648 hr
= IMXWriter_put_version(writer
, NULL
);
2649 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2651 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
2652 ok(hr
== S_OK
, "got %08x\n", hr
);
2654 hr
= IMXWriter_put_version(writer
, _bstr_(""));
2655 ok(hr
== S_OK
, "got %08x\n", hr
);
2656 hr
= IMXWriter_get_version(writer
, &str
);
2657 ok(hr
== S_OK
, "got %08x\n", hr
);
2658 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
2661 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
2662 ok(hr
== S_OK
, "got %08x\n", hr
);
2663 hr
= IMXWriter_get_version(writer
, &str
);
2664 ok(hr
== S_OK
, "got %08x\n", hr
);
2665 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
2668 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
2669 ok(hr
== S_OK
, "got %08x\n", hr
);
2670 hr
= IMXWriter_get_version(writer
, &str
);
2671 ok(hr
== S_OK
, "got %08x\n", hr
);
2672 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
2675 IMXWriter_Release(writer
);
2679 static void test_mxwriter_flush(void)
2681 ISAXContentHandler
*content
;
2684 ULARGE_INTEGER pos2
;
2689 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2690 &IID_IMXWriter
, (void**)&writer
);
2691 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2693 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2694 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2695 EXPECT_REF(stream
, 1);
2697 /* detach when nothing was attached */
2698 V_VT(&dest
) = VT_EMPTY
;
2699 hr
= IMXWriter_put_output(writer
, dest
);
2700 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2703 V_VT(&dest
) = VT_UNKNOWN
;
2704 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
2705 hr
= IMXWriter_put_output(writer
, dest
);
2706 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2707 todo_wine
EXPECT_REF(stream
, 3);
2709 /* detach setting VT_EMPTY destination */
2710 V_VT(&dest
) = VT_EMPTY
;
2711 hr
= IMXWriter_put_output(writer
, dest
);
2712 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2713 EXPECT_REF(stream
, 1);
2715 V_VT(&dest
) = VT_UNKNOWN
;
2716 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
2717 hr
= IMXWriter_put_output(writer
, dest
);
2718 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2720 /* flush() doesn't detach a stream */
2721 hr
= IMXWriter_flush(writer
);
2722 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2723 todo_wine
EXPECT_REF(stream
, 3);
2726 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2727 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2728 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
2730 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2731 ok(hr
== S_OK
, "got %08x\n", hr
);
2733 hr
= ISAXContentHandler_startDocument(content
);
2734 ok(hr
== S_OK
, "got %08x\n", hr
);
2737 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2738 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2739 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
2741 /* already started */
2742 hr
= ISAXContentHandler_startDocument(content
);
2743 ok(hr
== S_OK
, "got %08x\n", hr
);
2745 hr
= ISAXContentHandler_endDocument(content
);
2746 ok(hr
== S_OK
, "got %08x\n", hr
);
2748 /* flushed on endDocument() */
2750 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2751 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2752 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
2754 ISAXContentHandler_Release(content
);
2755 IStream_Release(stream
);
2756 IMXWriter_Release(writer
);
2759 static void test_mxwriter_startenddocument(void)
2761 ISAXContentHandler
*content
;
2766 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2767 &IID_IMXWriter
, (void**)&writer
);
2768 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2770 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2771 ok(hr
== S_OK
, "got %08x\n", hr
);
2773 hr
= ISAXContentHandler_startDocument(content
);
2774 ok(hr
== S_OK
, "got %08x\n", hr
);
2776 hr
= ISAXContentHandler_endDocument(content
);
2777 ok(hr
== S_OK
, "got %08x\n", hr
);
2779 V_VT(&dest
) = VT_EMPTY
;
2780 hr
= IMXWriter_get_output(writer
, &dest
);
2781 ok(hr
== S_OK
, "got %08x\n", hr
);
2782 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2783 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
2784 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2785 VariantClear(&dest
);
2787 /* now try another startDocument */
2788 hr
= ISAXContentHandler_startDocument(content
);
2789 ok(hr
== S_OK
, "got %08x\n", hr
);
2790 /* and get duplicated prolog */
2791 V_VT(&dest
) = VT_EMPTY
;
2792 hr
= IMXWriter_get_output(writer
, &dest
);
2793 ok(hr
== S_OK
, "got %08x\n", hr
);
2794 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2795 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
2796 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
2797 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2798 VariantClear(&dest
);
2800 ISAXContentHandler_Release(content
);
2801 IMXWriter_Release(writer
);
2803 /* now with omitted declaration */
2804 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2805 &IID_IMXWriter
, (void**)&writer
);
2806 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2808 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2809 ok(hr
== S_OK
, "got %08x\n", hr
);
2811 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2812 ok(hr
== S_OK
, "got %08x\n", hr
);
2814 hr
= ISAXContentHandler_startDocument(content
);
2815 ok(hr
== S_OK
, "got %08x\n", hr
);
2817 hr
= ISAXContentHandler_endDocument(content
);
2818 ok(hr
== S_OK
, "got %08x\n", hr
);
2820 V_VT(&dest
) = VT_EMPTY
;
2821 hr
= IMXWriter_get_output(writer
, &dest
);
2822 ok(hr
== S_OK
, "got %08x\n", hr
);
2823 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2824 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2825 VariantClear(&dest
);
2827 ISAXContentHandler_Release(content
);
2828 IMXWriter_Release(writer
);
2840 struct writer_startendelement_t
{
2842 enum startendtype type
;
2844 const char *local_name
;
2848 ISAXAttributes
*attr
;
2851 static const char startelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\">";
2852 static const char startendelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\"/>";
2854 static const struct writer_startendelement_t writer_startendelement
[] = {
2856 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2857 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2858 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2859 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
2860 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2862 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2863 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2864 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
2865 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2866 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2868 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2869 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
2870 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2871 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2872 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2874 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
2875 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2876 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2877 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2878 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2880 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2881 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2882 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2883 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
2884 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2886 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2887 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2888 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2889 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2890 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2892 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2893 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2894 /* endElement tests */
2895 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2896 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2897 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2899 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
2900 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2901 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2902 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2903 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
2905 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2906 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2907 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2908 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
2909 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2911 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2912 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2913 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
2914 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2915 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2917 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2918 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2919 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2920 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2921 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2923 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
2924 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2925 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2926 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2927 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2929 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2930 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2931 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2932 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2934 /* with attributes */
2935 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
2937 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
2938 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
2939 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
2940 /* empty elements */
2941 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
2942 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
2944 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
2945 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
2946 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
2947 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
2948 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
2950 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
2954 static void get_class_support_data(struct msxmlsupported_data_t
*table
, REFIID riid
)
2956 while (table
->clsid
)
2961 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, riid
, (void**)&unk
);
2962 if (hr
== S_OK
) IUnknown_Release(unk
);
2964 table
->supported
= hr
== S_OK
;
2965 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
2971 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
2975 while (table
->clsid
)
2977 ISAXContentHandler
*content
;
2981 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2988 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2989 &IID_IMXWriter
, (void**)&writer
);
2990 EXPECT_HR(hr
, S_OK
);
2992 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2993 EXPECT_HR(hr
, S_OK
);
2995 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2996 EXPECT_HR(hr
, S_OK
);
2998 hr
= ISAXContentHandler_startDocument(content
);
2999 EXPECT_HR(hr
, S_OK
);
3001 if (table
->type
== StartElement
)
3003 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3004 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
), table
->attr
);
3005 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3007 else if (table
->type
== EndElement
)
3009 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3010 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
));
3011 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3015 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3016 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
), table
->attr
);
3017 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3018 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
3019 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
));
3020 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3028 V_VT(&dest
) = VT_EMPTY
;
3029 hr
= IMXWriter_get_output(writer
, &dest
);
3030 EXPECT_HR(hr
, S_OK
);
3031 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3032 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3033 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3034 VariantClear(&dest
);
3037 ISAXContentHandler_Release(content
);
3038 IMXWriter_Release(writer
);
3047 static void test_mxwriter_startendelement(void)
3049 ISAXContentHandler
*content
;
3054 test_mxwriter_startendelement_batch(writer_startendelement
);
3056 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3057 &IID_IMXWriter
, (void**)&writer
);
3058 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
3060 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3061 ok(hr
== S_OK
, "got %08x\n", hr
);
3063 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3064 ok(hr
== S_OK
, "got %08x\n", hr
);
3066 hr
= ISAXContentHandler_startDocument(content
);
3067 ok(hr
== S_OK
, "got %08x\n", hr
);
3069 /* all string pointers should be not null */
3070 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
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 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
3081 ok(hr
== S_OK
, "got %08x\n", hr
);
3083 V_VT(&dest
) = VT_EMPTY
;
3084 hr
= IMXWriter_get_output(writer
, &dest
);
3085 ok(hr
== S_OK
, "got %08x\n", hr
);
3086 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3087 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3088 VariantClear(&dest
);
3090 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
3091 EXPECT_HR(hr
, E_INVALIDARG
);
3093 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
3094 EXPECT_HR(hr
, E_INVALIDARG
);
3096 /* only local name is an error too */
3097 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
3098 EXPECT_HR(hr
, E_INVALIDARG
);
3100 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
3101 EXPECT_HR(hr
, S_OK
);
3103 V_VT(&dest
) = VT_EMPTY
;
3104 hr
= IMXWriter_get_output(writer
, &dest
);
3105 EXPECT_HR(hr
, S_OK
);
3106 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3107 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3108 VariantClear(&dest
);
3110 hr
= ISAXContentHandler_endDocument(content
);
3111 EXPECT_HR(hr
, S_OK
);
3113 V_VT(&dest
) = VT_EMPTY
;
3114 hr
= IMXWriter_put_output(writer
, dest
);
3115 EXPECT_HR(hr
, S_OK
);
3117 V_VT(&dest
) = VT_EMPTY
;
3118 hr
= IMXWriter_get_output(writer
, &dest
);
3119 EXPECT_HR(hr
, S_OK
);
3120 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3121 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3122 VariantClear(&dest
);
3124 hr
= ISAXContentHandler_startDocument(content
);
3125 EXPECT_HR(hr
, S_OK
);
3127 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
3128 EXPECT_HR(hr
, S_OK
);
3130 V_VT(&dest
) = VT_EMPTY
;
3131 hr
= IMXWriter_get_output(writer
, &dest
);
3132 EXPECT_HR(hr
, S_OK
);
3133 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3134 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3135 VariantClear(&dest
);
3137 ISAXContentHandler_endDocument(content
);
3138 IMXWriter_flush(writer
);
3140 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
3141 EXPECT_HR(hr
, S_OK
);
3142 V_VT(&dest
) = VT_EMPTY
;
3143 hr
= IMXWriter_get_output(writer
, &dest
);
3144 EXPECT_HR(hr
, S_OK
);
3145 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3146 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3147 VariantClear(&dest
);
3149 ISAXContentHandler_Release(content
);
3150 IMXWriter_Release(writer
);
3154 struct writer_characters_t
{
3160 static const struct writer_characters_t writer_characters
[] = {
3161 { &CLSID_MXXMLWriter
, "< > & \"", "< > & \"" },
3162 { &CLSID_MXXMLWriter30
, "< > & \"", "< > & \"" },
3163 { &CLSID_MXXMLWriter40
, "< > & \"", "< > & \"" },
3164 { &CLSID_MXXMLWriter60
, "< > & \"", "< > & \"" },
3168 static void test_mxwriter_characters(void)
3170 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
3171 const struct writer_characters_t
*table
= writer_characters
;
3172 ISAXContentHandler
*content
;
3178 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3179 &IID_IMXWriter
, (void**)&writer
);
3180 EXPECT_HR(hr
, S_OK
);
3182 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3183 EXPECT_HR(hr
, S_OK
);
3185 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3186 EXPECT_HR(hr
, S_OK
);
3188 hr
= ISAXContentHandler_startDocument(content
);
3189 EXPECT_HR(hr
, S_OK
);
3191 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
3192 EXPECT_HR(hr
, E_INVALIDARG
);
3194 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3195 EXPECT_HR(hr
, S_OK
);
3197 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
3198 EXPECT_HR(hr
, S_OK
);
3200 V_VT(&dest
) = VT_EMPTY
;
3201 hr
= IMXWriter_get_output(writer
, &dest
);
3202 EXPECT_HR(hr
, S_OK
);
3203 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3204 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3205 VariantClear(&dest
);
3207 hr
= ISAXContentHandler_endDocument(content
);
3208 EXPECT_HR(hr
, S_OK
);
3210 ISAXContentHandler_Release(content
);
3211 IMXWriter_Release(writer
);
3213 /* try empty characters data to see if element is closed */
3214 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3215 &IID_IMXWriter
, (void**)&writer
);
3216 EXPECT_HR(hr
, S_OK
);
3218 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3219 EXPECT_HR(hr
, S_OK
);
3221 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3222 EXPECT_HR(hr
, S_OK
);
3224 hr
= ISAXContentHandler_startDocument(content
);
3225 EXPECT_HR(hr
, S_OK
);
3227 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3228 EXPECT_HR(hr
, S_OK
);
3230 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3231 EXPECT_HR(hr
, S_OK
);
3233 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3234 EXPECT_HR(hr
, S_OK
);
3236 V_VT(&dest
) = VT_EMPTY
;
3237 hr
= IMXWriter_get_output(writer
, &dest
);
3238 EXPECT_HR(hr
, S_OK
);
3239 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3240 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3241 VariantClear(&dest
);
3243 ISAXContentHandler_Release(content
);
3244 IMXWriter_Release(writer
);
3247 while (table
->clsid
)
3249 ISAXContentHandler
*content
;
3254 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3261 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3262 &IID_IMXWriter
, (void**)&writer
);
3263 EXPECT_HR(hr
, S_OK
);
3265 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3266 EXPECT_HR(hr
, S_OK
);
3268 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3269 EXPECT_HR(hr
, S_OK
);
3271 hr
= ISAXContentHandler_startDocument(content
);
3272 EXPECT_HR(hr
, S_OK
);
3274 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
3275 EXPECT_HR(hr
, S_OK
);
3280 V_VT(&dest
) = VT_EMPTY
;
3281 hr
= IMXWriter_get_output(writer
, &dest
);
3282 EXPECT_HR(hr
, S_OK
);
3283 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3284 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3285 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3286 VariantClear(&dest
);
3289 /* with disabled escaping */
3290 V_VT(&dest
) = VT_EMPTY
;
3291 hr
= IMXWriter_put_output(writer
, dest
);
3292 EXPECT_HR(hr
, S_OK
);
3294 hr
= IMXWriter_put_disableOutputEscaping(writer
, VARIANT_TRUE
);
3295 EXPECT_HR(hr
, S_OK
);
3297 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
3298 EXPECT_HR(hr
, S_OK
);
3303 V_VT(&dest
) = VT_EMPTY
;
3304 hr
= IMXWriter_get_output(writer
, &dest
);
3305 EXPECT_HR(hr
, S_OK
);
3306 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3307 ok(!lstrcmpW(_bstr_(table
->data
), V_BSTR(&dest
)),
3308 "test %d: got wrong content %s, expected \"%s\"\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->data
);
3309 VariantClear(&dest
);
3312 ISAXContentHandler_Release(content
);
3313 IMXWriter_Release(writer
);
3322 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
3324 VARIANT_TRUE
,"UTF-16",
3326 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3327 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3332 VARIANT_FALSE
,"UTF-16",
3334 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3339 VARIANT_TRUE
,"UTF-8",
3341 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
3342 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3343 * and the writer is released.
3350 VARIANT_TRUE
,"utf-8",
3352 {FALSE
,(const BYTE
*)utf8xml2
,sizeof(utf8xml2
)-1},
3353 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3354 * and the writer is released.
3361 VARIANT_TRUE
,"UTF-16",
3363 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3364 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3369 VARIANT_TRUE
,"UTF-16",
3371 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
3372 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3378 static void test_mxwriter_stream(void)
3381 ISAXContentHandler
*content
;
3386 ULARGE_INTEGER pos2
;
3387 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
3389 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
3390 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
3392 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3393 &IID_IMXWriter
, (void**)&writer
);
3394 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
3396 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3397 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
3399 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
3400 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
3402 V_VT(&dest
) = VT_UNKNOWN
;
3403 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
3404 hr
= IMXWriter_put_output(writer
, dest
);
3405 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
3406 VariantClear(&dest
);
3408 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
3409 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
3411 current_write_test
= test
->expected_writes
;
3413 hr
= ISAXContentHandler_startDocument(content
);
3414 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
3416 hr
= ISAXContentHandler_endDocument(content
);
3417 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
3419 ISAXContentHandler_Release(content
);
3420 IMXWriter_Release(writer
);
3422 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
3423 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
3426 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3427 &IID_IMXWriter
, (void**)&writer
);
3428 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
3430 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3431 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
3433 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3434 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
3436 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
3437 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
3439 V_VT(&dest
) = VT_UNKNOWN
;
3440 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3441 hr
= IMXWriter_put_output(writer
, dest
);
3442 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
3444 hr
= ISAXContentHandler_startDocument(content
);
3445 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
3447 /* Setting output of the mxwriter causes the current output to be flushed,
3448 * and the writer to start over.
3450 V_VT(&dest
) = VT_EMPTY
;
3451 hr
= IMXWriter_put_output(writer
, dest
);
3452 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
3455 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3456 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
3457 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
3459 hr
= ISAXContentHandler_startDocument(content
);
3460 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
3462 hr
= ISAXContentHandler_endDocument(content
);
3463 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
3465 V_VT(&dest
) = VT_EMPTY
;
3466 hr
= IMXWriter_get_output(writer
, &dest
);
3467 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
3468 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
3469 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3470 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3471 VariantClear(&dest
);
3473 /* test when BOM is written to output stream */
3474 V_VT(&dest
) = VT_EMPTY
;
3475 hr
= IMXWriter_put_output(writer
, dest
);
3476 EXPECT_HR(hr
, S_OK
);
3479 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
3480 EXPECT_HR(hr
, S_OK
);
3482 V_VT(&dest
) = VT_UNKNOWN
;
3483 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3484 hr
= IMXWriter_put_output(writer
, dest
);
3485 EXPECT_HR(hr
, S_OK
);
3487 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_TRUE
);
3488 EXPECT_HR(hr
, S_OK
);
3490 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
3491 EXPECT_HR(hr
, S_OK
);
3493 hr
= ISAXContentHandler_startDocument(content
);
3494 EXPECT_HR(hr
, S_OK
);
3498 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3499 EXPECT_HR(hr
, S_OK
);
3500 ok(pos2
.QuadPart
== 2, "got wrong position\n");
3502 ISAXContentHandler_Release(content
);
3503 IMXWriter_Release(writer
);
3508 static void test_mxwriter_encoding(void)
3510 ISAXContentHandler
*content
;
3519 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3520 &IID_IMXWriter
, (void**)&writer
);
3521 EXPECT_HR(hr
, S_OK
);
3523 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3524 EXPECT_HR(hr
, S_OK
);
3526 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
3527 EXPECT_HR(hr
, S_OK
);
3529 hr
= ISAXContentHandler_startDocument(content
);
3530 EXPECT_HR(hr
, S_OK
);
3532 hr
= ISAXContentHandler_endDocument(content
);
3533 EXPECT_HR(hr
, S_OK
);
3535 /* The content is always re-encoded to UTF-16 when the output is
3536 * retrieved as a BSTR.
3538 V_VT(&dest
) = VT_EMPTY
;
3539 hr
= IMXWriter_get_output(writer
, &dest
);
3540 EXPECT_HR(hr
, S_OK
);
3541 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
3542 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3543 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3544 VariantClear(&dest
);
3546 /* switch encoding when something is written already */
3547 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3548 EXPECT_HR(hr
, S_OK
);
3550 V_VT(&dest
) = VT_UNKNOWN
;
3551 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3552 hr
= IMXWriter_put_output(writer
, dest
);
3553 EXPECT_HR(hr
, S_OK
);
3555 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
3556 EXPECT_HR(hr
, S_OK
);
3558 /* write empty element */
3559 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3560 EXPECT_HR(hr
, S_OK
);
3562 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3563 EXPECT_HR(hr
, S_OK
);
3566 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
3567 EXPECT_HR(hr
, S_OK
);
3569 hr
= IMXWriter_flush(writer
);
3570 EXPECT_HR(hr
, S_OK
);
3572 hr
= GetHGlobalFromStream(stream
, &g
);
3573 EXPECT_HR(hr
, S_OK
);
3575 ptr
= GlobalLock(g
);
3576 ok(!strncmp(ptr
, "<a/>", 4), "got %c%c%c%c\n", ptr
[0],ptr
[1],ptr
[2],ptr
[3]);
3579 /* so output is unaffected, encoding name is stored however */
3580 hr
= IMXWriter_get_encoding(writer
, &s
);
3581 EXPECT_HR(hr
, S_OK
);
3582 ok(!lstrcmpW(s
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(s
));
3585 IStream_Release(stream
);
3587 ISAXContentHandler_Release(content
);
3588 IMXWriter_Release(writer
);
3593 static void test_obj_dispex(IUnknown
*obj
)
3595 static const WCHAR starW
[] = {'*',0};
3596 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
3597 IDispatchEx
*dispex
;
3604 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
3605 EXPECT_HR(hr
, S_OK
);
3606 if (FAILED(hr
)) return;
3609 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
3610 EXPECT_HR(hr
, S_OK
);
3611 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
3613 name
= SysAllocString(starW
);
3614 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
3615 EXPECT_HR(hr
, E_NOTIMPL
);
3616 SysFreeString(name
);
3618 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
3619 EXPECT_HR(hr
, E_NOTIMPL
);
3622 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
3623 EXPECT_HR(hr
, E_NOTIMPL
);
3624 ok(props
== 0, "expected 0 got %d\n", props
);
3626 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
3627 EXPECT_HR(hr
, E_NOTIMPL
);
3628 if (SUCCEEDED(hr
)) SysFreeString(name
);
3630 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
3631 EXPECT_HR(hr
, E_NOTIMPL
);
3633 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
3634 EXPECT_HR(hr
, E_NOTIMPL
);
3635 if (hr
== S_OK
&& unk
) IUnknown_Release(unk
);
3637 IDispatchEx_Release(dispex
);
3640 static void test_dispex(void)
3642 IVBSAXXMLReader
*vbreader
;
3643 ISAXXMLReader
*reader
;
3647 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
3648 &IID_ISAXXMLReader
, (void**)&reader
);
3649 EXPECT_HR(hr
, S_OK
);
3651 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
3652 EXPECT_HR(hr
, S_OK
);
3653 test_obj_dispex(unk
);
3654 IUnknown_Release(unk
);
3656 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
3657 EXPECT_HR(hr
, S_OK
);
3658 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
3659 EXPECT_HR(hr
, S_OK
);
3660 test_obj_dispex(unk
);
3661 IUnknown_Release(unk
);
3662 IVBSAXXMLReader_Release(vbreader
);
3664 ISAXXMLReader_Release(reader
);
3667 static void test_mxwriter_dispex(void)
3669 IDispatchEx
*dispex
;
3674 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3675 &IID_IMXWriter
, (void**)&writer
);
3676 EXPECT_HR(hr
, S_OK
);
3678 hr
= IMXWriter_QueryInterface(writer
, &IID_IDispatchEx
, (void**)&dispex
);
3679 EXPECT_HR(hr
, S_OK
);
3680 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
3681 test_obj_dispex(unk
);
3682 IUnknown_Release(unk
);
3683 IDispatchEx_Release(dispex
);
3685 IMXWriter_Release(writer
);
3688 static void test_mxwriter_comment(void)
3690 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
3691 ISAXContentHandler
*content
;
3692 ISAXLexicalHandler
*lexical
;
3697 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3698 &IID_IMXWriter
, (void**)&writer
);
3699 EXPECT_HR(hr
, S_OK
);
3701 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3702 EXPECT_HR(hr
, S_OK
);
3704 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
3705 EXPECT_HR(hr
, S_OK
);
3707 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3708 EXPECT_HR(hr
, S_OK
);
3710 hr
= ISAXContentHandler_startDocument(content
);
3711 EXPECT_HR(hr
, S_OK
);
3713 hr
= ISAXLexicalHandler_comment(lexical
, NULL
, 0);
3714 EXPECT_HR(hr
, E_INVALIDARG
);
3716 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, 0);
3717 EXPECT_HR(hr
, S_OK
);
3719 V_VT(&dest
) = VT_EMPTY
;
3720 hr
= IMXWriter_get_output(writer
, &dest
);
3721 EXPECT_HR(hr
, S_OK
);
3722 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3723 ok(!lstrcmpW(_bstr_("<!---->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3724 VariantClear(&dest
);
3726 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, sizeof(commentW
)/sizeof(WCHAR
)-1);
3727 EXPECT_HR(hr
, S_OK
);
3729 V_VT(&dest
) = VT_EMPTY
;
3730 hr
= IMXWriter_get_output(writer
, &dest
);
3731 EXPECT_HR(hr
, S_OK
);
3732 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3733 ok(!lstrcmpW(_bstr_("<!---->\r\n<!--comment-->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3734 VariantClear(&dest
);
3736 ISAXContentHandler_Release(content
);
3737 ISAXLexicalHandler_Release(lexical
);
3738 IMXWriter_Release(writer
);
3742 static void test_mxwriter_cdata(void)
3744 ISAXContentHandler
*content
;
3745 ISAXLexicalHandler
*lexical
;
3750 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3751 &IID_IMXWriter
, (void**)&writer
);
3752 EXPECT_HR(hr
, S_OK
);
3754 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3755 EXPECT_HR(hr
, S_OK
);
3757 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
3758 EXPECT_HR(hr
, S_OK
);
3760 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3761 EXPECT_HR(hr
, S_OK
);
3763 hr
= ISAXContentHandler_startDocument(content
);
3764 EXPECT_HR(hr
, S_OK
);
3766 hr
= ISAXLexicalHandler_startCDATA(lexical
);
3767 EXPECT_HR(hr
, S_OK
);
3769 V_VT(&dest
) = VT_EMPTY
;
3770 hr
= IMXWriter_get_output(writer
, &dest
);
3771 EXPECT_HR(hr
, S_OK
);
3772 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3773 ok(!lstrcmpW(_bstr_("<![CDATA["), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3774 VariantClear(&dest
);
3776 hr
= ISAXLexicalHandler_startCDATA(lexical
);
3777 EXPECT_HR(hr
, S_OK
);
3779 /* all these are escaped for text nodes */
3780 hr
= ISAXContentHandler_characters(content
, _bstr_("< > & \""), 7);
3781 EXPECT_HR(hr
, S_OK
);
3783 hr
= ISAXLexicalHandler_endCDATA(lexical
);
3784 EXPECT_HR(hr
, S_OK
);
3786 V_VT(&dest
) = VT_EMPTY
;
3787 hr
= IMXWriter_get_output(writer
, &dest
);
3788 EXPECT_HR(hr
, S_OK
);
3789 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3790 ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3791 VariantClear(&dest
);
3793 ISAXContentHandler_Release(content
);
3794 ISAXLexicalHandler_Release(lexical
);
3795 IMXWriter_Release(writer
);
3799 static void test_mxwriter_pi(void)
3801 static const WCHAR targetW
[] = {'t','a','r','g','e','t',0};
3802 static const WCHAR dataW
[] = {'d','a','t','a',0};
3803 ISAXContentHandler
*content
;
3808 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3809 &IID_IMXWriter
, (void**)&writer
);
3810 EXPECT_HR(hr
, S_OK
);
3812 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3813 EXPECT_HR(hr
, S_OK
);
3815 hr
= ISAXContentHandler_processingInstruction(content
, NULL
, 0, NULL
, 0);
3816 EXPECT_HR(hr
, E_INVALIDARG
);
3818 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 0, NULL
, 0);
3819 EXPECT_HR(hr
, S_OK
);
3821 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, NULL
, 0);
3822 EXPECT_HR(hr
, S_OK
);
3824 V_VT(&dest
) = VT_EMPTY
;
3825 hr
= IMXWriter_get_output(writer
, &dest
);
3826 EXPECT_HR(hr
, S_OK
);
3827 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3828 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3829 VariantClear(&dest
);
3831 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 4, dataW
, 4);
3832 EXPECT_HR(hr
, S_OK
);
3834 V_VT(&dest
) = VT_EMPTY
;
3835 hr
= IMXWriter_get_output(writer
, &dest
);
3836 EXPECT_HR(hr
, S_OK
);
3837 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3838 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
)));
3839 VariantClear(&dest
);
3841 V_VT(&dest
) = VT_EMPTY
;
3842 hr
= IMXWriter_put_output(writer
, dest
);
3843 EXPECT_HR(hr
, S_OK
);
3845 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, dataW
, 0);
3846 EXPECT_HR(hr
, S_OK
);
3848 V_VT(&dest
) = VT_EMPTY
;
3849 hr
= IMXWriter_get_output(writer
, &dest
);
3850 EXPECT_HR(hr
, S_OK
);
3851 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3852 ok(!lstrcmpW(_bstr_("<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3853 VariantClear(&dest
);
3856 ISAXContentHandler_Release(content
);
3857 IMXWriter_Release(writer
);
3860 static void test_mxwriter_ignorablespaces(void)
3862 static const WCHAR dataW
[] = {'d','a','t','a',0};
3863 ISAXContentHandler
*content
;
3868 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3869 &IID_IMXWriter
, (void**)&writer
);
3870 EXPECT_HR(hr
, S_OK
);
3872 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3873 EXPECT_HR(hr
, S_OK
);
3875 hr
= ISAXContentHandler_ignorableWhitespace(content
, NULL
, 0);
3876 EXPECT_HR(hr
, E_INVALIDARG
);
3878 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 0);
3879 EXPECT_HR(hr
, S_OK
);
3881 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 4);
3882 EXPECT_HR(hr
, S_OK
);
3884 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 1);
3885 EXPECT_HR(hr
, S_OK
);
3887 V_VT(&dest
) = VT_EMPTY
;
3888 hr
= IMXWriter_get_output(writer
, &dest
);
3889 EXPECT_HR(hr
, S_OK
);
3890 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3891 ok(!lstrcmpW(_bstr_("datad"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3892 VariantClear(&dest
);
3894 ISAXContentHandler_Release(content
);
3895 IMXWriter_Release(writer
);
3898 static void test_mxwriter_dtd(void)
3900 static const WCHAR contentW
[] = {'c','o','n','t','e','n','t'};
3901 static const WCHAR nameW
[] = {'n','a','m','e'};
3902 static const WCHAR pubW
[] = {'p','u','b'};
3903 static const WCHAR sysW
[] = {'s','y','s'};
3904 ISAXContentHandler
*content
;
3905 ISAXLexicalHandler
*lexical
;
3906 ISAXDeclHandler
*decl
;
3911 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3912 &IID_IMXWriter
, (void**)&writer
);
3913 EXPECT_HR(hr
, S_OK
);
3915 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3916 EXPECT_HR(hr
, S_OK
);
3918 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
3919 EXPECT_HR(hr
, S_OK
);
3921 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
3922 EXPECT_HR(hr
, S_OK
);
3924 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3925 EXPECT_HR(hr
, S_OK
);
3927 hr
= ISAXContentHandler_startDocument(content
);
3928 EXPECT_HR(hr
, S_OK
);
3930 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, NULL
, 0);
3931 EXPECT_HR(hr
, E_INVALIDARG
);
3933 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
3934 EXPECT_HR(hr
, E_INVALIDARG
);
3936 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, sysW
, sizeof(sysW
)/sizeof(WCHAR
));
3937 EXPECT_HR(hr
, E_INVALIDARG
);
3939 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
3940 EXPECT_HR(hr
, E_INVALIDARG
);
3942 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0, NULL
, 0);
3943 EXPECT_HR(hr
, S_OK
);
3945 V_VT(&dest
) = VT_EMPTY
;
3946 hr
= IMXWriter_get_output(writer
, &dest
);
3947 EXPECT_HR(hr
, S_OK
);
3948 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3949 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3950 VariantClear(&dest
);
3952 /* system id is required if public is present */
3953 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
3954 EXPECT_HR(hr
, E_INVALIDARG
);
3956 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
),
3957 pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
3958 EXPECT_HR(hr
, S_OK
);
3960 V_VT(&dest
) = VT_EMPTY
;
3961 hr
= IMXWriter_get_output(writer
, &dest
);
3962 EXPECT_HR(hr
, S_OK
);
3963 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3964 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
3965 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3966 VariantClear(&dest
);
3968 hr
= ISAXLexicalHandler_endDTD(lexical
);
3969 EXPECT_HR(hr
, S_OK
);
3971 hr
= ISAXLexicalHandler_endDTD(lexical
);
3972 EXPECT_HR(hr
, S_OK
);
3974 V_VT(&dest
) = VT_EMPTY
;
3975 hr
= IMXWriter_get_output(writer
, &dest
);
3976 EXPECT_HR(hr
, S_OK
);
3977 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3978 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
3979 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n"),
3980 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3981 VariantClear(&dest
);
3983 /* element declaration */
3984 V_VT(&dest
) = VT_EMPTY
;
3985 hr
= IMXWriter_put_output(writer
, dest
);
3986 EXPECT_HR(hr
, S_OK
);
3988 hr
= ISAXDeclHandler_elementDecl(decl
, NULL
, 0, NULL
, 0);
3989 EXPECT_HR(hr
, E_INVALIDARG
);
3991 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0);
3992 EXPECT_HR(hr
, E_INVALIDARG
);
3994 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, sizeof(contentW
)/sizeof(WCHAR
));
3995 EXPECT_HR(hr
, S_OK
);
3997 V_VT(&dest
) = VT_EMPTY
;
3998 hr
= IMXWriter_get_output(writer
, &dest
);
3999 EXPECT_HR(hr
, S_OK
);
4000 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4001 ok(!lstrcmpW(_bstr_("<!ELEMENT name content>\r\n"),
4002 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4003 VariantClear(&dest
);
4005 V_VT(&dest
) = VT_EMPTY
;
4006 hr
= IMXWriter_put_output(writer
, dest
);
4007 EXPECT_HR(hr
, S_OK
);
4009 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, 0);
4010 EXPECT_HR(hr
, S_OK
);
4012 V_VT(&dest
) = VT_EMPTY
;
4013 hr
= IMXWriter_get_output(writer
, &dest
);
4014 EXPECT_HR(hr
, S_OK
);
4015 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
4016 ok(!lstrcmpW(_bstr_("<!ELEMENT name >\r\n"),
4017 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
4018 VariantClear(&dest
);
4020 ISAXContentHandler_Release(content
);
4021 ISAXLexicalHandler_Release(lexical
);
4022 ISAXDeclHandler_Release(decl
);
4023 IMXWriter_Release(writer
);
4035 } addattribute_test_t
;
4037 static const addattribute_test_t addattribute_data
[] = {
4038 { &CLSID_SAXAttributes
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4039 { &CLSID_SAXAttributes30
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4040 { &CLSID_SAXAttributes40
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
4041 { &CLSID_SAXAttributes60
, NULL
, NULL
, "ns:qname", NULL
, "value", S_OK
},
4043 { &CLSID_SAXAttributes
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4044 { &CLSID_SAXAttributes30
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4045 { &CLSID_SAXAttributes40
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4046 { &CLSID_SAXAttributes60
, NULL
, "qname", "ns:qname", NULL
, "value", S_OK
},
4048 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4049 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4050 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
4051 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", NULL
, "value", S_OK
},
4053 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4054 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4055 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4056 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
4061 static void test_mxattr_addAttribute(void)
4063 const addattribute_test_t
*table
= addattribute_data
;
4066 while (table
->clsid
)
4068 ISAXAttributes
*saxattr
;
4069 IMXAttributes
*mxattr
;
4074 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
4081 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4082 &IID_IMXAttributes
, (void**)&mxattr
);
4083 EXPECT_HR(hr
, S_OK
);
4085 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4086 EXPECT_HR(hr
, S_OK
);
4088 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
4089 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4090 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4092 hr
= ISAXAttributes_getLength(saxattr
, NULL
);
4093 EXPECT_HR(hr
, E_POINTER
);
4097 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4098 EXPECT_HR(hr
, S_OK
);
4099 ok(len
== 0, "got %d\n", len
);
4101 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
4102 EXPECT_HR(hr
, E_INVALIDARG
);
4104 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
4105 EXPECT_HR(hr
, E_INVALIDARG
);
4107 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
4108 EXPECT_HR(hr
, E_INVALIDARG
);
4110 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
4111 EXPECT_HR(hr
, E_INVALIDARG
);
4113 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
4114 EXPECT_HR(hr
, E_INVALIDARG
);
4116 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
4117 EXPECT_HR(hr
, E_INVALIDARG
);
4119 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
4120 EXPECT_HR(hr
, E_INVALIDARG
);
4122 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
4123 EXPECT_HR(hr
, E_INVALIDARG
);
4125 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_(table
->uri
), _bstr_(table
->local
),
4126 _bstr_(table
->qname
), _bstr_(table
->type
), _bstr_(table
->value
));
4127 ok(hr
== table
->hr
, "%d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
4131 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
4132 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4133 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4135 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
4136 EXPECT_HR(hr
, E_POINTER
);
4138 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
4139 EXPECT_HR(hr
, E_POINTER
);
4141 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
4142 EXPECT_HR(hr
, E_POINTER
);
4144 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
4145 EXPECT_HR(hr
, E_POINTER
);
4147 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
4148 EXPECT_HR(hr
, E_POINTER
);
4150 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
4151 EXPECT_HR(hr
, E_POINTER
);
4155 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
4156 EXPECT_HR(hr
, S_OK
);
4157 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4159 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
4162 value
= (void*)0xdeadbeef;
4163 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
4164 EXPECT_HR(hr
, S_OK
);
4168 ok(!lstrcmpW(_bstr_(table
->type
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4170 ok(lstrlenW(value
) == len
, "%d: got wrong type value length %d\n", i
, len
);
4174 ok(*value
== 0, "%d: got type value %s\n", i
, wine_dbgstr_w(value
));
4175 ok(len
== 0, "%d: got wrong type value length %d\n", i
, len
);
4178 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, NULL
);
4179 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4180 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4182 EXPECT_HR(hr
, E_POINTER
);
4185 EXPECT_HR(hr
, E_INVALIDARG
);
4187 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, &index
);
4188 EXPECT_HR(hr
, E_INVALIDARG
);
4191 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_("nonexistent"), 11, &index
);
4192 EXPECT_HR(hr
, E_INVALIDARG
);
4193 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4196 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), 0, &index
);
4197 EXPECT_HR(hr
, E_INVALIDARG
);
4198 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4201 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &index
);
4202 EXPECT_HR(hr
, S_OK
);
4203 ok(index
== 0, "%d: got wrong index %d\n", i
, index
);
4206 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
)-1, &index
);
4207 EXPECT_HR(hr
, E_INVALIDARG
);
4208 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4210 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes40
) ||
4211 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes60
))
4213 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4214 EXPECT_HR(hr
, E_INVALIDARG
);
4216 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4217 EXPECT_HR(hr
, E_INVALIDARG
);
4219 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4220 EXPECT_HR(hr
, E_INVALIDARG
);
4222 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
4223 EXPECT_HR(hr
, E_INVALIDARG
);
4225 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
4226 EXPECT_HR(hr
, E_INVALIDARG
);
4228 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
4229 EXPECT_HR(hr
, E_INVALIDARG
);
4233 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4234 EXPECT_HR(hr
, E_POINTER
);
4236 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4237 EXPECT_HR(hr
, E_POINTER
);
4239 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4240 EXPECT_HR(hr
, E_POINTER
);
4242 /* versions 4 and 6 crash */
4243 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, NULL
);
4244 EXPECT_HR(hr
, E_POINTER
);
4246 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, &len
);
4247 EXPECT_HR(hr
, E_POINTER
);
4249 hr
= ISAXAttributes_getValueFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
, NULL
);
4250 EXPECT_HR(hr
, E_POINTER
);
4252 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, NULL
, NULL
);
4253 EXPECT_HR(hr
, E_POINTER
);
4255 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, NULL
, 0, &value
, NULL
);
4256 EXPECT_HR(hr
, E_POINTER
);
4258 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, &value
, NULL
);
4259 EXPECT_HR(hr
, E_POINTER
);
4261 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), 0, _bstr_(table
->local
), 0, NULL
, &len
);
4262 EXPECT_HR(hr
, E_POINTER
);
4264 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
), _bstr_(table
->local
),
4265 strlen(table
->local
), NULL
, NULL
);
4266 EXPECT_HR(hr
, E_POINTER
);
4269 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &value
, &len
);
4270 EXPECT_HR(hr
, S_OK
);
4271 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4273 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
4276 hr
= ISAXAttributes_getValueFromName(saxattr
, _bstr_(table
->uri
), strlen(table
->uri
),
4277 _bstr_(table
->local
), strlen(table
->local
), &value
, &len
);
4278 EXPECT_HR(hr
, S_OK
);
4279 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
4281 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
4286 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4287 EXPECT_HR(hr
, S_OK
);
4288 if (table
->hr
== S_OK
)
4289 ok(len
== 1, "%d: got %d length, expected 0\n", i
, len
);
4291 ok(len
== 0, "%d: got %d length, expected 1\n", i
, len
);
4293 ISAXAttributes_Release(saxattr
);
4294 IMXAttributes_Release(mxattr
);
4303 static void test_mxattr_clear(void)
4305 ISAXAttributes
*saxattr
;
4306 IMXAttributes
*mxattr
;
4311 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
4312 &IID_IMXAttributes
, (void**)&mxattr
);
4313 EXPECT_HR(hr
, S_OK
);
4315 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4316 EXPECT_HR(hr
, S_OK
);
4318 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, NULL
);
4319 EXPECT_HR(hr
, E_INVALIDARG
);
4321 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
4322 EXPECT_HR(hr
, E_INVALIDARG
);
4324 hr
= IMXAttributes_clear(mxattr
);
4325 EXPECT_HR(hr
, S_OK
);
4327 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("local"),
4328 _bstr_("qname"), _bstr_("type"), _bstr_("value"));
4329 EXPECT_HR(hr
, S_OK
);
4332 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4333 EXPECT_HR(hr
, S_OK
);
4334 ok(len
== 1, "got %d\n", len
);
4337 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, &len
);
4338 EXPECT_HR(hr
, E_POINTER
);
4339 ok(len
== -1, "got %d\n", len
);
4341 ptr
= (void*)0xdeadbeef;
4342 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, NULL
);
4343 EXPECT_HR(hr
, E_POINTER
);
4344 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
4347 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
4348 EXPECT_HR(hr
, S_OK
);
4349 ok(len
== 5, "got %d\n", len
);
4350 ok(!lstrcmpW(ptr
, _bstr_("qname")), "got %s\n", wine_dbgstr_w(ptr
));
4352 hr
= IMXAttributes_clear(mxattr
);
4353 EXPECT_HR(hr
, S_OK
);
4356 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4357 EXPECT_HR(hr
, S_OK
);
4358 ok(len
== 0, "got %d\n", len
);
4361 ptr
= (void*)0xdeadbeef;
4362 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
4363 EXPECT_HR(hr
, E_INVALIDARG
);
4364 ok(len
== -1, "got %d\n", len
);
4365 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
4367 IMXAttributes_Release(mxattr
);
4368 ISAXAttributes_Release(saxattr
);
4372 static void test_mxattr_dispex(void)
4374 IMXAttributes
*mxattr
;
4375 IDispatchEx
*dispex
;
4379 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
4380 &IID_IMXAttributes
, (void**)&mxattr
);
4381 EXPECT_HR(hr
, S_OK
);
4383 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IDispatchEx
, (void**)&dispex
);
4384 EXPECT_HR(hr
, S_OK
);
4385 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4386 test_obj_dispex(unk
);
4387 IUnknown_Release(unk
);
4388 IDispatchEx_Release(dispex
);
4390 IMXAttributes_Release(mxattr
);
4393 static void test_mxattr_qi(void)
4395 IVBSAXAttributes
*vbsaxattr
, *vbsaxattr2
;
4396 ISAXAttributes
*saxattr
;
4397 IMXAttributes
*mxattr
;
4400 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
4401 &IID_IMXAttributes
, (void**)&mxattr
);
4402 EXPECT_HR(hr
, S_OK
);
4404 EXPECT_REF(mxattr
, 1);
4405 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4406 EXPECT_HR(hr
, S_OK
);
4408 EXPECT_REF(mxattr
, 2);
4409 EXPECT_REF(saxattr
, 2);
4411 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr
);
4412 EXPECT_HR(hr
, S_OK
);
4414 EXPECT_REF(vbsaxattr
, 3);
4415 EXPECT_REF(mxattr
, 3);
4416 EXPECT_REF(saxattr
, 3);
4418 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr2
);
4419 EXPECT_HR(hr
, S_OK
);
4421 EXPECT_REF(vbsaxattr
, 4);
4422 EXPECT_REF(mxattr
, 4);
4423 EXPECT_REF(saxattr
, 4);
4425 IMXAttributes_Release(mxattr
);
4426 ISAXAttributes_Release(saxattr
);
4427 IVBSAXAttributes_Release(vbsaxattr
);
4428 IVBSAXAttributes_Release(vbsaxattr2
);
4431 static struct msxmlsupported_data_t saxattr_support_data
[] =
4433 { &CLSID_SAXAttributes
, "SAXAttributes" },
4434 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
4435 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
4436 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
4440 static void test_mxattr_localname(void)
4442 static const WCHAR localname1W
[] = {'l','o','c','a','l','n','a','m','e','1',0};
4443 static const WCHAR localnameW
[] = {'l','o','c','a','l','n','a','m','e',0};
4444 static const WCHAR uri1W
[] = {'u','r','i','1',0};
4445 static const WCHAR uriW
[] = {'u','r','i',0};
4447 const struct msxmlsupported_data_t
*table
= saxattr_support_data
;
4449 while (table
->clsid
)
4451 ISAXAttributes
*saxattr
;
4452 IMXAttributes
*mxattr
;
4456 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
4462 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4463 &IID_IMXAttributes
, (void**)&mxattr
);
4464 EXPECT_HR(hr
, S_OK
);
4466 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4467 EXPECT_HR(hr
, S_OK
);
4469 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, &index
);
4470 EXPECT_HR(hr
, E_INVALIDARG
);
4472 /* add some ambiguos attribute names */
4473 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
4474 _bstr_("a:localname"), _bstr_(""), _bstr_("value"));
4475 EXPECT_HR(hr
, S_OK
);
4476 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
4477 _bstr_("b:localname"), _bstr_(""), _bstr_("value"));
4478 EXPECT_HR(hr
, S_OK
);
4481 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localnameW
, lstrlenW(localnameW
), &index
);
4482 EXPECT_HR(hr
, S_OK
);
4483 ok(index
== 0, "%s: got index %d\n", table
->name
, index
);
4486 hr
= ISAXAttributes_getIndexFromName(saxattr
, uri1W
, lstrlenW(uri1W
), localnameW
, lstrlenW(localnameW
), &index
);
4487 EXPECT_HR(hr
, E_INVALIDARG
);
4488 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
4491 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), &index
);
4492 EXPECT_HR(hr
, E_INVALIDARG
);
4493 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
4495 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4496 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4498 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
4499 EXPECT_HR(hr
, E_POINTER
);
4501 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
4502 EXPECT_HR(hr
, E_POINTER
);
4506 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
4507 EXPECT_HR(hr
, E_INVALIDARG
);
4509 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
4510 EXPECT_HR(hr
, E_INVALIDARG
);
4513 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), NULL
, 0, &index
);
4514 EXPECT_HR(hr
, E_INVALIDARG
);
4516 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, localname1W
, lstrlenW(localname1W
), &index
);
4517 EXPECT_HR(hr
, E_INVALIDARG
);
4521 ISAXAttributes_Release(saxattr
);
4522 IMXAttributes_Release(mxattr
);
4526 START_TEST(saxreader
)
4528 ISAXXMLReader
*reader
;
4531 hr
= CoInitialize(NULL
);
4532 ok(hr
== S_OK
, "failed to init com\n");
4534 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
4535 &IID_ISAXXMLReader
, (void**)&reader
);
4539 skip("Failed to create SAXXMLReader instance\n");
4543 ISAXXMLReader_Release(reader
);
4545 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
4547 get_class_support_data(reader_support_data
, &IID_ISAXXMLReader
);
4550 test_saxreader_properties();
4551 test_saxreader_features();
4552 test_saxreader_encoding();
4555 /* MXXMLWriter tests */
4556 get_class_support_data(mxwriter_support_data
, &IID_IMXWriter
);
4557 if (is_clsid_supported(&CLSID_MXXMLWriter
, mxwriter_support_data
))
4559 test_mxwriter_handlers();
4560 test_mxwriter_startenddocument();
4561 test_mxwriter_startendelement();
4562 test_mxwriter_characters();
4563 test_mxwriter_comment();
4564 test_mxwriter_cdata();
4566 test_mxwriter_ignorablespaces();
4567 test_mxwriter_dtd();
4568 test_mxwriter_properties();
4569 test_mxwriter_flush();
4570 test_mxwriter_stream();
4571 test_mxwriter_encoding();
4572 test_mxwriter_dispex();
4575 win_skip("MXXMLWriter not supported\n");
4577 /* SAXAttributes tests */
4578 get_class_support_data(mxattributes_support_data
, &IID_IMXAttributes
);
4579 if (is_clsid_supported(&CLSID_SAXAttributes
, mxattributes_support_data
))
4582 test_mxattr_addAttribute();
4583 test_mxattr_clear();
4584 test_mxattr_localname();
4585 test_mxattr_dispex();
4588 skip("SAXAttributes not supported\n");