2 * Copyright 2015, 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "webservices_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
32 const char *debugstr_xmlstr( const WS_XML_STRING
*str
)
34 if (!str
) return "(null)";
35 return debugstr_an( (const char *)str
->bytes
, str
->length
);
38 ULONG
prop_size( const struct prop_desc
*desc
, ULONG count
)
40 ULONG i
, ret
= count
* sizeof(struct prop
);
41 for (i
= 0; i
< count
; i
++) ret
+= desc
[i
].size
;
45 void prop_init( const struct prop_desc
*desc
, ULONG count
, struct prop
*prop
, void *data
)
49 for (i
= 0; i
< count
; i
++)
52 prop
[i
].size
= desc
[i
].size
;
53 prop
[i
].readonly
= desc
[i
].readonly
;
54 prop
[i
].writeonly
= desc
[i
].writeonly
;
59 HRESULT
prop_set( const struct prop
*prop
, ULONG count
, ULONG id
, const void *value
, ULONG size
)
61 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].readonly
) return E_INVALIDARG
;
62 memcpy( prop
[id
].value
, value
, size
);
66 HRESULT
prop_get( const struct prop
*prop
, ULONG count
, ULONG id
, void *buf
, ULONG size
)
68 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].writeonly
) return E_INVALIDARG
;
69 memcpy( buf
, prop
[id
].value
, prop
[id
].size
);
73 static CRITICAL_SECTION dict_cs
;
74 static CRITICAL_SECTION_DEBUG dict_cs_debug
=
77 {&dict_cs_debug
.ProcessLocksList
,
78 &dict_cs_debug
.ProcessLocksList
},
79 0, 0, {(DWORD_PTR
)(__FILE__
": dict_cs")}
81 static CRITICAL_SECTION dict_cs
= {&dict_cs_debug
, -1, 0, 0, 0, 0};
83 static ULONG dict_size
, *dict_sorted
;
84 static WS_XML_DICTIONARY dict_builtin
=
86 {0x82704485,0x222a,0x4f7c,{0xb9,0x7b,0xe9,0xa4,0x62,0xa9,0x66,0x2b}}
89 /**************************************************************************
90 * WsGetDictionary [webservices.@]
92 HRESULT WINAPI
WsGetDictionary( WS_ENCODING encoding
, WS_XML_DICTIONARY
**dict
, WS_ERROR
*error
)
94 TRACE( "%u %p %p\n", encoding
, dict
, error
);
95 if (error
) FIXME( "ignoring error parameter\n" );
97 if (!dict
) return E_INVALIDARG
;
99 if (encoding
== WS_ENCODING_XML_BINARY_1
|| encoding
== WS_ENCODING_XML_BINARY_SESSION_1
)
100 *dict
= &dict_builtin
;
107 static inline int cmp_string( const unsigned char *str
, ULONG len
, const unsigned char *str2
, ULONG len2
)
109 if (len
< len2
) return -1;
110 else if (len
> len2
) return 1;
113 if (*str
== *str2
) { str
++; str2
++; }
114 else return *str
- *str2
;
119 /* return -1 and string id if found, sort index if not found */
120 static int find_string( const unsigned char *data
, ULONG len
, ULONG
*id
)
122 int i
, c
, min
= 0, max
= dict_builtin
.stringCount
- 1;
126 c
= cmp_string( data
, len
,
127 dict_builtin
.strings
[dict_sorted
[i
]].bytes
,
128 dict_builtin
.strings
[dict_sorted
[i
]].length
);
135 *id
= dict_builtin
.strings
[dict_sorted
[i
]].id
;
142 #define MIN_DICTIONARY_SIZE 256
143 #define MAX_DICTIONARY_SIZE 2048
145 static BOOL
grow_dict( ULONG size
)
148 ULONG new_size
, *tmp_sorted
;
150 if (dict_size
>= dict_builtin
.stringCount
+ size
) return TRUE
;
151 if (dict_size
+ size
> MAX_DICTIONARY_SIZE
) return FALSE
;
153 if (!dict_builtin
.strings
)
155 new_size
= max( MIN_DICTIONARY_SIZE
, size
);
156 if (!(dict_builtin
.strings
= heap_alloc( new_size
* sizeof(WS_XML_STRING
) ))) return FALSE
;
157 if (!(dict_sorted
= heap_alloc( new_size
* sizeof(ULONG
) )))
159 heap_free( dict_builtin
.strings
);
160 dict_builtin
.strings
= NULL
;
163 dict_size
= new_size
;
167 new_size
= max( dict_size
* 2, size
);
168 if (!(tmp
= heap_realloc( dict_builtin
.strings
, new_size
* sizeof(*tmp
) ))) return FALSE
;
169 dict_builtin
.strings
= tmp
;
170 if (!(tmp_sorted
= heap_realloc( dict_sorted
, new_size
* sizeof(*tmp_sorted
) ))) return FALSE
;
171 dict_sorted
= tmp_sorted
;
173 dict_size
= new_size
;
177 static BOOL
insert_string( unsigned char *data
, ULONG len
, int i
, ULONG
*ret_id
)
179 ULONG id
= dict_builtin
.stringCount
;
180 if (!grow_dict( 1 )) return FALSE
;
181 memmove( &dict_sorted
[i
] + 1, &dict_sorted
[i
], (dict_builtin
.stringCount
- i
) * sizeof(WS_XML_STRING
*) );
184 dict_builtin
.strings
[id
].length
= len
;
185 dict_builtin
.strings
[id
].bytes
= data
;
186 dict_builtin
.strings
[id
].dictionary
= &dict_builtin
;
187 dict_builtin
.strings
[id
].id
= id
;
188 dict_builtin
.stringCount
++;
193 static HRESULT
add_xml_string( WS_XML_STRING
*str
)
198 if (str
->dictionary
) return S_OK
;
200 EnterCriticalSection( &dict_cs
);
201 if ((index
= find_string( str
->bytes
, str
->length
, &id
)) == -1)
203 heap_free( str
->bytes
);
204 *str
= dict_builtin
.strings
[id
];
205 LeaveCriticalSection( &dict_cs
);
208 if (insert_string( str
->bytes
, str
->length
, index
, &id
))
210 *str
= dict_builtin
.strings
[id
];
211 LeaveCriticalSection( &dict_cs
);
214 LeaveCriticalSection( &dict_cs
);
215 return WS_E_QUOTA_EXCEEDED
;
218 WS_XML_STRING
*alloc_xml_string( const unsigned char *data
, ULONG len
)
222 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
223 if ((ret
->length
= len
) && !(ret
->bytes
= heap_alloc( len
)))
230 memcpy( ret
->bytes
, data
, len
);
231 if (add_xml_string( ret
) != S_OK
) WARN( "string not added to dictionary\n" );
236 void free_xml_string( WS_XML_STRING
*str
)
239 if (!str
->dictionary
) heap_free( str
->bytes
);
243 WS_XML_STRING
*dup_xml_string( const WS_XML_STRING
*src
)
250 if (!(ret
= heap_alloc( sizeof(*ret
) ))) return NULL
;
257 EnterCriticalSection( &dict_cs
);
258 if ((index
= find_string( src
->bytes
, src
->length
, &id
)) == -1)
260 *ret
= dict_builtin
.strings
[id
];
261 LeaveCriticalSection( &dict_cs
);
264 if (!(data
= heap_alloc( src
->length
)))
267 LeaveCriticalSection( &dict_cs
);
270 memcpy( data
, src
->bytes
, src
->length
);
271 if (insert_string( data
, src
->length
, index
, &id
))
273 *ret
= dict_builtin
.strings
[id
];
274 LeaveCriticalSection( &dict_cs
);
277 LeaveCriticalSection( &dict_cs
);
279 WARN( "string not added to dictionary\n" );
280 ret
->length
= src
->length
;
282 ret
->dictionary
= NULL
;
287 struct node
*alloc_node( WS_XML_NODE_TYPE type
)
291 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
292 ret
->hdr
.node
.nodeType
= type
;
293 list_init( &ret
->entry
);
294 list_init( &ret
->children
);
298 void free_attribute( WS_XML_ATTRIBUTE
*attr
)
301 free_xml_string( attr
->prefix
);
302 free_xml_string( attr
->localName
);
303 free_xml_string( attr
->ns
);
304 heap_free( attr
->value
);
308 void free_node( struct node
*node
)
311 switch (node_type( node
))
313 case WS_XML_NODE_TYPE_ELEMENT
:
315 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
318 for (i
= 0; i
< elem
->attributeCount
; i
++) free_attribute( elem
->attributes
[i
] );
319 heap_free( elem
->attributes
);
320 free_xml_string( elem
->prefix
);
321 free_xml_string( elem
->localName
);
322 free_xml_string( elem
->ns
);
325 case WS_XML_NODE_TYPE_TEXT
:
327 WS_XML_TEXT_NODE
*text
= (WS_XML_TEXT_NODE
*)node
;
328 heap_free( text
->text
);
331 case WS_XML_NODE_TYPE_COMMENT
:
333 WS_XML_COMMENT_NODE
*comment
= (WS_XML_COMMENT_NODE
*)node
;
334 heap_free( comment
->value
.bytes
);
337 case WS_XML_NODE_TYPE_CDATA
:
338 case WS_XML_NODE_TYPE_END_CDATA
:
339 case WS_XML_NODE_TYPE_END_ELEMENT
:
340 case WS_XML_NODE_TYPE_EOF
:
341 case WS_XML_NODE_TYPE_BOF
:
345 ERR( "unhandled type %u\n", node_type( node
) );
351 void destroy_nodes( struct node
*node
)
356 while ((ptr
= list_head( &node
->children
)))
358 struct node
*child
= LIST_ENTRY( ptr
, struct node
, entry
);
359 list_remove( &child
->entry
);
360 destroy_nodes( child
);
365 static WS_XML_ATTRIBUTE
*dup_attribute( const WS_XML_ATTRIBUTE
*src
)
367 WS_XML_ATTRIBUTE
*dst
;
368 const WS_XML_STRING
*prefix
= src
->prefix
;
369 const WS_XML_STRING
*localname
= src
->localName
;
370 const WS_XML_STRING
*ns
= src
->localName
;
371 const WS_XML_TEXT
*text
= src
->value
;
373 if (!(dst
= heap_alloc( sizeof(*dst
) ))) return NULL
;
374 dst
->singleQuote
= src
->singleQuote
;
375 dst
->isXmlNs
= src
->isXmlNs
;
377 if (!prefix
) dst
->prefix
= NULL
;
378 else if (!(dst
->prefix
= dup_xml_string( prefix
))) goto error
;
379 if (!(dst
->localName
= dup_xml_string( localname
))) goto error
;
380 if (!(dst
->ns
= dup_xml_string( ns
))) goto error
;
384 WS_XML_UTF8_TEXT
*utf8
;
385 const WS_XML_UTF8_TEXT
*utf8_src
= (const WS_XML_UTF8_TEXT
*)text
;
386 if (!(utf8
= alloc_utf8_text( utf8_src
->value
.bytes
, utf8_src
->value
.length
))) goto error
;
387 dst
->value
= &utf8
->text
;
393 free_attribute( dst
);
397 static WS_XML_ATTRIBUTE
**dup_attributes( WS_XML_ATTRIBUTE
* const *src
, ULONG count
)
399 WS_XML_ATTRIBUTE
**dst
;
402 if (!(dst
= heap_alloc( sizeof(*dst
) * count
))) return NULL
;
403 for (i
= 0; i
< count
; i
++)
405 if (!(dst
[i
] = dup_attribute( src
[i
] )))
407 for (; i
> 0; i
--) free_attribute( dst
[i
- 1] );
415 static struct node
*dup_element_node( const WS_XML_ELEMENT_NODE
*src
)
418 WS_XML_ELEMENT_NODE
*dst
;
419 ULONG count
= src
->attributeCount
;
420 WS_XML_ATTRIBUTE
**attrs
= src
->attributes
;
421 const WS_XML_STRING
*prefix
= (src
->prefix
&& src
->prefix
->length
) ? src
->prefix
: NULL
;
422 const WS_XML_STRING
*localname
= src
->localName
;
423 const WS_XML_STRING
*ns
= src
->ns
;
425 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
428 if (count
&& !(dst
->attributes
= dup_attributes( attrs
, count
))) goto error
;
429 dst
->attributeCount
= count
;
431 if (prefix
&& !(dst
->prefix
= dup_xml_string( prefix
))) goto error
;
432 if (localname
&& !(dst
->localName
= dup_xml_string( localname
))) goto error
;
433 if (ns
&& !(dst
->ns
= dup_xml_string( ns
))) goto error
;
441 static struct node
*dup_text_node( const WS_XML_TEXT_NODE
*src
)
444 WS_XML_TEXT_NODE
*dst
;
446 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
447 dst
= (WS_XML_TEXT_NODE
*)node
;
451 WS_XML_UTF8_TEXT
*utf8
;
452 const WS_XML_UTF8_TEXT
*utf8_src
= (const WS_XML_UTF8_TEXT
*)src
->text
;
453 if (!(utf8
= alloc_utf8_text( utf8_src
->value
.bytes
, utf8_src
->value
.length
)))
458 dst
->text
= &utf8
->text
;
463 static struct node
*dup_comment_node( const WS_XML_COMMENT_NODE
*src
)
466 WS_XML_COMMENT_NODE
*dst
;
468 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return NULL
;
469 dst
= (WS_XML_COMMENT_NODE
*)node
;
471 if (src
->value
.length
&& !(dst
->value
.bytes
= heap_alloc( src
->value
.length
)))
476 memcpy( dst
->value
.bytes
, src
->value
.bytes
, src
->value
.length
);
477 dst
->value
.length
= src
->value
.length
;
481 static struct node
*dup_node( const struct node
*src
)
483 switch (node_type( src
))
485 case WS_XML_NODE_TYPE_ELEMENT
:
486 return dup_element_node( &src
->hdr
);
488 case WS_XML_NODE_TYPE_TEXT
:
489 return dup_text_node( (const WS_XML_TEXT_NODE
*)src
);
491 case WS_XML_NODE_TYPE_COMMENT
:
492 return dup_comment_node( (const WS_XML_COMMENT_NODE
*)src
);
494 case WS_XML_NODE_TYPE_CDATA
:
495 case WS_XML_NODE_TYPE_END_CDATA
:
496 case WS_XML_NODE_TYPE_END_ELEMENT
:
497 case WS_XML_NODE_TYPE_EOF
:
498 case WS_XML_NODE_TYPE_BOF
:
499 return alloc_node( node_type( src
) );
502 ERR( "unhandled type %u\n", node_type( src
) );
508 static HRESULT
dup_tree( struct node
**dst
, const struct node
*src
)
511 const struct node
*child
;
513 if (!*dst
&& !(*dst
= dup_node( src
))) return E_OUTOFMEMORY
;
516 LIST_FOR_EACH_ENTRY( child
, &src
->children
, struct node
, entry
)
518 HRESULT hr
= E_OUTOFMEMORY
;
519 struct node
*new_child
;
521 if (!(new_child
= dup_node( child
)) || (hr
= dup_tree( &new_child
, child
)) != S_OK
)
523 destroy_nodes( *dst
);
526 new_child
->parent
= parent
;
527 list_add_tail( &parent
->children
, &new_child
->entry
);
532 static const struct prop_desc reader_props
[] =
534 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
535 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
536 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
537 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
538 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
539 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
540 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
541 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
542 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
543 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
544 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
545 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
546 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
547 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
548 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
553 READER_STATE_INITIAL
,
555 READER_STATE_STARTELEMENT
,
556 READER_STATE_STARTATTRIBUTE
,
557 READER_STATE_STARTCDATA
,
560 READER_STATE_ENDELEMENT
,
561 READER_STATE_ENDCDATA
,
562 READER_STATE_COMMENT
,
578 const unsigned char *read_bufptr
;
579 enum reader_state state
;
581 struct node
*current
;
584 struct prefix
*prefixes
;
586 ULONG nb_prefixes_allocated
;
587 WS_XML_READER_ENCODING_TYPE input_enc
;
588 WS_XML_READER_INPUT_TYPE input_type
;
589 struct xmlbuf
*input_buf
;
590 const unsigned char *input_data
;
592 ULONG text_conv_offset
;
593 WS_XML_DICTIONARY
*dict
;
595 struct prop prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
598 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
600 static struct reader
*alloc_reader(void)
602 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
604 ULONG size
= sizeof(*ret
) + prop_size( reader_props
, count
);
606 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
607 if (!(ret
->prefixes
= heap_alloc_zero( sizeof(*ret
->prefixes
) )))
612 ret
->nb_prefixes
= ret
->nb_prefixes_allocated
= 1;
614 ret
->magic
= READER_MAGIC
;
615 InitializeCriticalSection( &ret
->cs
);
616 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": reader.cs");
618 prop_init( reader_props
, count
, ret
->prop
, &ret
[1] );
619 ret
->prop_count
= count
;
623 static void clear_prefixes( struct prefix
*prefixes
, ULONG count
)
626 for (i
= 0; i
< count
; i
++)
628 free_xml_string( prefixes
[i
].str
);
629 prefixes
[i
].str
= NULL
;
630 free_xml_string( prefixes
[i
].ns
);
631 prefixes
[i
].ns
= NULL
;
635 static HRESULT
set_prefix( struct prefix
*prefix
, const WS_XML_STRING
*str
, const WS_XML_STRING
*ns
)
639 free_xml_string( prefix
->str
);
640 if (!(prefix
->str
= dup_xml_string( str
))) return E_OUTOFMEMORY
;
642 if (prefix
->ns
) free_xml_string( prefix
->ns
);
643 if (!(prefix
->ns
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
647 static HRESULT
bind_prefix( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
*ns
)
652 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
654 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
655 return set_prefix( &reader
->prefixes
[i
], NULL
, ns
);
657 if (i
>= reader
->nb_prefixes_allocated
)
659 ULONG new_size
= reader
->nb_prefixes_allocated
* sizeof(*reader
->prefixes
) * 2;
660 struct prefix
*tmp
= heap_realloc_zero( reader
->prefixes
, new_size
);
661 if (!tmp
) return E_OUTOFMEMORY
;
662 reader
->prefixes
= tmp
;
663 reader
->nb_prefixes_allocated
*= 2;
665 if ((hr
= set_prefix( &reader
->prefixes
[i
], prefix
, ns
)) != S_OK
) return hr
;
666 reader
->nb_prefixes
++;
670 static const WS_XML_STRING
*get_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
)
673 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
675 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
676 return reader
->prefixes
[i
].ns
;
681 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
683 if (!reader
->root
) reader
->root
= eof
;
686 eof
->parent
= reader
->root
;
687 list_add_tail( &reader
->root
->children
, &eof
->entry
);
689 reader
->current
= reader
->last
= eof
;
692 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
694 reader
->root
->parent
= bof
;
695 list_add_tail( &bof
->children
, &reader
->root
->entry
);
696 reader
->current
= reader
->last
= reader
->root
= bof
;
699 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
701 node
->parent
= parent
;
702 list_add_before( list_tail( &parent
->children
), &node
->entry
);
703 reader
->current
= reader
->last
= node
;
706 static void free_reader( struct reader
*reader
)
708 destroy_nodes( reader
->root
);
709 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
710 heap_free( reader
->prefixes
);
711 reader
->cs
.DebugInfo
->Spare
[0] = 0;
712 DeleteCriticalSection( &reader
->cs
);
716 static HRESULT
init_reader( struct reader
*reader
)
718 static const WS_XML_STRING empty
= {0, NULL
};
722 reader
->state
= READER_STATE_INITIAL
;
723 destroy_nodes( reader
->root
);
724 reader
->root
= reader
->current
= NULL
;
725 reader
->current_attr
= 0;
726 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
727 reader
->nb_prefixes
= 1;
728 if ((hr
= bind_prefix( reader
, &empty
, &empty
)) != S_OK
) return hr
;
730 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
731 read_insert_eof( reader
, node
);
732 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
733 reader
->dict
= &dict_builtin
;
737 /**************************************************************************
738 * WsCreateReader [webservices.@]
740 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
741 WS_XML_READER
**handle
, WS_ERROR
*error
)
743 struct reader
*reader
;
744 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
745 WS_CHARSET charset
= WS_CHARSET_UTF8
;
746 BOOL read_decl
= TRUE
;
749 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
750 if (error
) FIXME( "ignoring error parameter\n" );
752 if (!handle
) return E_INVALIDARG
;
753 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
755 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
756 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
757 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
758 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
759 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
761 for (i
= 0; i
< count
; i
++)
763 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
764 properties
[i
].valueSize
);
767 free_reader( reader
);
772 if ((hr
= init_reader( reader
)) != S_OK
)
774 free_reader( reader
);
778 *handle
= (WS_XML_READER
*)reader
;
782 /**************************************************************************
783 * WsFreeReader [webservices.@]
785 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
787 struct reader
*reader
= (struct reader
*)handle
;
789 TRACE( "%p\n", handle
);
793 EnterCriticalSection( &reader
->cs
);
795 if (reader
->magic
!= READER_MAGIC
)
797 LeaveCriticalSection( &reader
->cs
);
803 LeaveCriticalSection( &reader
->cs
);
804 free_reader( reader
);
807 /**************************************************************************
808 * WsFillReader [webservices.@]
810 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
813 struct reader
*reader
= (struct reader
*)handle
;
815 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
816 if (error
) FIXME( "ignoring error parameter\n" );
818 if (!reader
) return E_INVALIDARG
;
820 EnterCriticalSection( &reader
->cs
);
822 if (reader
->magic
!= READER_MAGIC
)
824 LeaveCriticalSection( &reader
->cs
);
828 /* FIXME: add support for stream input */
829 reader
->read_size
= min( min_size
, reader
->input_size
);
830 reader
->read_pos
= 0;
832 LeaveCriticalSection( &reader
->cs
);
836 /**************************************************************************
837 * WsGetNamespaceFromPrefix [webservices.@]
839 HRESULT WINAPI
WsGetNamespaceFromPrefix( WS_XML_READER
*handle
, const WS_XML_STRING
*prefix
,
840 BOOL required
, const WS_XML_STRING
**ns
, WS_ERROR
*error
)
842 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
843 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
844 static const WS_XML_STRING empty_ns
= {0, NULL
};
845 static const WS_XML_STRING xml_ns
= {36, (BYTE
*)"http://www.w3.org/XML/1998/namespace"};
846 static const WS_XML_STRING xmlns_ns
= {29, (BYTE
*)"http://www.w3.org/2000/xmlns/"};
847 struct reader
*reader
= (struct reader
*)handle
;
850 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(prefix
), required
, ns
, error
);
851 if (error
) FIXME( "ignoring error parameter\n" );
853 if (!reader
|| !prefix
|| !ns
) return E_INVALIDARG
;
855 EnterCriticalSection( &reader
->cs
);
857 if (reader
->magic
!= READER_MAGIC
)
859 LeaveCriticalSection( &reader
->cs
);
863 if (reader
->state
!= READER_STATE_STARTELEMENT
)
865 LeaveCriticalSection( &reader
->cs
);
866 return WS_E_INVALID_OPERATION
;
874 else if (WsXmlStringEquals( prefix
, &xml
, NULL
) == S_OK
)
879 else if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
886 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
889 for (i
= 0; i
< elem
->attributeCount
; i
++)
891 if (!elem
->attributes
[i
]->isXmlNs
) continue;
892 if (WsXmlStringEquals( prefix
, elem
->attributes
[i
]->prefix
, NULL
) == S_OK
)
894 *ns
= elem
->attributes
[i
]->ns
;
901 LeaveCriticalSection( &reader
->cs
);
905 if (required
) return WS_E_INVALID_FORMAT
;
913 /**************************************************************************
914 * WsGetReaderNode [webservices.@]
916 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
919 struct reader
*reader
= (struct reader
*)handle
;
921 TRACE( "%p %p %p\n", handle
, node
, error
);
922 if (error
) FIXME( "ignoring error parameter\n" );
924 if (!reader
|| !node
) return E_INVALIDARG
;
926 EnterCriticalSection( &reader
->cs
);
928 if (reader
->magic
!= READER_MAGIC
)
930 LeaveCriticalSection( &reader
->cs
);
934 *node
= &reader
->current
->hdr
.node
;
936 LeaveCriticalSection( &reader
->cs
);
940 /**************************************************************************
941 * WsGetReaderProperty [webservices.@]
943 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
944 void *buf
, ULONG size
, WS_ERROR
*error
)
946 struct reader
*reader
= (struct reader
*)handle
;
949 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
950 if (error
) FIXME( "ignoring error parameter\n" );
952 if (!reader
) return E_INVALIDARG
;
954 EnterCriticalSection( &reader
->cs
);
956 if (reader
->magic
!= READER_MAGIC
)
958 LeaveCriticalSection( &reader
->cs
);
962 if (!reader
->input_type
)
964 LeaveCriticalSection( &reader
->cs
);
965 return WS_E_INVALID_OPERATION
;
968 if (id
== WS_XML_READER_PROPERTY_CHARSET
)
971 if ((hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, &charset
, size
)) != S_OK
) goto done
;
974 hr
= WS_E_INVALID_FORMAT
;
977 *(WS_CHARSET
*)buf
= charset
;
980 else hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, buf
, size
);
983 LeaveCriticalSection( &reader
->cs
);
987 /**************************************************************************
988 * WsGetXmlAttribute [webservices.@]
990 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
991 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
993 FIXME( "%p %s %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
997 WS_XML_UTF8_TEXT
*alloc_utf8_text( const unsigned char *data
, ULONG len
)
999 WS_XML_UTF8_TEXT
*ret
;
1001 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
1002 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1003 ret
->value
.length
= len
;
1004 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
1005 ret
->value
.dictionary
= NULL
;
1007 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
1011 static inline BOOL
read_end_of_data( struct reader
*reader
)
1013 return reader
->read_pos
>= reader
->read_size
;
1016 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
1018 return &reader
->read_bufptr
[reader
->read_pos
];
1021 static inline HRESULT
read_peek( struct reader
*reader
, unsigned char *byte
)
1023 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
1024 *byte
= reader
->read_bufptr
[reader
->read_pos
];
1028 static inline HRESULT
read_byte( struct reader
*reader
, unsigned char *byte
)
1030 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
1031 *byte
= reader
->read_bufptr
[reader
->read_pos
++];
1035 static inline HRESULT
read_bytes( struct reader
*reader
, unsigned char *bytes
, unsigned int len
)
1037 if (reader
->read_pos
+ len
> reader
->read_size
) return WS_E_INVALID_FORMAT
;
1038 memcpy( bytes
, reader
->read_bufptr
+ reader
->read_pos
, len
);
1039 reader
->read_pos
+= len
;
1043 /* UTF-8 support based on libs/wine/utf8.c */
1045 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
1046 static const char utf8_length
[128] =
1048 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
1049 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
1050 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
1051 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
1052 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
1053 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
1054 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
1055 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
1058 /* first byte mask depending on UTF-8 sequence length */
1059 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
1061 /* minimum Unicode value depending on UTF-8 sequence length */
1062 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
1064 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
1066 unsigned int len
, res
;
1067 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
1068 const unsigned char *end
;
1070 if (reader
->read_pos
>= reader
->read_size
) return 0;
1077 len
= utf8_length
[ch
- 0x80];
1078 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
1079 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
+ 1;
1080 res
= ch
& utf8_mask
[len
];
1085 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
1086 res
= (res
<< 6) | ch
;
1088 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
1089 res
= (res
<< 6) | ch
;
1091 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
1092 res
= (res
<< 6) | ch
;
1093 if (res
< utf8_minval
[len
]) break;
1101 static inline void read_skip( struct reader
*reader
, unsigned int count
)
1103 if (reader
->read_pos
+ count
> reader
->read_size
) return;
1104 reader
->read_pos
+= count
;
1107 static inline void read_rewind( struct reader
*reader
, unsigned int count
)
1109 reader
->read_pos
-= count
;
1112 static inline BOOL
read_isnamechar( unsigned int ch
)
1114 /* FIXME: incomplete */
1115 return (ch
>= 'A' && ch
<= 'Z') ||
1116 (ch
>= 'a' && ch
<= 'z') ||
1117 (ch
>= '0' && ch
<= '9') ||
1118 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
1121 static inline BOOL
read_isspace( unsigned int ch
)
1123 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
1126 static inline void read_skip_whitespace( struct reader
*reader
)
1128 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
1132 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
1134 const unsigned char *ptr
= read_current_ptr( reader
);
1136 if (len
< 0) len
= strlen( str
);
1137 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
1140 if (*str
!= *ptr
) return *ptr
- *str
;
1146 static HRESULT
read_xmldecl( struct reader
*reader
)
1148 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
1150 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
1152 reader
->state
= READER_STATE_BOF
;
1155 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
1156 read_skip( reader
, 6 );
1158 /* FIXME: parse attributes */
1159 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
1162 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
1163 read_skip( reader
, 2 );
1165 reader
->state
= READER_STATE_BOF
;
1169 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
1171 if (elem
->attributeCount
)
1173 WS_XML_ATTRIBUTE
**tmp
;
1174 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
1175 return E_OUTOFMEMORY
;
1176 elem
->attributes
= tmp
;
1178 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
1179 elem
->attributes
[elem
->attributeCount
++] = attr
;
1183 static HRESULT
split_name( const unsigned char *str
, ULONG len
, const unsigned char **prefix
,
1184 ULONG
*prefix_len
, const unsigned char **localname
, ULONG
*localname_len
)
1186 const unsigned char *ptr
= str
;
1192 *localname_len
= len
;
1198 if (ptr
== str
) return WS_E_INVALID_FORMAT
;
1200 *prefix_len
= ptr
- str
;
1201 *localname
= ptr
+ 1;
1202 *localname_len
= len
;
1210 static HRESULT
parse_name( const unsigned char *str
, ULONG len
, WS_XML_STRING
**prefix
, WS_XML_STRING
**localname
)
1212 const unsigned char *localname_ptr
, *prefix_ptr
;
1213 ULONG localname_len
, prefix_len
;
1216 if ((hr
= split_name( str
, len
, &prefix_ptr
, &prefix_len
, &localname_ptr
, &localname_len
)) != S_OK
) return hr
;
1217 if (!(*prefix
= alloc_xml_string( prefix_ptr
, prefix_len
))) return E_OUTOFMEMORY
;
1218 if (!(*localname
= alloc_xml_string( localname_ptr
, localname_len
)))
1220 free_xml_string( *prefix
);
1222 return E_OUTOFMEMORY
;
1227 static int codepoint_to_utf8( int cp
, unsigned char *dst
)
1237 dst
[1] = 0x80 | (cp
& 0x3f);
1242 if ((cp
>= 0xd800 && cp
<= 0xdfff) || cp
== 0xfffe || cp
== 0xffff) return -1;
1245 dst
[2] = 0x80 | (cp
& 0x3f);
1247 dst
[1] = 0x80 | (cp
& 0x3f);
1252 if (cp
>= 0x110000) return -1;
1253 dst
[3] = 0x80 | (cp
& 0x3f);
1255 dst
[2] = 0x80 | (cp
& 0x3f);
1257 dst
[1] = 0x80 | (cp
& 0x3f);
1263 static HRESULT
decode_text( const unsigned char *str
, ULONG len
, unsigned char *ret
, ULONG
*ret_len
)
1265 const unsigned char *p
= str
;
1266 unsigned char *q
= ret
;
1274 if (!len
) return WS_E_INVALID_FORMAT
;
1276 if (len
>= 3 && !memcmp( p
, "lt;", 3 ))
1282 else if (len
>= 3 && !memcmp( p
, "gt;", 3 ))
1288 else if (len
>= 5 && !memcmp( p
, "quot;", 5 ))
1294 else if (len
>= 4 && !memcmp( p
, "amp;", 4 ))
1300 else if (len
>= 5 && !memcmp( p
, "apos;", 5 ))
1308 ULONG start
, nb_digits
, i
;
1309 int len_utf8
, cp
= 0;
1312 if (!len
) return WS_E_INVALID_FORMAT
;
1318 while (len
&& isxdigit( *p
)) { p
++; len
--; };
1319 if (!len
) return WS_E_INVALID_FORMAT
;
1321 p
-= nb_digits
= start
- len
;
1322 if (!nb_digits
|| nb_digits
> 6 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1323 for (i
= 0; i
< nb_digits
; i
++)
1326 if (*p
>= '0' && *p
<= '9') cp
+= *p
- '0';
1327 else if (*p
>= 'a' && *p
<= 'f') cp
+= *p
- 'a' + 10;
1328 else cp
+= *p
- 'A' + 10;
1332 else if (isdigit( *p
))
1334 while (len
&& *p
== '0') { p
++; len
--; };
1335 if (!len
) return WS_E_INVALID_FORMAT
;
1338 while (len
&& isdigit( *p
)) { p
++; len
--; };
1339 if (!len
) return WS_E_INVALID_FORMAT
;
1341 p
-= nb_digits
= start
- len
;
1342 if (!nb_digits
|| nb_digits
> 7 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1343 for (i
= 0; i
< nb_digits
; i
++)
1350 else return WS_E_INVALID_FORMAT
;
1352 if ((len_utf8
= codepoint_to_utf8( cp
, q
)) < 0) return WS_E_INVALID_FORMAT
;
1353 *ret_len
+= len_utf8
;
1357 else return WS_E_INVALID_FORMAT
;
1369 static HRESULT
read_attribute_value_text( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1371 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1372 unsigned int len
, ch
, skip
, quote
;
1373 const unsigned char *start
;
1374 HRESULT hr
= E_OUTOFMEMORY
;
1376 read_skip_whitespace( reader
);
1377 if (read_cmp( reader
, "=", 1 )) return WS_E_INVALID_FORMAT
;
1378 read_skip( reader
, 1 );
1380 read_skip_whitespace( reader
);
1381 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) return WS_E_INVALID_FORMAT
;
1382 quote
= read_utf8_char( reader
, &skip
);
1383 read_skip( reader
, 1 );
1386 start
= read_current_ptr( reader
);
1389 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1390 if (ch
== quote
) break;
1391 read_skip( reader
, skip
);
1394 read_skip( reader
, 1 );
1398 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1399 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1400 if (!(utf8
= alloc_utf8_text( NULL
, 0 )))
1408 if (!(utf8
= alloc_utf8_text( NULL
, len
))) goto error
;
1409 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
) goto error
;
1412 attr
->value
= &utf8
->text
;
1413 attr
->singleQuote
= (quote
== '\'');
1421 static inline BOOL
is_text_type( unsigned char type
)
1423 return (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
);
1426 static HRESULT
read_int31( struct reader
*reader
, ULONG
*len
)
1431 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1433 if (!(byte
& 0x80)) return S_OK
;
1435 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1436 *len
+= (byte
& 0x7f) << 7;
1437 if (!(byte
& 0x80)) return S_OK
;
1439 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1440 *len
+= (byte
& 0x7f) << 14;
1441 if (!(byte
& 0x80)) return S_OK
;
1443 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1444 *len
+= (byte
& 0x7f) << 21;
1445 if (!(byte
& 0x80)) return S_OK
;
1447 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1448 *len
+= (byte
& 0x07) << 28;
1452 static HRESULT
read_string( struct reader
*reader
, WS_XML_STRING
**str
)
1456 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
1457 if (!(*str
= alloc_xml_string( NULL
, len
))) return E_OUTOFMEMORY
;
1458 if ((hr
= read_bytes( reader
, (*str
)->bytes
, len
)) == S_OK
)
1460 if (add_xml_string( *str
) != S_OK
) WARN( "string not added to dictionary\n" );
1463 free_xml_string( *str
);
1467 static HRESULT
read_dict_string( struct reader
*reader
, WS_XML_STRING
**str
)
1471 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1472 if (!reader
->dict
|| (id
>>= 1) >= reader
->dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1473 if (!(*str
= alloc_xml_string( NULL
, 0 ))) return E_OUTOFMEMORY
;
1474 *(*str
) = reader
->dict
->strings
[id
];
1478 static HRESULT
read_attribute_value_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1480 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1485 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1486 if (!is_text_type( type
)) return WS_E_INVALID_FORMAT
;
1490 case RECORD_CHARS8_TEXT
:
1493 if ((hr
= read_byte( reader
, &len8
)) != S_OK
) return hr
;
1498 ERR( "unhandled record type %02x\n", type
);
1499 return WS_E_NOT_SUPPORTED
;
1502 if (!(utf8
= alloc_utf8_text( NULL
, len
))) return E_OUTOFMEMORY
;
1503 if (!len
) utf8
->value
.bytes
= (BYTE
*)(utf8
+ 1); /* quirk */
1504 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
1510 attr
->value
= &utf8
->text
;
1514 static HRESULT
read_attribute_text( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1516 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1517 WS_XML_ATTRIBUTE
*attr
;
1518 unsigned int len
= 0, ch
, skip
;
1519 const unsigned char *start
;
1520 WS_XML_STRING
*prefix
, *localname
;
1521 HRESULT hr
= WS_E_INVALID_FORMAT
;
1523 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1525 start
= read_current_ptr( reader
);
1528 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1529 if (!read_isnamechar( ch
)) break;
1530 read_skip( reader
, skip
);
1533 if (!len
) goto error
;
1535 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1536 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1538 free_xml_string( prefix
);
1540 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1542 free_xml_string( localname
);
1546 attr
->localName
= localname
;
1548 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1551 attr
->prefix
= prefix
;
1552 attr
->localName
= localname
;
1556 attr
->prefix
= prefix
;
1557 attr
->localName
= localname
;
1560 if ((hr
= read_attribute_value_text( reader
, attr
)) != S_OK
) goto error
;
1566 free_attribute( attr
);
1570 static inline BOOL
is_attribute_type( unsigned char type
)
1572 return (type
>= RECORD_SHORT_ATTRIBUTE
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
);
1575 static HRESULT
read_attribute_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1577 WS_XML_ATTRIBUTE
*attr
;
1578 unsigned char type
= 0;
1581 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1582 if (!is_attribute_type( type
)) return WS_E_INVALID_FORMAT
;
1583 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1585 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1587 unsigned char ch
= type
- RECORD_PREFIX_ATTRIBUTE_A
+ 'a';
1588 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1593 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1594 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1596 else if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1598 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ 'a';
1599 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1604 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1605 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1611 case RECORD_SHORT_ATTRIBUTE
:
1612 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1617 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1618 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1621 case RECORD_ATTRIBUTE
:
1622 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1623 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1624 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1627 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1628 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1633 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1634 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1637 case RECORD_DICTIONARY_ATTRIBUTE
:
1638 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1639 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1640 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1643 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1644 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1649 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1650 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1654 case RECORD_XMLNS_ATTRIBUTE
:
1655 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1656 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1657 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1661 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1662 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1667 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1668 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1672 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1673 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1674 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1675 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1680 ERR( "unhandled record type %02x\n", type
);
1681 return WS_E_NOT_SUPPORTED
;
1689 free_attribute( attr
);
1693 static inline struct node
*find_parent( struct reader
*reader
)
1695 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1697 if (is_valid_parent( reader
->current
->parent
->parent
)) return reader
->current
->parent
->parent
;
1700 if (is_valid_parent( reader
->current
)) return reader
->current
;
1701 if (is_valid_parent( reader
->current
->parent
)) return reader
->current
->parent
;
1705 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1707 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1708 const WS_XML_STRING
*ns
;
1711 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1712 if (!(elem
->ns
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
1714 for (i
= 0; i
< elem
->attributeCount
; i
++)
1716 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1717 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1718 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1719 if (!(attr
->ns
= alloc_xml_string( NULL
, ns
->length
))) return E_OUTOFMEMORY
;
1720 if (attr
->ns
->length
) memcpy( attr
->ns
->bytes
, ns
->bytes
, ns
->length
);
1725 static WS_XML_ELEMENT_NODE
*alloc_element_pair(void)
1727 struct node
*node
, *end
;
1728 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
1729 if (!(end
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
)))
1734 list_add_tail( &node
->children
, &end
->entry
);
1739 static HRESULT
read_attributes_text( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1741 WS_XML_ATTRIBUTE
*attr
;
1744 reader
->current_attr
= 0;
1747 read_skip_whitespace( reader
);
1748 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1749 if ((hr
= read_attribute_text( reader
, &attr
)) != S_OK
) return hr
;
1750 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1752 free_attribute( attr
);
1755 reader
->current_attr
++;
1760 static HRESULT
read_element_text( struct reader
*reader
)
1762 unsigned int len
= 0, ch
, skip
;
1763 const unsigned char *start
;
1764 struct node
*node
= NULL
, *parent
;
1765 WS_XML_ELEMENT_NODE
*elem
;
1766 HRESULT hr
= WS_E_INVALID_FORMAT
;
1768 if (read_end_of_data( reader
))
1770 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1771 reader
->last
= reader
->current
;
1772 reader
->state
= READER_STATE_EOF
;
1776 if (read_cmp( reader
, "<", 1 )) return WS_E_INVALID_FORMAT
;
1777 read_skip( reader
, 1 );
1778 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1780 read_rewind( reader
, 1 );
1781 return WS_E_INVALID_FORMAT
;
1784 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1785 node
= (struct node
*)elem
;
1787 start
= read_current_ptr( reader
);
1790 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1791 if (!read_isnamechar( ch
)) break;
1792 read_skip( reader
, skip
);
1795 if (!len
) goto error
;
1797 if (!(parent
= find_parent( reader
))) goto error
;
1798 if ((hr
= parse_name( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1800 if ((hr
= read_attributes_text( reader
, elem
)) != S_OK
) goto error
;
1801 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1803 read_insert_node( reader
, parent
, node
);
1804 reader
->state
= READER_STATE_STARTELEMENT
;
1808 destroy_nodes( node
);
1812 static inline BOOL
is_element_type( unsigned char type
)
1814 return (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
);
1817 static HRESULT
read_attributes_bin( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1819 WS_XML_ATTRIBUTE
*attr
;
1823 reader
->current_attr
= 0;
1826 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
1827 if (!is_attribute_type( type
)) break;
1828 if ((hr
= read_attribute_bin( reader
, &attr
)) != S_OK
) return hr
;
1829 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1831 free_attribute( attr
);
1834 reader
->current_attr
++;
1839 static HRESULT
read_element_bin( struct reader
*reader
)
1841 struct node
*node
= NULL
, *parent
;
1842 WS_XML_ELEMENT_NODE
*elem
;
1846 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1847 if (!is_element_type( type
)) return WS_E_INVALID_FORMAT
;
1849 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1850 node
= (struct node
*)elem
;
1852 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1854 unsigned char ch
= type
- RECORD_PREFIX_ELEMENT_A
+ 'a';
1855 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1860 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1862 else if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1864 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ 'a';
1865 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1870 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1876 case RECORD_SHORT_ELEMENT
:
1877 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1882 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1885 case RECORD_ELEMENT
:
1886 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1887 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1890 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1891 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1896 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1899 case RECORD_DICTIONARY_ELEMENT
:
1900 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1901 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1905 ERR( "unhandled record type %02x\n", type
);
1906 return WS_E_NOT_SUPPORTED
;
1910 if (!(parent
= find_parent( reader
)))
1912 hr
= WS_E_INVALID_FORMAT
;
1916 if ((hr
= read_attributes_bin( reader
, elem
)) != S_OK
) goto error
;
1917 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1919 read_insert_node( reader
, parent
, node
);
1920 reader
->state
= READER_STATE_STARTELEMENT
;
1924 destroy_nodes( node
);
1928 static HRESULT
read_text_text( struct reader
*reader
)
1930 unsigned int len
= 0, ch
, skip
;
1931 const unsigned char *start
;
1932 struct node
*node
, *parent
;
1933 WS_XML_TEXT_NODE
*text
;
1934 WS_XML_UTF8_TEXT
*utf8
;
1937 start
= read_current_ptr( reader
);
1940 if (read_end_of_data( reader
)) break;
1941 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1942 if (ch
== '<') break;
1943 read_skip( reader
, skip
);
1947 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1949 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1950 text
= (WS_XML_TEXT_NODE
*)node
;
1951 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
1954 return E_OUTOFMEMORY
;
1956 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1962 text
->text
= &utf8
->text
;
1964 read_insert_node( reader
, parent
, node
);
1965 reader
->state
= READER_STATE_TEXT
;
1966 reader
->text_conv_offset
= 0;
1970 static HRESULT
read_text_bin( struct reader
*reader
)
1973 struct node
*node
, *parent
;
1974 WS_XML_TEXT_NODE
*text
;
1975 WS_XML_UTF8_TEXT
*utf8
;
1979 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1980 if (!is_text_type( type
)) return WS_E_INVALID_FORMAT
;
1984 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
1987 if ((hr
= read_byte( reader
, &len8
)) != S_OK
) return hr
;
1992 ERR( "unhandled record type %02x\n", type
);
1993 return WS_E_NOT_SUPPORTED
;
1996 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1998 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1999 text
= (WS_XML_TEXT_NODE
*)node
;
2000 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
2003 return E_OUTOFMEMORY
;
2005 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
2011 text
->text
= &utf8
->text
;
2013 read_insert_node( reader
, parent
, node
);
2014 reader
->state
= READER_STATE_TEXT
;
2015 reader
->text_conv_offset
= 0;
2019 static HRESULT
read_node_text( struct reader
* );
2021 static HRESULT
read_startelement_text( struct reader
*reader
)
2023 read_skip_whitespace( reader
);
2024 if (!read_cmp( reader
, "/>", 2 ))
2026 read_skip( reader
, 2 );
2027 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->children
), struct node
, entry
);
2028 reader
->last
= reader
->current
;
2029 reader
->state
= READER_STATE_ENDELEMENT
;
2032 else if (!read_cmp( reader
, ">", 1 ))
2034 read_skip( reader
, 1 );
2035 return read_node_text( reader
);
2037 return WS_E_INVALID_FORMAT
;
2040 static HRESULT
read_node_bin( struct reader
* );
2042 static HRESULT
read_startelement_bin( struct reader
*reader
)
2044 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
2045 return read_node_bin( reader
);
2048 static HRESULT
read_startelement( struct reader
*reader
)
2050 switch (reader
->input_enc
)
2052 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_startelement_text( reader
);
2053 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_startelement_bin( reader
);
2055 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2056 return WS_E_NOT_SUPPORTED
;
2060 static HRESULT
read_to_startelement_text( struct reader
*reader
, BOOL
*found
)
2064 switch (reader
->state
)
2066 case READER_STATE_INITIAL
:
2067 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
2070 case READER_STATE_STARTELEMENT
:
2071 if (found
) *found
= TRUE
;
2078 read_skip_whitespace( reader
);
2079 if ((hr
= read_element_text( reader
)) == S_OK
&& found
)
2081 if (reader
->state
== READER_STATE_STARTELEMENT
)
2090 static HRESULT
read_to_startelement_bin( struct reader
*reader
, BOOL
*found
)
2094 if (reader
->state
== READER_STATE_STARTELEMENT
)
2096 if (found
) *found
= TRUE
;
2100 if ((hr
= read_element_bin( reader
)) == S_OK
&& found
)
2102 if (reader
->state
== READER_STATE_STARTELEMENT
)
2111 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
2113 switch (reader
->input_enc
)
2115 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_to_startelement_text( reader
, found
);
2116 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_to_startelement_bin( reader
, found
);
2118 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2119 return WS_E_NOT_SUPPORTED
;
2123 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
2126 if (len1
!= len2
) return 1;
2127 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
2131 static struct node
*find_startelement( struct reader
*reader
, const WS_XML_STRING
*prefix
,
2132 const WS_XML_STRING
*localname
)
2134 struct node
*parent
;
2135 const WS_XML_STRING
*str
;
2137 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
2139 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2141 str
= parent
->hdr
.prefix
;
2142 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
2143 str
= parent
->hdr
.localName
;
2144 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
2151 static HRESULT
read_endelement_text( struct reader
*reader
)
2153 struct node
*parent
;
2154 unsigned int len
= 0, ch
, skip
;
2155 const unsigned char *start
;
2156 WS_XML_STRING
*prefix
, *localname
;
2159 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
2160 read_skip( reader
, 2 );
2162 start
= read_current_ptr( reader
);
2165 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2168 read_skip( reader
, 1 );
2171 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
2172 read_skip( reader
, skip
);
2176 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
2177 parent
= find_startelement( reader
, prefix
, localname
);
2178 free_xml_string( prefix
);
2179 free_xml_string( localname
);
2180 if (!parent
) return WS_E_INVALID_FORMAT
;
2182 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2183 reader
->last
= reader
->current
;
2184 reader
->state
= READER_STATE_ENDELEMENT
;
2188 static HRESULT
read_endelement_bin( struct reader
*reader
)
2190 struct node
*parent
;
2194 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2195 if (type
!= RECORD_ENDELEMENT
) return WS_E_INVALID_FORMAT
;
2197 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2199 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2200 reader
->last
= reader
->current
;
2201 reader
->state
= READER_STATE_ENDELEMENT
;
2205 static HRESULT
read_endelement( struct reader
*reader
)
2207 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
2209 if (read_end_of_data( reader
))
2211 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2212 reader
->last
= reader
->current
;
2213 reader
->state
= READER_STATE_EOF
;
2217 switch (reader
->input_enc
)
2219 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_endelement_text( reader
);
2220 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_endelement_bin( reader
);
2222 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2223 return WS_E_NOT_SUPPORTED
;
2227 static HRESULT
read_comment_text( struct reader
*reader
)
2229 unsigned int len
= 0, ch
, skip
;
2230 const unsigned char *start
;
2231 struct node
*node
, *parent
;
2232 WS_XML_COMMENT_NODE
*comment
;
2234 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
2235 read_skip( reader
, 4 );
2237 start
= read_current_ptr( reader
);
2240 if (!read_cmp( reader
, "-->", 3 ))
2242 read_skip( reader
, 3 );
2245 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2246 read_skip( reader
, skip
);
2250 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2252 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2253 comment
= (WS_XML_COMMENT_NODE
*)node
;
2254 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2257 return E_OUTOFMEMORY
;
2259 memcpy( comment
->value
.bytes
, start
, len
);
2260 comment
->value
.length
= len
;
2262 read_insert_node( reader
, parent
, node
);
2263 reader
->state
= READER_STATE_COMMENT
;
2267 static HRESULT
read_comment_bin( struct reader
*reader
)
2269 struct node
*node
, *parent
;
2270 WS_XML_COMMENT_NODE
*comment
;
2275 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2276 if (type
!= RECORD_COMMENT
) return WS_E_INVALID_FORMAT
;
2277 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
2279 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2281 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2282 comment
= (WS_XML_COMMENT_NODE
*)node
;
2283 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2286 return E_OUTOFMEMORY
;
2288 if ((hr
= read_bytes( reader
, comment
->value
.bytes
, len
)) != S_OK
)
2291 return E_OUTOFMEMORY
;
2293 comment
->value
.length
= len
;
2295 read_insert_node( reader
, parent
, node
);
2296 reader
->state
= READER_STATE_COMMENT
;
2300 static HRESULT
read_startcdata( struct reader
*reader
)
2302 struct node
*node
, *endnode
, *parent
;
2304 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
2305 read_skip( reader
, 9 );
2307 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2309 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2310 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
)))
2313 return E_OUTOFMEMORY
;
2315 list_add_tail( &node
->children
, &endnode
->entry
);
2316 endnode
->parent
= node
;
2318 read_insert_node( reader
, parent
, node
);
2319 reader
->state
= READER_STATE_STARTCDATA
;
2323 static HRESULT
read_cdata( struct reader
*reader
)
2325 unsigned int len
= 0, ch
, skip
;
2326 const unsigned char *start
;
2328 WS_XML_TEXT_NODE
*text
;
2329 WS_XML_UTF8_TEXT
*utf8
;
2331 start
= read_current_ptr( reader
);
2334 if (!read_cmp( reader
, "]]>", 3 )) break;
2335 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2336 read_skip( reader
, skip
);
2340 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2341 text
= (WS_XML_TEXT_NODE
*)node
;
2342 if (!(utf8
= alloc_utf8_text( start
, len
)))
2345 return E_OUTOFMEMORY
;
2347 text
->text
= &utf8
->text
;
2349 read_insert_node( reader
, reader
->current
, node
);
2350 reader
->state
= READER_STATE_CDATA
;
2354 static HRESULT
read_endcdata( struct reader
*reader
)
2356 struct node
*parent
;
2358 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
2359 read_skip( reader
, 3 );
2361 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
) parent
= reader
->current
->parent
;
2362 else parent
= reader
->current
;
2364 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2365 reader
->last
= reader
->current
;
2366 reader
->state
= READER_STATE_ENDCDATA
;
2370 static HRESULT
read_node_text( struct reader
*reader
)
2376 if (read_end_of_data( reader
))
2378 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2379 reader
->last
= reader
->current
;
2380 reader
->state
= READER_STATE_EOF
;
2383 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
2384 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
2385 else if (!read_cmp( reader
, "<?", 2 ))
2387 hr
= read_xmldecl( reader
);
2388 if (FAILED( hr
)) return hr
;
2390 else if (!read_cmp( reader
, "</", 2 )) return read_endelement_text( reader
);
2391 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
2392 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment_text( reader
);
2393 else if (!read_cmp( reader
, "<", 1 )) return read_element_text( reader
);
2394 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement_text( reader
);
2395 else return read_text_text( reader
);
2399 static HRESULT
read_node_bin( struct reader
*reader
)
2404 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
)
2406 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->parent
->children
), struct node
, entry
);
2407 reader
->last
= reader
->current
;
2408 reader
->state
= READER_STATE_ENDELEMENT
;
2411 if (read_end_of_data( reader
))
2413 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2414 reader
->last
= reader
->current
;
2415 reader
->state
= READER_STATE_EOF
;
2419 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
2420 if (type
== RECORD_ENDELEMENT
)
2422 return read_endelement_bin( reader
);
2424 else if (type
== RECORD_COMMENT
)
2426 return read_comment_bin( reader
);
2428 else if (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
2430 return read_element_bin( reader
);
2432 else if (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
)
2434 return read_text_bin( reader
);
2436 FIXME( "unhandled record type %02x\n", type
);
2437 return WS_E_NOT_SUPPORTED
;
2440 static HRESULT
read_node( struct reader
*reader
)
2442 switch (reader
->input_enc
)
2444 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_node_text( reader
);
2445 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_node_bin( reader
);
2447 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2448 return WS_E_NOT_SUPPORTED
;
2452 HRESULT
copy_node( WS_XML_READER
*handle
, struct node
**node
)
2454 struct reader
*reader
= (struct reader
*)handle
;
2455 const struct list
*ptr
;
2456 const struct node
*start
;
2459 EnterCriticalSection( &reader
->cs
);
2461 if (reader
->magic
!= READER_MAGIC
)
2463 LeaveCriticalSection( &reader
->cs
);
2464 return E_INVALIDARG
;
2467 if (reader
->current
!= reader
->root
) ptr
= &reader
->current
->entry
;
2468 else /* copy whole tree */
2470 if (!read_end_of_data( reader
))
2474 if ((hr
= read_node( reader
)) != S_OK
) goto done
;
2475 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) break;
2478 ptr
= list_head( &reader
->root
->children
);
2481 start
= LIST_ENTRY( ptr
, struct node
, entry
);
2482 if (node_type( start
) == WS_XML_NODE_TYPE_EOF
) hr
= WS_E_INVALID_OPERATION
;
2483 else hr
= dup_tree( node
, start
);
2486 LeaveCriticalSection( &reader
->cs
);
2490 /**************************************************************************
2491 * WsReadEndElement [webservices.@]
2493 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2495 struct reader
*reader
= (struct reader
*)handle
;
2498 TRACE( "%p %p\n", handle
, error
);
2499 if (error
) FIXME( "ignoring error parameter\n" );
2501 if (!reader
) return E_INVALIDARG
;
2503 EnterCriticalSection( &reader
->cs
);
2505 if (reader
->magic
!= READER_MAGIC
)
2507 LeaveCriticalSection( &reader
->cs
);
2508 return E_INVALIDARG
;
2511 hr
= read_endelement( reader
);
2513 LeaveCriticalSection( &reader
->cs
);
2517 /**************************************************************************
2518 * WsReadNode [webservices.@]
2520 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2522 struct reader
*reader
= (struct reader
*)handle
;
2525 TRACE( "%p %p\n", handle
, error
);
2526 if (error
) FIXME( "ignoring error parameter\n" );
2528 if (!reader
) return E_INVALIDARG
;
2530 EnterCriticalSection( &reader
->cs
);
2532 if (reader
->magic
!= READER_MAGIC
)
2534 LeaveCriticalSection( &reader
->cs
);
2535 return E_INVALIDARG
;
2538 hr
= read_node( reader
);
2540 LeaveCriticalSection( &reader
->cs
);
2544 static HRESULT
skip_node( struct reader
*reader
)
2546 const struct node
*parent
;
2549 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) return WS_E_INVALID_OPERATION
;
2550 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_ELEMENT
) parent
= reader
->current
;
2555 if ((hr
= read_node( reader
) != S_OK
) || !parent
) break;
2556 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_END_ELEMENT
) continue;
2557 if (reader
->current
->parent
== parent
) return read_node( reader
);
2563 /**************************************************************************
2564 * WsSkipNode [webservices.@]
2566 HRESULT WINAPI
WsSkipNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2568 struct reader
*reader
= (struct reader
*)handle
;
2571 TRACE( "%p %p\n", handle
, error
);
2572 if (error
) FIXME( "ignoring error parameter\n" );
2574 if (!reader
) return E_INVALIDARG
;
2576 EnterCriticalSection( &reader
->cs
);
2578 if (reader
->magic
!= READER_MAGIC
)
2580 LeaveCriticalSection( &reader
->cs
);
2581 return E_INVALIDARG
;
2584 hr
= skip_node( reader
);
2586 LeaveCriticalSection( &reader
->cs
);
2590 /**************************************************************************
2591 * WsReadStartElement [webservices.@]
2593 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2595 struct reader
*reader
= (struct reader
*)handle
;
2598 TRACE( "%p %p\n", handle
, error
);
2599 if (error
) FIXME( "ignoring error parameter\n" );
2601 if (!reader
) return E_INVALIDARG
;
2603 EnterCriticalSection( &reader
->cs
);
2605 if (reader
->magic
!= READER_MAGIC
)
2607 LeaveCriticalSection( &reader
->cs
);
2608 return E_INVALIDARG
;
2611 hr
= read_startelement( reader
);
2613 LeaveCriticalSection( &reader
->cs
);
2617 /**************************************************************************
2618 * WsReadToStartElement [webservices.@]
2620 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2621 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
2623 struct reader
*reader
= (struct reader
*)handle
;
2626 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
2627 if (error
) FIXME( "ignoring error parameter\n" );
2629 if (!reader
) return E_INVALIDARG
;
2630 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
2632 EnterCriticalSection( &reader
->cs
);
2634 if (reader
->magic
!= READER_MAGIC
)
2636 LeaveCriticalSection( &reader
->cs
);
2637 return E_INVALIDARG
;
2640 hr
= read_to_startelement( reader
, found
);
2642 LeaveCriticalSection( &reader
->cs
);
2646 BOOL
move_to_root_element( struct node
*root
, struct node
**current
)
2651 if (!(ptr
= list_head( &root
->children
))) return FALSE
;
2652 node
= LIST_ENTRY( ptr
, struct node
, entry
);
2653 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
2658 while ((ptr
= list_next( &root
->children
, &node
->entry
)))
2660 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2661 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2671 BOOL
move_to_next_element( struct node
**current
)
2674 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2676 if (!parent
) return FALSE
;
2677 while ((ptr
= list_next( &parent
->children
, &node
->entry
)))
2679 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2680 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2690 BOOL
move_to_prev_element( struct node
**current
)
2693 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2695 if (!parent
) return FALSE
;
2696 while ((ptr
= list_prev( &parent
->children
, &node
->entry
)))
2698 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
2699 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
2709 BOOL
move_to_child_element( struct node
**current
)
2712 struct node
*child
, *node
= *current
;
2714 if (!(ptr
= list_head( &node
->children
))) return FALSE
;
2715 child
= LIST_ENTRY( ptr
, struct node
, entry
);
2716 if (node_type( child
) == WS_XML_NODE_TYPE_ELEMENT
)
2721 while ((ptr
= list_next( &node
->children
, &child
->entry
)))
2723 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2724 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2734 BOOL
move_to_end_element( struct node
**current
)
2737 struct node
*node
= *current
;
2739 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
2741 if ((ptr
= list_tail( &node
->children
)))
2743 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
2744 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
2753 BOOL
move_to_parent_element( struct node
**current
)
2755 struct node
*parent
= (*current
)->parent
;
2757 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
2758 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
2766 BOOL
move_to_first_node( struct node
**current
)
2769 struct node
*node
= *current
;
2771 if ((ptr
= list_head( &node
->parent
->children
)))
2773 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2779 BOOL
move_to_next_node( struct node
**current
)
2782 struct node
*node
= *current
;
2784 if ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
2786 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2792 BOOL
move_to_prev_node( struct node
**current
)
2795 struct node
*node
= *current
;
2797 if ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
2799 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2805 BOOL
move_to_bof( struct node
*root
, struct node
**current
)
2811 BOOL
move_to_eof( struct node
*root
, struct node
**current
)
2814 if ((ptr
= list_tail( &root
->children
)))
2816 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2822 BOOL
move_to_child_node( struct node
**current
)
2825 struct node
*node
= *current
;
2827 if ((ptr
= list_head( &node
->children
)))
2829 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2835 BOOL
move_to_parent_node( struct node
**current
)
2837 struct node
*parent
= (*current
)->parent
;
2838 if (!parent
) return FALSE
;
2843 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
2845 BOOL success
= FALSE
;
2848 if (!read_end_of_data( reader
))
2850 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
2851 if (hr
!= S_OK
) return hr
;
2855 case WS_MOVE_TO_ROOT_ELEMENT
:
2856 success
= move_to_root_element( reader
->root
, &reader
->current
);
2859 case WS_MOVE_TO_NEXT_ELEMENT
:
2860 success
= move_to_next_element( &reader
->current
);
2863 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
2864 success
= move_to_prev_element( &reader
->current
);
2867 case WS_MOVE_TO_CHILD_ELEMENT
:
2868 success
= move_to_child_element( &reader
->current
);
2871 case WS_MOVE_TO_END_ELEMENT
:
2872 success
= move_to_end_element( &reader
->current
);
2875 case WS_MOVE_TO_PARENT_ELEMENT
:
2876 success
= move_to_parent_element( &reader
->current
);
2879 case WS_MOVE_TO_FIRST_NODE
:
2880 success
= move_to_first_node( &reader
->current
);
2883 case WS_MOVE_TO_NEXT_NODE
:
2884 success
= move_to_next_node( &reader
->current
);
2887 case WS_MOVE_TO_PREVIOUS_NODE
:
2888 success
= move_to_prev_node( &reader
->current
);
2891 case WS_MOVE_TO_CHILD_NODE
:
2892 success
= move_to_child_node( &reader
->current
);
2895 case WS_MOVE_TO_BOF
:
2896 success
= move_to_bof( reader
->root
, &reader
->current
);
2899 case WS_MOVE_TO_EOF
:
2900 success
= move_to_eof( reader
->root
, &reader
->current
);
2904 FIXME( "unhandled move %u\n", move
);
2913 return success
? S_OK
: WS_E_INVALID_FORMAT
;
2916 /**************************************************************************
2917 * WsMoveReader [webservices.@]
2919 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
2921 struct reader
*reader
= (struct reader
*)handle
;
2924 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
2925 if (error
) FIXME( "ignoring error parameter\n" );
2927 if (!reader
) return E_INVALIDARG
;
2929 EnterCriticalSection( &reader
->cs
);
2931 if (reader
->magic
!= READER_MAGIC
)
2933 LeaveCriticalSection( &reader
->cs
);
2934 return E_INVALIDARG
;
2937 if (!reader
->input_type
)
2939 LeaveCriticalSection( &reader
->cs
);
2940 return WS_E_INVALID_OPERATION
;
2943 hr
= read_move_to( reader
, move
, found
);
2945 LeaveCriticalSection( &reader
->cs
);
2949 /**************************************************************************
2950 * WsReadStartAttribute [webservices.@]
2952 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
2954 struct reader
*reader
= (struct reader
*)handle
;
2955 const WS_XML_ELEMENT_NODE
*elem
;
2957 TRACE( "%p %u %p\n", handle
, index
, error
);
2958 if (error
) FIXME( "ignoring error parameter\n" );
2960 if (!reader
) return E_INVALIDARG
;
2962 EnterCriticalSection( &reader
->cs
);
2964 if (reader
->magic
!= READER_MAGIC
)
2966 LeaveCriticalSection( &reader
->cs
);
2967 return E_INVALIDARG
;
2970 elem
= &reader
->current
->hdr
;
2971 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
2973 LeaveCriticalSection( &reader
->cs
);
2974 return WS_E_INVALID_FORMAT
;
2977 reader
->current_attr
= index
;
2978 reader
->state
= READER_STATE_STARTATTRIBUTE
;
2980 LeaveCriticalSection( &reader
->cs
);
2984 /**************************************************************************
2985 * WsReadEndAttribute [webservices.@]
2987 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
2989 struct reader
*reader
= (struct reader
*)handle
;
2991 TRACE( "%p %p\n", handle
, error
);
2992 if (error
) FIXME( "ignoring error parameter\n" );
2994 if (!reader
) return E_INVALIDARG
;
2996 EnterCriticalSection( &reader
->cs
);
2998 if (reader
->magic
!= READER_MAGIC
)
3000 LeaveCriticalSection( &reader
->cs
);
3001 return E_INVALIDARG
;
3004 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
3006 LeaveCriticalSection( &reader
->cs
);
3007 return WS_E_INVALID_FORMAT
;
3010 reader
->state
= READER_STATE_STARTELEMENT
;
3012 LeaveCriticalSection( &reader
->cs
);
3016 static HRESULT
find_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
**ns
)
3018 const struct node
*node
;
3019 for (node
= reader
->current
->parent
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3021 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3023 for (i
= 0; i
< elem
->attributeCount
; i
++)
3025 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3026 if (WsXmlStringEquals( elem
->attributes
[i
]->prefix
, prefix
, NULL
) != S_OK
) continue;
3027 *ns
= elem
->attributes
[i
]->ns
;
3031 return WS_E_INVALID_FORMAT
;
3034 static HRESULT
read_qualified_name( struct reader
*reader
, WS_HEAP
*heap
, WS_XML_STRING
*prefix_ret
,
3035 WS_XML_STRING
*localname_ret
, WS_XML_STRING
*ns_ret
)
3037 const WS_XML_TEXT_NODE
*node
= (const WS_XML_TEXT_NODE
*)reader
->current
;
3038 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)node
->text
;
3039 unsigned char *prefix_bytes
, *localname_bytes
, *ns_bytes
;
3040 const unsigned char *ptr
= utf8
->value
.bytes
;
3041 WS_XML_STRING prefix
, localname
, empty
= {0, NULL
};
3042 const WS_XML_STRING
*ns
= &empty
;
3043 ULONG len
= utf8
->value
.length
;
3046 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3047 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3048 if (!len
) return WS_E_INVALID_FORMAT
;
3050 if ((hr
= split_name( ptr
, len
, (const unsigned char **)&prefix
.bytes
, &prefix
.length
,
3051 (const unsigned char **)&localname
.bytes
, &localname
.length
)) != S_OK
) return hr
;
3053 if (!localname
.length
) return WS_E_INVALID_FORMAT
;
3054 if (prefix
.length
&& (hr
= find_namespace( reader
, &prefix
, &ns
)) != S_OK
) return hr
;
3056 if (!(prefix_bytes
= ws_alloc( heap
, prefix
.length
))) return WS_E_QUOTA_EXCEEDED
;
3057 memcpy( prefix_bytes
, prefix
.bytes
, prefix
.length
);
3059 if (!(localname_bytes
= ws_alloc( heap
, localname
.length
)))
3061 ws_free( heap
, prefix_bytes
, prefix
.length
);
3062 return WS_E_QUOTA_EXCEEDED
;
3064 memcpy( localname_bytes
, localname
.bytes
, localname
.length
);
3066 if (!(ns_bytes
= ws_alloc( heap
, ns
->length
)))
3068 ws_free( heap
, prefix_bytes
, prefix
.length
);
3069 ws_free( heap
, localname_bytes
, localname
.length
);
3070 return WS_E_QUOTA_EXCEEDED
;
3072 memcpy( ns_bytes
, ns
->bytes
, ns
->length
);
3074 prefix_ret
->bytes
= prefix_bytes
;
3075 prefix_ret
->length
= prefix
.length
;
3077 localname_ret
->bytes
= localname_bytes
;
3078 localname_ret
->length
= localname
.length
;
3080 ns_ret
->bytes
= ns_bytes
;
3081 ns_ret
->length
= ns
->length
;
3086 /**************************************************************************
3087 * WsReadQualifiedName [webservices.@]
3089 HRESULT WINAPI
WsReadQualifiedName( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
3090 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
,
3093 struct reader
*reader
= (struct reader
*)handle
;
3096 TRACE( "%p %p %p %p %p %p\n", handle
, heap
, prefix
, localname
, ns
, error
);
3097 if (error
) FIXME( "ignoring error parameter\n" );
3099 if (!reader
|| !heap
) return E_INVALIDARG
;
3101 EnterCriticalSection( &reader
->cs
);
3103 if (reader
->magic
!= READER_MAGIC
)
3105 LeaveCriticalSection( &reader
->cs
);
3106 return E_INVALIDARG
;
3109 if (!reader
->input_type
)
3111 LeaveCriticalSection( &reader
->cs
);
3112 return WS_E_INVALID_OPERATION
;
3117 LeaveCriticalSection( &reader
->cs
);
3118 return E_INVALIDARG
;
3121 if (reader
->state
!= READER_STATE_TEXT
)
3123 LeaveCriticalSection( &reader
->cs
);
3124 return WS_E_INVALID_FORMAT
;
3127 hr
= read_qualified_name( reader
, heap
, prefix
, localname
, ns
);
3129 LeaveCriticalSection( &reader
->cs
);
3133 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
3137 switch (text
->textType
)
3139 case WS_XML_TEXT_TYPE_UTF8
:
3141 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
3142 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
3143 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
3144 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
3149 FIXME( "unhandled type %u\n", text
->textType
);
3156 #define MAX_INT8 0x7f
3157 #define MIN_INT8 (-MAX_INT8 - 1)
3158 #define MAX_INT16 0x7fff
3159 #define MIN_INT16 (-MAX_INT16 - 1)
3160 #define MAX_INT32 0x7fffffff
3161 #define MIN_INT32 (-MAX_INT32 - 1)
3162 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
3163 #define MIN_INT64 (-MAX_INT64 - 1)
3164 #define MAX_UINT8 0xff
3165 #define MAX_UINT16 0xffff
3166 #define MAX_UINT32 0xffffffff
3167 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
3169 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
3171 BOOL negative
= FALSE
;
3172 const unsigned char *ptr
= str
;
3175 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3176 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3177 if (!len
) return WS_E_INVALID_FORMAT
;
3185 if (!len
) return WS_E_INVALID_FORMAT
;
3191 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3193 if (negative
) val
= -val
;
3195 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
3196 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
3198 return WS_E_NUMERIC_OVERFLOW
;
3200 *ret
= *ret
* 10 + val
;
3207 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
3209 const unsigned char *ptr
= str
;
3212 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3213 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3214 if (!len
) return WS_E_INVALID_FORMAT
;
3220 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3223 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
3224 *ret
= *ret
* 10 + val
;
3231 BOOL
set_fpword( unsigned short new, unsigned short *old
)
3233 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3234 unsigned short fpword
;
3236 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
3239 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3242 FIXME( "not implemented\n" );
3247 void restore_fpword( unsigned short fpword
)
3249 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3250 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3252 FIXME( "not implemented\n" );
3256 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
3258 static const unsigned __int64 nan
= 0xfff8000000000000;
3259 static const unsigned __int64 inf
= 0x7ff0000000000000;
3260 static const unsigned __int64 inf_min
= 0xfff0000000000000;
3261 HRESULT hr
= WS_E_INVALID_FORMAT
;
3262 const unsigned char *p
= str
, *q
;
3263 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
3264 unsigned __int64 val
= 0, tmp
;
3265 long double exp_val
= 1.0, exp_mul
= 10.0;
3266 unsigned short fpword
;
3268 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3269 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3270 if (!len
) return WS_E_INVALID_FORMAT
;
3272 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
3274 *(unsigned __int64
*)ret
= nan
;
3277 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
3279 *(unsigned __int64
*)ret
= inf
;
3282 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
3284 *(unsigned __int64
*)ret
= inf_min
;
3294 else if (*p
== '+') { p
++; len
--; };
3295 if (!len
) return S_OK
;
3297 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
3300 while (len
&& isdigit( *q
)) { q
++; len
--; }
3301 have_digits
= nb_digits
= q
- p
;
3302 for (i
= 0; i
< nb_digits
; i
++)
3304 tmp
= val
* 10 + p
[i
] - '0';
3305 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
3307 for (; i
< nb_digits
; i
++) exp
++;
3318 while (len
&& isdigit( *q
)) { q
++; len
--; };
3319 have_digits
|= nb_digits
= q
- p
;
3320 for (i
= 0; i
< nb_digits
; i
++)
3322 tmp
= val
* 10 + p
[i
] - '0';
3323 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
3328 if (len
> 1 && tolower(*q
) == 'e')
3330 if (!have_digits
) goto done
;
3337 else if (*p
== '+') { p
++; len
--; };
3340 while (len
&& isdigit( *q
)) { q
++; len
--; };
3342 if (!nb_digits
|| len
) goto done
;
3343 for (i
= 0; i
< nb_digits
; i
++)
3345 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
3346 exp_tmp
= MAX_INT32
;
3348 exp_tmp
*= exp_sign
;
3350 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
3351 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
3352 else exp
+= exp_tmp
;
3355 if (!have_digits
|| len
) goto done
;
3357 if ((neg_exp
= exp
< 0)) exp
= -exp
;
3358 for (; exp
; exp
>>= 1)
3360 if (exp
& 1) exp_val
*= exp_mul
;
3364 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
3368 restore_fpword( fpword
);
3372 static HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
3374 static const unsigned char hex
[] =
3376 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3377 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3378 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3379 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3380 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3381 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3382 0,10,11,12,13,14,15 /* 0x60 */
3384 const unsigned char *p
= str
;
3387 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3388 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3389 if (len
!= 36) return WS_E_INVALID_FORMAT
;
3391 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
3392 return WS_E_INVALID_FORMAT
;
3394 for (i
= 0; i
< 36; i
++)
3396 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
3397 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
3400 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
3401 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
3403 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
3404 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
3406 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
3407 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
3408 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
3409 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
3410 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
3411 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
3412 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
3413 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
3418 static inline unsigned char decode_char( unsigned char c
)
3420 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
3421 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
3422 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
3423 if (c
== '+') return 62;
3424 if (c
== '/') return 63;
3428 static ULONG
decode_base64( const unsigned char *base64
, ULONG len
, unsigned char *buf
)
3431 unsigned char c0
, c1
, c2
, c3
;
3432 const unsigned char *p
= base64
;
3436 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3437 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3438 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3439 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3440 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3441 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3442 buf
[i
+ 2] = (c2
<< 6) | c3
;
3449 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3450 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3451 buf
[i
] = (c0
<< 2) | (c1
>> 4);
3454 else if (p
[3] == '=')
3456 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3457 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3458 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3459 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3460 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3465 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3466 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3467 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3468 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3469 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3470 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3471 buf
[i
+ 2] = (c2
<< 6) | c3
;
3477 static HRESULT
str_to_bytes( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_BYTES
*ret
)
3479 const unsigned char *p
= str
;
3481 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3482 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3484 if (len
% 4) return WS_E_INVALID_FORMAT
;
3485 if (!(ret
->bytes
= ws_alloc( heap
, len
* 3 / 4 ))) return WS_E_QUOTA_EXCEEDED
;
3486 ret
->length
= decode_base64( p
, len
, ret
->bytes
);
3490 static const int month_offsets
[2][12] =
3492 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
3493 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
3496 static inline int valid_day( int year
, int month
, int day
)
3498 return day
> 0 && day
<= month_days
[leap_year( year
)][month
- 1];
3501 static inline int leap_days_before( int year
)
3503 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
3506 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
3508 const unsigned char *p
= bytes
, *q
;
3509 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
3511 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3512 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3515 while (len
&& isdigit( *q
)) { q
++; len
--; };
3516 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3517 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
3518 if (year
< 1) return WS_E_INVALID_FORMAT
;
3521 while (len
&& isdigit( *q
)) { q
++; len
--; };
3522 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3523 month
= (p
[0] - '0') * 10 + p
[1] - '0';
3524 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
3527 while (len
&& isdigit( *q
)) { q
++; len
--; };
3528 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
3529 day
= (p
[0] - '0') * 10 + p
[1] - '0';
3530 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
3533 while (len
&& isdigit( *q
)) { q
++; len
--; };
3534 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3535 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3536 if (hour
> 24) return WS_E_INVALID_FORMAT
;
3539 while (len
&& isdigit( *q
)) { q
++; len
--; };
3540 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3541 min
= (p
[0] - '0') * 10 + p
[1] - '0';
3542 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3545 while (len
&& isdigit( *q
)) { q
++; len
--; };
3546 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
3547 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
3548 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3552 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
3554 while (len
&& isdigit( *q
)) { q
++; len
--; };
3556 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
3557 for (i
= 0; i
< nb_digits
; i
++)
3559 sec_frac
+= (p
[i
] - '0') * mul
;
3565 if (--len
) return WS_E_INVALID_FORMAT
;
3566 tz_hour
= tz_min
= tz_neg
= 0;
3567 ret
->format
= WS_DATETIME_FORMAT_UTC
;
3569 else if (*q
== '+' || *q
== '-')
3571 tz_neg
= (*q
== '-') ? 1 : 0;
3574 while (len
&& isdigit( *q
)) { q
++; len
--; };
3575 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3576 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3577 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
3580 while (len
&& isdigit( *q
)) { q
++; len
--; };
3581 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
3582 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
3583 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
3585 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
3587 else return WS_E_INVALID_FORMAT
;
3589 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
3590 ret
->ticks
+= month_offsets
[leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
3591 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
3592 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
3593 ret
->ticks
+= min
* TICKS_PER_MIN
;
3594 ret
->ticks
+= sec
* TICKS_PER_SEC
;
3595 ret
->ticks
+= sec_frac
;
3599 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
3600 return WS_E_INVALID_FORMAT
;
3601 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
3602 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
3606 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
3607 return WS_E_INVALID_FORMAT
;
3608 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
3609 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
3615 /**************************************************************************
3616 * WsDateTimeToFileTime [webservices.@]
3618 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
3620 unsigned __int64 ticks
;
3622 TRACE( "%p %p %p\n", dt
, ft
, error
);
3623 if (error
) FIXME( "ignoring error parameter\n" );
3625 if (!dt
|| !ft
) return E_INVALIDARG
;
3627 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
3628 ticks
= dt
->ticks
- TICKS_1601_01_01
;
3629 ft
->dwHighDateTime
= ticks
>> 32;
3630 ft
->dwLowDateTime
= (DWORD
)ticks
;
3634 /**************************************************************************
3635 * WsFileTimeToDateTime [webservices.@]
3637 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
3639 unsigned __int64 ticks
;
3641 TRACE( "%p %p %p\n", ft
, dt
, error
);
3642 if (error
) FIXME( "ignoring error parameter\n" );
3644 if (!dt
|| !ft
) return E_INVALIDARG
;
3646 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
3647 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
3648 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
3649 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
3650 dt
->format
= WS_DATETIME_FORMAT_UTC
;
3654 static HRESULT
read_get_node_text( struct reader
*reader
, WS_XML_UTF8_TEXT
**ret
)
3656 WS_XML_TEXT_NODE
*text
;
3658 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
3659 return WS_E_INVALID_FORMAT
;
3661 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
3662 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3664 FIXME( "text type %u not supported\n", text
->text
->textType
);
3667 *ret
= (WS_XML_UTF8_TEXT
*)text
->text
;
3671 static HRESULT
read_get_attribute_text( struct reader
*reader
, ULONG index
, WS_XML_UTF8_TEXT
**ret
)
3673 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3674 WS_XML_ATTRIBUTE
*attr
;
3676 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
3677 return WS_E_INVALID_FORMAT
;
3679 attr
= elem
->attributes
[index
];
3680 if (attr
->value
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3682 FIXME( "text type %u not supported\n", attr
->value
->textType
);
3685 *ret
= (WS_XML_UTF8_TEXT
*)attr
->value
;
3689 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
3690 const WS_XML_STRING
*ns
, ULONG
*index
)
3693 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3697 *index
= reader
->current_attr
;
3700 for (i
= 0; i
< elem
->attributeCount
; i
++)
3702 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
3703 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
3705 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
3706 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
3715 /**************************************************************************
3716 * WsFindAttribute [webservices.@]
3718 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
3719 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
3722 struct reader
*reader
= (struct reader
*)handle
;
3725 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3726 required
, index
, error
);
3727 if (error
) FIXME( "ignoring error parameter\n" );
3729 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
3731 EnterCriticalSection( &reader
->cs
);
3733 if (reader
->magic
!= READER_MAGIC
)
3735 LeaveCriticalSection( &reader
->cs
);
3736 return E_INVALIDARG
;
3739 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
3741 LeaveCriticalSection( &reader
->cs
);
3742 return WS_E_INVALID_OPERATION
;
3745 if (!find_attribute( reader
, localname
, ns
, index
))
3747 if (required
) hr
= WS_E_INVALID_FORMAT
;
3755 LeaveCriticalSection( &reader
->cs
);
3759 static HRESULT
read_get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3760 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3761 WS_XML_UTF8_TEXT
**ret
, BOOL
*found
)
3765 case WS_ATTRIBUTE_TYPE_MAPPING
:
3768 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
3769 return read_get_attribute_text( reader
, index
, ret
);
3771 case WS_ELEMENT_TYPE_MAPPING
:
3772 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3773 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3779 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3781 if (WsXmlStringEquals( localname
, elem
->localName
, NULL
) != S_OK
||
3782 WsXmlStringEquals( ns
, elem
->ns
, NULL
) != S_OK
)
3787 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
3789 return read_get_node_text( reader
, ret
);
3792 FIXME( "mapping %u not supported\n", mapping
);
3797 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3798 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3799 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3800 WS_HEAP
*heap
, void *ret
, ULONG size
)
3802 WS_XML_UTF8_TEXT
*utf8
;
3804 BOOL found
, val
= FALSE
;
3808 FIXME( "description not supported\n" );
3811 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3814 ULONG len
= utf8
->value
.length
;
3815 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
3816 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
3817 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
3818 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
3819 else return WS_E_INVALID_FORMAT
;
3824 case WS_READ_REQUIRED_VALUE
:
3825 if (!found
) return WS_E_INVALID_FORMAT
;
3828 case WS_READ_NILLABLE_VALUE
:
3829 if (size
!= sizeof(BOOL
)) return E_INVALIDARG
;
3833 case WS_READ_REQUIRED_POINTER
:
3834 if (!found
) return WS_E_INVALID_FORMAT
;
3837 case WS_READ_OPTIONAL_POINTER
:
3838 case WS_READ_NILLABLE_POINTER
:
3840 BOOL
*heap_val
= NULL
;
3841 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3844 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3847 *(BOOL
**)ret
= heap_val
;
3851 FIXME( "read option %u not supported\n", option
);
3858 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3859 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3860 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3861 WS_HEAP
*heap
, void *ret
, ULONG size
)
3863 WS_XML_UTF8_TEXT
*utf8
;
3870 FIXME( "description not supported\n" );
3873 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3874 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
3879 case WS_READ_REQUIRED_VALUE
:
3880 if (!found
) return WS_E_INVALID_FORMAT
;
3883 case WS_READ_NILLABLE_VALUE
:
3884 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
3888 case WS_READ_REQUIRED_POINTER
:
3889 if (!found
) return WS_E_INVALID_FORMAT
;
3892 case WS_READ_OPTIONAL_POINTER
:
3893 case WS_READ_NILLABLE_POINTER
:
3895 INT8
*heap_val
= NULL
;
3896 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3899 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3902 *(INT8
**)ret
= heap_val
;
3906 FIXME( "read option %u not supported\n", option
);
3913 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3914 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3915 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3916 WS_HEAP
*heap
, void *ret
, ULONG size
)
3918 WS_XML_UTF8_TEXT
*utf8
;
3925 FIXME( "description not supported\n" );
3928 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3929 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
3934 case WS_READ_REQUIRED_VALUE
:
3935 if (!found
) return WS_E_INVALID_FORMAT
;
3938 case WS_READ_NILLABLE_VALUE
:
3939 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
3940 *(INT16
*)ret
= val
;
3943 case WS_READ_REQUIRED_POINTER
:
3944 if (!found
) return WS_E_INVALID_FORMAT
;
3947 case WS_READ_OPTIONAL_POINTER
:
3948 case WS_READ_NILLABLE_POINTER
:
3950 INT16
*heap_val
= NULL
;
3951 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3954 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3957 *(INT16
**)ret
= heap_val
;
3961 FIXME( "read option %u not supported\n", option
);
3968 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3969 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3970 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3971 WS_HEAP
*heap
, void *ret
, ULONG size
)
3973 WS_XML_UTF8_TEXT
*utf8
;
3980 FIXME( "description not supported\n" );
3983 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3984 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
3989 case WS_READ_REQUIRED_VALUE
:
3990 if (!found
) return WS_E_INVALID_FORMAT
;
3993 case WS_READ_NILLABLE_VALUE
:
3994 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
3995 *(INT32
*)ret
= val
;
3998 case WS_READ_REQUIRED_POINTER
:
3999 if (!found
) return WS_E_INVALID_FORMAT
;
4002 case WS_READ_OPTIONAL_POINTER
:
4003 case WS_READ_NILLABLE_POINTER
:
4005 INT32
*heap_val
= NULL
;
4006 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4009 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4012 *(INT32
**)ret
= heap_val
;
4016 FIXME( "read option %u not supported\n", option
);
4023 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4024 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4025 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4026 WS_HEAP
*heap
, void *ret
, ULONG size
)
4028 WS_XML_UTF8_TEXT
*utf8
;
4035 FIXME( "description not supported\n" );
4038 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4039 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
4044 case WS_READ_REQUIRED_VALUE
:
4045 if (!found
) return WS_E_INVALID_FORMAT
;
4048 case WS_READ_NILLABLE_VALUE
:
4049 if (size
!= sizeof(INT64
)) return E_INVALIDARG
;
4050 *(INT64
*)ret
= val
;
4053 case WS_READ_REQUIRED_POINTER
:
4054 if (!found
) return WS_E_INVALID_FORMAT
;
4057 case WS_READ_OPTIONAL_POINTER
:
4058 case WS_READ_NILLABLE_POINTER
:
4060 INT64
*heap_val
= NULL
;
4061 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4064 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4067 *(INT64
**)ret
= heap_val
;
4071 FIXME( "read option %u not supported\n", option
);
4078 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4079 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4080 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4081 WS_HEAP
*heap
, void *ret
, ULONG size
)
4083 WS_XML_UTF8_TEXT
*utf8
;
4090 FIXME( "description not supported\n" );
4093 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4094 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
4099 case WS_READ_REQUIRED_VALUE
:
4100 if (!found
) return WS_E_INVALID_FORMAT
;
4103 case WS_READ_NILLABLE_VALUE
:
4104 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
4105 *(UINT8
*)ret
= val
;
4108 case WS_READ_REQUIRED_POINTER
:
4109 if (!found
) return WS_E_INVALID_FORMAT
;
4112 case WS_READ_OPTIONAL_POINTER
:
4113 case WS_READ_NILLABLE_POINTER
:
4115 UINT8
*heap_val
= NULL
;
4116 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4119 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4122 *(UINT8
**)ret
= heap_val
;
4126 FIXME( "read option %u not supported\n", option
);
4133 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4134 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4135 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4136 WS_HEAP
*heap
, void *ret
, ULONG size
)
4138 WS_XML_UTF8_TEXT
*utf8
;
4145 FIXME( "description not supported\n" );
4148 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4149 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
4154 case WS_READ_REQUIRED_VALUE
:
4155 if (!found
) return WS_E_INVALID_FORMAT
;
4158 case WS_READ_NILLABLE_VALUE
:
4159 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
4160 *(UINT16
*)ret
= val
;
4163 case WS_READ_REQUIRED_POINTER
:
4164 if (!found
) return WS_E_INVALID_FORMAT
;
4167 case WS_READ_OPTIONAL_POINTER
:
4168 case WS_READ_NILLABLE_POINTER
:
4170 UINT16
*heap_val
= NULL
;
4171 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4174 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4177 *(UINT16
**)ret
= heap_val
;
4181 FIXME( "read option %u not supported\n", option
);
4188 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4189 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4190 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4191 WS_HEAP
*heap
, void *ret
, ULONG size
)
4193 WS_XML_UTF8_TEXT
*utf8
;
4200 FIXME( "description not supported\n" );
4203 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4204 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
4209 case WS_READ_REQUIRED_VALUE
:
4210 if (!found
) return WS_E_INVALID_FORMAT
;
4213 case WS_READ_NILLABLE_VALUE
:
4214 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
4215 *(UINT32
*)ret
= val
;
4218 case WS_READ_REQUIRED_POINTER
:
4219 if (!found
) return WS_E_INVALID_FORMAT
;
4222 case WS_READ_OPTIONAL_POINTER
:
4223 case WS_READ_NILLABLE_POINTER
:
4225 UINT32
*heap_val
= NULL
;
4226 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4229 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4232 *(UINT32
**)ret
= heap_val
;
4236 FIXME( "read option %u not supported\n", option
);
4243 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4244 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4245 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4246 WS_HEAP
*heap
, void *ret
, ULONG size
)
4248 WS_XML_UTF8_TEXT
*utf8
;
4255 FIXME( "description not supported\n" );
4258 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4259 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
)) != S_OK
)
4264 case WS_READ_REQUIRED_VALUE
:
4265 if (!found
) return WS_E_INVALID_FORMAT
;
4268 case WS_READ_NILLABLE_VALUE
:
4269 if (size
!= sizeof(UINT64
)) return E_INVALIDARG
;
4270 *(UINT64
*)ret
= val
;
4273 case WS_READ_REQUIRED_POINTER
:
4274 if (!found
) return WS_E_INVALID_FORMAT
;
4277 case WS_READ_OPTIONAL_POINTER
:
4278 case WS_READ_NILLABLE_POINTER
:
4280 UINT64
*heap_val
= NULL
;
4281 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4284 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4287 *(UINT64
**)ret
= heap_val
;
4291 FIXME( "read option %u not supported\n", option
);
4298 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4299 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4300 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4301 WS_HEAP
*heap
, void *ret
, ULONG size
)
4303 WS_XML_UTF8_TEXT
*utf8
;
4308 if (desc
) FIXME( "ignoring description\n" );
4310 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4311 if (found
&& (hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4315 case WS_READ_REQUIRED_VALUE
:
4316 if (!found
) return WS_E_INVALID_FORMAT
;
4319 case WS_READ_NILLABLE_VALUE
:
4320 if (size
!= sizeof(double)) return E_INVALIDARG
;
4321 *(double *)ret
= val
;
4324 case WS_READ_REQUIRED_POINTER
:
4325 if (!found
) return WS_E_INVALID_FORMAT
;
4328 case WS_READ_OPTIONAL_POINTER
:
4329 case WS_READ_NILLABLE_POINTER
:
4331 double *heap_val
= NULL
;
4332 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4335 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4338 *(double **)ret
= heap_val
;
4342 FIXME( "read option %u not supported\n", option
);
4349 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4350 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4351 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4352 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
4354 WS_XML_UTF8_TEXT
*utf8
;
4361 FIXME( "description not supported\n" );
4364 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4365 if (found
&& !(str
= xmltext_to_widechar( heap
, &utf8
->text
))) return WS_E_QUOTA_EXCEEDED
;
4369 case WS_READ_REQUIRED_POINTER
:
4370 if (!found
) return WS_E_INVALID_FORMAT
;
4373 case WS_READ_OPTIONAL_POINTER
:
4374 case WS_READ_NILLABLE_POINTER
:
4375 if (size
!= sizeof(str
)) return E_INVALIDARG
;
4380 FIXME( "read option %u not supported\n", option
);
4387 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
4390 for (i
= 0; i
< desc
->valueCount
; i
++)
4392 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
4394 *ret
= desc
->values
[i
].value
;
4398 return WS_E_INVALID_FORMAT
;
4401 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4402 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4403 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4404 WS_HEAP
*heap
, void *ret
, ULONG size
)
4406 WS_XML_UTF8_TEXT
*utf8
;
4411 if (!desc
) return E_INVALIDARG
;
4413 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4414 if (found
&& (hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
4418 case WS_READ_REQUIRED_VALUE
:
4419 if (!found
) return WS_E_INVALID_FORMAT
;
4422 case WS_READ_NILLABLE_VALUE
:
4423 if (size
!= sizeof(int)) return E_INVALIDARG
;
4427 case WS_READ_REQUIRED_POINTER
:
4428 if (!found
) return WS_E_INVALID_FORMAT
;
4431 case WS_READ_OPTIONAL_POINTER
:
4432 case WS_READ_NILLABLE_POINTER
:
4434 int *heap_val
= NULL
;
4435 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4438 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4441 *(int **)ret
= heap_val
;
4445 FIXME( "read option %u not supported\n", option
);
4452 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4453 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4454 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4455 WS_HEAP
*heap
, void *ret
, ULONG size
)
4457 WS_XML_UTF8_TEXT
*utf8
;
4459 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
4462 if (desc
) FIXME( "ignoring description\n" );
4464 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4465 if (found
&& (hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4469 case WS_READ_REQUIRED_VALUE
:
4470 if (!found
) return WS_E_INVALID_FORMAT
;
4473 case WS_READ_NILLABLE_VALUE
:
4474 if (size
!= sizeof(WS_DATETIME
)) return E_INVALIDARG
;
4475 *(WS_DATETIME
*)ret
= val
;
4478 case WS_READ_REQUIRED_POINTER
:
4479 if (!found
) return WS_E_INVALID_FORMAT
;
4482 case WS_READ_OPTIONAL_POINTER
:
4483 case WS_READ_NILLABLE_POINTER
:
4485 WS_DATETIME
*heap_val
= NULL
;
4486 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4489 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4492 *(WS_DATETIME
**)ret
= heap_val
;
4496 FIXME( "read option %u not supported\n", option
);
4503 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4504 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4505 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4506 WS_HEAP
*heap
, void *ret
, ULONG size
)
4508 WS_XML_UTF8_TEXT
*utf8
;
4513 if (desc
) FIXME( "ignoring description\n" );
4515 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4516 if (found
&& (hr
= str_to_guid( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4520 case WS_READ_REQUIRED_VALUE
:
4521 if (!found
) return WS_E_INVALID_FORMAT
;
4524 case WS_READ_NILLABLE_VALUE
:
4525 if (size
!= sizeof(GUID
)) return E_INVALIDARG
;
4529 case WS_READ_REQUIRED_POINTER
:
4530 if (!found
) return WS_E_INVALID_FORMAT
;
4533 case WS_READ_OPTIONAL_POINTER
:
4534 case WS_READ_NILLABLE_POINTER
:
4536 GUID
*heap_val
= NULL
;
4537 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4540 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4543 *(GUID
**)ret
= heap_val
;
4547 FIXME( "read option %u not supported\n", option
);
4554 static HRESULT
read_type_bytes( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4555 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4556 const WS_BYTES_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4557 WS_HEAP
*heap
, void *ret
, ULONG size
)
4559 WS_XML_UTF8_TEXT
*utf8
;
4564 if (desc
) FIXME( "ignoring description\n" );
4566 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4567 if (found
&& (hr
= str_to_bytes( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4572 case WS_READ_REQUIRED_VALUE
:
4573 if (!found
) return WS_E_INVALID_FORMAT
;
4576 case WS_READ_NILLABLE_VALUE
:
4577 if (size
!= sizeof(WS_BYTES
)) return E_INVALIDARG
;
4578 *(WS_BYTES
*)ret
= val
;
4581 case WS_READ_REQUIRED_POINTER
:
4582 if (!found
) return WS_E_INVALID_FORMAT
;
4585 case WS_READ_OPTIONAL_POINTER
:
4586 case WS_READ_NILLABLE_POINTER
:
4588 WS_BYTES
*heap_val
= NULL
;
4589 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4592 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4595 *(WS_BYTES
**)ret
= heap_val
;
4599 FIXME( "read option %u not supported\n", option
);
4606 static BOOL
is_empty_text_node( const struct node
*node
)
4608 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4609 const WS_XML_UTF8_TEXT
*utf8
;
4612 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
4613 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
4615 ERR( "unhandled text type %u\n", text
->text
->textType
);
4618 utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
4619 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
4623 static HRESULT
read_next_node( struct reader
*reader
)
4625 if (reader
->current
== reader
->last
) return read_node( reader
);
4626 if (move_to_child_node( &reader
->current
)) return S_OK
;
4627 if (move_to_next_node( &reader
->current
)) return S_OK
;
4628 if (!move_to_parent_node( &reader
->current
)) return WS_E_INVALID_FORMAT
;
4629 if (move_to_next_node( &reader
->current
)) return S_OK
;
4630 return WS_E_INVALID_FORMAT
;
4633 /* skips comment and empty text nodes */
4634 static HRESULT
read_type_next_node( struct reader
*reader
)
4639 WS_XML_NODE_TYPE type
;
4641 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
4642 type
= node_type( reader
->current
);
4643 if (type
== WS_XML_NODE_TYPE_COMMENT
||
4644 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
4649 static BOOL
match_current_element( struct reader
*reader
, const WS_XML_STRING
*localname
,
4650 const WS_XML_STRING
*ns
)
4652 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
4653 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
4654 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
4655 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
4658 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
4659 const WS_XML_STRING
*ns
)
4665 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
4666 if (reader
->current
== reader
->last
)
4669 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
4670 if (!found
) return WS_E_INVALID_FORMAT
;
4672 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
4674 node
= reader
->current
;
4675 attr
= reader
->current_attr
;
4677 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
4678 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
4680 reader
->current
= node
;
4681 reader
->current_attr
= attr
;
4683 return WS_E_INVALID_FORMAT
;
4686 ULONG
get_type_size( WS_TYPE type
, const WS_STRUCT_DESCRIPTION
*desc
)
4692 return sizeof(INT8
);
4695 case WS_UINT16_TYPE
:
4696 return sizeof(INT16
);
4700 case WS_UINT32_TYPE
:
4702 return sizeof(INT32
);
4705 case WS_UINT64_TYPE
:
4706 return sizeof(INT64
);
4708 case WS_DOUBLE_TYPE
:
4709 return sizeof(double);
4711 case WS_DATETIME_TYPE
:
4712 return sizeof(WS_DATETIME
);
4715 return sizeof(GUID
);
4717 case WS_STRING_TYPE
:
4718 return sizeof(WS_STRING
);
4721 return sizeof(WCHAR
*);
4724 return sizeof(WS_BYTES
);
4726 case WS_XML_STRING_TYPE
:
4727 return sizeof(WS_XML_STRING
);
4729 case WS_STRUCT_TYPE
:
4732 case WS_DESCRIPTION_TYPE
:
4733 return sizeof(WS_STRUCT_DESCRIPTION
*);
4736 ERR( "unhandled type %u\n", type
);
4741 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
, ULONG options
)
4743 if (options
& WS_FIELD_POINTER
)
4745 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
4746 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
4747 return WS_READ_REQUIRED_POINTER
;
4758 case WS_UINT16_TYPE
:
4759 case WS_UINT32_TYPE
:
4760 case WS_UINT64_TYPE
:
4761 case WS_DOUBLE_TYPE
:
4762 case WS_DATETIME_TYPE
:
4764 case WS_STRING_TYPE
:
4766 case WS_XML_STRING_TYPE
:
4767 case WS_STRUCT_TYPE
:
4769 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_READ_NILLABLE_VALUE
;
4770 return WS_READ_REQUIRED_VALUE
;
4773 case WS_DESCRIPTION_TYPE
:
4774 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
4775 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
4776 return WS_READ_REQUIRED_POINTER
;
4779 FIXME( "unhandled type %u\n", type
);
4784 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
4785 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
4788 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
4789 WS_HEAP
*heap
, void **ret
, ULONG
*count
)
4792 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
4793 WS_READ_OPTION option
;
4796 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
4798 /* wrapper element */
4799 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
4802 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
4803 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
4805 item_size
= sizeof(void *);
4807 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
4810 if (nb_items
>= nb_allocated
)
4812 SIZE_T old_size
= nb_allocated
* item_size
, new_size
= old_size
* 2;
4813 if (!(buf
= ws_realloc_zero( heap
, buf
, old_size
, new_size
)))
4814 return WS_E_QUOTA_EXCEEDED
;
4817 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
4818 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
4819 if (hr
== WS_E_INVALID_FORMAT
) break;
4822 ws_free( heap
, buf
, nb_allocated
* item_size
);
4825 offset
+= item_size
;
4829 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
4831 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
4833 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
4834 desc
->itemRange
->maxItemCount
);
4835 ws_free( heap
, buf
, nb_allocated
* item_size
);
4836 return WS_E_INVALID_FORMAT
;
4845 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
4846 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
4849 if (reader
->current
== reader
->last
)
4852 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
4853 if (!found
) return WS_E_INVALID_FORMAT
;
4855 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
4856 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
4858 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
4859 desc
->typeDescription
, option
, heap
, ret
, size
);
4862 static HRESULT
read_type_struct_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
4863 WS_HEAP
*heap
, char *buf
, ULONG offset
)
4866 WS_READ_OPTION option
;
4870 if (!desc
) return E_INVALIDARG
;
4871 if (desc
->options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
4873 FIXME( "options %08x not supported\n", desc
->options
);
4876 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
4878 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
4879 size
= get_type_size( desc
->type
, desc
->typeDescription
);
4881 size
= sizeof(void *);
4884 switch (desc
->mapping
)
4886 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING
:
4887 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
4890 case WS_ATTRIBUTE_FIELD_MAPPING
:
4891 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
4892 desc
->typeDescription
, option
, heap
, ptr
, size
);
4895 case WS_ELEMENT_FIELD_MAPPING
:
4896 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
4897 desc
->typeDescription
, option
, heap
, ptr
, size
);
4900 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
4903 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, &count
);
4904 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
4907 case WS_TEXT_FIELD_MAPPING
:
4908 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
4912 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
4916 if (hr
== WS_E_INVALID_FORMAT
)
4920 case WS_READ_REQUIRED_VALUE
:
4921 case WS_READ_REQUIRED_POINTER
:
4922 return WS_E_INVALID_FORMAT
;
4924 case WS_READ_NILLABLE_VALUE
:
4925 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
4928 case WS_READ_OPTIONAL_POINTER
:
4929 case WS_READ_NILLABLE_POINTER
:
4930 *(void **)ptr
= NULL
;
4934 ERR( "unhandled option %u\n", option
);
4942 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4943 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4944 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4945 WS_HEAP
*heap
, void *ret
, ULONG size
)
4951 if (!desc
) return E_INVALIDARG
;
4952 if (desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
4954 FIXME( "struct options %08x not supported\n",
4955 desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
);
4960 case WS_READ_REQUIRED_POINTER
:
4961 case WS_READ_OPTIONAL_POINTER
:
4962 case WS_READ_NILLABLE_POINTER
:
4963 if (size
!= sizeof(void *)) return E_INVALIDARG
;
4964 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
4967 case WS_READ_REQUIRED_VALUE
:
4968 case WS_READ_NILLABLE_VALUE
:
4969 if (size
!= desc
->size
) return E_INVALIDARG
;
4974 FIXME( "unhandled read option %u\n", option
);
4978 for (i
= 0; i
< desc
->fieldCount
; i
++)
4980 offset
= desc
->fields
[i
]->offset
;
4981 if ((hr
= read_type_struct_field( reader
, desc
->fields
[i
], heap
, buf
, offset
)) != S_OK
)
4987 case WS_READ_REQUIRED_POINTER
:
4990 ws_free( heap
, buf
, desc
->size
);
4993 *(char **)ret
= buf
;
4996 case WS_READ_OPTIONAL_POINTER
:
4997 case WS_READ_NILLABLE_POINTER
:
4998 if (is_nil_value( buf
, desc
->size
))
5000 ws_free( heap
, buf
, desc
->size
);
5003 *(char **)ret
= buf
;
5006 case WS_READ_REQUIRED_VALUE
:
5007 case WS_READ_NILLABLE_VALUE
:
5008 if (hr
!= S_OK
) return hr
;
5012 ERR( "unhandled read option %u\n", option
);
5016 if (desc
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5018 struct node
*parent
= find_parent( reader
);
5019 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
5024 static HRESULT
start_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
5025 const WS_XML_STRING
*ns
)
5029 case WS_ELEMENT_TYPE_MAPPING
:
5030 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5031 return read_type_next_element_node( reader
, localname
, ns
);
5033 case WS_ANY_ELEMENT_TYPE_MAPPING
:
5034 case WS_ATTRIBUTE_TYPE_MAPPING
:
5038 FIXME( "unhandled mapping %u\n", mapping
);
5043 static HRESULT
read_type_endelement_node( struct reader
*reader
)
5045 const struct node
*parent
= find_parent( reader
);
5050 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
5051 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
&& reader
->current
->parent
== parent
)
5055 if (read_end_of_data( reader
) || !(parent
->flags
& NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
)) break;
5058 return WS_E_INVALID_FORMAT
;
5061 static HRESULT
end_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
)
5065 case WS_ELEMENT_TYPE_MAPPING
:
5066 return read_type_endelement_node( reader
);
5068 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5069 return read_type_next_node( reader
);
5071 case WS_ATTRIBUTE_TYPE_MAPPING
:
5077 static HRESULT
is_nil_element( const WS_XML_ELEMENT_NODE
*elem
)
5079 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
5080 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
5083 for (i
= 0; i
< elem
->attributeCount
; i
++)
5085 const WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[i
]->value
;
5087 if (elem
->attributes
[i
]->isXmlNs
) continue;
5088 if (WsXmlStringEquals( elem
->attributes
[i
]->localName
, &localname
, NULL
) == S_OK
&&
5089 WsXmlStringEquals( elem
->attributes
[i
]->ns
, &ns
, NULL
) == S_OK
&&
5090 text
->value
.length
== 4 && !memcmp( text
->value
.bytes
, "true", 4 )) return TRUE
;
5095 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5096 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
, const void *desc
,
5097 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
)
5101 if ((hr
= start_mapping( reader
, mapping
, localname
, ns
)) != S_OK
) return hr
;
5103 if (mapping
== WS_ELEMENT_TYPE_MAPPING
&& is_nil_element( &reader
->current
->hdr
))
5105 if (option
!= WS_READ_NILLABLE_POINTER
&& option
!= WS_READ_NILLABLE_VALUE
) return WS_E_INVALID_FORMAT
;
5106 return end_mapping( reader
, mapping
);
5112 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5117 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5122 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5127 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5132 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5137 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5141 case WS_UINT16_TYPE
:
5142 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5146 case WS_UINT32_TYPE
:
5147 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5151 case WS_UINT64_TYPE
:
5152 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5156 case WS_DOUBLE_TYPE
:
5157 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5161 case WS_DATETIME_TYPE
:
5162 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5167 if ((hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5172 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5177 if ((hr
= read_type_bytes( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5181 case WS_STRUCT_TYPE
:
5182 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5187 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5192 FIXME( "type %u not supported\n", type
);
5196 return end_mapping( reader
, mapping
);
5199 /**************************************************************************
5200 * WsReadType [webservices.@]
5202 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5203 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
5204 ULONG size
, WS_ERROR
*error
)
5206 struct reader
*reader
= (struct reader
*)handle
;
5209 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
5211 if (error
) FIXME( "ignoring error parameter\n" );
5213 if (!reader
|| !value
) return E_INVALIDARG
;
5215 EnterCriticalSection( &reader
->cs
);
5217 if (reader
->magic
!= READER_MAGIC
)
5219 LeaveCriticalSection( &reader
->cs
);
5220 return E_INVALIDARG
;
5223 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
5225 LeaveCriticalSection( &reader
->cs
);
5231 case WS_ELEMENT_TYPE_MAPPING
:
5232 hr
= read_node( reader
);
5239 if (hr
== S_OK
&& !read_end_of_data( reader
)) hr
= WS_E_INVALID_FORMAT
;
5241 LeaveCriticalSection( &reader
->cs
);
5245 /**************************************************************************
5246 * WsReadElement [webservices.@]
5248 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
5249 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5252 struct reader
*reader
= (struct reader
*)handle
;
5255 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5256 if (error
) FIXME( "ignoring error parameter\n" );
5258 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5260 EnterCriticalSection( &reader
->cs
);
5262 if (reader
->magic
!= READER_MAGIC
)
5264 LeaveCriticalSection( &reader
->cs
);
5265 return E_INVALIDARG
;
5268 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
5269 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5271 LeaveCriticalSection( &reader
->cs
);
5275 /**************************************************************************
5276 * WsReadValue [webservices.@]
5278 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
5281 struct reader
*reader
= (struct reader
*)handle
;
5282 WS_TYPE type
= map_value_type( value_type
);
5285 TRACE( "%p %u %p %u %p\n", handle
, type
, value
, size
, error
);
5286 if (error
) FIXME( "ignoring error parameter\n" );
5288 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
5290 EnterCriticalSection( &reader
->cs
);
5292 if (reader
->magic
!= READER_MAGIC
)
5294 LeaveCriticalSection( &reader
->cs
);
5295 return E_INVALIDARG
;
5298 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
5299 NULL
, value
, size
);
5301 LeaveCriticalSection( &reader
->cs
);
5305 /**************************************************************************
5306 * WsReadAttribute [webservices.@]
5308 HRESULT WINAPI
WsReadAttribute( WS_XML_READER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
5309 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5312 struct reader
*reader
= (struct reader
*)handle
;
5315 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5316 if (error
) FIXME( "ignoring error parameter\n" );
5318 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5320 EnterCriticalSection( &reader
->cs
);
5322 if (reader
->magic
!= READER_MAGIC
)
5324 LeaveCriticalSection( &reader
->cs
);
5325 return E_INVALIDARG
;
5328 if (!reader
->input_type
)
5330 LeaveCriticalSection( &reader
->cs
);
5331 return WS_E_INVALID_OPERATION
;
5334 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->attributeLocalName
,
5335 desc
->attributeNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5337 LeaveCriticalSection( &reader
->cs
);
5341 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5343 static const char bom
[] = {0xef,0xbb,0xbf};
5344 const unsigned char *p
= data
;
5346 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
5347 (size
> 2 && !(*offset
= 0));
5350 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5352 static const char bom
[] = {0xff,0xfe};
5353 const unsigned char *p
= data
;
5355 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
5356 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
5359 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5363 /* FIXME: parse xml declaration */
5365 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
5366 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
5369 FIXME( "charset not recognized\n" );
5373 TRACE( "detected charset %u\n", ret
);
5377 static void set_input_buffer( struct reader
*reader
, struct xmlbuf
*buf
, const unsigned char *data
, ULONG size
)
5379 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
5380 reader
->input_buf
= buf
;
5381 reader
->input_data
= data
;
5382 reader
->input_size
= size
;
5384 reader
->read_size
= reader
->input_size
;
5385 reader
->read_pos
= 0;
5386 reader
->read_bufptr
= reader
->input_data
;
5388 reader
->text_conv_offset
= 0;
5391 /**************************************************************************
5392 * WsSetInput [webservices.@]
5394 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
5395 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
5396 ULONG count
, WS_ERROR
*error
)
5398 struct reader
*reader
= (struct reader
*)handle
;
5400 ULONG i
, offset
= 0;
5403 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
5404 if (error
) FIXME( "ignoring error parameter\n" );
5406 if (!reader
) return E_INVALIDARG
;
5408 EnterCriticalSection( &reader
->cs
);
5410 if (reader
->magic
!= READER_MAGIC
)
5412 LeaveCriticalSection( &reader
->cs
);
5413 return E_INVALIDARG
;
5416 for (i
= 0; i
< count
; i
++)
5418 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
5419 properties
[i
].valueSize
);
5420 if (hr
!= S_OK
) goto done
;
5423 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
5425 switch (encoding
->encodingType
)
5427 case WS_XML_READER_ENCODING_TYPE_TEXT
:
5429 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
5430 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
5431 WS_CHARSET charset
= text
->charSet
;
5433 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
5435 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
5440 if (charset
== WS_CHARSET_AUTO
)
5441 charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
5443 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
5444 &charset
, sizeof(charset
) );
5445 if (hr
!= S_OK
) goto done
;
5447 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
5450 case WS_XML_READER_ENCODING_TYPE_BINARY
:
5452 WS_XML_READER_BINARY_ENCODING
*bin
= (WS_XML_READER_BINARY_ENCODING
*)encoding
;
5453 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_BINARY
;
5454 reader
->dict
= bin
->staticDictionary
;
5458 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
5463 switch (input
->inputType
)
5465 case WS_XML_READER_INPUT_TYPE_BUFFER
:
5467 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
5468 set_input_buffer( reader
, NULL
, (const unsigned char *)buf
->encodedData
+ offset
,
5469 buf
->encodedDataSize
- offset
);
5473 FIXME( "input type %u not supported\n", input
->inputType
);
5478 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
5479 else read_insert_bof( reader
, node
);
5482 LeaveCriticalSection( &reader
->cs
);
5486 /**************************************************************************
5487 * WsSetInputToBuffer [webservices.@]
5489 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
5490 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
5493 struct reader
*reader
= (struct reader
*)handle
;
5494 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
5497 ULONG i
, offset
= 0;
5500 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
5501 if (error
) FIXME( "ignoring error parameter\n" );
5503 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
5505 EnterCriticalSection( &reader
->cs
);
5507 if (reader
->magic
!= READER_MAGIC
)
5509 LeaveCriticalSection( &reader
->cs
);
5510 return E_INVALIDARG
;
5513 for (i
= 0; i
< count
; i
++)
5515 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
5516 properties
[i
].valueSize
);
5517 if (hr
!= S_OK
) goto done
;
5520 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
5522 charset
= detect_charset( xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
, &offset
);
5523 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
, &charset
,
5525 if (hr
!= S_OK
) goto done
;
5527 set_input_buffer( reader
, xmlbuf
, xmlbuf
->bytes
.bytes
+ offset
, xmlbuf
->bytes
.length
- offset
);
5528 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
5529 else read_insert_bof( reader
, node
);
5532 LeaveCriticalSection( &reader
->cs
);
5536 /**************************************************************************
5537 * WsXmlStringEquals [webservices.@]
5539 HRESULT WINAPI
WsXmlStringEquals( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
, WS_ERROR
*error
)
5541 TRACE( "%s %s %p\n", debugstr_xmlstr(str1
), debugstr_xmlstr(str2
), error
);
5542 if (error
) FIXME( "ignoring error parameter\n" );
5544 if (!str1
|| !str2
) return E_INVALIDARG
;
5546 if (str1
->length
!= str2
->length
) return S_FALSE
;
5547 if (!memcmp( str1
->bytes
, str2
->bytes
, str1
->length
)) return S_OK
;
5551 /**************************************************************************
5552 * WsGetReaderPosition [webservices.@]
5554 HRESULT WINAPI
WsGetReaderPosition( WS_XML_READER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
5556 struct reader
*reader
= (struct reader
*)handle
;
5558 TRACE( "%p %p %p\n", handle
, pos
, error
);
5559 if (error
) FIXME( "ignoring error parameter\n" );
5561 if (!reader
|| !pos
) return E_INVALIDARG
;
5563 EnterCriticalSection( &reader
->cs
);
5565 if (reader
->magic
!= READER_MAGIC
)
5567 LeaveCriticalSection( &reader
->cs
);
5568 return E_INVALIDARG
;
5571 if (!reader
->input_buf
)
5573 LeaveCriticalSection( &reader
->cs
);
5574 return WS_E_INVALID_OPERATION
;
5577 pos
->buffer
= (WS_XML_BUFFER
*)reader
->input_buf
;
5578 pos
->node
= reader
->current
;
5580 LeaveCriticalSection( &reader
->cs
);
5584 /**************************************************************************
5585 * WsSetReaderPosition [webservices.@]
5587 HRESULT WINAPI
WsSetReaderPosition( WS_XML_READER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
5589 struct reader
*reader
= (struct reader
*)handle
;
5591 TRACE( "%p %p %p\n", handle
, pos
, error
);
5592 if (error
) FIXME( "ignoring error parameter\n" );
5594 if (!reader
|| !pos
) return E_INVALIDARG
;
5596 EnterCriticalSection( &reader
->cs
);
5598 if (reader
->magic
!= READER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= reader
->input_buf
)
5600 LeaveCriticalSection( &reader
->cs
);
5601 return E_INVALIDARG
;
5604 if (!reader
->input_buf
)
5606 LeaveCriticalSection( &reader
->cs
);
5607 return WS_E_INVALID_OPERATION
;
5610 reader
->current
= pos
->node
;
5612 LeaveCriticalSection( &reader
->cs
);
5616 static HRESULT
utf8_to_base64( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_BASE64_TEXT
*base64
)
5618 if (utf8
->value
.length
% 4) return WS_E_INVALID_FORMAT
;
5619 if (!(base64
->bytes
= heap_alloc( utf8
->value
.length
* 3 / 4 ))) return E_OUTOFMEMORY
;
5620 base64
->length
= decode_base64( utf8
->value
.bytes
, utf8
->value
.length
, base64
->bytes
);
5624 /**************************************************************************
5625 * WsReadBytes [webservices.@]
5627 HRESULT WINAPI
WsReadBytes( WS_XML_READER
*handle
, void *bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
5629 struct reader
*reader
= (struct reader
*)handle
;
5632 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
5633 if (error
) FIXME( "ignoring error parameter\n" );
5635 if (!reader
) return E_INVALIDARG
;
5637 EnterCriticalSection( &reader
->cs
);
5639 if (reader
->magic
!= READER_MAGIC
)
5641 LeaveCriticalSection( &reader
->cs
);
5642 return E_INVALIDARG
;
5645 if (!reader
->input_type
)
5647 LeaveCriticalSection( &reader
->cs
);
5648 return WS_E_INVALID_OPERATION
;
5653 LeaveCriticalSection( &reader
->cs
);
5654 return E_INVALIDARG
;
5658 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
5660 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
5661 WS_XML_BASE64_TEXT base64
;
5663 if ((hr
= utf8_to_base64( (const WS_XML_UTF8_TEXT
*)text
->text
, &base64
)) != S_OK
)
5665 LeaveCriticalSection( &reader
->cs
);
5668 if (reader
->text_conv_offset
== base64
.length
)
5670 heap_free( base64
.bytes
);
5671 hr
= read_node( reader
);
5672 LeaveCriticalSection( &reader
->cs
);
5675 *count
= min( base64
.length
- reader
->text_conv_offset
, max_count
);
5676 memcpy( bytes
, base64
.bytes
+ reader
->text_conv_offset
, *count
);
5677 reader
->text_conv_offset
+= *count
;
5678 heap_free( base64
.bytes
);
5681 LeaveCriticalSection( &reader
->cs
);
5685 static HRESULT
utf8_to_utf16( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_UTF16_TEXT
*utf16
)
5687 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
5688 if (!(utf16
->bytes
= heap_alloc( len
* sizeof(WCHAR
) ))) return E_OUTOFMEMORY
;
5689 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, (WCHAR
*)utf16
->bytes
, len
);
5690 utf16
->byteCount
= len
* sizeof(WCHAR
);
5694 /**************************************************************************
5695 * WsReadChars [webservices.@]
5697 HRESULT WINAPI
WsReadChars( WS_XML_READER
*handle
, WCHAR
*chars
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
5699 struct reader
*reader
= (struct reader
*)handle
;
5701 TRACE( "%p %p %u %p %p\n", handle
, chars
, max_count
, count
, error
);
5702 if (error
) FIXME( "ignoring error parameter\n" );
5704 if (!reader
) return E_INVALIDARG
;
5706 EnterCriticalSection( &reader
->cs
);
5708 if (reader
->magic
!= READER_MAGIC
)
5710 LeaveCriticalSection( &reader
->cs
);
5711 return E_INVALIDARG
;
5714 if (!reader
->input_type
)
5716 LeaveCriticalSection( &reader
->cs
);
5717 return WS_E_INVALID_OPERATION
;
5722 LeaveCriticalSection( &reader
->cs
);
5723 return E_INVALIDARG
;
5727 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& chars
)
5729 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
5730 WS_XML_UTF16_TEXT utf16
;
5733 if ((hr
= utf8_to_utf16( (const WS_XML_UTF8_TEXT
*)text
->text
, &utf16
)) != S_OK
)
5735 LeaveCriticalSection( &reader
->cs
);
5738 if (reader
->text_conv_offset
== utf16
.byteCount
/ sizeof(WCHAR
))
5740 heap_free( utf16
.bytes
);
5741 hr
= read_node( reader
);
5742 LeaveCriticalSection( &reader
->cs
);
5745 *count
= min( utf16
.byteCount
/ sizeof(WCHAR
) - reader
->text_conv_offset
, max_count
);
5746 memcpy( chars
, utf16
.bytes
+ reader
->text_conv_offset
* sizeof(WCHAR
), *count
* sizeof(WCHAR
) );
5747 reader
->text_conv_offset
+= *count
;
5748 heap_free( utf16
.bytes
);
5751 LeaveCriticalSection( &reader
->cs
);
5755 /**************************************************************************
5756 * WsReadCharsUtf8 [webservices.@]
5758 HRESULT WINAPI
WsReadCharsUtf8( WS_XML_READER
*handle
, BYTE
*bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
5760 struct reader
*reader
= (struct reader
*)handle
;
5763 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
5764 if (error
) FIXME( "ignoring error parameter\n" );
5766 if (!reader
) return E_INVALIDARG
;
5768 EnterCriticalSection( &reader
->cs
);
5770 if (reader
->magic
!= READER_MAGIC
)
5772 LeaveCriticalSection( &reader
->cs
);
5773 return E_INVALIDARG
;
5776 if (!reader
->input_type
)
5778 LeaveCriticalSection( &reader
->cs
);
5779 return WS_E_INVALID_OPERATION
;
5784 LeaveCriticalSection( &reader
->cs
);
5785 return E_INVALIDARG
;
5789 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
5791 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
5792 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
5794 if (reader
->text_conv_offset
== utf8
->value
.length
)
5796 hr
= read_node( reader
);
5797 LeaveCriticalSection( &reader
->cs
);
5800 *count
= min( utf8
->value
.length
- reader
->text_conv_offset
, max_count
);
5801 memcpy( bytes
, utf8
->value
.bytes
+ reader
->text_conv_offset
, *count
);
5802 reader
->text_conv_offset
+= *count
;
5805 LeaveCriticalSection( &reader
->cs
);
5809 HRESULT
get_param_desc( const WS_STRUCT_DESCRIPTION
*desc
, USHORT index
, const WS_FIELD_DESCRIPTION
**ret
)
5811 if (index
>= desc
->fieldCount
) return E_INVALIDARG
;
5812 *ret
= desc
->fields
[index
];
5816 static ULONG
get_field_size( const WS_FIELD_DESCRIPTION
*desc
)
5818 WS_READ_OPTION option
;
5821 switch ((option
= get_field_read_option( desc
->type
, desc
->options
)))
5823 case WS_READ_REQUIRED_POINTER
:
5824 case WS_READ_OPTIONAL_POINTER
:
5825 case WS_READ_NILLABLE_POINTER
:
5826 size
= sizeof(void *);
5829 case WS_READ_REQUIRED_VALUE
:
5830 case WS_READ_NILLABLE_VALUE
:
5831 size
= get_type_size( desc
->type
, desc
->typeDescription
);
5835 WARN( "unhandled option %u\n", option
);
5842 static HRESULT
read_param( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
, void *ret
)
5844 if (!ret
&& !(ret
= ws_alloc_zero( heap
, get_field_size(desc
) ))) return WS_E_QUOTA_EXCEEDED
;
5845 return read_type_struct_field( reader
, desc
, heap
, ret
, 0 );
5848 static HRESULT
read_param_array( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
,
5849 void **ret
, ULONG
*count
)
5851 if (!ret
&& !(ret
= ws_alloc_zero( heap
, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED
;
5852 return read_type_repeating_element( reader
, desc
, heap
, ret
, count
);
5855 static void set_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, ULONG len
,
5859 for (i
= 0; i
< count
; i
++)
5861 if (params
[i
].outputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
5863 if ((ptr
= *(ULONG
**)args
[i
])) *ptr
= len
;
5868 HRESULT
read_output_params( WS_XML_READER
*handle
, WS_HEAP
*heap
, const WS_ELEMENT_DESCRIPTION
*desc
,
5869 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
5871 struct reader
*reader
= (struct reader
*)handle
;
5872 const WS_STRUCT_DESCRIPTION
*desc_struct
;
5873 const WS_FIELD_DESCRIPTION
*desc_field
;
5877 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
5879 EnterCriticalSection( &reader
->cs
);
5881 if (reader
->magic
!= READER_MAGIC
)
5883 LeaveCriticalSection( &reader
->cs
);
5884 return E_INVALIDARG
;
5887 if ((hr
= start_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
)
5890 for (i
= 0; i
< count
; i
++)
5892 if (params
[i
].outputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
5893 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
5895 FIXME( "messages type not supported\n" );
5899 if ((hr
= get_param_desc( desc_struct
, params
[i
].outputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
5900 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
5902 void *ptr
= *(void **)args
[i
];
5903 if ((hr
= read_param( reader
, desc_field
, heap
, ptr
)) != S_OK
) goto done
;
5905 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
5907 void **ptr
= *(void ***)args
[i
];
5908 if ((hr
= read_param_array( reader
, desc_field
, heap
, ptr
, &len
)) != S_OK
) goto done
;
5909 set_array_len( params
, count
, params
[i
].outputMessageIndex
, len
, args
);
5913 if (desc_struct
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5915 struct node
*parent
= find_parent( reader
);
5916 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
5919 hr
= end_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
);
5922 LeaveCriticalSection( &reader
->cs
);