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 szTestAttributes
[] =
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 static struct attribute_entry ch_attributes_alt_6
[] = {
737 { "prefix_test", "arg1", "test:arg1", "arg1" },
738 { "", "arg2", "arg2", "arg2" },
739 { "prefix_test", "ar3", "test:ar3", "arg3" },
740 { "http://www.w3.org/2000/xmlns/", "", "xmlns:test", "prefix_test" },
741 { "http://www.w3.org/2000/xmlns/", "", "xmlns", "prefix" },
745 static struct attribute_entry ch_attributes2_6
[] = {
746 { "http://www.w3.org/2000/xmlns/", "", "xmlns:p", "test" },
750 static struct call_entry content_handler_test_attributes_alternate_6
[] = {
751 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
752 { CH_STARTDOCUMENT
, 1, 22, S_OK
},
753 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "test", "prefix_test" },
754 { CH_STARTPREFIXMAPPING
, 2, 95, S_OK
, "", "prefix" },
755 { CH_STARTELEMENT
, 2, 95, S_OK
, "prefix", "document", "document", ch_attributes_alt_6
},
756 { CH_CHARACTERS
, 3, 1, S_OK
, "\n" },
757 { CH_STARTPREFIXMAPPING
, 3, 24, S_OK
, "p", "test" },
758 { CH_STARTELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1", ch_attributes2_6
},
759 { CH_ENDELEMENT
, 3, 24, S_OK
, "prefix", "node1", "node1" },
760 { CH_ENDPREFIXMAPPING
, 3, 24, S_OK
, "p" },
761 { CH_ENDELEMENT
, 3, 35, S_OK
, "prefix", "document", "document" },
762 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "test" },
763 { CH_ENDPREFIXMAPPING
, 3, 35, S_OK
, "" },
764 { CH_ENDDOCUMENT
, 4, 0, S_OK
},
768 static struct attribute_entry xmlspace_attrs
[] = {
769 { "http://www.w3.org/XML/1998/namespace", "space", "xml:space", "preserve" },
773 static struct call_entry xmlspaceattr_test
[] = {
774 { CH_PUTDOCUMENTLOCATOR
, 0, 0, S_OK
},
775 { CH_STARTDOCUMENT
, 0, 0, S_OK
},
776 { CH_STARTELEMENT
, 1, 64, S_OK
, "", "a", "a", xmlspace_attrs
},
777 { CH_CHARACTERS
, 1, 64, S_OK
, " Some text data " },
778 { CH_ENDELEMENT
, 1, 82, S_OK
, "", "a", "a" },
779 { CH_ENDDOCUMENT
, 0, 0, S_OK
},
783 static struct call_entry xmlspaceattr_test_alternate
[] = {
784 { CH_PUTDOCUMENTLOCATOR
, 1, 0, S_OK
},
785 { CH_STARTDOCUMENT
, 1, 39, S_OK
},
786 { CH_STARTELEMENT
, 1, 63, S_OK
, "", "a", "a", xmlspace_attrs
},
787 { CH_CHARACTERS
, 1, 80, S_OK
, " Some text data " },
788 { CH_ENDELEMENT
, 1, 83, S_OK
, "", "a", "a" },
789 { CH_ENDDOCUMENT
, 1, 83, S_OK
},
793 static const char xmlspace_attr
[] =
794 "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
795 "<a xml:space=\"preserve\"> Some text data </a>";
797 static struct call_entry
*expectCall
;
798 static ISAXLocator
*locator
;
801 static void set_expected_seq(struct call_entry
*expected
)
803 expectCall
= expected
;
806 /* to be called once on each tested callback return */
807 static HRESULT
get_expected_ret(void)
809 HRESULT hr
= expectCall
->ret
;
810 if (expectCall
->id
!= CH_ENDTEST
) expectCall
++;
814 static HRESULT WINAPI
contentHandler_QueryInterface(
815 ISAXContentHandler
* iface
,
821 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXContentHandler
))
827 return E_NOINTERFACE
;
833 static ULONG WINAPI
contentHandler_AddRef(
834 ISAXContentHandler
* iface
)
839 static ULONG WINAPI
contentHandler_Release(
840 ISAXContentHandler
* iface
)
845 static HRESULT WINAPI
contentHandler_putDocumentLocator(
846 ISAXContentHandler
* iface
,
847 ISAXLocator
*pLocator
)
849 struct call_entry call
;
854 memset(&call
, 0, sizeof(call
));
855 init_call_entry(locator
, &call
);
856 call
.id
= CH_PUTDOCUMENTLOCATOR
;
857 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
859 if (msxml_version
>= 6) {
860 ISAXAttributes
*attr
, *attr1
;
861 IMXAttributes
*mxattr
;
863 EXPECT_REF(pLocator
, 1);
864 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr
);
866 EXPECT_REF(pLocator
, 2);
867 hr
= ISAXLocator_QueryInterface(pLocator
, &IID_ISAXAttributes
, (void**)&attr1
);
869 EXPECT_REF(pLocator
, 3);
870 ok(attr
== attr1
, "got %p, %p\n", attr
, attr1
);
872 hr
= ISAXAttributes_QueryInterface(attr
, &IID_IMXAttributes
, (void**)&mxattr
);
873 EXPECT_HR(hr
, E_NOINTERFACE
);
875 ISAXAttributes_Release(attr
);
876 ISAXAttributes_Release(attr1
);
879 return get_expected_ret();
882 static ISAXAttributes
*test_attr_ptr
;
883 static HRESULT WINAPI
contentHandler_startDocument(
884 ISAXContentHandler
* iface
)
886 struct call_entry call
;
888 init_call_entry(locator
, &call
);
889 call
.id
= CH_STARTDOCUMENT
;
890 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
892 test_attr_ptr
= NULL
;
894 return get_expected_ret();
897 static HRESULT WINAPI
contentHandler_endDocument(
898 ISAXContentHandler
* iface
)
900 struct call_entry call
;
902 init_call_entry(locator
, &call
);
903 call
.id
= CH_ENDDOCUMENT
;
904 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
906 return get_expected_ret();
909 static HRESULT WINAPI
contentHandler_startPrefixMapping(
910 ISAXContentHandler
* iface
,
911 const WCHAR
*prefix
, int prefix_len
,
912 const WCHAR
*uri
, int uri_len
)
914 struct call_entry call
;
916 init_call_entry(locator
, &call
);
917 call
.id
= CH_STARTPREFIXMAPPING
;
918 call
.arg1W
= SysAllocStringLen(prefix
, prefix_len
);
919 call
.arg2W
= SysAllocStringLen(uri
, uri_len
);
920 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
922 return get_expected_ret();
925 static HRESULT WINAPI
contentHandler_endPrefixMapping(
926 ISAXContentHandler
* iface
,
927 const WCHAR
*prefix
, int len
)
929 struct call_entry call
;
931 init_call_entry(locator
, &call
);
932 call
.id
= CH_ENDPREFIXMAPPING
;
933 call
.arg1W
= SysAllocStringLen(prefix
, len
);
934 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
936 return get_expected_ret();
939 static HRESULT WINAPI
contentHandler_startElement(
940 ISAXContentHandler
* iface
,
941 const WCHAR
*uri
, int uri_len
,
942 const WCHAR
*localname
, int local_len
,
943 const WCHAR
*qname
, int qname_len
,
944 ISAXAttributes
*saxattr
)
946 struct call_entry call
;
947 IMXAttributes
*mxattr
;
951 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IMXAttributes
, (void**)&mxattr
);
952 EXPECT_HR(hr
, E_NOINTERFACE
);
954 init_call_entry(locator
, &call
);
955 call
.id
= CH_STARTELEMENT
;
956 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
957 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
958 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
961 test_attr_ptr
= saxattr
;
962 ok(test_attr_ptr
== saxattr
, "Multiple ISAXAttributes instances are used (%p %p)\n", test_attr_ptr
, saxattr
);
964 /* store actual attributes */
966 hr
= ISAXAttributes_getLength(saxattr
, &len
);
973 struct attribute_entry
*attr
;
974 attr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
*sizeof(struct attribute_entry
));
976 for (i
= 0; i
< len
; i
++)
981 hr
= ISAXAttributes_getName(saxattr
, i
, &uri
, &uri_len
,
982 &localname
, &local_len
, &qname
, &qname_len
);
985 hr
= ISAXAttributes_getValue(saxattr
, i
, &value
, &value_len
);
988 attr
[i
].uriW
= SysAllocStringLen(uri
, uri_len
);
989 attr
[i
].localW
= SysAllocStringLen(localname
, local_len
);
990 attr
[i
].qnameW
= SysAllocStringLen(qname
, qname_len
);
991 attr
[i
].valueW
= SysAllocStringLen(value
, value_len
);
994 call
.attributes
= attr
;
995 call
.attr_count
= len
;
998 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1000 return get_expected_ret();
1003 static HRESULT WINAPI
contentHandler_endElement(
1004 ISAXContentHandler
* iface
,
1005 const WCHAR
*uri
, int uri_len
,
1006 const WCHAR
*localname
, int local_len
,
1007 const WCHAR
*qname
, int qname_len
)
1009 struct call_entry call
;
1011 init_call_entry(locator
, &call
);
1012 call
.id
= CH_ENDELEMENT
;
1013 call
.arg1W
= SysAllocStringLen(uri
, uri_len
);
1014 call
.arg2W
= SysAllocStringLen(localname
, local_len
);
1015 call
.arg3W
= SysAllocStringLen(qname
, qname_len
);
1016 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1018 return get_expected_ret();
1021 static HRESULT WINAPI
contentHandler_characters(
1022 ISAXContentHandler
* iface
,
1026 struct call_entry call
;
1028 init_call_entry(locator
, &call
);
1029 call
.id
= CH_CHARACTERS
;
1030 call
.arg1W
= SysAllocStringLen(chars
, len
);
1031 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1033 return get_expected_ret();
1036 static HRESULT WINAPI
contentHandler_ignorableWhitespace(
1037 ISAXContentHandler
* iface
,
1038 const WCHAR
*chars
, int len
)
1040 struct call_entry call
;
1042 init_call_entry(locator
, &call
);
1043 call
.id
= CH_IGNORABLEWHITESPACE
;
1044 call
.arg1W
= SysAllocStringLen(chars
, len
);
1045 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1047 return get_expected_ret();
1050 static HRESULT WINAPI
contentHandler_processingInstruction(
1051 ISAXContentHandler
* iface
,
1052 const WCHAR
*target
, int target_len
,
1053 const WCHAR
*data
, int data_len
)
1055 struct call_entry call
;
1057 init_call_entry(locator
, &call
);
1058 call
.id
= CH_PROCESSINGINSTRUCTION
;
1059 call
.arg1W
= SysAllocStringLen(target
, target_len
);
1060 call
.arg2W
= SysAllocStringLen(data
, data_len
);
1061 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1063 return get_expected_ret();
1066 static HRESULT WINAPI
contentHandler_skippedEntity(
1067 ISAXContentHandler
* iface
,
1068 const WCHAR
*name
, int len
)
1070 struct call_entry call
;
1072 init_call_entry(locator
, &call
);
1073 call
.id
= CH_SKIPPEDENTITY
;
1074 call
.arg1W
= SysAllocStringLen(name
, len
);
1076 return get_expected_ret();
1079 static const ISAXContentHandlerVtbl contentHandlerVtbl
=
1081 contentHandler_QueryInterface
,
1082 contentHandler_AddRef
,
1083 contentHandler_Release
,
1084 contentHandler_putDocumentLocator
,
1085 contentHandler_startDocument
,
1086 contentHandler_endDocument
,
1087 contentHandler_startPrefixMapping
,
1088 contentHandler_endPrefixMapping
,
1089 contentHandler_startElement
,
1090 contentHandler_endElement
,
1091 contentHandler_characters
,
1092 contentHandler_ignorableWhitespace
,
1093 contentHandler_processingInstruction
,
1094 contentHandler_skippedEntity
1097 static ISAXContentHandler contentHandler
= { &contentHandlerVtbl
};
1099 static HRESULT WINAPI
isaxerrorHandler_QueryInterface(
1100 ISAXErrorHandler
* iface
,
1106 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXErrorHandler
))
1112 return E_NOINTERFACE
;
1118 static ULONG WINAPI
isaxerrorHandler_AddRef(
1119 ISAXErrorHandler
* iface
)
1124 static ULONG WINAPI
isaxerrorHandler_Release(
1125 ISAXErrorHandler
* iface
)
1130 static HRESULT WINAPI
isaxerrorHandler_error(
1131 ISAXErrorHandler
* iface
,
1132 ISAXLocator
*pLocator
,
1133 const WCHAR
*pErrorMessage
,
1134 HRESULT hrErrorCode
)
1136 ok(0, "unexpected call\n");
1140 static HRESULT WINAPI
isaxerrorHandler_fatalError(
1141 ISAXErrorHandler
* iface
,
1142 ISAXLocator
*pLocator
,
1143 const WCHAR
*message
,
1146 struct call_entry call
;
1148 init_call_entry(locator
, &call
);
1149 call
.id
= EH_FATALERROR
;
1152 add_call(sequences
, CONTENT_HANDLER_INDEX
, &call
);
1158 static HRESULT WINAPI
isaxerrorHanddler_ignorableWarning(
1159 ISAXErrorHandler
* iface
,
1160 ISAXLocator
*pLocator
,
1161 const WCHAR
*pErrorMessage
,
1162 HRESULT hrErrorCode
)
1164 ok(0, "unexpected call\n");
1168 static const ISAXErrorHandlerVtbl errorHandlerVtbl
=
1170 isaxerrorHandler_QueryInterface
,
1171 isaxerrorHandler_AddRef
,
1172 isaxerrorHandler_Release
,
1173 isaxerrorHandler_error
,
1174 isaxerrorHandler_fatalError
,
1175 isaxerrorHanddler_ignorableWarning
1178 static ISAXErrorHandler errorHandler
= { &errorHandlerVtbl
};
1180 static HRESULT WINAPI
isaxattributes_QueryInterface(
1181 ISAXAttributes
* iface
,
1187 if(IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_ISAXAttributes
))
1193 return E_NOINTERFACE
;
1199 static ULONG WINAPI
isaxattributes_AddRef(ISAXAttributes
* iface
)
1204 static ULONG WINAPI
isaxattributes_Release(ISAXAttributes
* iface
)
1209 static HRESULT WINAPI
isaxattributes_getLength(ISAXAttributes
* iface
, int *length
)
1215 static HRESULT WINAPI
isaxattributes_getURI(
1216 ISAXAttributes
* iface
,
1221 ok(0, "unexpected call\n");
1225 static HRESULT WINAPI
isaxattributes_getLocalName(
1226 ISAXAttributes
* iface
,
1228 const WCHAR
**pLocalName
,
1229 int *pLocalNameLength
)
1231 ok(0, "unexpected call\n");
1235 static HRESULT WINAPI
isaxattributes_getQName(
1236 ISAXAttributes
* iface
,
1238 const WCHAR
**QName
,
1241 static const WCHAR attrqnamesW
[][15] = {{'a',':','a','t','t','r','1','j','u','n','k',0},
1242 {'a','t','t','r','2','j','u','n','k',0},
1243 {'a','t','t','r','3',0}};
1244 static const int attrqnamelen
[] = {7, 5, 5};
1246 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1248 *QName
= attrqnamesW
[index
];
1249 *QNameLength
= attrqnamelen
[index
];
1254 static HRESULT WINAPI
isaxattributes_getName(
1255 ISAXAttributes
* iface
,
1259 const WCHAR
** pLocalName
,
1260 int * pLocalNameSize
,
1261 const WCHAR
** pQName
,
1264 ok(0, "unexpected call\n");
1268 static HRESULT WINAPI
isaxattributes_getIndexFromName(
1269 ISAXAttributes
* iface
,
1272 const WCHAR
* pLocalName
,
1273 int cocalNameLength
,
1276 ok(0, "unexpected call\n");
1280 static HRESULT WINAPI
isaxattributes_getIndexFromQName(
1281 ISAXAttributes
* iface
,
1282 const WCHAR
* pQName
,
1286 ok(0, "unexpected call\n");
1290 static HRESULT WINAPI
isaxattributes_getType(
1291 ISAXAttributes
* iface
,
1293 const WCHAR
** pType
,
1296 ok(0, "unexpected call\n");
1300 static HRESULT WINAPI
isaxattributes_getTypeFromName(
1301 ISAXAttributes
* iface
,
1304 const WCHAR
* pLocalName
,
1306 const WCHAR
** pType
,
1309 ok(0, "unexpected call\n");
1313 static HRESULT WINAPI
isaxattributes_getTypeFromQName(
1314 ISAXAttributes
* iface
,
1315 const WCHAR
* pQName
,
1317 const WCHAR
** pType
,
1320 ok(0, "unexpected call\n");
1324 static HRESULT WINAPI
isaxattributes_getValue(ISAXAttributes
* iface
, int index
,
1325 const WCHAR
**value
, int *nValue
)
1327 static const WCHAR attrvaluesW
[][10] = {{'a','1','j','u','n','k',0},
1328 {'a','2','j','u','n','k',0},
1329 {'<','&','"','>',0}};
1330 static const int attrvalueslen
[] = {2, 2, 4};
1332 ok(index
>= 0 && index
<= 2, "invalid index received %d\n", index
);
1334 *value
= attrvaluesW
[index
];
1335 *nValue
= attrvalueslen
[index
];
1340 static HRESULT WINAPI
isaxattributes_getValueFromName(
1341 ISAXAttributes
* iface
,
1344 const WCHAR
* pLocalName
,
1346 const WCHAR
** pValue
,
1349 ok(0, "unexpected call\n");
1353 static HRESULT WINAPI
isaxattributes_getValueFromQName(
1354 ISAXAttributes
* iface
,
1355 const WCHAR
* pQName
,
1357 const WCHAR
** pValue
,
1360 ok(0, "unexpected call\n");
1364 static const ISAXAttributesVtbl SAXAttributesVtbl
=
1366 isaxattributes_QueryInterface
,
1367 isaxattributes_AddRef
,
1368 isaxattributes_Release
,
1369 isaxattributes_getLength
,
1370 isaxattributes_getURI
,
1371 isaxattributes_getLocalName
,
1372 isaxattributes_getQName
,
1373 isaxattributes_getName
,
1374 isaxattributes_getIndexFromName
,
1375 isaxattributes_getIndexFromQName
,
1376 isaxattributes_getType
,
1377 isaxattributes_getTypeFromName
,
1378 isaxattributes_getTypeFromQName
,
1379 isaxattributes_getValue
,
1380 isaxattributes_getValueFromName
,
1381 isaxattributes_getValueFromQName
1384 static ISAXAttributes saxattributes
= { &SAXAttributesVtbl
};
1386 static int handler_addrefcalled
;
1388 static HRESULT WINAPI
isaxlexical_QueryInterface(ISAXLexicalHandler
* iface
, REFIID riid
, void **ppvObject
)
1392 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
1393 IsEqualGUID(riid
, &IID_ISAXLexicalHandler
))
1399 return E_NOINTERFACE
;
1405 static ULONG WINAPI
isaxlexical_AddRef(ISAXLexicalHandler
* iface
)
1407 handler_addrefcalled
++;
1411 static ULONG WINAPI
isaxlexical_Release(ISAXLexicalHandler
* iface
)
1416 static HRESULT WINAPI
isaxlexical_startDTD(ISAXLexicalHandler
* iface
,
1417 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
,
1418 int nPublicId
, const WCHAR
* pSystemId
, int nSystemId
)
1420 ok(0, "call not expected\n");
1424 static HRESULT WINAPI
isaxlexical_endDTD(ISAXLexicalHandler
* iface
)
1426 ok(0, "call not expected\n");
1430 static HRESULT WINAPI
isaxlexical_startEntity(ISAXLexicalHandler
*iface
,
1431 const WCHAR
* pName
, int nName
)
1433 ok(0, "call not expected\n");
1437 static HRESULT WINAPI
isaxlexical_endEntity(ISAXLexicalHandler
*iface
,
1438 const WCHAR
* pName
, int nName
)
1440 ok(0, "call not expected\n");
1444 static HRESULT WINAPI
isaxlexical_startCDATA(ISAXLexicalHandler
*iface
)
1446 ok(0, "call not expected\n");
1450 static HRESULT WINAPI
isaxlexical_endCDATA(ISAXLexicalHandler
*iface
)
1452 ok(0, "call not expected\n");
1456 static HRESULT WINAPI
isaxlexical_comment(ISAXLexicalHandler
*iface
,
1457 const WCHAR
* pChars
, int nChars
)
1459 ok(0, "call not expected\n");
1463 static const ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1465 isaxlexical_QueryInterface
,
1467 isaxlexical_Release
,
1468 isaxlexical_startDTD
,
1470 isaxlexical_startEntity
,
1471 isaxlexical_endEntity
,
1472 isaxlexical_startCDATA
,
1473 isaxlexical_endCDATA
,
1477 static ISAXLexicalHandler saxlexicalhandler
= { &SAXLexicalHandlerVtbl
};
1479 static HRESULT WINAPI
isaxdecl_QueryInterface(ISAXDeclHandler
* iface
, REFIID riid
, void **ppvObject
)
1483 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
1484 IsEqualGUID(riid
, &IID_ISAXDeclHandler
))
1490 return E_NOINTERFACE
;
1496 static ULONG WINAPI
isaxdecl_AddRef(ISAXDeclHandler
* iface
)
1498 handler_addrefcalled
++;
1502 static ULONG WINAPI
isaxdecl_Release(ISAXDeclHandler
* iface
)
1507 static HRESULT WINAPI
isaxdecl_elementDecl(ISAXDeclHandler
* iface
,
1508 const WCHAR
* pName
, int nName
, const WCHAR
* pModel
, int nModel
)
1510 ok(0, "call not expected\n");
1514 static HRESULT WINAPI
isaxdecl_attributeDecl(ISAXDeclHandler
* iface
,
1515 const WCHAR
* pElementName
, int nElementName
, const WCHAR
* pAttributeName
,
1516 int nAttributeName
, const WCHAR
* pType
, int nType
, const WCHAR
* pValueDefault
,
1517 int nValueDefault
, const WCHAR
* pValue
, int nValue
)
1519 ok(0, "call not expected\n");
1523 static HRESULT WINAPI
isaxdecl_internalEntityDecl(ISAXDeclHandler
* iface
,
1524 const WCHAR
* pName
, int nName
, const WCHAR
* pValue
, int nValue
)
1526 ok(0, "call not expected\n");
1530 static HRESULT WINAPI
isaxdecl_externalEntityDecl(ISAXDeclHandler
* iface
,
1531 const WCHAR
* pName
, int nName
, const WCHAR
* pPublicId
, int nPublicId
,
1532 const WCHAR
* pSystemId
, int nSystemId
)
1534 ok(0, "call not expected\n");
1538 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
=
1540 isaxdecl_QueryInterface
,
1543 isaxdecl_elementDecl
,
1544 isaxdecl_attributeDecl
,
1545 isaxdecl_internalEntityDecl
,
1546 isaxdecl_externalEntityDecl
1549 static ISAXDeclHandler saxdeclhandler
= { &SAXDeclHandlerVtbl
};
1551 typedef struct mxwriter_write_test_t
{
1557 } mxwriter_write_test
;
1559 typedef struct mxwriter_stream_test_t
{
1561 const char *encoding
;
1562 mxwriter_write_test expected_writes
[4];
1563 } mxwriter_stream_test
;
1565 static const mxwriter_write_test
*current_write_test
;
1566 static DWORD current_stream_test_index
;
1568 static HRESULT WINAPI
istream_QueryInterface(IStream
*iface
, REFIID riid
, void **ppvObject
)
1572 if(IsEqualGUID(riid
, &IID_IStream
) || IsEqualGUID(riid
, &IID_IUnknown
))
1575 return E_NOINTERFACE
;
1580 static ULONG WINAPI
istream_AddRef(IStream
*iface
)
1585 static ULONG WINAPI
istream_Release(IStream
*iface
)
1590 static HRESULT WINAPI
istream_Read(IStream
*iface
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
1592 ok(0, "unexpected call\n");
1596 static HRESULT WINAPI
istream_Write(IStream
*iface
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
1600 ok(pv
!= NULL
, "pv == NULL\n");
1602 if(current_write_test
->last
) {
1603 ok(0, "Too many Write calls made on test %d\n", current_stream_test_index
);
1607 fail
= current_write_test
->fail_write
;
1609 ok(current_write_test
->cb
== cb
, "Expected %d, but got %d on test %d\n",
1610 current_write_test
->cb
, cb
, current_stream_test_index
);
1613 ok(current_write_test
->null_written
, "pcbWritten was NULL on test %d\n", current_stream_test_index
);
1615 ok(!memcmp(current_write_test
->data
, pv
, cb
), "Unexpected data on test %d\n", current_stream_test_index
);
1617 ++current_write_test
;
1622 return fail
? E_FAIL
: S_OK
;
1625 static HRESULT WINAPI
istream_Seek(IStream
*iface
, LARGE_INTEGER dlibMove
, DWORD dwOrigin
,
1626 ULARGE_INTEGER
*plibNewPosition
)
1628 ok(0, "unexpected call\n");
1632 static HRESULT WINAPI
istream_SetSize(IStream
*iface
, ULARGE_INTEGER libNewSize
)
1634 ok(0, "unexpected call\n");
1638 static HRESULT WINAPI
istream_CopyTo(IStream
*iface
, IStream
*pstm
, ULARGE_INTEGER cb
,
1639 ULARGE_INTEGER
*pcbRead
, ULARGE_INTEGER
*plibWritten
)
1641 ok(0, "unexpected call\n");
1645 static HRESULT WINAPI
istream_Commit(IStream
*iface
, DWORD grfCommitFlags
)
1647 ok(0, "unexpected call\n");
1651 static HRESULT WINAPI
istream_Revert(IStream
*iface
)
1653 ok(0, "unexpected call\n");
1657 static HRESULT WINAPI
istream_LockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1658 ULARGE_INTEGER cb
, DWORD dwLockType
)
1660 ok(0, "unexpected call\n");
1664 static HRESULT WINAPI
istream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER libOffset
,
1665 ULARGE_INTEGER cb
, DWORD dwLockType
)
1667 ok(0, "unexpected call\n");
1671 static HRESULT WINAPI
istream_Stat(IStream
*iface
, STATSTG
*pstatstg
, DWORD grfStatFlag
)
1673 ok(0, "unexpected call\n");
1677 static HRESULT WINAPI
istream_Clone(IStream
*iface
, IStream
**ppstm
)
1679 ok(0, "unexpected call\n");
1683 static const IStreamVtbl StreamVtbl
= {
1684 istream_QueryInterface
,
1695 istream_UnlockRegion
,
1700 static IStream mxstream
= { &StreamVtbl
};
1702 static struct msxmlsupported_data_t reader_support_data
[] =
1704 { &CLSID_SAXXMLReader
, "SAXReader" },
1705 { &CLSID_SAXXMLReader30
, "SAXReader30" },
1706 { &CLSID_SAXXMLReader40
, "SAXReader40" },
1707 { &CLSID_SAXXMLReader60
, "SAXReader60" },
1711 static void test_saxreader(void)
1713 const struct msxmlsupported_data_t
*table
= reader_support_data
;
1715 ISAXXMLReader
*reader
= NULL
;
1717 ISAXContentHandler
*content
;
1718 ISAXErrorHandler
*lpErrorHandler
;
1720 SAFEARRAYBOUND SADim
[1];
1723 ULARGE_INTEGER liSize
;
1724 LARGE_INTEGER liPos
;
1727 static const CHAR testXmlA
[] = "test.xml";
1728 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
1729 IXMLDOMDocument
*doc
;
1733 while (table
->clsid
)
1735 struct call_entry
*test_seq
;
1737 if (!is_clsid_supported(table
->clsid
, reader_support_data
))
1743 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
1744 EXPECT_HR(hr
, S_OK
);
1746 msxml_version
= IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
) ? 6 : 0;
1748 /* crashes on old versions */
1749 if (!IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) &&
1750 !IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1752 hr
= ISAXXMLReader_getContentHandler(reader
, NULL
);
1753 EXPECT_HR(hr
, E_POINTER
);
1755 hr
= ISAXXMLReader_getErrorHandler(reader
, NULL
);
1756 EXPECT_HR(hr
, E_POINTER
);
1759 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
1760 EXPECT_HR(hr
, S_OK
);
1761 ok(content
== NULL
, "Expected %p, got %p\n", NULL
, content
);
1763 hr
= ISAXXMLReader_getErrorHandler(reader
, &lpErrorHandler
);
1764 EXPECT_HR(hr
, S_OK
);
1765 ok(lpErrorHandler
== NULL
, "Expected %p, got %p\n", NULL
, lpErrorHandler
);
1767 hr
= ISAXXMLReader_putContentHandler(reader
, NULL
);
1768 EXPECT_HR(hr
, S_OK
);
1770 hr
= ISAXXMLReader_putContentHandler(reader
, &contentHandler
);
1771 EXPECT_HR(hr
, S_OK
);
1773 hr
= ISAXXMLReader_putErrorHandler(reader
, &errorHandler
);
1774 EXPECT_HR(hr
, S_OK
);
1776 hr
= ISAXXMLReader_getContentHandler(reader
, &content
);
1777 EXPECT_HR(hr
, S_OK
);
1778 ok(content
== &contentHandler
, "Expected %p, got %p\n", &contentHandler
, content
);
1780 V_VT(&var
) = VT_BSTR
;
1781 V_BSTR(&var
) = SysAllocString(szSimpleXML
);
1783 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1784 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1785 test_seq
= content_handler_test1_alternate
;
1787 test_seq
= content_handler_test1
;
1788 set_expected_seq(test_seq
);
1789 hr
= ISAXXMLReader_parse(reader
, var
);
1790 EXPECT_HR(hr
, S_OK
);
1791 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1", FALSE
);
1795 SADim
[0].lLbound
= 0;
1796 SADim
[0].cElements
= sizeof(testXML
)-1;
1797 sa
= SafeArrayCreate(VT_UI1
, 1, SADim
);
1798 SafeArrayAccessData(sa
, (void**)&ptr
);
1799 memcpy(ptr
, testXML
, sizeof(testXML
)-1);
1800 SafeArrayUnaccessData(sa
);
1801 V_VT(&var
) = VT_ARRAY
|VT_UI1
;
1804 set_expected_seq(test_seq
);
1805 hr
= ISAXXMLReader_parse(reader
, var
);
1806 EXPECT_HR(hr
, S_OK
);
1807 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from safe array", FALSE
);
1809 SafeArrayDestroy(sa
);
1811 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1812 liSize
.QuadPart
= strlen(testXML
);
1813 IStream_SetSize(stream
, liSize
);
1814 IStream_Write(stream
, testXML
, strlen(testXML
), &written
);
1816 IStream_Seek(stream
, liPos
, STREAM_SEEK_SET
, NULL
);
1817 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
1818 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
1820 set_expected_seq(test_seq
);
1821 hr
= ISAXXMLReader_parse(reader
, var
);
1822 EXPECT_HR(hr
, S_OK
);
1823 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from stream", FALSE
);
1825 IStream_Release(stream
);
1827 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1828 liSize
.QuadPart
= strlen(szTestAttributes
);
1829 IStream_SetSize(stream
, liSize
);
1830 IStream_Write(stream
, szTestAttributes
, strlen(szTestAttributes
), &written
);
1832 IStream_Seek(stream
, liPos
, STREAM_SEEK_SET
, NULL
);
1833 V_VT(&var
) = VT_UNKNOWN
|VT_DISPATCH
;
1834 V_UNKNOWN(&var
) = (IUnknown
*)stream
;
1836 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
))
1837 test_seq
= content_handler_test_attributes_alternate_4
;
1838 else if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1839 test_seq
= content_handler_test_attributes_alternate_6
;
1841 test_seq
= content_handler_test_attributes
;
1843 set_expected_seq(test_seq
);
1844 hr
= ISAXXMLReader_parse(reader
, var
);
1845 EXPECT_HR(hr
, S_OK
);
1847 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1848 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1849 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", FALSE
);
1851 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test attributes", TRUE
);
1853 IStream_Release(stream
);
1855 V_VT(&var
) = VT_BSTR
;
1856 V_BSTR(&var
) = SysAllocString(carriage_ret_test
);
1858 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1859 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1860 test_seq
= content_handler_test2_alternate
;
1862 test_seq
= content_handler_test2
;
1864 set_expected_seq(test_seq
);
1865 hr
= ISAXXMLReader_parse(reader
, var
);
1866 EXPECT_HR(hr
, S_OK
);
1867 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 2", FALSE
);
1872 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1873 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
1874 WriteFile(file
, testXML
, sizeof(testXML
)-1, &written
, NULL
);
1877 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1878 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1879 test_seq
= content_handler_test1_alternate
;
1881 test_seq
= content_handler_test1
;
1882 set_expected_seq(test_seq
);
1883 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1884 EXPECT_HR(hr
, S_OK
);
1885 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test 1: from file url", FALSE
);
1888 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1889 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1890 test_seq
= content_handler_testerror_alternate
;
1892 test_seq
= content_handler_testerror
;
1893 set_expected_seq(test_seq
);
1894 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1895 EXPECT_HR(hr
, E_FAIL
);
1896 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content test error", FALSE
);
1898 /* callback ret values */
1899 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1900 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1902 test_seq
= content_handler_test_callback_rets_alt
;
1903 set_expected_seq(test_seq
);
1904 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1905 EXPECT_HR(hr
, S_OK
);
1909 test_seq
= content_handler_test_callback_rets
;
1910 set_expected_seq(test_seq
);
1911 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
1912 EXPECT_HR(hr
, S_FALSE
);
1914 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "content callback ret values", FALSE
);
1916 DeleteFileA(testXmlA
);
1918 /* parse from IXMLDOMDocument */
1919 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
1920 &IID_IXMLDOMDocument
, (void**)&doc
);
1921 EXPECT_HR(hr
, S_OK
);
1923 str
= SysAllocString(szSimpleXML
);
1924 hr
= IXMLDOMDocument_loadXML(doc
, str
, &v
);
1925 EXPECT_HR(hr
, S_OK
);
1927 V_VT(&var
) = VT_UNKNOWN
;
1928 V_UNKNOWN(&var
) = (IUnknown
*)doc
;
1930 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1931 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1932 test_seq
= content_handler_test2_alternate
;
1934 test_seq
= content_handler_test2
;
1936 set_expected_seq(test_seq
);
1937 hr
= ISAXXMLReader_parse(reader
, var
);
1938 EXPECT_HR(hr
, S_OK
);
1939 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "parse from IXMLDOMDocument", FALSE
);
1940 IXMLDOMDocument_Release(doc
);
1942 /* xml:space test */
1943 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1944 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1946 test_seq
= xmlspaceattr_test_alternate
;
1949 test_seq
= xmlspaceattr_test
;
1951 set_expected_seq(test_seq
);
1952 V_VT(&var
) = VT_BSTR
;
1953 V_BSTR(&var
) = _bstr_(xmlspace_attr
);
1954 hr
= ISAXXMLReader_parse(reader
, var
);
1955 EXPECT_HR(hr
, S_OK
);
1957 if (IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader40
) ||
1958 IsEqualGUID(table
->clsid
, &CLSID_SAXXMLReader60
))
1960 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", TRUE
);
1963 ok_sequence(sequences
, CONTENT_HANDLER_INDEX
, test_seq
, "xml:space handling", FALSE
);
1965 ISAXXMLReader_Release(reader
);
1971 ISAXXMLReader_Release(reader
);
1976 struct saxreader_props_test_t
1978 const char *prop_name
;
1982 static const struct saxreader_props_test_t props_test_data
[] = {
1983 { "http://xml.org/sax/properties/lexical-handler", (IUnknown
*)&saxlexicalhandler
},
1984 { "http://xml.org/sax/properties/declaration-handler", (IUnknown
*)&saxdeclhandler
},
1988 static void test_saxreader_properties(void)
1990 const struct saxreader_props_test_t
*ptr
= props_test_data
;
1991 ISAXXMLReader
*reader
;
1994 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
1995 &IID_ISAXXMLReader
, (void**)&reader
);
1996 EXPECT_HR(hr
, S_OK
);
1998 hr
= ISAXXMLReader_getProperty(reader
, _bstr_("http://xml.org/sax/properties/lexical-handler"), NULL
);
1999 EXPECT_HR(hr
, E_POINTER
);
2001 while (ptr
->prop_name
)
2005 V_VT(&v
) = VT_EMPTY
;
2006 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2007 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2008 EXPECT_HR(hr
, S_OK
);
2009 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2010 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2012 V_VT(&v
) = VT_UNKNOWN
;
2013 V_UNKNOWN(&v
) = ptr
->iface
;
2014 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2015 EXPECT_HR(hr
, S_OK
);
2017 V_VT(&v
) = VT_EMPTY
;
2018 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2019 handler_addrefcalled
= 0;
2020 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2021 EXPECT_HR(hr
, S_OK
);
2022 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2023 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2024 ok(handler_addrefcalled
== 1, "AddRef called %d times\n", handler_addrefcalled
);
2027 V_VT(&v
) = VT_EMPTY
;
2028 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2029 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2030 EXPECT_HR(hr
, S_OK
);
2032 V_VT(&v
) = VT_EMPTY
;
2033 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2034 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2035 EXPECT_HR(hr
, S_OK
);
2036 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2037 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2039 V_VT(&v
) = VT_UNKNOWN
;
2040 V_UNKNOWN(&v
) = ptr
->iface
;
2041 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2042 EXPECT_HR(hr
, S_OK
);
2044 /* only VT_EMPTY seems to be valid to reset property */
2046 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2047 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2048 EXPECT_HR(hr
, E_INVALIDARG
);
2050 V_VT(&v
) = VT_EMPTY
;
2051 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2052 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2053 EXPECT_HR(hr
, S_OK
);
2054 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2055 ok(V_UNKNOWN(&v
) == ptr
->iface
, "got %p\n", V_UNKNOWN(&v
));
2058 V_VT(&v
) = VT_UNKNOWN
;
2059 V_UNKNOWN(&v
) = NULL
;
2060 hr
= ISAXXMLReader_putProperty(reader
, _bstr_(ptr
->prop_name
), v
);
2061 EXPECT_HR(hr
, S_OK
);
2063 V_VT(&v
) = VT_EMPTY
;
2064 V_UNKNOWN(&v
) = (IUnknown
*)0xdeadbeef;
2065 hr
= ISAXXMLReader_getProperty(reader
, _bstr_(ptr
->prop_name
), &v
);
2066 EXPECT_HR(hr
, S_OK
);
2067 ok(V_VT(&v
) == VT_UNKNOWN
, "got %d\n", V_VT(&v
));
2068 ok(V_UNKNOWN(&v
) == NULL
, "got %p\n", V_UNKNOWN(&v
));
2073 ISAXXMLReader_Release(reader
);
2077 struct feature_ns_entry_t
{
2083 static const struct feature_ns_entry_t feature_ns_entry_data
[] = {
2084 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", VARIANT_TRUE
},
2085 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", VARIANT_TRUE
},
2086 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", VARIANT_TRUE
},
2087 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", VARIANT_TRUE
},
2091 static void test_saxreader_features(void)
2093 const struct feature_ns_entry_t
*entry
= feature_ns_entry_data
;
2094 ISAXXMLReader
*reader
;
2101 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2104 win_skip("can't create %s instance\n", entry
->clsid
);
2110 hr
= ISAXXMLReader_getFeature(reader
, _bstr_("http://xml.org/sax/features/namespaces"), &value
);
2111 EXPECT_HR(hr
, S_OK
);
2112 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2115 hr
= ISAXXMLReader_getFeature(reader
, _bstr_("http://xml.org/sax/features/namespace-prefixes"), &value
);
2116 EXPECT_HR(hr
, S_OK
);
2117 ok(entry
->value
== value
, "%s: got wrong default value %x, expected %x\n", entry
->clsid
, value
, entry
->value
);
2119 ISAXXMLReader_Release(reader
);
2125 /* UTF-8 data with UTF-8 BOM and UTF-16 in prolog */
2126 static const CHAR UTF8BOMTest
[] =
2127 "\xEF\xBB\xBF<?xml version = \"1.0\" encoding = \"UTF-16\"?>\n"
2130 struct enc_test_entry_t
{
2138 static const struct enc_test_entry_t encoding_test_data
[] = {
2139 { &CLSID_SAXXMLReader
, "CLSID_SAXXMLReader", UTF8BOMTest
, 0xc00ce56f, 1 },
2140 { &CLSID_SAXXMLReader30
, "CLSID_SAXXMLReader30", UTF8BOMTest
, 0xc00ce56f, 1 },
2141 { &CLSID_SAXXMLReader40
, "CLSID_SAXXMLReader40", UTF8BOMTest
, S_OK
, 0 },
2142 { &CLSID_SAXXMLReader60
, "CLSID_SAXXMLReader60", UTF8BOMTest
, S_OK
, 0 },
2146 static void test_encoding(void)
2148 const struct enc_test_entry_t
*entry
= encoding_test_data
;
2149 static const WCHAR testXmlW
[] = {'t','e','s','t','.','x','m','l',0};
2150 static const CHAR testXmlA
[] = "test.xml";
2151 ISAXXMLReader
*reader
;
2158 hr
= CoCreateInstance(entry
->guid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISAXXMLReader
, (void**)&reader
);
2161 win_skip("can't create %s instance\n", entry
->clsid
);
2166 file
= CreateFileA(testXmlA
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2167 ok(file
!= INVALID_HANDLE_VALUE
, "Could not create file: %u\n", GetLastError());
2168 WriteFile(file
, UTF8BOMTest
, sizeof(UTF8BOMTest
)-1, &written
, NULL
);
2171 hr
= ISAXXMLReader_parseURL(reader
, testXmlW
);
2173 todo_wine
ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2175 ok(hr
== entry
->hr
, "Expected 0x%08x, got 0x%08x. CLSID %s\n", entry
->hr
, hr
, entry
->clsid
);
2177 DeleteFileA(testXmlA
);
2178 ISAXXMLReader_Release(reader
);
2184 static void test_mxwriter_handlers(void)
2186 ISAXContentHandler
*handler
;
2187 IMXWriter
*writer
, *writer2
;
2188 ISAXDeclHandler
*decl
;
2189 ISAXLexicalHandler
*lh
;
2192 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2193 &IID_IMXWriter
, (void**)&writer
);
2194 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2196 EXPECT_REF(writer
, 1);
2198 /* ISAXContentHandler */
2199 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&handler
);
2200 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2201 EXPECT_REF(writer
, 2);
2202 EXPECT_REF(handler
, 2);
2204 hr
= ISAXContentHandler_QueryInterface(handler
, &IID_IMXWriter
, (void**)&writer2
);
2205 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2206 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2207 EXPECT_REF(writer
, 3);
2208 EXPECT_REF(writer2
, 3);
2209 IMXWriter_Release(writer2
);
2210 ISAXContentHandler_Release(handler
);
2212 /* ISAXLexicalHandler */
2213 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lh
);
2214 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2215 EXPECT_REF(writer
, 2);
2218 hr
= ISAXLexicalHandler_QueryInterface(lh
, &IID_IMXWriter
, (void**)&writer2
);
2219 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2220 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2221 EXPECT_REF(writer
, 3);
2222 EXPECT_REF(writer2
, 3);
2223 IMXWriter_Release(writer2
);
2224 ISAXLexicalHandler_Release(lh
);
2226 /* ISAXDeclHandler */
2227 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
2228 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2229 EXPECT_REF(writer
, 2);
2232 hr
= ISAXDeclHandler_QueryInterface(decl
, &IID_IMXWriter
, (void**)&writer2
);
2233 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2234 ok(writer2
== writer
, "got %p, expected %p\n", writer2
, writer
);
2235 EXPECT_REF(writer
, 3);
2236 EXPECT_REF(writer2
, 3);
2237 IMXWriter_Release(writer2
);
2238 ISAXDeclHandler_Release(decl
);
2240 IMXWriter_Release(writer
);
2244 static struct msxmlsupported_data_t mxwriter_support_data
[] =
2246 { &CLSID_MXXMLWriter
, "MXXMLWriter" },
2247 { &CLSID_MXXMLWriter30
, "MXXMLWriter30" },
2248 { &CLSID_MXXMLWriter40
, "MXXMLWriter40" },
2249 { &CLSID_MXXMLWriter60
, "MXXMLWriter60" },
2253 static struct msxmlsupported_data_t mxattributes_support_data
[] =
2255 { &CLSID_SAXAttributes
, "SAXAttributes" },
2256 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
2257 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
2258 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
2262 struct mxwriter_props_t
2266 VARIANT_BOOL disable_escape
;
2267 VARIANT_BOOL indent
;
2268 VARIANT_BOOL omitdecl
;
2269 VARIANT_BOOL standalone
;
2270 const char *encoding
;
2273 static const struct mxwriter_props_t mxwriter_default_props
[] =
2275 { &CLSID_MXXMLWriter
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2276 { &CLSID_MXXMLWriter30
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2277 { &CLSID_MXXMLWriter40
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2278 { &CLSID_MXXMLWriter60
, VARIANT_TRUE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, VARIANT_FALSE
, "UTF-16" },
2282 static void test_mxwriter_default_properties(const struct mxwriter_props_t
*table
)
2286 while (table
->clsid
)
2293 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2300 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2301 &IID_IMXWriter
, (void**)&writer
);
2302 EXPECT_HR(hr
, S_OK
);
2305 hr
= IMXWriter_get_byteOrderMark(writer
, &b
);
2306 EXPECT_HR(hr
, S_OK
);
2307 ok(table
->bom
== b
, "test %d: got BOM %d, expected %d\n", i
, b
, table
->bom
);
2309 b
= !table
->disable_escape
;
2310 hr
= IMXWriter_get_disableOutputEscaping(writer
, &b
);
2311 EXPECT_HR(hr
, S_OK
);
2312 ok(table
->disable_escape
== b
, "test %d: got disable escape %d, expected %d\n", i
, b
,
2313 table
->disable_escape
);
2316 hr
= IMXWriter_get_indent(writer
, &b
);
2317 EXPECT_HR(hr
, S_OK
);
2318 ok(table
->indent
== b
, "test %d: got indent %d, expected %d\n", i
, b
, table
->indent
);
2320 b
= !table
->omitdecl
;
2321 hr
= IMXWriter_get_omitXMLDeclaration(writer
, &b
);
2322 EXPECT_HR(hr
, S_OK
);
2323 ok(table
->omitdecl
== b
, "test %d: got omitdecl %d, expected %d\n", i
, b
, table
->omitdecl
);
2325 b
= !table
->standalone
;
2326 hr
= IMXWriter_get_standalone(writer
, &b
);
2327 EXPECT_HR(hr
, S_OK
);
2328 ok(table
->standalone
== b
, "test %d: got standalone %d, expected %d\n", i
, b
, table
->standalone
);
2330 hr
= IMXWriter_get_encoding(writer
, &encoding
);
2331 EXPECT_HR(hr
, S_OK
);
2332 ok(!lstrcmpW(encoding
, _bstr_(table
->encoding
)), "test %d: got encoding %s, expected %s\n",
2333 i
, wine_dbgstr_w(encoding
), table
->encoding
);
2334 SysFreeString(encoding
);
2336 IMXWriter_Release(writer
);
2343 static void test_mxwriter_properties(void)
2345 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
2346 static const WCHAR emptyW
[] = {0};
2347 static const WCHAR testW
[] = {'t','e','s','t',0};
2348 ISAXContentHandler
*content
;
2355 test_mxwriter_default_properties(mxwriter_default_props
);
2357 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2358 &IID_IMXWriter
, (void**)&writer
);
2359 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2361 hr
= IMXWriter_get_disableOutputEscaping(writer
, NULL
);
2362 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2364 hr
= IMXWriter_get_byteOrderMark(writer
, NULL
);
2365 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2367 hr
= IMXWriter_get_indent(writer
, NULL
);
2368 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2370 hr
= IMXWriter_get_omitXMLDeclaration(writer
, NULL
);
2371 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2373 hr
= IMXWriter_get_standalone(writer
, NULL
);
2374 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2377 hr
= IMXWriter_put_standalone(writer
, VARIANT_TRUE
);
2378 ok(hr
== S_OK
, "got %08x\n", hr
);
2381 hr
= IMXWriter_get_standalone(writer
, &b
);
2382 ok(hr
== S_OK
, "got %08x\n", hr
);
2383 ok(b
== VARIANT_TRUE
, "got %d\n", b
);
2385 hr
= IMXWriter_get_encoding(writer
, NULL
);
2386 EXPECT_HR(hr
, E_POINTER
);
2388 /* UTF-16 is a default setting apparently */
2389 str
= (void*)0xdeadbeef;
2390 hr
= IMXWriter_get_encoding(writer
, &str
);
2391 EXPECT_HR(hr
, S_OK
);
2392 ok(lstrcmpW(str
, utf16W
) == 0, "expected empty string, got %s\n", wine_dbgstr_w(str
));
2394 str2
= (void*)0xdeadbeef;
2395 hr
= IMXWriter_get_encoding(writer
, &str2
);
2396 ok(hr
== S_OK
, "got %08x\n", hr
);
2397 ok(str
!= str2
, "expected newly allocated, got same %p\n", str
);
2399 SysFreeString(str2
);
2402 /* put empty string */
2403 str
= SysAllocString(emptyW
);
2404 hr
= IMXWriter_put_encoding(writer
, str
);
2405 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2408 str
= (void*)0xdeadbeef;
2409 hr
= IMXWriter_get_encoding(writer
, &str
);
2410 EXPECT_HR(hr
, S_OK
);
2411 ok(!lstrcmpW(str
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(str
));
2414 /* invalid encoding name */
2415 str
= SysAllocString(testW
);
2416 hr
= IMXWriter_put_encoding(writer
, str
);
2417 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2420 /* test case sensivity */
2421 hr
= IMXWriter_put_encoding(writer
, _bstr_("utf-8"));
2422 EXPECT_HR(hr
, S_OK
);
2423 str
= (void*)0xdeadbeef;
2424 hr
= IMXWriter_get_encoding(writer
, &str
);
2425 EXPECT_HR(hr
, S_OK
);
2426 ok(!lstrcmpW(str
, _bstr_("utf-8")), "got %s\n", wine_dbgstr_w(str
));
2429 hr
= IMXWriter_put_encoding(writer
, _bstr_("uTf-16"));
2430 EXPECT_HR(hr
, S_OK
);
2431 str
= (void*)0xdeadbeef;
2432 hr
= IMXWriter_get_encoding(writer
, &str
);
2433 EXPECT_HR(hr
, S_OK
);
2434 ok(!lstrcmpW(str
, _bstr_("uTf-16")), "got %s\n", wine_dbgstr_w(str
));
2437 /* how it affects document creation */
2438 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2439 EXPECT_HR(hr
, S_OK
);
2441 hr
= ISAXContentHandler_startDocument(content
);
2442 EXPECT_HR(hr
, S_OK
);
2443 hr
= ISAXContentHandler_endDocument(content
);
2444 EXPECT_HR(hr
, S_OK
);
2446 V_VT(&dest
) = VT_EMPTY
;
2447 hr
= IMXWriter_get_output(writer
, &dest
);
2448 EXPECT_HR(hr
, S_OK
);
2449 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2450 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>\r\n"),
2451 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2452 VariantClear(&dest
);
2453 ISAXContentHandler_Release(content
);
2455 hr
= IMXWriter_get_version(writer
, NULL
);
2456 ok(hr
== E_POINTER
, "got %08x\n", hr
);
2457 /* default version is 'surprisingly' 1.0 */
2458 hr
= IMXWriter_get_version(writer
, &str
);
2459 ok(hr
== S_OK
, "got %08x\n", hr
);
2460 ok(!lstrcmpW(str
, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str
));
2463 /* store version string as is */
2464 hr
= IMXWriter_put_version(writer
, NULL
);
2465 ok(hr
== E_INVALIDARG
, "got %08x\n", hr
);
2467 hr
= IMXWriter_put_version(writer
, _bstr_("1.0"));
2468 ok(hr
== S_OK
, "got %08x\n", hr
);
2470 hr
= IMXWriter_put_version(writer
, _bstr_(""));
2471 ok(hr
== S_OK
, "got %08x\n", hr
);
2472 hr
= IMXWriter_get_version(writer
, &str
);
2473 ok(hr
== S_OK
, "got %08x\n", hr
);
2474 ok(!lstrcmpW(str
, _bstr_("")), "got %s\n", wine_dbgstr_w(str
));
2477 hr
= IMXWriter_put_version(writer
, _bstr_("a.b"));
2478 ok(hr
== S_OK
, "got %08x\n", hr
);
2479 hr
= IMXWriter_get_version(writer
, &str
);
2480 ok(hr
== S_OK
, "got %08x\n", hr
);
2481 ok(!lstrcmpW(str
, _bstr_("a.b")), "got %s\n", wine_dbgstr_w(str
));
2484 hr
= IMXWriter_put_version(writer
, _bstr_("2.0"));
2485 ok(hr
== S_OK
, "got %08x\n", hr
);
2486 hr
= IMXWriter_get_version(writer
, &str
);
2487 ok(hr
== S_OK
, "got %08x\n", hr
);
2488 ok(!lstrcmpW(str
, _bstr_("2.0")), "got %s\n", wine_dbgstr_w(str
));
2491 IMXWriter_Release(writer
);
2495 static void test_mxwriter_flush(void)
2497 ISAXContentHandler
*content
;
2500 ULARGE_INTEGER pos2
;
2505 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2506 &IID_IMXWriter
, (void**)&writer
);
2507 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2509 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
2510 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2511 EXPECT_REF(stream
, 1);
2513 /* detach when nothing was attached */
2514 V_VT(&dest
) = VT_EMPTY
;
2515 hr
= IMXWriter_put_output(writer
, dest
);
2516 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2519 V_VT(&dest
) = VT_UNKNOWN
;
2520 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
2521 hr
= IMXWriter_put_output(writer
, dest
);
2522 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2523 todo_wine
EXPECT_REF(stream
, 3);
2525 /* detach setting VT_EMPTY destination */
2526 V_VT(&dest
) = VT_EMPTY
;
2527 hr
= IMXWriter_put_output(writer
, dest
);
2528 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2529 EXPECT_REF(stream
, 1);
2531 V_VT(&dest
) = VT_UNKNOWN
;
2532 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
2533 hr
= IMXWriter_put_output(writer
, dest
);
2534 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2536 /* flush() doesn't detach a stream */
2537 hr
= IMXWriter_flush(writer
);
2538 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2539 todo_wine
EXPECT_REF(stream
, 3);
2542 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2543 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2544 ok(pos2
.QuadPart
== 0, "expected stream beginning\n");
2546 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2547 ok(hr
== S_OK
, "got %08x\n", hr
);
2549 hr
= ISAXContentHandler_startDocument(content
);
2550 ok(hr
== S_OK
, "got %08x\n", hr
);
2553 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2554 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2555 ok(pos2
.QuadPart
!= 0, "expected stream beginning\n");
2557 /* already started */
2558 hr
= ISAXContentHandler_startDocument(content
);
2559 ok(hr
== S_OK
, "got %08x\n", hr
);
2561 hr
= ISAXContentHandler_endDocument(content
);
2562 ok(hr
== S_OK
, "got %08x\n", hr
);
2564 /* flushed on endDocument() */
2566 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
2567 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2568 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
2570 ISAXContentHandler_Release(content
);
2571 IStream_Release(stream
);
2572 IMXWriter_Release(writer
);
2575 static void test_mxwriter_startenddocument(void)
2577 ISAXContentHandler
*content
;
2582 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2583 &IID_IMXWriter
, (void**)&writer
);
2584 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2586 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2587 ok(hr
== S_OK
, "got %08x\n", hr
);
2589 hr
= ISAXContentHandler_startDocument(content
);
2590 ok(hr
== S_OK
, "got %08x\n", hr
);
2592 hr
= ISAXContentHandler_endDocument(content
);
2593 ok(hr
== S_OK
, "got %08x\n", hr
);
2595 V_VT(&dest
) = VT_EMPTY
;
2596 hr
= IMXWriter_get_output(writer
, &dest
);
2597 ok(hr
== S_OK
, "got %08x\n", hr
);
2598 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2599 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
2600 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2601 VariantClear(&dest
);
2603 /* now try another startDocument */
2604 hr
= ISAXContentHandler_startDocument(content
);
2605 ok(hr
== S_OK
, "got %08x\n", hr
);
2606 /* and get duplicated prolog */
2607 V_VT(&dest
) = VT_EMPTY
;
2608 hr
= IMXWriter_get_output(writer
, &dest
);
2609 ok(hr
== S_OK
, "got %08x\n", hr
);
2610 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2611 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"
2612 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
2613 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2614 VariantClear(&dest
);
2616 ISAXContentHandler_Release(content
);
2617 IMXWriter_Release(writer
);
2619 /* now with omitted declaration */
2620 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2621 &IID_IMXWriter
, (void**)&writer
);
2622 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2624 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2625 ok(hr
== S_OK
, "got %08x\n", hr
);
2627 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2628 ok(hr
== S_OK
, "got %08x\n", hr
);
2630 hr
= ISAXContentHandler_startDocument(content
);
2631 ok(hr
== S_OK
, "got %08x\n", hr
);
2633 hr
= ISAXContentHandler_endDocument(content
);
2634 ok(hr
== S_OK
, "got %08x\n", hr
);
2636 V_VT(&dest
) = VT_EMPTY
;
2637 hr
= IMXWriter_get_output(writer
, &dest
);
2638 ok(hr
== S_OK
, "got %08x\n", hr
);
2639 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2640 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2641 VariantClear(&dest
);
2643 ISAXContentHandler_Release(content
);
2644 IMXWriter_Release(writer
);
2656 struct writer_startendelement_t
{
2658 enum startendtype type
;
2660 const char *local_name
;
2664 ISAXAttributes
*attr
;
2667 static const char startelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\">";
2668 static const char startendelement_xml
[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"<&">\"/>";
2670 static const struct writer_startendelement_t writer_startendelement
[] = {
2672 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2673 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2674 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2675 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, NULL
, "<>", S_OK
},
2676 { &CLSID_MXXMLWriter
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2678 { &CLSID_MXXMLWriter30
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2679 { &CLSID_MXXMLWriter40
, StartElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2680 { &CLSID_MXXMLWriter60
, StartElement
, "uri", NULL
, NULL
, "<>", S_OK
},
2681 { &CLSID_MXXMLWriter
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2682 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2684 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2685 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, "local", NULL
, "<>", S_OK
},
2686 { &CLSID_MXXMLWriter
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2687 { &CLSID_MXXMLWriter30
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2688 { &CLSID_MXXMLWriter40
, StartElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2690 { &CLSID_MXXMLWriter60
, StartElement
, NULL
, NULL
, "qname", "<qname>", S_OK
},
2691 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2692 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2693 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2694 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "qname", "<qname>", S_OK
},
2696 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2697 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2698 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2699 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", NULL
, "<>", S_OK
},
2700 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2702 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2703 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2704 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", "<uri:local>", S_OK
},
2705 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2706 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2708 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2709 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local2", "<uri:local2>", S_OK
},
2710 /* endElement tests */
2711 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2712 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2713 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, NULL
, NULL
, E_INVALIDARG
},
2715 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, NULL
, "</>", S_OK
},
2716 { &CLSID_MXXMLWriter
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2717 { &CLSID_MXXMLWriter30
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2718 { &CLSID_MXXMLWriter40
, EndElement
, "uri", NULL
, NULL
, NULL
, E_INVALIDARG
},
2719 { &CLSID_MXXMLWriter60
, EndElement
, "uri", NULL
, NULL
, "</>", S_OK
},
2721 { &CLSID_MXXMLWriter
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2722 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2723 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, "local", NULL
, NULL
, E_INVALIDARG
},
2724 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, "local", NULL
, "</>", S_OK
},
2725 { &CLSID_MXXMLWriter
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2727 { &CLSID_MXXMLWriter30
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2728 { &CLSID_MXXMLWriter40
, EndElement
, NULL
, NULL
, "qname", NULL
, E_INVALIDARG
},
2729 { &CLSID_MXXMLWriter60
, EndElement
, NULL
, NULL
, "qname", "</qname>", S_OK
},
2730 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2731 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2733 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2734 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "qname", "</qname>", S_OK
},
2735 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2736 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2737 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", NULL
, NULL
, E_INVALIDARG
},
2739 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", NULL
, "</>", S_OK
},
2740 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2741 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2742 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2743 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local", "</uri:local>", S_OK
},
2745 { &CLSID_MXXMLWriter
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2746 { &CLSID_MXXMLWriter30
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2747 { &CLSID_MXXMLWriter40
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2748 { &CLSID_MXXMLWriter60
, EndElement
, "uri", "local", "uri:local2", "</uri:local2>", S_OK
},
2750 /* with attributes */
2751 { &CLSID_MXXMLWriter
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
2753 { &CLSID_MXXMLWriter30
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
2754 { &CLSID_MXXMLWriter40
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
2755 { &CLSID_MXXMLWriter60
, StartElement
, "uri", "local", "uri:local", startelement_xml
, S_OK
, &saxattributes
},
2756 /* empty elements */
2757 { &CLSID_MXXMLWriter
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
2758 { &CLSID_MXXMLWriter30
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
2760 { &CLSID_MXXMLWriter40
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
2761 { &CLSID_MXXMLWriter60
, StartEndElement
, "uri", "local", "uri:local", startendelement_xml
, S_OK
, &saxattributes
},
2762 { &CLSID_MXXMLWriter
, StartEndElement
, "", "", "", "</>", S_OK
},
2763 { &CLSID_MXXMLWriter30
, StartEndElement
, "", "", "", "</>", S_OK
},
2764 { &CLSID_MXXMLWriter40
, StartEndElement
, "", "", "", "</>", S_OK
},
2766 { &CLSID_MXXMLWriter60
, StartEndElement
, "", "", "", "</>", S_OK
},
2770 static void get_class_support_data(struct msxmlsupported_data_t
*table
, REFIID riid
)
2772 while (table
->clsid
)
2777 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
, riid
, (void**)&unk
);
2778 if (hr
== S_OK
) IUnknown_Release(unk
);
2780 table
->supported
= hr
== S_OK
;
2781 if (hr
!= S_OK
) win_skip("class %s not supported\n", table
->name
);
2787 static void test_mxwriter_startendelement_batch(const struct writer_startendelement_t
*table
)
2791 while (table
->clsid
)
2793 ISAXContentHandler
*content
;
2797 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
2804 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
2805 &IID_IMXWriter
, (void**)&writer
);
2806 EXPECT_HR(hr
, S_OK
);
2808 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2809 EXPECT_HR(hr
, S_OK
);
2811 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2812 EXPECT_HR(hr
, S_OK
);
2814 hr
= ISAXContentHandler_startDocument(content
);
2815 EXPECT_HR(hr
, S_OK
);
2817 if (table
->type
== StartElement
)
2819 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
2820 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
), table
->attr
);
2821 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
2823 else if (table
->type
== EndElement
)
2825 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
2826 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
));
2827 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
2831 hr
= ISAXContentHandler_startElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
2832 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
), table
->attr
);
2833 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
2834 hr
= ISAXContentHandler_endElement(content
, _bstr_(table
->uri
), lstrlen(table
->uri
),
2835 _bstr_(table
->local_name
), lstrlen(table
->local_name
), _bstr_(table
->qname
), lstrlen(table
->qname
));
2836 ok(hr
== table
->hr
, "test %d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
2844 V_VT(&dest
) = VT_EMPTY
;
2845 hr
= IMXWriter_get_output(writer
, &dest
);
2846 EXPECT_HR(hr
, S_OK
);
2847 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2848 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
2849 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
2850 VariantClear(&dest
);
2853 ISAXContentHandler_Release(content
);
2854 IMXWriter_Release(writer
);
2863 static void test_mxwriter_startendelement(void)
2865 ISAXContentHandler
*content
;
2870 test_mxwriter_startendelement_batch(writer_startendelement
);
2872 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2873 &IID_IMXWriter
, (void**)&writer
);
2874 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2876 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2877 ok(hr
== S_OK
, "got %08x\n", hr
);
2879 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
2880 ok(hr
== S_OK
, "got %08x\n", hr
);
2882 hr
= ISAXContentHandler_startDocument(content
);
2883 ok(hr
== S_OK
, "got %08x\n", hr
);
2885 /* all string pointers should be not null */
2886 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL
);
2887 ok(hr
== S_OK
, "got %08x\n", hr
);
2889 V_VT(&dest
) = VT_EMPTY
;
2890 hr
= IMXWriter_get_output(writer
, &dest
);
2891 ok(hr
== S_OK
, "got %08x\n", hr
);
2892 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2893 ok(!lstrcmpW(_bstr_("<>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2894 VariantClear(&dest
);
2896 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL
);
2897 ok(hr
== S_OK
, "got %08x\n", hr
);
2899 V_VT(&dest
) = VT_EMPTY
;
2900 hr
= IMXWriter_get_output(writer
, &dest
);
2901 ok(hr
== S_OK
, "got %08x\n", hr
);
2902 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2903 ok(!lstrcmpW(_bstr_("<><b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2904 VariantClear(&dest
);
2906 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, NULL
, 0, _bstr_("a:b"), 3);
2907 EXPECT_HR(hr
, E_INVALIDARG
);
2909 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, _bstr_("a:b"), 3);
2910 EXPECT_HR(hr
, E_INVALIDARG
);
2912 /* only local name is an error too */
2913 hr
= ISAXContentHandler_endElement(content
, NULL
, 0, _bstr_("b"), 1, NULL
, 0);
2914 EXPECT_HR(hr
, E_INVALIDARG
);
2916 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1);
2917 EXPECT_HR(hr
, S_OK
);
2919 V_VT(&dest
) = VT_EMPTY
;
2920 hr
= IMXWriter_get_output(writer
, &dest
);
2921 EXPECT_HR(hr
, S_OK
);
2922 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2923 ok(!lstrcmpW(_bstr_("<><b></b>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2924 VariantClear(&dest
);
2926 hr
= ISAXContentHandler_endDocument(content
);
2927 EXPECT_HR(hr
, S_OK
);
2929 V_VT(&dest
) = VT_EMPTY
;
2930 hr
= IMXWriter_put_output(writer
, dest
);
2931 EXPECT_HR(hr
, S_OK
);
2933 V_VT(&dest
) = VT_EMPTY
;
2934 hr
= IMXWriter_get_output(writer
, &dest
);
2935 EXPECT_HR(hr
, S_OK
);
2936 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2937 ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2938 VariantClear(&dest
);
2940 hr
= ISAXContentHandler_startDocument(content
);
2941 EXPECT_HR(hr
, S_OK
);
2943 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL
);
2944 EXPECT_HR(hr
, S_OK
);
2946 V_VT(&dest
) = VT_EMPTY
;
2947 hr
= IMXWriter_get_output(writer
, &dest
);
2948 EXPECT_HR(hr
, S_OK
);
2949 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2950 ok(!lstrcmpW(_bstr_("<abc>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2951 VariantClear(&dest
);
2953 ISAXContentHandler_endDocument(content
);
2954 IMXWriter_flush(writer
);
2956 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3);
2957 EXPECT_HR(hr
, S_OK
);
2958 V_VT(&dest
) = VT_EMPTY
;
2959 hr
= IMXWriter_get_output(writer
, &dest
);
2960 EXPECT_HR(hr
, S_OK
);
2961 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
2962 ok(!lstrcmpW(_bstr_("<abc></abd>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
2963 VariantClear(&dest
);
2965 ISAXContentHandler_Release(content
);
2966 IMXWriter_Release(writer
);
2970 struct writer_characters_t
{
2976 static const struct writer_characters_t writer_characters
[] = {
2977 { &CLSID_MXXMLWriter
, "< > & \"", "< > & \"" },
2978 { &CLSID_MXXMLWriter30
, "< > & \"", "< > & \"" },
2979 { &CLSID_MXXMLWriter40
, "< > & \"", "< > & \"" },
2980 { &CLSID_MXXMLWriter60
, "< > & \"", "< > & \"" },
2984 static void test_mxwriter_characters(void)
2986 static const WCHAR chardataW
[] = {'T','E','S','T','C','H','A','R','D','A','T','A',' ','.',0};
2987 const struct writer_characters_t
*table
= writer_characters
;
2988 ISAXContentHandler
*content
;
2994 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
2995 &IID_IMXWriter
, (void**)&writer
);
2996 EXPECT_HR(hr
, S_OK
);
2998 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
2999 EXPECT_HR(hr
, S_OK
);
3001 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3002 EXPECT_HR(hr
, S_OK
);
3004 hr
= ISAXContentHandler_startDocument(content
);
3005 EXPECT_HR(hr
, S_OK
);
3007 hr
= ISAXContentHandler_characters(content
, NULL
, 0);
3008 EXPECT_HR(hr
, E_INVALIDARG
);
3010 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3011 EXPECT_HR(hr
, S_OK
);
3013 hr
= ISAXContentHandler_characters(content
, chardataW
, sizeof(chardataW
)/sizeof(WCHAR
) - 1);
3014 EXPECT_HR(hr
, S_OK
);
3016 V_VT(&dest
) = VT_EMPTY
;
3017 hr
= IMXWriter_get_output(writer
, &dest
);
3018 EXPECT_HR(hr
, S_OK
);
3019 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3020 ok(!lstrcmpW(_bstr_("TESTCHARDATA ."), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3021 VariantClear(&dest
);
3023 hr
= ISAXContentHandler_endDocument(content
);
3024 EXPECT_HR(hr
, S_OK
);
3026 ISAXContentHandler_Release(content
);
3027 IMXWriter_Release(writer
);
3029 /* try empty characters data to see if element is closed */
3030 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3031 &IID_IMXWriter
, (void**)&writer
);
3032 EXPECT_HR(hr
, S_OK
);
3034 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3035 EXPECT_HR(hr
, S_OK
);
3037 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3038 EXPECT_HR(hr
, S_OK
);
3040 hr
= ISAXContentHandler_startDocument(content
);
3041 EXPECT_HR(hr
, S_OK
);
3043 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3044 EXPECT_HR(hr
, S_OK
);
3046 hr
= ISAXContentHandler_characters(content
, chardataW
, 0);
3047 EXPECT_HR(hr
, S_OK
);
3049 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3050 EXPECT_HR(hr
, S_OK
);
3052 V_VT(&dest
) = VT_EMPTY
;
3053 hr
= IMXWriter_get_output(writer
, &dest
);
3054 EXPECT_HR(hr
, S_OK
);
3055 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3056 ok(!lstrcmpW(_bstr_("<a></a>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3057 VariantClear(&dest
);
3059 ISAXContentHandler_Release(content
);
3060 IMXWriter_Release(writer
);
3063 while (table
->clsid
)
3065 ISAXContentHandler
*content
;
3069 if (!is_clsid_supported(table
->clsid
, mxwriter_support_data
))
3076 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3077 &IID_IMXWriter
, (void**)&writer
);
3078 EXPECT_HR(hr
, S_OK
);
3080 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3081 EXPECT_HR(hr
, S_OK
);
3083 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3084 EXPECT_HR(hr
, S_OK
);
3086 hr
= ISAXContentHandler_startDocument(content
);
3087 EXPECT_HR(hr
, S_OK
);
3089 hr
= ISAXContentHandler_characters(content
, _bstr_(table
->data
), strlen(table
->data
));
3090 EXPECT_HR(hr
, S_OK
);
3097 V_VT(&dest
) = VT_EMPTY
;
3098 hr
= IMXWriter_get_output(writer
, &dest
);
3099 EXPECT_HR(hr
, S_OK
);
3100 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3101 ok(!lstrcmpW(_bstr_(table
->output
), V_BSTR(&dest
)),
3102 "test %d: got wrong content %s, expected %s\n", i
, wine_dbgstr_w(V_BSTR(&dest
)), table
->output
);
3103 VariantClear(&dest
);
3113 static const mxwriter_stream_test mxwriter_stream_tests
[] = {
3115 VARIANT_TRUE
,"UTF-16",
3117 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3118 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3123 VARIANT_FALSE
,"UTF-16",
3125 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3130 VARIANT_TRUE
,"UTF-8",
3132 {FALSE
,(const BYTE
*)szUtf8XML
,sizeof(szUtf8XML
)-1},
3133 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3134 * and the writer is released.
3141 VARIANT_TRUE
,"utf-8",
3143 {FALSE
,(const BYTE
*)utf8xml2
,sizeof(utf8xml2
)-1},
3144 /* For some reason Windows makes an empty write call when UTF-8 encoding is used
3145 * and the writer is released.
3152 VARIANT_TRUE
,"UTF-16",
3154 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
},
3155 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3160 VARIANT_TRUE
,"UTF-16",
3162 {FALSE
,(const BYTE
*)szUtf16BOM
,sizeof(szUtf16BOM
),TRUE
,TRUE
},
3163 {FALSE
,(const BYTE
*)szUtf16XML
,sizeof(szUtf16XML
)},
3169 static void test_mxwriter_stream(void)
3172 ISAXContentHandler
*content
;
3177 ULARGE_INTEGER pos2
;
3178 DWORD test_count
= sizeof(mxwriter_stream_tests
)/sizeof(mxwriter_stream_tests
[0]);
3180 for(current_stream_test_index
= 0; current_stream_test_index
< test_count
; ++current_stream_test_index
) {
3181 const mxwriter_stream_test
*test
= mxwriter_stream_tests
+current_stream_test_index
;
3183 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3184 &IID_IMXWriter
, (void**)&writer
);
3185 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
3187 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3188 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
3190 hr
= IMXWriter_put_encoding(writer
, _bstr_(test
->encoding
));
3191 ok(hr
== S_OK
, "put_encoding failed with %08x on test %d\n", hr
, current_stream_test_index
);
3193 V_VT(&dest
) = VT_UNKNOWN
;
3194 V_UNKNOWN(&dest
) = (IUnknown
*)&mxstream
;
3195 hr
= IMXWriter_put_output(writer
, dest
);
3196 ok(hr
== S_OK
, "put_output failed with %08x on test %d\n", hr
, current_stream_test_index
);
3197 VariantClear(&dest
);
3199 hr
= IMXWriter_put_byteOrderMark(writer
, test
->bom
);
3200 ok(hr
== S_OK
, "put_byteOrderMark failed with %08x on test %d\n", hr
, current_stream_test_index
);
3202 current_write_test
= test
->expected_writes
;
3204 hr
= ISAXContentHandler_startDocument(content
);
3205 ok(hr
== S_OK
, "startDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
3207 hr
= ISAXContentHandler_endDocument(content
);
3208 ok(hr
== S_OK
, "endDocument failed with %08x on test %d\n", hr
, current_stream_test_index
);
3210 ISAXContentHandler_Release(content
);
3211 IMXWriter_Release(writer
);
3213 ok(current_write_test
->last
, "The last %d write calls on test %d were missed\n",
3214 (int)(current_write_test
-test
->expected_writes
), current_stream_test_index
);
3217 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3218 &IID_IMXWriter
, (void**)&writer
);
3219 ok(hr
== S_OK
, "CoCreateInstance failed: %08x\n", hr
);
3221 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3222 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hr
);
3224 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3225 ok(hr
== S_OK
, "QueryInterface(ISAXContentHandler) failed: %08x\n", hr
);
3227 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
3228 ok(hr
== S_OK
, "put_encoding failed: %08x\n", hr
);
3230 V_VT(&dest
) = VT_UNKNOWN
;
3231 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3232 hr
= IMXWriter_put_output(writer
, dest
);
3233 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
3235 hr
= ISAXContentHandler_startDocument(content
);
3236 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
3238 /* Setting output of the mxwriter causes the current output to be flushed,
3239 * and the writer to start over.
3241 V_VT(&dest
) = VT_EMPTY
;
3242 hr
= IMXWriter_put_output(writer
, dest
);
3243 ok(hr
== S_OK
, "put_output failed: %08x\n", hr
);
3246 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3247 ok(hr
== S_OK
, "Seek failed: %08x\n", hr
);
3248 ok(pos2
.QuadPart
!= 0, "expected stream position moved\n");
3250 hr
= ISAXContentHandler_startDocument(content
);
3251 ok(hr
== S_OK
, "startDocument failed: %08x\n", hr
);
3253 hr
= ISAXContentHandler_endDocument(content
);
3254 ok(hr
== S_OK
, "endDocument failed: %08x\n", hr
);
3256 V_VT(&dest
) = VT_EMPTY
;
3257 hr
= IMXWriter_get_output(writer
, &dest
);
3258 ok(hr
== S_OK
, "get_output failed: %08x\n", hr
);
3259 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
3260 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3261 "Got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3262 VariantClear(&dest
);
3264 /* test when BOM is written to output stream */
3265 V_VT(&dest
) = VT_EMPTY
;
3266 hr
= IMXWriter_put_output(writer
, dest
);
3267 EXPECT_HR(hr
, S_OK
);
3270 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_SET
, NULL
);
3271 EXPECT_HR(hr
, S_OK
);
3273 V_VT(&dest
) = VT_UNKNOWN
;
3274 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3275 hr
= IMXWriter_put_output(writer
, dest
);
3276 EXPECT_HR(hr
, S_OK
);
3278 hr
= IMXWriter_put_byteOrderMark(writer
, VARIANT_TRUE
);
3279 EXPECT_HR(hr
, S_OK
);
3281 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
3282 EXPECT_HR(hr
, S_OK
);
3284 hr
= ISAXContentHandler_startDocument(content
);
3285 EXPECT_HR(hr
, S_OK
);
3289 hr
= IStream_Seek(stream
, pos
, STREAM_SEEK_CUR
, &pos2
);
3290 EXPECT_HR(hr
, S_OK
);
3291 ok(pos2
.QuadPart
== 2, "got wrong position\n");
3293 ISAXContentHandler_Release(content
);
3294 IMXWriter_Release(writer
);
3299 static void test_mxwriter_encoding(void)
3301 ISAXContentHandler
*content
;
3310 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3311 &IID_IMXWriter
, (void**)&writer
);
3312 EXPECT_HR(hr
, S_OK
);
3314 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3315 EXPECT_HR(hr
, S_OK
);
3317 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
3318 EXPECT_HR(hr
, S_OK
);
3320 hr
= ISAXContentHandler_startDocument(content
);
3321 EXPECT_HR(hr
, S_OK
);
3323 hr
= ISAXContentHandler_endDocument(content
);
3324 EXPECT_HR(hr
, S_OK
);
3326 /* The content is always re-encoded to UTF-16 when the output is
3327 * retrieved as a BSTR.
3329 V_VT(&dest
) = VT_EMPTY
;
3330 hr
= IMXWriter_get_output(writer
, &dest
);
3331 EXPECT_HR(hr
, S_OK
);
3332 ok(V_VT(&dest
) == VT_BSTR
, "Expected VT_BSTR, got %d\n", V_VT(&dest
));
3333 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest
)),
3334 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3335 VariantClear(&dest
);
3337 /* switch encoding when something is written already */
3338 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3339 EXPECT_HR(hr
, S_OK
);
3341 V_VT(&dest
) = VT_UNKNOWN
;
3342 V_UNKNOWN(&dest
) = (IUnknown
*)stream
;
3343 hr
= IMXWriter_put_output(writer
, dest
);
3344 EXPECT_HR(hr
, S_OK
);
3346 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-8"));
3347 EXPECT_HR(hr
, S_OK
);
3349 /* write empty element */
3350 hr
= ISAXContentHandler_startElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL
);
3351 EXPECT_HR(hr
, S_OK
);
3353 hr
= ISAXContentHandler_endElement(content
, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1);
3354 EXPECT_HR(hr
, S_OK
);
3357 hr
= IMXWriter_put_encoding(writer
, _bstr_("UTF-16"));
3358 EXPECT_HR(hr
, S_OK
);
3360 hr
= IMXWriter_flush(writer
);
3361 EXPECT_HR(hr
, S_OK
);
3363 hr
= GetHGlobalFromStream(stream
, &g
);
3364 EXPECT_HR(hr
, S_OK
);
3366 ptr
= GlobalLock(g
);
3367 ok(!strncmp(ptr
, "<a/>", 4), "got %c%c%c%c\n", ptr
[0],ptr
[1],ptr
[2],ptr
[3]);
3370 /* so output is unaffected, encoding name is stored however */
3371 hr
= IMXWriter_get_encoding(writer
, &s
);
3372 EXPECT_HR(hr
, S_OK
);
3373 ok(!lstrcmpW(s
, _bstr_("UTF-16")), "got %s\n", wine_dbgstr_w(s
));
3376 IStream_Release(stream
);
3378 ISAXContentHandler_Release(content
);
3379 IMXWriter_Release(writer
);
3384 static void test_obj_dispex(IUnknown
*obj
)
3386 static const WCHAR starW
[] = {'*',0};
3387 DISPID dispid
= DISPID_SAX_XMLREADER_GETFEATURE
;
3388 IDispatchEx
*dispex
;
3395 hr
= IUnknown_QueryInterface(obj
, &IID_IDispatchEx
, (void**)&dispex
);
3396 EXPECT_HR(hr
, S_OK
);
3397 if (FAILED(hr
)) return;
3400 hr
= IDispatchEx_GetTypeInfoCount(dispex
, &ticnt
);
3401 EXPECT_HR(hr
, S_OK
);
3402 ok(ticnt
== 1, "ticnt=%u\n", ticnt
);
3404 name
= SysAllocString(starW
);
3405 hr
= IDispatchEx_DeleteMemberByName(dispex
, name
, fdexNameCaseSensitive
);
3406 EXPECT_HR(hr
, E_NOTIMPL
);
3407 SysFreeString(name
);
3409 hr
= IDispatchEx_DeleteMemberByDispID(dispex
, dispid
);
3410 EXPECT_HR(hr
, E_NOTIMPL
);
3413 hr
= IDispatchEx_GetMemberProperties(dispex
, dispid
, grfdexPropCanAll
, &props
);
3414 EXPECT_HR(hr
, E_NOTIMPL
);
3415 ok(props
== 0, "expected 0 got %d\n", props
);
3417 hr
= IDispatchEx_GetMemberName(dispex
, dispid
, &name
);
3418 EXPECT_HR(hr
, E_NOTIMPL
);
3419 if (SUCCEEDED(hr
)) SysFreeString(name
);
3421 hr
= IDispatchEx_GetNextDispID(dispex
, fdexEnumDefault
, DISPID_SAX_XMLREADER_GETFEATURE
, &dispid
);
3422 EXPECT_HR(hr
, E_NOTIMPL
);
3424 hr
= IDispatchEx_GetNameSpaceParent(dispex
, &unk
);
3425 EXPECT_HR(hr
, E_NOTIMPL
);
3426 if (hr
== S_OK
&& unk
) IUnknown_Release(unk
);
3428 IDispatchEx_Release(dispex
);
3431 static void test_dispex(void)
3433 IVBSAXXMLReader
*vbreader
;
3434 ISAXXMLReader
*reader
;
3438 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
3439 &IID_ISAXXMLReader
, (void**)&reader
);
3440 EXPECT_HR(hr
, S_OK
);
3442 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IUnknown
, (void**)&unk
);
3443 EXPECT_HR(hr
, S_OK
);
3444 test_obj_dispex(unk
);
3445 IUnknown_Release(unk
);
3447 hr
= ISAXXMLReader_QueryInterface(reader
, &IID_IVBSAXXMLReader
, (void**)&vbreader
);
3448 EXPECT_HR(hr
, S_OK
);
3449 hr
= IVBSAXXMLReader_QueryInterface(vbreader
, &IID_IUnknown
, (void**)&unk
);
3450 EXPECT_HR(hr
, S_OK
);
3451 test_obj_dispex(unk
);
3452 IUnknown_Release(unk
);
3453 IVBSAXXMLReader_Release(vbreader
);
3455 ISAXXMLReader_Release(reader
);
3458 static void test_mxwriter_dispex(void)
3460 IDispatchEx
*dispex
;
3465 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3466 &IID_IMXWriter
, (void**)&writer
);
3467 EXPECT_HR(hr
, S_OK
);
3469 hr
= IMXWriter_QueryInterface(writer
, &IID_IDispatchEx
, (void**)&dispex
);
3470 EXPECT_HR(hr
, S_OK
);
3471 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
3472 test_obj_dispex(unk
);
3473 IUnknown_Release(unk
);
3474 IDispatchEx_Release(dispex
);
3476 IMXWriter_Release(writer
);
3479 static void test_mxwriter_comment(void)
3481 static const WCHAR commentW
[] = {'c','o','m','m','e','n','t',0};
3482 ISAXContentHandler
*content
;
3483 ISAXLexicalHandler
*lexical
;
3488 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3489 &IID_IMXWriter
, (void**)&writer
);
3490 EXPECT_HR(hr
, S_OK
);
3492 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3493 EXPECT_HR(hr
, S_OK
);
3495 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
3496 EXPECT_HR(hr
, S_OK
);
3498 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3499 EXPECT_HR(hr
, S_OK
);
3501 hr
= ISAXContentHandler_startDocument(content
);
3502 EXPECT_HR(hr
, S_OK
);
3504 hr
= ISAXLexicalHandler_comment(lexical
, NULL
, 0);
3505 EXPECT_HR(hr
, E_INVALIDARG
);
3507 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, 0);
3508 EXPECT_HR(hr
, S_OK
);
3510 V_VT(&dest
) = VT_EMPTY
;
3511 hr
= IMXWriter_get_output(writer
, &dest
);
3512 EXPECT_HR(hr
, S_OK
);
3513 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3514 ok(!lstrcmpW(_bstr_("<!---->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3515 VariantClear(&dest
);
3517 hr
= ISAXLexicalHandler_comment(lexical
, commentW
, sizeof(commentW
)/sizeof(WCHAR
)-1);
3518 EXPECT_HR(hr
, S_OK
);
3520 V_VT(&dest
) = VT_EMPTY
;
3521 hr
= IMXWriter_get_output(writer
, &dest
);
3522 EXPECT_HR(hr
, S_OK
);
3523 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3524 ok(!lstrcmpW(_bstr_("<!---->\r\n<!--comment-->\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3525 VariantClear(&dest
);
3527 ISAXContentHandler_Release(content
);
3528 ISAXLexicalHandler_Release(lexical
);
3529 IMXWriter_Release(writer
);
3533 static void test_mxwriter_cdata(void)
3535 ISAXContentHandler
*content
;
3536 ISAXLexicalHandler
*lexical
;
3541 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3542 &IID_IMXWriter
, (void**)&writer
);
3543 EXPECT_HR(hr
, S_OK
);
3545 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3546 EXPECT_HR(hr
, S_OK
);
3548 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
3549 EXPECT_HR(hr
, S_OK
);
3551 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3552 EXPECT_HR(hr
, S_OK
);
3554 hr
= ISAXContentHandler_startDocument(content
);
3555 EXPECT_HR(hr
, S_OK
);
3557 hr
= ISAXLexicalHandler_startCDATA(lexical
);
3558 EXPECT_HR(hr
, S_OK
);
3560 V_VT(&dest
) = VT_EMPTY
;
3561 hr
= IMXWriter_get_output(writer
, &dest
);
3562 EXPECT_HR(hr
, S_OK
);
3563 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3564 ok(!lstrcmpW(_bstr_("<![CDATA["), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3565 VariantClear(&dest
);
3567 hr
= ISAXLexicalHandler_startCDATA(lexical
);
3568 EXPECT_HR(hr
, S_OK
);
3570 /* all these are escaped for text nodes */
3571 hr
= ISAXContentHandler_characters(content
, _bstr_("< > & \""), 7);
3572 EXPECT_HR(hr
, S_OK
);
3574 hr
= ISAXLexicalHandler_endCDATA(lexical
);
3575 EXPECT_HR(hr
, S_OK
);
3577 V_VT(&dest
) = VT_EMPTY
;
3578 hr
= IMXWriter_get_output(writer
, &dest
);
3579 EXPECT_HR(hr
, S_OK
);
3580 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3581 ok(!lstrcmpW(_bstr_("<![CDATA[<![CDATA[< > & \"]]>"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3582 VariantClear(&dest
);
3584 ISAXContentHandler_Release(content
);
3585 ISAXLexicalHandler_Release(lexical
);
3586 IMXWriter_Release(writer
);
3590 static void test_mxwriter_pi(void)
3592 static const WCHAR targetW
[] = {'t','a','r','g','e','t',0};
3593 static const WCHAR dataW
[] = {'d','a','t','a',0};
3594 ISAXContentHandler
*content
;
3599 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3600 &IID_IMXWriter
, (void**)&writer
);
3601 EXPECT_HR(hr
, S_OK
);
3603 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3604 EXPECT_HR(hr
, S_OK
);
3606 hr
= ISAXContentHandler_processingInstruction(content
, NULL
, 0, NULL
, 0);
3607 EXPECT_HR(hr
, E_INVALIDARG
);
3609 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 0, NULL
, 0);
3610 EXPECT_HR(hr
, S_OK
);
3612 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, NULL
, 0);
3613 EXPECT_HR(hr
, S_OK
);
3615 V_VT(&dest
) = VT_EMPTY
;
3616 hr
= IMXWriter_get_output(writer
, &dest
);
3617 EXPECT_HR(hr
, S_OK
);
3618 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3619 ok(!lstrcmpW(_bstr_("<?\?>\r\n<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3620 VariantClear(&dest
);
3622 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 4, dataW
, 4);
3623 EXPECT_HR(hr
, S_OK
);
3625 V_VT(&dest
) = VT_EMPTY
;
3626 hr
= IMXWriter_get_output(writer
, &dest
);
3627 EXPECT_HR(hr
, S_OK
);
3628 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3629 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
)));
3630 VariantClear(&dest
);
3632 V_VT(&dest
) = VT_EMPTY
;
3633 hr
= IMXWriter_put_output(writer
, dest
);
3634 EXPECT_HR(hr
, S_OK
);
3636 hr
= ISAXContentHandler_processingInstruction(content
, targetW
, 6, dataW
, 0);
3637 EXPECT_HR(hr
, S_OK
);
3639 V_VT(&dest
) = VT_EMPTY
;
3640 hr
= IMXWriter_get_output(writer
, &dest
);
3641 EXPECT_HR(hr
, S_OK
);
3642 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3643 ok(!lstrcmpW(_bstr_("<?target?>\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3644 VariantClear(&dest
);
3647 ISAXContentHandler_Release(content
);
3648 IMXWriter_Release(writer
);
3651 static void test_mxwriter_ignorablespaces(void)
3653 static const WCHAR dataW
[] = {'d','a','t','a',0};
3654 ISAXContentHandler
*content
;
3659 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3660 &IID_IMXWriter
, (void**)&writer
);
3661 EXPECT_HR(hr
, S_OK
);
3663 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3664 EXPECT_HR(hr
, S_OK
);
3666 hr
= ISAXContentHandler_ignorableWhitespace(content
, NULL
, 0);
3667 EXPECT_HR(hr
, E_INVALIDARG
);
3669 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 0);
3670 EXPECT_HR(hr
, S_OK
);
3672 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 4);
3673 EXPECT_HR(hr
, S_OK
);
3675 hr
= ISAXContentHandler_ignorableWhitespace(content
, dataW
, 1);
3676 EXPECT_HR(hr
, S_OK
);
3678 V_VT(&dest
) = VT_EMPTY
;
3679 hr
= IMXWriter_get_output(writer
, &dest
);
3680 EXPECT_HR(hr
, S_OK
);
3681 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3682 ok(!lstrcmpW(_bstr_("datad"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3683 VariantClear(&dest
);
3685 ISAXContentHandler_Release(content
);
3686 IMXWriter_Release(writer
);
3689 static void test_mxwriter_dtd(void)
3691 static const WCHAR contentW
[] = {'c','o','n','t','e','n','t'};
3692 static const WCHAR nameW
[] = {'n','a','m','e'};
3693 static const WCHAR pubW
[] = {'p','u','b'};
3694 static const WCHAR sysW
[] = {'s','y','s'};
3695 ISAXContentHandler
*content
;
3696 ISAXLexicalHandler
*lexical
;
3697 ISAXDeclHandler
*decl
;
3702 hr
= CoCreateInstance(&CLSID_MXXMLWriter
, NULL
, CLSCTX_INPROC_SERVER
,
3703 &IID_IMXWriter
, (void**)&writer
);
3704 EXPECT_HR(hr
, S_OK
);
3706 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXContentHandler
, (void**)&content
);
3707 EXPECT_HR(hr
, S_OK
);
3709 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXLexicalHandler
, (void**)&lexical
);
3710 EXPECT_HR(hr
, S_OK
);
3712 hr
= IMXWriter_QueryInterface(writer
, &IID_ISAXDeclHandler
, (void**)&decl
);
3713 EXPECT_HR(hr
, S_OK
);
3715 hr
= IMXWriter_put_omitXMLDeclaration(writer
, VARIANT_TRUE
);
3716 EXPECT_HR(hr
, S_OK
);
3718 hr
= ISAXContentHandler_startDocument(content
);
3719 EXPECT_HR(hr
, S_OK
);
3721 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, NULL
, 0);
3722 EXPECT_HR(hr
, E_INVALIDARG
);
3724 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
3725 EXPECT_HR(hr
, E_INVALIDARG
);
3727 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, NULL
, 0, sysW
, sizeof(sysW
)/sizeof(WCHAR
));
3728 EXPECT_HR(hr
, E_INVALIDARG
);
3730 hr
= ISAXLexicalHandler_startDTD(lexical
, NULL
, 0, pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
3731 EXPECT_HR(hr
, E_INVALIDARG
);
3733 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0, NULL
, 0);
3734 EXPECT_HR(hr
, S_OK
);
3736 V_VT(&dest
) = VT_EMPTY
;
3737 hr
= IMXWriter_get_output(writer
, &dest
);
3738 EXPECT_HR(hr
, S_OK
);
3739 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3740 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3741 VariantClear(&dest
);
3743 /* system id is required if public is present */
3744 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), pubW
, sizeof(pubW
)/sizeof(WCHAR
), NULL
, 0);
3745 EXPECT_HR(hr
, E_INVALIDARG
);
3747 hr
= ISAXLexicalHandler_startDTD(lexical
, nameW
, sizeof(nameW
)/sizeof(WCHAR
),
3748 pubW
, sizeof(pubW
)/sizeof(WCHAR
), sysW
, sizeof(sysW
)/sizeof(WCHAR
));
3749 EXPECT_HR(hr
, S_OK
);
3751 V_VT(&dest
) = VT_EMPTY
;
3752 hr
= IMXWriter_get_output(writer
, &dest
);
3753 EXPECT_HR(hr
, S_OK
);
3754 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3755 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
3756 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n"), V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3757 VariantClear(&dest
);
3759 hr
= ISAXLexicalHandler_endDTD(lexical
);
3760 EXPECT_HR(hr
, S_OK
);
3762 hr
= ISAXLexicalHandler_endDTD(lexical
);
3763 EXPECT_HR(hr
, S_OK
);
3765 V_VT(&dest
) = VT_EMPTY
;
3766 hr
= IMXWriter_get_output(writer
, &dest
);
3767 EXPECT_HR(hr
, S_OK
);
3768 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3769 ok(!lstrcmpW(_bstr_("<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\""
3770 "<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n"),
3771 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3772 VariantClear(&dest
);
3774 /* element declaration */
3775 V_VT(&dest
) = VT_EMPTY
;
3776 hr
= IMXWriter_put_output(writer
, dest
);
3777 EXPECT_HR(hr
, S_OK
);
3779 hr
= ISAXDeclHandler_elementDecl(decl
, NULL
, 0, NULL
, 0);
3780 EXPECT_HR(hr
, E_INVALIDARG
);
3782 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), NULL
, 0);
3783 EXPECT_HR(hr
, E_INVALIDARG
);
3785 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, sizeof(contentW
)/sizeof(WCHAR
));
3786 EXPECT_HR(hr
, S_OK
);
3788 V_VT(&dest
) = VT_EMPTY
;
3789 hr
= IMXWriter_get_output(writer
, &dest
);
3790 EXPECT_HR(hr
, S_OK
);
3791 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3792 ok(!lstrcmpW(_bstr_("<!ELEMENT name content>\r\n"),
3793 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3794 VariantClear(&dest
);
3796 V_VT(&dest
) = VT_EMPTY
;
3797 hr
= IMXWriter_put_output(writer
, dest
);
3798 EXPECT_HR(hr
, S_OK
);
3800 hr
= ISAXDeclHandler_elementDecl(decl
, nameW
, sizeof(nameW
)/sizeof(WCHAR
), contentW
, 0);
3801 EXPECT_HR(hr
, S_OK
);
3803 V_VT(&dest
) = VT_EMPTY
;
3804 hr
= IMXWriter_get_output(writer
, &dest
);
3805 EXPECT_HR(hr
, S_OK
);
3806 ok(V_VT(&dest
) == VT_BSTR
, "got %d\n", V_VT(&dest
));
3807 ok(!lstrcmpW(_bstr_("<!ELEMENT name >\r\n"),
3808 V_BSTR(&dest
)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest
)));
3809 VariantClear(&dest
);
3811 ISAXContentHandler_Release(content
);
3812 ISAXLexicalHandler_Release(lexical
);
3813 ISAXDeclHandler_Release(decl
);
3814 IMXWriter_Release(writer
);
3826 } addattribute_test_t
;
3828 static const addattribute_test_t addattribute_data
[] = {
3829 { &CLSID_SAXAttributes
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
3830 { &CLSID_SAXAttributes30
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
3831 { &CLSID_SAXAttributes40
, NULL
, NULL
, "ns:qname", NULL
, "value", E_INVALIDARG
},
3832 { &CLSID_SAXAttributes60
, NULL
, NULL
, "ns:qname", NULL
, "value", S_OK
},
3834 { &CLSID_SAXAttributes
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
3835 { &CLSID_SAXAttributes30
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
3836 { &CLSID_SAXAttributes40
, NULL
, "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
3837 { &CLSID_SAXAttributes60
, NULL
, "qname", "ns:qname", NULL
, "value", S_OK
},
3839 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
3840 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
3841 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", NULL
, "value", E_INVALIDARG
},
3842 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", NULL
, "value", S_OK
},
3844 { &CLSID_SAXAttributes
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
3845 { &CLSID_SAXAttributes30
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
3846 { &CLSID_SAXAttributes40
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
3847 { &CLSID_SAXAttributes60
, "uri", "qname", "ns:qname", "type", "value", S_OK
},
3852 static void test_mxattr_addAttribute(void)
3854 const addattribute_test_t
*table
= addattribute_data
;
3857 while (table
->clsid
)
3859 ISAXAttributes
*saxattr
;
3860 IMXAttributes
*mxattr
;
3865 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
3872 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
3873 &IID_IMXAttributes
, (void**)&mxattr
);
3874 EXPECT_HR(hr
, S_OK
);
3876 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
3877 EXPECT_HR(hr
, S_OK
);
3879 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
3880 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
3881 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
3883 hr
= ISAXAttributes_getLength(saxattr
, NULL
);
3884 EXPECT_HR(hr
, E_POINTER
);
3888 hr
= ISAXAttributes_getLength(saxattr
, &len
);
3889 EXPECT_HR(hr
, S_OK
);
3890 ok(len
== 0, "got %d\n", len
);
3892 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
3893 EXPECT_HR(hr
, E_INVALIDARG
);
3895 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
3896 EXPECT_HR(hr
, E_INVALIDARG
);
3898 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
3899 EXPECT_HR(hr
, E_INVALIDARG
);
3901 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
3902 EXPECT_HR(hr
, E_INVALIDARG
);
3904 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
3905 EXPECT_HR(hr
, E_INVALIDARG
);
3907 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
3908 EXPECT_HR(hr
, E_INVALIDARG
);
3910 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
3911 EXPECT_HR(hr
, E_INVALIDARG
);
3913 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
3914 EXPECT_HR(hr
, E_INVALIDARG
);
3916 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_(table
->uri
), _bstr_(table
->local
),
3917 _bstr_(table
->qname
), _bstr_(table
->type
), _bstr_(table
->value
));
3918 ok(hr
== table
->hr
, "%d: got 0x%08x, expected 0x%08x\n", i
, hr
, table
->hr
);
3922 /* SAXAttributes40 and SAXAttributes60 both crash on this test */
3923 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
3924 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
3926 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, &len
);
3927 EXPECT_HR(hr
, E_POINTER
);
3929 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, NULL
);
3930 EXPECT_HR(hr
, E_POINTER
);
3932 hr
= ISAXAttributes_getValue(saxattr
, 0, NULL
, NULL
);
3933 EXPECT_HR(hr
, E_POINTER
);
3935 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, &len
);
3936 EXPECT_HR(hr
, E_POINTER
);
3938 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, NULL
);
3939 EXPECT_HR(hr
, E_POINTER
);
3941 hr
= ISAXAttributes_getType(saxattr
, 0, NULL
, NULL
);
3942 EXPECT_HR(hr
, E_POINTER
);
3946 hr
= ISAXAttributes_getValue(saxattr
, 0, &value
, &len
);
3947 EXPECT_HR(hr
, S_OK
);
3948 ok(!lstrcmpW(_bstr_(table
->value
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
3950 ok(lstrlenW(value
) == len
, "%d: got wrong value length %d\n", i
, len
);
3953 value
= (void*)0xdeadbeef;
3954 hr
= ISAXAttributes_getType(saxattr
, 0, &value
, &len
);
3955 EXPECT_HR(hr
, S_OK
);
3959 ok(!lstrcmpW(_bstr_(table
->type
), value
), "%d: got %s, expected %s\n", i
, wine_dbgstr_w(value
),
3961 ok(lstrlenW(value
) == len
, "%d: got wrong type value length %d\n", i
, len
);
3965 ok(*value
== 0, "%d: got type value %s\n", i
, wine_dbgstr_w(value
));
3966 ok(len
== 0, "%d: got wrong type value length %d\n", i
, len
);
3969 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, NULL
);
3970 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
3971 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
3973 EXPECT_HR(hr
, E_POINTER
);
3976 EXPECT_HR(hr
, E_INVALIDARG
);
3978 hr
= ISAXAttributes_getIndexFromQName(saxattr
, NULL
, 0, &index
);
3979 EXPECT_HR(hr
, E_INVALIDARG
);
3982 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_("nonexistent"), 11, &index
);
3983 EXPECT_HR(hr
, E_INVALIDARG
);
3984 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
3987 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), 0, &index
);
3988 EXPECT_HR(hr
, E_INVALIDARG
);
3989 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
3992 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &index
);
3993 EXPECT_HR(hr
, S_OK
);
3994 ok(index
== 0, "%d: got wrong index %d\n", i
, index
);
3997 hr
= ISAXAttributes_getIndexFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
)-1, &index
);
3998 EXPECT_HR(hr
, E_INVALIDARG
);
3999 ok(index
== -1, "%d: got wrong index %d\n", i
, index
);
4001 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes40
) ||
4002 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes60
))
4004 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4005 EXPECT_HR(hr
, E_INVALIDARG
);
4007 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4008 EXPECT_HR(hr
, E_INVALIDARG
);
4010 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4011 EXPECT_HR(hr
, E_INVALIDARG
);
4015 hr
= ISAXAttributes_getValueFromQName(saxattr
, NULL
, 0, NULL
, NULL
);
4016 EXPECT_HR(hr
, E_POINTER
);
4018 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, NULL
, NULL
);
4019 EXPECT_HR(hr
, E_POINTER
);
4021 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), 0, &value
, NULL
);
4022 EXPECT_HR(hr
, E_POINTER
);
4024 /* versions 4 and 6 crash */
4025 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, NULL
);
4026 EXPECT_HR(hr
, E_POINTER
);
4028 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), NULL
, &len
);
4029 EXPECT_HR(hr
, E_POINTER
);
4032 hr
= ISAXAttributes_getValueFromQName(saxattr
, _bstr_(table
->qname
), strlen(table
->qname
), &value
, &len
);
4033 EXPECT_HR(hr
, S_OK
);
4037 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4038 EXPECT_HR(hr
, S_OK
);
4039 if (table
->hr
== S_OK
)
4040 ok(len
== 1, "%d: got %d length, expected 0\n", i
, len
);
4042 ok(len
== 0, "%d: got %d length, expected 1\n", i
, len
);
4044 ISAXAttributes_Release(saxattr
);
4045 IMXAttributes_Release(mxattr
);
4054 static void test_mxattr_clear(void)
4056 ISAXAttributes
*saxattr
;
4057 IMXAttributes
*mxattr
;
4062 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
4063 &IID_IMXAttributes
, (void**)&mxattr
);
4064 EXPECT_HR(hr
, S_OK
);
4066 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4067 EXPECT_HR(hr
, S_OK
);
4069 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, NULL
);
4070 EXPECT_HR(hr
, E_INVALIDARG
);
4072 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
4073 EXPECT_HR(hr
, E_INVALIDARG
);
4075 hr
= IMXAttributes_clear(mxattr
);
4076 EXPECT_HR(hr
, S_OK
);
4078 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("local"),
4079 _bstr_("qname"), _bstr_("type"), _bstr_("value"));
4080 EXPECT_HR(hr
, S_OK
);
4083 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4084 EXPECT_HR(hr
, S_OK
);
4085 ok(len
== 1, "got %d\n", len
);
4088 hr
= ISAXAttributes_getQName(saxattr
, 0, NULL
, &len
);
4089 EXPECT_HR(hr
, E_POINTER
);
4090 ok(len
== -1, "got %d\n", len
);
4092 ptr
= (void*)0xdeadbeef;
4093 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, NULL
);
4094 EXPECT_HR(hr
, E_POINTER
);
4095 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
4098 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
4099 EXPECT_HR(hr
, S_OK
);
4100 ok(len
== 5, "got %d\n", len
);
4101 ok(!lstrcmpW(ptr
, _bstr_("qname")), "got %s\n", wine_dbgstr_w(ptr
));
4103 hr
= IMXAttributes_clear(mxattr
);
4104 EXPECT_HR(hr
, S_OK
);
4107 hr
= ISAXAttributes_getLength(saxattr
, &len
);
4108 EXPECT_HR(hr
, S_OK
);
4109 ok(len
== 0, "got %d\n", len
);
4112 ptr
= (void*)0xdeadbeef;
4113 hr
= ISAXAttributes_getQName(saxattr
, 0, &ptr
, &len
);
4114 EXPECT_HR(hr
, E_INVALIDARG
);
4115 ok(len
== -1, "got %d\n", len
);
4116 ok(ptr
== (void*)0xdeadbeef, "got %p\n", ptr
);
4118 IMXAttributes_Release(mxattr
);
4119 ISAXAttributes_Release(saxattr
);
4123 static void test_mxattr_dispex(void)
4125 IMXAttributes
*mxattr
;
4126 IDispatchEx
*dispex
;
4130 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
4131 &IID_IMXAttributes
, (void**)&mxattr
);
4132 EXPECT_HR(hr
, S_OK
);
4134 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IDispatchEx
, (void**)&dispex
);
4135 EXPECT_HR(hr
, S_OK
);
4136 hr
= IDispatchEx_QueryInterface(dispex
, &IID_IUnknown
, (void**)&unk
);
4137 test_obj_dispex(unk
);
4138 IUnknown_Release(unk
);
4139 IDispatchEx_Release(dispex
);
4141 IMXAttributes_Release(mxattr
);
4144 static void test_mxattr_qi(void)
4146 IVBSAXAttributes
*vbsaxattr
, *vbsaxattr2
;
4147 ISAXAttributes
*saxattr
;
4148 IMXAttributes
*mxattr
;
4151 hr
= CoCreateInstance(&CLSID_SAXAttributes
, NULL
, CLSCTX_INPROC_SERVER
,
4152 &IID_IMXAttributes
, (void**)&mxattr
);
4153 EXPECT_HR(hr
, S_OK
);
4155 EXPECT_REF(mxattr
, 1);
4156 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4157 EXPECT_HR(hr
, S_OK
);
4159 EXPECT_REF(mxattr
, 2);
4160 EXPECT_REF(saxattr
, 2);
4162 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr
);
4163 EXPECT_HR(hr
, S_OK
);
4165 EXPECT_REF(vbsaxattr
, 3);
4166 EXPECT_REF(mxattr
, 3);
4167 EXPECT_REF(saxattr
, 3);
4169 hr
= ISAXAttributes_QueryInterface(saxattr
, &IID_IVBSAXAttributes
, (void**)&vbsaxattr2
);
4170 EXPECT_HR(hr
, S_OK
);
4172 EXPECT_REF(vbsaxattr
, 4);
4173 EXPECT_REF(mxattr
, 4);
4174 EXPECT_REF(saxattr
, 4);
4176 IMXAttributes_Release(mxattr
);
4177 ISAXAttributes_Release(saxattr
);
4178 IVBSAXAttributes_Release(vbsaxattr
);
4179 IVBSAXAttributes_Release(vbsaxattr2
);
4182 static struct msxmlsupported_data_t saxattr_support_data
[] =
4184 { &CLSID_SAXAttributes
, "SAXAttributes" },
4185 { &CLSID_SAXAttributes30
, "SAXAttributes30" },
4186 { &CLSID_SAXAttributes40
, "SAXAttributes40" },
4187 { &CLSID_SAXAttributes60
, "SAXAttributes60" },
4191 static void test_mxattr_localname(void)
4193 static const WCHAR localname1W
[] = {'l','o','c','a','l','n','a','m','e','1',0};
4194 static const WCHAR localnameW
[] = {'l','o','c','a','l','n','a','m','e',0};
4195 static const WCHAR uri1W
[] = {'u','r','i','1',0};
4196 static const WCHAR uriW
[] = {'u','r','i',0};
4198 const struct msxmlsupported_data_t
*table
= saxattr_support_data
;
4200 while (table
->clsid
)
4202 ISAXAttributes
*saxattr
;
4203 IMXAttributes
*mxattr
;
4207 if (!is_clsid_supported(table
->clsid
, mxattributes_support_data
))
4213 hr
= CoCreateInstance(table
->clsid
, NULL
, CLSCTX_INPROC_SERVER
,
4214 &IID_IMXAttributes
, (void**)&mxattr
);
4215 EXPECT_HR(hr
, S_OK
);
4217 hr
= IMXAttributes_QueryInterface(mxattr
, &IID_ISAXAttributes
, (void**)&saxattr
);
4218 EXPECT_HR(hr
, S_OK
);
4220 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, &index
);
4221 EXPECT_HR(hr
, E_INVALIDARG
);
4223 /* add some ambiguos attribute names */
4224 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
4225 _bstr_("a:localname"), _bstr_(""), _bstr_("value"));
4226 EXPECT_HR(hr
, S_OK
);
4227 hr
= IMXAttributes_addAttribute(mxattr
, _bstr_("uri"), _bstr_("localname"),
4228 _bstr_("b:localname"), _bstr_(""), _bstr_("value"));
4229 EXPECT_HR(hr
, S_OK
);
4232 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localnameW
, lstrlenW(localnameW
), &index
);
4233 EXPECT_HR(hr
, S_OK
);
4234 ok(index
== 0, "%s: got index %d\n", table
->name
, index
);
4237 hr
= ISAXAttributes_getIndexFromName(saxattr
, uri1W
, lstrlenW(uri1W
), localnameW
, lstrlenW(localnameW
), &index
);
4238 EXPECT_HR(hr
, E_INVALIDARG
);
4239 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
4242 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), &index
);
4243 EXPECT_HR(hr
, E_INVALIDARG
);
4244 ok(index
== -1, "%s: got index %d\n", table
->name
, index
);
4246 if (IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes
) ||
4247 IsEqualGUID(table
->clsid
, &CLSID_SAXAttributes30
))
4249 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
4250 EXPECT_HR(hr
, E_POINTER
);
4252 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
4253 EXPECT_HR(hr
, E_POINTER
);
4257 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, NULL
, 0, NULL
);
4258 EXPECT_HR(hr
, E_INVALIDARG
);
4260 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), localname1W
, lstrlenW(localname1W
), NULL
);
4261 EXPECT_HR(hr
, E_INVALIDARG
);
4264 hr
= ISAXAttributes_getIndexFromName(saxattr
, uriW
, lstrlenW(uriW
), NULL
, 0, &index
);
4265 EXPECT_HR(hr
, E_INVALIDARG
);
4267 hr
= ISAXAttributes_getIndexFromName(saxattr
, NULL
, 0, localname1W
, lstrlenW(localname1W
), &index
);
4268 EXPECT_HR(hr
, E_INVALIDARG
);
4272 ISAXAttributes_Release(saxattr
);
4273 IMXAttributes_Release(mxattr
);
4277 START_TEST(saxreader
)
4279 ISAXXMLReader
*reader
;
4282 hr
= CoInitialize(NULL
);
4283 ok(hr
== S_OK
, "failed to init com\n");
4285 hr
= CoCreateInstance(&CLSID_SAXXMLReader
, NULL
, CLSCTX_INPROC_SERVER
,
4286 &IID_ISAXXMLReader
, (void**)&reader
);
4290 skip("Failed to create SAXXMLReader instance\n");
4294 ISAXXMLReader_Release(reader
);
4296 init_call_sequences(sequences
, NUM_CALL_SEQUENCES
);
4298 get_class_support_data(reader_support_data
, &IID_ISAXXMLReader
);
4301 test_saxreader_properties();
4302 test_saxreader_features();
4306 /* MXXMLWriter tests */
4307 get_class_support_data(mxwriter_support_data
, &IID_IMXWriter
);
4308 if (is_clsid_supported(&CLSID_MXXMLWriter
, mxwriter_support_data
))
4310 test_mxwriter_handlers();
4311 test_mxwriter_startenddocument();
4312 test_mxwriter_startendelement();
4313 test_mxwriter_characters();
4314 test_mxwriter_comment();
4315 test_mxwriter_cdata();
4317 test_mxwriter_ignorablespaces();
4318 test_mxwriter_dtd();
4319 test_mxwriter_properties();
4320 test_mxwriter_flush();
4321 test_mxwriter_stream();
4322 test_mxwriter_encoding();
4323 test_mxwriter_dispex();
4326 win_skip("MXXMLWriter not supported\n");
4328 /* SAXAttributes tests */
4329 get_class_support_data(mxattributes_support_data
, &IID_IMXAttributes
);
4330 if (is_clsid_supported(&CLSID_SAXAttributes
, mxattributes_support_data
))
4333 test_mxattr_addAttribute();
4334 test_mxattr_clear();
4335 test_mxattr_localname();
4336 test_mxattr_dispex();
4339 skip("SAXAttributes not supported\n");