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
25 #include "webservices.h"
27 #include "wine/debug.h"
28 #include "wine/list.h"
29 #include "webservices_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
33 ULONG
prop_size( const struct prop_desc
*desc
, ULONG count
)
35 ULONG i
, ret
= count
* sizeof(struct prop
);
36 for (i
= 0; i
< count
; i
++) ret
+= desc
[i
].size
;
40 void prop_init( const struct prop_desc
*desc
, ULONG count
, struct prop
*prop
, void *data
)
44 for (i
= 0; i
< count
; i
++)
47 prop
[i
].size
= desc
[i
].size
;
48 prop
[i
].readonly
= desc
[i
].readonly
;
49 prop
[i
].writeonly
= desc
[i
].writeonly
;
54 HRESULT
prop_set( const struct prop
*prop
, ULONG count
, ULONG id
, const void *value
, ULONG size
)
56 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].readonly
) return E_INVALIDARG
;
57 memcpy( prop
[id
].value
, value
, size
);
61 HRESULT
prop_get( const struct prop
*prop
, ULONG count
, ULONG id
, void *buf
, ULONG size
)
63 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].writeonly
) return E_INVALIDARG
;
64 memcpy( buf
, prop
[id
].value
, prop
[id
].size
);
68 struct node
*alloc_node( WS_XML_NODE_TYPE type
)
72 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
73 ret
->hdr
.node
.nodeType
= type
;
74 list_init( &ret
->entry
);
75 list_init( &ret
->children
);
79 void free_attribute( WS_XML_ATTRIBUTE
*attr
)
82 free_xml_string( attr
->prefix
);
83 free_xml_string( attr
->localName
);
84 free_xml_string( attr
->ns
);
85 heap_free( attr
->value
);
89 void free_node( struct node
*node
)
92 switch (node_type( node
))
94 case WS_XML_NODE_TYPE_ELEMENT
:
96 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
99 for (i
= 0; i
< elem
->attributeCount
; i
++) free_attribute( elem
->attributes
[i
] );
100 heap_free( elem
->attributes
);
101 free_xml_string( elem
->prefix
);
102 free_xml_string( elem
->localName
);
103 free_xml_string( elem
->ns
);
106 case WS_XML_NODE_TYPE_TEXT
:
108 WS_XML_TEXT_NODE
*text
= (WS_XML_TEXT_NODE
*)node
;
109 heap_free( text
->text
);
112 case WS_XML_NODE_TYPE_COMMENT
:
114 WS_XML_COMMENT_NODE
*comment
= (WS_XML_COMMENT_NODE
*)node
;
115 heap_free( comment
->value
.bytes
);
118 case WS_XML_NODE_TYPE_CDATA
:
119 case WS_XML_NODE_TYPE_END_CDATA
:
120 case WS_XML_NODE_TYPE_END_ELEMENT
:
121 case WS_XML_NODE_TYPE_EOF
:
122 case WS_XML_NODE_TYPE_BOF
:
126 ERR( "unhandled type %u\n", node_type( node
) );
132 void destroy_nodes( struct node
*node
)
137 while ((ptr
= list_head( &node
->children
)))
139 struct node
*child
= LIST_ENTRY( ptr
, struct node
, entry
);
140 list_remove( &child
->entry
);
141 destroy_nodes( child
);
146 static WS_XML_ATTRIBUTE
*dup_attribute( const WS_XML_ATTRIBUTE
*src
)
148 WS_XML_ATTRIBUTE
*dst
;
149 const WS_XML_STRING
*prefix
= src
->prefix
;
150 const WS_XML_STRING
*localname
= src
->localName
;
151 const WS_XML_STRING
*ns
= src
->localName
;
152 const WS_XML_TEXT
*text
= src
->value
;
154 if (!(dst
= heap_alloc( sizeof(*dst
) ))) return NULL
;
155 dst
->singleQuote
= src
->singleQuote
;
156 dst
->isXmlNs
= src
->isXmlNs
;
158 if (!prefix
) dst
->prefix
= NULL
;
159 else if (!(dst
->prefix
= dup_xml_string( prefix
))) goto error
;
160 if (!(dst
->localName
= dup_xml_string( localname
))) goto error
;
161 if (!(dst
->ns
= dup_xml_string( ns
))) goto error
;
165 WS_XML_UTF8_TEXT
*utf8
;
166 const WS_XML_UTF8_TEXT
*utf8_src
= (const WS_XML_UTF8_TEXT
*)text
;
167 if (!(utf8
= alloc_utf8_text( utf8_src
->value
.bytes
, utf8_src
->value
.length
))) goto error
;
168 dst
->value
= &utf8
->text
;
174 free_attribute( dst
);
178 static WS_XML_ATTRIBUTE
**dup_attributes( WS_XML_ATTRIBUTE
* const *src
, ULONG count
)
180 WS_XML_ATTRIBUTE
**dst
;
183 if (!(dst
= heap_alloc( sizeof(*dst
) * count
))) return NULL
;
184 for (i
= 0; i
< count
; i
++)
186 if (!(dst
[i
] = dup_attribute( src
[i
] )))
188 for (; i
> 0; i
--) free_attribute( dst
[i
- 1] );
196 static struct node
*dup_element_node( const WS_XML_ELEMENT_NODE
*src
)
199 WS_XML_ELEMENT_NODE
*dst
;
200 ULONG count
= src
->attributeCount
;
201 WS_XML_ATTRIBUTE
**attrs
= src
->attributes
;
202 const WS_XML_STRING
*prefix
= (src
->prefix
&& src
->prefix
->length
) ? src
->prefix
: NULL
;
203 const WS_XML_STRING
*localname
= src
->localName
;
204 const WS_XML_STRING
*ns
= src
->ns
;
206 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
209 if (count
&& !(dst
->attributes
= dup_attributes( attrs
, count
))) goto error
;
210 dst
->attributeCount
= count
;
212 if (prefix
&& !(dst
->prefix
= dup_xml_string( prefix
))) goto error
;
213 if (localname
&& !(dst
->localName
= dup_xml_string( localname
))) goto error
;
214 if (ns
&& !(dst
->ns
= dup_xml_string( ns
))) goto error
;
222 static struct node
*dup_text_node( const WS_XML_TEXT_NODE
*src
)
225 WS_XML_TEXT_NODE
*dst
;
227 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
228 dst
= (WS_XML_TEXT_NODE
*)node
;
232 WS_XML_UTF8_TEXT
*utf8
;
233 const WS_XML_UTF8_TEXT
*utf8_src
= (const WS_XML_UTF8_TEXT
*)src
->text
;
234 if (!(utf8
= alloc_utf8_text( utf8_src
->value
.bytes
, utf8_src
->value
.length
)))
239 dst
->text
= &utf8
->text
;
244 static struct node
*dup_comment_node( const WS_XML_COMMENT_NODE
*src
)
247 WS_XML_COMMENT_NODE
*dst
;
249 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return NULL
;
250 dst
= (WS_XML_COMMENT_NODE
*)node
;
252 if (src
->value
.length
&& !(dst
->value
.bytes
= heap_alloc( src
->value
.length
)))
257 memcpy( dst
->value
.bytes
, src
->value
.bytes
, src
->value
.length
);
258 dst
->value
.length
= src
->value
.length
;
262 static struct node
*dup_node( const struct node
*src
)
264 switch (node_type( src
))
266 case WS_XML_NODE_TYPE_ELEMENT
:
267 return dup_element_node( &src
->hdr
);
269 case WS_XML_NODE_TYPE_TEXT
:
270 return dup_text_node( (const WS_XML_TEXT_NODE
*)src
);
272 case WS_XML_NODE_TYPE_COMMENT
:
273 return dup_comment_node( (const WS_XML_COMMENT_NODE
*)src
);
275 case WS_XML_NODE_TYPE_CDATA
:
276 case WS_XML_NODE_TYPE_END_CDATA
:
277 case WS_XML_NODE_TYPE_END_ELEMENT
:
278 case WS_XML_NODE_TYPE_EOF
:
279 case WS_XML_NODE_TYPE_BOF
:
280 return alloc_node( node_type( src
) );
283 ERR( "unhandled type %u\n", node_type( src
) );
289 static HRESULT
dup_tree( struct node
**dst
, const struct node
*src
)
292 const struct node
*child
;
294 if (!*dst
&& !(*dst
= dup_node( src
))) return E_OUTOFMEMORY
;
297 LIST_FOR_EACH_ENTRY( child
, &src
->children
, struct node
, entry
)
299 HRESULT hr
= E_OUTOFMEMORY
;
300 struct node
*new_child
;
302 if (!(new_child
= dup_node( child
)) || (hr
= dup_tree( &new_child
, child
)) != S_OK
)
304 destroy_nodes( *dst
);
307 new_child
->parent
= parent
;
308 list_add_tail( &parent
->children
, &new_child
->entry
);
313 static const struct prop_desc reader_props
[] =
315 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
316 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
317 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
318 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
319 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
320 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
321 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
322 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
323 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
324 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
325 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
326 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
327 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
328 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
329 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
334 READER_STATE_INITIAL
,
336 READER_STATE_STARTELEMENT
,
337 READER_STATE_STARTATTRIBUTE
,
338 READER_STATE_STARTCDATA
,
341 READER_STATE_ENDELEMENT
,
342 READER_STATE_ENDCDATA
,
343 READER_STATE_COMMENT
,
359 const unsigned char *read_bufptr
;
360 enum reader_state state
;
362 struct node
*current
;
365 struct prefix
*prefixes
;
367 ULONG nb_prefixes_allocated
;
368 WS_XML_READER_ENCODING_TYPE input_enc
;
369 WS_CHARSET input_charset
;
370 WS_XML_READER_INPUT_TYPE input_type
;
371 struct xmlbuf
*input_buf
;
372 const unsigned char *input_data
;
374 ULONG text_conv_offset
;
375 const WS_XML_DICTIONARY
*dict_static
;
376 WS_XML_DICTIONARY
*dict
;
378 struct prop prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
381 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
383 static struct reader
*alloc_reader(void)
385 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
387 ULONG size
= sizeof(*ret
) + prop_size( reader_props
, count
);
389 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
390 if (!(ret
->prefixes
= heap_alloc_zero( sizeof(*ret
->prefixes
) )))
395 ret
->nb_prefixes
= ret
->nb_prefixes_allocated
= 1;
397 ret
->magic
= READER_MAGIC
;
398 InitializeCriticalSection( &ret
->cs
);
399 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": reader.cs");
401 prop_init( reader_props
, count
, ret
->prop
, &ret
[1] );
402 ret
->prop_count
= count
;
406 static void clear_prefixes( struct prefix
*prefixes
, ULONG count
)
409 for (i
= 0; i
< count
; i
++)
411 free_xml_string( prefixes
[i
].str
);
412 prefixes
[i
].str
= NULL
;
413 free_xml_string( prefixes
[i
].ns
);
414 prefixes
[i
].ns
= NULL
;
418 static HRESULT
set_prefix( struct prefix
*prefix
, const WS_XML_STRING
*str
, const WS_XML_STRING
*ns
)
422 free_xml_string( prefix
->str
);
423 if (!(prefix
->str
= dup_xml_string( str
))) return E_OUTOFMEMORY
;
425 if (prefix
->ns
) free_xml_string( prefix
->ns
);
426 if (!(prefix
->ns
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
430 static HRESULT
bind_prefix( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
*ns
)
435 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
437 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
438 return set_prefix( &reader
->prefixes
[i
], NULL
, ns
);
440 if (i
>= reader
->nb_prefixes_allocated
)
442 ULONG new_size
= reader
->nb_prefixes_allocated
* sizeof(*reader
->prefixes
) * 2;
443 struct prefix
*tmp
= heap_realloc_zero( reader
->prefixes
, new_size
);
444 if (!tmp
) return E_OUTOFMEMORY
;
445 reader
->prefixes
= tmp
;
446 reader
->nb_prefixes_allocated
*= 2;
448 if ((hr
= set_prefix( &reader
->prefixes
[i
], prefix
, ns
)) != S_OK
) return hr
;
449 reader
->nb_prefixes
++;
453 static const WS_XML_STRING
*get_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
)
456 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
458 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
459 return reader
->prefixes
[i
].ns
;
464 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
466 if (!reader
->root
) reader
->root
= eof
;
469 eof
->parent
= reader
->root
;
470 list_add_tail( &reader
->root
->children
, &eof
->entry
);
472 reader
->current
= reader
->last
= eof
;
475 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
477 reader
->root
->parent
= bof
;
478 list_add_tail( &bof
->children
, &reader
->root
->entry
);
479 reader
->current
= reader
->last
= reader
->root
= bof
;
482 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
484 node
->parent
= parent
;
485 list_add_before( list_tail( &parent
->children
), &node
->entry
);
486 reader
->current
= reader
->last
= node
;
489 static void free_reader( struct reader
*reader
)
491 destroy_nodes( reader
->root
);
492 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
493 heap_free( reader
->prefixes
);
494 reader
->cs
.DebugInfo
->Spare
[0] = 0;
495 DeleteCriticalSection( &reader
->cs
);
499 static HRESULT
init_reader( struct reader
*reader
)
501 static const WS_XML_STRING empty
= {0, NULL
};
505 reader
->state
= READER_STATE_INITIAL
;
506 destroy_nodes( reader
->root
);
507 reader
->root
= reader
->current
= NULL
;
508 reader
->current_attr
= 0;
509 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
510 reader
->nb_prefixes
= 1;
511 if ((hr
= bind_prefix( reader
, &empty
, &empty
)) != S_OK
) return hr
;
513 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
514 read_insert_eof( reader
, node
);
515 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
516 reader
->input_charset
= WS_CHARSET_UTF8
;
517 reader
->dict_static
= NULL
;
522 /**************************************************************************
523 * WsCreateReader [webservices.@]
525 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
526 WS_XML_READER
**handle
, WS_ERROR
*error
)
528 struct reader
*reader
;
529 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
530 BOOL read_decl
= TRUE
;
533 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
534 if (error
) FIXME( "ignoring error parameter\n" );
536 if (!handle
) return E_INVALIDARG
;
537 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
539 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
540 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
541 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
542 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
544 for (i
= 0; i
< count
; i
++)
546 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
547 properties
[i
].valueSize
);
550 free_reader( reader
);
555 if ((hr
= init_reader( reader
)) != S_OK
)
557 free_reader( reader
);
561 *handle
= (WS_XML_READER
*)reader
;
565 /**************************************************************************
566 * WsFreeReader [webservices.@]
568 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
570 struct reader
*reader
= (struct reader
*)handle
;
572 TRACE( "%p\n", handle
);
576 EnterCriticalSection( &reader
->cs
);
578 if (reader
->magic
!= READER_MAGIC
)
580 LeaveCriticalSection( &reader
->cs
);
586 LeaveCriticalSection( &reader
->cs
);
587 free_reader( reader
);
590 /**************************************************************************
591 * WsFillReader [webservices.@]
593 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
596 struct reader
*reader
= (struct reader
*)handle
;
598 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
599 if (error
) FIXME( "ignoring error parameter\n" );
601 if (!reader
) return E_INVALIDARG
;
603 EnterCriticalSection( &reader
->cs
);
605 if (reader
->magic
!= READER_MAGIC
)
607 LeaveCriticalSection( &reader
->cs
);
611 /* FIXME: add support for stream input */
612 reader
->read_size
= min( min_size
, reader
->input_size
);
613 reader
->read_pos
= 0;
615 LeaveCriticalSection( &reader
->cs
);
619 /**************************************************************************
620 * WsGetNamespaceFromPrefix [webservices.@]
622 HRESULT WINAPI
WsGetNamespaceFromPrefix( WS_XML_READER
*handle
, const WS_XML_STRING
*prefix
,
623 BOOL required
, const WS_XML_STRING
**ns
, WS_ERROR
*error
)
625 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
626 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
627 static const WS_XML_STRING empty_ns
= {0, NULL
};
628 static const WS_XML_STRING xml_ns
= {36, (BYTE
*)"http://www.w3.org/XML/1998/namespace"};
629 static const WS_XML_STRING xmlns_ns
= {29, (BYTE
*)"http://www.w3.org/2000/xmlns/"};
630 struct reader
*reader
= (struct reader
*)handle
;
633 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(prefix
), required
, ns
, error
);
634 if (error
) FIXME( "ignoring error parameter\n" );
636 if (!reader
|| !prefix
|| !ns
) return E_INVALIDARG
;
638 EnterCriticalSection( &reader
->cs
);
640 if (reader
->magic
!= READER_MAGIC
)
642 LeaveCriticalSection( &reader
->cs
);
646 if (reader
->state
!= READER_STATE_STARTELEMENT
)
648 LeaveCriticalSection( &reader
->cs
);
649 return WS_E_INVALID_OPERATION
;
657 else if (WsXmlStringEquals( prefix
, &xml
, NULL
) == S_OK
)
662 else if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
669 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
672 for (i
= 0; i
< elem
->attributeCount
; i
++)
674 if (!elem
->attributes
[i
]->isXmlNs
) continue;
675 if (WsXmlStringEquals( prefix
, elem
->attributes
[i
]->prefix
, NULL
) == S_OK
)
677 *ns
= elem
->attributes
[i
]->ns
;
684 LeaveCriticalSection( &reader
->cs
);
688 if (required
) return WS_E_INVALID_FORMAT
;
696 /**************************************************************************
697 * WsGetReaderNode [webservices.@]
699 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
702 struct reader
*reader
= (struct reader
*)handle
;
704 TRACE( "%p %p %p\n", handle
, node
, error
);
705 if (error
) FIXME( "ignoring error parameter\n" );
707 if (!reader
|| !node
) return E_INVALIDARG
;
709 EnterCriticalSection( &reader
->cs
);
711 if (reader
->magic
!= READER_MAGIC
)
713 LeaveCriticalSection( &reader
->cs
);
717 *node
= &reader
->current
->hdr
.node
;
719 LeaveCriticalSection( &reader
->cs
);
723 static HRESULT
get_charset( struct reader
*reader
, void *buf
, ULONG size
)
725 if (!buf
|| size
!= sizeof(reader
->input_charset
)) return E_INVALIDARG
;
726 if (!reader
->input_charset
) return WS_E_INVALID_FORMAT
;
727 *(WS_CHARSET
*)buf
= reader
->input_charset
;
731 /**************************************************************************
732 * WsGetReaderProperty [webservices.@]
734 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
735 void *buf
, ULONG size
, WS_ERROR
*error
)
737 struct reader
*reader
= (struct reader
*)handle
;
740 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
741 if (error
) FIXME( "ignoring error parameter\n" );
743 if (!reader
) return E_INVALIDARG
;
745 EnterCriticalSection( &reader
->cs
);
747 if (reader
->magic
!= READER_MAGIC
)
749 LeaveCriticalSection( &reader
->cs
);
753 if (!reader
->input_type
)
755 LeaveCriticalSection( &reader
->cs
);
756 return WS_E_INVALID_OPERATION
;
759 if (id
== WS_XML_READER_PROPERTY_CHARSET
) hr
= get_charset( reader
, buf
, size
);
760 else hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, buf
, size
);
762 LeaveCriticalSection( &reader
->cs
);
766 /**************************************************************************
767 * WsGetXmlAttribute [webservices.@]
769 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
770 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
772 FIXME( "%p %s %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
776 WS_XML_UTF8_TEXT
*alloc_utf8_text( const BYTE
*data
, ULONG len
)
778 WS_XML_UTF8_TEXT
*ret
;
780 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
781 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
782 ret
->value
.length
= len
;
783 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
784 ret
->value
.dictionary
= NULL
;
786 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
790 static WS_XML_BASE64_TEXT
*alloc_base64_text( const BYTE
*data
, ULONG len
)
792 WS_XML_BASE64_TEXT
*ret
;
794 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
795 ret
->text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
797 ret
->bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
798 if (data
) memcpy( ret
->bytes
, data
, len
);
802 static inline BOOL
read_end_of_data( struct reader
*reader
)
804 return reader
->read_pos
>= reader
->read_size
;
807 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
809 return &reader
->read_bufptr
[reader
->read_pos
];
812 static inline HRESULT
read_peek( struct reader
*reader
, unsigned char *byte
)
814 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
815 *byte
= reader
->read_bufptr
[reader
->read_pos
];
819 static inline HRESULT
read_byte( struct reader
*reader
, unsigned char *byte
)
821 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
822 *byte
= reader
->read_bufptr
[reader
->read_pos
++];
826 static inline HRESULT
read_bytes( struct reader
*reader
, unsigned char *bytes
, unsigned int len
)
828 if (reader
->read_pos
+ len
> reader
->read_size
) return WS_E_INVALID_FORMAT
;
829 memcpy( bytes
, reader
->read_bufptr
+ reader
->read_pos
, len
);
830 reader
->read_pos
+= len
;
834 /* UTF-8 support based on libs/wine/utf8.c */
836 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
837 static const char utf8_length
[128] =
839 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
840 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
841 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
842 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
843 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
844 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
845 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
846 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
849 /* first byte mask depending on UTF-8 sequence length */
850 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
852 /* minimum Unicode value depending on UTF-8 sequence length */
853 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
855 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
857 unsigned int len
, res
;
858 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
859 const unsigned char *end
;
861 if (reader
->read_pos
>= reader
->read_size
) return 0;
868 len
= utf8_length
[ch
- 0x80];
869 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
870 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
+ 1;
871 res
= ch
& utf8_mask
[len
];
876 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
877 res
= (res
<< 6) | ch
;
879 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
880 res
= (res
<< 6) | ch
;
882 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
883 res
= (res
<< 6) | ch
;
884 if (res
< utf8_minval
[len
]) break;
892 static inline void read_skip( struct reader
*reader
, unsigned int count
)
894 if (reader
->read_pos
+ count
> reader
->read_size
) return;
895 reader
->read_pos
+= count
;
898 static inline void read_rewind( struct reader
*reader
, unsigned int count
)
900 reader
->read_pos
-= count
;
903 static inline BOOL
read_isnamechar( unsigned int ch
)
905 /* FIXME: incomplete */
906 return (ch
>= 'A' && ch
<= 'Z') ||
907 (ch
>= 'a' && ch
<= 'z') ||
908 (ch
>= '0' && ch
<= '9') ||
909 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
912 static inline BOOL
read_isspace( unsigned int ch
)
914 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
917 static inline void read_skip_whitespace( struct reader
*reader
)
919 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
923 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
925 const unsigned char *ptr
= read_current_ptr( reader
);
927 if (len
< 0) len
= strlen( str
);
928 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
931 if (*str
!= *ptr
) return *ptr
- *str
;
937 static HRESULT
read_xmldecl( struct reader
*reader
)
939 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
941 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
943 reader
->state
= READER_STATE_BOF
;
946 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
947 read_skip( reader
, 6 );
949 /* FIXME: parse attributes */
950 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
953 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
954 read_skip( reader
, 2 );
956 reader
->state
= READER_STATE_BOF
;
960 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
962 if (elem
->attributeCount
)
964 WS_XML_ATTRIBUTE
**tmp
;
965 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
966 return E_OUTOFMEMORY
;
967 elem
->attributes
= tmp
;
969 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
970 elem
->attributes
[elem
->attributeCount
++] = attr
;
974 static inline void init_xml_string( BYTE
*bytes
, ULONG len
, WS_XML_STRING
*str
)
978 str
->dictionary
= NULL
;
982 static HRESULT
split_qname( const BYTE
*str
, ULONG len
, WS_XML_STRING
*prefix
, WS_XML_STRING
*localname
)
984 BYTE
*prefix_bytes
= NULL
, *localname_bytes
= (BYTE
*)str
, *ptr
= (BYTE
*)str
;
985 ULONG prefix_len
= 0, localname_len
= len
;
991 if (ptr
== str
) return WS_E_INVALID_FORMAT
;
992 prefix_bytes
= (BYTE
*)str
;
993 prefix_len
= ptr
- str
;
994 localname_bytes
= ptr
+ 1;
1000 if (!localname_len
) return WS_E_INVALID_FORMAT
;
1002 init_xml_string( prefix_bytes
, prefix_len
, prefix
);
1003 init_xml_string( localname_bytes
, localname_len
, localname
);
1007 static HRESULT
parse_qname( const BYTE
*str
, ULONG len
, WS_XML_STRING
**prefix_ret
, WS_XML_STRING
**localname_ret
)
1009 WS_XML_STRING prefix
, localname
;
1012 if ((hr
= split_qname( str
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
1013 if (!(*prefix_ret
= alloc_xml_string( NULL
, prefix
.length
))) return E_OUTOFMEMORY
;
1014 if (!(*localname_ret
= dup_xml_string( &localname
)))
1016 free_xml_string( *prefix_ret
);
1017 return E_OUTOFMEMORY
;
1019 memcpy( (*prefix_ret
)->bytes
, prefix
.bytes
, prefix
.length
);
1020 if (prefix
.length
&& add_xml_string( *prefix_ret
) != S_OK
) WARN( "prefix not added to dictionary\n" );
1024 static int codepoint_to_utf8( int cp
, unsigned char *dst
)
1034 dst
[1] = 0x80 | (cp
& 0x3f);
1039 if ((cp
>= 0xd800 && cp
<= 0xdfff) || cp
== 0xfffe || cp
== 0xffff) return -1;
1042 dst
[2] = 0x80 | (cp
& 0x3f);
1044 dst
[1] = 0x80 | (cp
& 0x3f);
1049 if (cp
>= 0x110000) return -1;
1050 dst
[3] = 0x80 | (cp
& 0x3f);
1052 dst
[2] = 0x80 | (cp
& 0x3f);
1054 dst
[1] = 0x80 | (cp
& 0x3f);
1060 static HRESULT
decode_text( const unsigned char *str
, ULONG len
, unsigned char *ret
, ULONG
*ret_len
)
1062 const unsigned char *p
= str
;
1063 unsigned char *q
= ret
;
1071 if (!len
) return WS_E_INVALID_FORMAT
;
1073 if (len
>= 3 && !memcmp( p
, "lt;", 3 ))
1079 else if (len
>= 3 && !memcmp( p
, "gt;", 3 ))
1085 else if (len
>= 5 && !memcmp( p
, "quot;", 5 ))
1091 else if (len
>= 4 && !memcmp( p
, "amp;", 4 ))
1097 else if (len
>= 5 && !memcmp( p
, "apos;", 5 ))
1105 ULONG start
, nb_digits
, i
;
1106 int len_utf8
, cp
= 0;
1109 if (!len
) return WS_E_INVALID_FORMAT
;
1115 while (len
&& isxdigit( *p
)) { p
++; len
--; };
1116 if (!len
) return WS_E_INVALID_FORMAT
;
1118 p
-= nb_digits
= start
- len
;
1119 if (!nb_digits
|| nb_digits
> 6 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1120 for (i
= 0; i
< nb_digits
; i
++)
1123 if (*p
>= '0' && *p
<= '9') cp
+= *p
- '0';
1124 else if (*p
>= 'a' && *p
<= 'f') cp
+= *p
- 'a' + 10;
1125 else cp
+= *p
- 'A' + 10;
1129 else if (isdigit( *p
))
1131 while (len
&& *p
== '0') { p
++; len
--; };
1132 if (!len
) return WS_E_INVALID_FORMAT
;
1135 while (len
&& isdigit( *p
)) { p
++; len
--; };
1136 if (!len
) return WS_E_INVALID_FORMAT
;
1138 p
-= nb_digits
= start
- len
;
1139 if (!nb_digits
|| nb_digits
> 7 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1140 for (i
= 0; i
< nb_digits
; i
++)
1147 else return WS_E_INVALID_FORMAT
;
1149 if ((len_utf8
= codepoint_to_utf8( cp
, q
)) < 0) return WS_E_INVALID_FORMAT
;
1150 *ret_len
+= len_utf8
;
1154 else return WS_E_INVALID_FORMAT
;
1166 static HRESULT
read_attribute_value_text( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1168 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1169 unsigned int len
, ch
, skip
, quote
;
1170 const unsigned char *start
;
1171 HRESULT hr
= E_OUTOFMEMORY
;
1173 read_skip_whitespace( reader
);
1174 if (read_cmp( reader
, "=", 1 )) return WS_E_INVALID_FORMAT
;
1175 read_skip( reader
, 1 );
1177 read_skip_whitespace( reader
);
1178 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) return WS_E_INVALID_FORMAT
;
1179 quote
= read_utf8_char( reader
, &skip
);
1180 read_skip( reader
, 1 );
1183 start
= read_current_ptr( reader
);
1186 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1187 if (ch
== quote
) break;
1188 read_skip( reader
, skip
);
1191 read_skip( reader
, 1 );
1195 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1196 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1197 if (!(utf8
= alloc_utf8_text( NULL
, 0 )))
1205 if (!(utf8
= alloc_utf8_text( NULL
, len
))) goto error
;
1206 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
) goto error
;
1209 attr
->value
= &utf8
->text
;
1210 attr
->singleQuote
= (quote
== '\'');
1218 static inline BOOL
is_text_type( unsigned char type
)
1220 return (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
);
1223 static HRESULT
read_int31( struct reader
*reader
, ULONG
*len
)
1228 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1230 if (!(byte
& 0x80)) return S_OK
;
1232 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1233 *len
+= (byte
& 0x7f) << 7;
1234 if (!(byte
& 0x80)) return S_OK
;
1236 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1237 *len
+= (byte
& 0x7f) << 14;
1238 if (!(byte
& 0x80)) return S_OK
;
1240 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1241 *len
+= (byte
& 0x7f) << 21;
1242 if (!(byte
& 0x80)) return S_OK
;
1244 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1245 *len
+= (byte
& 0x07) << 28;
1249 static HRESULT
read_string( struct reader
*reader
, WS_XML_STRING
**str
)
1253 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
1254 if (!(*str
= alloc_xml_string( NULL
, len
))) return E_OUTOFMEMORY
;
1255 if ((hr
= read_bytes( reader
, (*str
)->bytes
, len
)) == S_OK
)
1257 if (add_xml_string( *str
) != S_OK
) WARN( "string not added to dictionary\n" );
1260 free_xml_string( *str
);
1264 static HRESULT
read_dict_string( struct reader
*reader
, WS_XML_STRING
**str
)
1266 const WS_XML_DICTIONARY
*dict
;
1270 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1271 dict
= (id
& 1) ? reader
->dict
: reader
->dict_static
;
1272 if (!dict
|| (id
>>= 1) >= dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1273 if (!(*str
= alloc_xml_string( NULL
, 0 ))) return E_OUTOFMEMORY
;
1274 *(*str
) = dict
->strings
[id
];
1278 static HRESULT
read_datetime( struct reader
*reader
, WS_DATETIME
*ret
)
1283 if ((hr
= read_bytes( reader
, (unsigned char *)&val
, sizeof(val
) )) != S_OK
) return hr
;
1285 if ((val
& 0x03) == 1) ret
->format
= WS_DATETIME_FORMAT_UTC
;
1286 else if ((val
& 0x03) == 2) ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
1287 else ret
->format
= WS_DATETIME_FORMAT_NONE
;
1289 if ((ret
->ticks
= val
>> 2) > TICKS_MAX
) return WS_E_INVALID_FORMAT
;
1293 static HRESULT
lookup_string( struct reader
*reader
, ULONG id
, const WS_XML_STRING
**ret
)
1295 const WS_XML_DICTIONARY
*dict
= (id
& 1) ? reader
->dict
: reader
->dict_static
;
1296 if (!dict
|| (id
>>= 1) >= dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1297 *ret
= &dict
->strings
[id
];
1301 static HRESULT
read_attribute_value_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1303 static const unsigned char zero
[] = {'0'}, one
[] = {'1'};
1304 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1305 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1306 WS_XML_BASE64_TEXT
*base64
;
1307 const WS_XML_STRING
*str
;
1308 unsigned char type
, buf
[46];
1318 WS_DATETIME datetime
;
1323 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1324 if (!is_text_type( type
)) return WS_E_INVALID_FORMAT
;
1328 case RECORD_ZERO_TEXT
:
1329 if (!(utf8
= alloc_utf8_text( zero
, sizeof(zero
) ))) return E_OUTOFMEMORY
;
1332 case RECORD_ONE_TEXT
:
1333 if (!(utf8
= alloc_utf8_text( one
, sizeof(one
) ))) return E_OUTOFMEMORY
;
1336 case RECORD_FALSE_TEXT
:
1337 if (!(utf8
= alloc_utf8_text( false, sizeof(false) ))) return E_OUTOFMEMORY
;
1340 case RECORD_TRUE_TEXT
:
1341 if (!(utf8
= alloc_utf8_text( true, sizeof(true) ))) return E_OUTOFMEMORY
;
1344 case RECORD_INT8_TEXT
:
1345 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
1346 len
= format_int8( &val_int8
, buf
);
1347 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1350 case RECORD_INT16_TEXT
:
1351 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
1352 len
= format_int16( &val_int16
, buf
);
1353 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1356 case RECORD_INT32_TEXT
:
1357 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1358 len
= format_int32( &val_int32
, buf
);
1359 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1362 case RECORD_INT64_TEXT
:
1363 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
1364 len
= format_int64( &val_int64
, buf
);
1365 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1368 case RECORD_DOUBLE_TEXT
:
1369 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
1370 len
= format_double( &val_double
, buf
);
1371 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1374 case RECORD_DATETIME_TEXT
:
1375 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
1376 len
= format_datetime( &datetime
, buf
);
1377 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1380 case RECORD_CHARS8_TEXT
:
1381 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1385 case RECORD_CHARS16_TEXT
:
1386 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
1390 case RECORD_CHARS32_TEXT
:
1391 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1392 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1396 case RECORD_BYTES8_TEXT
:
1397 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1398 if (!(base64
= alloc_base64_text( NULL
, val_uint8
))) return E_OUTOFMEMORY
;
1399 if ((hr
= read_bytes( reader
, base64
->bytes
, val_uint8
)) != S_OK
)
1401 heap_free( base64
);
1406 case RECORD_BYTES16_TEXT
:
1407 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
1408 if (!(base64
= alloc_base64_text( NULL
, val_uint16
))) return E_OUTOFMEMORY
;
1409 if ((hr
= read_bytes( reader
, base64
->bytes
, val_uint16
)) != S_OK
)
1411 heap_free( base64
);
1416 case RECORD_BYTES32_TEXT
:
1417 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1418 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1419 if (!(base64
= alloc_base64_text( NULL
, val_int32
))) return E_OUTOFMEMORY
;
1420 if ((hr
= read_bytes( reader
, base64
->bytes
, val_int32
)) != S_OK
)
1422 heap_free( base64
);
1427 case RECORD_EMPTY_TEXT
:
1431 case RECORD_DICTIONARY_TEXT
:
1432 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1433 if ((hr
= lookup_string( reader
, id
, &str
)) != S_OK
) return hr
;
1434 if (!(utf8
= alloc_utf8_text( str
->bytes
, str
->length
))) return E_OUTOFMEMORY
;
1437 case RECORD_UNIQUEID_TEXT
:
1438 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
1439 len
= format_urn( &uuid
, buf
);
1440 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1443 case RECORD_UUID_TEXT
:
1444 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
1445 len
= format_guid( &uuid
, buf
);
1446 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1449 case RECORD_UINT64_TEXT
:
1450 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
1451 len
= format_uint64( &val_uint64
, buf
);
1452 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1455 case RECORD_BOOL_TEXT
:
1456 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
1457 len
= format_bool( &val_bool
, buf
);
1458 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1462 ERR( "unhandled record type %02x\n", type
);
1463 return WS_E_NOT_SUPPORTED
;
1466 if (type
>= RECORD_BYTES8_TEXT
&& type
<= RECORD_BYTES32_TEXT
)
1468 attr
->value
= &base64
->text
;
1474 if (!(utf8
= alloc_utf8_text( NULL
, len
))) return E_OUTOFMEMORY
;
1475 if (!len
) utf8
->value
.bytes
= (BYTE
*)(utf8
+ 1); /* quirk */
1476 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
1483 attr
->value
= &utf8
->text
;
1487 static HRESULT
read_attribute_text( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1489 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1490 WS_XML_ATTRIBUTE
*attr
;
1491 unsigned int len
= 0, ch
, skip
;
1492 const unsigned char *start
;
1493 WS_XML_STRING
*prefix
, *localname
;
1494 HRESULT hr
= WS_E_INVALID_FORMAT
;
1496 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1498 start
= read_current_ptr( reader
);
1501 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1502 if (!read_isnamechar( ch
)) break;
1503 read_skip( reader
, skip
);
1506 if (!len
) goto error
;
1508 if ((hr
= parse_qname( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1509 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1511 free_xml_string( prefix
);
1513 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1515 free_xml_string( localname
);
1519 attr
->localName
= localname
;
1521 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1524 attr
->prefix
= prefix
;
1525 attr
->localName
= localname
;
1529 attr
->prefix
= prefix
;
1530 attr
->localName
= localname
;
1533 if ((hr
= read_attribute_value_text( reader
, attr
)) != S_OK
) goto error
;
1539 free_attribute( attr
);
1543 static inline BOOL
is_attribute_type( unsigned char type
)
1545 return (type
>= RECORD_SHORT_ATTRIBUTE
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
);
1548 static HRESULT
read_attribute_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1550 WS_XML_ATTRIBUTE
*attr
;
1551 unsigned char type
= 0;
1554 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1555 if (!is_attribute_type( type
)) return WS_E_INVALID_FORMAT
;
1556 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1558 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1560 unsigned char ch
= type
- RECORD_PREFIX_ATTRIBUTE_A
+ 'a';
1561 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1566 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1567 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1569 else if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1571 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ 'a';
1572 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1577 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1578 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1584 case RECORD_SHORT_ATTRIBUTE
:
1585 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1590 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1591 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1594 case RECORD_ATTRIBUTE
:
1595 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1596 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1597 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1600 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1601 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1606 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1607 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1610 case RECORD_DICTIONARY_ATTRIBUTE
:
1611 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1612 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1613 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1616 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1617 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1622 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1623 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1627 case RECORD_XMLNS_ATTRIBUTE
:
1628 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1629 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1630 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1634 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1635 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1640 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1641 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1645 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1646 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1647 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1648 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1653 ERR( "unhandled record type %02x\n", type
);
1654 return WS_E_NOT_SUPPORTED
;
1662 free_attribute( attr
);
1666 static inline struct node
*find_parent( struct reader
*reader
)
1668 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1670 if (is_valid_parent( reader
->current
->parent
->parent
)) return reader
->current
->parent
->parent
;
1673 if (is_valid_parent( reader
->current
)) return reader
->current
;
1674 if (is_valid_parent( reader
->current
->parent
)) return reader
->current
->parent
;
1678 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1680 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1681 const WS_XML_STRING
*ns
;
1684 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1685 if (!(elem
->ns
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
1687 for (i
= 0; i
< elem
->attributeCount
; i
++)
1689 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1690 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1691 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1692 if (!(attr
->ns
= alloc_xml_string( NULL
, ns
->length
))) return E_OUTOFMEMORY
;
1693 if (attr
->ns
->length
) memcpy( attr
->ns
->bytes
, ns
->bytes
, ns
->length
);
1698 static WS_XML_ELEMENT_NODE
*alloc_element_pair(void)
1700 struct node
*node
, *end
;
1701 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
1702 if (!(end
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
)))
1707 list_add_tail( &node
->children
, &end
->entry
);
1712 static HRESULT
read_attributes_text( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1714 WS_XML_ATTRIBUTE
*attr
;
1717 reader
->current_attr
= 0;
1720 read_skip_whitespace( reader
);
1721 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1722 if ((hr
= read_attribute_text( reader
, &attr
)) != S_OK
) return hr
;
1723 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1725 free_attribute( attr
);
1728 reader
->current_attr
++;
1733 static HRESULT
read_element_text( struct reader
*reader
)
1735 unsigned int len
= 0, ch
, skip
;
1736 const unsigned char *start
;
1737 struct node
*node
= NULL
, *parent
;
1738 WS_XML_ELEMENT_NODE
*elem
;
1739 HRESULT hr
= WS_E_INVALID_FORMAT
;
1741 if (read_end_of_data( reader
))
1743 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1744 reader
->last
= reader
->current
;
1745 reader
->state
= READER_STATE_EOF
;
1749 if (read_cmp( reader
, "<", 1 )) return WS_E_INVALID_FORMAT
;
1750 read_skip( reader
, 1 );
1751 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1753 read_rewind( reader
, 1 );
1754 return WS_E_INVALID_FORMAT
;
1757 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1758 node
= (struct node
*)elem
;
1760 start
= read_current_ptr( reader
);
1763 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1764 if (!read_isnamechar( ch
)) break;
1765 read_skip( reader
, skip
);
1768 if (!len
) goto error
;
1770 if (!(parent
= find_parent( reader
))) goto error
;
1771 if ((hr
= parse_qname( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1772 if ((hr
= read_attributes_text( reader
, elem
)) != S_OK
) goto error
;
1773 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1775 read_insert_node( reader
, parent
, node
);
1776 reader
->state
= READER_STATE_STARTELEMENT
;
1780 destroy_nodes( node
);
1784 static inline BOOL
is_element_type( unsigned char type
)
1786 return (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
);
1789 static HRESULT
read_attributes_bin( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1791 WS_XML_ATTRIBUTE
*attr
;
1795 reader
->current_attr
= 0;
1798 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
1799 if (!is_attribute_type( type
)) break;
1800 if ((hr
= read_attribute_bin( reader
, &attr
)) != S_OK
) return hr
;
1801 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1803 free_attribute( attr
);
1806 reader
->current_attr
++;
1811 static HRESULT
read_element_bin( struct reader
*reader
)
1813 struct node
*node
= NULL
, *parent
;
1814 WS_XML_ELEMENT_NODE
*elem
;
1818 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1819 if (!is_element_type( type
)) return WS_E_INVALID_FORMAT
;
1821 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1822 node
= (struct node
*)elem
;
1824 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1826 unsigned char ch
= type
- RECORD_PREFIX_ELEMENT_A
+ 'a';
1827 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1832 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1834 else if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1836 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ 'a';
1837 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1842 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1848 case RECORD_SHORT_ELEMENT
:
1849 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1854 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1857 case RECORD_ELEMENT
:
1858 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1859 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1862 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1863 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1868 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1871 case RECORD_DICTIONARY_ELEMENT
:
1872 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1873 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1877 ERR( "unhandled record type %02x\n", type
);
1878 return WS_E_NOT_SUPPORTED
;
1882 if (!(parent
= find_parent( reader
)))
1884 hr
= WS_E_INVALID_FORMAT
;
1888 if ((hr
= read_attributes_bin( reader
, elem
)) != S_OK
) goto error
;
1889 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1891 read_insert_node( reader
, parent
, node
);
1892 reader
->state
= READER_STATE_STARTELEMENT
;
1896 destroy_nodes( node
);
1900 static HRESULT
read_text_text( struct reader
*reader
)
1902 unsigned int len
= 0, ch
, skip
;
1903 const unsigned char *start
;
1904 struct node
*node
, *parent
;
1905 WS_XML_TEXT_NODE
*text
;
1906 WS_XML_UTF8_TEXT
*utf8
;
1909 start
= read_current_ptr( reader
);
1912 if (read_end_of_data( reader
)) break;
1913 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1914 if (ch
== '<') break;
1915 read_skip( reader
, skip
);
1919 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1921 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1922 text
= (WS_XML_TEXT_NODE
*)node
;
1923 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
1926 return E_OUTOFMEMORY
;
1928 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1934 text
->text
= &utf8
->text
;
1936 read_insert_node( reader
, parent
, node
);
1937 reader
->state
= READER_STATE_TEXT
;
1938 reader
->text_conv_offset
= 0;
1942 static struct node
*alloc_utf8_text_node( const BYTE
*data
, ULONG len
, WS_XML_UTF8_TEXT
**ret
)
1945 WS_XML_UTF8_TEXT
*utf8
;
1946 WS_XML_TEXT_NODE
*text
;
1948 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
1949 if (!(utf8
= alloc_utf8_text( data
, len
)))
1954 text
= (WS_XML_TEXT_NODE
*)node
;
1955 text
->text
= &utf8
->text
;
1956 if (ret
) *ret
= utf8
;
1960 static struct node
*alloc_base64_text_node( const BYTE
*data
, ULONG len
, WS_XML_BASE64_TEXT
**ret
)
1963 WS_XML_BASE64_TEXT
*base64
;
1964 WS_XML_TEXT_NODE
*text
;
1966 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
1967 if (!(base64
= alloc_base64_text( data
, len
)))
1972 text
= (WS_XML_TEXT_NODE
*)node
;
1973 text
->text
= &base64
->text
;
1974 if (ret
) *ret
= base64
;
1978 static HRESULT
append_text_bytes( struct reader
*reader
, WS_XML_TEXT_NODE
*node
, ULONG len
)
1980 WS_XML_BASE64_TEXT
*new, *old
= (WS_XML_BASE64_TEXT
*)node
->text
;
1983 if (!(new = alloc_base64_text( NULL
, old
->length
+ len
))) return E_OUTOFMEMORY
;
1984 memcpy( new->bytes
, old
->bytes
, old
->length
);
1985 if ((hr
= read_bytes( reader
, new->bytes
+ old
->length
, len
)) != S_OK
) return hr
;
1987 node
->text
= &new->text
;
1991 static HRESULT
read_text_bytes( struct reader
*reader
, unsigned char type
)
1993 struct node
*node
= NULL
, *parent
;
1994 WS_XML_BASE64_TEXT
*base64
;
1998 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2003 case RECORD_BYTES8_TEXT
:
2004 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT
:
2007 if ((hr
= read_byte( reader
, (unsigned char *)&len_uint8
)) != S_OK
) goto error
;
2011 case RECORD_BYTES16_TEXT
:
2012 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT
:
2015 if ((hr
= read_bytes( reader
, (unsigned char *)&len_uint16
, sizeof(len_uint16
) )) != S_OK
) goto error
;
2019 case RECORD_BYTES32_TEXT
:
2020 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT
:
2023 if ((hr
= read_bytes( reader
, (unsigned char *)&len_int32
, sizeof(len_int32
) )) != S_OK
) goto error
;
2026 hr
= WS_E_INVALID_FORMAT
;
2033 ERR( "unexpected type %u\n", type
);
2040 if (!(node
= alloc_base64_text_node( NULL
, len
, &base64
))) return E_OUTOFMEMORY
;
2041 if ((hr
= read_bytes( reader
, base64
->bytes
, len
)) != S_OK
) goto error
;
2043 else if ((hr
= append_text_bytes( reader
, (WS_XML_TEXT_NODE
*)node
, len
)) != S_OK
) goto error
;
2047 node
->flags
|= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
;
2050 if ((hr
= read_peek( reader
, &type
)) != S_OK
) goto error
;
2051 if (type
< RECORD_BYTES8_TEXT
|| type
> RECORD_BYTES32_TEXT_WITH_ENDELEMENT
) break;
2052 read_skip( reader
, 1 );
2055 read_insert_node( reader
, parent
, node
);
2056 reader
->state
= READER_STATE_TEXT
;
2057 reader
->text_conv_offset
= 0;
2065 static HRESULT
read_text_bin( struct reader
*reader
)
2067 static const unsigned char zero
[] = {'0'}, one
[] = {'1'};
2068 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
2069 unsigned char type
, buf
[46];
2070 struct node
*node
= NULL
, *parent
;
2071 WS_XML_UTF8_TEXT
*utf8
;
2072 const WS_XML_STRING
*str
;
2082 WS_DATETIME datetime
;
2087 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2088 if (!is_text_type( type
) || !(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2092 case RECORD_ZERO_TEXT
:
2093 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2094 if (!(node
= alloc_utf8_text_node( zero
, sizeof(zero
), NULL
))) return E_OUTOFMEMORY
;
2097 case RECORD_ONE_TEXT
:
2098 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2099 if (!(node
= alloc_utf8_text_node( one
, sizeof(one
), NULL
))) return E_OUTOFMEMORY
;
2102 case RECORD_FALSE_TEXT
:
2103 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2104 if (!(node
= alloc_utf8_text_node( false, sizeof(false), NULL
))) return E_OUTOFMEMORY
;
2107 case RECORD_TRUE_TEXT
:
2108 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2109 if (!(node
= alloc_utf8_text_node( true, sizeof(true), NULL
))) return E_OUTOFMEMORY
;
2112 case RECORD_INT8_TEXT
:
2113 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2114 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
2115 len
= format_int8( &val_int8
, buf
);
2116 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2119 case RECORD_INT16_TEXT
:
2120 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2121 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
2122 len
= format_int16( &val_int16
, buf
);
2123 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2126 case RECORD_INT32_TEXT
:
2127 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2128 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2129 len
= format_int32( &val_int32
, buf
);
2130 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2133 case RECORD_INT64_TEXT
:
2134 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2135 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
2136 len
= format_int64( &val_int64
, buf
);
2137 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2140 case RECORD_DOUBLE_TEXT
:
2141 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2142 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
2143 len
= format_double( &val_double
, buf
);
2144 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2147 case RECORD_DATETIME_TEXT
:
2148 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2149 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
2150 len
= format_datetime( &datetime
, buf
);
2151 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2154 case RECORD_CHARS8_TEXT
:
2155 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2156 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
2160 case RECORD_CHARS16_TEXT
:
2161 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2162 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
2166 case RECORD_CHARS32_TEXT
:
2167 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT
:
2168 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2169 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
2173 case RECORD_BYTES8_TEXT
:
2174 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT
:
2175 case RECORD_BYTES16_TEXT
:
2176 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT
:
2177 case RECORD_BYTES32_TEXT
:
2178 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT
:
2179 return read_text_bytes( reader
, type
);
2181 case RECORD_EMPTY_TEXT
:
2182 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT
:
2186 case RECORD_DICTIONARY_TEXT
:
2187 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2188 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
2189 if ((hr
= lookup_string( reader
, id
, &str
)) != S_OK
) return hr
;
2190 if (!(node
= alloc_utf8_text_node( str
->bytes
, str
->length
, NULL
))) return E_OUTOFMEMORY
;
2193 case RECORD_UNIQUEID_TEXT
:
2194 case RECORD_UNIQUEID_TEXT_WITH_ENDELEMENT
:
2195 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2196 len
= format_urn( &uuid
, buf
);
2197 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2200 case RECORD_UUID_TEXT
:
2201 case RECORD_UUID_TEXT_WITH_ENDELEMENT
:
2202 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2203 len
= format_guid( &uuid
, buf
);
2204 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2207 case RECORD_UINT64_TEXT
:
2208 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2209 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
2210 len
= format_uint64( &val_uint64
, buf
);
2211 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2214 case RECORD_BOOL_TEXT
:
2215 case RECORD_BOOL_TEXT_WITH_ENDELEMENT
:
2216 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
2217 len
= format_bool( &val_bool
, buf
);
2218 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2222 ERR( "unhandled record type %02x\n", type
);
2223 return WS_E_NOT_SUPPORTED
;
2228 if (!(node
= alloc_utf8_text_node( NULL
, len
, &utf8
))) return E_OUTOFMEMORY
;
2229 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
2236 if (type
& 1) node
->flags
|= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
;
2237 read_insert_node( reader
, parent
, node
);
2238 reader
->state
= READER_STATE_TEXT
;
2239 reader
->text_conv_offset
= 0;
2243 static HRESULT
read_node_text( struct reader
* );
2245 static HRESULT
read_startelement_text( struct reader
*reader
)
2247 read_skip_whitespace( reader
);
2248 if (!read_cmp( reader
, "/>", 2 ))
2250 read_skip( reader
, 2 );
2251 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->children
), struct node
, entry
);
2252 reader
->last
= reader
->current
;
2253 reader
->state
= READER_STATE_ENDELEMENT
;
2256 else if (!read_cmp( reader
, ">", 1 ))
2258 read_skip( reader
, 1 );
2259 return read_node_text( reader
);
2261 return WS_E_INVALID_FORMAT
;
2264 static HRESULT
read_node_bin( struct reader
* );
2266 static HRESULT
read_startelement_bin( struct reader
*reader
)
2268 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
2269 return read_node_bin( reader
);
2272 static HRESULT
read_startelement( struct reader
*reader
)
2274 switch (reader
->input_enc
)
2276 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_startelement_text( reader
);
2277 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_startelement_bin( reader
);
2279 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2280 return WS_E_NOT_SUPPORTED
;
2284 static HRESULT
read_to_startelement_text( struct reader
*reader
, BOOL
*found
)
2288 switch (reader
->state
)
2290 case READER_STATE_INITIAL
:
2291 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
2294 case READER_STATE_STARTELEMENT
:
2295 if (found
) *found
= TRUE
;
2302 read_skip_whitespace( reader
);
2303 if ((hr
= read_element_text( reader
)) == S_OK
&& found
)
2305 if (reader
->state
== READER_STATE_STARTELEMENT
)
2314 static HRESULT
read_to_startelement_bin( struct reader
*reader
, BOOL
*found
)
2318 if (reader
->state
== READER_STATE_STARTELEMENT
)
2320 if (found
) *found
= TRUE
;
2324 if ((hr
= read_element_bin( reader
)) == S_OK
&& found
)
2326 if (reader
->state
== READER_STATE_STARTELEMENT
)
2335 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
2337 switch (reader
->input_enc
)
2339 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_to_startelement_text( reader
, found
);
2340 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_to_startelement_bin( reader
, found
);
2342 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2343 return WS_E_NOT_SUPPORTED
;
2347 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
2350 if (len1
!= len2
) return 1;
2351 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
2355 static struct node
*find_startelement( struct reader
*reader
, const WS_XML_STRING
*prefix
,
2356 const WS_XML_STRING
*localname
)
2358 struct node
*parent
;
2359 const WS_XML_STRING
*str
;
2361 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
2363 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2365 str
= parent
->hdr
.prefix
;
2366 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
2367 str
= parent
->hdr
.localName
;
2368 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
2375 static HRESULT
read_endelement_text( struct reader
*reader
)
2377 struct node
*parent
;
2378 unsigned int len
= 0, ch
, skip
;
2379 const unsigned char *start
;
2380 WS_XML_STRING prefix
, localname
;
2383 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
2384 read_skip( reader
, 2 );
2386 start
= read_current_ptr( reader
);
2389 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2392 read_skip( reader
, 1 );
2395 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
2396 read_skip( reader
, skip
);
2400 if ((hr
= split_qname( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
2401 if (!(parent
= find_startelement( reader
, &prefix
, &localname
))) return WS_E_INVALID_FORMAT
;
2403 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2404 reader
->last
= reader
->current
;
2405 reader
->state
= READER_STATE_ENDELEMENT
;
2409 static HRESULT
read_endelement_bin( struct reader
*reader
)
2411 struct node
*parent
;
2415 if (!(reader
->current
->flags
& NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
))
2417 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2418 if (type
!= RECORD_ENDELEMENT
) return WS_E_INVALID_FORMAT
;
2420 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2422 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2423 reader
->last
= reader
->current
;
2424 reader
->state
= READER_STATE_ENDELEMENT
;
2428 static HRESULT
read_endelement( struct reader
*reader
)
2430 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
2432 if (read_end_of_data( reader
))
2434 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2435 reader
->last
= reader
->current
;
2436 reader
->state
= READER_STATE_EOF
;
2440 switch (reader
->input_enc
)
2442 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_endelement_text( reader
);
2443 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_endelement_bin( reader
);
2445 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2446 return WS_E_NOT_SUPPORTED
;
2450 static HRESULT
read_comment_text( struct reader
*reader
)
2452 unsigned int len
= 0, ch
, skip
;
2453 const unsigned char *start
;
2454 struct node
*node
, *parent
;
2455 WS_XML_COMMENT_NODE
*comment
;
2457 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
2458 read_skip( reader
, 4 );
2460 start
= read_current_ptr( reader
);
2463 if (!read_cmp( reader
, "-->", 3 ))
2465 read_skip( reader
, 3 );
2468 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2469 read_skip( reader
, skip
);
2473 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2475 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2476 comment
= (WS_XML_COMMENT_NODE
*)node
;
2477 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2480 return E_OUTOFMEMORY
;
2482 memcpy( comment
->value
.bytes
, start
, len
);
2483 comment
->value
.length
= len
;
2485 read_insert_node( reader
, parent
, node
);
2486 reader
->state
= READER_STATE_COMMENT
;
2490 static HRESULT
read_comment_bin( struct reader
*reader
)
2492 struct node
*node
, *parent
;
2493 WS_XML_COMMENT_NODE
*comment
;
2498 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2499 if (type
!= RECORD_COMMENT
) return WS_E_INVALID_FORMAT
;
2500 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
2502 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2504 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2505 comment
= (WS_XML_COMMENT_NODE
*)node
;
2506 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2509 return E_OUTOFMEMORY
;
2511 if ((hr
= read_bytes( reader
, comment
->value
.bytes
, len
)) != S_OK
)
2514 return E_OUTOFMEMORY
;
2516 comment
->value
.length
= len
;
2518 read_insert_node( reader
, parent
, node
);
2519 reader
->state
= READER_STATE_COMMENT
;
2523 static HRESULT
read_startcdata( struct reader
*reader
)
2525 struct node
*node
, *endnode
, *parent
;
2527 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
2528 read_skip( reader
, 9 );
2530 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2532 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2533 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
)))
2536 return E_OUTOFMEMORY
;
2538 list_add_tail( &node
->children
, &endnode
->entry
);
2539 endnode
->parent
= node
;
2541 read_insert_node( reader
, parent
, node
);
2542 reader
->state
= READER_STATE_STARTCDATA
;
2546 static HRESULT
read_cdata( struct reader
*reader
)
2548 unsigned int len
= 0, ch
, skip
;
2549 const unsigned char *start
;
2551 WS_XML_TEXT_NODE
*text
;
2552 WS_XML_UTF8_TEXT
*utf8
;
2554 start
= read_current_ptr( reader
);
2557 if (!read_cmp( reader
, "]]>", 3 )) break;
2558 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2559 read_skip( reader
, skip
);
2563 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2564 text
= (WS_XML_TEXT_NODE
*)node
;
2565 if (!(utf8
= alloc_utf8_text( start
, len
)))
2568 return E_OUTOFMEMORY
;
2570 text
->text
= &utf8
->text
;
2572 read_insert_node( reader
, reader
->current
, node
);
2573 reader
->state
= READER_STATE_CDATA
;
2577 static HRESULT
read_endcdata( struct reader
*reader
)
2579 struct node
*parent
;
2581 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
2582 read_skip( reader
, 3 );
2584 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
) parent
= reader
->current
->parent
;
2585 else parent
= reader
->current
;
2587 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2588 reader
->last
= reader
->current
;
2589 reader
->state
= READER_STATE_ENDCDATA
;
2593 static HRESULT
read_node_text( struct reader
*reader
)
2599 if (read_end_of_data( reader
))
2601 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2602 reader
->last
= reader
->current
;
2603 reader
->state
= READER_STATE_EOF
;
2606 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
2607 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
2608 else if (!read_cmp( reader
, "<?", 2 ))
2610 hr
= read_xmldecl( reader
);
2611 if (FAILED( hr
)) return hr
;
2613 else if (!read_cmp( reader
, "</", 2 )) return read_endelement_text( reader
);
2614 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
2615 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment_text( reader
);
2616 else if (!read_cmp( reader
, "<", 1 )) return read_element_text( reader
);
2617 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement_text( reader
);
2618 else return read_text_text( reader
);
2622 static HRESULT
read_node_bin( struct reader
*reader
)
2627 if (reader
->current
->flags
& NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
)
2629 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->parent
->children
), struct node
, entry
);
2630 reader
->last
= reader
->current
;
2631 reader
->state
= READER_STATE_ENDELEMENT
;
2634 if (read_end_of_data( reader
))
2636 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2637 reader
->last
= reader
->current
;
2638 reader
->state
= READER_STATE_EOF
;
2642 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
2643 if (type
== RECORD_ENDELEMENT
)
2645 return read_endelement_bin( reader
);
2647 else if (type
== RECORD_COMMENT
)
2649 return read_comment_bin( reader
);
2651 else if (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
2653 return read_element_bin( reader
);
2655 else if (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
)
2657 return read_text_bin( reader
);
2659 FIXME( "unhandled record type %02x\n", type
);
2660 return WS_E_NOT_SUPPORTED
;
2663 static HRESULT
read_node( struct reader
*reader
)
2665 switch (reader
->input_enc
)
2667 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_node_text( reader
);
2668 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_node_bin( reader
);
2670 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2671 return WS_E_NOT_SUPPORTED
;
2675 HRESULT
copy_node( WS_XML_READER
*handle
, struct node
**node
)
2677 struct reader
*reader
= (struct reader
*)handle
;
2678 const struct list
*ptr
;
2679 const struct node
*start
;
2682 EnterCriticalSection( &reader
->cs
);
2684 if (reader
->magic
!= READER_MAGIC
)
2686 LeaveCriticalSection( &reader
->cs
);
2687 return E_INVALIDARG
;
2690 if (reader
->current
!= reader
->root
) ptr
= &reader
->current
->entry
;
2691 else /* copy whole tree */
2693 if (!read_end_of_data( reader
))
2697 if ((hr
= read_node( reader
)) != S_OK
) goto done
;
2698 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) break;
2701 ptr
= list_head( &reader
->root
->children
);
2704 start
= LIST_ENTRY( ptr
, struct node
, entry
);
2705 if (node_type( start
) == WS_XML_NODE_TYPE_EOF
) hr
= WS_E_INVALID_OPERATION
;
2706 else hr
= dup_tree( node
, start
);
2709 LeaveCriticalSection( &reader
->cs
);
2713 /**************************************************************************
2714 * WsReadEndElement [webservices.@]
2716 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2718 struct reader
*reader
= (struct reader
*)handle
;
2721 TRACE( "%p %p\n", handle
, error
);
2722 if (error
) FIXME( "ignoring error parameter\n" );
2724 if (!reader
) return E_INVALIDARG
;
2726 EnterCriticalSection( &reader
->cs
);
2728 if (reader
->magic
!= READER_MAGIC
)
2730 LeaveCriticalSection( &reader
->cs
);
2731 return E_INVALIDARG
;
2734 hr
= read_endelement( reader
);
2736 LeaveCriticalSection( &reader
->cs
);
2740 /**************************************************************************
2741 * WsReadNode [webservices.@]
2743 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2745 struct reader
*reader
= (struct reader
*)handle
;
2748 TRACE( "%p %p\n", handle
, error
);
2749 if (error
) FIXME( "ignoring error parameter\n" );
2751 if (!reader
) return E_INVALIDARG
;
2753 EnterCriticalSection( &reader
->cs
);
2755 if (reader
->magic
!= READER_MAGIC
)
2757 LeaveCriticalSection( &reader
->cs
);
2758 return E_INVALIDARG
;
2761 hr
= read_node( reader
);
2763 LeaveCriticalSection( &reader
->cs
);
2767 static HRESULT
skip_node( struct reader
*reader
)
2769 const struct node
*parent
;
2772 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) return WS_E_INVALID_OPERATION
;
2773 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_ELEMENT
) parent
= reader
->current
;
2778 if ((hr
= read_node( reader
) != S_OK
) || !parent
) break;
2779 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_END_ELEMENT
) continue;
2780 if (reader
->current
->parent
== parent
) return read_node( reader
);
2786 /**************************************************************************
2787 * WsSkipNode [webservices.@]
2789 HRESULT WINAPI
WsSkipNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2791 struct reader
*reader
= (struct reader
*)handle
;
2794 TRACE( "%p %p\n", handle
, error
);
2795 if (error
) FIXME( "ignoring error parameter\n" );
2797 if (!reader
) return E_INVALIDARG
;
2799 EnterCriticalSection( &reader
->cs
);
2801 if (reader
->magic
!= READER_MAGIC
)
2803 LeaveCriticalSection( &reader
->cs
);
2804 return E_INVALIDARG
;
2807 hr
= skip_node( reader
);
2809 LeaveCriticalSection( &reader
->cs
);
2813 /**************************************************************************
2814 * WsReadStartElement [webservices.@]
2816 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2818 struct reader
*reader
= (struct reader
*)handle
;
2821 TRACE( "%p %p\n", handle
, error
);
2822 if (error
) FIXME( "ignoring error parameter\n" );
2824 if (!reader
) return E_INVALIDARG
;
2826 EnterCriticalSection( &reader
->cs
);
2828 if (reader
->magic
!= READER_MAGIC
)
2830 LeaveCriticalSection( &reader
->cs
);
2831 return E_INVALIDARG
;
2834 hr
= read_startelement( reader
);
2836 LeaveCriticalSection( &reader
->cs
);
2840 /**************************************************************************
2841 * WsReadToStartElement [webservices.@]
2843 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2844 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
2846 struct reader
*reader
= (struct reader
*)handle
;
2849 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
2850 if (error
) FIXME( "ignoring error parameter\n" );
2852 if (!reader
) return E_INVALIDARG
;
2853 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
2855 EnterCriticalSection( &reader
->cs
);
2857 if (reader
->magic
!= READER_MAGIC
)
2859 LeaveCriticalSection( &reader
->cs
);
2860 return E_INVALIDARG
;
2863 hr
= read_to_startelement( reader
, found
);
2865 LeaveCriticalSection( &reader
->cs
);
2869 BOOL
move_to_root_element( struct node
*root
, struct node
**current
)
2874 if (!(ptr
= list_head( &root
->children
))) return FALSE
;
2875 node
= LIST_ENTRY( ptr
, struct node
, entry
);
2876 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
2881 while ((ptr
= list_next( &root
->children
, &node
->entry
)))
2883 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2884 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2894 BOOL
move_to_next_element( struct node
**current
)
2897 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2899 if (!parent
) return FALSE
;
2900 while ((ptr
= list_next( &parent
->children
, &node
->entry
)))
2902 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2903 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2913 BOOL
move_to_prev_element( struct node
**current
)
2916 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2918 if (!parent
) return FALSE
;
2919 while ((ptr
= list_prev( &parent
->children
, &node
->entry
)))
2921 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
2922 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
2932 BOOL
move_to_child_element( struct node
**current
)
2935 struct node
*child
, *node
= *current
;
2937 if (!(ptr
= list_head( &node
->children
))) return FALSE
;
2938 child
= LIST_ENTRY( ptr
, struct node
, entry
);
2939 if (node_type( child
) == WS_XML_NODE_TYPE_ELEMENT
)
2944 while ((ptr
= list_next( &node
->children
, &child
->entry
)))
2946 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2947 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2957 BOOL
move_to_end_element( struct node
**current
)
2960 struct node
*node
= *current
;
2962 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
2964 if ((ptr
= list_tail( &node
->children
)))
2966 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
2967 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
2976 BOOL
move_to_parent_element( struct node
**current
)
2978 struct node
*parent
= (*current
)->parent
;
2980 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
2981 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
2989 BOOL
move_to_first_node( struct node
**current
)
2992 struct node
*node
= *current
;
2994 if ((ptr
= list_head( &node
->parent
->children
)))
2996 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3002 BOOL
move_to_next_node( struct node
**current
)
3005 struct node
*node
= *current
;
3007 if ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
3009 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3015 BOOL
move_to_prev_node( struct node
**current
)
3018 struct node
*node
= *current
;
3020 if ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
3022 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3028 BOOL
move_to_bof( struct node
*root
, struct node
**current
)
3034 BOOL
move_to_eof( struct node
*root
, struct node
**current
)
3037 if ((ptr
= list_tail( &root
->children
)))
3039 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3045 BOOL
move_to_child_node( struct node
**current
)
3048 struct node
*node
= *current
;
3050 if ((ptr
= list_head( &node
->children
)))
3052 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3058 BOOL
move_to_parent_node( struct node
**current
)
3060 struct node
*parent
= (*current
)->parent
;
3061 if (!parent
) return FALSE
;
3066 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
3068 BOOL success
= FALSE
;
3071 if (!read_end_of_data( reader
))
3073 struct node
*saved_current
= reader
->current
;
3074 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
3075 if (hr
!= S_OK
) return hr
;
3076 reader
->current
= saved_current
;
3080 case WS_MOVE_TO_ROOT_ELEMENT
:
3081 success
= move_to_root_element( reader
->root
, &reader
->current
);
3084 case WS_MOVE_TO_NEXT_ELEMENT
:
3085 success
= move_to_next_element( &reader
->current
);
3088 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
3089 success
= move_to_prev_element( &reader
->current
);
3092 case WS_MOVE_TO_CHILD_ELEMENT
:
3093 success
= move_to_child_element( &reader
->current
);
3096 case WS_MOVE_TO_END_ELEMENT
:
3097 success
= move_to_end_element( &reader
->current
);
3100 case WS_MOVE_TO_PARENT_ELEMENT
:
3101 success
= move_to_parent_element( &reader
->current
);
3104 case WS_MOVE_TO_FIRST_NODE
:
3105 success
= move_to_first_node( &reader
->current
);
3108 case WS_MOVE_TO_NEXT_NODE
:
3109 success
= move_to_next_node( &reader
->current
);
3112 case WS_MOVE_TO_PREVIOUS_NODE
:
3113 success
= move_to_prev_node( &reader
->current
);
3116 case WS_MOVE_TO_CHILD_NODE
:
3117 success
= move_to_child_node( &reader
->current
);
3120 case WS_MOVE_TO_BOF
:
3121 success
= move_to_bof( reader
->root
, &reader
->current
);
3124 case WS_MOVE_TO_EOF
:
3125 success
= move_to_eof( reader
->root
, &reader
->current
);
3129 FIXME( "unhandled move %u\n", move
);
3138 return success
? S_OK
: WS_E_INVALID_FORMAT
;
3141 /**************************************************************************
3142 * WsMoveReader [webservices.@]
3144 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
3146 struct reader
*reader
= (struct reader
*)handle
;
3149 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
3150 if (error
) FIXME( "ignoring error parameter\n" );
3152 if (!reader
) return E_INVALIDARG
;
3154 EnterCriticalSection( &reader
->cs
);
3156 if (reader
->magic
!= READER_MAGIC
)
3158 LeaveCriticalSection( &reader
->cs
);
3159 return E_INVALIDARG
;
3162 if (!reader
->input_type
)
3164 LeaveCriticalSection( &reader
->cs
);
3165 return WS_E_INVALID_OPERATION
;
3168 hr
= read_move_to( reader
, move
, found
);
3170 LeaveCriticalSection( &reader
->cs
);
3174 /**************************************************************************
3175 * WsReadStartAttribute [webservices.@]
3177 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
3179 struct reader
*reader
= (struct reader
*)handle
;
3180 const WS_XML_ELEMENT_NODE
*elem
;
3182 TRACE( "%p %u %p\n", handle
, index
, error
);
3183 if (error
) FIXME( "ignoring error parameter\n" );
3185 if (!reader
) return E_INVALIDARG
;
3187 EnterCriticalSection( &reader
->cs
);
3189 if (reader
->magic
!= READER_MAGIC
)
3191 LeaveCriticalSection( &reader
->cs
);
3192 return E_INVALIDARG
;
3195 elem
= &reader
->current
->hdr
;
3196 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
3198 LeaveCriticalSection( &reader
->cs
);
3199 return WS_E_INVALID_FORMAT
;
3202 reader
->current_attr
= index
;
3203 reader
->state
= READER_STATE_STARTATTRIBUTE
;
3205 LeaveCriticalSection( &reader
->cs
);
3209 /**************************************************************************
3210 * WsReadEndAttribute [webservices.@]
3212 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
3214 struct reader
*reader
= (struct reader
*)handle
;
3216 TRACE( "%p %p\n", handle
, error
);
3217 if (error
) FIXME( "ignoring error parameter\n" );
3219 if (!reader
) return E_INVALIDARG
;
3221 EnterCriticalSection( &reader
->cs
);
3223 if (reader
->magic
!= READER_MAGIC
)
3225 LeaveCriticalSection( &reader
->cs
);
3226 return E_INVALIDARG
;
3229 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
3231 LeaveCriticalSection( &reader
->cs
);
3232 return WS_E_INVALID_FORMAT
;
3235 reader
->state
= READER_STATE_STARTELEMENT
;
3237 LeaveCriticalSection( &reader
->cs
);
3241 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
3245 switch (text
->textType
)
3247 case WS_XML_TEXT_TYPE_UTF8
:
3249 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
3250 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
3251 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
3252 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
3257 FIXME( "unhandled type %u\n", text
->textType
);
3264 #define MAX_INT8 0x7f
3265 #define MIN_INT8 (-MAX_INT8 - 1)
3266 #define MAX_INT16 0x7fff
3267 #define MIN_INT16 (-MAX_INT16 - 1)
3268 #define MAX_INT32 0x7fffffff
3269 #define MIN_INT32 (-MAX_INT32 - 1)
3270 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
3271 #define MIN_INT64 (-MAX_INT64 - 1)
3272 #define MAX_UINT8 0xff
3273 #define MAX_UINT16 0xffff
3274 #define MAX_UINT32 0xffffffff
3275 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
3277 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
3279 BOOL negative
= FALSE
;
3280 const unsigned char *ptr
= str
;
3283 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3284 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3285 if (!len
) return WS_E_INVALID_FORMAT
;
3293 if (!len
) return WS_E_INVALID_FORMAT
;
3299 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3301 if (negative
) val
= -val
;
3303 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
3304 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
3306 return WS_E_NUMERIC_OVERFLOW
;
3308 *ret
= *ret
* 10 + val
;
3315 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
3317 const unsigned char *ptr
= str
;
3320 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3321 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3322 if (!len
) return WS_E_INVALID_FORMAT
;
3328 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3331 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
3332 *ret
= *ret
* 10 + val
;
3339 BOOL
set_fpword( unsigned short new, unsigned short *old
)
3341 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3342 unsigned short fpword
;
3344 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
3347 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3350 FIXME( "not implemented\n" );
3355 void restore_fpword( unsigned short fpword
)
3357 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3358 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3360 FIXME( "not implemented\n" );
3364 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
3366 static const unsigned __int64 nan
= 0xfff8000000000000;
3367 static const unsigned __int64 inf
= 0x7ff0000000000000;
3368 static const unsigned __int64 inf_min
= 0xfff0000000000000;
3369 HRESULT hr
= WS_E_INVALID_FORMAT
;
3370 const unsigned char *p
= str
, *q
;
3371 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
3372 unsigned __int64 val
= 0, tmp
;
3373 long double exp_val
= 1.0, exp_mul
= 10.0;
3374 unsigned short fpword
;
3376 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3377 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3378 if (!len
) return WS_E_INVALID_FORMAT
;
3380 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
3382 *(unsigned __int64
*)ret
= nan
;
3385 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
3387 *(unsigned __int64
*)ret
= inf
;
3390 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
3392 *(unsigned __int64
*)ret
= inf_min
;
3402 else if (*p
== '+') { p
++; len
--; };
3403 if (!len
) return S_OK
;
3405 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
3408 while (len
&& isdigit( *q
)) { q
++; len
--; }
3409 have_digits
= nb_digits
= q
- p
;
3410 for (i
= 0; i
< nb_digits
; i
++)
3412 tmp
= val
* 10 + p
[i
] - '0';
3413 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
3415 for (; i
< nb_digits
; i
++) exp
++;
3426 while (len
&& isdigit( *q
)) { q
++; len
--; };
3427 have_digits
|= nb_digits
= q
- p
;
3428 for (i
= 0; i
< nb_digits
; i
++)
3430 tmp
= val
* 10 + p
[i
] - '0';
3431 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
3436 if (len
> 1 && tolower(*q
) == 'e')
3438 if (!have_digits
) goto done
;
3445 else if (*p
== '+') { p
++; len
--; };
3448 while (len
&& isdigit( *q
)) { q
++; len
--; };
3450 if (!nb_digits
|| len
) goto done
;
3451 for (i
= 0; i
< nb_digits
; i
++)
3453 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
3454 exp_tmp
= MAX_INT32
;
3456 exp_tmp
*= exp_sign
;
3458 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
3459 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
3460 else exp
+= exp_tmp
;
3463 if (!have_digits
|| len
) goto done
;
3465 if ((neg_exp
= exp
< 0)) exp
= -exp
;
3466 for (; exp
; exp
>>= 1)
3468 if (exp
& 1) exp_val
*= exp_mul
;
3472 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
3476 restore_fpword( fpword
);
3480 static HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
3482 static const unsigned char hex
[] =
3484 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3485 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3486 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3487 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3488 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3489 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3490 0,10,11,12,13,14,15 /* 0x60 */
3492 const unsigned char *p
= str
;
3495 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3496 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3497 if (len
!= 36) return WS_E_INVALID_FORMAT
;
3499 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
3500 return WS_E_INVALID_FORMAT
;
3502 for (i
= 0; i
< 36; i
++)
3504 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
3505 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
3508 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
3509 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
3511 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
3512 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
3514 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
3515 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
3516 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
3517 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
3518 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
3519 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
3520 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
3521 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
3526 static HRESULT
str_to_string( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_STRING
*ret
)
3528 int len_utf16
= MultiByteToWideChar( CP_UTF8
, 0, (const char *)str
, len
, NULL
, 0 );
3529 if (!(ret
->chars
= ws_alloc( heap
, len_utf16
* sizeof(WCHAR
) ))) return WS_E_QUOTA_EXCEEDED
;
3530 MultiByteToWideChar( CP_UTF8
, 0, (const char *)str
, len
, ret
->chars
, len_utf16
);
3531 ret
->length
= len_utf16
;
3535 static HRESULT
str_to_unique_id( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_UNIQUE_ID
*ret
)
3537 if (len
== 45 && !memcmp( str
, "urn:uuid:", 9 ))
3539 ret
->uri
.length
= 0;
3540 ret
->uri
.chars
= NULL
;
3541 return str_to_guid( str
+ 9, len
- 9, &ret
->guid
);
3544 memset( &ret
->guid
, 0, sizeof(ret
->guid
) );
3545 return str_to_string( str
, len
, heap
, &ret
->uri
);
3548 static inline unsigned char decode_char( unsigned char c
)
3550 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
3551 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
3552 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
3553 if (c
== '+') return 62;
3554 if (c
== '/') return 63;
3558 static ULONG
decode_base64( const unsigned char *base64
, ULONG len
, unsigned char *buf
)
3561 unsigned char c0
, c1
, c2
, c3
;
3562 const unsigned char *p
= base64
;
3566 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3567 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3568 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3569 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3570 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3571 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3572 buf
[i
+ 2] = (c2
<< 6) | c3
;
3579 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3580 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3581 buf
[i
] = (c0
<< 2) | (c1
>> 4);
3584 else if (p
[3] == '=')
3586 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3587 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3588 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3589 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3590 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3595 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3596 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3597 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3598 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3599 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3600 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3601 buf
[i
+ 2] = (c2
<< 6) | c3
;
3607 static HRESULT
str_to_bytes( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_BYTES
*ret
)
3609 const unsigned char *p
= str
;
3611 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3612 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3614 if (len
% 4) return WS_E_INVALID_FORMAT
;
3615 if (!(ret
->bytes
= ws_alloc( heap
, len
* 3 / 4 ))) return WS_E_QUOTA_EXCEEDED
;
3616 ret
->length
= decode_base64( p
, len
, ret
->bytes
);
3620 static HRESULT
str_to_xml_string( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_XML_STRING
*ret
)
3622 if (!(ret
->bytes
= ws_alloc( heap
, len
))) return WS_E_QUOTA_EXCEEDED
;
3623 memcpy( ret
->bytes
, str
, len
);
3625 ret
->dictionary
= NULL
;
3630 static HRESULT
copy_xml_string( WS_HEAP
*heap
, const WS_XML_STRING
*src
, WS_XML_STRING
*dst
)
3632 if (!(dst
->bytes
= ws_alloc( heap
, src
->length
))) return WS_E_QUOTA_EXCEEDED
;
3633 memcpy( dst
->bytes
, src
->bytes
, src
->length
);
3634 dst
->length
= src
->length
;
3638 static HRESULT
str_to_qname( struct reader
*reader
, const unsigned char *str
, ULONG len
, WS_HEAP
*heap
,
3639 WS_XML_STRING
*prefix_ret
, WS_XML_STRING
*localname_ret
, WS_XML_STRING
*ns_ret
)
3641 const unsigned char *p
= str
;
3642 WS_XML_STRING prefix
, localname
;
3643 const WS_XML_STRING
*ns
;
3646 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3647 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3649 if ((hr
= split_qname( p
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
3650 if (!(ns
= get_namespace( reader
, &prefix
))) return WS_E_INVALID_FORMAT
;
3652 if (prefix_ret
&& (hr
= copy_xml_string( heap
, &prefix
, prefix_ret
)) != S_OK
) return hr
;
3653 if ((hr
= copy_xml_string( heap
, &localname
, localname_ret
)) != S_OK
)
3655 ws_free( heap
, prefix_ret
->bytes
, prefix_ret
->length
);
3658 if ((hr
= copy_xml_string( heap
, ns
, ns_ret
)) != S_OK
)
3660 ws_free( heap
, prefix_ret
->bytes
, prefix_ret
->length
);
3661 ws_free( heap
, localname_ret
->bytes
, localname_ret
->length
);
3667 static HRESULT
read_qualified_name( struct reader
*reader
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
3668 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
)
3670 const WS_XML_TEXT_NODE
*node
= (const WS_XML_TEXT_NODE
*)reader
->current
;
3671 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)node
->text
;
3672 return str_to_qname( reader
, utf8
->value
.bytes
, utf8
->value
.length
, heap
, prefix
, localname
, ns
);
3675 /**************************************************************************
3676 * WsReadQualifiedName [webservices.@]
3678 HRESULT WINAPI
WsReadQualifiedName( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
3679 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
,
3682 struct reader
*reader
= (struct reader
*)handle
;
3685 TRACE( "%p %p %p %p %p %p\n", handle
, heap
, prefix
, localname
, ns
, error
);
3686 if (error
) FIXME( "ignoring error parameter\n" );
3688 if (!reader
|| !heap
) return E_INVALIDARG
;
3690 EnterCriticalSection( &reader
->cs
);
3692 if (reader
->magic
!= READER_MAGIC
)
3694 LeaveCriticalSection( &reader
->cs
);
3695 return E_INVALIDARG
;
3698 if (!reader
->input_type
)
3700 LeaveCriticalSection( &reader
->cs
);
3701 return WS_E_INVALID_OPERATION
;
3706 LeaveCriticalSection( &reader
->cs
);
3707 return E_INVALIDARG
;
3710 if (reader
->state
!= READER_STATE_TEXT
)
3712 LeaveCriticalSection( &reader
->cs
);
3713 return WS_E_INVALID_FORMAT
;
3716 hr
= read_qualified_name( reader
, heap
, prefix
, localname
, ns
);
3718 LeaveCriticalSection( &reader
->cs
);
3722 static const int month_offsets
[2][12] =
3724 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
3725 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
3728 static inline int valid_day( int year
, int month
, int day
)
3730 return day
> 0 && day
<= month_days
[leap_year( year
)][month
- 1];
3733 static inline int leap_days_before( int year
)
3735 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
3738 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
3740 const unsigned char *p
= bytes
, *q
;
3741 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
3743 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3744 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3747 while (len
&& isdigit( *q
)) { q
++; len
--; };
3748 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3749 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
3750 if (year
< 1) return WS_E_INVALID_FORMAT
;
3753 while (len
&& isdigit( *q
)) { q
++; len
--; };
3754 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3755 month
= (p
[0] - '0') * 10 + p
[1] - '0';
3756 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
3759 while (len
&& isdigit( *q
)) { q
++; len
--; };
3760 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
3761 day
= (p
[0] - '0') * 10 + p
[1] - '0';
3762 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
3765 while (len
&& isdigit( *q
)) { q
++; len
--; };
3766 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3767 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3768 if (hour
> 24) return WS_E_INVALID_FORMAT
;
3771 while (len
&& isdigit( *q
)) { q
++; len
--; };
3772 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3773 min
= (p
[0] - '0') * 10 + p
[1] - '0';
3774 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3777 while (len
&& isdigit( *q
)) { q
++; len
--; };
3778 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
3779 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
3780 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3784 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
3786 while (len
&& isdigit( *q
)) { q
++; len
--; };
3788 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
3789 for (i
= 0; i
< nb_digits
; i
++)
3791 sec_frac
+= (p
[i
] - '0') * mul
;
3797 if (--len
) return WS_E_INVALID_FORMAT
;
3798 tz_hour
= tz_min
= tz_neg
= 0;
3799 ret
->format
= WS_DATETIME_FORMAT_UTC
;
3801 else if (*q
== '+' || *q
== '-')
3803 tz_neg
= (*q
== '-') ? 1 : 0;
3806 while (len
&& isdigit( *q
)) { q
++; len
--; };
3807 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3808 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3809 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
3812 while (len
&& isdigit( *q
)) { q
++; len
--; };
3813 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
3814 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
3815 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
3817 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
3819 else return WS_E_INVALID_FORMAT
;
3821 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
3822 ret
->ticks
+= month_offsets
[leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
3823 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
3824 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
3825 ret
->ticks
+= min
* TICKS_PER_MIN
;
3826 ret
->ticks
+= sec
* TICKS_PER_SEC
;
3827 ret
->ticks
+= sec_frac
;
3831 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
3832 return WS_E_INVALID_FORMAT
;
3833 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
3834 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
3838 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
3839 return WS_E_INVALID_FORMAT
;
3840 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
3841 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
3847 /**************************************************************************
3848 * WsDateTimeToFileTime [webservices.@]
3850 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
3852 unsigned __int64 ticks
;
3854 TRACE( "%p %p %p\n", dt
, ft
, error
);
3855 if (error
) FIXME( "ignoring error parameter\n" );
3857 if (!dt
|| !ft
) return E_INVALIDARG
;
3859 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
3860 ticks
= dt
->ticks
- TICKS_1601_01_01
;
3861 ft
->dwHighDateTime
= ticks
>> 32;
3862 ft
->dwLowDateTime
= (DWORD
)ticks
;
3866 /**************************************************************************
3867 * WsFileTimeToDateTime [webservices.@]
3869 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
3871 unsigned __int64 ticks
;
3873 TRACE( "%p %p %p\n", ft
, dt
, error
);
3874 if (error
) FIXME( "ignoring error parameter\n" );
3876 if (!dt
|| !ft
) return E_INVALIDARG
;
3878 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
3879 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
3880 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
3881 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
3882 dt
->format
= WS_DATETIME_FORMAT_UTC
;
3886 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
3887 const WS_XML_STRING
*ns
, ULONG
*index
)
3890 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3894 *index
= reader
->current_attr
;
3897 for (i
= 0; i
< elem
->attributeCount
; i
++)
3899 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
3900 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
3902 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
3903 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
3912 /**************************************************************************
3913 * WsFindAttribute [webservices.@]
3915 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
3916 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
3919 struct reader
*reader
= (struct reader
*)handle
;
3922 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3923 required
, index
, error
);
3924 if (error
) FIXME( "ignoring error parameter\n" );
3926 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
3928 EnterCriticalSection( &reader
->cs
);
3930 if (reader
->magic
!= READER_MAGIC
)
3932 LeaveCriticalSection( &reader
->cs
);
3933 return E_INVALIDARG
;
3936 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
3938 LeaveCriticalSection( &reader
->cs
);
3939 return WS_E_INVALID_OPERATION
;
3942 if (!find_attribute( reader
, localname
, ns
, index
))
3944 if (required
) hr
= WS_E_INVALID_FORMAT
;
3952 LeaveCriticalSection( &reader
->cs
);
3956 static HRESULT
get_node_text( struct reader
*reader
, const WS_XML_TEXT
**ret
)
3958 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
3963 static HRESULT
get_attribute_text( struct reader
*reader
, ULONG index
, const WS_XML_TEXT
**ret
)
3965 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3966 *ret
= elem
->attributes
[index
]->value
;
3970 static BOOL
match_element( const struct node
*node
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
3972 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
3973 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
3974 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
3975 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
3978 static HRESULT
read_next_node( struct reader
*reader
)
3980 if (reader
->current
== reader
->last
) return read_node( reader
);
3981 if (move_to_child_node( &reader
->current
)) return S_OK
;
3982 if (move_to_next_node( &reader
->current
)) return S_OK
;
3983 if (!move_to_parent_node( &reader
->current
)) return WS_E_INVALID_FORMAT
;
3984 if (move_to_next_node( &reader
->current
)) return S_OK
;
3985 return WS_E_INVALID_FORMAT
;
3988 static HRESULT
get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
3989 const WS_XML_STRING
*ns
, const WS_XML_TEXT
**ret
, BOOL
*found
)
3993 case WS_ATTRIBUTE_TYPE_MAPPING
:
3996 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
3997 return get_attribute_text( reader
, index
, ret
);
3999 case WS_ELEMENT_TYPE_MAPPING
:
4000 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
4001 case WS_ANY_ELEMENT_TYPE_MAPPING
:
4007 if (!match_element( reader
->current
, localname
, ns
))
4012 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
4013 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
4015 if (!move_to_parent_element( &reader
->current
)) return WS_E_INVALID_FORMAT
;
4020 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
4025 return get_node_text( reader
, ret
);
4028 FIXME( "mapping %u not supported\n", mapping
);
4033 static const WS_XML_UTF8_TEXT
*text_to_utf8( const WS_XML_TEXT
*text
)
4035 assert( text
->textType
== WS_XML_TEXT_TYPE_UTF8
);
4036 return (const WS_XML_UTF8_TEXT
*)text
;
4039 static const WS_XML_BASE64_TEXT
*text_to_base64( const WS_XML_TEXT
*text
)
4041 assert( text
->textType
== WS_XML_TEXT_TYPE_BASE64
);
4042 return (const WS_XML_BASE64_TEXT
*)text
;
4045 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4046 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4047 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4048 WS_HEAP
*heap
, void *ret
, ULONG size
)
4050 const WS_XML_TEXT
*text
;
4052 BOOL found
, val
= FALSE
;
4056 FIXME( "description not supported\n" );
4059 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4062 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4063 ULONG len
= utf8
->value
.length
;
4064 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
4065 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
4066 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
4067 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
4068 else return WS_E_INVALID_FORMAT
;
4073 case WS_READ_REQUIRED_VALUE
:
4074 if (!found
) return WS_E_INVALID_FORMAT
;
4077 case WS_READ_NILLABLE_VALUE
:
4078 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4082 case WS_READ_REQUIRED_POINTER
:
4083 if (!found
) return WS_E_INVALID_FORMAT
;
4086 case WS_READ_OPTIONAL_POINTER
:
4087 case WS_READ_NILLABLE_POINTER
:
4089 BOOL
*heap_val
= NULL
;
4090 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4093 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4096 *(BOOL
**)ret
= heap_val
;
4100 FIXME( "read option %u not supported\n", option
);
4107 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4108 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4109 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4110 WS_HEAP
*heap
, void *ret
, ULONG size
)
4112 const WS_XML_TEXT
*text
;
4119 FIXME( "description not supported\n" );
4122 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4125 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4126 if ((hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
4132 case WS_READ_REQUIRED_VALUE
:
4133 if (!found
) return WS_E_INVALID_FORMAT
;
4136 case WS_READ_NILLABLE_VALUE
:
4137 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
4141 case WS_READ_REQUIRED_POINTER
:
4142 if (!found
) return WS_E_INVALID_FORMAT
;
4145 case WS_READ_OPTIONAL_POINTER
:
4146 case WS_READ_NILLABLE_POINTER
:
4148 INT8
*heap_val
= NULL
;
4149 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4152 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4155 *(INT8
**)ret
= heap_val
;
4159 FIXME( "read option %u not supported\n", option
);
4166 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4167 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4168 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4169 WS_HEAP
*heap
, void *ret
, ULONG size
)
4171 const WS_XML_TEXT
*text
;
4178 FIXME( "description not supported\n" );
4181 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4184 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4185 if ((hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
4191 case WS_READ_REQUIRED_VALUE
:
4192 if (!found
) return WS_E_INVALID_FORMAT
;
4195 case WS_READ_NILLABLE_VALUE
:
4196 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
4197 *(INT16
*)ret
= val
;
4200 case WS_READ_REQUIRED_POINTER
:
4201 if (!found
) return WS_E_INVALID_FORMAT
;
4204 case WS_READ_OPTIONAL_POINTER
:
4205 case WS_READ_NILLABLE_POINTER
:
4207 INT16
*heap_val
= NULL
;
4208 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4211 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4214 *(INT16
**)ret
= heap_val
;
4218 FIXME( "read option %u not supported\n", option
);
4225 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4226 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4227 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4228 WS_HEAP
*heap
, void *ret
, ULONG size
)
4230 const WS_XML_TEXT
*text
;
4237 FIXME( "description not supported\n" );
4240 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4243 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4244 if ((hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
4250 case WS_READ_REQUIRED_VALUE
:
4251 if (!found
) return WS_E_INVALID_FORMAT
;
4254 case WS_READ_NILLABLE_VALUE
:
4255 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
4256 *(INT32
*)ret
= val
;
4259 case WS_READ_REQUIRED_POINTER
:
4260 if (!found
) return WS_E_INVALID_FORMAT
;
4263 case WS_READ_OPTIONAL_POINTER
:
4264 case WS_READ_NILLABLE_POINTER
:
4266 INT32
*heap_val
= NULL
;
4267 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4270 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4273 *(INT32
**)ret
= heap_val
;
4277 FIXME( "read option %u not supported\n", option
);
4284 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4285 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4286 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4287 WS_HEAP
*heap
, void *ret
, ULONG size
)
4289 const WS_XML_TEXT
*text
;
4296 FIXME( "description not supported\n" );
4299 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4302 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4303 if ((hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
4309 case WS_READ_REQUIRED_VALUE
:
4310 if (!found
) return WS_E_INVALID_FORMAT
;
4313 case WS_READ_NILLABLE_VALUE
:
4314 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4315 *(INT64
*)ret
= val
;
4318 case WS_READ_REQUIRED_POINTER
:
4319 if (!found
) return WS_E_INVALID_FORMAT
;
4322 case WS_READ_OPTIONAL_POINTER
:
4323 case WS_READ_NILLABLE_POINTER
:
4325 INT64
*heap_val
= NULL
;
4326 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4329 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4332 *(INT64
**)ret
= heap_val
;
4336 FIXME( "read option %u not supported\n", option
);
4343 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4344 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4345 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4346 WS_HEAP
*heap
, void *ret
, ULONG size
)
4348 const WS_XML_TEXT
*text
;
4355 FIXME( "description not supported\n" );
4358 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4361 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4362 if ((hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
4368 case WS_READ_REQUIRED_VALUE
:
4369 if (!found
) return WS_E_INVALID_FORMAT
;
4372 case WS_READ_NILLABLE_VALUE
:
4373 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
4374 *(UINT8
*)ret
= val
;
4377 case WS_READ_REQUIRED_POINTER
:
4378 if (!found
) return WS_E_INVALID_FORMAT
;
4381 case WS_READ_OPTIONAL_POINTER
:
4382 case WS_READ_NILLABLE_POINTER
:
4384 UINT8
*heap_val
= NULL
;
4385 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4388 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4391 *(UINT8
**)ret
= heap_val
;
4395 FIXME( "read option %u not supported\n", option
);
4402 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4403 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4404 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4405 WS_HEAP
*heap
, void *ret
, ULONG size
)
4407 const WS_XML_TEXT
*text
;
4414 FIXME( "description not supported\n" );
4417 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4420 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4421 if ((hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
4427 case WS_READ_REQUIRED_VALUE
:
4428 if (!found
) return WS_E_INVALID_FORMAT
;
4431 case WS_READ_NILLABLE_VALUE
:
4432 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
4433 *(UINT16
*)ret
= val
;
4436 case WS_READ_REQUIRED_POINTER
:
4437 if (!found
) return WS_E_INVALID_FORMAT
;
4440 case WS_READ_OPTIONAL_POINTER
:
4441 case WS_READ_NILLABLE_POINTER
:
4443 UINT16
*heap_val
= NULL
;
4444 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4447 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4450 *(UINT16
**)ret
= heap_val
;
4454 FIXME( "read option %u not supported\n", option
);
4461 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4462 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4463 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4464 WS_HEAP
*heap
, void *ret
, ULONG size
)
4466 const WS_XML_TEXT
*text
;
4473 FIXME( "description not supported\n" );
4476 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4479 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4480 if ((hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
4486 case WS_READ_REQUIRED_VALUE
:
4487 if (!found
) return WS_E_INVALID_FORMAT
;
4490 case WS_READ_NILLABLE_VALUE
:
4491 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
4492 *(UINT32
*)ret
= val
;
4495 case WS_READ_REQUIRED_POINTER
:
4496 if (!found
) return WS_E_INVALID_FORMAT
;
4499 case WS_READ_OPTIONAL_POINTER
:
4500 case WS_READ_NILLABLE_POINTER
:
4502 UINT32
*heap_val
= NULL
;
4503 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4506 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4509 *(UINT32
**)ret
= heap_val
;
4513 FIXME( "read option %u not supported\n", option
);
4520 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4521 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4522 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4523 WS_HEAP
*heap
, void *ret
, ULONG size
)
4525 const WS_XML_TEXT
*text
;
4532 FIXME( "description not supported\n" );
4535 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4538 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4539 if ((hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
)) != S_OK
)
4545 case WS_READ_REQUIRED_VALUE
:
4546 if (!found
) return WS_E_INVALID_FORMAT
;
4549 case WS_READ_NILLABLE_VALUE
:
4550 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4551 *(UINT64
*)ret
= val
;
4554 case WS_READ_REQUIRED_POINTER
:
4555 if (!found
) return WS_E_INVALID_FORMAT
;
4558 case WS_READ_OPTIONAL_POINTER
:
4559 case WS_READ_NILLABLE_POINTER
:
4561 UINT64
*heap_val
= NULL
;
4562 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4565 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4568 *(UINT64
**)ret
= heap_val
;
4572 FIXME( "read option %u not supported\n", option
);
4579 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4580 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4581 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4582 WS_HEAP
*heap
, void *ret
, ULONG size
)
4584 const WS_XML_TEXT
*text
;
4589 if (desc
) FIXME( "ignoring description\n" );
4591 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4594 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4595 if ((hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4600 case WS_READ_REQUIRED_VALUE
:
4601 if (!found
) return WS_E_INVALID_FORMAT
;
4604 case WS_READ_NILLABLE_VALUE
:
4605 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4606 *(double *)ret
= val
;
4609 case WS_READ_REQUIRED_POINTER
:
4610 if (!found
) return WS_E_INVALID_FORMAT
;
4613 case WS_READ_OPTIONAL_POINTER
:
4614 case WS_READ_NILLABLE_POINTER
:
4616 double *heap_val
= NULL
;
4617 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4620 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4623 *(double **)ret
= heap_val
;
4627 FIXME( "read option %u not supported\n", option
);
4634 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4635 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4636 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4637 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
4639 const WS_XML_TEXT
*text
;
4646 FIXME( "description not supported\n" );
4649 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4650 if (found
&& !(str
= xmltext_to_widechar( heap
, text
))) return WS_E_QUOTA_EXCEEDED
;
4654 case WS_READ_REQUIRED_POINTER
:
4655 if (!str
&& !(str
= ws_alloc_zero( heap
, sizeof(*str
) ))) return WS_E_QUOTA_EXCEEDED
;
4658 case WS_READ_OPTIONAL_POINTER
:
4659 case WS_READ_NILLABLE_POINTER
:
4660 if (size
!= sizeof(str
)) return E_INVALIDARG
;
4665 FIXME( "read option %u not supported\n", option
);
4672 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
4675 for (i
= 0; i
< desc
->valueCount
; i
++)
4677 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
4679 *ret
= desc
->values
[i
].value
;
4683 return WS_E_INVALID_FORMAT
;
4686 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4687 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4688 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4689 WS_HEAP
*heap
, void *ret
, ULONG size
)
4691 const WS_XML_TEXT
*text
;
4696 if (!desc
) return E_INVALIDARG
;
4698 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4701 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4702 if ((hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
4707 case WS_READ_REQUIRED_VALUE
:
4708 if (!found
) return WS_E_INVALID_FORMAT
;
4711 case WS_READ_NILLABLE_VALUE
:
4712 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4716 case WS_READ_REQUIRED_POINTER
:
4717 if (!found
) return WS_E_INVALID_FORMAT
;
4720 case WS_READ_OPTIONAL_POINTER
:
4721 case WS_READ_NILLABLE_POINTER
:
4723 int *heap_val
= NULL
;
4724 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4727 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4730 *(int **)ret
= heap_val
;
4734 FIXME( "read option %u not supported\n", option
);
4741 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4742 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4743 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4744 WS_HEAP
*heap
, void *ret
, ULONG size
)
4746 const WS_XML_TEXT
*text
;
4748 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
4751 if (desc
) FIXME( "ignoring description\n" );
4753 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4756 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4757 if ((hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4762 case WS_READ_REQUIRED_VALUE
:
4763 if (!found
) return WS_E_INVALID_FORMAT
;
4766 case WS_READ_NILLABLE_VALUE
:
4767 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4768 *(WS_DATETIME
*)ret
= val
;
4771 case WS_READ_REQUIRED_POINTER
:
4772 if (!found
) return WS_E_INVALID_FORMAT
;
4775 case WS_READ_OPTIONAL_POINTER
:
4776 case WS_READ_NILLABLE_POINTER
:
4778 WS_DATETIME
*heap_val
= NULL
;
4779 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4782 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4785 *(WS_DATETIME
**)ret
= heap_val
;
4789 FIXME( "read option %u not supported\n", option
);
4796 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4797 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4798 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4799 WS_HEAP
*heap
, void *ret
, ULONG size
)
4801 const WS_XML_TEXT
*text
;
4806 if (desc
) FIXME( "ignoring description\n" );
4808 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4811 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4812 if ((hr
= str_to_guid( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4817 case WS_READ_REQUIRED_VALUE
:
4818 if (!found
) return WS_E_INVALID_FORMAT
;
4821 case WS_READ_NILLABLE_VALUE
:
4822 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4826 case WS_READ_REQUIRED_POINTER
:
4827 if (!found
) return WS_E_INVALID_FORMAT
;
4830 case WS_READ_OPTIONAL_POINTER
:
4831 case WS_READ_NILLABLE_POINTER
:
4833 GUID
*heap_val
= NULL
;
4834 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4837 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4840 *(GUID
**)ret
= heap_val
;
4844 FIXME( "read option %u not supported\n", option
);
4851 static HRESULT
read_type_unique_id( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4852 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4853 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4854 WS_HEAP
*heap
, void *ret
, ULONG size
)
4856 const WS_XML_TEXT
*text
;
4857 WS_UNIQUE_ID val
= {{0}};
4861 if (desc
) FIXME( "ignoring description\n" );
4863 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4866 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4867 if ((hr
= str_to_unique_id( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
) return hr
;
4872 case WS_READ_REQUIRED_VALUE
:
4873 if (!found
) return WS_E_INVALID_FORMAT
;
4876 case WS_READ_NILLABLE_VALUE
:
4877 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4878 *(WS_UNIQUE_ID
*)ret
= val
;
4881 case WS_READ_REQUIRED_POINTER
:
4882 if (!found
) return WS_E_INVALID_FORMAT
;
4885 case WS_READ_OPTIONAL_POINTER
:
4886 case WS_READ_NILLABLE_POINTER
:
4888 WS_UNIQUE_ID
*heap_val
= NULL
;
4889 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4892 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4895 *(WS_UNIQUE_ID
**)ret
= heap_val
;
4899 FIXME( "read option %u not supported\n", option
);
4906 static HRESULT
read_type_string( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4907 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4908 const WS_STRING_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4909 WS_HEAP
*heap
, void *ret
, ULONG size
)
4911 const WS_XML_TEXT
*text
;
4912 WS_STRING val
= {0};
4916 if (desc
) FIXME( "ignoring description\n" );
4918 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4921 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4922 if ((hr
= str_to_string( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4928 case WS_READ_REQUIRED_VALUE
:
4929 case WS_READ_NILLABLE_VALUE
:
4930 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4931 *(WS_STRING
*)ret
= val
;
4934 case WS_READ_REQUIRED_POINTER
:
4936 WS_STRING
*heap_val
;
4937 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4938 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4940 *(WS_STRING
**)ret
= heap_val
;
4943 case WS_READ_OPTIONAL_POINTER
:
4944 case WS_READ_NILLABLE_POINTER
:
4946 WS_STRING
*heap_val
= NULL
;
4947 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4950 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4953 *(WS_STRING
**)ret
= heap_val
;
4957 FIXME( "read option %u not supported\n", option
);
4964 static HRESULT
read_type_bytes( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4965 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4966 const WS_BYTES_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4967 WS_HEAP
*heap
, void *ret
, ULONG size
)
4969 const WS_XML_TEXT
*text
;
4974 if (desc
) FIXME( "ignoring description\n" );
4976 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
4979 switch (reader
->input_enc
)
4981 case WS_XML_READER_ENCODING_TYPE_TEXT
:
4983 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
4984 if ((hr
= str_to_bytes( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4988 case WS_XML_READER_ENCODING_TYPE_BINARY
:
4990 const WS_XML_BASE64_TEXT
*base64
= text_to_base64( text
);
4991 if (!(val
.bytes
= ws_alloc( heap
, base64
->length
))) return WS_E_QUOTA_EXCEEDED
;
4992 memcpy( val
.bytes
, base64
->bytes
, base64
->length
);
4993 val
.length
= base64
->length
;
4997 FIXME( "unhandled input encoding %u\n", reader
->input_enc
);
4998 return WS_E_NOT_SUPPORTED
;
5004 case WS_READ_REQUIRED_VALUE
:
5005 case WS_READ_NILLABLE_VALUE
:
5006 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5007 *(WS_BYTES
*)ret
= val
;
5010 case WS_READ_REQUIRED_POINTER
:
5013 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5014 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5016 *(WS_BYTES
**)ret
= heap_val
;
5019 case WS_READ_OPTIONAL_POINTER
:
5020 case WS_READ_NILLABLE_POINTER
:
5022 WS_BYTES
*heap_val
= NULL
;
5023 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5026 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5029 *(WS_BYTES
**)ret
= heap_val
;
5033 FIXME( "read option %u not supported\n", option
);
5040 static HRESULT
read_type_xml_string( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5041 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5042 const WS_XML_STRING_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5043 WS_HEAP
*heap
, void *ret
, ULONG size
)
5045 const WS_XML_TEXT
*text
;
5046 WS_XML_STRING val
= {0};
5050 if (desc
) FIXME( "ignoring description\n" );
5052 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
5055 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
5056 if ((hr
= str_to_xml_string( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
5062 case WS_READ_REQUIRED_VALUE
:
5063 case WS_READ_NILLABLE_VALUE
:
5064 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5065 *(WS_XML_STRING
*)ret
= val
;
5068 case WS_READ_REQUIRED_POINTER
:
5070 WS_XML_STRING
*heap_val
;
5071 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5072 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5074 *(WS_XML_STRING
**)ret
= heap_val
;
5077 case WS_READ_OPTIONAL_POINTER
:
5078 case WS_READ_NILLABLE_POINTER
:
5080 WS_XML_STRING
*heap_val
= NULL
;
5081 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5084 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5087 *(WS_XML_STRING
**)ret
= heap_val
;
5091 FIXME( "read option %u not supported\n", option
);
5098 static HRESULT
read_type_qname( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5099 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5100 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5101 WS_HEAP
*heap
, void *ret
, ULONG size
)
5103 const WS_XML_TEXT
*text
;
5104 WS_XML_QNAME val
= {{0}};
5108 if (desc
) FIXME( "ignoring description\n" );
5110 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
5111 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
5112 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
5114 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, &found
)) != S_OK
) return hr
;
5117 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
);
5118 if ((hr
= str_to_qname( reader
, utf8
->value
.bytes
, utf8
->value
.length
, heap
, NULL
,
5119 &val
.localName
, &val
.ns
)) != S_OK
) return hr
;
5124 case WS_READ_REQUIRED_VALUE
:
5125 if (!found
) return WS_E_INVALID_FORMAT
;
5128 case WS_READ_NILLABLE_VALUE
:
5129 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5130 *(WS_XML_QNAME
*)ret
= val
;
5133 case WS_READ_REQUIRED_POINTER
:
5134 if (!found
) return WS_E_INVALID_FORMAT
;
5137 case WS_READ_OPTIONAL_POINTER
:
5138 case WS_READ_NILLABLE_POINTER
:
5140 WS_XML_QNAME
*heap_val
= NULL
;
5141 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5144 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5147 *(WS_XML_QNAME
**)ret
= heap_val
;
5151 FIXME( "read option %u not supported\n", option
);
5158 static BOOL
is_empty_text_node( const struct node
*node
)
5160 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
5162 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
5163 switch (text
->text
->textType
)
5165 case WS_XML_TEXT_TYPE_UTF8
:
5168 const WS_XML_UTF8_TEXT
*utf8
= text_to_utf8( text
->text
);
5169 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
5172 case WS_XML_TEXT_TYPE_BASE64
:
5174 const WS_XML_BASE64_TEXT
*base64
= text_to_base64( text
->text
);
5175 return !base64
->length
;
5178 ERR( "unhandled text type %u\n", text
->text
->textType
);
5183 /* skips comment and empty text nodes */
5184 static HRESULT
read_type_next_node( struct reader
*reader
)
5189 WS_XML_NODE_TYPE type
;
5191 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
5192 type
= node_type( reader
->current
);
5193 if (type
== WS_XML_NODE_TYPE_COMMENT
||
5194 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
5199 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
5200 const WS_XML_STRING
*ns
)
5206 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
5207 if (reader
->current
== reader
->last
)
5210 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
5211 if (!found
) return WS_E_INVALID_FORMAT
;
5213 if (match_element( reader
->current
, localname
, ns
)) return S_OK
;
5215 node
= reader
->current
;
5216 attr
= reader
->current_attr
;
5218 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
5219 if (match_element( reader
->current
, localname
, ns
)) return S_OK
;
5221 reader
->current
= node
;
5222 reader
->current_attr
= attr
;
5224 return WS_E_INVALID_FORMAT
;
5227 ULONG
get_type_size( WS_TYPE type
, const void *desc
)
5233 return sizeof(INT8
);
5236 case WS_UINT16_TYPE
:
5237 return sizeof(INT16
);
5241 case WS_UINT32_TYPE
:
5243 return sizeof(INT32
);
5246 case WS_UINT64_TYPE
:
5247 return sizeof(INT64
);
5249 case WS_DOUBLE_TYPE
:
5250 return sizeof(double);
5252 case WS_DATETIME_TYPE
:
5253 return sizeof(WS_DATETIME
);
5256 return sizeof(GUID
);
5258 case WS_STRING_TYPE
:
5259 return sizeof(WS_STRING
);
5262 return sizeof(WCHAR
*);
5265 return sizeof(WS_BYTES
);
5267 case WS_XML_STRING_TYPE
:
5268 return sizeof(WS_XML_STRING
);
5270 case WS_XML_QNAME_TYPE
:
5271 return sizeof(WS_XML_QNAME
);
5273 case WS_DESCRIPTION_TYPE
:
5274 return sizeof(WS_STRUCT_DESCRIPTION
*);
5276 case WS_STRUCT_TYPE
:
5278 const WS_STRUCT_DESCRIPTION
*desc_struct
= desc
;
5279 return desc_struct
->size
;
5283 const WS_UNION_DESCRIPTION
*desc_union
= desc
;
5284 return desc_union
->size
;
5287 ERR( "unhandled type %u\n", type
);
5292 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
, ULONG options
)
5294 if (options
& WS_FIELD_POINTER
)
5296 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
5297 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
5298 return WS_READ_REQUIRED_POINTER
;
5309 case WS_UINT16_TYPE
:
5310 case WS_UINT32_TYPE
:
5311 case WS_UINT64_TYPE
:
5312 case WS_DOUBLE_TYPE
:
5313 case WS_DATETIME_TYPE
:
5315 case WS_UNIQUE_ID_TYPE
:
5316 case WS_STRING_TYPE
:
5318 case WS_XML_STRING_TYPE
:
5319 case WS_XML_QNAME_TYPE
:
5320 case WS_STRUCT_TYPE
:
5323 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_READ_NILLABLE_VALUE
;
5324 return WS_READ_REQUIRED_VALUE
;
5327 case WS_DESCRIPTION_TYPE
:
5328 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
5329 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
5330 return WS_READ_REQUIRED_POINTER
;
5333 FIXME( "unhandled type %u\n", type
);
5338 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
5339 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
5342 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5343 WS_HEAP
*heap
, void **ret
, ULONG
*count
)
5346 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
5347 WS_READ_OPTION option
;
5350 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
5352 /* wrapper element */
5353 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
5356 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
5357 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
5359 item_size
= sizeof(void *);
5361 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
5364 if (nb_items
>= nb_allocated
)
5366 SIZE_T old_size
= nb_allocated
* item_size
, new_size
= old_size
* 2;
5367 if (!(buf
= ws_realloc_zero( heap
, buf
, old_size
, new_size
)))
5368 return WS_E_QUOTA_EXCEEDED
;
5371 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
5372 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
5373 if (hr
== WS_E_INVALID_FORMAT
) break;
5376 ws_free( heap
, buf
, nb_allocated
* item_size
);
5379 offset
+= item_size
;
5383 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
5385 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
5387 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
5388 desc
->itemRange
->maxItemCount
);
5389 ws_free( heap
, buf
, nb_allocated
* item_size
);
5390 return WS_E_INVALID_FORMAT
;
5399 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5400 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
5403 if (reader
->current
== reader
->last
)
5406 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
5407 if (!found
) return WS_E_INVALID_FORMAT
;
5409 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
5410 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
5412 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
5413 desc
->typeDescription
, option
, heap
, ret
, size
);
5416 static HRESULT
read_type_field( struct reader
*, const WS_FIELD_DESCRIPTION
*, WS_HEAP
*, char *, ULONG
);
5418 static HRESULT
read_type_union( struct reader
*reader
, const WS_UNION_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5419 WS_HEAP
*heap
, void *ret
, ULONG size
)
5422 HRESULT hr
= WS_E_INVALID_FORMAT
;
5426 case WS_READ_REQUIRED_VALUE
:
5427 case WS_READ_NILLABLE_VALUE
:
5428 if (size
!= desc
->size
) return E_INVALIDARG
;
5432 return E_INVALIDARG
;
5435 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
5436 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
5437 for (i
= 0; i
< desc
->fieldCount
; i
++)
5439 if (match_element( reader
->current
, desc
->fields
[i
]->field
.localName
, desc
->fields
[i
]->field
.ns
))
5442 if (i
== desc
->fieldCount
)
5444 if (!move_to_parent_element( &reader
->current
)) return WS_E_INVALID_FORMAT
;
5445 *(int *)((char *)ret
+ desc
->enumOffset
) = desc
->noneEnumValue
;
5449 offset
= desc
->fields
[i
]->field
.offset
;
5450 if ((hr
= read_type_field( reader
, &desc
->fields
[i
]->field
, heap
, ret
, offset
)) == S_OK
)
5451 *(int *)((char *)ret
+ desc
->enumOffset
) = desc
->fields
[i
]->value
;
5456 case WS_READ_NILLABLE_VALUE
:
5459 case WS_READ_REQUIRED_VALUE
:
5460 if (hr
!= S_OK
) return hr
;
5464 return E_INVALIDARG
;
5470 static HRESULT
read_type_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
, char *buf
,
5474 WS_READ_OPTION option
;
5478 if (!desc
) return E_INVALIDARG
;
5479 if (desc
->options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
5481 FIXME( "options %08x not supported\n", desc
->options
);
5484 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
5486 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
5487 size
= get_type_size( desc
->type
, desc
->typeDescription
);
5489 size
= sizeof(void *);
5492 switch (desc
->mapping
)
5494 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING
:
5495 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
5498 case WS_ATTRIBUTE_FIELD_MAPPING
:
5499 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
5500 desc
->typeDescription
, option
, heap
, ptr
, size
);
5503 case WS_ELEMENT_FIELD_MAPPING
:
5504 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
5505 desc
->typeDescription
, option
, heap
, ptr
, size
);
5508 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
5509 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
||
5510 (desc
->options
& (WS_FIELD_POINTER
|WS_FIELD_NILLABLE
))) return E_INVALIDARG
;
5511 hr
= read_type_union( reader
, desc
->typeDescription
, option
, heap
, ptr
, size
);
5514 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
5517 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, &count
);
5518 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
5521 case WS_TEXT_FIELD_MAPPING
:
5522 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
5526 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
5530 if (hr
== WS_E_INVALID_FORMAT
)
5534 case WS_READ_REQUIRED_VALUE
:
5535 case WS_READ_REQUIRED_POINTER
:
5536 return WS_E_INVALID_FORMAT
;
5538 case WS_READ_NILLABLE_VALUE
:
5539 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
5542 case WS_READ_OPTIONAL_POINTER
:
5543 case WS_READ_NILLABLE_POINTER
:
5544 *(void **)ptr
= NULL
;
5548 ERR( "unhandled option %u\n", option
);
5556 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
5557 const WS_XML_STRING
*ns
, const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5558 WS_HEAP
*heap
, void *ret
, ULONG size
)
5564 if (!desc
) return E_INVALIDARG
;
5565 if (desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5567 FIXME( "struct options %08x not supported\n",
5568 desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
);
5573 case WS_READ_REQUIRED_POINTER
:
5574 case WS_READ_OPTIONAL_POINTER
:
5575 case WS_READ_NILLABLE_POINTER
:
5576 if (size
!= sizeof(void *)) return E_INVALIDARG
;
5577 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
5580 case WS_READ_REQUIRED_VALUE
:
5581 case WS_READ_NILLABLE_VALUE
:
5582 if (size
!= desc
->size
) return E_INVALIDARG
;
5587 FIXME( "unhandled read option %u\n", option
);
5591 for (i
= 0; i
< desc
->fieldCount
; i
++)
5593 offset
= desc
->fields
[i
]->offset
;
5594 if ((hr
= read_type_field( reader
, desc
->fields
[i
], heap
, buf
, offset
)) != S_OK
) break;
5599 case WS_READ_REQUIRED_POINTER
:
5602 ws_free( heap
, buf
, desc
->size
);
5605 *(char **)ret
= buf
;
5608 case WS_READ_OPTIONAL_POINTER
:
5609 case WS_READ_NILLABLE_POINTER
:
5610 if (is_nil_value( buf
, desc
->size
))
5612 ws_free( heap
, buf
, desc
->size
);
5615 *(char **)ret
= buf
;
5618 case WS_READ_REQUIRED_VALUE
:
5619 case WS_READ_NILLABLE_VALUE
:
5620 if (hr
!= S_OK
) return hr
;
5624 ERR( "unhandled read option %u\n", option
);
5628 if (desc
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5630 struct node
*parent
= find_parent( reader
);
5631 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
5636 static HRESULT
start_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
5637 const WS_XML_STRING
*ns
)
5641 case WS_ELEMENT_TYPE_MAPPING
:
5642 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5643 return read_type_next_element_node( reader
, localname
, ns
);
5645 case WS_ANY_ELEMENT_TYPE_MAPPING
:
5646 case WS_ATTRIBUTE_TYPE_MAPPING
:
5650 FIXME( "unhandled mapping %u\n", mapping
);
5655 static HRESULT
read_type_endelement_node( struct reader
*reader
)
5657 const struct node
*parent
= find_parent( reader
);
5662 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
5663 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
&& reader
->current
->parent
== parent
)
5667 if (read_end_of_data( reader
) || !(parent
->flags
& NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
)) break;
5670 return WS_E_INVALID_FORMAT
;
5673 static HRESULT
end_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
)
5677 case WS_ELEMENT_TYPE_MAPPING
:
5678 return read_type_endelement_node( reader
);
5680 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5681 return read_type_next_node( reader
);
5683 case WS_ATTRIBUTE_TYPE_MAPPING
:
5689 static HRESULT
is_nil_element( const WS_XML_ELEMENT_NODE
*elem
)
5691 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
5692 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
5695 for (i
= 0; i
< elem
->attributeCount
; i
++)
5697 const WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[i
]->value
;
5699 if (elem
->attributes
[i
]->isXmlNs
) continue;
5700 if (WsXmlStringEquals( elem
->attributes
[i
]->localName
, &localname
, NULL
) == S_OK
&&
5701 WsXmlStringEquals( elem
->attributes
[i
]->ns
, &ns
, NULL
) == S_OK
&&
5702 text
->value
.length
== 4 && !memcmp( text
->value
.bytes
, "true", 4 )) return TRUE
;
5707 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5708 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
, const void *desc
,
5709 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
)
5713 if ((hr
= start_mapping( reader
, mapping
, localname
, ns
)) != S_OK
) return hr
;
5715 if (mapping
== WS_ELEMENT_TYPE_MAPPING
&& is_nil_element( &reader
->current
->hdr
))
5717 if (option
!= WS_READ_NILLABLE_POINTER
&& option
!= WS_READ_NILLABLE_VALUE
) return WS_E_INVALID_FORMAT
;
5718 return end_mapping( reader
, mapping
);
5724 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5729 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5734 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5739 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5744 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5749 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5753 case WS_UINT16_TYPE
:
5754 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5758 case WS_UINT32_TYPE
:
5759 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5763 case WS_UINT64_TYPE
:
5764 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5768 case WS_DOUBLE_TYPE
:
5769 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5773 case WS_DATETIME_TYPE
:
5774 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5779 if ((hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5783 case WS_UNIQUE_ID_TYPE
:
5784 if ((hr
= read_type_unique_id( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5788 case WS_STRING_TYPE
:
5789 if ((hr
= read_type_string( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5794 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5799 if ((hr
= read_type_bytes( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5803 case WS_XML_STRING_TYPE
:
5804 if ((hr
= read_type_xml_string( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5808 case WS_XML_QNAME_TYPE
:
5809 if ((hr
= read_type_qname( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5813 case WS_STRUCT_TYPE
:
5814 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5819 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5824 FIXME( "type %u not supported\n", type
);
5828 return end_mapping( reader
, mapping
);
5831 /**************************************************************************
5832 * WsReadType [webservices.@]
5834 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5835 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
5836 ULONG size
, WS_ERROR
*error
)
5838 struct reader
*reader
= (struct reader
*)handle
;
5841 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
5843 if (error
) FIXME( "ignoring error parameter\n" );
5845 if (!reader
|| !value
) return E_INVALIDARG
;
5847 EnterCriticalSection( &reader
->cs
);
5849 if (reader
->magic
!= READER_MAGIC
)
5851 LeaveCriticalSection( &reader
->cs
);
5852 return E_INVALIDARG
;
5855 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
5857 LeaveCriticalSection( &reader
->cs
);
5863 case WS_ELEMENT_TYPE_MAPPING
:
5864 hr
= read_node( reader
);
5871 if (hr
== S_OK
&& !read_end_of_data( reader
)) hr
= WS_E_INVALID_FORMAT
;
5873 LeaveCriticalSection( &reader
->cs
);
5877 HRESULT
read_header( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5878 WS_TYPE type
, const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
5881 struct reader
*reader
= (struct reader
*)handle
;
5884 EnterCriticalSection( &reader
->cs
);
5886 if (reader
->magic
!= READER_MAGIC
)
5888 LeaveCriticalSection( &reader
->cs
);
5889 return E_INVALIDARG
;
5892 hr
= read_type( reader
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, type
, localname
, ns
, desc
, option
, heap
,
5895 LeaveCriticalSection( &reader
->cs
);
5899 /**************************************************************************
5900 * WsReadElement [webservices.@]
5902 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
5903 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5906 struct reader
*reader
= (struct reader
*)handle
;
5909 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5910 if (error
) FIXME( "ignoring error parameter\n" );
5912 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5914 EnterCriticalSection( &reader
->cs
);
5916 if (reader
->magic
!= READER_MAGIC
)
5918 LeaveCriticalSection( &reader
->cs
);
5919 return E_INVALIDARG
;
5922 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
5923 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5925 LeaveCriticalSection( &reader
->cs
);
5929 /**************************************************************************
5930 * WsReadValue [webservices.@]
5932 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
5935 struct reader
*reader
= (struct reader
*)handle
;
5936 WS_TYPE type
= map_value_type( value_type
);
5939 TRACE( "%p %u %p %u %p\n", handle
, type
, value
, size
, error
);
5940 if (error
) FIXME( "ignoring error parameter\n" );
5942 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
5944 EnterCriticalSection( &reader
->cs
);
5946 if (reader
->magic
!= READER_MAGIC
)
5948 LeaveCriticalSection( &reader
->cs
);
5949 return E_INVALIDARG
;
5952 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
5953 NULL
, value
, size
);
5955 LeaveCriticalSection( &reader
->cs
);
5959 /**************************************************************************
5960 * WsReadAttribute [webservices.@]
5962 HRESULT WINAPI
WsReadAttribute( WS_XML_READER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
5963 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5966 struct reader
*reader
= (struct reader
*)handle
;
5969 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5970 if (error
) FIXME( "ignoring error parameter\n" );
5972 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5974 EnterCriticalSection( &reader
->cs
);
5976 if (reader
->magic
!= READER_MAGIC
)
5978 LeaveCriticalSection( &reader
->cs
);
5979 return E_INVALIDARG
;
5982 if (!reader
->input_type
)
5984 LeaveCriticalSection( &reader
->cs
);
5985 return WS_E_INVALID_OPERATION
;
5988 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->attributeLocalName
,
5989 desc
->attributeNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5991 LeaveCriticalSection( &reader
->cs
);
5995 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5997 static const char bom
[] = {0xef,0xbb,0xbf};
5998 const unsigned char *p
= data
;
6000 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
6001 (size
> 2 && !(*offset
= 0));
6004 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
6006 static const char bom
[] = {0xff,0xfe};
6007 const unsigned char *p
= data
;
6009 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
6010 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
6013 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
6017 /* FIXME: parse xml declaration */
6019 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
6020 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
6023 FIXME( "charset not recognized\n" );
6027 TRACE( "detected charset %u\n", ret
);
6031 static void set_input_buffer( struct reader
*reader
, struct xmlbuf
*buf
, const unsigned char *data
, ULONG size
)
6033 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
6034 reader
->input_buf
= buf
;
6035 reader
->input_data
= data
;
6036 reader
->input_size
= size
;
6038 reader
->read_size
= reader
->input_size
;
6039 reader
->read_pos
= 0;
6040 reader
->read_bufptr
= reader
->input_data
;
6042 reader
->text_conv_offset
= 0;
6045 /**************************************************************************
6046 * WsSetInput [webservices.@]
6048 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
6049 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
6050 ULONG count
, WS_ERROR
*error
)
6052 struct reader
*reader
= (struct reader
*)handle
;
6054 ULONG i
, offset
= 0;
6057 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
6058 if (error
) FIXME( "ignoring error parameter\n" );
6060 if (!reader
) return E_INVALIDARG
;
6062 EnterCriticalSection( &reader
->cs
);
6064 if (reader
->magic
!= READER_MAGIC
)
6066 LeaveCriticalSection( &reader
->cs
);
6067 return E_INVALIDARG
;
6070 for (i
= 0; i
< count
; i
++)
6072 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
6073 properties
[i
].valueSize
);
6074 if (hr
!= S_OK
) goto done
;
6077 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
6079 switch (encoding
->encodingType
)
6081 case WS_XML_READER_ENCODING_TYPE_TEXT
:
6083 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
6084 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
6086 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
6088 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
6093 if (text
->charSet
!= WS_CHARSET_AUTO
) reader
->input_charset
= text
->charSet
;
6094 else reader
->input_charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
6096 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
6099 case WS_XML_READER_ENCODING_TYPE_BINARY
:
6101 WS_XML_READER_BINARY_ENCODING
*bin
= (WS_XML_READER_BINARY_ENCODING
*)encoding
;
6102 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_BINARY
;
6103 reader
->input_charset
= 0;
6104 reader
->dict_static
= bin
->staticDictionary
? bin
->staticDictionary
: &dict_builtin_static
.dict
;
6105 reader
->dict
= bin
->dynamicDictionary
? bin
->dynamicDictionary
: &dict_builtin
.dict
;
6109 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
6114 switch (input
->inputType
)
6116 case WS_XML_READER_INPUT_TYPE_BUFFER
:
6118 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
6119 set_input_buffer( reader
, NULL
, (const unsigned char *)buf
->encodedData
+ offset
,
6120 buf
->encodedDataSize
- offset
);
6124 FIXME( "input type %u not supported\n", input
->inputType
);
6129 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
6130 else read_insert_bof( reader
, node
);
6133 LeaveCriticalSection( &reader
->cs
);
6137 /**************************************************************************
6138 * WsSetInputToBuffer [webservices.@]
6140 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
6141 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
6144 struct reader
*reader
= (struct reader
*)handle
;
6145 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
6150 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
6151 if (error
) FIXME( "ignoring error parameter\n" );
6153 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
6155 EnterCriticalSection( &reader
->cs
);
6157 if (reader
->magic
!= READER_MAGIC
)
6159 LeaveCriticalSection( &reader
->cs
);
6160 return E_INVALIDARG
;
6163 for (i
= 0; i
< count
; i
++)
6165 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
6166 properties
[i
].valueSize
);
6167 if (hr
!= S_OK
) goto done
;
6170 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
6172 reader
->input_enc
= xmlbuf
->encoding
;
6173 reader
->input_charset
= xmlbuf
->charset
;
6174 set_input_buffer( reader
, xmlbuf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
6176 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
6177 else read_insert_bof( reader
, node
);
6180 LeaveCriticalSection( &reader
->cs
);
6184 /**************************************************************************
6185 * WsGetReaderPosition [webservices.@]
6187 HRESULT WINAPI
WsGetReaderPosition( WS_XML_READER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
6189 struct reader
*reader
= (struct reader
*)handle
;
6191 TRACE( "%p %p %p\n", handle
, pos
, error
);
6192 if (error
) FIXME( "ignoring error parameter\n" );
6194 if (!reader
|| !pos
) return E_INVALIDARG
;
6196 EnterCriticalSection( &reader
->cs
);
6198 if (reader
->magic
!= READER_MAGIC
)
6200 LeaveCriticalSection( &reader
->cs
);
6201 return E_INVALIDARG
;
6204 if (!reader
->input_buf
)
6206 LeaveCriticalSection( &reader
->cs
);
6207 return WS_E_INVALID_OPERATION
;
6210 pos
->buffer
= (WS_XML_BUFFER
*)reader
->input_buf
;
6211 pos
->node
= reader
->current
;
6213 LeaveCriticalSection( &reader
->cs
);
6217 /**************************************************************************
6218 * WsSetReaderPosition [webservices.@]
6220 HRESULT WINAPI
WsSetReaderPosition( WS_XML_READER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
6222 struct reader
*reader
= (struct reader
*)handle
;
6224 TRACE( "%p %p %p\n", handle
, pos
, error
);
6225 if (error
) FIXME( "ignoring error parameter\n" );
6227 if (!reader
|| !pos
) return E_INVALIDARG
;
6229 EnterCriticalSection( &reader
->cs
);
6231 if (reader
->magic
!= READER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= reader
->input_buf
)
6233 LeaveCriticalSection( &reader
->cs
);
6234 return E_INVALIDARG
;
6237 if (!reader
->input_buf
)
6239 LeaveCriticalSection( &reader
->cs
);
6240 return WS_E_INVALID_OPERATION
;
6243 reader
->current
= pos
->node
;
6245 LeaveCriticalSection( &reader
->cs
);
6249 static HRESULT
utf8_to_base64( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_BASE64_TEXT
*base64
)
6251 if (utf8
->value
.length
% 4) return WS_E_INVALID_FORMAT
;
6252 if (!(base64
->bytes
= heap_alloc( utf8
->value
.length
* 3 / 4 ))) return E_OUTOFMEMORY
;
6253 base64
->length
= decode_base64( utf8
->value
.bytes
, utf8
->value
.length
, base64
->bytes
);
6257 /**************************************************************************
6258 * WsReadBytes [webservices.@]
6260 HRESULT WINAPI
WsReadBytes( WS_XML_READER
*handle
, void *bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
6262 struct reader
*reader
= (struct reader
*)handle
;
6265 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
6266 if (error
) FIXME( "ignoring error parameter\n" );
6268 if (!reader
) return E_INVALIDARG
;
6270 EnterCriticalSection( &reader
->cs
);
6272 if (reader
->magic
!= READER_MAGIC
)
6274 LeaveCriticalSection( &reader
->cs
);
6275 return E_INVALIDARG
;
6278 if (!reader
->input_type
)
6280 LeaveCriticalSection( &reader
->cs
);
6281 return WS_E_INVALID_OPERATION
;
6286 LeaveCriticalSection( &reader
->cs
);
6287 return E_INVALIDARG
;
6291 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
6293 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
6294 WS_XML_BASE64_TEXT base64
;
6296 if ((hr
= utf8_to_base64( (const WS_XML_UTF8_TEXT
*)text
->text
, &base64
)) != S_OK
)
6298 LeaveCriticalSection( &reader
->cs
);
6301 if (reader
->text_conv_offset
== base64
.length
)
6303 heap_free( base64
.bytes
);
6304 hr
= read_node( reader
);
6305 LeaveCriticalSection( &reader
->cs
);
6308 *count
= min( base64
.length
- reader
->text_conv_offset
, max_count
);
6309 memcpy( bytes
, base64
.bytes
+ reader
->text_conv_offset
, *count
);
6310 reader
->text_conv_offset
+= *count
;
6311 heap_free( base64
.bytes
);
6314 LeaveCriticalSection( &reader
->cs
);
6318 static HRESULT
utf8_to_utf16( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_UTF16_TEXT
*utf16
)
6320 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
6321 if (!(utf16
->bytes
= heap_alloc( len
* sizeof(WCHAR
) ))) return E_OUTOFMEMORY
;
6322 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, (WCHAR
*)utf16
->bytes
, len
);
6323 utf16
->byteCount
= len
* sizeof(WCHAR
);
6327 /**************************************************************************
6328 * WsReadChars [webservices.@]
6330 HRESULT WINAPI
WsReadChars( WS_XML_READER
*handle
, WCHAR
*chars
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
6332 struct reader
*reader
= (struct reader
*)handle
;
6334 TRACE( "%p %p %u %p %p\n", handle
, chars
, max_count
, count
, error
);
6335 if (error
) FIXME( "ignoring error parameter\n" );
6337 if (!reader
) return E_INVALIDARG
;
6339 EnterCriticalSection( &reader
->cs
);
6341 if (reader
->magic
!= READER_MAGIC
)
6343 LeaveCriticalSection( &reader
->cs
);
6344 return E_INVALIDARG
;
6347 if (!reader
->input_type
)
6349 LeaveCriticalSection( &reader
->cs
);
6350 return WS_E_INVALID_OPERATION
;
6355 LeaveCriticalSection( &reader
->cs
);
6356 return E_INVALIDARG
;
6360 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& chars
)
6362 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
6363 WS_XML_UTF16_TEXT utf16
;
6366 if ((hr
= utf8_to_utf16( (const WS_XML_UTF8_TEXT
*)text
->text
, &utf16
)) != S_OK
)
6368 LeaveCriticalSection( &reader
->cs
);
6371 if (reader
->text_conv_offset
== utf16
.byteCount
/ sizeof(WCHAR
))
6373 heap_free( utf16
.bytes
);
6374 hr
= read_node( reader
);
6375 LeaveCriticalSection( &reader
->cs
);
6378 *count
= min( utf16
.byteCount
/ sizeof(WCHAR
) - reader
->text_conv_offset
, max_count
);
6379 memcpy( chars
, utf16
.bytes
+ reader
->text_conv_offset
* sizeof(WCHAR
), *count
* sizeof(WCHAR
) );
6380 reader
->text_conv_offset
+= *count
;
6381 heap_free( utf16
.bytes
);
6384 LeaveCriticalSection( &reader
->cs
);
6388 /**************************************************************************
6389 * WsReadCharsUtf8 [webservices.@]
6391 HRESULT WINAPI
WsReadCharsUtf8( WS_XML_READER
*handle
, BYTE
*bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
6393 struct reader
*reader
= (struct reader
*)handle
;
6396 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
6397 if (error
) FIXME( "ignoring error parameter\n" );
6399 if (!reader
) return E_INVALIDARG
;
6401 EnterCriticalSection( &reader
->cs
);
6403 if (reader
->magic
!= READER_MAGIC
)
6405 LeaveCriticalSection( &reader
->cs
);
6406 return E_INVALIDARG
;
6409 if (!reader
->input_type
)
6411 LeaveCriticalSection( &reader
->cs
);
6412 return WS_E_INVALID_OPERATION
;
6417 LeaveCriticalSection( &reader
->cs
);
6418 return E_INVALIDARG
;
6422 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
6424 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
6425 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
6427 if (reader
->text_conv_offset
== utf8
->value
.length
)
6429 hr
= read_node( reader
);
6430 LeaveCriticalSection( &reader
->cs
);
6433 *count
= min( utf8
->value
.length
- reader
->text_conv_offset
, max_count
);
6434 memcpy( bytes
, utf8
->value
.bytes
+ reader
->text_conv_offset
, *count
);
6435 reader
->text_conv_offset
+= *count
;
6438 LeaveCriticalSection( &reader
->cs
);
6442 static HRESULT
move_to_element( struct reader
*reader
)
6445 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_BOF
&&
6446 (hr
= read_move_to( reader
, WS_MOVE_TO_CHILD_NODE
, NULL
)) != S_OK
) return hr
;
6447 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return E_FAIL
;
6451 static HRESULT
copy_tree( struct reader
*reader
, WS_XML_WRITER
*writer
)
6453 const struct node
*node
, *parent
;
6457 if ((hr
= move_to_element( reader
)) != S_OK
) return hr
;
6458 parent
= reader
->current
;
6461 node
= reader
->current
;
6462 if ((hr
= WsWriteNode( writer
, (const WS_XML_NODE
*)node
, NULL
)) != S_OK
) break;
6463 if (node_type( node
) == WS_XML_NODE_TYPE_END_ELEMENT
&& node
->parent
== parent
) done
= TRUE
;
6464 if ((hr
= read_next_node( reader
)) != S_OK
|| done
) break;
6469 /**************************************************************************
6470 * WsReadXmlBuffer [webservices.@]
6472 HRESULT WINAPI
WsReadXmlBuffer( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_BUFFER
**ret
, WS_ERROR
*error
)
6474 struct reader
*reader
= (struct reader
*)handle
;
6475 WS_XML_WRITER
*writer
= NULL
;
6476 WS_XML_BUFFER
*buffer
;
6479 TRACE( "%p %p %p %p\n", handle
, heap
, ret
, error
);
6480 if (error
) FIXME( "ignoring error parameter\n" );
6482 if (!reader
|| !heap
) return E_INVALIDARG
;
6483 if (!ret
) return E_FAIL
;
6485 EnterCriticalSection( &reader
->cs
);
6487 if (reader
->magic
!= READER_MAGIC
)
6489 LeaveCriticalSection( &reader
->cs
);
6490 return E_INVALIDARG
;
6493 if (!reader
->input_type
)
6495 LeaveCriticalSection( &reader
->cs
);
6496 return WS_E_INVALID_OPERATION
;
6499 if ((hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
)) != S_OK
) goto done
;
6500 if ((hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
)) != S_OK
) goto done
;
6501 if ((hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
)) != S_OK
) goto done
;
6502 if ((hr
= copy_tree( reader
, writer
)) == S_OK
) *ret
= buffer
;
6505 if (hr
!= S_OK
) free_xmlbuf( (struct xmlbuf
*)buffer
);
6506 WsFreeWriter( writer
);
6507 LeaveCriticalSection( &reader
->cs
);
6511 HRESULT
get_param_desc( const WS_STRUCT_DESCRIPTION
*desc
, USHORT index
, const WS_FIELD_DESCRIPTION
**ret
)
6513 if (index
>= desc
->fieldCount
) return E_INVALIDARG
;
6514 *ret
= desc
->fields
[index
];
6518 static ULONG
get_field_size( const WS_FIELD_DESCRIPTION
*desc
)
6520 WS_READ_OPTION option
;
6523 switch ((option
= get_field_read_option( desc
->type
, desc
->options
)))
6525 case WS_READ_REQUIRED_POINTER
:
6526 case WS_READ_OPTIONAL_POINTER
:
6527 case WS_READ_NILLABLE_POINTER
:
6528 size
= sizeof(void *);
6531 case WS_READ_REQUIRED_VALUE
:
6532 case WS_READ_NILLABLE_VALUE
:
6533 size
= get_type_size( desc
->type
, desc
->typeDescription
);
6537 WARN( "unhandled option %u\n", option
);
6544 static HRESULT
read_param( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
, void *ret
)
6546 if (!ret
&& !(ret
= ws_alloc_zero( heap
, get_field_size(desc
) ))) return WS_E_QUOTA_EXCEEDED
;
6547 return read_type_field( reader
, desc
, heap
, ret
, 0 );
6550 static HRESULT
read_param_array( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
,
6551 void **ret
, ULONG
*count
)
6553 if (!ret
&& !(ret
= ws_alloc_zero( heap
, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED
;
6554 return read_type_repeating_element( reader
, desc
, heap
, ret
, count
);
6557 static void set_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, ULONG len
,
6561 for (i
= 0; i
< count
; i
++)
6563 if (params
[i
].outputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
6565 if ((ptr
= *(ULONG
**)args
[i
])) *ptr
= len
;
6570 HRESULT
read_output_params( WS_XML_READER
*handle
, WS_HEAP
*heap
, const WS_ELEMENT_DESCRIPTION
*desc
,
6571 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
6573 struct reader
*reader
= (struct reader
*)handle
;
6574 const WS_STRUCT_DESCRIPTION
*desc_struct
;
6575 const WS_FIELD_DESCRIPTION
*desc_field
;
6579 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
6581 EnterCriticalSection( &reader
->cs
);
6583 if (reader
->magic
!= READER_MAGIC
)
6585 LeaveCriticalSection( &reader
->cs
);
6586 return E_INVALIDARG
;
6589 if ((hr
= start_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
)
6592 for (i
= 0; i
< count
; i
++)
6594 if (params
[i
].outputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
6595 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
6597 FIXME( "messages type not supported\n" );
6601 if ((hr
= get_param_desc( desc_struct
, params
[i
].outputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
6602 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
6604 void *ptr
= *(void **)args
[i
];
6605 if ((hr
= read_param( reader
, desc_field
, heap
, ptr
)) != S_OK
) goto done
;
6607 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
6609 void **ptr
= *(void ***)args
[i
];
6610 if ((hr
= read_param_array( reader
, desc_field
, heap
, ptr
, &len
)) != S_OK
) goto done
;
6611 set_array_len( params
, count
, params
[i
].outputMessageIndex
, len
, args
);
6615 if (desc_struct
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
6617 struct node
*parent
= find_parent( reader
);
6618 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
6621 hr
= end_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
);
6624 LeaveCriticalSection( &reader
->cs
);