webservices: Fix is_nil_element in binary mode.
[wine.git] / dlls / webservices / reader.c
blob3e5434cf642b0d5bb28f46ba5695c4a564e9e76a
1 /*
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
19 #include <stdarg.h>
20 #include <assert.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winnls.h"
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;
37 return ret;
40 void prop_init( const struct prop_desc *desc, ULONG count, struct prop *prop, void *data )
42 ULONG i;
43 char *ptr = data;
44 for (i = 0; i < count; i++)
46 prop[i].value = ptr;
47 prop[i].size = desc[i].size;
48 prop[i].readonly = desc[i].readonly;
49 prop[i].writeonly = desc[i].writeonly;
50 ptr += prop[i].size;
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 );
58 return S_OK;
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 );
65 return S_OK;
68 struct node *alloc_node( WS_XML_NODE_TYPE type )
70 struct node *ret;
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 );
76 return ret;
79 void free_attribute( WS_XML_ATTRIBUTE *attr )
81 if (!attr) return;
82 free_xml_string( attr->prefix );
83 free_xml_string( attr->localName );
84 free_xml_string( attr->ns );
85 heap_free( attr->value );
86 heap_free( attr );
89 void free_node( struct node *node )
91 if (!node) return;
92 switch (node_type( node ))
94 case WS_XML_NODE_TYPE_ELEMENT:
96 WS_XML_ELEMENT_NODE *elem = &node->hdr;
97 ULONG i;
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 );
104 break;
106 case WS_XML_NODE_TYPE_TEXT:
108 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
109 heap_free( text->text );
110 break;
112 case WS_XML_NODE_TYPE_COMMENT:
114 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
115 heap_free( comment->value.bytes );
116 break;
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:
123 break;
125 default:
126 ERR( "unhandled type %u\n", node_type( node ) );
127 break;
129 heap_free( node );
132 void destroy_nodes( struct node *node )
134 struct list *ptr;
136 if (!node) return;
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 );
143 free_node( node );
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, FALSE ))) goto error;
160 if (!(dst->localName = dup_xml_string( localname, FALSE ))) goto error;
161 if (!(dst->ns = dup_xml_string( ns, FALSE ))) goto error;
163 if (text)
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;
171 return dst;
173 error:
174 free_attribute( dst );
175 return NULL;
178 static WS_XML_ATTRIBUTE **dup_attributes( WS_XML_ATTRIBUTE * const *src, ULONG count )
180 WS_XML_ATTRIBUTE **dst;
181 ULONG i;
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] );
189 heap_free( dst );
190 return NULL;
193 return dst;
196 static struct node *dup_element_node( const WS_XML_ELEMENT_NODE *src )
198 struct node *node;
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;
207 dst = &node->hdr;
209 if (count && !(dst->attributes = dup_attributes( attrs, count ))) goto error;
210 dst->attributeCount = count;
212 if (prefix && !(dst->prefix = dup_xml_string( prefix, FALSE ))) goto error;
213 if (localname && !(dst->localName = dup_xml_string( localname, FALSE ))) goto error;
214 if (ns && !(dst->ns = dup_xml_string( ns, FALSE ))) goto error;
215 return node;
217 error:
218 free_node( node );
219 return NULL;
222 static struct node *dup_text_node( const WS_XML_TEXT_NODE *src )
224 struct node *node;
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;
230 if (src->text)
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 )))
236 free_node( node );
237 return NULL;
239 dst->text = &utf8->text;
241 return node;
244 static struct node *dup_comment_node( const WS_XML_COMMENT_NODE *src )
246 struct node *node;
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 )))
254 free_node( node );
255 return NULL;
257 memcpy( dst->value.bytes, src->value.bytes, src->value.length );
258 dst->value.length = src->value.length;
259 return node;
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 ) );
282 default:
283 ERR( "unhandled type %u\n", node_type( src ) );
284 break;
286 return NULL;
289 static HRESULT dup_tree( struct node **dst, const struct node *src )
291 struct node *parent;
292 const struct node *child;
294 if (!*dst && !(*dst = dup_node( src ))) return E_OUTOFMEMORY;
295 parent = *dst;
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 );
305 return hr;
307 new_child->parent = parent;
308 list_add_tail( &parent->children, &new_child->entry );
310 return S_OK;
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 */
332 enum reader_state
334 READER_STATE_INITIAL,
335 READER_STATE_BOF,
336 READER_STATE_STARTELEMENT,
337 READER_STATE_STARTATTRIBUTE,
338 READER_STATE_STARTCDATA,
339 READER_STATE_CDATA,
340 READER_STATE_TEXT,
341 READER_STATE_ENDELEMENT,
342 READER_STATE_ENDCDATA,
343 READER_STATE_COMMENT,
344 READER_STATE_EOF
347 struct prefix
349 WS_XML_STRING *str;
350 WS_XML_STRING *ns;
353 struct reader
355 ULONG magic;
356 CRITICAL_SECTION cs;
357 ULONG read_size;
358 ULONG read_pos;
359 const unsigned char *read_bufptr;
360 enum reader_state state;
361 struct node *root;
362 struct node *current;
363 ULONG current_attr;
364 struct node *last;
365 struct prefix *prefixes;
366 ULONG nb_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;
373 ULONG input_size;
374 ULONG text_conv_offset;
375 const WS_XML_DICTIONARY *dict_static;
376 WS_XML_DICTIONARY *dict;
377 ULONG prop_count;
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]);
386 struct reader *ret;
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) )))
392 heap_free( ret );
393 return NULL;
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;
403 return ret;
406 static void clear_prefixes( struct prefix *prefixes, ULONG count )
408 ULONG i;
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 )
420 if (str)
422 free_xml_string( prefix->str );
423 if (!(prefix->str = dup_xml_string( str, FALSE ))) return E_OUTOFMEMORY;
425 if (prefix->ns) free_xml_string( prefix->ns );
426 if (!(prefix->ns = dup_xml_string( ns, FALSE ))) return E_OUTOFMEMORY;
427 return S_OK;
430 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
432 ULONG i;
433 HRESULT hr;
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++;
450 return S_OK;
453 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
455 ULONG i;
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;
461 return NULL;
464 static void read_insert_eof( struct reader *reader, struct node *eof )
466 if (!reader->root) reader->root = eof;
467 else
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 );
496 heap_free( reader );
499 static HRESULT init_reader( struct reader *reader )
501 static const WS_XML_STRING empty = {0, NULL};
502 struct node *node;
503 HRESULT hr;
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;
518 reader->dict = NULL;
519 return S_OK;
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;
531 HRESULT hr;
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 );
548 if (hr != S_OK)
550 free_reader( reader );
551 return hr;
555 if ((hr = init_reader( reader )) != S_OK)
557 free_reader( reader );
558 return hr;
561 TRACE( "created %p\n", reader );
562 *handle = (WS_XML_READER *)reader;
563 return S_OK;
566 /**************************************************************************
567 * WsFreeReader [webservices.@]
569 void WINAPI WsFreeReader( WS_XML_READER *handle )
571 struct reader *reader = (struct reader *)handle;
573 TRACE( "%p\n", handle );
575 if (!reader) return;
577 EnterCriticalSection( &reader->cs );
579 if (reader->magic != READER_MAGIC)
581 LeaveCriticalSection( &reader->cs );
582 return;
585 reader->magic = 0;
587 LeaveCriticalSection( &reader->cs );
588 free_reader( reader );
591 /**************************************************************************
592 * WsFillReader [webservices.@]
594 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
595 WS_ERROR *error )
597 struct reader *reader = (struct reader *)handle;
599 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
600 if (error) FIXME( "ignoring error parameter\n" );
602 if (!reader) return E_INVALIDARG;
604 EnterCriticalSection( &reader->cs );
606 if (reader->magic != READER_MAGIC)
608 LeaveCriticalSection( &reader->cs );
609 return E_INVALIDARG;
612 /* FIXME: add support for stream input */
613 reader->read_size = min( min_size, reader->input_size );
614 reader->read_pos = 0;
616 LeaveCriticalSection( &reader->cs );
617 return S_OK;
620 /**************************************************************************
621 * WsGetNamespaceFromPrefix [webservices.@]
623 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
624 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
626 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
627 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
628 static const WS_XML_STRING empty_ns = {0, NULL};
629 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
630 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
631 struct reader *reader = (struct reader *)handle;
632 BOOL found = FALSE;
634 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
635 if (error) FIXME( "ignoring error parameter\n" );
637 if (!reader || !prefix || !ns) return E_INVALIDARG;
639 EnterCriticalSection( &reader->cs );
641 if (reader->magic != READER_MAGIC)
643 LeaveCriticalSection( &reader->cs );
644 return E_INVALIDARG;
647 if (reader->state != READER_STATE_STARTELEMENT)
649 LeaveCriticalSection( &reader->cs );
650 return WS_E_INVALID_OPERATION;
653 if (!prefix->length)
655 *ns = &empty_ns;
656 found = TRUE;
658 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
660 *ns = &xml_ns;
661 found = TRUE;
663 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
665 *ns = &xmlns_ns;
666 found = TRUE;
668 else
670 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
671 ULONG i;
673 for (i = 0; i < elem->attributeCount; i++)
675 if (!elem->attributes[i]->isXmlNs) continue;
676 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
678 *ns = elem->attributes[i]->ns;
679 found = TRUE;
680 break;
685 LeaveCriticalSection( &reader->cs );
687 if (!found)
689 if (required) return WS_E_INVALID_FORMAT;
690 *ns = NULL;
691 return S_FALSE;
694 return S_OK;
697 /**************************************************************************
698 * WsGetReaderNode [webservices.@]
700 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
701 WS_ERROR *error )
703 struct reader *reader = (struct reader *)handle;
705 TRACE( "%p %p %p\n", handle, node, error );
706 if (error) FIXME( "ignoring error parameter\n" );
708 if (!reader || !node) return E_INVALIDARG;
710 EnterCriticalSection( &reader->cs );
712 if (reader->magic != READER_MAGIC)
714 LeaveCriticalSection( &reader->cs );
715 return E_INVALIDARG;
718 *node = &reader->current->hdr.node;
720 LeaveCriticalSection( &reader->cs );
721 return S_OK;
724 static HRESULT get_charset( struct reader *reader, void *buf, ULONG size )
726 if (!buf || size != sizeof(reader->input_charset)) return E_INVALIDARG;
727 if (!reader->input_charset) return WS_E_INVALID_FORMAT;
728 *(WS_CHARSET *)buf = reader->input_charset;
729 return S_OK;
732 /**************************************************************************
733 * WsGetReaderProperty [webservices.@]
735 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
736 void *buf, ULONG size, WS_ERROR *error )
738 struct reader *reader = (struct reader *)handle;
739 HRESULT hr;
741 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
742 if (error) FIXME( "ignoring error parameter\n" );
744 if (!reader) return E_INVALIDARG;
746 EnterCriticalSection( &reader->cs );
748 if (reader->magic != READER_MAGIC)
750 LeaveCriticalSection( &reader->cs );
751 return E_INVALIDARG;
754 if (!reader->input_type)
756 LeaveCriticalSection( &reader->cs );
757 return WS_E_INVALID_OPERATION;
760 if (id == WS_XML_READER_PROPERTY_CHARSET) hr = get_charset( reader, buf, size );
761 else hr = prop_get( reader->prop, reader->prop_count, id, buf, size );
763 LeaveCriticalSection( &reader->cs );
764 return hr;
767 /**************************************************************************
768 * WsGetXmlAttribute [webservices.@]
770 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
771 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
773 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
774 return E_NOTIMPL;
777 WS_XML_UTF8_TEXT *alloc_utf8_text( const BYTE *data, ULONG len )
779 WS_XML_UTF8_TEXT *ret;
781 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
782 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
783 ret->value.length = len;
784 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
785 ret->value.dictionary = NULL;
786 ret->value.id = 0;
787 if (data) memcpy( ret->value.bytes, data, len );
788 return ret;
791 WS_XML_UTF16_TEXT *alloc_utf16_text( const BYTE *data, ULONG len )
793 WS_XML_UTF16_TEXT *ret;
795 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
796 ret->text.textType = WS_XML_TEXT_TYPE_UTF16;
797 ret->byteCount = len;
798 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
799 if (data) memcpy( ret->bytes, data, len );
800 return ret;
803 WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *data, ULONG len )
805 WS_XML_BASE64_TEXT *ret;
807 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
808 ret->text.textType = WS_XML_TEXT_TYPE_BASE64;
809 ret->length = len;
810 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
811 if (data) memcpy( ret->bytes, data, len );
812 return ret;
815 WS_XML_BOOL_TEXT *alloc_bool_text( BOOL value )
817 WS_XML_BOOL_TEXT *ret;
819 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
820 ret->text.textType = WS_XML_TEXT_TYPE_BOOL;
821 ret->value = value;
822 return ret;
825 WS_XML_INT32_TEXT *alloc_int32_text( INT32 value )
827 WS_XML_INT32_TEXT *ret;
829 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
830 ret->text.textType = WS_XML_TEXT_TYPE_INT32;
831 ret->value = value;
832 return ret;
835 WS_XML_INT64_TEXT *alloc_int64_text( INT64 value )
837 WS_XML_INT64_TEXT *ret;
839 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
840 ret->text.textType = WS_XML_TEXT_TYPE_INT64;
841 ret->value = value;
842 return ret;
845 WS_XML_UINT64_TEXT *alloc_uint64_text( UINT64 value )
847 WS_XML_UINT64_TEXT *ret;
849 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
850 ret->text.textType = WS_XML_TEXT_TYPE_UINT64;
851 ret->value = value;
852 return ret;
855 WS_XML_FLOAT_TEXT *alloc_float_text( float value )
857 WS_XML_FLOAT_TEXT *ret;
859 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
860 ret->text.textType = WS_XML_TEXT_TYPE_FLOAT;
861 ret->value = value;
862 return ret;
865 WS_XML_DOUBLE_TEXT *alloc_double_text( double value )
867 WS_XML_DOUBLE_TEXT *ret;
869 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
870 ret->text.textType = WS_XML_TEXT_TYPE_DOUBLE;
871 ret->value = value;
872 return ret;
875 WS_XML_GUID_TEXT *alloc_guid_text( const GUID *value )
877 WS_XML_GUID_TEXT *ret;
879 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
880 ret->text.textType = WS_XML_TEXT_TYPE_GUID;
881 ret->value = *value;
882 return ret;
885 WS_XML_UNIQUE_ID_TEXT *alloc_unique_id_text( const GUID *value )
887 WS_XML_UNIQUE_ID_TEXT *ret;
889 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
890 ret->text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID;
891 ret->value = *value;
892 return ret;
895 WS_XML_DATETIME_TEXT *alloc_datetime_text( const WS_DATETIME *value )
897 WS_XML_DATETIME_TEXT *ret;
899 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
900 ret->text.textType = WS_XML_TEXT_TYPE_DATETIME;
901 ret->value = *value;
902 return ret;
905 static inline BOOL read_end_of_data( struct reader *reader )
907 return reader->read_pos >= reader->read_size;
910 static inline const unsigned char *read_current_ptr( struct reader *reader )
912 return &reader->read_bufptr[reader->read_pos];
915 static inline HRESULT read_peek( struct reader *reader, unsigned char *byte )
917 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
918 *byte = reader->read_bufptr[reader->read_pos];
919 return S_OK;
922 static inline HRESULT read_byte( struct reader *reader, unsigned char *byte )
924 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
925 *byte = reader->read_bufptr[reader->read_pos++];
926 return S_OK;
929 static inline HRESULT read_bytes( struct reader *reader, unsigned char *bytes, unsigned int len )
931 if (reader->read_pos + len > reader->read_size) return WS_E_INVALID_FORMAT;
932 memcpy( bytes, reader->read_bufptr + reader->read_pos, len );
933 reader->read_pos += len;
934 return S_OK;
937 /* UTF-8 support based on libs/wine/utf8.c */
939 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
940 static const char utf8_length[128] =
942 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
943 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
944 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
945 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
946 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
947 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
948 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
949 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
952 /* first byte mask depending on UTF-8 sequence length */
953 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
955 /* minimum Unicode value depending on UTF-8 sequence length */
956 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
958 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
960 unsigned int len, res;
961 unsigned char ch = reader->read_bufptr[reader->read_pos];
962 const unsigned char *end;
964 if (reader->read_pos >= reader->read_size) return 0;
966 if (ch < 0x80)
968 *skip = 1;
969 return ch;
971 len = utf8_length[ch - 0x80];
972 if (reader->read_pos + len >= reader->read_size) return 0;
973 end = reader->read_bufptr + reader->read_pos + len + 1;
974 res = ch & utf8_mask[len];
976 switch (len)
978 case 3:
979 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
980 res = (res << 6) | ch;
981 case 2:
982 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
983 res = (res << 6) | ch;
984 case 1:
985 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
986 res = (res << 6) | ch;
987 if (res < utf8_minval[len]) break;
988 *skip = len + 1;
989 return res;
992 return 0;
995 static inline void read_skip( struct reader *reader, unsigned int count )
997 if (reader->read_pos + count > reader->read_size) return;
998 reader->read_pos += count;
1001 static inline void read_rewind( struct reader *reader, unsigned int count )
1003 reader->read_pos -= count;
1006 static inline BOOL read_isnamechar( unsigned int ch )
1008 /* FIXME: incomplete */
1009 return (ch >= 'A' && ch <= 'Z') ||
1010 (ch >= 'a' && ch <= 'z') ||
1011 (ch >= '0' && ch <= '9') ||
1012 ch == '_' || ch == '-' || ch == '.' || ch == ':';
1015 static inline BOOL read_isspace( unsigned int ch )
1017 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
1020 static inline void read_skip_whitespace( struct reader *reader )
1022 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
1023 reader->read_pos++;
1026 static inline int read_cmp( struct reader *reader, const char *str, int len )
1028 const unsigned char *ptr = read_current_ptr( reader );
1030 if (len < 0) len = strlen( str );
1031 if (reader->read_pos + len > reader->read_size) return -1;
1032 while (len--)
1034 if (*str != *ptr) return *ptr - *str;
1035 str++; ptr++;
1037 return 0;
1040 static HRESULT read_xmldecl( struct reader *reader )
1042 if (!reader->read_size) return WS_E_INVALID_FORMAT;
1044 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
1046 reader->state = READER_STATE_BOF;
1047 return S_OK;
1049 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
1050 read_skip( reader, 6 );
1052 /* FIXME: parse attributes */
1053 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
1054 reader->read_pos++;
1056 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
1057 read_skip( reader, 2 );
1059 reader->state = READER_STATE_BOF;
1060 return S_OK;
1063 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
1065 if (elem->attributeCount)
1067 WS_XML_ATTRIBUTE **tmp;
1068 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
1069 return E_OUTOFMEMORY;
1070 elem->attributes = tmp;
1072 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
1073 elem->attributes[elem->attributeCount++] = attr;
1074 return S_OK;
1077 static inline void init_xml_string( BYTE *bytes, ULONG len, WS_XML_STRING *str )
1079 str->length = len;
1080 str->bytes = bytes;
1081 str->dictionary = NULL;
1082 str->id = 0;
1085 static HRESULT split_qname( const BYTE *str, ULONG len, WS_XML_STRING *prefix, WS_XML_STRING *localname )
1087 BYTE *prefix_bytes = NULL, *localname_bytes = (BYTE *)str, *ptr = (BYTE *)str;
1088 ULONG prefix_len = 0, localname_len = len;
1090 while (len--)
1092 if (*ptr == ':')
1094 if (ptr == str) return WS_E_INVALID_FORMAT;
1095 prefix_bytes = (BYTE *)str;
1096 prefix_len = ptr - str;
1097 localname_bytes = ptr + 1;
1098 localname_len = len;
1099 break;
1101 ptr++;
1103 if (!localname_len) return WS_E_INVALID_FORMAT;
1105 init_xml_string( prefix_bytes, prefix_len, prefix );
1106 init_xml_string( localname_bytes, localname_len, localname );
1107 return S_OK;
1110 static HRESULT parse_qname( const BYTE *str, ULONG len, WS_XML_STRING **prefix_ret, WS_XML_STRING **localname_ret )
1112 WS_XML_STRING prefix, localname;
1113 HRESULT hr;
1115 if ((hr = split_qname( str, len, &prefix, &localname )) != S_OK) return hr;
1116 if (!(*prefix_ret = alloc_xml_string( NULL, prefix.length ))) return E_OUTOFMEMORY;
1117 if (!(*localname_ret = dup_xml_string( &localname, FALSE )))
1119 free_xml_string( *prefix_ret );
1120 return E_OUTOFMEMORY;
1122 memcpy( (*prefix_ret)->bytes, prefix.bytes, prefix.length );
1123 if (prefix.length && add_xml_string( *prefix_ret ) != S_OK) WARN( "prefix not added to dictionary\n" );
1124 return S_OK;
1127 static int codepoint_to_utf8( int cp, unsigned char *dst )
1129 if (!cp) return -1;
1130 if (cp < 0x80)
1132 *dst = cp;
1133 return 1;
1135 if (cp < 0x800)
1137 dst[1] = 0x80 | (cp & 0x3f);
1138 cp >>= 6;
1139 dst[0] = 0xc0 | cp;
1140 return 2;
1142 if ((cp >= 0xd800 && cp <= 0xdfff) || cp == 0xfffe || cp == 0xffff) return -1;
1143 if (cp < 0x10000)
1145 dst[2] = 0x80 | (cp & 0x3f);
1146 cp >>= 6;
1147 dst[1] = 0x80 | (cp & 0x3f);
1148 cp >>= 6;
1149 dst[0] = 0xe0 | cp;
1150 return 3;
1152 if (cp >= 0x110000) return -1;
1153 dst[3] = 0x80 | (cp & 0x3f);
1154 cp >>= 6;
1155 dst[2] = 0x80 | (cp & 0x3f);
1156 cp >>= 6;
1157 dst[1] = 0x80 | (cp & 0x3f);
1158 cp >>= 6;
1159 dst[0] = 0xf0 | cp;
1160 return 4;
1163 static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char *ret, ULONG *ret_len )
1165 const unsigned char *p = str;
1166 unsigned char *q = ret;
1168 *ret_len = 0;
1169 while (len)
1171 if (*p == '&')
1173 p++; len--;
1174 if (!len) return WS_E_INVALID_FORMAT;
1176 if (len >= 3 && !memcmp( p, "lt;", 3 ))
1178 *q++ = '<';
1179 p += 3;
1180 len -= 3;
1182 else if (len >= 3 && !memcmp( p, "gt;", 3 ))
1184 *q++ = '>';
1185 p += 3;
1186 len -= 3;
1188 else if (len >= 5 && !memcmp( p, "quot;", 5 ))
1190 *q++ = '"';
1191 p += 5;
1192 len -= 5;
1194 else if (len >= 4 && !memcmp( p, "amp;", 4 ))
1196 *q++ = '&';
1197 p += 4;
1198 len -= 4;
1200 else if (len >= 5 && !memcmp( p, "apos;", 5 ))
1202 *q++ = '\'';
1203 p += 5;
1204 len -= 5;
1206 else if (*p == '#')
1208 ULONG start, nb_digits, i;
1209 int len_utf8, cp = 0;
1211 p++; len--;
1212 if (!len) return WS_E_INVALID_FORMAT;
1213 if (*p == 'x')
1215 p++; len--;
1217 start = len;
1218 while (len && isxdigit( *p )) { p++; len--; };
1219 if (!len) return WS_E_INVALID_FORMAT;
1221 p -= nb_digits = start - len;
1222 if (!nb_digits || nb_digits > 6 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1223 for (i = 0; i < nb_digits; i++)
1225 cp *= 16;
1226 if (*p >= '0' && *p <= '9') cp += *p - '0';
1227 else if (*p >= 'a' && *p <= 'f') cp += *p - 'a' + 10;
1228 else cp += *p - 'A' + 10;
1229 p++;
1232 else if (isdigit( *p ))
1234 while (len && *p == '0') { p++; len--; };
1235 if (!len) return WS_E_INVALID_FORMAT;
1237 start = len;
1238 while (len && isdigit( *p )) { p++; len--; };
1239 if (!len) return WS_E_INVALID_FORMAT;
1241 p -= nb_digits = start - len;
1242 if (!nb_digits || nb_digits > 7 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1243 for (i = 0; i < nb_digits; i++)
1245 cp *= 10;
1246 cp += *p - '0';
1247 p++;
1250 else return WS_E_INVALID_FORMAT;
1251 p++; len--;
1252 if ((len_utf8 = codepoint_to_utf8( cp, q )) < 0) return WS_E_INVALID_FORMAT;
1253 *ret_len += len_utf8;
1254 q += len_utf8;
1255 continue;
1257 else return WS_E_INVALID_FORMAT;
1259 else
1261 *q++ = *p++;
1262 len--;
1264 *ret_len += 1;
1266 return S_OK;
1269 static HRESULT read_attribute_value_text( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1271 WS_XML_UTF8_TEXT *utf8 = NULL;
1272 unsigned int len, ch, skip, quote;
1273 const unsigned char *start;
1274 HRESULT hr = E_OUTOFMEMORY;
1276 read_skip_whitespace( reader );
1277 if (read_cmp( reader, "=", 1 )) return WS_E_INVALID_FORMAT;
1278 read_skip( reader, 1 );
1280 read_skip_whitespace( reader );
1281 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) return WS_E_INVALID_FORMAT;
1282 quote = read_utf8_char( reader, &skip );
1283 read_skip( reader, 1 );
1285 len = 0;
1286 start = read_current_ptr( reader );
1287 for (;;)
1289 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1290 if (ch == quote) break;
1291 read_skip( reader, skip );
1292 len += skip;
1294 read_skip( reader, 1 );
1296 if (attr->isXmlNs)
1298 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1299 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1300 if (!(utf8 = alloc_utf8_text( NULL, 0 )))
1302 hr = E_OUTOFMEMORY;
1303 goto error;
1306 else
1308 if (!(utf8 = alloc_utf8_text( NULL, len ))) goto error;
1309 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK) goto error;
1312 attr->value = &utf8->text;
1313 attr->singleQuote = (quote == '\'');
1314 return S_OK;
1316 error:
1317 heap_free( utf8 );
1318 return hr;
1321 static inline BOOL is_text_type( unsigned char type )
1323 return (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT);
1326 static HRESULT read_int31( struct reader *reader, ULONG *len )
1328 unsigned char byte;
1329 HRESULT hr;
1331 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1332 *len = byte & 0x7f;
1333 if (!(byte & 0x80)) return S_OK;
1335 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1336 *len += (byte & 0x7f) << 7;
1337 if (!(byte & 0x80)) return S_OK;
1339 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1340 *len += (byte & 0x7f) << 14;
1341 if (!(byte & 0x80)) return S_OK;
1343 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1344 *len += (byte & 0x7f) << 21;
1345 if (!(byte & 0x80)) return S_OK;
1347 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1348 *len += (byte & 0x07) << 28;
1349 return S_OK;
1352 static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
1354 ULONG len;
1355 HRESULT hr;
1356 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
1357 if (!(*str = alloc_xml_string( NULL, len ))) return E_OUTOFMEMORY;
1358 if ((hr = read_bytes( reader, (*str)->bytes, len )) == S_OK)
1360 if (add_xml_string( *str ) != S_OK) WARN( "string not added to dictionary\n" );
1361 return S_OK;
1363 free_xml_string( *str );
1364 return hr;
1367 static HRESULT read_dict_string( struct reader *reader, WS_XML_STRING **str )
1369 const WS_XML_DICTIONARY *dict;
1370 HRESULT hr;
1371 ULONG id;
1373 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1374 dict = (id & 1) ? reader->dict : reader->dict_static;
1375 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1376 if (!(*str = alloc_xml_string( NULL, 0 ))) return E_OUTOFMEMORY;
1377 *(*str) = dict->strings[id];
1378 return S_OK;
1381 static HRESULT read_datetime( struct reader *reader, WS_DATETIME *ret )
1383 UINT64 val;
1384 HRESULT hr;
1386 if ((hr = read_bytes( reader, (unsigned char *)&val, sizeof(val) )) != S_OK) return hr;
1388 if ((val & 0x03) == 1) ret->format = WS_DATETIME_FORMAT_UTC;
1389 else if ((val & 0x03) == 2) ret->format = WS_DATETIME_FORMAT_LOCAL;
1390 else ret->format = WS_DATETIME_FORMAT_NONE;
1392 if ((ret->ticks = val >> 2) > TICKS_MAX) return WS_E_INVALID_FORMAT;
1393 return S_OK;
1396 static HRESULT lookup_string( struct reader *reader, ULONG id, const WS_XML_STRING **ret )
1398 const WS_XML_DICTIONARY *dict = (id & 1) ? reader->dict : reader->dict_static;
1399 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1400 *ret = &dict->strings[id];
1401 return S_OK;
1404 static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1406 WS_XML_UTF8_TEXT *text_utf8 = NULL;
1407 WS_XML_BASE64_TEXT *text_base64 = NULL;
1408 WS_XML_INT32_TEXT *text_int32;
1409 WS_XML_INT64_TEXT *text_int64;
1410 WS_XML_BOOL_TEXT *text_bool;
1411 const WS_XML_STRING *str;
1412 unsigned char type;
1413 UINT8 val_uint8;
1414 UINT16 val_uint16;
1415 INT32 val_int32;
1416 ULONG len = 0, id;
1417 GUID guid;
1418 HRESULT hr;
1420 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1421 if (!is_text_type( type )) return WS_E_INVALID_FORMAT;
1423 switch (type)
1425 case RECORD_ZERO_TEXT:
1427 if (!(text_int32 = alloc_int32_text( 0 ))) return E_OUTOFMEMORY;
1428 attr->value = &text_int32->text;
1429 return S_OK;
1431 case RECORD_ONE_TEXT:
1433 if (!(text_int32 = alloc_int32_text( 1 ))) return E_OUTOFMEMORY;
1434 attr->value = &text_int32->text;
1435 return S_OK;
1437 case RECORD_FALSE_TEXT:
1439 if (!(text_bool = alloc_bool_text( FALSE ))) return E_OUTOFMEMORY;
1440 attr->value = &text_bool->text;
1441 return S_OK;
1443 case RECORD_TRUE_TEXT:
1445 if (!(text_bool = alloc_bool_text( TRUE ))) return E_OUTOFMEMORY;
1446 attr->value = &text_bool->text;
1447 return S_OK;
1449 case RECORD_INT8_TEXT:
1451 INT8 val_int8;
1452 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
1453 if (!(text_int64 = alloc_int64_text( val_int8 ))) return E_OUTOFMEMORY;
1454 attr->value = &text_int64->text;
1455 return S_OK;
1457 case RECORD_INT16_TEXT:
1459 INT16 val_int16;
1460 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
1461 if (!(text_int64 = alloc_int64_text( val_int16 ))) return E_OUTOFMEMORY;
1462 attr->value = &text_int64->text;
1463 return S_OK;
1465 case RECORD_INT32_TEXT:
1466 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1467 if (!(text_int64 = alloc_int64_text( val_int32 ))) return E_OUTOFMEMORY;
1468 attr->value = &text_int64->text;
1469 return S_OK;
1471 case RECORD_INT64_TEXT:
1473 INT64 val_int64;
1474 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
1475 if (!(text_int64 = alloc_int64_text( val_int64 ))) return E_OUTOFMEMORY;
1476 attr->value = &text_int64->text;
1477 return S_OK;
1479 case RECORD_FLOAT_TEXT:
1481 WS_XML_FLOAT_TEXT *text_float;
1482 float val_float;
1484 if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
1485 if (!(text_float = alloc_float_text( val_float ))) return E_OUTOFMEMORY;
1486 attr->value = &text_float->text;
1487 return S_OK;
1489 case RECORD_DOUBLE_TEXT:
1491 WS_XML_DOUBLE_TEXT *text_double;
1492 double val_double;
1494 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
1495 if (!(text_double = alloc_double_text( val_double ))) return E_OUTOFMEMORY;
1496 attr->value = &text_double->text;
1497 return S_OK;
1499 case RECORD_DATETIME_TEXT:
1501 WS_XML_DATETIME_TEXT *text_datetime;
1502 WS_DATETIME datetime;
1504 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
1505 if (!(text_datetime = alloc_datetime_text( &datetime ))) return E_OUTOFMEMORY;
1506 attr->value = &text_datetime->text;
1507 return S_OK;
1509 case RECORD_CHARS8_TEXT:
1510 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1511 len = val_uint8;
1512 break;
1514 case RECORD_CHARS16_TEXT:
1515 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1516 len = val_uint16;
1517 break;
1519 case RECORD_CHARS32_TEXT:
1520 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1521 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1522 len = val_int32;
1523 break;
1525 case RECORD_BYTES8_TEXT:
1526 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1527 if (!(text_base64 = alloc_base64_text( NULL, val_uint8 ))) return E_OUTOFMEMORY;
1528 if ((hr = read_bytes( reader, text_base64->bytes, val_uint8 )) != S_OK)
1530 heap_free( text_base64 );
1531 return hr;
1533 break;
1535 case RECORD_BYTES16_TEXT:
1536 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1537 if (!(text_base64 = alloc_base64_text( NULL, val_uint16 ))) return E_OUTOFMEMORY;
1538 if ((hr = read_bytes( reader, text_base64->bytes, val_uint16 )) != S_OK)
1540 heap_free( text_base64 );
1541 return hr;
1543 break;
1545 case RECORD_BYTES32_TEXT:
1546 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1547 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1548 if (!(text_base64 = alloc_base64_text( NULL, val_int32 ))) return E_OUTOFMEMORY;
1549 if ((hr = read_bytes( reader, text_base64->bytes, val_int32 )) != S_OK)
1551 heap_free( text_base64 );
1552 return hr;
1554 break;
1556 case RECORD_EMPTY_TEXT:
1557 break;
1559 case RECORD_DICTIONARY_TEXT:
1560 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1561 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
1562 if (!(text_utf8 = alloc_utf8_text( str->bytes, str->length ))) return E_OUTOFMEMORY;
1563 break;
1565 case RECORD_UNIQUE_ID_TEXT:
1567 WS_XML_UNIQUE_ID_TEXT *text_unique_id;
1568 if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
1569 if (!(text_unique_id = alloc_unique_id_text( &guid ))) return E_OUTOFMEMORY;
1570 attr->value = &text_unique_id->text;
1571 return S_OK;
1573 case RECORD_GUID_TEXT:
1575 WS_XML_GUID_TEXT *guid_text;
1576 if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
1577 if (!(guid_text = alloc_guid_text( &guid ))) return E_OUTOFMEMORY;
1578 attr->value = &guid_text->text;
1579 return S_OK;
1581 case RECORD_UINT64_TEXT:
1583 WS_XML_UINT64_TEXT *text_uint64;
1584 UINT64 val_uint64;
1586 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
1587 if (!(text_uint64 = alloc_uint64_text( val_uint64 ))) return E_OUTOFMEMORY;
1588 attr->value = &text_uint64->text;
1589 return S_OK;
1591 case RECORD_BOOL_TEXT:
1593 WS_XML_BOOL_TEXT *text_bool;
1594 BOOL val_bool;
1596 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
1597 if (!(text_bool = alloc_bool_text( !!val_bool ))) return E_OUTOFMEMORY;
1598 attr->value = &text_bool->text;
1599 return S_OK;
1601 default:
1602 ERR( "unhandled record type %02x\n", type );
1603 return WS_E_NOT_SUPPORTED;
1606 if (type >= RECORD_BYTES8_TEXT && type <= RECORD_BYTES32_TEXT)
1608 attr->value = &text_base64->text;
1609 return S_OK;
1612 if (!text_utf8)
1614 if (!(text_utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
1615 if (!len) text_utf8->value.bytes = (BYTE *)(text_utf8 + 1); /* quirk */
1616 if ((hr = read_bytes( reader, text_utf8->value.bytes, len )) != S_OK)
1618 heap_free( text_utf8 );
1619 return hr;
1623 attr->value = &text_utf8->text;
1624 return S_OK;
1627 static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1629 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1630 WS_XML_ATTRIBUTE *attr;
1631 unsigned int len = 0, ch, skip;
1632 const unsigned char *start;
1633 WS_XML_STRING *prefix, *localname;
1634 HRESULT hr = WS_E_INVALID_FORMAT;
1636 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1638 start = read_current_ptr( reader );
1639 for (;;)
1641 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1642 if (!read_isnamechar( ch )) break;
1643 read_skip( reader, skip );
1644 len += skip;
1646 if (!len) goto error;
1648 if ((hr = parse_qname( start, len, &prefix, &localname )) != S_OK) goto error;
1649 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1651 free_xml_string( prefix );
1652 attr->isXmlNs = 1;
1653 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1655 free_xml_string( localname );
1656 hr = E_OUTOFMEMORY;
1657 goto error;
1659 attr->localName = localname;
1661 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1663 attr->isXmlNs = 1;
1664 attr->prefix = prefix;
1665 attr->localName = localname;
1667 else
1669 attr->prefix = prefix;
1670 attr->localName = localname;
1673 if ((hr = read_attribute_value_text( reader, attr )) != S_OK) goto error;
1675 *ret = attr;
1676 return S_OK;
1678 error:
1679 free_attribute( attr );
1680 return hr;
1683 static inline BOOL is_attribute_type( unsigned char type )
1685 return (type >= RECORD_SHORT_ATTRIBUTE && type <= RECORD_PREFIX_ATTRIBUTE_Z);
1688 static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1690 WS_XML_ATTRIBUTE *attr;
1691 unsigned char type = 0;
1692 HRESULT hr;
1694 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1695 if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT;
1696 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1698 if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z)
1700 unsigned char ch = type - RECORD_PREFIX_ATTRIBUTE_A + 'a';
1701 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1703 hr = E_OUTOFMEMORY;
1704 goto error;
1706 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1707 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1709 else if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
1711 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A + 'a';
1712 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1714 hr = E_OUTOFMEMORY;
1715 goto error;
1717 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1718 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1720 else
1722 switch (type)
1724 case RECORD_SHORT_ATTRIBUTE:
1725 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1727 hr = E_OUTOFMEMORY;
1728 goto error;
1730 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1731 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1732 break;
1734 case RECORD_ATTRIBUTE:
1735 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1736 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1737 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1738 break;
1740 case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
1741 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1743 hr = E_OUTOFMEMORY;
1744 goto error;
1746 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1747 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1748 break;
1750 case RECORD_DICTIONARY_ATTRIBUTE:
1751 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1752 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1753 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1754 break;
1756 case RECORD_SHORT_XMLNS_ATTRIBUTE:
1757 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1759 hr = E_OUTOFMEMORY;
1760 goto error;
1762 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1763 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1764 attr->isXmlNs = 1;
1765 break;
1767 case RECORD_XMLNS_ATTRIBUTE:
1768 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1769 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1770 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1771 attr->isXmlNs = 1;
1772 break;
1774 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
1775 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1777 hr = E_OUTOFMEMORY;
1778 goto error;
1780 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1781 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1782 attr->isXmlNs = 1;
1783 break;
1785 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
1786 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1787 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1788 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1789 attr->isXmlNs = 1;
1790 break;
1792 default:
1793 ERR( "unhandled record type %02x\n", type );
1794 return WS_E_NOT_SUPPORTED;
1798 *ret = attr;
1799 return S_OK;
1801 error:
1802 free_attribute( attr );
1803 return hr;
1806 static inline struct node *find_parent( struct reader *reader )
1808 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT)
1810 if (is_valid_parent( reader->current->parent->parent )) return reader->current->parent->parent;
1811 return NULL;
1813 if (is_valid_parent( reader->current )) return reader->current;
1814 if (is_valid_parent( reader->current->parent )) return reader->current->parent;
1815 return NULL;
1818 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1820 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1821 const WS_XML_STRING *ns;
1822 ULONG i;
1824 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1825 if (!(elem->ns = dup_xml_string( ns, FALSE ))) return E_OUTOFMEMORY;
1827 for (i = 0; i < elem->attributeCount; i++)
1829 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1830 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1831 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1832 if (!(attr->ns = alloc_xml_string( NULL, ns->length ))) return E_OUTOFMEMORY;
1833 if (attr->ns->length) memcpy( attr->ns->bytes, ns->bytes, ns->length );
1835 return S_OK;
1838 static WS_XML_ELEMENT_NODE *alloc_element_pair(void)
1840 struct node *node, *end;
1841 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
1842 if (!(end = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT )))
1844 free_node( node );
1845 return NULL;
1847 list_add_tail( &node->children, &end->entry );
1848 end->parent = node;
1849 return &node->hdr;
1852 static HRESULT read_attributes_text( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1854 WS_XML_ATTRIBUTE *attr;
1855 HRESULT hr;
1857 reader->current_attr = 0;
1858 for (;;)
1860 read_skip_whitespace( reader );
1861 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1862 if ((hr = read_attribute_text( reader, &attr )) != S_OK) return hr;
1863 if ((hr = append_attribute( elem, attr )) != S_OK)
1865 free_attribute( attr );
1866 return hr;
1868 reader->current_attr++;
1870 return S_OK;
1873 static HRESULT read_element_text( struct reader *reader )
1875 unsigned int len = 0, ch, skip;
1876 const unsigned char *start;
1877 struct node *node = NULL, *parent;
1878 WS_XML_ELEMENT_NODE *elem;
1879 HRESULT hr = WS_E_INVALID_FORMAT;
1881 if (read_end_of_data( reader ))
1883 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1884 reader->last = reader->current;
1885 reader->state = READER_STATE_EOF;
1886 return S_OK;
1889 if (read_cmp( reader, "<", 1 )) return WS_E_INVALID_FORMAT;
1890 read_skip( reader, 1 );
1891 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1893 read_rewind( reader, 1 );
1894 return WS_E_INVALID_FORMAT;
1897 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1898 node = (struct node *)elem;
1900 start = read_current_ptr( reader );
1901 for (;;)
1903 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1904 if (!read_isnamechar( ch )) break;
1905 read_skip( reader, skip );
1906 len += skip;
1908 if (!len) goto error;
1910 if (!(parent = find_parent( reader ))) goto error;
1911 if ((hr = parse_qname( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1912 if ((hr = read_attributes_text( reader, elem )) != S_OK) goto error;
1913 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1915 read_insert_node( reader, parent, node );
1916 reader->state = READER_STATE_STARTELEMENT;
1917 return S_OK;
1919 error:
1920 destroy_nodes( node );
1921 return hr;
1924 static inline BOOL is_element_type( unsigned char type )
1926 return (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z);
1929 static HRESULT read_attributes_bin( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1931 WS_XML_ATTRIBUTE *attr;
1932 unsigned char type;
1933 HRESULT hr;
1935 reader->current_attr = 0;
1936 for (;;)
1938 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
1939 if (!is_attribute_type( type )) break;
1940 if ((hr = read_attribute_bin( reader, &attr )) != S_OK) return hr;
1941 if ((hr = append_attribute( elem, attr )) != S_OK)
1943 free_attribute( attr );
1944 return hr;
1946 reader->current_attr++;
1948 return S_OK;
1951 static HRESULT read_element_bin( struct reader *reader )
1953 struct node *node = NULL, *parent;
1954 WS_XML_ELEMENT_NODE *elem;
1955 unsigned char type;
1956 HRESULT hr;
1958 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1959 if (!is_element_type( type )) return WS_E_INVALID_FORMAT;
1961 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1962 node = (struct node *)elem;
1964 if (type >= RECORD_PREFIX_ELEMENT_A && type <= RECORD_PREFIX_ELEMENT_Z)
1966 unsigned char ch = type - RECORD_PREFIX_ELEMENT_A + 'a';
1967 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1969 hr = E_OUTOFMEMORY;
1970 goto error;
1972 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1974 else if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
1976 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ELEMENT_A + 'a';
1977 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1979 hr = E_OUTOFMEMORY;
1980 goto error;
1982 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1984 else
1986 switch (type)
1988 case RECORD_SHORT_ELEMENT:
1989 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
1991 hr = E_OUTOFMEMORY;
1992 goto error;
1994 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1995 break;
1997 case RECORD_ELEMENT:
1998 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
1999 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
2000 break;
2002 case RECORD_SHORT_DICTIONARY_ELEMENT:
2003 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
2005 hr = E_OUTOFMEMORY;
2006 goto error;
2008 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
2009 break;
2011 case RECORD_DICTIONARY_ELEMENT:
2012 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
2013 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
2014 break;
2016 default:
2017 ERR( "unhandled record type %02x\n", type );
2018 return WS_E_NOT_SUPPORTED;
2022 if (!(parent = find_parent( reader )))
2024 hr = WS_E_INVALID_FORMAT;
2025 goto error;
2028 if ((hr = read_attributes_bin( reader, elem )) != S_OK) goto error;
2029 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
2031 read_insert_node( reader, parent, node );
2032 reader->state = READER_STATE_STARTELEMENT;
2033 return S_OK;
2035 error:
2036 destroy_nodes( node );
2037 return hr;
2040 static HRESULT read_text_text( struct reader *reader )
2042 unsigned int len = 0, ch, skip;
2043 const unsigned char *start;
2044 struct node *node, *parent;
2045 WS_XML_TEXT_NODE *text;
2046 WS_XML_UTF8_TEXT *utf8;
2047 HRESULT hr;
2049 start = read_current_ptr( reader );
2050 for (;;)
2052 if (read_end_of_data( reader )) break;
2053 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2054 if (ch == '<') break;
2055 read_skip( reader, skip );
2056 len += skip;
2059 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2061 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2062 text = (WS_XML_TEXT_NODE *)node;
2063 if (!(utf8 = alloc_utf8_text( NULL, len )))
2065 heap_free( node );
2066 return E_OUTOFMEMORY;
2068 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
2070 heap_free( utf8 );
2071 heap_free( node );
2072 return hr;
2074 text->text = &utf8->text;
2076 read_insert_node( reader, parent, node );
2077 reader->state = READER_STATE_TEXT;
2078 reader->text_conv_offset = 0;
2079 return S_OK;
2082 static struct node *alloc_utf8_text_node( const BYTE *data, ULONG len, WS_XML_UTF8_TEXT **ret )
2084 struct node *node;
2085 WS_XML_UTF8_TEXT *utf8;
2086 WS_XML_TEXT_NODE *text;
2088 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2089 if (!(utf8 = alloc_utf8_text( data, len )))
2091 heap_free( node );
2092 return NULL;
2094 text = (WS_XML_TEXT_NODE *)node;
2095 text->text = &utf8->text;
2096 if (ret) *ret = utf8;
2097 return node;
2100 static struct node *alloc_base64_text_node( const BYTE *data, ULONG len, WS_XML_BASE64_TEXT **ret )
2102 struct node *node;
2103 WS_XML_BASE64_TEXT *base64;
2104 WS_XML_TEXT_NODE *text;
2106 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2107 if (!(base64 = alloc_base64_text( data, len )))
2109 heap_free( node );
2110 return NULL;
2112 text = (WS_XML_TEXT_NODE *)node;
2113 text->text = &base64->text;
2114 if (ret) *ret = base64;
2115 return node;
2118 static struct node *alloc_bool_text_node( BOOL value )
2120 struct node *node;
2121 WS_XML_BOOL_TEXT *text_bool;
2122 WS_XML_TEXT_NODE *text;
2124 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2125 if (!(text_bool = alloc_bool_text( value )))
2127 heap_free( node );
2128 return NULL;
2130 text = (WS_XML_TEXT_NODE *)node;
2131 text->text = &text_bool->text;
2132 return node;
2135 static struct node *alloc_int32_text_node( INT32 value )
2137 struct node *node;
2138 WS_XML_INT32_TEXT *text_int32;
2139 WS_XML_TEXT_NODE *text;
2141 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2142 if (!(text_int32 = alloc_int32_text( value )))
2144 heap_free( node );
2145 return NULL;
2147 text = (WS_XML_TEXT_NODE *)node;
2148 text->text = &text_int32->text;
2149 return node;
2152 static struct node *alloc_int64_text_node( INT64 value )
2154 struct node *node;
2155 WS_XML_INT64_TEXT *text_int64;
2156 WS_XML_TEXT_NODE *text;
2158 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2159 if (!(text_int64 = alloc_int64_text( value )))
2161 heap_free( node );
2162 return NULL;
2164 text = (WS_XML_TEXT_NODE *)node;
2165 text->text = &text_int64->text;
2166 return node;
2169 static struct node *alloc_float_text_node( float value )
2171 struct node *node;
2172 WS_XML_FLOAT_TEXT *text_float;
2173 WS_XML_TEXT_NODE *text;
2175 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2176 if (!(text_float = alloc_float_text( value )))
2178 heap_free( node );
2179 return NULL;
2181 text = (WS_XML_TEXT_NODE *)node;
2182 text->text = &text_float->text;
2183 return node;
2186 static struct node *alloc_double_text_node( double value )
2188 struct node *node;
2189 WS_XML_DOUBLE_TEXT *text_double;
2190 WS_XML_TEXT_NODE *text;
2192 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2193 if (!(text_double = alloc_double_text( value )))
2195 heap_free( node );
2196 return NULL;
2198 text = (WS_XML_TEXT_NODE *)node;
2199 text->text = &text_double->text;
2200 return node;
2203 static struct node *alloc_datetime_text_node( const WS_DATETIME *value )
2205 struct node *node;
2206 WS_XML_DATETIME_TEXT *text_datetime;
2207 WS_XML_TEXT_NODE *text;
2209 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2210 if (!(text_datetime = alloc_datetime_text( value )))
2212 heap_free( node );
2213 return NULL;
2215 text = (WS_XML_TEXT_NODE *)node;
2216 text->text = &text_datetime->text;
2217 return node;
2220 static struct node *alloc_unique_id_text_node( const GUID *value )
2222 struct node *node;
2223 WS_XML_UNIQUE_ID_TEXT *text_unique_id;
2224 WS_XML_TEXT_NODE *text;
2226 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2227 if (!(text_unique_id = alloc_unique_id_text( value )))
2229 heap_free( node );
2230 return NULL;
2232 text = (WS_XML_TEXT_NODE *)node;
2233 text->text = &text_unique_id->text;
2234 return node;
2237 static struct node *alloc_guid_text_node( const GUID *value )
2239 struct node *node;
2240 WS_XML_GUID_TEXT *text_guid;
2241 WS_XML_TEXT_NODE *text;
2243 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2244 if (!(text_guid = alloc_guid_text( value )))
2246 heap_free( node );
2247 return NULL;
2249 text = (WS_XML_TEXT_NODE *)node;
2250 text->text = &text_guid->text;
2251 return node;
2254 static struct node *alloc_uint64_text_node( UINT64 value )
2256 struct node *node;
2257 WS_XML_UINT64_TEXT *text_uint64;
2258 WS_XML_TEXT_NODE *text;
2260 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2261 if (!(text_uint64 = alloc_uint64_text( value )))
2263 heap_free( node );
2264 return NULL;
2266 text = (WS_XML_TEXT_NODE *)node;
2267 text->text = &text_uint64->text;
2268 return node;
2271 static HRESULT append_text_bytes( struct reader *reader, WS_XML_TEXT_NODE *node, ULONG len )
2273 WS_XML_BASE64_TEXT *new, *old = (WS_XML_BASE64_TEXT *)node->text;
2274 HRESULT hr;
2276 if (!(new = alloc_base64_text( NULL, old->length + len ))) return E_OUTOFMEMORY;
2277 memcpy( new->bytes, old->bytes, old->length );
2278 if ((hr = read_bytes( reader, new->bytes + old->length, len )) != S_OK) return hr;
2279 heap_free( old );
2280 node->text = &new->text;
2281 return S_OK;
2284 static HRESULT read_text_bytes( struct reader *reader, unsigned char type )
2286 struct node *node = NULL, *parent;
2287 WS_XML_BASE64_TEXT *base64;
2288 HRESULT hr;
2289 ULONG len;
2291 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2292 for (;;)
2294 switch (type)
2296 case RECORD_BYTES8_TEXT:
2297 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2299 UINT8 len_uint8;
2300 if ((hr = read_byte( reader, (unsigned char *)&len_uint8 )) != S_OK) goto error;
2301 len = len_uint8;
2302 break;
2304 case RECORD_BYTES16_TEXT:
2305 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2307 UINT16 len_uint16;
2308 if ((hr = read_bytes( reader, (unsigned char *)&len_uint16, sizeof(len_uint16) )) != S_OK) goto error;
2309 len = len_uint16;
2310 break;
2312 case RECORD_BYTES32_TEXT:
2313 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2315 INT32 len_int32;
2316 if ((hr = read_bytes( reader, (unsigned char *)&len_int32, sizeof(len_int32) )) != S_OK) goto error;
2317 if (len_int32 < 0)
2319 hr = WS_E_INVALID_FORMAT;
2320 goto error;
2322 len = len_int32;
2323 break;
2325 default:
2326 ERR( "unexpected type %u\n", type );
2327 hr = E_INVALIDARG;
2328 goto error;
2331 if (!node)
2333 if (!(node = alloc_base64_text_node( NULL, len, &base64 ))) return E_OUTOFMEMORY;
2334 if ((hr = read_bytes( reader, base64->bytes, len )) != S_OK) goto error;
2336 else if ((hr = append_text_bytes( reader, (WS_XML_TEXT_NODE *)node, len )) != S_OK) goto error;
2338 if (type & 1)
2340 node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2341 break;
2343 if ((hr = read_peek( reader, &type )) != S_OK) goto error;
2344 if (type < RECORD_BYTES8_TEXT || type > RECORD_BYTES32_TEXT_WITH_ENDELEMENT) break;
2345 read_skip( reader, 1 );
2348 read_insert_node( reader, parent, node );
2349 reader->state = READER_STATE_TEXT;
2350 reader->text_conv_offset = 0;
2351 return S_OK;
2353 error:
2354 free_node( node );
2355 return hr;
2358 static HRESULT read_text_bin( struct reader *reader )
2360 struct node *node = NULL, *parent;
2361 unsigned char type;
2362 WS_XML_UTF8_TEXT *utf8;
2363 INT32 val_int32;
2364 UINT8 val_uint8;
2365 UINT16 val_uint16;
2366 ULONG len, id;
2367 GUID uuid;
2368 HRESULT hr;
2370 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2371 if (!is_text_type( type ) || !(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2373 switch (type)
2375 case RECORD_ZERO_TEXT:
2376 case RECORD_ZERO_TEXT_WITH_ENDELEMENT:
2377 if (!(node = alloc_int32_text_node( 0 ))) return E_OUTOFMEMORY;
2378 break;
2380 case RECORD_ONE_TEXT:
2381 case RECORD_ONE_TEXT_WITH_ENDELEMENT:
2382 if (!(node = alloc_int32_text_node( 1 ))) return E_OUTOFMEMORY;
2383 break;
2385 case RECORD_FALSE_TEXT:
2386 case RECORD_FALSE_TEXT_WITH_ENDELEMENT:
2387 if (!(node = alloc_bool_text_node( FALSE ))) return E_OUTOFMEMORY;
2388 break;
2390 case RECORD_TRUE_TEXT:
2391 case RECORD_TRUE_TEXT_WITH_ENDELEMENT:
2392 if (!(node = alloc_bool_text_node( TRUE ))) return E_OUTOFMEMORY;
2393 break;
2395 case RECORD_INT8_TEXT:
2396 case RECORD_INT8_TEXT_WITH_ENDELEMENT:
2398 INT8 val_int8;
2399 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
2400 if (!(node = alloc_int32_text_node( val_int8 ))) return E_OUTOFMEMORY;
2401 break;
2403 case RECORD_INT16_TEXT:
2404 case RECORD_INT16_TEXT_WITH_ENDELEMENT:
2406 INT16 val_int16;
2407 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
2408 if (!(node = alloc_int32_text_node( val_int16 ))) return E_OUTOFMEMORY;
2409 break;
2411 case RECORD_INT32_TEXT:
2412 case RECORD_INT32_TEXT_WITH_ENDELEMENT:
2413 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2414 if (!(node = alloc_int32_text_node( val_int32 ))) return E_OUTOFMEMORY;
2415 break;
2417 case RECORD_INT64_TEXT:
2418 case RECORD_INT64_TEXT_WITH_ENDELEMENT:
2420 INT64 val_int64;
2421 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
2422 if (!(node = alloc_int64_text_node( val_int64 ))) return E_OUTOFMEMORY;
2423 break;
2425 case RECORD_FLOAT_TEXT:
2426 case RECORD_FLOAT_TEXT_WITH_ENDELEMENT:
2428 float val_float;
2429 if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
2430 if (!(node = alloc_float_text_node( val_float ))) return E_OUTOFMEMORY;
2431 break;
2433 case RECORD_DOUBLE_TEXT:
2434 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT:
2436 double val_double;
2437 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
2438 if (!(node = alloc_double_text_node( val_double ))) return E_OUTOFMEMORY;
2439 break;
2441 case RECORD_DATETIME_TEXT:
2442 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT:
2444 WS_DATETIME datetime;
2445 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
2446 if (!(node = alloc_datetime_text_node( &datetime ))) return E_OUTOFMEMORY;
2447 break;
2449 case RECORD_CHARS8_TEXT:
2450 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT:
2451 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
2452 len = val_uint8;
2453 break;
2455 case RECORD_CHARS16_TEXT:
2456 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT:
2457 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
2458 len = val_uint16;
2459 break;
2461 case RECORD_CHARS32_TEXT:
2462 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT:
2463 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2464 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
2465 len = val_int32;
2466 break;
2468 case RECORD_BYTES8_TEXT:
2469 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2470 case RECORD_BYTES16_TEXT:
2471 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2472 case RECORD_BYTES32_TEXT:
2473 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2474 return read_text_bytes( reader, type );
2476 case RECORD_EMPTY_TEXT:
2477 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT:
2478 len = 0;
2479 break;
2481 case RECORD_DICTIONARY_TEXT:
2482 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT:
2484 const WS_XML_STRING *str;
2485 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
2486 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
2487 if (!(node = alloc_utf8_text_node( str->bytes, str->length, NULL ))) return E_OUTOFMEMORY;
2488 break;
2490 case RECORD_UNIQUE_ID_TEXT:
2491 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT:
2492 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2493 if (!(node = alloc_unique_id_text_node( &uuid ))) return E_OUTOFMEMORY;
2494 break;
2496 case RECORD_GUID_TEXT:
2497 case RECORD_GUID_TEXT_WITH_ENDELEMENT:
2498 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2499 if (!(node = alloc_guid_text_node( &uuid ))) return E_OUTOFMEMORY;
2500 break;
2502 case RECORD_UINT64_TEXT:
2503 case RECORD_UINT64_TEXT_WITH_ENDELEMENT:
2505 UINT64 val_uint64;
2506 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
2507 if (!(node = alloc_uint64_text_node( val_uint64 ))) return E_OUTOFMEMORY;
2508 break;
2510 case RECORD_BOOL_TEXT:
2511 case RECORD_BOOL_TEXT_WITH_ENDELEMENT:
2513 BOOL val_bool;
2514 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
2515 if (!(node = alloc_bool_text_node( !!val_bool ))) return E_OUTOFMEMORY;
2516 break;
2518 default:
2519 ERR( "unhandled record type %02x\n", type );
2520 return WS_E_NOT_SUPPORTED;
2523 if (!node)
2525 if (!(node = alloc_utf8_text_node( NULL, len, &utf8 ))) return E_OUTOFMEMORY;
2526 if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
2527 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
2529 free_node( node );
2530 return hr;
2534 if (type & 1) node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2535 read_insert_node( reader, parent, node );
2536 reader->state = READER_STATE_TEXT;
2537 reader->text_conv_offset = 0;
2538 return S_OK;
2541 static HRESULT read_node_text( struct reader * );
2543 static HRESULT read_startelement_text( struct reader *reader )
2545 read_skip_whitespace( reader );
2546 if (!read_cmp( reader, "/>", 2 ))
2548 read_skip( reader, 2 );
2549 reader->current = LIST_ENTRY( list_tail( &reader->current->children ), struct node, entry );
2550 reader->last = reader->current;
2551 reader->state = READER_STATE_ENDELEMENT;
2552 return S_OK;
2554 else if (!read_cmp( reader, ">", 1 ))
2556 read_skip( reader, 1 );
2557 return read_node_text( reader );
2559 return WS_E_INVALID_FORMAT;
2562 static HRESULT read_node_bin( struct reader * );
2564 static HRESULT read_startelement_bin( struct reader *reader )
2566 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
2567 return read_node_bin( reader );
2570 static HRESULT read_startelement( struct reader *reader )
2572 switch (reader->input_enc)
2574 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_startelement_text( reader );
2575 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_startelement_bin( reader );
2576 default:
2577 ERR( "unhandled encoding %u\n", reader->input_enc );
2578 return WS_E_NOT_SUPPORTED;
2582 static HRESULT read_to_startelement_text( struct reader *reader, BOOL *found )
2584 HRESULT hr;
2586 switch (reader->state)
2588 case READER_STATE_INITIAL:
2589 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
2590 break;
2592 case READER_STATE_STARTELEMENT:
2593 if (found) *found = TRUE;
2594 return S_OK;
2596 default:
2597 break;
2600 read_skip_whitespace( reader );
2601 if ((hr = read_element_text( reader )) == S_OK && found)
2603 if (reader->state == READER_STATE_STARTELEMENT)
2604 *found = TRUE;
2605 else
2606 *found = FALSE;
2609 return hr;
2612 static HRESULT read_to_startelement_bin( struct reader *reader, BOOL *found )
2614 HRESULT hr;
2616 if (reader->state == READER_STATE_STARTELEMENT)
2618 if (found) *found = TRUE;
2619 return S_OK;
2622 if ((hr = read_element_bin( reader )) == S_OK && found)
2624 if (reader->state == READER_STATE_STARTELEMENT)
2625 *found = TRUE;
2626 else
2627 *found = FALSE;
2630 return hr;
2633 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
2635 switch (reader->input_enc)
2637 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_to_startelement_text( reader, found );
2638 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_to_startelement_bin( reader, found );
2639 default:
2640 ERR( "unhandled encoding %u\n", reader->input_enc );
2641 return WS_E_NOT_SUPPORTED;
2645 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
2647 ULONG i;
2648 if (len1 != len2) return 1;
2649 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
2650 return 0;
2653 static struct node *find_startelement( struct reader *reader, const WS_XML_STRING *prefix,
2654 const WS_XML_STRING *localname )
2656 struct node *parent;
2657 const WS_XML_STRING *str;
2659 for (parent = reader->current; parent; parent = parent->parent)
2661 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
2663 str = parent->hdr.prefix;
2664 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
2665 str = parent->hdr.localName;
2666 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
2667 return parent;
2670 return NULL;
2673 static HRESULT read_endelement_text( struct reader *reader )
2675 struct node *parent;
2676 unsigned int len = 0, ch, skip;
2677 const unsigned char *start;
2678 WS_XML_STRING prefix, localname;
2679 HRESULT hr;
2681 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
2682 read_skip( reader, 2 );
2684 start = read_current_ptr( reader );
2685 for (;;)
2687 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2688 if (ch == '>')
2690 read_skip( reader, 1 );
2691 break;
2693 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
2694 read_skip( reader, skip );
2695 len += skip;
2698 if ((hr = split_qname( start, len, &prefix, &localname )) != S_OK) return hr;
2699 if (!(parent = find_startelement( reader, &prefix, &localname ))) return WS_E_INVALID_FORMAT;
2701 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2702 reader->last = reader->current;
2703 reader->state = READER_STATE_ENDELEMENT;
2704 return S_OK;
2707 static HRESULT read_endelement_bin( struct reader *reader )
2709 struct node *parent;
2710 unsigned char type;
2711 HRESULT hr;
2713 if (!(reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT))
2715 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2716 if (type != RECORD_ENDELEMENT) return WS_E_INVALID_FORMAT;
2718 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2720 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2721 reader->last = reader->current;
2722 reader->state = READER_STATE_ENDELEMENT;
2723 return S_OK;
2726 static HRESULT read_endelement( struct reader *reader )
2728 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2730 if (read_end_of_data( reader ))
2732 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2733 reader->last = reader->current;
2734 reader->state = READER_STATE_EOF;
2735 return S_OK;
2738 switch (reader->input_enc)
2740 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_endelement_text( reader );
2741 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_endelement_bin( reader );
2742 default:
2743 ERR( "unhandled encoding %u\n", reader->input_enc );
2744 return WS_E_NOT_SUPPORTED;
2748 static HRESULT read_comment_text( struct reader *reader )
2750 unsigned int len = 0, ch, skip;
2751 const unsigned char *start;
2752 struct node *node, *parent;
2753 WS_XML_COMMENT_NODE *comment;
2755 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
2756 read_skip( reader, 4 );
2758 start = read_current_ptr( reader );
2759 for (;;)
2761 if (!read_cmp( reader, "-->", 3 ))
2763 read_skip( reader, 3 );
2764 break;
2766 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2767 read_skip( reader, skip );
2768 len += skip;
2771 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2773 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2774 comment = (WS_XML_COMMENT_NODE *)node;
2775 if (!(comment->value.bytes = heap_alloc( len )))
2777 heap_free( node );
2778 return E_OUTOFMEMORY;
2780 memcpy( comment->value.bytes, start, len );
2781 comment->value.length = len;
2783 read_insert_node( reader, parent, node );
2784 reader->state = READER_STATE_COMMENT;
2785 return S_OK;
2788 static HRESULT read_comment_bin( struct reader *reader )
2790 struct node *node, *parent;
2791 WS_XML_COMMENT_NODE *comment;
2792 unsigned char type;
2793 ULONG len;
2794 HRESULT hr;
2796 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2797 if (type != RECORD_COMMENT) return WS_E_INVALID_FORMAT;
2798 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
2800 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2802 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2803 comment = (WS_XML_COMMENT_NODE *)node;
2804 if (!(comment->value.bytes = heap_alloc( len )))
2806 heap_free( node );
2807 return E_OUTOFMEMORY;
2809 if ((hr = read_bytes( reader, comment->value.bytes, len )) != S_OK)
2811 free_node( node );
2812 return E_OUTOFMEMORY;
2814 comment->value.length = len;
2816 read_insert_node( reader, parent, node );
2817 reader->state = READER_STATE_COMMENT;
2818 return S_OK;
2821 static HRESULT read_startcdata( struct reader *reader )
2823 struct node *node, *endnode, *parent;
2825 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
2826 read_skip( reader, 9 );
2828 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2830 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
2831 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_CDATA )))
2833 heap_free( node );
2834 return E_OUTOFMEMORY;
2836 list_add_tail( &node->children, &endnode->entry );
2837 endnode->parent = node;
2839 read_insert_node( reader, parent, node );
2840 reader->state = READER_STATE_STARTCDATA;
2841 return S_OK;
2844 static HRESULT read_cdata( struct reader *reader )
2846 unsigned int len = 0, ch, skip;
2847 const unsigned char *start;
2848 struct node *node;
2849 WS_XML_TEXT_NODE *text;
2850 WS_XML_UTF8_TEXT *utf8;
2852 start = read_current_ptr( reader );
2853 for (;;)
2855 if (!read_cmp( reader, "]]>", 3 )) break;
2856 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2857 read_skip( reader, skip );
2858 len += skip;
2861 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2862 text = (WS_XML_TEXT_NODE *)node;
2863 if (!(utf8 = alloc_utf8_text( start, len )))
2865 heap_free( node );
2866 return E_OUTOFMEMORY;
2868 text->text = &utf8->text;
2870 read_insert_node( reader, reader->current, node );
2871 reader->state = READER_STATE_CDATA;
2872 return S_OK;
2875 static HRESULT read_endcdata( struct reader *reader )
2877 struct node *parent;
2879 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
2880 read_skip( reader, 3 );
2882 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT) parent = reader->current->parent;
2883 else parent = reader->current;
2885 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2886 reader->last = reader->current;
2887 reader->state = READER_STATE_ENDCDATA;
2888 return S_OK;
2891 static HRESULT read_node_text( struct reader *reader )
2893 HRESULT hr;
2895 for (;;)
2897 if (read_end_of_data( reader ))
2899 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2900 reader->last = reader->current;
2901 reader->state = READER_STATE_EOF;
2902 return S_OK;
2904 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
2905 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
2906 else if (!read_cmp( reader, "<?", 2 ))
2908 hr = read_xmldecl( reader );
2909 if (FAILED( hr )) return hr;
2911 else if (!read_cmp( reader, "</", 2 )) return read_endelement_text( reader );
2912 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
2913 else if (!read_cmp( reader, "<!--", 4 )) return read_comment_text( reader );
2914 else if (!read_cmp( reader, "<", 1 )) return read_element_text( reader );
2915 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement_text( reader );
2916 else return read_text_text( reader );
2920 static HRESULT read_node_bin( struct reader *reader )
2922 unsigned char type;
2923 HRESULT hr;
2925 if (reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT)
2927 reader->current = LIST_ENTRY( list_tail( &reader->current->parent->children ), struct node, entry );
2928 reader->last = reader->current;
2929 reader->state = READER_STATE_ENDELEMENT;
2930 return S_OK;
2932 if (read_end_of_data( reader ))
2934 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2935 reader->last = reader->current;
2936 reader->state = READER_STATE_EOF;
2937 return S_OK;
2940 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
2941 if (type == RECORD_ENDELEMENT)
2943 return read_endelement_bin( reader );
2945 else if (type == RECORD_COMMENT)
2947 return read_comment_bin( reader );
2949 else if (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z)
2951 return read_element_bin( reader );
2953 else if (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT)
2955 return read_text_bin( reader );
2957 FIXME( "unhandled record type %02x\n", type );
2958 return WS_E_NOT_SUPPORTED;
2961 static HRESULT read_node( struct reader *reader )
2963 switch (reader->input_enc)
2965 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_node_text( reader );
2966 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_node_bin( reader );
2967 default:
2968 ERR( "unhandled encoding %u\n", reader->input_enc );
2969 return WS_E_NOT_SUPPORTED;
2973 HRESULT copy_node( WS_XML_READER *handle, struct node **node )
2975 struct reader *reader = (struct reader *)handle;
2976 const struct list *ptr;
2977 const struct node *start;
2978 HRESULT hr;
2980 EnterCriticalSection( &reader->cs );
2982 if (reader->magic != READER_MAGIC)
2984 LeaveCriticalSection( &reader->cs );
2985 return E_INVALIDARG;
2988 if (reader->current != reader->root) ptr = &reader->current->entry;
2989 else /* copy whole tree */
2991 if (!read_end_of_data( reader ))
2993 for (;;)
2995 if ((hr = read_node( reader )) != S_OK) goto done;
2996 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) break;
2999 ptr = list_head( &reader->root->children );
3002 start = LIST_ENTRY( ptr, struct node, entry );
3003 if (node_type( start ) == WS_XML_NODE_TYPE_EOF) hr = WS_E_INVALID_OPERATION;
3004 else hr = dup_tree( node, start );
3006 done:
3007 LeaveCriticalSection( &reader->cs );
3008 return hr;
3011 /**************************************************************************
3012 * WsReadEndElement [webservices.@]
3014 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
3016 struct reader *reader = (struct reader *)handle;
3017 HRESULT hr;
3019 TRACE( "%p %p\n", handle, error );
3020 if (error) FIXME( "ignoring error parameter\n" );
3022 if (!reader) return E_INVALIDARG;
3024 EnterCriticalSection( &reader->cs );
3026 if (reader->magic != READER_MAGIC)
3028 LeaveCriticalSection( &reader->cs );
3029 return E_INVALIDARG;
3032 hr = read_endelement( reader );
3034 LeaveCriticalSection( &reader->cs );
3035 return hr;
3038 /**************************************************************************
3039 * WsReadNode [webservices.@]
3041 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
3043 struct reader *reader = (struct reader *)handle;
3044 HRESULT hr;
3046 TRACE( "%p %p\n", handle, error );
3047 if (error) FIXME( "ignoring error parameter\n" );
3049 if (!reader) return E_INVALIDARG;
3051 EnterCriticalSection( &reader->cs );
3053 if (reader->magic != READER_MAGIC)
3055 LeaveCriticalSection( &reader->cs );
3056 return E_INVALIDARG;
3059 hr = read_node( reader );
3061 LeaveCriticalSection( &reader->cs );
3062 return hr;
3065 static HRESULT skip_node( struct reader *reader )
3067 const struct node *parent;
3068 HRESULT hr;
3070 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) return WS_E_INVALID_OPERATION;
3071 if (node_type( reader->current ) == WS_XML_NODE_TYPE_ELEMENT) parent = reader->current;
3072 else parent = NULL;
3074 for (;;)
3076 if ((hr = read_node( reader )) != S_OK || !parent) break;
3077 if (node_type( reader->current ) != WS_XML_NODE_TYPE_END_ELEMENT) continue;
3078 if (reader->current->parent == parent) return read_node( reader );
3081 return hr;
3084 /**************************************************************************
3085 * WsSkipNode [webservices.@]
3087 HRESULT WINAPI WsSkipNode( WS_XML_READER *handle, WS_ERROR *error )
3089 struct reader *reader = (struct reader *)handle;
3090 HRESULT hr;
3092 TRACE( "%p %p\n", handle, error );
3093 if (error) FIXME( "ignoring error parameter\n" );
3095 if (!reader) return E_INVALIDARG;
3097 EnterCriticalSection( &reader->cs );
3099 if (reader->magic != READER_MAGIC)
3101 LeaveCriticalSection( &reader->cs );
3102 return E_INVALIDARG;
3105 hr = skip_node( reader );
3107 LeaveCriticalSection( &reader->cs );
3108 return hr;
3111 /**************************************************************************
3112 * WsReadStartElement [webservices.@]
3114 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
3116 struct reader *reader = (struct reader *)handle;
3117 HRESULT hr;
3119 TRACE( "%p %p\n", handle, error );
3120 if (error) FIXME( "ignoring error parameter\n" );
3122 if (!reader) return E_INVALIDARG;
3124 EnterCriticalSection( &reader->cs );
3126 if (reader->magic != READER_MAGIC)
3128 LeaveCriticalSection( &reader->cs );
3129 return E_INVALIDARG;
3132 hr = read_startelement( reader );
3134 LeaveCriticalSection( &reader->cs );
3135 return hr;
3138 /**************************************************************************
3139 * WsReadToStartElement [webservices.@]
3141 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
3142 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
3144 struct reader *reader = (struct reader *)handle;
3145 HRESULT hr;
3147 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
3148 if (error) FIXME( "ignoring error parameter\n" );
3150 if (!reader) return E_INVALIDARG;
3151 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
3153 EnterCriticalSection( &reader->cs );
3155 if (reader->magic != READER_MAGIC)
3157 LeaveCriticalSection( &reader->cs );
3158 return E_INVALIDARG;
3161 hr = read_to_startelement( reader, found );
3163 LeaveCriticalSection( &reader->cs );
3164 return hr;
3167 BOOL move_to_root_element( struct node *root, struct node **current )
3169 struct list *ptr;
3170 struct node *node;
3172 if (!(ptr = list_head( &root->children ))) return FALSE;
3173 node = LIST_ENTRY( ptr, struct node, entry );
3174 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
3176 *current = node;
3177 return TRUE;
3179 while ((ptr = list_next( &root->children, &node->entry )))
3181 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3182 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3184 *current = next;
3185 return TRUE;
3187 node = next;
3189 return FALSE;
3192 BOOL move_to_next_element( struct node **current )
3194 struct list *ptr;
3195 struct node *node = *current, *parent = (*current)->parent;
3197 if (!parent) return FALSE;
3198 while ((ptr = list_next( &parent->children, &node->entry )))
3200 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3201 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3203 *current = next;
3204 return TRUE;
3206 node = next;
3208 return FALSE;
3211 BOOL move_to_prev_element( struct node **current )
3213 struct list *ptr;
3214 struct node *node = *current, *parent = (*current)->parent;
3216 if (!parent) return FALSE;
3217 while ((ptr = list_prev( &parent->children, &node->entry )))
3219 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
3220 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
3222 *current = prev;
3223 return TRUE;
3225 node = prev;
3227 return FALSE;
3230 BOOL move_to_child_element( struct node **current )
3232 struct list *ptr;
3233 struct node *child, *node = *current;
3235 if (!(ptr = list_head( &node->children ))) return FALSE;
3236 child = LIST_ENTRY( ptr, struct node, entry );
3237 if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
3239 *current = child;
3240 return TRUE;
3242 while ((ptr = list_next( &node->children, &child->entry )))
3244 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3245 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3247 *current = next;
3248 return TRUE;
3250 child = next;
3252 return FALSE;
3255 BOOL move_to_end_element( struct node **current )
3257 struct list *ptr;
3258 struct node *node = *current;
3260 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3262 if ((ptr = list_tail( &node->children )))
3264 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
3265 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
3267 *current = tail;
3268 return TRUE;
3271 return FALSE;
3274 BOOL move_to_parent_element( struct node **current )
3276 struct node *parent = (*current)->parent;
3278 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
3279 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
3281 *current = parent;
3282 return TRUE;
3284 return FALSE;
3287 BOOL move_to_first_node( struct node **current )
3289 struct list *ptr;
3290 struct node *node = *current;
3292 if ((ptr = list_head( &node->parent->children )))
3294 *current = LIST_ENTRY( ptr, struct node, entry );
3295 return TRUE;
3297 return FALSE;
3300 BOOL move_to_next_node( struct node **current )
3302 struct list *ptr;
3303 struct node *node = *current;
3305 if ((ptr = list_next( &node->parent->children, &node->entry )))
3307 *current = LIST_ENTRY( ptr, struct node, entry );
3308 return TRUE;
3310 return FALSE;
3313 BOOL move_to_prev_node( struct node **current )
3315 struct list *ptr;
3316 struct node *node = *current;
3318 if ((ptr = list_prev( &node->parent->children, &node->entry )))
3320 *current = LIST_ENTRY( ptr, struct node, entry );
3321 return TRUE;
3323 return FALSE;
3326 BOOL move_to_bof( struct node *root, struct node **current )
3328 *current = root;
3329 return TRUE;
3332 BOOL move_to_eof( struct node *root, struct node **current )
3334 struct list *ptr;
3335 if ((ptr = list_tail( &root->children )))
3337 *current = LIST_ENTRY( ptr, struct node, entry );
3338 return TRUE;
3340 return FALSE;
3343 BOOL move_to_child_node( struct node **current )
3345 struct list *ptr;
3346 struct node *node = *current;
3348 if ((ptr = list_head( &node->children )))
3350 *current = LIST_ENTRY( ptr, struct node, entry );
3351 return TRUE;
3353 return FALSE;
3356 BOOL move_to_parent_node( struct node **current )
3358 struct node *parent = (*current)->parent;
3359 if (!parent) return FALSE;
3360 *current = parent;
3361 return TRUE;
3364 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
3366 BOOL success = FALSE;
3367 HRESULT hr = S_OK;
3369 if (!read_end_of_data( reader ))
3371 struct node *saved_current = reader->current;
3372 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
3373 if (hr != S_OK) return hr;
3374 reader->current = saved_current;
3376 switch (move)
3378 case WS_MOVE_TO_ROOT_ELEMENT:
3379 success = move_to_root_element( reader->root, &reader->current );
3380 break;
3382 case WS_MOVE_TO_NEXT_ELEMENT:
3383 success = move_to_next_element( &reader->current );
3384 break;
3386 case WS_MOVE_TO_PREVIOUS_ELEMENT:
3387 success = move_to_prev_element( &reader->current );
3388 break;
3390 case WS_MOVE_TO_CHILD_ELEMENT:
3391 success = move_to_child_element( &reader->current );
3392 break;
3394 case WS_MOVE_TO_END_ELEMENT:
3395 success = move_to_end_element( &reader->current );
3396 break;
3398 case WS_MOVE_TO_PARENT_ELEMENT:
3399 success = move_to_parent_element( &reader->current );
3400 break;
3402 case WS_MOVE_TO_FIRST_NODE:
3403 success = move_to_first_node( &reader->current );
3404 break;
3406 case WS_MOVE_TO_NEXT_NODE:
3407 success = move_to_next_node( &reader->current );
3408 break;
3410 case WS_MOVE_TO_PREVIOUS_NODE:
3411 success = move_to_prev_node( &reader->current );
3412 break;
3414 case WS_MOVE_TO_CHILD_NODE:
3415 success = move_to_child_node( &reader->current );
3416 break;
3418 case WS_MOVE_TO_BOF:
3419 success = move_to_bof( reader->root, &reader->current );
3420 break;
3422 case WS_MOVE_TO_EOF:
3423 success = move_to_eof( reader->root, &reader->current );
3424 break;
3426 default:
3427 FIXME( "unhandled move %u\n", move );
3428 return E_NOTIMPL;
3431 if (found)
3433 *found = success;
3434 return S_OK;
3436 return success ? S_OK : WS_E_INVALID_FORMAT;
3439 /**************************************************************************
3440 * WsMoveReader [webservices.@]
3442 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
3444 struct reader *reader = (struct reader *)handle;
3445 HRESULT hr;
3447 TRACE( "%p %u %p %p\n", handle, move, found, error );
3448 if (error) FIXME( "ignoring error parameter\n" );
3450 if (!reader) return E_INVALIDARG;
3452 EnterCriticalSection( &reader->cs );
3454 if (reader->magic != READER_MAGIC)
3456 LeaveCriticalSection( &reader->cs );
3457 return E_INVALIDARG;
3460 if (!reader->input_type)
3462 LeaveCriticalSection( &reader->cs );
3463 return WS_E_INVALID_OPERATION;
3466 hr = read_move_to( reader, move, found );
3468 LeaveCriticalSection( &reader->cs );
3469 return hr;
3472 /**************************************************************************
3473 * WsReadStartAttribute [webservices.@]
3475 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
3477 struct reader *reader = (struct reader *)handle;
3478 const WS_XML_ELEMENT_NODE *elem;
3480 TRACE( "%p %u %p\n", handle, index, error );
3481 if (error) FIXME( "ignoring error parameter\n" );
3483 if (!reader) return E_INVALIDARG;
3485 EnterCriticalSection( &reader->cs );
3487 if (reader->magic != READER_MAGIC)
3489 LeaveCriticalSection( &reader->cs );
3490 return E_INVALIDARG;
3493 elem = &reader->current->hdr;
3494 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
3496 LeaveCriticalSection( &reader->cs );
3497 return WS_E_INVALID_FORMAT;
3500 reader->current_attr = index;
3501 reader->state = READER_STATE_STARTATTRIBUTE;
3503 LeaveCriticalSection( &reader->cs );
3504 return S_OK;
3507 /**************************************************************************
3508 * WsReadEndAttribute [webservices.@]
3510 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
3512 struct reader *reader = (struct reader *)handle;
3514 TRACE( "%p %p\n", handle, error );
3515 if (error) FIXME( "ignoring error parameter\n" );
3517 if (!reader) return E_INVALIDARG;
3519 EnterCriticalSection( &reader->cs );
3521 if (reader->magic != READER_MAGIC)
3523 LeaveCriticalSection( &reader->cs );
3524 return E_INVALIDARG;
3527 if (reader->state != READER_STATE_STARTATTRIBUTE)
3529 LeaveCriticalSection( &reader->cs );
3530 return WS_E_INVALID_FORMAT;
3533 reader->state = READER_STATE_STARTELEMENT;
3535 LeaveCriticalSection( &reader->cs );
3536 return S_OK;
3539 static HRESULT str_to_bool( const unsigned char *str, ULONG len, BOOL *ret )
3541 if (len == 4 && !memcmp( str, "true", 4 )) *ret = TRUE;
3542 else if (len == 1 && !memcmp( str, "1", 1 )) *ret = TRUE;
3543 else if (len == 5 && !memcmp( str, "false", 5 )) *ret = FALSE;
3544 else if (len == 1 && !memcmp( str, "0", 1 )) *ret = FALSE;
3545 else return WS_E_INVALID_FORMAT;
3546 return S_OK;
3549 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
3551 BOOL negative = FALSE;
3552 const unsigned char *ptr = str;
3554 *ret = 0;
3555 while (len && read_isspace( *ptr )) { ptr++; len--; }
3556 while (len && read_isspace( ptr[len - 1] )) { len--; }
3557 if (!len) return WS_E_INVALID_FORMAT;
3559 if (*ptr == '-')
3561 negative = TRUE;
3562 ptr++;
3563 len--;
3565 if (!len) return WS_E_INVALID_FORMAT;
3567 while (len--)
3569 int val;
3571 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3572 val = *ptr - '0';
3573 if (negative) val = -val;
3575 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
3576 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
3578 return WS_E_NUMERIC_OVERFLOW;
3580 *ret = *ret * 10 + val;
3581 ptr++;
3584 return S_OK;
3587 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
3589 const unsigned char *ptr = str;
3591 *ret = 0;
3592 while (len && read_isspace( *ptr )) { ptr++; len--; }
3593 while (len && read_isspace( ptr[len - 1] )) { len--; }
3594 if (!len) return WS_E_INVALID_FORMAT;
3596 while (len--)
3598 unsigned int val;
3600 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3601 val = *ptr - '0';
3603 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
3604 *ret = *ret * 10 + val;
3605 ptr++;
3608 return S_OK;
3611 BOOL set_fpword( unsigned short new, unsigned short *old )
3613 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3614 unsigned short fpword;
3616 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
3617 *old = fpword;
3618 fpword = new;
3619 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3620 return TRUE;
3621 #else
3622 FIXME( "not implemented\n" );
3623 return FALSE;
3624 #endif
3627 void restore_fpword( unsigned short fpword )
3629 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3630 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3631 #else
3632 FIXME( "not implemented\n" );
3633 #endif
3636 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
3638 static const unsigned __int64 nan = 0xfff8000000000000;
3639 static const unsigned __int64 inf = 0x7ff0000000000000;
3640 static const unsigned __int64 inf_min = 0xfff0000000000000;
3641 HRESULT hr = WS_E_INVALID_FORMAT;
3642 const unsigned char *p = str, *q;
3643 int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
3644 unsigned __int64 val = 0, tmp;
3645 long double exp_val = 1.0, exp_mul = 10.0;
3646 unsigned short fpword;
3648 while (len && read_isspace( *p )) { p++; len--; }
3649 while (len && read_isspace( p[len - 1] )) { len--; }
3650 if (!len) return WS_E_INVALID_FORMAT;
3652 if (len == 3 && !memcmp( p, "NaN", 3 ))
3654 *(unsigned __int64 *)ret = nan;
3655 return S_OK;
3657 if (len == 3 && !memcmp( p, "INF", 3 ))
3659 *(unsigned __int64 *)ret = inf;
3660 return S_OK;
3662 if (len == 4 && !memcmp( p, "-INF", 4 ))
3664 *(unsigned __int64 *)ret = inf_min;
3665 return S_OK;
3668 *ret = 0.0;
3669 if (*p == '-')
3671 sign = -1;
3672 p++; len--;
3674 else if (*p == '+') { p++; len--; };
3675 if (!len) return S_OK;
3677 if (!set_fpword( 0x37f, &fpword )) return E_NOTIMPL;
3679 q = p;
3680 while (len && isdigit( *q )) { q++; len--; }
3681 have_digits = nb_digits = q - p;
3682 for (i = 0; i < nb_digits; i++)
3684 tmp = val * 10 + p[i] - '0';
3685 if (val > MAX_UINT64 / 10 || tmp < val)
3687 for (; i < nb_digits; i++) exp++;
3688 break;
3690 val = tmp;
3693 if (len)
3695 if (*q == '.')
3697 p = ++q; len--;
3698 while (len && isdigit( *q )) { q++; len--; };
3699 have_digits |= nb_digits = q - p;
3700 for (i = 0; i < nb_digits; i++)
3702 tmp = val * 10 + p[i] - '0';
3703 if (val > MAX_UINT64 / 10 || tmp < val) break;
3704 val = tmp;
3705 exp--;
3708 if (len > 1 && tolower(*q) == 'e')
3710 if (!have_digits) goto done;
3711 p = ++q; len--;
3712 if (*p == '-')
3714 exp_sign = -1;
3715 p++; len--;
3717 else if (*p == '+') { p++; len--; };
3719 q = p;
3720 while (len && isdigit( *q )) { q++; len--; };
3721 nb_digits = q - p;
3722 if (!nb_digits || len) goto done;
3723 for (i = 0; i < nb_digits; i++)
3725 if (exp_tmp > MAX_INT32 / 10 || (exp_tmp = exp_tmp * 10 + p[i] - '0') < 0)
3726 exp_tmp = MAX_INT32;
3728 exp_tmp *= exp_sign;
3730 if (exp < 0 && exp_tmp < 0 && exp + exp_tmp >= 0) exp = MIN_INT32;
3731 else if (exp > 0 && exp_tmp > 0 && exp + exp_tmp < 0) exp = MAX_INT32;
3732 else exp += exp_tmp;
3735 if (!have_digits || len) goto done;
3737 if ((neg_exp = exp < 0)) exp = -exp;
3738 for (; exp; exp >>= 1)
3740 if (exp & 1) exp_val *= exp_mul;
3741 exp_mul *= exp_mul;
3744 *ret = sign * (neg_exp ? val / exp_val : val * exp_val);
3745 hr = S_OK;
3747 done:
3748 restore_fpword( fpword );
3749 return hr;
3752 static HRESULT str_to_float( const unsigned char *str, ULONG len, float *ret )
3754 static const unsigned int inf = 0x7f800000;
3755 static const unsigned int inf_min = 0xff800000;
3756 const unsigned char *p = str;
3757 double val;
3758 HRESULT hr;
3760 while (len && read_isspace( *p )) { p++; len--; }
3761 while (len && read_isspace( p[len - 1] )) { len--; }
3762 if (!len) return WS_E_INVALID_FORMAT;
3764 if (len == 3 && !memcmp( p, "INF", 3 ))
3766 *(unsigned int *)ret = inf;
3767 return S_OK;
3769 if (len == 4 && !memcmp( p, "-INF", 4 ))
3771 *(unsigned int *)ret = inf_min;
3772 return S_OK;
3775 if ((hr = str_to_double( p, len, &val )) != S_OK) return hr;
3776 *ret = val;
3777 return S_OK;
3780 static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
3782 static const unsigned char hex[] =
3784 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3785 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3786 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3787 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3788 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3789 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3790 0,10,11,12,13,14,15 /* 0x60 */
3792 const unsigned char *p = str;
3793 ULONG i;
3795 while (len && read_isspace( *p )) { p++; len--; }
3796 while (len && read_isspace( p[len - 1] )) { len--; }
3797 if (len != 36) return WS_E_INVALID_FORMAT;
3799 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
3800 return WS_E_INVALID_FORMAT;
3802 for (i = 0; i < 36; i++)
3804 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
3805 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
3808 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
3809 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
3811 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
3812 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
3814 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
3815 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
3816 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
3817 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
3818 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
3819 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
3820 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
3821 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
3823 return S_OK;
3826 static HRESULT str_to_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_STRING *ret )
3828 int len_utf16 = MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, NULL, 0 );
3829 if (!(ret->chars = ws_alloc( heap, len_utf16 * sizeof(WCHAR) ))) return WS_E_QUOTA_EXCEEDED;
3830 MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, ret->chars, len_utf16 );
3831 ret->length = len_utf16;
3832 return S_OK;
3835 static HRESULT str_to_unique_id( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_UNIQUE_ID *ret )
3837 if (len == 45 && !memcmp( str, "urn:uuid:", 9 ))
3839 ret->uri.length = 0;
3840 ret->uri.chars = NULL;
3841 return str_to_guid( str + 9, len - 9, &ret->guid );
3844 memset( &ret->guid, 0, sizeof(ret->guid) );
3845 return str_to_string( str, len, heap, &ret->uri );
3848 static inline unsigned char decode_char( unsigned char c )
3850 if (c >= 'A' && c <= 'Z') return c - 'A';
3851 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
3852 if (c >= '0' && c <= '9') return c - '0' + 52;
3853 if (c == '+') return 62;
3854 if (c == '/') return 63;
3855 return 64;
3858 static ULONG decode_base64( const unsigned char *base64, ULONG len, unsigned char *buf )
3860 ULONG i = 0;
3861 unsigned char c0, c1, c2, c3;
3862 const unsigned char *p = base64;
3864 while (len > 4)
3866 if ((c0 = decode_char( p[0] )) > 63) return 0;
3867 if ((c1 = decode_char( p[1] )) > 63) return 0;
3868 if ((c2 = decode_char( p[2] )) > 63) return 0;
3869 if ((c3 = decode_char( p[3] )) > 63) return 0;
3870 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3871 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3872 buf[i + 2] = (c2 << 6) | c3;
3873 len -= 4;
3874 i += 3;
3875 p += 4;
3877 if (p[2] == '=')
3879 if ((c0 = decode_char( p[0] )) > 63) return 0;
3880 if ((c1 = decode_char( p[1] )) > 63) return 0;
3881 buf[i] = (c0 << 2) | (c1 >> 4);
3882 i++;
3884 else if (p[3] == '=')
3886 if ((c0 = decode_char( p[0] )) > 63) return 0;
3887 if ((c1 = decode_char( p[1] )) > 63) return 0;
3888 if ((c2 = decode_char( p[2] )) > 63) return 0;
3889 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3890 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3891 i += 2;
3893 else
3895 if ((c0 = decode_char( p[0] )) > 63) return 0;
3896 if ((c1 = decode_char( p[1] )) > 63) return 0;
3897 if ((c2 = decode_char( p[2] )) > 63) return 0;
3898 if ((c3 = decode_char( p[3] )) > 63) return 0;
3899 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3900 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3901 buf[i + 2] = (c2 << 6) | c3;
3902 i += 3;
3904 return i;
3907 static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_BYTES *ret )
3909 const unsigned char *p = str;
3911 while (len && read_isspace( *p )) { p++; len--; }
3912 while (len && read_isspace( p[len - 1] )) { len--; }
3914 if (len % 4) return WS_E_INVALID_FORMAT;
3915 if (!(ret->bytes = ws_alloc( heap, len * 3 / 4 ))) return WS_E_QUOTA_EXCEEDED;
3916 ret->length = decode_base64( p, len, ret->bytes );
3917 return S_OK;
3920 static HRESULT str_to_xml_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_XML_STRING *ret )
3922 if (!(ret->bytes = ws_alloc( heap, len ))) return WS_E_QUOTA_EXCEEDED;
3923 memcpy( ret->bytes, str, len );
3924 ret->length = len;
3925 ret->dictionary = NULL;
3926 ret->id = 0;
3927 return S_OK;
3930 static HRESULT copy_xml_string( WS_HEAP *heap, const WS_XML_STRING *src, WS_XML_STRING *dst )
3932 if (!(dst->bytes = ws_alloc( heap, src->length ))) return WS_E_QUOTA_EXCEEDED;
3933 memcpy( dst->bytes, src->bytes, src->length );
3934 dst->length = src->length;
3935 return S_OK;
3938 static HRESULT str_to_qname( struct reader *reader, const unsigned char *str, ULONG len, WS_HEAP *heap,
3939 WS_XML_STRING *prefix_ret, WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
3941 const unsigned char *p = str;
3942 WS_XML_STRING prefix, localname;
3943 const WS_XML_STRING *ns;
3944 HRESULT hr;
3946 while (len && read_isspace( *p )) { p++; len--; }
3947 while (len && read_isspace( p[len - 1] )) { len--; }
3949 if ((hr = split_qname( p, len, &prefix, &localname )) != S_OK) return hr;
3950 if (!(ns = get_namespace( reader, &prefix ))) return WS_E_INVALID_FORMAT;
3952 if (prefix_ret && (hr = copy_xml_string( heap, &prefix, prefix_ret )) != S_OK) return hr;
3953 if ((hr = copy_xml_string( heap, &localname, localname_ret )) != S_OK)
3955 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
3956 return hr;
3958 if ((hr = copy_xml_string( heap, ns, ns_ret )) != S_OK)
3960 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
3961 ws_free( heap, localname_ret->bytes, localname_ret->length );
3962 return hr;
3964 return S_OK;
3967 static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix,
3968 WS_XML_STRING *localname, WS_XML_STRING *ns )
3970 const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
3971 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
3972 return str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap, prefix, localname, ns );
3975 /**************************************************************************
3976 * WsReadQualifiedName [webservices.@]
3978 HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
3979 WS_XML_STRING *localname, WS_XML_STRING *ns,
3980 WS_ERROR *error )
3982 struct reader *reader = (struct reader *)handle;
3983 HRESULT hr;
3985 TRACE( "%p %p %p %p %p %p\n", handle, heap, prefix, localname, ns, error );
3986 if (error) FIXME( "ignoring error parameter\n" );
3988 if (!reader || !heap) return E_INVALIDARG;
3990 EnterCriticalSection( &reader->cs );
3992 if (reader->magic != READER_MAGIC)
3994 LeaveCriticalSection( &reader->cs );
3995 return E_INVALIDARG;
3998 if (!reader->input_type)
4000 LeaveCriticalSection( &reader->cs );
4001 return WS_E_INVALID_OPERATION;
4004 if (!localname)
4006 LeaveCriticalSection( &reader->cs );
4007 return E_INVALIDARG;
4010 if (reader->state != READER_STATE_TEXT)
4012 LeaveCriticalSection( &reader->cs );
4013 return WS_E_INVALID_FORMAT;
4016 hr = read_qualified_name( reader, heap, prefix, localname, ns );
4018 LeaveCriticalSection( &reader->cs );
4019 return hr;
4022 static const int month_offsets[2][12] =
4024 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
4025 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
4028 static inline int valid_day( int year, int month, int day )
4030 return day > 0 && day <= month_days[leap_year( year )][month - 1];
4033 static inline int leap_days_before( int year )
4035 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
4038 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
4040 const unsigned char *p = bytes, *q;
4041 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
4043 while (len && read_isspace( *p )) { p++; len--; }
4044 while (len && read_isspace( p[len - 1] )) { len--; }
4046 q = p;
4047 while (len && isdigit( *q )) { q++; len--; };
4048 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
4049 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
4050 if (year < 1) return WS_E_INVALID_FORMAT;
4052 p = ++q; len--;
4053 while (len && isdigit( *q )) { q++; len--; };
4054 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
4055 month = (p[0] - '0') * 10 + p[1] - '0';
4056 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
4058 p = ++q; len--;
4059 while (len && isdigit( *q )) { q++; len--; };
4060 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
4061 day = (p[0] - '0') * 10 + p[1] - '0';
4062 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
4064 p = ++q; len--;
4065 while (len && isdigit( *q )) { q++; len--; };
4066 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4067 hour = (p[0] - '0') * 10 + p[1] - '0';
4068 if (hour > 24) return WS_E_INVALID_FORMAT;
4070 p = ++q; len--;
4071 while (len && isdigit( *q )) { q++; len--; };
4072 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4073 min = (p[0] - '0') * 10 + p[1] - '0';
4074 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
4076 p = ++q; len--;
4077 while (len && isdigit( *q )) { q++; len--; };
4078 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
4079 sec = (p[0] - '0') * 10 + p[1] - '0';
4080 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
4082 if (*q == '.')
4084 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
4085 p = ++q; len--;
4086 while (len && isdigit( *q )) { q++; len--; };
4087 nb_digits = q - p;
4088 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
4089 for (i = 0; i < nb_digits; i++)
4091 sec_frac += (p[i] - '0') * mul;
4092 mul /= 10;
4095 if (*q == 'Z')
4097 if (--len) return WS_E_INVALID_FORMAT;
4098 tz_hour = tz_min = tz_neg = 0;
4099 ret->format = WS_DATETIME_FORMAT_UTC;
4101 else if (*q == '+' || *q == '-')
4103 tz_neg = (*q == '-') ? 1 : 0;
4105 p = ++q; len--;
4106 while (len && isdigit( *q )) { q++; len--; };
4107 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4108 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
4109 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
4111 p = ++q; len--;
4112 while (len && isdigit( *q )) { q++; len--; };
4113 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
4114 tz_min = (p[0] - '0') * 10 + p[1] - '0';
4115 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
4117 ret->format = WS_DATETIME_FORMAT_LOCAL;
4119 else return WS_E_INVALID_FORMAT;
4121 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
4122 ret->ticks += month_offsets[leap_year( year )][month - 1] * TICKS_PER_DAY;
4123 ret->ticks += (day - 1) * TICKS_PER_DAY;
4124 ret->ticks += hour * TICKS_PER_HOUR;
4125 ret->ticks += min * TICKS_PER_MIN;
4126 ret->ticks += sec * TICKS_PER_SEC;
4127 ret->ticks += sec_frac;
4129 if (tz_neg)
4131 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
4132 return WS_E_INVALID_FORMAT;
4133 ret->ticks += tz_hour * TICKS_PER_HOUR;
4134 ret->ticks += tz_min * TICKS_PER_MIN;
4136 else
4138 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
4139 return WS_E_INVALID_FORMAT;
4140 ret->ticks -= tz_hour * TICKS_PER_HOUR;
4141 ret->ticks -= tz_min * TICKS_PER_MIN;
4144 return S_OK;
4147 /**************************************************************************
4148 * WsDateTimeToFileTime [webservices.@]
4150 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
4152 unsigned __int64 ticks;
4154 TRACE( "%p %p %p\n", dt, ft, error );
4155 if (error) FIXME( "ignoring error parameter\n" );
4157 if (!dt || !ft) return E_INVALIDARG;
4159 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
4160 ticks = dt->ticks - TICKS_1601_01_01;
4161 ft->dwHighDateTime = ticks >> 32;
4162 ft->dwLowDateTime = (DWORD)ticks;
4163 return S_OK;
4166 /**************************************************************************
4167 * WsFileTimeToDateTime [webservices.@]
4169 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
4171 unsigned __int64 ticks;
4173 TRACE( "%p %p %p\n", ft, dt, error );
4174 if (error) FIXME( "ignoring error parameter\n" );
4176 if (!dt || !ft) return E_INVALIDARG;
4178 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
4179 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
4180 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
4181 dt->ticks = ticks + TICKS_1601_01_01;
4182 dt->format = WS_DATETIME_FORMAT_UTC;
4183 return S_OK;
4186 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
4187 const WS_XML_STRING *ns, ULONG *index )
4189 ULONG i;
4190 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4192 if (!localname)
4194 *index = reader->current_attr;
4195 return TRUE;
4197 for (i = 0; i < elem->attributeCount; i++)
4199 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
4200 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
4202 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
4203 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
4205 *index = i;
4206 return TRUE;
4209 return FALSE;
4212 /**************************************************************************
4213 * WsFindAttribute [webservices.@]
4215 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
4216 const WS_XML_STRING *ns, BOOL required, ULONG *index,
4217 WS_ERROR *error )
4219 struct reader *reader = (struct reader *)handle;
4220 HRESULT hr = S_OK;
4222 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
4223 required, index, error );
4224 if (error) FIXME( "ignoring error parameter\n" );
4226 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
4228 EnterCriticalSection( &reader->cs );
4230 if (reader->magic != READER_MAGIC)
4232 LeaveCriticalSection( &reader->cs );
4233 return E_INVALIDARG;
4236 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
4238 LeaveCriticalSection( &reader->cs );
4239 return WS_E_INVALID_OPERATION;
4242 if (!find_attribute( reader, localname, ns, index ))
4244 if (required) hr = WS_E_INVALID_FORMAT;
4245 else
4247 *index = ~0u;
4248 hr = S_FALSE;
4252 LeaveCriticalSection( &reader->cs );
4253 return hr;
4256 static HRESULT get_node_text( struct reader *reader, const WS_XML_TEXT **ret )
4258 WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
4259 *ret = node->text;
4260 return S_OK;
4263 static HRESULT get_attribute_text( struct reader *reader, ULONG index, const WS_XML_TEXT **ret )
4265 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4266 *ret = elem->attributes[index]->value;
4267 return S_OK;
4270 static BOOL match_element( const struct node *node, const WS_XML_STRING *localname, const WS_XML_STRING *ns )
4272 const WS_XML_ELEMENT_NODE *elem = (const WS_XML_ELEMENT_NODE *)node;
4273 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
4274 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
4275 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
4278 static HRESULT read_next_node( struct reader *reader )
4280 if (reader->current == reader->last) return read_node( reader );
4281 if (move_to_child_node( &reader->current )) return S_OK;
4282 if (move_to_next_node( &reader->current )) return S_OK;
4283 if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
4284 if (move_to_next_node( &reader->current )) return S_OK;
4285 return WS_E_INVALID_FORMAT;
4288 static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
4289 const WS_XML_STRING *ns, const WS_XML_TEXT **ret, BOOL *found )
4291 switch (mapping)
4293 case WS_ATTRIBUTE_TYPE_MAPPING:
4295 ULONG index;
4296 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
4297 return get_attribute_text( reader, index, ret );
4299 case WS_ELEMENT_TYPE_MAPPING:
4300 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
4301 case WS_ANY_ELEMENT_TYPE_MAPPING:
4303 *found = TRUE;
4304 if (localname)
4306 HRESULT hr;
4307 if (!match_element( reader->current, localname, ns ))
4309 *found = FALSE;
4310 return S_OK;
4312 if ((hr = read_next_node( reader )) != S_OK) return hr;
4313 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4315 if (!move_to_parent_element( &reader->current )) return WS_E_INVALID_FORMAT;
4316 *found = FALSE;
4317 return S_OK;
4320 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4322 *found = FALSE;
4323 return S_OK;
4325 return get_node_text( reader, ret );
4327 default:
4328 FIXME( "mapping %u not supported\n", mapping );
4329 return E_NOTIMPL;
4333 static HRESULT text_to_bool( const WS_XML_TEXT *text, BOOL *val )
4335 HRESULT hr;
4337 switch (text->textType)
4339 case WS_XML_TEXT_TYPE_UTF8:
4341 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4342 hr = str_to_bool( text_utf8->value.bytes, text_utf8->value.length, val );
4343 break;
4345 case WS_XML_TEXT_TYPE_BOOL:
4347 const WS_XML_BOOL_TEXT *text_bool = (const WS_XML_BOOL_TEXT *)text;
4348 *val = text_bool->value;
4349 hr = S_OK;
4350 break;
4352 default:
4353 FIXME( "unhandled text type %u\n", text->textType );
4354 return E_NOTIMPL;
4357 return hr;
4360 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
4361 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4362 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
4363 WS_HEAP *heap, void *ret, ULONG size )
4365 const WS_XML_TEXT *text;
4366 HRESULT hr;
4367 BOOL found, val = FALSE;
4369 if (desc)
4371 FIXME( "description not supported\n" );
4372 return E_NOTIMPL;
4374 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4375 if (found && (hr = text_to_bool( text, &val )) != S_OK) return hr;
4377 switch (option)
4379 case WS_READ_REQUIRED_VALUE:
4380 if (!found) return WS_E_INVALID_FORMAT;
4381 /* fall through */
4383 case WS_READ_NILLABLE_VALUE:
4384 if (size != sizeof(val)) return E_INVALIDARG;
4385 *(BOOL *)ret = val;
4386 break;
4388 case WS_READ_REQUIRED_POINTER:
4389 if (!found) return WS_E_INVALID_FORMAT;
4390 /* fall through */
4392 case WS_READ_OPTIONAL_POINTER:
4393 case WS_READ_NILLABLE_POINTER:
4395 BOOL *heap_val = NULL;
4396 if (size != sizeof(heap_val)) return E_INVALIDARG;
4397 if (found)
4399 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4400 *heap_val = val;
4402 *(BOOL **)ret = heap_val;
4403 break;
4405 default:
4406 FIXME( "read option %u not supported\n", option );
4407 return E_NOTIMPL;
4410 return S_OK;
4413 static HRESULT text_to_int8( const WS_XML_TEXT *text, INT64 *val )
4415 HRESULT hr;
4417 switch (text->textType)
4419 case WS_XML_TEXT_TYPE_UTF8:
4421 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4422 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT8, MAX_INT8, val );
4423 break;
4425 case WS_XML_TEXT_TYPE_INT32:
4427 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4428 assert( text_int32->value >= MIN_INT8 );
4429 assert( text_int32->value <= MAX_INT8 );
4430 *val = text_int32->value;
4431 hr = S_OK;
4432 break;
4434 default:
4435 FIXME( "unhandled text type %u\n", text->textType );
4436 return E_NOTIMPL;
4439 return hr;
4442 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
4443 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4444 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
4445 WS_HEAP *heap, void *ret, ULONG size )
4447 const WS_XML_TEXT *text;
4448 HRESULT hr;
4449 INT64 val = 0;
4450 BOOL found;
4452 if (desc)
4454 FIXME( "description not supported\n" );
4455 return E_NOTIMPL;
4457 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4458 if (found && (hr = text_to_int8( text, &val )) != S_OK) return hr;
4460 switch (option)
4462 case WS_READ_REQUIRED_VALUE:
4463 if (!found) return WS_E_INVALID_FORMAT;
4464 /* fall through */
4466 case WS_READ_NILLABLE_VALUE:
4467 if (size != sizeof(INT8)) return E_INVALIDARG;
4468 *(INT8 *)ret = val;
4469 break;
4471 case WS_READ_REQUIRED_POINTER:
4472 if (!found) return WS_E_INVALID_FORMAT;
4473 /* fall through */
4475 case WS_READ_OPTIONAL_POINTER:
4476 case WS_READ_NILLABLE_POINTER:
4478 INT8 *heap_val = NULL;
4479 if (size != sizeof(heap_val)) return E_INVALIDARG;
4480 if (found)
4482 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4483 *heap_val = val;
4485 *(INT8 **)ret = heap_val;
4486 break;
4488 default:
4489 FIXME( "read option %u not supported\n", option );
4490 return E_NOTIMPL;
4493 return S_OK;
4496 static HRESULT text_to_int16( const WS_XML_TEXT *text, INT64 *val )
4498 HRESULT hr;
4500 switch (text->textType)
4502 case WS_XML_TEXT_TYPE_UTF8:
4504 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4505 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT16, MAX_INT16, val );
4506 break;
4508 case WS_XML_TEXT_TYPE_INT32:
4510 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4511 assert( text_int32->value >= MIN_INT16 );
4512 assert( text_int32->value <= MAX_INT16 );
4513 *val = text_int32->value;
4514 hr = S_OK;
4515 break;
4517 default:
4518 FIXME( "unhandled text type %u\n", text->textType );
4519 return E_NOTIMPL;
4522 return hr;
4525 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
4526 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4527 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
4528 WS_HEAP *heap, void *ret, ULONG size )
4530 const WS_XML_TEXT *text;
4531 HRESULT hr;
4532 INT64 val = 0;
4533 BOOL found;
4535 if (desc)
4537 FIXME( "description not supported\n" );
4538 return E_NOTIMPL;
4540 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4541 if (found && (hr = text_to_int16( text, &val )) != S_OK) return hr;
4543 switch (option)
4545 case WS_READ_REQUIRED_VALUE:
4546 if (!found) return WS_E_INVALID_FORMAT;
4547 /* fall through */
4549 case WS_READ_NILLABLE_VALUE:
4550 if (size != sizeof(INT16)) return E_INVALIDARG;
4551 *(INT16 *)ret = val;
4552 break;
4554 case WS_READ_REQUIRED_POINTER:
4555 if (!found) return WS_E_INVALID_FORMAT;
4556 /* fall through */
4558 case WS_READ_OPTIONAL_POINTER:
4559 case WS_READ_NILLABLE_POINTER:
4561 INT16 *heap_val = NULL;
4562 if (size != sizeof(heap_val)) return E_INVALIDARG;
4563 if (found)
4565 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4566 *heap_val = val;
4568 *(INT16 **)ret = heap_val;
4569 break;
4571 default:
4572 FIXME( "read option %u not supported\n", option );
4573 return E_NOTIMPL;
4576 return S_OK;
4579 static HRESULT text_to_int32( const WS_XML_TEXT *text, INT64 *val )
4581 HRESULT hr;
4583 switch (text->textType)
4585 case WS_XML_TEXT_TYPE_UTF8:
4587 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4588 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT32, MAX_INT32, val );
4589 break;
4591 case WS_XML_TEXT_TYPE_INT32:
4593 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4594 *val = text_int32->value;
4595 hr = S_OK;
4596 break;
4598 default:
4599 FIXME( "unhandled text type %u\n", text->textType );
4600 return E_NOTIMPL;
4603 return hr;
4606 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
4607 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4608 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
4609 WS_HEAP *heap, void *ret, ULONG size )
4611 const WS_XML_TEXT *text;
4612 HRESULT hr;
4613 INT64 val = 0;
4614 BOOL found;
4616 if (desc)
4618 FIXME( "description not supported\n" );
4619 return E_NOTIMPL;
4621 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4622 if (found && (hr = text_to_int32( text, &val )) != S_OK) return hr;
4624 switch (option)
4626 case WS_READ_REQUIRED_VALUE:
4627 if (!found) return WS_E_INVALID_FORMAT;
4628 /* fall through */
4630 case WS_READ_NILLABLE_VALUE:
4631 if (size != sizeof(INT32)) return E_INVALIDARG;
4632 *(INT32 *)ret = val;
4633 break;
4635 case WS_READ_REQUIRED_POINTER:
4636 if (!found) return WS_E_INVALID_FORMAT;
4637 /* fall through */
4639 case WS_READ_OPTIONAL_POINTER:
4640 case WS_READ_NILLABLE_POINTER:
4642 INT32 *heap_val = NULL;
4643 if (size != sizeof(heap_val)) return E_INVALIDARG;
4644 if (found)
4646 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4647 *heap_val = val;
4649 *(INT32 **)ret = heap_val;
4650 break;
4652 default:
4653 FIXME( "read option %u not supported\n", option );
4654 return E_NOTIMPL;
4657 return S_OK;
4660 static HRESULT text_to_int64( const WS_XML_TEXT *text, INT64 *val )
4662 HRESULT hr;
4664 switch (text->textType)
4666 case WS_XML_TEXT_TYPE_UTF8:
4668 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4669 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT64, MAX_INT64, val );
4670 break;
4672 case WS_XML_TEXT_TYPE_INT64:
4674 const WS_XML_INT64_TEXT *text_int64 = (const WS_XML_INT64_TEXT *)text;
4675 *val = text_int64->value;
4676 hr = S_OK;
4677 break;
4679 default:
4680 FIXME( "unhandled text type %u\n", text->textType );
4681 return E_NOTIMPL;
4684 return hr;
4687 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
4688 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4689 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
4690 WS_HEAP *heap, void *ret, ULONG size )
4692 const WS_XML_TEXT *text;
4693 HRESULT hr;
4694 INT64 val = 0;
4695 BOOL found;
4697 if (desc)
4699 FIXME( "description not supported\n" );
4700 return E_NOTIMPL;
4702 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4703 if (found && (hr = text_to_int64( text, &val )) != S_OK) return hr;
4705 switch (option)
4707 case WS_READ_REQUIRED_VALUE:
4708 if (!found) return WS_E_INVALID_FORMAT;
4709 /* fall through */
4711 case WS_READ_NILLABLE_VALUE:
4712 if (size != sizeof(val)) return E_INVALIDARG;
4713 *(INT64 *)ret = val;
4714 break;
4716 case WS_READ_REQUIRED_POINTER:
4717 if (!found) return WS_E_INVALID_FORMAT;
4718 /* fall through */
4720 case WS_READ_OPTIONAL_POINTER:
4721 case WS_READ_NILLABLE_POINTER:
4723 INT64 *heap_val = NULL;
4724 if (size != sizeof(heap_val)) return E_INVALIDARG;
4725 if (found)
4727 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4728 *heap_val = val;
4730 *(INT64 **)ret = heap_val;
4731 break;
4733 default:
4734 FIXME( "read option %u not supported\n", option );
4735 return E_NOTIMPL;
4738 return S_OK;
4741 static HRESULT text_to_uint8( const WS_XML_TEXT *text, UINT64 *val )
4743 HRESULT hr;
4745 switch (text->textType)
4747 case WS_XML_TEXT_TYPE_UTF8:
4749 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4750 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT8, val );
4751 break;
4753 case WS_XML_TEXT_TYPE_UINT64:
4755 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4756 assert( text_uint64->value <= MAX_UINT8 );
4757 *val = text_uint64->value;
4758 hr = S_OK;
4759 break;
4761 default:
4762 FIXME( "unhandled text type %u\n", text->textType );
4763 return E_NOTIMPL;
4766 return hr;
4769 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
4770 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4771 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
4772 WS_HEAP *heap, void *ret, ULONG size )
4774 const WS_XML_TEXT *text;
4775 HRESULT hr;
4776 UINT64 val = 0;
4777 BOOL found;
4779 if (desc)
4781 FIXME( "description not supported\n" );
4782 return E_NOTIMPL;
4784 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4785 if (found && (hr = text_to_uint8( text, &val )) != S_OK) return hr;
4787 switch (option)
4789 case WS_READ_REQUIRED_VALUE:
4790 if (!found) return WS_E_INVALID_FORMAT;
4791 /* fall through */
4793 case WS_READ_NILLABLE_VALUE:
4794 if (size != sizeof(UINT8)) return E_INVALIDARG;
4795 *(UINT8 *)ret = val;
4796 break;
4798 case WS_READ_REQUIRED_POINTER:
4799 if (!found) return WS_E_INVALID_FORMAT;
4800 /* fall through */
4802 case WS_READ_OPTIONAL_POINTER:
4803 case WS_READ_NILLABLE_POINTER:
4805 UINT8 *heap_val = NULL;
4806 if (size != sizeof(heap_val)) return E_INVALIDARG;
4807 if (found)
4809 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4810 *heap_val = val;
4812 *(UINT8 **)ret = heap_val;
4813 break;
4815 default:
4816 FIXME( "read option %u not supported\n", option );
4817 return E_NOTIMPL;
4820 return S_OK;
4823 static HRESULT text_to_uint16( const WS_XML_TEXT *text, UINT64 *val )
4825 HRESULT hr;
4827 switch (text->textType)
4829 case WS_XML_TEXT_TYPE_UTF8:
4831 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4832 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT16, val );
4833 break;
4835 case WS_XML_TEXT_TYPE_INT32:
4837 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4838 assert( text_int32->value >= 0 );
4839 assert( text_int32->value <= MAX_UINT16 );
4840 *val = text_int32->value;
4841 hr = S_OK;
4842 break;
4844 case WS_XML_TEXT_TYPE_UINT64:
4846 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4847 assert( text_uint64->value <= MAX_UINT16 );
4848 *val = text_uint64->value;
4849 hr = S_OK;
4850 break;
4852 default:
4853 FIXME( "unhandled text type %u\n", text->textType );
4854 return E_NOTIMPL;
4857 return hr;
4860 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
4861 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4862 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
4863 WS_HEAP *heap, void *ret, ULONG size )
4865 const WS_XML_TEXT *text;
4866 HRESULT hr;
4867 UINT64 val = 0;
4868 BOOL found;
4870 if (desc)
4872 FIXME( "description not supported\n" );
4873 return E_NOTIMPL;
4875 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4876 if (found && (hr = text_to_uint16( text, &val )) != S_OK) return hr;
4878 switch (option)
4880 case WS_READ_REQUIRED_VALUE:
4881 if (!found) return WS_E_INVALID_FORMAT;
4882 /* fall through */
4884 case WS_READ_NILLABLE_VALUE:
4885 if (size != sizeof(UINT16)) return E_INVALIDARG;
4886 *(UINT16 *)ret = val;
4887 break;
4889 case WS_READ_REQUIRED_POINTER:
4890 if (!found) return WS_E_INVALID_FORMAT;
4891 /* fall through */
4893 case WS_READ_OPTIONAL_POINTER:
4894 case WS_READ_NILLABLE_POINTER:
4896 UINT16 *heap_val = NULL;
4897 if (size != sizeof(heap_val)) return E_INVALIDARG;
4898 if (found)
4900 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4901 *heap_val = val;
4903 *(UINT16 **)ret = heap_val;
4904 break;
4906 default:
4907 FIXME( "read option %u not supported\n", option );
4908 return E_NOTIMPL;
4911 return S_OK;
4914 static HRESULT text_to_uint32( const WS_XML_TEXT *text, UINT64 *val )
4916 HRESULT hr;
4918 switch (text->textType)
4920 case WS_XML_TEXT_TYPE_UTF8:
4922 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4923 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT32, val );
4924 break;
4926 case WS_XML_TEXT_TYPE_INT32:
4928 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4929 assert( text_int32->value >= 0 );
4930 *val = text_int32->value;
4931 hr = S_OK;
4932 break;
4934 case WS_XML_TEXT_TYPE_UINT64:
4936 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4937 assert( text_uint64->value <= MAX_UINT32 );
4938 *val = text_uint64->value;
4939 hr = S_OK;
4940 break;
4942 default:
4943 FIXME( "unhandled text type %u\n", text->textType );
4944 return E_NOTIMPL;
4947 return hr;
4950 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
4951 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4952 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
4953 WS_HEAP *heap, void *ret, ULONG size )
4955 const WS_XML_TEXT *text;
4956 HRESULT hr;
4957 UINT64 val = 0;
4958 BOOL found;
4960 if (desc)
4962 FIXME( "description not supported\n" );
4963 return E_NOTIMPL;
4965 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4966 if (found && (hr = text_to_uint32( text, &val )) != S_OK) return hr;
4968 switch (option)
4970 case WS_READ_REQUIRED_VALUE:
4971 if (!found) return WS_E_INVALID_FORMAT;
4972 /* fall through */
4974 case WS_READ_NILLABLE_VALUE:
4975 if (size != sizeof(UINT32)) return E_INVALIDARG;
4976 *(UINT32 *)ret = val;
4977 break;
4979 case WS_READ_REQUIRED_POINTER:
4980 if (!found) return WS_E_INVALID_FORMAT;
4981 /* fall through */
4983 case WS_READ_OPTIONAL_POINTER:
4984 case WS_READ_NILLABLE_POINTER:
4986 UINT32 *heap_val = NULL;
4987 if (size != sizeof(heap_val)) return E_INVALIDARG;
4988 if (found)
4990 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4991 *heap_val = val;
4993 *(UINT32 **)ret = heap_val;
4994 break;
4996 default:
4997 FIXME( "read option %u not supported\n", option );
4998 return E_NOTIMPL;
5001 return S_OK;
5004 static HRESULT text_to_uint64( const WS_XML_TEXT *text, UINT64 *val )
5006 HRESULT hr;
5008 switch (text->textType)
5010 case WS_XML_TEXT_TYPE_UTF8:
5012 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5013 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT64, val );
5014 break;
5016 case WS_XML_TEXT_TYPE_UINT64:
5018 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
5019 *val = text_uint64->value;
5020 hr = S_OK;
5021 break;
5023 default:
5024 FIXME( "unhandled text type %u\n", text->textType );
5025 return E_NOTIMPL;
5028 return hr;
5031 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
5032 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5033 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
5034 WS_HEAP *heap, void *ret, ULONG size )
5036 const WS_XML_TEXT *text;
5037 HRESULT hr;
5038 UINT64 val = 0;
5039 BOOL found;
5041 if (desc)
5043 FIXME( "description not supported\n" );
5044 return E_NOTIMPL;
5046 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5047 if (found && (hr = text_to_uint64( text, &val )) != S_OK) return hr;
5049 switch (option)
5051 case WS_READ_REQUIRED_VALUE:
5052 if (!found) return WS_E_INVALID_FORMAT;
5053 /* fall through */
5055 case WS_READ_NILLABLE_VALUE:
5056 if (size != sizeof(val)) return E_INVALIDARG;
5057 *(UINT64 *)ret = val;
5058 break;
5060 case WS_READ_REQUIRED_POINTER:
5061 if (!found) return WS_E_INVALID_FORMAT;
5062 /* fall through */
5064 case WS_READ_OPTIONAL_POINTER:
5065 case WS_READ_NILLABLE_POINTER:
5067 UINT64 *heap_val = NULL;
5068 if (size != sizeof(heap_val)) return E_INVALIDARG;
5069 if (found)
5071 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5072 *heap_val = val;
5074 *(UINT64 **)ret = heap_val;
5075 break;
5077 default:
5078 FIXME( "read option %u not supported\n", option );
5079 return E_NOTIMPL;
5082 return S_OK;
5085 static HRESULT text_to_float( const WS_XML_TEXT *text, float *val )
5087 HRESULT hr;
5089 switch (text->textType)
5091 case WS_XML_TEXT_TYPE_UTF8:
5093 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5094 hr = str_to_float( text_utf8->value.bytes, text_utf8->value.length, val );
5095 break;
5097 case WS_XML_TEXT_TYPE_FLOAT:
5099 const WS_XML_FLOAT_TEXT *text_float = (const WS_XML_FLOAT_TEXT *)text;
5100 *val = text_float->value;
5101 hr = S_OK;
5102 break;
5104 default:
5105 FIXME( "unhandled text type %u\n", text->textType );
5106 return E_NOTIMPL;
5109 return hr;
5112 static HRESULT read_type_float( struct reader *reader, WS_TYPE_MAPPING mapping,
5113 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5114 const WS_FLOAT_DESCRIPTION *desc, WS_READ_OPTION option,
5115 WS_HEAP *heap, void *ret, ULONG size )
5117 const WS_XML_TEXT *text;
5118 HRESULT hr;
5119 float val = 0.0;
5120 BOOL found;
5122 if (desc) FIXME( "ignoring description\n" );
5124 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5125 if (found && (hr = text_to_float( text, &val )) != S_OK) return hr;
5127 switch (option)
5129 case WS_READ_REQUIRED_VALUE:
5130 if (!found) return WS_E_INVALID_FORMAT;
5131 /* fall through */
5133 case WS_READ_NILLABLE_VALUE:
5134 if (size != sizeof(val)) return E_INVALIDARG;
5135 *(float *)ret = val;
5136 break;
5138 case WS_READ_REQUIRED_POINTER:
5139 if (!found) return WS_E_INVALID_FORMAT;
5140 /* fall through */
5142 case WS_READ_OPTIONAL_POINTER:
5143 case WS_READ_NILLABLE_POINTER:
5145 float *heap_val = NULL;
5146 if (size != sizeof(heap_val)) return E_INVALIDARG;
5147 if (found)
5149 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5150 *heap_val = val;
5152 *(float **)ret = heap_val;
5153 break;
5155 default:
5156 FIXME( "read option %u not supported\n", option );
5157 return E_NOTIMPL;
5160 return S_OK;
5163 static HRESULT text_to_double( const WS_XML_TEXT *text, double *val )
5165 HRESULT hr;
5167 switch (text->textType)
5169 case WS_XML_TEXT_TYPE_UTF8:
5171 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5172 hr = str_to_double( text_utf8->value.bytes, text_utf8->value.length, val );
5173 break;
5175 case WS_XML_TEXT_TYPE_DOUBLE:
5177 const WS_XML_DOUBLE_TEXT *text_double = (const WS_XML_DOUBLE_TEXT *)text;
5178 *val = text_double->value;
5179 hr = S_OK;
5180 break;
5182 default:
5183 FIXME( "unhandled text type %u\n", text->textType );
5184 return E_NOTIMPL;
5187 return hr;
5190 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
5191 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5192 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
5193 WS_HEAP *heap, void *ret, ULONG size )
5195 const WS_XML_TEXT *text;
5196 HRESULT hr;
5197 double val = 0.0;
5198 BOOL found;
5200 if (desc) FIXME( "ignoring description\n" );
5202 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5203 if (found && (hr = text_to_double( text, &val )) != S_OK) return hr;
5205 switch (option)
5207 case WS_READ_REQUIRED_VALUE:
5208 if (!found) return WS_E_INVALID_FORMAT;
5209 /* fall through */
5211 case WS_READ_NILLABLE_VALUE:
5212 if (size != sizeof(val)) return E_INVALIDARG;
5213 *(double *)ret = val;
5214 break;
5216 case WS_READ_REQUIRED_POINTER:
5217 if (!found) return WS_E_INVALID_FORMAT;
5218 /* fall through */
5220 case WS_READ_OPTIONAL_POINTER:
5221 case WS_READ_NILLABLE_POINTER:
5223 double *heap_val = NULL;
5224 if (size != sizeof(heap_val)) return E_INVALIDARG;
5225 if (found)
5227 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5228 *heap_val = val;
5230 *(double **)ret = heap_val;
5231 break;
5233 default:
5234 FIXME( "read option %u not supported\n", option );
5235 return E_NOTIMPL;
5238 return S_OK;
5241 static HRESULT text_to_wsz( const WS_XML_TEXT *text, WS_HEAP *heap, WCHAR **ret )
5243 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5244 int len;
5246 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5247 len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
5248 if (!(*ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
5249 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, *ret, len );
5250 (*ret)[len] = 0;
5251 return S_OK;
5254 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
5255 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5256 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
5257 WS_HEAP *heap, WCHAR **ret, ULONG size )
5259 const WS_XML_TEXT *text;
5260 HRESULT hr;
5261 WCHAR *str = NULL;
5262 BOOL found;
5264 if (desc)
5266 FIXME( "description not supported\n" );
5267 return E_NOTIMPL;
5269 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5270 if (found && (hr = text_to_wsz( text, heap, &str )) != S_OK) return hr;
5272 switch (option)
5274 case WS_READ_REQUIRED_POINTER:
5275 if (!str && !(str = ws_alloc_zero( heap, sizeof(*str) ))) return WS_E_QUOTA_EXCEEDED;
5276 /* fall through */
5278 case WS_READ_OPTIONAL_POINTER:
5279 case WS_READ_NILLABLE_POINTER:
5280 if (size != sizeof(str)) return E_INVALIDARG;
5281 *ret = str;
5282 break;
5284 default:
5285 FIXME( "read option %u not supported\n", option );
5286 return E_NOTIMPL;
5289 return S_OK;
5292 static HRESULT get_enum_value( const WS_XML_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
5294 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5295 ULONG i;
5297 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5298 for (i = 0; i < desc->valueCount; i++)
5300 if (WsXmlStringEquals( &utf8->value, desc->values[i].name, NULL ) == S_OK)
5302 *ret = desc->values[i].value;
5303 return S_OK;
5306 return WS_E_INVALID_FORMAT;
5309 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
5310 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5311 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
5312 WS_HEAP *heap, void *ret, ULONG size )
5314 const WS_XML_TEXT *text;
5315 HRESULT hr;
5316 int val = 0;
5317 BOOL found;
5319 if (!desc) return E_INVALIDARG;
5321 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5322 if (found && (hr = get_enum_value( text, desc, &val )) != S_OK) return hr;
5324 switch (option)
5326 case WS_READ_REQUIRED_VALUE:
5327 if (!found) return WS_E_INVALID_FORMAT;
5328 /* fall through */
5330 case WS_READ_NILLABLE_VALUE:
5331 if (size != sizeof(val)) return E_INVALIDARG;
5332 *(int *)ret = val;
5333 break;
5335 case WS_READ_REQUIRED_POINTER:
5336 if (!found) return WS_E_INVALID_FORMAT;
5337 /* fall through */
5339 case WS_READ_OPTIONAL_POINTER:
5340 case WS_READ_NILLABLE_POINTER:
5342 int *heap_val = NULL;
5343 if (size != sizeof(heap_val)) return E_INVALIDARG;
5344 if (found)
5346 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5347 *heap_val = val;
5349 *(int **)ret = heap_val;
5350 break;
5352 default:
5353 FIXME( "read option %u not supported\n", option );
5354 return E_NOTIMPL;
5357 return S_OK;
5360 static HRESULT text_to_datetime( const WS_XML_TEXT *text, WS_DATETIME *val )
5362 HRESULT hr;
5364 switch (text->textType)
5366 case WS_XML_TEXT_TYPE_UTF8:
5368 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5369 hr = str_to_datetime( text_utf8->value.bytes, text_utf8->value.length, val );
5370 break;
5372 case WS_XML_TEXT_TYPE_DATETIME:
5374 const WS_XML_DATETIME_TEXT *text_datetime = (const WS_XML_DATETIME_TEXT *)text;
5375 *val = text_datetime->value;
5376 hr = S_OK;
5377 break;
5379 default:
5380 FIXME( "unhandled text type %u\n", text->textType );
5381 return E_NOTIMPL;
5384 return hr;
5387 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
5388 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5389 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
5390 WS_HEAP *heap, void *ret, ULONG size )
5392 const WS_XML_TEXT *text;
5393 HRESULT hr;
5394 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
5395 BOOL found;
5397 if (desc) FIXME( "ignoring description\n" );
5399 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5400 if (found && (hr = text_to_datetime( text, &val )) != S_OK) return hr;
5402 switch (option)
5404 case WS_READ_REQUIRED_VALUE:
5405 if (!found) return WS_E_INVALID_FORMAT;
5406 /* fall through */
5408 case WS_READ_NILLABLE_VALUE:
5409 if (size != sizeof(val)) return E_INVALIDARG;
5410 *(WS_DATETIME *)ret = val;
5411 break;
5413 case WS_READ_REQUIRED_POINTER:
5414 if (!found) return WS_E_INVALID_FORMAT;
5415 /* fall through */
5417 case WS_READ_OPTIONAL_POINTER:
5418 case WS_READ_NILLABLE_POINTER:
5420 WS_DATETIME *heap_val = NULL;
5421 if (size != sizeof(heap_val)) return E_INVALIDARG;
5422 if (found)
5424 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5425 *heap_val = val;
5427 *(WS_DATETIME **)ret = heap_val;
5428 break;
5430 default:
5431 FIXME( "read option %u not supported\n", option );
5432 return E_NOTIMPL;
5435 return S_OK;
5438 static HRESULT text_to_guid( const WS_XML_TEXT *text, GUID *val )
5440 HRESULT hr;
5442 switch (text->textType)
5444 case WS_XML_TEXT_TYPE_UTF8:
5446 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5447 hr = str_to_guid( text_utf8->value.bytes, text_utf8->value.length, val );
5448 break;
5450 case WS_XML_TEXT_TYPE_GUID:
5452 const WS_XML_GUID_TEXT *text_guid = (const WS_XML_GUID_TEXT *)text;
5453 *val = text_guid->value;
5454 hr = S_OK;
5455 break;
5457 default:
5458 FIXME( "unhandled text type %u\n", text->textType );
5459 return E_NOTIMPL;
5462 return hr;
5465 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
5466 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5467 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
5468 WS_HEAP *heap, void *ret, ULONG size )
5470 const WS_XML_TEXT *text;
5471 GUID val = {0};
5472 HRESULT hr;
5473 BOOL found;
5475 if (desc) FIXME( "ignoring description\n" );
5477 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5478 if (found && (hr = text_to_guid( text, &val )) != S_OK) return hr;
5480 switch (option)
5482 case WS_READ_REQUIRED_VALUE:
5483 if (!found) return WS_E_INVALID_FORMAT;
5484 /* fall through */
5486 case WS_READ_NILLABLE_VALUE:
5487 if (size != sizeof(val)) return E_INVALIDARG;
5488 *(GUID *)ret = val;
5489 break;
5491 case WS_READ_REQUIRED_POINTER:
5492 if (!found) return WS_E_INVALID_FORMAT;
5493 /* fall through */
5495 case WS_READ_OPTIONAL_POINTER:
5496 case WS_READ_NILLABLE_POINTER:
5498 GUID *heap_val = NULL;
5499 if (size != sizeof(heap_val)) return E_INVALIDARG;
5500 if (found)
5502 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5503 *heap_val = val;
5505 *(GUID **)ret = heap_val;
5506 break;
5508 default:
5509 FIXME( "read option %u not supported\n", option );
5510 return E_NOTIMPL;
5513 return S_OK;
5516 static HRESULT text_to_unique_id( const WS_XML_TEXT *text, WS_HEAP *heap, WS_UNIQUE_ID *val )
5518 HRESULT hr;
5520 switch (text->textType)
5522 case WS_XML_TEXT_TYPE_UTF8:
5524 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5525 hr = str_to_unique_id( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5526 break;
5528 case WS_XML_TEXT_TYPE_UNIQUE_ID:
5530 const WS_XML_UNIQUE_ID_TEXT *text_unique_id = (const WS_XML_UNIQUE_ID_TEXT *)text;
5531 val->guid = text_unique_id->value;
5532 val->uri.length = 0;
5533 val->uri.chars = NULL;
5534 hr = S_OK;
5535 break;
5537 default:
5538 FIXME( "unhandled text type %u\n", text->textType );
5539 return E_NOTIMPL;
5542 return hr;
5545 static HRESULT read_type_unique_id( struct reader *reader, WS_TYPE_MAPPING mapping,
5546 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5547 const WS_UNIQUE_ID_DESCRIPTION *desc, WS_READ_OPTION option,
5548 WS_HEAP *heap, void *ret, ULONG size )
5550 const WS_XML_TEXT *text;
5551 WS_UNIQUE_ID val = {{0}};
5552 HRESULT hr;
5553 BOOL found;
5555 if (desc) FIXME( "ignoring description\n" );
5557 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5558 if (found && (hr = text_to_unique_id( text, heap, &val )) != S_OK) return hr;
5560 switch (option)
5562 case WS_READ_REQUIRED_VALUE:
5563 if (!found) return WS_E_INVALID_FORMAT;
5564 /* fall through */
5566 case WS_READ_NILLABLE_VALUE:
5567 if (size != sizeof(val)) return E_INVALIDARG;
5568 *(WS_UNIQUE_ID *)ret = val;
5569 break;
5571 case WS_READ_REQUIRED_POINTER:
5572 if (!found) return WS_E_INVALID_FORMAT;
5573 /* fall through */
5575 case WS_READ_OPTIONAL_POINTER:
5576 case WS_READ_NILLABLE_POINTER:
5578 WS_UNIQUE_ID *heap_val = NULL;
5579 if (size != sizeof(heap_val)) return E_INVALIDARG;
5580 if (found)
5582 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5583 *heap_val = val;
5585 *(WS_UNIQUE_ID **)ret = heap_val;
5586 break;
5588 default:
5589 FIXME( "read option %u not supported\n", option );
5590 return E_NOTIMPL;
5593 return S_OK;
5596 static HRESULT text_to_string( const WS_XML_TEXT *text, WS_HEAP *heap, WS_STRING *val )
5598 HRESULT hr;
5600 switch (text->textType)
5602 case WS_XML_TEXT_TYPE_UTF8:
5604 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5605 hr = str_to_string( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5606 break;
5608 case WS_XML_TEXT_TYPE_UTF16:
5610 const WS_XML_UTF16_TEXT *text_utf16 = (const WS_XML_UTF16_TEXT *)text;
5611 if (!(val->chars = ws_alloc( heap, text_utf16->byteCount ))) return WS_E_QUOTA_EXCEEDED;
5612 memcpy( val->chars, text_utf16->bytes, text_utf16->byteCount );
5613 val->length = text_utf16->byteCount / sizeof(WCHAR);
5614 hr = S_OK;
5615 break;
5617 default:
5618 FIXME( "unhandled text type %u\n", text->textType );
5619 return E_NOTIMPL;
5622 return hr;
5625 static HRESULT read_type_string( struct reader *reader, WS_TYPE_MAPPING mapping,
5626 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5627 const WS_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
5628 WS_HEAP *heap, void *ret, ULONG size )
5630 const WS_XML_TEXT *text;
5631 WS_STRING val = {0};
5632 HRESULT hr;
5633 BOOL found;
5635 if (desc) FIXME( "ignoring description\n" );
5637 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5638 if (found && (hr = text_to_string( text, heap, &val )) != S_OK) return hr;
5640 switch (option)
5642 case WS_READ_REQUIRED_VALUE:
5643 case WS_READ_NILLABLE_VALUE:
5644 if (size != sizeof(val)) return E_INVALIDARG;
5645 *(WS_STRING *)ret = val;
5646 break;
5648 case WS_READ_REQUIRED_POINTER:
5650 WS_STRING *heap_val;
5651 if (size != sizeof(heap_val)) return E_INVALIDARG;
5652 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5653 *heap_val = val;
5654 *(WS_STRING **)ret = heap_val;
5655 break;
5657 case WS_READ_OPTIONAL_POINTER:
5658 case WS_READ_NILLABLE_POINTER:
5660 WS_STRING *heap_val = NULL;
5661 if (size != sizeof(heap_val)) return E_INVALIDARG;
5662 if (found)
5664 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5665 *heap_val = val;
5667 *(WS_STRING **)ret = heap_val;
5668 break;
5670 default:
5671 FIXME( "read option %u not supported\n", option );
5672 return E_NOTIMPL;
5675 return S_OK;
5678 static HRESULT text_to_bytes( const WS_XML_TEXT *text, WS_HEAP *heap, WS_BYTES *val )
5680 HRESULT hr;
5682 switch (text->textType)
5684 case WS_XML_TEXT_TYPE_UTF8:
5686 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5687 hr = str_to_bytes( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5688 break;
5690 case WS_XML_TEXT_TYPE_BASE64:
5692 const WS_XML_BASE64_TEXT *text_base64 = (const WS_XML_BASE64_TEXT *)text;
5693 if (!(val->bytes = ws_alloc( heap, text_base64->length ))) return WS_E_QUOTA_EXCEEDED;
5694 memcpy( val->bytes, text_base64->bytes, text_base64->length );
5695 val->length = text_base64->length;
5696 hr = S_OK;
5697 break;
5699 default:
5700 FIXME( "unhandled text type %u\n", text->textType );
5701 return E_NOTIMPL;
5704 return hr;
5707 static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
5708 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5709 const WS_BYTES_DESCRIPTION *desc, WS_READ_OPTION option,
5710 WS_HEAP *heap, void *ret, ULONG size )
5712 const WS_XML_TEXT *text;
5713 WS_BYTES val = {0};
5714 HRESULT hr;
5715 BOOL found;
5717 if (desc) FIXME( "ignoring description\n" );
5719 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5720 if (found && (hr = text_to_bytes( text, heap, &val )) != S_OK) return hr;
5722 switch (option)
5724 case WS_READ_REQUIRED_VALUE:
5725 case WS_READ_NILLABLE_VALUE:
5726 if (size != sizeof(val)) return E_INVALIDARG;
5727 *(WS_BYTES *)ret = val;
5728 break;
5730 case WS_READ_REQUIRED_POINTER:
5732 WS_BYTES *heap_val;
5733 if (size != sizeof(heap_val)) return E_INVALIDARG;
5734 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5735 *heap_val = val;
5736 *(WS_BYTES **)ret = heap_val;
5737 break;
5739 case WS_READ_OPTIONAL_POINTER:
5740 case WS_READ_NILLABLE_POINTER:
5742 WS_BYTES *heap_val = NULL;
5743 if (size != sizeof(heap_val)) return E_INVALIDARG;
5744 if (found)
5746 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5747 *heap_val = val;
5749 *(WS_BYTES **)ret = heap_val;
5750 break;
5752 default:
5753 FIXME( "read option %u not supported\n", option );
5754 return E_NOTIMPL;
5757 return S_OK;
5760 static HRESULT text_to_xml_string( const WS_XML_TEXT *text, WS_HEAP *heap, WS_XML_STRING *val )
5762 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5763 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5764 return str_to_xml_string( utf8->value.bytes, utf8->value.length, heap, val );
5767 static HRESULT read_type_xml_string( struct reader *reader, WS_TYPE_MAPPING mapping,
5768 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5769 const WS_XML_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
5770 WS_HEAP *heap, void *ret, ULONG size )
5772 const WS_XML_TEXT *text;
5773 WS_XML_STRING val = {0};
5774 HRESULT hr;
5775 BOOL found;
5777 if (desc) FIXME( "ignoring description\n" );
5779 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5780 if (found && (hr = text_to_xml_string( text, heap, &val )) != S_OK) return hr;
5782 switch (option)
5784 case WS_READ_REQUIRED_VALUE:
5785 case WS_READ_NILLABLE_VALUE:
5786 if (size != sizeof(val)) return E_INVALIDARG;
5787 *(WS_XML_STRING *)ret = val;
5788 break;
5790 case WS_READ_REQUIRED_POINTER:
5792 WS_XML_STRING *heap_val;
5793 if (size != sizeof(heap_val)) return E_INVALIDARG;
5794 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5795 *heap_val = val;
5796 *(WS_XML_STRING **)ret = heap_val;
5797 break;
5799 case WS_READ_OPTIONAL_POINTER:
5800 case WS_READ_NILLABLE_POINTER:
5802 WS_XML_STRING *heap_val = NULL;
5803 if (size != sizeof(heap_val)) return E_INVALIDARG;
5804 if (found)
5806 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5807 *heap_val = val;
5809 *(WS_XML_STRING **)ret = heap_val;
5810 break;
5812 default:
5813 FIXME( "read option %u not supported\n", option );
5814 return E_NOTIMPL;
5817 return S_OK;
5820 static HRESULT text_to_qname( struct reader *reader, const WS_XML_TEXT *text, WS_HEAP *heap, WS_XML_QNAME *val )
5822 HRESULT hr;
5824 switch (text->textType)
5826 case WS_XML_TEXT_TYPE_UTF8:
5828 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5829 hr = str_to_qname( reader, text_utf8->value.bytes, text_utf8->value.length, heap, NULL,
5830 &val->localName, &val->ns );
5831 break;
5833 case WS_XML_TEXT_TYPE_QNAME:
5835 const WS_XML_QNAME_TEXT *text_qname = (const WS_XML_QNAME_TEXT *)text;
5836 if ((hr = copy_xml_string( heap, text_qname->localName, &val->localName )) != S_OK) return hr;
5837 if ((hr = copy_xml_string( heap, text_qname->ns, &val->ns )) != S_OK)
5839 ws_free( heap, val->localName.bytes, val->localName.length );
5840 return hr;
5842 break;
5844 default:
5845 FIXME( "unhandled text type %u\n", text->textType );
5846 return E_NOTIMPL;
5849 return hr;
5852 static HRESULT read_type_qname( struct reader *reader, WS_TYPE_MAPPING mapping,
5853 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5854 const WS_XML_QNAME_DESCRIPTION *desc, WS_READ_OPTION option,
5855 WS_HEAP *heap, void *ret, ULONG size )
5857 const WS_XML_TEXT *text;
5858 WS_XML_QNAME val = {{0}};
5859 HRESULT hr;
5860 BOOL found;
5862 if (desc) FIXME( "ignoring description\n" );
5864 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
5865 if ((hr = read_startelement( reader )) != S_OK) return hr;
5866 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
5868 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5869 if (found && (hr = text_to_qname( reader, text, heap, &val )) != S_OK) return hr;
5871 switch (option)
5873 case WS_READ_REQUIRED_VALUE:
5874 if (!found) return WS_E_INVALID_FORMAT;
5875 /* fall through */
5877 case WS_READ_NILLABLE_VALUE:
5878 if (size != sizeof(val)) return E_INVALIDARG;
5879 *(WS_XML_QNAME *)ret = val;
5880 break;
5882 case WS_READ_REQUIRED_POINTER:
5883 if (!found) return WS_E_INVALID_FORMAT;
5884 /* fall through */
5886 case WS_READ_OPTIONAL_POINTER:
5887 case WS_READ_NILLABLE_POINTER:
5889 WS_XML_QNAME *heap_val = NULL;
5890 if (size != sizeof(heap_val)) return E_INVALIDARG;
5891 if (found)
5893 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5894 *heap_val = val;
5896 *(WS_XML_QNAME **)ret = heap_val;
5897 break;
5899 default:
5900 FIXME( "read option %u not supported\n", option );
5901 return E_NOTIMPL;
5904 return S_OK;
5907 static BOOL is_empty_text_node( const struct node *node )
5909 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
5911 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
5912 switch (text->text->textType)
5914 case WS_XML_TEXT_TYPE_UTF8:
5916 ULONG i;
5917 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
5918 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
5919 return TRUE;
5921 case WS_XML_TEXT_TYPE_BASE64:
5923 const WS_XML_BASE64_TEXT *base64 = (const WS_XML_BASE64_TEXT *)text->text;
5924 return !base64->length;
5926 case WS_XML_TEXT_TYPE_BOOL:
5927 case WS_XML_TEXT_TYPE_INT32:
5928 case WS_XML_TEXT_TYPE_INT64:
5929 case WS_XML_TEXT_TYPE_UINT64:
5930 case WS_XML_TEXT_TYPE_FLOAT:
5931 case WS_XML_TEXT_TYPE_DOUBLE:
5932 case WS_XML_TEXT_TYPE_DECIMAL:
5933 case WS_XML_TEXT_TYPE_GUID:
5934 case WS_XML_TEXT_TYPE_UNIQUE_ID:
5935 case WS_XML_TEXT_TYPE_DATETIME:
5936 return FALSE;
5938 default:
5939 ERR( "unhandled text type %u\n", text->text->textType );
5940 return FALSE;
5944 /* skips comment and empty text nodes */
5945 static HRESULT read_type_next_node( struct reader *reader )
5947 for (;;)
5949 HRESULT hr;
5950 WS_XML_NODE_TYPE type;
5952 if ((hr = read_next_node( reader )) != S_OK) return hr;
5953 type = node_type( reader->current );
5954 if (type == WS_XML_NODE_TYPE_COMMENT ||
5955 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
5956 return S_OK;
5960 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
5961 const WS_XML_STRING *ns )
5963 struct node *node;
5964 ULONG attr;
5965 HRESULT hr;
5967 if (!localname) return S_OK; /* assume reader is already correctly positioned */
5968 if (reader->current == reader->last)
5970 BOOL found;
5971 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
5972 if (!found) return WS_E_INVALID_FORMAT;
5974 if (match_element( reader->current, localname, ns )) return S_OK;
5976 node = reader->current;
5977 attr = reader->current_attr;
5979 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
5980 if (match_element( reader->current, localname, ns )) return S_OK;
5982 reader->current = node;
5983 reader->current_attr = attr;
5985 return WS_E_INVALID_FORMAT;
5988 ULONG get_type_size( WS_TYPE type, const void *desc )
5990 switch (type)
5992 case WS_INT8_TYPE:
5993 case WS_UINT8_TYPE:
5994 return sizeof(INT8);
5996 case WS_INT16_TYPE:
5997 case WS_UINT16_TYPE:
5998 return sizeof(INT16);
6000 case WS_BOOL_TYPE:
6001 case WS_INT32_TYPE:
6002 case WS_UINT32_TYPE:
6003 case WS_ENUM_TYPE:
6004 return sizeof(INT32);
6006 case WS_INT64_TYPE:
6007 case WS_UINT64_TYPE:
6008 return sizeof(INT64);
6010 case WS_FLOAT_TYPE:
6011 return sizeof(float);
6013 case WS_DOUBLE_TYPE:
6014 return sizeof(double);
6016 case WS_DATETIME_TYPE:
6017 return sizeof(WS_DATETIME);
6019 case WS_GUID_TYPE:
6020 return sizeof(GUID);
6022 case WS_UNIQUE_ID_TYPE:
6023 return sizeof(WS_UNIQUE_ID);
6025 case WS_STRING_TYPE:
6026 return sizeof(WS_STRING);
6028 case WS_WSZ_TYPE:
6029 return sizeof(WCHAR *);
6031 case WS_BYTES_TYPE:
6032 return sizeof(WS_BYTES);
6034 case WS_XML_STRING_TYPE:
6035 return sizeof(WS_XML_STRING);
6037 case WS_XML_QNAME_TYPE:
6038 return sizeof(WS_XML_QNAME);
6040 case WS_DESCRIPTION_TYPE:
6041 return sizeof(WS_STRUCT_DESCRIPTION *);
6043 case WS_STRUCT_TYPE:
6045 const WS_STRUCT_DESCRIPTION *desc_struct = desc;
6046 return desc_struct->size;
6048 case WS_UNION_TYPE:
6050 const WS_UNION_DESCRIPTION *desc_union = desc;
6051 return desc_union->size;
6053 default:
6054 ERR( "unhandled type %u\n", type );
6055 return 0;
6059 static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
6061 if (options & WS_FIELD_POINTER)
6063 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
6064 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
6065 return WS_READ_REQUIRED_POINTER;
6068 switch (type)
6070 case WS_BOOL_TYPE:
6071 case WS_INT8_TYPE:
6072 case WS_INT16_TYPE:
6073 case WS_INT32_TYPE:
6074 case WS_INT64_TYPE:
6075 case WS_UINT8_TYPE:
6076 case WS_UINT16_TYPE:
6077 case WS_UINT32_TYPE:
6078 case WS_UINT64_TYPE:
6079 case WS_FLOAT_TYPE:
6080 case WS_DOUBLE_TYPE:
6081 case WS_DATETIME_TYPE:
6082 case WS_GUID_TYPE:
6083 case WS_UNIQUE_ID_TYPE:
6084 case WS_STRING_TYPE:
6085 case WS_BYTES_TYPE:
6086 case WS_XML_STRING_TYPE:
6087 case WS_XML_QNAME_TYPE:
6088 case WS_STRUCT_TYPE:
6089 case WS_ENUM_TYPE:
6090 case WS_UNION_TYPE:
6091 if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
6092 return WS_READ_REQUIRED_VALUE;
6094 case WS_WSZ_TYPE:
6095 case WS_DESCRIPTION_TYPE:
6096 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
6097 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
6098 return WS_READ_REQUIRED_POINTER;
6100 default:
6101 FIXME( "unhandled type %u\n", type );
6102 return 0;
6106 static HRESULT read_type_field( struct reader *, const WS_FIELD_DESCRIPTION *, WS_HEAP *, char *, ULONG );
6108 static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_READ_OPTION option,
6109 WS_HEAP *heap, void *ret, ULONG size )
6111 BOOL found = FALSE;
6112 HRESULT hr;
6113 ULONG i;
6115 switch (option)
6117 case WS_READ_REQUIRED_VALUE:
6118 case WS_READ_NILLABLE_VALUE:
6119 if (size != desc->size) return E_INVALIDARG;
6120 break;
6122 default:
6123 return E_INVALIDARG;
6126 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6127 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
6128 for (i = 0; i < desc->fieldCount; i++)
6130 if ((found = match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns )))
6131 break;
6134 if (!found) *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
6135 else
6137 ULONG offset = desc->fields[i]->field.offset;
6138 if ((hr = read_type_field( reader, &desc->fields[i]->field, heap, ret, offset )) == S_OK)
6139 *(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
6142 switch (option)
6144 case WS_READ_NILLABLE_VALUE:
6145 if (!found) move_to_parent_element( &reader->current );
6146 break;
6148 case WS_READ_REQUIRED_VALUE:
6149 if (!found) hr = WS_E_INVALID_FORMAT;
6150 break;
6152 default:
6153 return E_INVALIDARG;
6156 return hr;
6159 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
6160 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
6161 void *, ULONG );
6163 static HRESULT read_type_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
6164 void **ret, ULONG *count )
6166 HRESULT hr;
6167 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
6168 WS_READ_OPTION option;
6169 char *buf;
6171 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
6173 /* wrapper element */
6174 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
6175 return hr;
6177 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
6178 item_size = get_type_size( desc->type, desc->typeDescription );
6179 else
6180 item_size = sizeof(void *);
6182 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
6183 for (;;)
6185 if (nb_items >= nb_allocated)
6187 SIZE_T old_size = nb_allocated * item_size, new_size = old_size * 2;
6188 if (!(buf = ws_realloc_zero( heap, buf, old_size, new_size ))) return WS_E_QUOTA_EXCEEDED;
6189 nb_allocated *= 2;
6192 if (desc->type == WS_UNION_TYPE)
6193 hr = read_type_union( reader, desc->typeDescription, option, heap, buf + offset, item_size );
6194 else
6195 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
6196 desc->typeDescription, option, heap, buf + offset, item_size );
6198 if (hr == WS_E_INVALID_FORMAT) break;
6199 if (hr != S_OK)
6201 ws_free( heap, buf, nb_allocated * item_size );
6202 return hr;
6204 offset += item_size;
6205 nb_items++;
6208 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
6210 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
6212 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
6213 desc->itemRange->maxItemCount );
6214 ws_free( heap, buf, nb_allocated * item_size );
6215 return WS_E_INVALID_FORMAT;
6218 *count = nb_items;
6219 *ret = buf;
6221 return S_OK;
6224 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
6225 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
6227 HRESULT hr;
6228 if (reader->current == reader->last)
6230 BOOL found;
6231 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
6232 if (!found) return WS_E_INVALID_FORMAT;
6234 if ((hr = read_next_node( reader )) != S_OK) return hr;
6235 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
6237 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
6238 desc->typeDescription, option, heap, ret, size );
6241 static HRESULT read_type_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, char *buf,
6242 ULONG offset )
6244 char *ptr;
6245 WS_READ_OPTION option;
6246 ULONG size;
6247 HRESULT hr;
6249 if (!desc) return E_INVALIDARG;
6250 if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE|WS_FIELD_NILLABLE_ITEM))
6252 FIXME( "options %08x not supported\n", desc->options );
6253 return E_NOTIMPL;
6255 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
6257 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
6258 size = get_type_size( desc->type, desc->typeDescription );
6259 else
6260 size = sizeof(void *);
6262 ptr = buf + offset;
6263 switch (desc->mapping)
6265 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING:
6266 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
6267 return S_OK;
6269 case WS_ATTRIBUTE_FIELD_MAPPING:
6270 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
6271 desc->typeDescription, option, heap, ptr, size );
6272 break;
6274 case WS_ELEMENT_FIELD_MAPPING:
6275 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
6276 desc->typeDescription, option, heap, ptr, size );
6277 break;
6279 case WS_ELEMENT_CHOICE_FIELD_MAPPING:
6280 if (desc->type != WS_UNION_TYPE || !desc->typeDescription ||
6281 (desc->options & (WS_FIELD_POINTER|WS_FIELD_NILLABLE))) return E_INVALIDARG;
6282 hr = read_type_union( reader, desc->typeDescription, option, heap, ptr, size );
6283 break;
6285 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
6286 case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING:
6288 ULONG count;
6289 hr = read_type_array( reader, desc, heap, (void **)ptr, &count );
6290 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
6291 break;
6293 case WS_TEXT_FIELD_MAPPING:
6294 hr = read_type_text( reader, desc, option, heap, ptr, size );
6295 break;
6297 default:
6298 FIXME( "unhandled field mapping %u\n", desc->mapping );
6299 return E_NOTIMPL;
6302 if (hr == WS_E_INVALID_FORMAT)
6304 switch (option)
6306 case WS_READ_REQUIRED_VALUE:
6307 case WS_READ_REQUIRED_POINTER:
6308 return WS_E_INVALID_FORMAT;
6310 case WS_READ_NILLABLE_VALUE:
6311 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
6312 return S_OK;
6314 case WS_READ_OPTIONAL_POINTER:
6315 case WS_READ_NILLABLE_POINTER:
6316 *(void **)ptr = NULL;
6317 return S_OK;
6319 default:
6320 ERR( "unhandled option %u\n", option );
6321 return E_NOTIMPL;
6325 return hr;
6328 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
6329 const WS_XML_STRING *ns, const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
6330 WS_HEAP *heap, void *ret, ULONG size )
6332 ULONG i, offset;
6333 HRESULT hr;
6334 char *buf;
6336 if (!desc) return E_INVALIDARG;
6337 if (desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6339 FIXME( "struct options %08x not supported\n",
6340 desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT );
6343 switch (option)
6345 case WS_READ_REQUIRED_POINTER:
6346 case WS_READ_OPTIONAL_POINTER:
6347 case WS_READ_NILLABLE_POINTER:
6348 if (size != sizeof(void *)) return E_INVALIDARG;
6349 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
6350 break;
6352 case WS_READ_REQUIRED_VALUE:
6353 case WS_READ_NILLABLE_VALUE:
6354 if (size != desc->size) return E_INVALIDARG;
6355 buf = ret;
6356 break;
6358 default:
6359 FIXME( "unhandled read option %u\n", option );
6360 return E_NOTIMPL;
6363 for (i = 0; i < desc->fieldCount; i++)
6365 offset = desc->fields[i]->offset;
6366 if ((hr = read_type_field( reader, desc->fields[i], heap, buf, offset )) != S_OK) break;
6369 switch (option)
6371 case WS_READ_REQUIRED_POINTER:
6372 if (hr != S_OK)
6374 ws_free( heap, buf, desc->size );
6375 return hr;
6377 *(char **)ret = buf;
6378 break;
6380 case WS_READ_OPTIONAL_POINTER:
6381 case WS_READ_NILLABLE_POINTER:
6382 if (is_nil_value( buf, desc->size ))
6384 ws_free( heap, buf, desc->size );
6385 buf = NULL;
6387 *(char **)ret = buf;
6388 break;
6390 case WS_READ_REQUIRED_VALUE:
6391 case WS_READ_NILLABLE_VALUE:
6392 if (hr != S_OK) return hr;
6393 break;
6395 default:
6396 ERR( "unhandled read option %u\n", option );
6397 return E_NOTIMPL;
6400 if (desc->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6402 struct node *parent = find_parent( reader );
6403 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
6405 return S_OK;
6408 static HRESULT start_mapping( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
6409 const WS_XML_STRING *ns )
6411 switch (mapping)
6413 case WS_ELEMENT_TYPE_MAPPING:
6414 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
6415 return read_type_next_element_node( reader, localname, ns );
6417 case WS_ANY_ELEMENT_TYPE_MAPPING:
6418 case WS_ATTRIBUTE_TYPE_MAPPING:
6419 return S_OK;
6421 default:
6422 FIXME( "unhandled mapping %u\n", mapping );
6423 return E_NOTIMPL;
6427 static HRESULT read_type_endelement_node( struct reader *reader )
6429 const struct node *parent = find_parent( reader );
6430 HRESULT hr;
6432 for (;;)
6434 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6435 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == parent)
6437 return S_OK;
6439 if (read_end_of_data( reader ) || !(parent->flags & NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT)) break;
6442 return WS_E_INVALID_FORMAT;
6445 static HRESULT end_mapping( struct reader *reader, WS_TYPE_MAPPING mapping )
6447 switch (mapping)
6449 case WS_ELEMENT_TYPE_MAPPING:
6450 return read_type_endelement_node( reader );
6452 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
6453 return read_type_next_node( reader );
6455 case WS_ATTRIBUTE_TYPE_MAPPING:
6456 default:
6457 return S_OK;
6461 static BOOL is_true_text( const WS_XML_TEXT *text )
6463 switch (text->textType)
6465 case WS_XML_TEXT_TYPE_UTF8:
6467 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
6468 if (text_utf8->value.length == 4 && !memcmp( text_utf8->value.bytes, "true", 4 )) return TRUE;
6469 return FALSE;
6471 case WS_XML_TEXT_TYPE_BOOL:
6473 const WS_XML_BOOL_TEXT *text_bool = (const WS_XML_BOOL_TEXT *)text;
6474 return text_bool->value;
6476 default:
6477 ERR( "unhandled text type %u\n", text->textType );
6478 return FALSE;
6482 static HRESULT is_nil_element( const WS_XML_ELEMENT_NODE *elem )
6484 static const WS_XML_STRING localname = {3, (BYTE *)"nil"};
6485 static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance"};
6486 ULONG i;
6488 for (i = 0; i < elem->attributeCount; i++)
6490 if (elem->attributes[i]->isXmlNs) continue;
6491 if (WsXmlStringEquals( elem->attributes[i]->localName, &localname, NULL ) == S_OK &&
6492 WsXmlStringEquals( elem->attributes[i]->ns, &ns, NULL ) == S_OK &&
6493 is_true_text( elem->attributes[i]->value )) return TRUE;
6495 return FALSE;
6498 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
6499 const WS_XML_STRING *localname, const WS_XML_STRING *ns, const void *desc,
6500 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size )
6502 HRESULT hr;
6504 if ((hr = start_mapping( reader, mapping, localname, ns )) != S_OK) return hr;
6506 if (mapping == WS_ELEMENT_TYPE_MAPPING && is_nil_element( &reader->current->hdr ))
6508 if (option != WS_READ_NILLABLE_POINTER && option != WS_READ_NILLABLE_VALUE) return WS_E_INVALID_FORMAT;
6509 return end_mapping( reader, mapping );
6512 switch (type)
6514 case WS_BOOL_TYPE:
6515 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6516 return hr;
6517 break;
6519 case WS_INT8_TYPE:
6520 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6521 return hr;
6522 break;
6524 case WS_INT16_TYPE:
6525 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6526 return hr;
6527 break;
6529 case WS_INT32_TYPE:
6530 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6531 return hr;
6532 break;
6534 case WS_INT64_TYPE:
6535 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6536 return hr;
6537 break;
6539 case WS_UINT8_TYPE:
6540 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6541 return hr;
6542 break;
6544 case WS_UINT16_TYPE:
6545 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6546 return hr;
6547 break;
6549 case WS_UINT32_TYPE:
6550 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6551 return hr;
6552 break;
6554 case WS_UINT64_TYPE:
6555 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6556 return hr;
6557 break;
6559 case WS_FLOAT_TYPE:
6560 if ((hr = read_type_float( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6561 return hr;
6562 break;
6564 case WS_DOUBLE_TYPE:
6565 if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6566 return hr;
6567 break;
6569 case WS_DATETIME_TYPE:
6570 if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6571 return hr;
6572 break;
6574 case WS_GUID_TYPE:
6575 if ((hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6576 return hr;
6577 break;
6579 case WS_UNIQUE_ID_TYPE:
6580 if ((hr = read_type_unique_id( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6581 return hr;
6582 break;
6584 case WS_STRING_TYPE:
6585 if ((hr = read_type_string( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6586 return hr;
6587 break;
6589 case WS_WSZ_TYPE:
6590 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6591 return hr;
6592 break;
6594 case WS_BYTES_TYPE:
6595 if ((hr = read_type_bytes( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6596 return hr;
6597 break;
6599 case WS_XML_STRING_TYPE:
6600 if ((hr = read_type_xml_string( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6601 return hr;
6602 break;
6604 case WS_XML_QNAME_TYPE:
6605 if ((hr = read_type_qname( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6606 return hr;
6607 break;
6609 case WS_STRUCT_TYPE:
6610 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6611 return hr;
6612 break;
6614 case WS_ENUM_TYPE:
6615 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6616 return hr;
6617 break;
6619 default:
6620 FIXME( "type %u not supported\n", type );
6621 return E_NOTIMPL;
6624 return end_mapping( reader, mapping );
6627 /**************************************************************************
6628 * WsReadType [webservices.@]
6630 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
6631 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
6632 ULONG size, WS_ERROR *error )
6634 struct reader *reader = (struct reader *)handle;
6635 HRESULT hr;
6637 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
6638 size, error );
6639 if (error) FIXME( "ignoring error parameter\n" );
6641 if (!reader || !value) return E_INVALIDARG;
6643 EnterCriticalSection( &reader->cs );
6645 if (reader->magic != READER_MAGIC)
6647 LeaveCriticalSection( &reader->cs );
6648 return E_INVALIDARG;
6651 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
6653 LeaveCriticalSection( &reader->cs );
6654 return hr;
6657 switch (mapping)
6659 case WS_ELEMENT_TYPE_MAPPING:
6660 hr = read_node( reader );
6661 break;
6663 default:
6664 break;
6667 if (hr == S_OK && !read_end_of_data( reader )) hr = WS_E_INVALID_FORMAT;
6669 LeaveCriticalSection( &reader->cs );
6670 return hr;
6673 HRESULT read_header( WS_XML_READER *handle, const WS_XML_STRING *localname, const WS_XML_STRING *ns,
6674 WS_TYPE type, const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
6675 ULONG size )
6677 struct reader *reader = (struct reader *)handle;
6678 HRESULT hr;
6680 EnterCriticalSection( &reader->cs );
6682 if (reader->magic != READER_MAGIC)
6684 LeaveCriticalSection( &reader->cs );
6685 return E_INVALIDARG;
6688 hr = read_type( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, localname, ns, desc, option, heap,
6689 value, size );
6691 LeaveCriticalSection( &reader->cs );
6692 return hr;
6695 /**************************************************************************
6696 * WsReadElement [webservices.@]
6698 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
6699 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
6700 WS_ERROR *error )
6702 struct reader *reader = (struct reader *)handle;
6703 HRESULT hr;
6705 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
6706 if (error) FIXME( "ignoring error parameter\n" );
6708 if (!reader || !desc || !value) return E_INVALIDARG;
6710 EnterCriticalSection( &reader->cs );
6712 if (reader->magic != READER_MAGIC)
6714 LeaveCriticalSection( &reader->cs );
6715 return E_INVALIDARG;
6718 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
6719 desc->elementNs, desc->typeDescription, option, heap, value, size );
6721 LeaveCriticalSection( &reader->cs );
6722 return hr;
6725 /**************************************************************************
6726 * WsReadValue [webservices.@]
6728 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
6729 WS_ERROR *error )
6731 struct reader *reader = (struct reader *)handle;
6732 WS_TYPE type = map_value_type( value_type );
6733 HRESULT hr;
6735 TRACE( "%p %u %p %u %p\n", handle, type, value, size, error );
6736 if (error) FIXME( "ignoring error parameter\n" );
6738 if (!reader || !value || type == ~0u) return E_INVALIDARG;
6740 EnterCriticalSection( &reader->cs );
6742 if (reader->magic != READER_MAGIC)
6744 LeaveCriticalSection( &reader->cs );
6745 return E_INVALIDARG;
6748 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
6749 NULL, value, size );
6751 LeaveCriticalSection( &reader->cs );
6752 return hr;
6755 /**************************************************************************
6756 * WsReadAttribute [webservices.@]
6758 HRESULT WINAPI WsReadAttribute( WS_XML_READER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
6759 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
6760 WS_ERROR *error )
6762 struct reader *reader = (struct reader *)handle;
6763 HRESULT hr;
6765 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
6766 if (error) FIXME( "ignoring error parameter\n" );
6768 if (!reader || !desc || !value) return E_INVALIDARG;
6770 EnterCriticalSection( &reader->cs );
6772 if (reader->magic != READER_MAGIC)
6774 LeaveCriticalSection( &reader->cs );
6775 return E_INVALIDARG;
6778 if (!reader->input_type)
6780 LeaveCriticalSection( &reader->cs );
6781 return WS_E_INVALID_OPERATION;
6784 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->attributeLocalName,
6785 desc->attributeNs, desc->typeDescription, option, heap, value, size );
6787 LeaveCriticalSection( &reader->cs );
6788 return hr;
6791 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
6793 static const char bom[] = {0xef,0xbb,0xbf};
6794 const unsigned char *p = data;
6796 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
6797 (size > 2 && !(*offset = 0));
6800 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
6802 static const char bom[] = {0xff,0xfe};
6803 const unsigned char *p = data;
6805 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
6806 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
6809 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
6811 WS_CHARSET ret = 0;
6813 /* FIXME: parse xml declaration */
6815 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
6816 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
6817 else
6819 FIXME( "charset not recognized\n" );
6820 return 0;
6823 TRACE( "detected charset %u\n", ret );
6824 return ret;
6827 static void set_input_buffer( struct reader *reader, struct xmlbuf *buf, const unsigned char *data, ULONG size )
6829 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
6830 reader->input_buf = buf;
6831 reader->input_data = data;
6832 reader->input_size = size;
6834 reader->read_size = reader->input_size;
6835 reader->read_pos = 0;
6836 reader->read_bufptr = reader->input_data;
6838 reader->text_conv_offset = 0;
6841 /**************************************************************************
6842 * WsSetInput [webservices.@]
6844 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
6845 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
6846 ULONG count, WS_ERROR *error )
6848 struct reader *reader = (struct reader *)handle;
6849 struct node *node;
6850 ULONG i, offset = 0;
6851 HRESULT hr;
6853 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
6854 if (error) FIXME( "ignoring error parameter\n" );
6856 if (!reader) return E_INVALIDARG;
6858 EnterCriticalSection( &reader->cs );
6860 if (reader->magic != READER_MAGIC)
6862 LeaveCriticalSection( &reader->cs );
6863 return E_INVALIDARG;
6866 for (i = 0; i < count; i++)
6868 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
6869 properties[i].valueSize );
6870 if (hr != S_OK) goto done;
6873 if ((hr = init_reader( reader )) != S_OK) goto done;
6875 switch (encoding->encodingType)
6877 case WS_XML_READER_ENCODING_TYPE_TEXT:
6879 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
6880 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
6882 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
6884 FIXME( "charset detection on input type %u not supported\n", input->inputType );
6885 hr = E_NOTIMPL;
6886 goto done;
6889 if (text->charSet != WS_CHARSET_AUTO) reader->input_charset = text->charSet;
6890 else reader->input_charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
6892 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
6893 break;
6895 case WS_XML_READER_ENCODING_TYPE_BINARY:
6897 WS_XML_READER_BINARY_ENCODING *bin = (WS_XML_READER_BINARY_ENCODING *)encoding;
6898 reader->input_enc = WS_XML_READER_ENCODING_TYPE_BINARY;
6899 reader->input_charset = 0;
6900 reader->dict_static = bin->staticDictionary ? bin->staticDictionary : &dict_builtin_static.dict;
6901 reader->dict = bin->dynamicDictionary ? bin->dynamicDictionary : &dict_builtin.dict;
6902 break;
6904 default:
6905 FIXME( "encoding type %u not supported\n", encoding->encodingType );
6906 hr = E_NOTIMPL;
6907 goto done;
6910 switch (input->inputType)
6912 case WS_XML_READER_INPUT_TYPE_BUFFER:
6914 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
6915 set_input_buffer( reader, NULL, (const unsigned char *)buf->encodedData + offset,
6916 buf->encodedDataSize - offset );
6917 break;
6919 default:
6920 FIXME( "input type %u not supported\n", input->inputType );
6921 hr = E_NOTIMPL;
6922 goto done;
6925 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
6926 else read_insert_bof( reader, node );
6928 done:
6929 LeaveCriticalSection( &reader->cs );
6930 return hr;
6933 /**************************************************************************
6934 * WsSetInputToBuffer [webservices.@]
6936 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
6937 const WS_XML_READER_PROPERTY *properties, ULONG count,
6938 WS_ERROR *error )
6940 struct reader *reader = (struct reader *)handle;
6941 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
6942 struct node *node;
6943 HRESULT hr;
6944 ULONG i;
6946 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
6947 if (error) FIXME( "ignoring error parameter\n" );
6949 if (!reader || !xmlbuf) return E_INVALIDARG;
6951 EnterCriticalSection( &reader->cs );
6953 if (reader->magic != READER_MAGIC)
6955 LeaveCriticalSection( &reader->cs );
6956 return E_INVALIDARG;
6959 for (i = 0; i < count; i++)
6961 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
6962 properties[i].valueSize );
6963 if (hr != S_OK) goto done;
6966 if ((hr = init_reader( reader )) != S_OK) goto done;
6968 reader->input_enc = xmlbuf->encoding;
6969 reader->input_charset = xmlbuf->charset;
6970 reader->dict_static = xmlbuf->dict_static;
6971 reader->dict = xmlbuf->dict;
6972 set_input_buffer( reader, xmlbuf, xmlbuf->bytes.bytes, xmlbuf->bytes.length );
6974 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
6975 else read_insert_bof( reader, node );
6977 done:
6978 LeaveCriticalSection( &reader->cs );
6979 return hr;
6982 /**************************************************************************
6983 * WsGetReaderPosition [webservices.@]
6985 HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
6987 struct reader *reader = (struct reader *)handle;
6989 TRACE( "%p %p %p\n", handle, pos, error );
6990 if (error) FIXME( "ignoring error parameter\n" );
6992 if (!reader || !pos) return E_INVALIDARG;
6994 EnterCriticalSection( &reader->cs );
6996 if (reader->magic != READER_MAGIC)
6998 LeaveCriticalSection( &reader->cs );
6999 return E_INVALIDARG;
7002 if (!reader->input_buf)
7004 LeaveCriticalSection( &reader->cs );
7005 return WS_E_INVALID_OPERATION;
7008 pos->buffer = (WS_XML_BUFFER *)reader->input_buf;
7009 pos->node = reader->current;
7011 LeaveCriticalSection( &reader->cs );
7012 return S_OK;
7015 /**************************************************************************
7016 * WsSetReaderPosition [webservices.@]
7018 HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
7020 struct reader *reader = (struct reader *)handle;
7022 TRACE( "%p %p %p\n", handle, pos, error );
7023 if (error) FIXME( "ignoring error parameter\n" );
7025 if (!reader || !pos) return E_INVALIDARG;
7027 EnterCriticalSection( &reader->cs );
7029 if (reader->magic != READER_MAGIC || (struct xmlbuf *)pos->buffer != reader->input_buf)
7031 LeaveCriticalSection( &reader->cs );
7032 return E_INVALIDARG;
7035 if (!reader->input_buf)
7037 LeaveCriticalSection( &reader->cs );
7038 return WS_E_INVALID_OPERATION;
7041 reader->current = pos->node;
7043 LeaveCriticalSection( &reader->cs );
7044 return S_OK;
7047 static HRESULT utf8_to_base64( const WS_XML_UTF8_TEXT *utf8, WS_XML_BASE64_TEXT *base64 )
7049 if (utf8->value.length % 4) return WS_E_INVALID_FORMAT;
7050 if (!(base64->bytes = heap_alloc( utf8->value.length * 3 / 4 ))) return E_OUTOFMEMORY;
7051 base64->length = decode_base64( utf8->value.bytes, utf8->value.length, base64->bytes );
7052 return S_OK;
7055 /**************************************************************************
7056 * WsReadBytes [webservices.@]
7058 HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
7060 struct reader *reader = (struct reader *)handle;
7061 HRESULT hr;
7063 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
7064 if (error) FIXME( "ignoring error parameter\n" );
7066 if (!reader) return E_INVALIDARG;
7068 EnterCriticalSection( &reader->cs );
7070 if (reader->magic != READER_MAGIC)
7072 LeaveCriticalSection( &reader->cs );
7073 return E_INVALIDARG;
7076 if (!reader->input_type)
7078 LeaveCriticalSection( &reader->cs );
7079 return WS_E_INVALID_OPERATION;
7082 if (!count)
7084 LeaveCriticalSection( &reader->cs );
7085 return E_INVALIDARG;
7088 *count = 0;
7089 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
7091 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7092 WS_XML_BASE64_TEXT base64;
7094 if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK)
7096 LeaveCriticalSection( &reader->cs );
7097 return hr;
7099 if (reader->text_conv_offset == base64.length)
7101 heap_free( base64.bytes );
7102 hr = read_node( reader );
7103 LeaveCriticalSection( &reader->cs );
7104 return hr;
7106 *count = min( base64.length - reader->text_conv_offset, max_count );
7107 memcpy( bytes, base64.bytes + reader->text_conv_offset, *count );
7108 reader->text_conv_offset += *count;
7109 heap_free( base64.bytes );
7112 LeaveCriticalSection( &reader->cs );
7113 return S_OK;
7116 static HRESULT utf8_to_utf16( const WS_XML_UTF8_TEXT *utf8, WS_XML_UTF16_TEXT *utf16 )
7118 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
7119 if (!(utf16->bytes = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
7120 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, (WCHAR *)utf16->bytes, len );
7121 utf16->byteCount = len * sizeof(WCHAR);
7122 return S_OK;
7125 /**************************************************************************
7126 * WsReadChars [webservices.@]
7128 HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count, ULONG *count, WS_ERROR *error )
7130 struct reader *reader = (struct reader *)handle;
7132 TRACE( "%p %p %u %p %p\n", handle, chars, max_count, count, error );
7133 if (error) FIXME( "ignoring error parameter\n" );
7135 if (!reader) return E_INVALIDARG;
7137 EnterCriticalSection( &reader->cs );
7139 if (reader->magic != READER_MAGIC)
7141 LeaveCriticalSection( &reader->cs );
7142 return E_INVALIDARG;
7145 if (!reader->input_type)
7147 LeaveCriticalSection( &reader->cs );
7148 return WS_E_INVALID_OPERATION;
7151 if (!count)
7153 LeaveCriticalSection( &reader->cs );
7154 return E_INVALIDARG;
7157 *count = 0;
7158 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && chars)
7160 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7161 WS_XML_UTF16_TEXT utf16;
7162 HRESULT hr;
7164 if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK)
7166 LeaveCriticalSection( &reader->cs );
7167 return hr;
7169 if (reader->text_conv_offset == utf16.byteCount / sizeof(WCHAR))
7171 heap_free( utf16.bytes );
7172 hr = read_node( reader );
7173 LeaveCriticalSection( &reader->cs );
7174 return hr;
7176 *count = min( utf16.byteCount / sizeof(WCHAR) - reader->text_conv_offset, max_count );
7177 memcpy( chars, utf16.bytes + reader->text_conv_offset * sizeof(WCHAR), *count * sizeof(WCHAR) );
7178 reader->text_conv_offset += *count;
7179 heap_free( utf16.bytes );
7182 LeaveCriticalSection( &reader->cs );
7183 return S_OK;
7186 /**************************************************************************
7187 * WsReadCharsUtf8 [webservices.@]
7189 HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
7191 struct reader *reader = (struct reader *)handle;
7192 HRESULT hr;
7194 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
7195 if (error) FIXME( "ignoring error parameter\n" );
7197 if (!reader) return E_INVALIDARG;
7199 EnterCriticalSection( &reader->cs );
7201 if (reader->magic != READER_MAGIC)
7203 LeaveCriticalSection( &reader->cs );
7204 return E_INVALIDARG;
7207 if (!reader->input_type)
7209 LeaveCriticalSection( &reader->cs );
7210 return WS_E_INVALID_OPERATION;
7213 if (!count)
7215 LeaveCriticalSection( &reader->cs );
7216 return E_INVALIDARG;
7219 *count = 0;
7220 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
7222 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7223 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
7225 if (reader->text_conv_offset == utf8->value.length)
7227 hr = read_node( reader );
7228 LeaveCriticalSection( &reader->cs );
7229 return hr;
7231 *count = min( utf8->value.length - reader->text_conv_offset, max_count );
7232 memcpy( bytes, utf8->value.bytes + reader->text_conv_offset, *count );
7233 reader->text_conv_offset += *count;
7236 LeaveCriticalSection( &reader->cs );
7237 return S_OK;
7240 static HRESULT move_to_element( struct reader *reader )
7242 HRESULT hr;
7243 if (node_type( reader->current ) == WS_XML_NODE_TYPE_BOF &&
7244 (hr = read_move_to( reader, WS_MOVE_TO_CHILD_NODE, NULL )) != S_OK) return hr;
7245 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return E_FAIL;
7246 return S_OK;
7249 static HRESULT copy_tree( struct reader *reader, WS_XML_WRITER *writer )
7251 const struct node *node, *parent;
7252 BOOL done = FALSE;
7253 HRESULT hr;
7255 if ((hr = move_to_element( reader )) != S_OK) return hr;
7256 parent = reader->current;
7257 for (;;)
7259 node = reader->current;
7260 if ((hr = WsWriteNode( writer, (const WS_XML_NODE *)node, NULL )) != S_OK) break;
7261 if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT && node->parent == parent) done = TRUE;
7262 if ((hr = read_next_node( reader )) != S_OK || done) break;
7264 return hr;
7267 /**************************************************************************
7268 * WsReadXmlBuffer [webservices.@]
7270 HRESULT WINAPI WsReadXmlBuffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret, WS_ERROR *error )
7272 struct reader *reader = (struct reader *)handle;
7273 WS_XML_WRITER *writer = NULL;
7274 WS_XML_BUFFER *buffer;
7275 HRESULT hr;
7277 TRACE( "%p %p %p %p\n", handle, heap, ret, error );
7278 if (error) FIXME( "ignoring error parameter\n" );
7280 if (!reader || !heap) return E_INVALIDARG;
7281 if (!ret) return E_FAIL;
7283 EnterCriticalSection( &reader->cs );
7285 if (reader->magic != READER_MAGIC)
7287 LeaveCriticalSection( &reader->cs );
7288 return E_INVALIDARG;
7291 if (!reader->input_type)
7293 LeaveCriticalSection( &reader->cs );
7294 return WS_E_INVALID_OPERATION;
7297 if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
7298 if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL )) != S_OK) goto done;
7299 if ((hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL )) != S_OK) goto done;
7300 if ((hr = copy_tree( reader, writer )) == S_OK) *ret = buffer;
7302 done:
7303 if (hr != S_OK) free_xmlbuf( (struct xmlbuf *)buffer );
7304 WsFreeWriter( writer );
7305 LeaveCriticalSection( &reader->cs );
7306 return hr;
7309 HRESULT create_header_buffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret )
7311 struct reader *reader = (struct reader *)handle;
7312 HRESULT hr = WS_E_QUOTA_EXCEEDED;
7313 struct xmlbuf *xmlbuf;
7315 EnterCriticalSection( &reader->cs );
7317 if (reader->magic != READER_MAGIC)
7319 LeaveCriticalSection( &reader->cs );
7320 return E_INVALIDARG;
7323 if ((xmlbuf = alloc_xmlbuf( heap, reader->read_pos, reader->input_enc, reader->input_charset,
7324 reader->dict_static, reader->dict )))
7326 memcpy( xmlbuf->bytes.bytes, reader->read_bufptr, reader->read_pos );
7327 xmlbuf->bytes.length = reader->read_pos;
7328 *ret = (WS_XML_BUFFER *)xmlbuf;
7329 hr = S_OK;
7332 LeaveCriticalSection( &reader->cs );
7333 return hr;
7336 HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *desc, USHORT index, const WS_FIELD_DESCRIPTION **ret )
7338 if (index >= desc->fieldCount) return E_INVALIDARG;
7339 *ret = desc->fields[index];
7340 return S_OK;
7343 static ULONG get_field_size( const WS_FIELD_DESCRIPTION *desc )
7345 if (desc->options & WS_FIELD_POINTER) return sizeof(void *);
7346 return get_type_size( desc->type, desc->typeDescription );
7349 static HRESULT read_param( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, void *ret )
7351 if (!ret && !(ret = ws_alloc_zero( heap, get_field_size(desc) ))) return WS_E_QUOTA_EXCEEDED;
7352 return read_type_field( reader, desc, heap, ret, 0 );
7355 static HRESULT read_param_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
7356 void **ret, ULONG *count )
7358 if (!ret && !(ret = ws_alloc_zero( heap, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED;
7359 return read_type_array( reader, desc, heap, ret, count );
7362 static void set_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, ULONG index, ULONG len,
7363 const void **args )
7365 ULONG i, *ptr;
7366 for (i = 0; i < count; i++)
7368 if (params[i].outputMessageIndex != index || params[i].parameterType != WS_PARAMETER_TYPE_ARRAY_COUNT)
7369 continue;
7370 if ((ptr = *(ULONG **)args[i])) *ptr = len;
7371 break;
7375 HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEMENT_DESCRIPTION *desc,
7376 const WS_PARAMETER_DESCRIPTION *params, ULONG count, const void **args )
7378 struct reader *reader = (struct reader *)handle;
7379 const WS_STRUCT_DESCRIPTION *desc_struct;
7380 const WS_FIELD_DESCRIPTION *desc_field;
7381 ULONG i, len;
7382 HRESULT hr;
7384 if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG;
7386 EnterCriticalSection( &reader->cs );
7388 if (reader->magic != READER_MAGIC)
7390 LeaveCriticalSection( &reader->cs );
7391 return E_INVALIDARG;
7394 if ((hr = start_mapping( reader, WS_ELEMENT_TYPE_MAPPING, desc->elementLocalName, desc->elementNs )) != S_OK)
7395 goto done;
7397 for (i = 0; i < count; i++)
7399 if (params[i].outputMessageIndex == INVALID_PARAMETER_INDEX) continue;
7400 if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES)
7402 FIXME( "messages type not supported\n" );
7403 hr = E_NOTIMPL;
7404 goto done;
7406 if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) goto done;
7407 if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL)
7409 void *ptr = *(void **)args[i];
7410 if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) goto done;
7412 else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY)
7414 void **ptr = *(void ***)args[i];
7415 if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) goto done;
7416 set_array_len( params, count, params[i].outputMessageIndex, len, args );
7420 if (desc_struct->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
7422 struct node *parent = find_parent( reader );
7423 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
7426 hr = end_mapping( reader, WS_ELEMENT_TYPE_MAPPING );
7428 done:
7429 LeaveCriticalSection( &reader->cs );
7430 return hr;