webservices: Accept empty namespace in attribute type mapping.
[wine.git] / dlls / webservices / reader.c
blob4d37a38a8acc5c9c091ae2d0a3856305bbd5fa21
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>
21 #include <float.h>
22 #include <locale.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "webservices.h"
29 #include "wine/debug.h"
30 #include "wine/heap.h"
31 #include "wine/list.h"
32 #include "webservices_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
36 ULONG prop_size( const struct prop_desc *desc, ULONG count )
38 ULONG i, ret = count * sizeof(struct prop);
39 for (i = 0; i < count; i++) ret += desc[i].size;
40 return ret;
43 void prop_init( const struct prop_desc *desc, ULONG count, struct prop *prop, void *data )
45 ULONG i;
46 char *ptr = data;
47 for (i = 0; i < count; i++)
49 prop[i].value = ptr;
50 prop[i].size = desc[i].size;
51 prop[i].readonly = desc[i].readonly;
52 prop[i].writeonly = desc[i].writeonly;
53 ptr += prop[i].size;
57 HRESULT prop_set( const struct prop *prop, ULONG count, ULONG id, const void *value, ULONG size )
59 if (id >= count || size != prop[id].size || prop[id].readonly) return E_INVALIDARG;
60 memcpy( prop[id].value, value, size );
61 return S_OK;
64 HRESULT prop_get( const struct prop *prop, ULONG count, ULONG id, void *buf, ULONG size )
66 if (id >= count || size != prop[id].size || prop[id].writeonly) return E_INVALIDARG;
67 memcpy( buf, prop[id].value, prop[id].size );
68 return S_OK;
71 struct node *alloc_node( WS_XML_NODE_TYPE type )
73 struct node *ret;
75 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
76 ret->hdr.node.nodeType = type;
77 list_init( &ret->entry );
78 list_init( &ret->children );
79 return ret;
82 void free_attribute( WS_XML_ATTRIBUTE *attr )
84 if (!attr) return;
85 free_xml_string( attr->prefix );
86 free_xml_string( attr->localName );
87 free_xml_string( attr->ns );
88 heap_free( attr->value );
89 heap_free( attr );
92 void free_node( struct node *node )
94 if (!node) return;
95 switch (node_type( node ))
97 case WS_XML_NODE_TYPE_ELEMENT:
99 WS_XML_ELEMENT_NODE *elem = &node->hdr;
100 ULONG i;
102 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
103 heap_free( elem->attributes );
104 free_xml_string( elem->prefix );
105 free_xml_string( elem->localName );
106 free_xml_string( elem->ns );
107 break;
109 case WS_XML_NODE_TYPE_TEXT:
111 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
112 heap_free( text->text );
113 break;
115 case WS_XML_NODE_TYPE_COMMENT:
117 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
118 heap_free( comment->value.bytes );
119 break;
121 case WS_XML_NODE_TYPE_CDATA:
122 case WS_XML_NODE_TYPE_END_CDATA:
123 case WS_XML_NODE_TYPE_END_ELEMENT:
124 case WS_XML_NODE_TYPE_EOF:
125 case WS_XML_NODE_TYPE_BOF:
126 break;
128 default:
129 ERR( "unhandled type %u\n", node_type( node ) );
130 break;
132 heap_free( node );
135 void destroy_nodes( struct node *node )
137 struct list *ptr;
139 if (!node) return;
140 while ((ptr = list_head( &node->children )))
142 struct node *child = LIST_ENTRY( ptr, struct node, entry );
143 list_remove( &child->entry );
144 destroy_nodes( child );
146 free_node( node );
149 static WS_XML_ATTRIBUTE *dup_attribute( const WS_XML_ATTRIBUTE *src, WS_XML_WRITER_ENCODING_TYPE enc )
151 WS_XML_ATTRIBUTE *dst;
152 HRESULT hr;
154 if (!(dst = heap_alloc_zero( sizeof(*dst) ))) return NULL;
155 dst->singleQuote = src->singleQuote;
156 dst->isXmlNs = src->isXmlNs;
158 if (src->prefix && !(dst->prefix = dup_xml_string( src->prefix, FALSE ))) goto error;
159 if (src->localName && !(dst->localName = dup_xml_string( src->localName, FALSE ))) goto error;
160 if (src->ns && !(dst->ns = dup_xml_string( src->ns, FALSE ))) goto error;
162 if (src->value)
164 switch (enc)
166 case WS_XML_WRITER_ENCODING_TYPE_BINARY:
167 if ((hr = text_to_text( src->value, NULL, NULL, &dst->value )) != S_OK) goto error;
168 break;
170 case WS_XML_WRITER_ENCODING_TYPE_TEXT:
171 if ((hr = text_to_utf8text( src->value, NULL, NULL, (WS_XML_UTF8_TEXT **)&dst->value )) != S_OK)
172 goto error;
173 break;
175 default:
176 ERR( "unhandled encoding %u\n", enc );
177 goto error;
181 return dst;
183 error:
184 free_attribute( dst );
185 return NULL;
188 static WS_XML_ATTRIBUTE **dup_attributes( WS_XML_ATTRIBUTE * const *src, ULONG count,
189 WS_XML_WRITER_ENCODING_TYPE enc )
191 WS_XML_ATTRIBUTE **dst;
192 ULONG i;
194 if (!(dst = heap_alloc( sizeof(*dst) * count ))) return NULL;
195 for (i = 0; i < count; i++)
197 if (!(dst[i] = dup_attribute( src[i], enc )))
199 for (; i > 0; i--) free_attribute( dst[i - 1] );
200 heap_free( dst );
201 return NULL;
204 return dst;
207 static struct node *dup_element_node( const WS_XML_ELEMENT_NODE *src, WS_XML_WRITER_ENCODING_TYPE enc )
209 struct node *node;
210 WS_XML_ELEMENT_NODE *dst;
211 ULONG count = src->attributeCount;
212 WS_XML_ATTRIBUTE **attrs = src->attributes;
213 const WS_XML_STRING *prefix = (src->prefix && src->prefix->length) ? src->prefix : NULL;
214 const WS_XML_STRING *localname = src->localName;
215 const WS_XML_STRING *ns = src->ns;
217 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
218 dst = &node->hdr;
220 if (count && !(dst->attributes = dup_attributes( attrs, count, enc ))) goto error;
221 dst->attributeCount = count;
223 if (prefix && !(dst->prefix = dup_xml_string( prefix, FALSE ))) goto error;
224 if (localname && !(dst->localName = dup_xml_string( localname, FALSE ))) goto error;
225 if (ns && !(dst->ns = dup_xml_string( ns, FALSE ))) goto error;
226 return node;
228 error:
229 free_node( node );
230 return NULL;
233 static struct node *dup_text_node( const WS_XML_TEXT_NODE *src, WS_XML_WRITER_ENCODING_TYPE enc )
235 struct node *node;
236 WS_XML_TEXT_NODE *dst;
237 HRESULT hr;
239 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
240 dst = (WS_XML_TEXT_NODE *)node;
241 if (!src->text) return node;
243 switch (enc)
245 case WS_XML_WRITER_ENCODING_TYPE_BINARY:
246 hr = text_to_text( src->text, NULL, NULL, &dst->text );
247 break;
249 case WS_XML_WRITER_ENCODING_TYPE_TEXT:
250 hr = text_to_utf8text( src->text, NULL, NULL, (WS_XML_UTF8_TEXT **)&dst->text );
251 break;
253 default:
254 ERR( "unhandled encoding %u\n", enc );
255 free_node( node );
256 return NULL;
259 if (hr != S_OK)
261 free_node( node );
262 return NULL;
265 return node;
268 static struct node *dup_comment_node( const WS_XML_COMMENT_NODE *src )
270 struct node *node;
271 WS_XML_COMMENT_NODE *dst;
273 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return NULL;
274 dst = (WS_XML_COMMENT_NODE *)node;
276 if (src->value.length && !(dst->value.bytes = heap_alloc( src->value.length )))
278 free_node( node );
279 return NULL;
281 memcpy( dst->value.bytes, src->value.bytes, src->value.length );
282 dst->value.length = src->value.length;
283 return node;
286 static struct node *dup_node( const struct node *src, WS_XML_WRITER_ENCODING_TYPE enc )
288 switch (node_type( src ))
290 case WS_XML_NODE_TYPE_ELEMENT:
291 return dup_element_node( &src->hdr, enc );
293 case WS_XML_NODE_TYPE_TEXT:
294 return dup_text_node( (const WS_XML_TEXT_NODE *)src, enc );
296 case WS_XML_NODE_TYPE_COMMENT:
297 return dup_comment_node( (const WS_XML_COMMENT_NODE *)src );
299 case WS_XML_NODE_TYPE_CDATA:
300 case WS_XML_NODE_TYPE_END_CDATA:
301 case WS_XML_NODE_TYPE_END_ELEMENT:
302 case WS_XML_NODE_TYPE_EOF:
303 case WS_XML_NODE_TYPE_BOF:
304 return alloc_node( node_type( src ) );
306 default:
307 ERR( "unhandled type %u\n", node_type( src ) );
308 break;
310 return NULL;
313 static HRESULT dup_tree( const struct node *src, WS_XML_WRITER_ENCODING_TYPE enc, struct node **dst )
315 struct node *parent;
316 const struct node *child;
318 if (!*dst && !(*dst = dup_node( src, enc ))) return E_OUTOFMEMORY;
319 parent = *dst;
321 LIST_FOR_EACH_ENTRY( child, &src->children, struct node, entry )
323 HRESULT hr = E_OUTOFMEMORY;
324 struct node *new_child;
326 if (!(new_child = dup_node( child, enc )) || (hr = dup_tree( child, enc, &new_child )) != S_OK)
328 destroy_nodes( *dst );
329 return hr;
331 new_child->parent = parent;
332 list_add_tail( &parent->children, &new_child->entry );
334 return S_OK;
337 static const struct prop_desc reader_props[] =
339 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
340 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
341 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
342 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
343 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
344 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
345 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
346 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
347 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
348 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
349 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
350 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
351 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
352 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
353 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
356 enum reader_state
358 READER_STATE_INITIAL,
359 READER_STATE_BOF,
360 READER_STATE_STARTELEMENT,
361 READER_STATE_STARTATTRIBUTE,
362 READER_STATE_STARTCDATA,
363 READER_STATE_CDATA,
364 READER_STATE_TEXT,
365 READER_STATE_ENDELEMENT,
366 READER_STATE_ENDCDATA,
367 READER_STATE_COMMENT,
368 READER_STATE_EOF
371 struct prefix
373 WS_XML_STRING *str;
374 WS_XML_STRING *ns;
377 struct reader
379 ULONG magic;
380 CRITICAL_SECTION cs;
381 ULONG read_size;
382 ULONG read_pos;
383 const unsigned char *read_bufptr;
384 enum reader_state state;
385 struct node *root;
386 struct node *current;
387 ULONG current_attr;
388 struct node *last;
389 struct prefix *prefixes;
390 ULONG nb_prefixes;
391 ULONG nb_prefixes_allocated;
392 WS_XML_READER_ENCODING_TYPE input_enc;
393 WS_CHARSET input_charset;
394 WS_XML_READER_INPUT_TYPE input_type;
395 WS_READ_CALLBACK input_cb;
396 void *input_cb_state;
397 struct xmlbuf *input_buf;
398 const unsigned char *input_data;
399 ULONG input_size;
400 ULONG text_conv_offset;
401 unsigned char *stream_buf;
402 const WS_XML_DICTIONARY *dict_static;
403 WS_XML_DICTIONARY *dict;
404 ULONG prop_count;
405 struct prop prop[ARRAY_SIZE( reader_props )];
408 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
410 static struct reader *alloc_reader(void)
412 static const ULONG count = ARRAY_SIZE( reader_props );
413 struct reader *ret;
414 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
416 if (!(ret = heap_alloc_zero( size ))) return NULL;
417 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
419 heap_free( ret );
420 return NULL;
422 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
424 ret->magic = READER_MAGIC;
425 InitializeCriticalSection( &ret->cs );
426 ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": reader.cs");
428 prop_init( reader_props, count, ret->prop, &ret[1] );
429 ret->prop_count = count;
430 return ret;
433 static void clear_prefixes( struct prefix *prefixes, ULONG count )
435 ULONG i;
436 for (i = 0; i < count; i++)
438 free_xml_string( prefixes[i].str );
439 prefixes[i].str = NULL;
440 free_xml_string( prefixes[i].ns );
441 prefixes[i].ns = NULL;
445 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
447 if (str)
449 free_xml_string( prefix->str );
450 if (!(prefix->str = dup_xml_string( str, FALSE ))) return E_OUTOFMEMORY;
452 if (prefix->ns) free_xml_string( prefix->ns );
453 if (!(prefix->ns = dup_xml_string( ns, FALSE ))) return E_OUTOFMEMORY;
454 return S_OK;
457 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
459 ULONG i;
460 HRESULT hr;
462 for (i = 0; i < reader->nb_prefixes; i++)
464 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
465 return set_prefix( &reader->prefixes[i], NULL, ns );
467 if (i >= reader->nb_prefixes_allocated)
469 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
470 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
471 if (!tmp) return E_OUTOFMEMORY;
472 reader->prefixes = tmp;
473 reader->nb_prefixes_allocated *= 2;
475 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
476 reader->nb_prefixes++;
477 return S_OK;
480 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
482 ULONG i;
483 for (i = 0; i < reader->nb_prefixes; i++)
485 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
486 return reader->prefixes[i].ns;
488 return NULL;
491 static void read_insert_eof( struct reader *reader, struct node *eof )
493 if (!reader->root) reader->root = eof;
494 else
496 eof->parent = reader->root;
497 list_add_tail( &reader->root->children, &eof->entry );
499 reader->current = reader->last = eof;
502 static void read_insert_bof( struct reader *reader, struct node *bof )
504 reader->root->parent = bof;
505 list_add_tail( &bof->children, &reader->root->entry );
506 reader->current = reader->last = reader->root = bof;
509 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
511 node->parent = parent;
512 list_add_before( list_tail( &parent->children ), &node->entry );
513 reader->current = reader->last = node;
516 static void free_reader( struct reader *reader )
518 destroy_nodes( reader->root );
519 clear_prefixes( reader->prefixes, reader->nb_prefixes );
520 heap_free( reader->prefixes );
521 heap_free( reader->stream_buf );
523 reader->cs.DebugInfo->Spare[0] = 0;
524 DeleteCriticalSection( &reader->cs );
525 heap_free( reader );
528 static HRESULT init_reader( struct reader *reader )
530 static const WS_XML_STRING empty = {0, NULL};
531 struct node *node;
532 HRESULT hr;
534 reader->state = READER_STATE_INITIAL;
535 destroy_nodes( reader->root );
536 reader->root = reader->current = NULL;
537 reader->current_attr = 0;
538 clear_prefixes( reader->prefixes, reader->nb_prefixes );
539 reader->nb_prefixes = 1;
540 if ((hr = bind_prefix( reader, &empty, &empty )) != S_OK) return hr;
542 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
543 read_insert_eof( reader, node );
544 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
545 reader->input_charset = WS_CHARSET_UTF8;
546 reader->dict_static = NULL;
547 reader->dict = NULL;
548 return S_OK;
551 /**************************************************************************
552 * WsCreateReader [webservices.@]
554 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
555 WS_XML_READER **handle, WS_ERROR *error )
557 struct reader *reader;
558 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
559 BOOL read_decl = TRUE;
560 HRESULT hr;
562 TRACE( "%p %u %p %p\n", properties, count, handle, error );
563 if (error) FIXME( "ignoring error parameter\n" );
565 if (!handle) return E_INVALIDARG;
566 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
568 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
569 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
570 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
571 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
573 for (i = 0; i < count; i++)
575 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
576 properties[i].valueSize );
577 if (hr != S_OK)
579 free_reader( reader );
580 return hr;
584 if ((hr = init_reader( reader )) != S_OK)
586 free_reader( reader );
587 return hr;
590 TRACE( "created %p\n", reader );
591 *handle = (WS_XML_READER *)reader;
592 return S_OK;
595 /**************************************************************************
596 * WsFreeReader [webservices.@]
598 void WINAPI WsFreeReader( WS_XML_READER *handle )
600 struct reader *reader = (struct reader *)handle;
602 TRACE( "%p\n", handle );
604 if (!reader) return;
606 EnterCriticalSection( &reader->cs );
608 if (reader->magic != READER_MAGIC)
610 LeaveCriticalSection( &reader->cs );
611 return;
614 reader->magic = 0;
616 LeaveCriticalSection( &reader->cs );
617 free_reader( reader );
620 static HRESULT read_more_data( struct reader *reader, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
621 WS_ERROR *error )
623 ULONG size = 0, max_size;
625 if (reader->read_size - reader->read_pos >= min_size) return S_OK;
626 if (reader->input_type != WS_XML_READER_INPUT_TYPE_STREAM) return WS_E_INVALID_FORMAT;
627 if (min_size > reader->input_size) return WS_E_QUOTA_EXCEEDED;
629 if (reader->read_pos)
631 memmove( reader->stream_buf, reader->stream_buf + reader->read_pos, reader->read_size - reader->read_pos );
632 reader->read_size -= reader->read_pos;
633 reader->read_pos = 0;
635 max_size = reader->input_size - reader->read_size;
637 reader->input_cb( reader->input_cb_state, reader->stream_buf + reader->read_size, max_size, &size, ctx, error );
638 if (size < min_size) return WS_E_QUOTA_EXCEEDED;
639 reader->read_size += size;
640 return S_OK;
643 /**************************************************************************
644 * WsFillReader [webservices.@]
646 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
647 WS_ERROR *error )
649 struct reader *reader = (struct reader *)handle;
650 HRESULT hr;
652 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
653 if (error) FIXME( "ignoring error parameter\n" );
654 if (ctx) FIXME( "ignoring ctx parameter\n" );
656 if (!reader) return E_INVALIDARG;
658 EnterCriticalSection( &reader->cs );
660 if (reader->magic != READER_MAGIC)
662 LeaveCriticalSection( &reader->cs );
663 return E_INVALIDARG;
666 if (reader->input_type == WS_XML_READER_INPUT_TYPE_STREAM)
668 hr = read_more_data( reader, min_size, ctx, error );
670 else
672 reader->read_size = min( min_size, reader->input_size );
673 reader->read_pos = 0;
674 hr = S_OK;
677 LeaveCriticalSection( &reader->cs );
678 TRACE( "returning %08x\n", hr );
679 return hr;
682 /**************************************************************************
683 * WsGetNamespaceFromPrefix [webservices.@]
685 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
686 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
688 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
689 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
690 static const WS_XML_STRING empty_ns = {0, NULL};
691 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
692 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
693 struct reader *reader = (struct reader *)handle;
694 BOOL found = FALSE;
695 HRESULT hr = S_OK;
697 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
698 if (error) FIXME( "ignoring error parameter\n" );
700 if (!reader || !prefix || !ns) return E_INVALIDARG;
702 EnterCriticalSection( &reader->cs );
704 if (reader->magic != READER_MAGIC)
706 LeaveCriticalSection( &reader->cs );
707 return E_INVALIDARG;
710 if (reader->state != READER_STATE_STARTELEMENT) hr = WS_E_INVALID_OPERATION;
711 else if (!prefix->length)
713 *ns = &empty_ns;
714 found = TRUE;
716 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
718 *ns = &xml_ns;
719 found = TRUE;
721 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
723 *ns = &xmlns_ns;
724 found = TRUE;
726 else
728 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
729 ULONG i;
731 for (i = 0; i < elem->attributeCount; i++)
733 if (!elem->attributes[i]->isXmlNs) continue;
734 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
736 *ns = elem->attributes[i]->ns;
737 found = TRUE;
738 break;
743 LeaveCriticalSection( &reader->cs );
745 if (hr == S_OK && !found)
747 if (required) hr = WS_E_INVALID_FORMAT;
748 else
750 *ns = NULL;
751 hr = S_FALSE;
755 TRACE( "returning %08x\n", hr );
756 return hr;
759 /**************************************************************************
760 * WsGetReaderNode [webservices.@]
762 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
763 WS_ERROR *error )
765 struct reader *reader = (struct reader *)handle;
766 HRESULT hr = S_OK;
768 TRACE( "%p %p %p\n", handle, node, error );
769 if (error) FIXME( "ignoring error parameter\n" );
771 if (!reader || !node) return E_INVALIDARG;
773 EnterCriticalSection( &reader->cs );
775 if (reader->magic != READER_MAGIC)
777 LeaveCriticalSection( &reader->cs );
778 return E_INVALIDARG;
781 *node = &reader->current->hdr.node;
783 LeaveCriticalSection( &reader->cs );
784 TRACE( "returning %08x\n", hr );
785 return S_OK;
788 static HRESULT get_charset( struct reader *reader, void *buf, ULONG size )
790 if (!buf || size != sizeof(reader->input_charset)) return E_INVALIDARG;
791 if (!reader->input_charset) return WS_E_INVALID_FORMAT;
792 *(WS_CHARSET *)buf = reader->input_charset;
793 return S_OK;
796 /**************************************************************************
797 * WsGetReaderProperty [webservices.@]
799 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
800 void *buf, ULONG size, WS_ERROR *error )
802 struct reader *reader = (struct reader *)handle;
803 HRESULT hr;
805 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
806 if (error) FIXME( "ignoring error parameter\n" );
808 if (!reader) return E_INVALIDARG;
810 EnterCriticalSection( &reader->cs );
812 if (reader->magic != READER_MAGIC)
814 LeaveCriticalSection( &reader->cs );
815 return E_INVALIDARG;
818 if (!reader->input_type) hr = WS_E_INVALID_OPERATION;
819 else if (id == WS_XML_READER_PROPERTY_CHARSET) hr = get_charset( reader, buf, size );
820 else hr = prop_get( reader->prop, reader->prop_count, id, buf, size );
822 LeaveCriticalSection( &reader->cs );
823 TRACE( "returning %08x\n", hr );
824 return hr;
827 /**************************************************************************
828 * WsGetXmlAttribute [webservices.@]
830 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
831 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
833 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
834 return E_NOTIMPL;
837 WS_XML_UTF8_TEXT *alloc_utf8_text( const BYTE *data, ULONG len )
839 WS_XML_UTF8_TEXT *ret;
841 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
842 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
843 ret->value.length = len;
844 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
845 ret->value.dictionary = NULL;
846 ret->value.id = 0;
847 if (data) memcpy( ret->value.bytes, data, len );
848 return ret;
851 WS_XML_UTF16_TEXT *alloc_utf16_text( const BYTE *data, ULONG len )
853 WS_XML_UTF16_TEXT *ret;
855 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
856 ret->text.textType = WS_XML_TEXT_TYPE_UTF16;
857 ret->byteCount = len;
858 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
859 if (data) memcpy( ret->bytes, data, len );
860 return ret;
863 WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *data, ULONG len )
865 WS_XML_BASE64_TEXT *ret;
867 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
868 ret->text.textType = WS_XML_TEXT_TYPE_BASE64;
869 ret->length = len;
870 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
871 if (data) memcpy( ret->bytes, data, len );
872 return ret;
875 WS_XML_BOOL_TEXT *alloc_bool_text( BOOL value )
877 WS_XML_BOOL_TEXT *ret;
879 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
880 ret->text.textType = WS_XML_TEXT_TYPE_BOOL;
881 ret->value = value;
882 return ret;
885 WS_XML_INT32_TEXT *alloc_int32_text( INT32 value )
887 WS_XML_INT32_TEXT *ret;
889 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
890 ret->text.textType = WS_XML_TEXT_TYPE_INT32;
891 ret->value = value;
892 return ret;
895 WS_XML_INT64_TEXT *alloc_int64_text( INT64 value )
897 WS_XML_INT64_TEXT *ret;
899 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
900 ret->text.textType = WS_XML_TEXT_TYPE_INT64;
901 ret->value = value;
902 return ret;
905 WS_XML_UINT64_TEXT *alloc_uint64_text( UINT64 value )
907 WS_XML_UINT64_TEXT *ret;
909 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
910 ret->text.textType = WS_XML_TEXT_TYPE_UINT64;
911 ret->value = value;
912 return ret;
915 WS_XML_FLOAT_TEXT *alloc_float_text( float value )
917 WS_XML_FLOAT_TEXT *ret;
919 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
920 ret->text.textType = WS_XML_TEXT_TYPE_FLOAT;
921 ret->value = value;
922 return ret;
925 WS_XML_DOUBLE_TEXT *alloc_double_text( double value )
927 WS_XML_DOUBLE_TEXT *ret;
929 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
930 ret->text.textType = WS_XML_TEXT_TYPE_DOUBLE;
931 ret->value = value;
932 return ret;
935 WS_XML_GUID_TEXT *alloc_guid_text( const GUID *value )
937 WS_XML_GUID_TEXT *ret;
939 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
940 ret->text.textType = WS_XML_TEXT_TYPE_GUID;
941 ret->value = *value;
942 return ret;
945 WS_XML_UNIQUE_ID_TEXT *alloc_unique_id_text( const GUID *value )
947 WS_XML_UNIQUE_ID_TEXT *ret;
949 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
950 ret->text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID;
951 ret->value = *value;
952 return ret;
955 WS_XML_DATETIME_TEXT *alloc_datetime_text( const WS_DATETIME *value )
957 WS_XML_DATETIME_TEXT *ret;
959 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
960 ret->text.textType = WS_XML_TEXT_TYPE_DATETIME;
961 ret->value = *value;
962 return ret;
965 static inline BOOL read_end_of_data( struct reader *reader )
967 return (read_more_data( reader, 1, NULL, NULL ) != S_OK);
970 static inline const unsigned char *read_current_ptr( struct reader *reader )
972 return &reader->read_bufptr[reader->read_pos];
975 static inline void read_skip( struct reader *reader, unsigned int count )
977 assert( reader->read_pos + count <= reader->read_size );
978 reader->read_pos += count;
981 static inline HRESULT read_peek( struct reader *reader, unsigned char *bytes, unsigned int len )
983 HRESULT hr;
984 if ((hr = read_more_data( reader, len, NULL, NULL )) != S_OK) return hr;
985 memcpy( bytes, read_current_ptr( reader ), len );
986 return S_OK;
989 static inline HRESULT read_byte( struct reader *reader, unsigned char *byte )
991 HRESULT hr;
992 if ((hr = read_more_data( reader, 1, NULL, NULL )) != S_OK) return hr;
993 *byte = *read_current_ptr( reader );
994 read_skip( reader, 1 );
995 return S_OK;
998 static inline HRESULT read_bytes( struct reader *reader, unsigned char *bytes, unsigned int len )
1000 HRESULT hr;
1001 if ((hr = read_more_data( reader, len, NULL, NULL )) != S_OK) return hr;
1002 memcpy( bytes, read_current_ptr( reader ), len );
1003 read_skip( reader, len );
1004 return S_OK;
1007 /* UTF-8 support based on libs/wine/utf8.c */
1009 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
1010 static const char utf8_length[128] =
1012 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
1013 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
1014 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
1015 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
1016 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
1017 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
1018 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
1019 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
1022 /* first byte mask depending on UTF-8 sequence length */
1023 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
1025 /* minimum Unicode value depending on UTF-8 sequence length */
1026 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
1028 static inline HRESULT read_utf8_char( struct reader *reader, unsigned int *ret, unsigned int *skip )
1030 unsigned int len;
1031 unsigned char ch;
1032 const unsigned char *end;
1033 HRESULT hr;
1035 if ((hr = read_more_data( reader, 1, NULL, NULL )) != S_OK) return hr;
1036 ch = *read_current_ptr( reader );
1037 if (ch < 0x80)
1039 *ret = ch;
1040 *skip = 1;
1041 return S_OK;
1044 len = utf8_length[ch - 0x80];
1045 if ((hr = read_more_data( reader, len, NULL, NULL )) != S_OK) return hr;
1046 end = read_current_ptr( reader ) + len + 1;
1047 *ret = ch & utf8_mask[len];
1049 switch (len)
1051 case 3:
1052 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
1053 *ret = (*ret << 6) | ch;
1054 case 2:
1055 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
1056 *ret = (*ret << 6) | ch;
1057 case 1:
1058 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
1059 *ret = (*ret << 6) | ch;
1060 if (*ret < utf8_minval[len]) break;
1061 *skip = len + 1;
1062 return S_OK;
1065 return WS_E_INVALID_FORMAT;
1068 static inline BOOL read_isnamechar( unsigned int ch )
1070 /* FIXME: incomplete */
1071 return (ch >= 'A' && ch <= 'Z') ||
1072 (ch >= 'a' && ch <= 'z') ||
1073 (ch >= '0' && ch <= '9') ||
1074 ch == '_' || ch == '-' || ch == '.' || ch == ':';
1077 static inline BOOL read_isspace( unsigned int ch )
1079 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
1082 static inline void read_skip_whitespace( struct reader *reader )
1084 for (;;)
1086 if (read_more_data( reader, 1, NULL, NULL ) != S_OK || !read_isspace( *read_current_ptr( reader ) )) break;
1087 read_skip( reader, 1 );
1091 static inline HRESULT read_cmp( struct reader *reader, const char *str, int len )
1093 const unsigned char *ptr;
1094 HRESULT hr;
1096 if (len < 0) len = strlen( str );
1097 if ((hr = read_more_data( reader, len, NULL, NULL )) != S_OK) return hr;
1099 ptr = read_current_ptr( reader );
1100 while (len--)
1102 if (*str != *ptr) return WS_E_INVALID_FORMAT;
1103 str++; ptr++;
1105 return S_OK;
1108 static HRESULT read_xmldecl( struct reader *reader )
1110 HRESULT hr;
1112 if ((hr = read_more_data( reader, 1, NULL, NULL )) != S_OK) return hr;
1113 if (*read_current_ptr( reader ) != '<' || (hr = read_cmp( reader, "<?", 2 )) != S_OK)
1115 reader->state = READER_STATE_BOF;
1116 return S_OK;
1118 if ((hr = read_cmp( reader, "<?xml ", 6 )) != S_OK) return hr;
1119 read_skip( reader, 6 );
1121 /* FIXME: parse attributes */
1122 for (;;)
1124 if (read_more_data( reader, 1, NULL, NULL ) != S_OK || *read_current_ptr( reader ) == '?' ) break;
1125 read_skip( reader, 1 );
1128 if ((hr = read_cmp( reader, "?>", 2 )) != S_OK) return hr;
1129 read_skip( reader, 2 );
1131 reader->state = READER_STATE_BOF;
1132 return S_OK;
1135 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
1137 if (elem->attributeCount)
1139 WS_XML_ATTRIBUTE **tmp;
1140 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
1141 return E_OUTOFMEMORY;
1142 elem->attributes = tmp;
1144 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
1145 elem->attributes[elem->attributeCount++] = attr;
1146 return S_OK;
1149 static inline void init_xml_string( BYTE *bytes, ULONG len, WS_XML_STRING *str )
1151 str->length = len;
1152 str->bytes = bytes;
1153 str->dictionary = NULL;
1154 str->id = 0;
1157 static HRESULT split_qname( const BYTE *str, ULONG len, WS_XML_STRING *prefix, WS_XML_STRING *localname )
1159 BYTE *prefix_bytes = NULL, *localname_bytes = (BYTE *)str, *ptr = (BYTE *)str;
1160 ULONG prefix_len = 0, localname_len = len;
1162 while (len--)
1164 if (*ptr == ':')
1166 if (ptr == str) return WS_E_INVALID_FORMAT;
1167 prefix_bytes = (BYTE *)str;
1168 prefix_len = ptr - str;
1169 localname_bytes = ptr + 1;
1170 localname_len = len;
1171 break;
1173 ptr++;
1175 if (!localname_len) return WS_E_INVALID_FORMAT;
1177 init_xml_string( prefix_bytes, prefix_len, prefix );
1178 init_xml_string( localname_bytes, localname_len, localname );
1179 return S_OK;
1182 static HRESULT parse_qname( const BYTE *str, ULONG len, WS_XML_STRING **prefix_ret, WS_XML_STRING **localname_ret )
1184 WS_XML_STRING prefix, localname;
1185 HRESULT hr;
1187 if ((hr = split_qname( str, len, &prefix, &localname )) != S_OK) return hr;
1188 if (!(*prefix_ret = alloc_xml_string( NULL, prefix.length ))) return E_OUTOFMEMORY;
1189 if (!(*localname_ret = dup_xml_string( &localname, FALSE )))
1191 free_xml_string( *prefix_ret );
1192 return E_OUTOFMEMORY;
1194 memcpy( (*prefix_ret)->bytes, prefix.bytes, prefix.length );
1195 if (prefix.length && add_xml_string( *prefix_ret ) != S_OK) WARN( "prefix not added to dictionary\n" );
1196 return S_OK;
1199 static int codepoint_to_utf8( int cp, unsigned char *dst )
1201 if (!cp) return -1;
1202 if (cp < 0x80)
1204 *dst = cp;
1205 return 1;
1207 if (cp < 0x800)
1209 dst[1] = 0x80 | (cp & 0x3f);
1210 cp >>= 6;
1211 dst[0] = 0xc0 | cp;
1212 return 2;
1214 if ((cp >= 0xd800 && cp <= 0xdfff) || cp == 0xfffe || cp == 0xffff) return -1;
1215 if (cp < 0x10000)
1217 dst[2] = 0x80 | (cp & 0x3f);
1218 cp >>= 6;
1219 dst[1] = 0x80 | (cp & 0x3f);
1220 cp >>= 6;
1221 dst[0] = 0xe0 | cp;
1222 return 3;
1224 if (cp >= 0x110000) return -1;
1225 dst[3] = 0x80 | (cp & 0x3f);
1226 cp >>= 6;
1227 dst[2] = 0x80 | (cp & 0x3f);
1228 cp >>= 6;
1229 dst[1] = 0x80 | (cp & 0x3f);
1230 cp >>= 6;
1231 dst[0] = 0xf0 | cp;
1232 return 4;
1235 static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char *ret, ULONG *ret_len )
1237 const unsigned char *p = str;
1238 unsigned char *q = ret;
1240 *ret_len = 0;
1241 while (len)
1243 if (*p == '&')
1245 p++; len--;
1246 if (!len) return WS_E_INVALID_FORMAT;
1248 if (len >= 3 && !memcmp( p, "lt;", 3 ))
1250 *q++ = '<';
1251 p += 3;
1252 len -= 3;
1254 else if (len >= 3 && !memcmp( p, "gt;", 3 ))
1256 *q++ = '>';
1257 p += 3;
1258 len -= 3;
1260 else if (len >= 5 && !memcmp( p, "quot;", 5 ))
1262 *q++ = '"';
1263 p += 5;
1264 len -= 5;
1266 else if (len >= 4 && !memcmp( p, "amp;", 4 ))
1268 *q++ = '&';
1269 p += 4;
1270 len -= 4;
1272 else if (len >= 5 && !memcmp( p, "apos;", 5 ))
1274 *q++ = '\'';
1275 p += 5;
1276 len -= 5;
1278 else if (*p == '#')
1280 ULONG start, nb_digits, i;
1281 int len_utf8, cp = 0;
1283 p++; len--;
1284 if (!len) return WS_E_INVALID_FORMAT;
1285 if (*p == 'x')
1287 p++; len--;
1289 start = len;
1290 while (len && isxdigit( *p )) { p++; len--; };
1291 if (!len) return WS_E_INVALID_FORMAT;
1293 p -= nb_digits = start - len;
1294 if (!nb_digits || nb_digits > 6 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1295 for (i = 0; i < nb_digits; i++)
1297 cp *= 16;
1298 if (*p >= '0' && *p <= '9') cp += *p - '0';
1299 else if (*p >= 'a' && *p <= 'f') cp += *p - 'a' + 10;
1300 else cp += *p - 'A' + 10;
1301 p++;
1304 else if (isdigit( *p ))
1306 while (len && *p == '0') { p++; len--; };
1307 if (!len) return WS_E_INVALID_FORMAT;
1309 start = len;
1310 while (len && isdigit( *p )) { p++; len--; };
1311 if (!len) return WS_E_INVALID_FORMAT;
1313 p -= nb_digits = start - len;
1314 if (!nb_digits || nb_digits > 7 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1315 for (i = 0; i < nb_digits; i++)
1317 cp *= 10;
1318 cp += *p - '0';
1319 p++;
1322 else return WS_E_INVALID_FORMAT;
1323 p++; len--;
1324 if ((len_utf8 = codepoint_to_utf8( cp, q )) < 0) return WS_E_INVALID_FORMAT;
1325 *ret_len += len_utf8;
1326 q += len_utf8;
1327 continue;
1329 else return WS_E_INVALID_FORMAT;
1331 else
1333 *q++ = *p++;
1334 len--;
1336 *ret_len += 1;
1338 return S_OK;
1341 static HRESULT read_attribute_value_text( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1343 WS_XML_UTF8_TEXT *utf8;
1344 unsigned int len, ch, skip, quote;
1345 const unsigned char *start;
1346 HRESULT hr;
1348 read_skip_whitespace( reader );
1349 if ((hr = read_cmp( reader, "=", 1 )) != S_OK) return hr;
1350 read_skip( reader, 1 );
1352 read_skip_whitespace( reader );
1353 if ((hr = read_cmp( reader, "\"", 1 )) != S_OK && (hr = read_cmp( reader, "'", 1 )) != S_OK) return hr;
1354 if ((hr = read_utf8_char( reader, &quote, &skip )) != S_OK) return hr;
1355 read_skip( reader, 1 );
1357 len = 0;
1358 start = read_current_ptr( reader );
1359 for (;;)
1361 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
1362 if (ch == quote) break;
1363 read_skip( reader, skip );
1364 len += skip;
1366 read_skip( reader, 1 );
1368 if (attr->isXmlNs)
1370 if (!(attr->ns = alloc_xml_string( start, len ))) return E_OUTOFMEMORY;
1371 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) return hr;
1372 if (!(utf8 = alloc_utf8_text( NULL, 0 ))) return E_OUTOFMEMORY;
1374 else
1376 if (!(utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
1377 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
1379 heap_free( utf8 );
1380 return hr;
1384 attr->value = &utf8->text;
1385 attr->singleQuote = (quote == '\'');
1386 return S_OK;
1389 static inline BOOL is_text_type( unsigned char type )
1391 return (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT);
1394 static HRESULT read_int31( struct reader *reader, ULONG *len )
1396 unsigned char byte;
1397 HRESULT hr;
1399 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1400 *len = byte & 0x7f;
1401 if (!(byte & 0x80)) return S_OK;
1403 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1404 *len += (byte & 0x7f) << 7;
1405 if (!(byte & 0x80)) return S_OK;
1407 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1408 *len += (byte & 0x7f) << 14;
1409 if (!(byte & 0x80)) return S_OK;
1411 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1412 *len += (byte & 0x7f) << 21;
1413 if (!(byte & 0x80)) return S_OK;
1415 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1416 *len += (byte & 0x07) << 28;
1417 return S_OK;
1420 static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
1422 ULONG len;
1423 HRESULT hr;
1424 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
1425 if (!(*str = alloc_xml_string( NULL, len ))) return E_OUTOFMEMORY;
1426 if ((hr = read_bytes( reader, (*str)->bytes, len )) == S_OK)
1428 if (add_xml_string( *str ) != S_OK) WARN( "string not added to dictionary\n" );
1429 return S_OK;
1431 free_xml_string( *str );
1432 return hr;
1435 static HRESULT read_dict_string( struct reader *reader, WS_XML_STRING **str )
1437 const WS_XML_DICTIONARY *dict;
1438 HRESULT hr;
1439 ULONG id;
1441 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1442 dict = (id & 1) ? reader->dict : reader->dict_static;
1443 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1444 if (!(*str = alloc_xml_string( NULL, 0 ))) return E_OUTOFMEMORY;
1445 *(*str) = dict->strings[id];
1446 return S_OK;
1449 static HRESULT read_datetime( struct reader *reader, WS_DATETIME *ret )
1451 UINT64 val;
1452 HRESULT hr;
1454 if ((hr = read_bytes( reader, (unsigned char *)&val, sizeof(val) )) != S_OK) return hr;
1456 if ((val & 0x03) == 1) ret->format = WS_DATETIME_FORMAT_UTC;
1457 else if ((val & 0x03) == 2) ret->format = WS_DATETIME_FORMAT_LOCAL;
1458 else ret->format = WS_DATETIME_FORMAT_NONE;
1460 if ((ret->ticks = val >> 2) > TICKS_MAX) return WS_E_INVALID_FORMAT;
1461 return S_OK;
1464 static HRESULT lookup_string( struct reader *reader, ULONG id, const WS_XML_STRING **ret )
1466 const WS_XML_DICTIONARY *dict = (id & 1) ? reader->dict : reader->dict_static;
1467 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1468 *ret = &dict->strings[id];
1469 return S_OK;
1472 static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1474 WS_XML_UTF8_TEXT *text_utf8 = NULL;
1475 WS_XML_BASE64_TEXT *text_base64 = NULL;
1476 WS_XML_INT32_TEXT *text_int32;
1477 WS_XML_INT64_TEXT *text_int64;
1478 WS_XML_BOOL_TEXT *text_bool;
1479 const WS_XML_STRING *str;
1480 unsigned char type;
1481 UINT8 val_uint8;
1482 UINT16 val_uint16;
1483 INT32 val_int32;
1484 ULONG len = 0, id;
1485 GUID guid;
1486 HRESULT hr;
1488 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1489 if (!is_text_type( type )) return WS_E_INVALID_FORMAT;
1491 switch (type)
1493 case RECORD_ZERO_TEXT:
1495 if (!(text_int32 = alloc_int32_text( 0 ))) return E_OUTOFMEMORY;
1496 attr->value = &text_int32->text;
1497 return S_OK;
1499 case RECORD_ONE_TEXT:
1501 if (!(text_int32 = alloc_int32_text( 1 ))) return E_OUTOFMEMORY;
1502 attr->value = &text_int32->text;
1503 return S_OK;
1505 case RECORD_FALSE_TEXT:
1507 if (!(text_bool = alloc_bool_text( FALSE ))) return E_OUTOFMEMORY;
1508 attr->value = &text_bool->text;
1509 return S_OK;
1511 case RECORD_TRUE_TEXT:
1513 if (!(text_bool = alloc_bool_text( TRUE ))) return E_OUTOFMEMORY;
1514 attr->value = &text_bool->text;
1515 return S_OK;
1517 case RECORD_INT8_TEXT:
1519 INT8 val_int8;
1520 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
1521 if (!(text_int64 = alloc_int64_text( val_int8 ))) return E_OUTOFMEMORY;
1522 attr->value = &text_int64->text;
1523 return S_OK;
1525 case RECORD_INT16_TEXT:
1527 INT16 val_int16;
1528 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
1529 if (!(text_int64 = alloc_int64_text( val_int16 ))) return E_OUTOFMEMORY;
1530 attr->value = &text_int64->text;
1531 return S_OK;
1533 case RECORD_INT32_TEXT:
1534 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1535 if (!(text_int64 = alloc_int64_text( val_int32 ))) return E_OUTOFMEMORY;
1536 attr->value = &text_int64->text;
1537 return S_OK;
1539 case RECORD_INT64_TEXT:
1541 INT64 val_int64;
1542 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
1543 if (!(text_int64 = alloc_int64_text( val_int64 ))) return E_OUTOFMEMORY;
1544 attr->value = &text_int64->text;
1545 return S_OK;
1547 case RECORD_FLOAT_TEXT:
1549 WS_XML_FLOAT_TEXT *text_float;
1550 float val_float;
1552 if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
1553 if (!(text_float = alloc_float_text( val_float ))) return E_OUTOFMEMORY;
1554 attr->value = &text_float->text;
1555 return S_OK;
1557 case RECORD_DOUBLE_TEXT:
1559 WS_XML_DOUBLE_TEXT *text_double;
1560 double val_double;
1562 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
1563 if (!(text_double = alloc_double_text( val_double ))) return E_OUTOFMEMORY;
1564 attr->value = &text_double->text;
1565 return S_OK;
1567 case RECORD_DATETIME_TEXT:
1569 WS_XML_DATETIME_TEXT *text_datetime;
1570 WS_DATETIME datetime;
1572 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
1573 if (!(text_datetime = alloc_datetime_text( &datetime ))) return E_OUTOFMEMORY;
1574 attr->value = &text_datetime->text;
1575 return S_OK;
1577 case RECORD_CHARS8_TEXT:
1578 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1579 len = val_uint8;
1580 break;
1582 case RECORD_CHARS16_TEXT:
1583 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1584 len = val_uint16;
1585 break;
1587 case RECORD_CHARS32_TEXT:
1588 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1589 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1590 len = val_int32;
1591 break;
1593 case RECORD_BYTES8_TEXT:
1594 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1595 if (!(text_base64 = alloc_base64_text( NULL, val_uint8 ))) return E_OUTOFMEMORY;
1596 if ((hr = read_bytes( reader, text_base64->bytes, val_uint8 )) != S_OK)
1598 heap_free( text_base64 );
1599 return hr;
1601 break;
1603 case RECORD_BYTES16_TEXT:
1604 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1605 if (!(text_base64 = alloc_base64_text( NULL, val_uint16 ))) return E_OUTOFMEMORY;
1606 if ((hr = read_bytes( reader, text_base64->bytes, val_uint16 )) != S_OK)
1608 heap_free( text_base64 );
1609 return hr;
1611 break;
1613 case RECORD_BYTES32_TEXT:
1614 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1615 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1616 if (!(text_base64 = alloc_base64_text( NULL, val_int32 ))) return E_OUTOFMEMORY;
1617 if ((hr = read_bytes( reader, text_base64->bytes, val_int32 )) != S_OK)
1619 heap_free( text_base64 );
1620 return hr;
1622 break;
1624 case RECORD_EMPTY_TEXT:
1625 break;
1627 case RECORD_DICTIONARY_TEXT:
1628 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1629 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
1630 if (!(text_utf8 = alloc_utf8_text( str->bytes, str->length ))) return E_OUTOFMEMORY;
1631 break;
1633 case RECORD_UNIQUE_ID_TEXT:
1635 WS_XML_UNIQUE_ID_TEXT *text_unique_id;
1636 if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
1637 if (!(text_unique_id = alloc_unique_id_text( &guid ))) return E_OUTOFMEMORY;
1638 attr->value = &text_unique_id->text;
1639 return S_OK;
1641 case RECORD_GUID_TEXT:
1643 WS_XML_GUID_TEXT *guid_text;
1644 if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
1645 if (!(guid_text = alloc_guid_text( &guid ))) return E_OUTOFMEMORY;
1646 attr->value = &guid_text->text;
1647 return S_OK;
1649 case RECORD_UINT64_TEXT:
1651 WS_XML_UINT64_TEXT *text_uint64;
1652 UINT64 val_uint64;
1654 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
1655 if (!(text_uint64 = alloc_uint64_text( val_uint64 ))) return E_OUTOFMEMORY;
1656 attr->value = &text_uint64->text;
1657 return S_OK;
1659 case RECORD_BOOL_TEXT:
1661 WS_XML_BOOL_TEXT *text_bool;
1662 BOOL val_bool;
1664 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
1665 if (!(text_bool = alloc_bool_text( !!val_bool ))) return E_OUTOFMEMORY;
1666 attr->value = &text_bool->text;
1667 return S_OK;
1669 default:
1670 ERR( "unhandled record type %02x\n", type );
1671 return WS_E_NOT_SUPPORTED;
1674 if (type >= RECORD_BYTES8_TEXT && type <= RECORD_BYTES32_TEXT)
1676 attr->value = &text_base64->text;
1677 return S_OK;
1680 if (!text_utf8)
1682 if (!(text_utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
1683 if (!len) text_utf8->value.bytes = (BYTE *)(text_utf8 + 1); /* quirk */
1684 if ((hr = read_bytes( reader, text_utf8->value.bytes, len )) != S_OK)
1686 heap_free( text_utf8 );
1687 return hr;
1691 attr->value = &text_utf8->text;
1692 return S_OK;
1695 static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1697 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1698 WS_XML_ATTRIBUTE *attr;
1699 unsigned int len = 0, ch, skip;
1700 const unsigned char *start;
1701 WS_XML_STRING *prefix, *localname;
1702 HRESULT hr;
1704 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1706 start = read_current_ptr( reader );
1707 for (;;)
1709 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) goto error;
1710 if (!read_isnamechar( ch )) break;
1711 read_skip( reader, skip );
1712 len += skip;
1714 if (!len)
1716 hr = WS_E_INVALID_FORMAT;
1717 goto error;
1720 if ((hr = parse_qname( start, len, &prefix, &localname )) != S_OK) goto error;
1721 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1723 free_xml_string( prefix );
1724 attr->isXmlNs = 1;
1725 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1727 free_xml_string( localname );
1728 hr = E_OUTOFMEMORY;
1729 goto error;
1731 attr->localName = localname;
1733 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1735 attr->isXmlNs = 1;
1736 attr->prefix = prefix;
1737 attr->localName = localname;
1739 else
1741 attr->prefix = prefix;
1742 attr->localName = localname;
1745 if ((hr = read_attribute_value_text( reader, attr )) != S_OK) goto error;
1747 *ret = attr;
1748 return S_OK;
1750 error:
1751 free_attribute( attr );
1752 return hr;
1755 static inline BOOL is_attribute_type( unsigned char type )
1757 return (type >= RECORD_SHORT_ATTRIBUTE && type <= RECORD_PREFIX_ATTRIBUTE_Z);
1760 static WS_XML_STRING *get_xmlns_localname( struct reader *reader, const WS_XML_STRING *prefix )
1762 if (!get_namespace( reader, prefix )) return alloc_xml_string( NULL, 0 );
1763 return alloc_xml_string( prefix->bytes, prefix->length );
1766 static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1768 WS_XML_UTF8_TEXT *utf8;
1769 WS_XML_ATTRIBUTE *attr;
1770 unsigned char type = 0;
1771 HRESULT hr;
1773 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1774 if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT;
1775 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1777 if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z)
1779 unsigned char ch = type - RECORD_PREFIX_ATTRIBUTE_A + 'a';
1780 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1782 hr = E_OUTOFMEMORY;
1783 goto error;
1785 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1786 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1788 else if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
1790 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A + 'a';
1791 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1793 hr = E_OUTOFMEMORY;
1794 goto error;
1796 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1797 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1799 else
1801 switch (type)
1803 case RECORD_SHORT_ATTRIBUTE:
1804 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1806 hr = E_OUTOFMEMORY;
1807 goto error;
1809 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1810 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1811 break;
1813 case RECORD_ATTRIBUTE:
1814 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1815 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1816 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1817 break;
1819 case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
1820 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1822 hr = E_OUTOFMEMORY;
1823 goto error;
1825 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1826 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1827 break;
1829 case RECORD_DICTIONARY_ATTRIBUTE:
1830 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1831 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1832 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1833 break;
1835 case RECORD_SHORT_XMLNS_ATTRIBUTE:
1836 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1838 hr = E_OUTOFMEMORY;
1839 goto error;
1841 if (!(attr->localName = get_xmlns_localname( reader, attr->prefix )))
1843 hr = E_OUTOFMEMORY;
1844 goto error;
1846 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1847 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1848 attr->isXmlNs = 1;
1849 break;
1851 case RECORD_XMLNS_ATTRIBUTE:
1852 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1853 if (!(attr->localName = get_xmlns_localname( reader, attr->prefix )))
1855 hr = E_OUTOFMEMORY;
1856 goto error;
1858 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1859 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1860 attr->isXmlNs = 1;
1861 break;
1863 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
1864 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1866 hr = E_OUTOFMEMORY;
1867 goto error;
1869 if (!(attr->localName = get_xmlns_localname( reader, attr->prefix )))
1871 hr = E_OUTOFMEMORY;
1872 goto error;
1874 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1875 if (!(utf8 = alloc_utf8_text( NULL, 0 )))
1877 hr = E_OUTOFMEMORY;
1878 goto error;
1880 attr->value = &utf8->text;
1881 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1882 attr->isXmlNs = 1;
1883 break;
1885 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
1886 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1887 if (!(attr->localName = get_xmlns_localname( reader, attr->prefix )))
1889 hr = E_OUTOFMEMORY;
1890 goto error;
1892 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1893 if (!(utf8 = alloc_utf8_text( NULL, 0 )))
1895 hr = E_OUTOFMEMORY;
1896 goto error;
1898 attr->value = &utf8->text;
1899 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1900 attr->isXmlNs = 1;
1901 break;
1903 default:
1904 ERR( "unhandled record type %02x\n", type );
1905 return WS_E_NOT_SUPPORTED;
1909 *ret = attr;
1910 return S_OK;
1912 error:
1913 free_attribute( attr );
1914 return hr;
1917 static inline struct node *find_parent( struct reader *reader )
1919 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT)
1921 if (is_valid_parent( reader->current->parent->parent )) return reader->current->parent->parent;
1922 return NULL;
1924 if (is_valid_parent( reader->current )) return reader->current;
1925 if (is_valid_parent( reader->current->parent )) return reader->current->parent;
1926 return NULL;
1929 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1931 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1932 const WS_XML_STRING *ns;
1933 ULONG i;
1935 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1936 if (!(elem->ns = dup_xml_string( ns, FALSE ))) return E_OUTOFMEMORY;
1938 for (i = 0; i < elem->attributeCount; i++)
1940 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1941 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1942 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1943 if (!(attr->ns = alloc_xml_string( NULL, ns->length ))) return E_OUTOFMEMORY;
1944 if (attr->ns->length) memcpy( attr->ns->bytes, ns->bytes, ns->length );
1946 return S_OK;
1949 static WS_XML_ELEMENT_NODE *alloc_element_pair(void)
1951 struct node *node, *end;
1952 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
1953 if (!(end = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT )))
1955 free_node( node );
1956 return NULL;
1958 list_add_tail( &node->children, &end->entry );
1959 end->parent = node;
1960 return &node->hdr;
1963 static HRESULT read_attributes_text( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1965 WS_XML_ATTRIBUTE *attr;
1966 HRESULT hr;
1968 reader->current_attr = 0;
1969 for (;;)
1971 read_skip_whitespace( reader );
1972 if (read_cmp( reader, ">", 1 ) == S_OK || read_cmp( reader, "/>", 2 ) == S_OK) break;
1973 if ((hr = read_attribute_text( reader, &attr )) != S_OK) return hr;
1974 if ((hr = append_attribute( elem, attr )) != S_OK)
1976 free_attribute( attr );
1977 return hr;
1979 reader->current_attr++;
1981 return S_OK;
1984 static HRESULT read_element_text( struct reader *reader )
1986 unsigned int len = 0, ch, skip;
1987 const unsigned char *start;
1988 unsigned char buf[2];
1989 struct node *node = NULL, *parent;
1990 WS_XML_ELEMENT_NODE *elem;
1991 HRESULT hr;
1993 if (read_end_of_data( reader ))
1995 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1996 reader->last = reader->current;
1997 reader->state = READER_STATE_EOF;
1998 return S_OK;
2001 if ((hr = read_peek( reader, buf, 2 )) != S_OK) return hr;
2002 if (buf[0] != '<' || !read_isnamechar( buf[1] )) return WS_E_INVALID_FORMAT;
2003 read_skip( reader, 1 );
2005 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
2006 node = (struct node *)elem;
2008 start = read_current_ptr( reader );
2009 for (;;)
2011 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) goto error;
2012 if (!read_isnamechar( ch )) break;
2013 read_skip( reader, skip );
2014 len += skip;
2016 if (!len)
2018 hr = WS_E_INVALID_FORMAT;
2019 goto error;
2022 if (!(parent = find_parent( reader ))) goto error;
2023 if ((hr = parse_qname( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
2024 if ((hr = read_attributes_text( reader, elem )) != S_OK) goto error;
2025 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
2027 read_insert_node( reader, parent, node );
2028 reader->state = READER_STATE_STARTELEMENT;
2029 return S_OK;
2031 error:
2032 destroy_nodes( node );
2033 return hr;
2036 static inline BOOL is_element_type( unsigned char type )
2038 return (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z);
2041 static HRESULT read_attributes_bin( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
2043 WS_XML_ATTRIBUTE *attr;
2044 unsigned char type;
2045 HRESULT hr;
2047 reader->current_attr = 0;
2048 for (;;)
2050 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
2051 if (!is_attribute_type( type )) break;
2052 if ((hr = read_attribute_bin( reader, &attr )) != S_OK) return hr;
2053 if ((hr = append_attribute( elem, attr )) != S_OK)
2055 free_attribute( attr );
2056 return hr;
2058 reader->current_attr++;
2060 return S_OK;
2063 static HRESULT read_element_bin( struct reader *reader )
2065 struct node *node = NULL, *parent;
2066 WS_XML_ELEMENT_NODE *elem;
2067 unsigned char type;
2068 HRESULT hr;
2070 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2071 if (!is_element_type( type )) return WS_E_INVALID_FORMAT;
2073 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
2074 node = (struct node *)elem;
2076 if (type >= RECORD_PREFIX_ELEMENT_A && type <= RECORD_PREFIX_ELEMENT_Z)
2078 unsigned char ch = type - RECORD_PREFIX_ELEMENT_A + 'a';
2079 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
2081 hr = E_OUTOFMEMORY;
2082 goto error;
2084 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
2086 else if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
2088 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ELEMENT_A + 'a';
2089 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
2091 hr = E_OUTOFMEMORY;
2092 goto error;
2094 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
2096 else
2098 switch (type)
2100 case RECORD_SHORT_ELEMENT:
2101 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
2103 hr = E_OUTOFMEMORY;
2104 goto error;
2106 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
2107 break;
2109 case RECORD_ELEMENT:
2110 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
2111 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
2112 break;
2114 case RECORD_SHORT_DICTIONARY_ELEMENT:
2115 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
2117 hr = E_OUTOFMEMORY;
2118 goto error;
2120 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
2121 break;
2123 case RECORD_DICTIONARY_ELEMENT:
2124 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
2125 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
2126 break;
2128 default:
2129 ERR( "unhandled record type %02x\n", type );
2130 return WS_E_NOT_SUPPORTED;
2134 if (!(parent = find_parent( reader )))
2136 hr = WS_E_INVALID_FORMAT;
2137 goto error;
2140 if ((hr = read_attributes_bin( reader, elem )) != S_OK) goto error;
2141 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
2143 read_insert_node( reader, parent, node );
2144 reader->state = READER_STATE_STARTELEMENT;
2145 return S_OK;
2147 error:
2148 destroy_nodes( node );
2149 return hr;
2152 static HRESULT read_text_text( struct reader *reader )
2154 unsigned int len = 0, ch, skip;
2155 const unsigned char *start;
2156 struct node *node, *parent;
2157 WS_XML_TEXT_NODE *text;
2158 WS_XML_UTF8_TEXT *utf8;
2159 HRESULT hr;
2161 start = read_current_ptr( reader );
2162 for (;;)
2164 if (read_end_of_data( reader )) break;
2165 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
2166 if (ch == '<') break;
2167 read_skip( reader, skip );
2168 len += skip;
2171 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2173 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2174 text = (WS_XML_TEXT_NODE *)node;
2175 if (!(utf8 = alloc_utf8_text( NULL, len )))
2177 heap_free( node );
2178 return E_OUTOFMEMORY;
2180 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
2182 heap_free( utf8 );
2183 heap_free( node );
2184 return hr;
2186 text->text = &utf8->text;
2188 read_insert_node( reader, parent, node );
2189 reader->state = READER_STATE_TEXT;
2190 reader->text_conv_offset = 0;
2191 return S_OK;
2194 static struct node *alloc_utf8_text_node( const BYTE *data, ULONG len, WS_XML_UTF8_TEXT **ret )
2196 struct node *node;
2197 WS_XML_UTF8_TEXT *utf8;
2198 WS_XML_TEXT_NODE *text;
2200 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2201 if (!(utf8 = alloc_utf8_text( data, len )))
2203 heap_free( node );
2204 return NULL;
2206 text = (WS_XML_TEXT_NODE *)node;
2207 text->text = &utf8->text;
2208 if (ret) *ret = utf8;
2209 return node;
2212 static struct node *alloc_base64_text_node( const BYTE *data, ULONG len, WS_XML_BASE64_TEXT **ret )
2214 struct node *node;
2215 WS_XML_BASE64_TEXT *base64;
2216 WS_XML_TEXT_NODE *text;
2218 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2219 if (!(base64 = alloc_base64_text( data, len )))
2221 heap_free( node );
2222 return NULL;
2224 text = (WS_XML_TEXT_NODE *)node;
2225 text->text = &base64->text;
2226 if (ret) *ret = base64;
2227 return node;
2230 static struct node *alloc_bool_text_node( BOOL value )
2232 struct node *node;
2233 WS_XML_BOOL_TEXT *text_bool;
2234 WS_XML_TEXT_NODE *text;
2236 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2237 if (!(text_bool = alloc_bool_text( value )))
2239 heap_free( node );
2240 return NULL;
2242 text = (WS_XML_TEXT_NODE *)node;
2243 text->text = &text_bool->text;
2244 return node;
2247 static struct node *alloc_int32_text_node( INT32 value )
2249 struct node *node;
2250 WS_XML_INT32_TEXT *text_int32;
2251 WS_XML_TEXT_NODE *text;
2253 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2254 if (!(text_int32 = alloc_int32_text( value )))
2256 heap_free( node );
2257 return NULL;
2259 text = (WS_XML_TEXT_NODE *)node;
2260 text->text = &text_int32->text;
2261 return node;
2264 static struct node *alloc_int64_text_node( INT64 value )
2266 struct node *node;
2267 WS_XML_INT64_TEXT *text_int64;
2268 WS_XML_TEXT_NODE *text;
2270 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2271 if (!(text_int64 = alloc_int64_text( value )))
2273 heap_free( node );
2274 return NULL;
2276 text = (WS_XML_TEXT_NODE *)node;
2277 text->text = &text_int64->text;
2278 return node;
2281 static struct node *alloc_float_text_node( float value )
2283 struct node *node;
2284 WS_XML_FLOAT_TEXT *text_float;
2285 WS_XML_TEXT_NODE *text;
2287 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2288 if (!(text_float = alloc_float_text( value )))
2290 heap_free( node );
2291 return NULL;
2293 text = (WS_XML_TEXT_NODE *)node;
2294 text->text = &text_float->text;
2295 return node;
2298 static struct node *alloc_double_text_node( double value )
2300 struct node *node;
2301 WS_XML_DOUBLE_TEXT *text_double;
2302 WS_XML_TEXT_NODE *text;
2304 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2305 if (!(text_double = alloc_double_text( value )))
2307 heap_free( node );
2308 return NULL;
2310 text = (WS_XML_TEXT_NODE *)node;
2311 text->text = &text_double->text;
2312 return node;
2315 static struct node *alloc_datetime_text_node( const WS_DATETIME *value )
2317 struct node *node;
2318 WS_XML_DATETIME_TEXT *text_datetime;
2319 WS_XML_TEXT_NODE *text;
2321 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2322 if (!(text_datetime = alloc_datetime_text( value )))
2324 heap_free( node );
2325 return NULL;
2327 text = (WS_XML_TEXT_NODE *)node;
2328 text->text = &text_datetime->text;
2329 return node;
2332 static struct node *alloc_unique_id_text_node( const GUID *value )
2334 struct node *node;
2335 WS_XML_UNIQUE_ID_TEXT *text_unique_id;
2336 WS_XML_TEXT_NODE *text;
2338 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2339 if (!(text_unique_id = alloc_unique_id_text( value )))
2341 heap_free( node );
2342 return NULL;
2344 text = (WS_XML_TEXT_NODE *)node;
2345 text->text = &text_unique_id->text;
2346 return node;
2349 static struct node *alloc_guid_text_node( const GUID *value )
2351 struct node *node;
2352 WS_XML_GUID_TEXT *text_guid;
2353 WS_XML_TEXT_NODE *text;
2355 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2356 if (!(text_guid = alloc_guid_text( value )))
2358 heap_free( node );
2359 return NULL;
2361 text = (WS_XML_TEXT_NODE *)node;
2362 text->text = &text_guid->text;
2363 return node;
2366 static struct node *alloc_uint64_text_node( UINT64 value )
2368 struct node *node;
2369 WS_XML_UINT64_TEXT *text_uint64;
2370 WS_XML_TEXT_NODE *text;
2372 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2373 if (!(text_uint64 = alloc_uint64_text( value )))
2375 heap_free( node );
2376 return NULL;
2378 text = (WS_XML_TEXT_NODE *)node;
2379 text->text = &text_uint64->text;
2380 return node;
2383 static HRESULT append_text_bytes( struct reader *reader, WS_XML_TEXT_NODE *node, ULONG len )
2385 WS_XML_BASE64_TEXT *new, *old = (WS_XML_BASE64_TEXT *)node->text;
2386 HRESULT hr;
2388 if (!(new = alloc_base64_text( NULL, old->length + len ))) return E_OUTOFMEMORY;
2389 memcpy( new->bytes, old->bytes, old->length );
2390 if ((hr = read_bytes( reader, new->bytes + old->length, len )) != S_OK) return hr;
2391 heap_free( old );
2392 node->text = &new->text;
2393 return S_OK;
2396 static HRESULT read_text_bytes( struct reader *reader, unsigned char type )
2398 struct node *node = NULL, *parent;
2399 WS_XML_BASE64_TEXT *base64;
2400 HRESULT hr;
2401 ULONG len;
2403 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2404 for (;;)
2406 switch (type)
2408 case RECORD_BYTES8_TEXT:
2409 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2411 UINT8 len_uint8;
2412 if ((hr = read_byte( reader, (unsigned char *)&len_uint8 )) != S_OK) goto error;
2413 len = len_uint8;
2414 break;
2416 case RECORD_BYTES16_TEXT:
2417 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2419 UINT16 len_uint16;
2420 if ((hr = read_bytes( reader, (unsigned char *)&len_uint16, sizeof(len_uint16) )) != S_OK) goto error;
2421 len = len_uint16;
2422 break;
2424 case RECORD_BYTES32_TEXT:
2425 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2427 INT32 len_int32;
2428 if ((hr = read_bytes( reader, (unsigned char *)&len_int32, sizeof(len_int32) )) != S_OK) goto error;
2429 if (len_int32 < 0)
2431 hr = WS_E_INVALID_FORMAT;
2432 goto error;
2434 len = len_int32;
2435 break;
2437 default:
2438 ERR( "unexpected type %u\n", type );
2439 hr = E_INVALIDARG;
2440 goto error;
2443 if (!node)
2445 if (!(node = alloc_base64_text_node( NULL, len, &base64 ))) return E_OUTOFMEMORY;
2446 if ((hr = read_bytes( reader, base64->bytes, len )) != S_OK) goto error;
2448 else if ((hr = append_text_bytes( reader, (WS_XML_TEXT_NODE *)node, len )) != S_OK) goto error;
2450 if (type & 1)
2452 node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2453 break;
2455 if ((hr = read_peek( reader, &type, 1 )) != S_OK) goto error;
2456 if (type < RECORD_BYTES8_TEXT || type > RECORD_BYTES32_TEXT_WITH_ENDELEMENT) break;
2457 read_skip( reader, 1 );
2460 read_insert_node( reader, parent, node );
2461 reader->state = READER_STATE_TEXT;
2462 reader->text_conv_offset = 0;
2463 return S_OK;
2465 error:
2466 free_node( node );
2467 return hr;
2470 static HRESULT read_text_bin( struct reader *reader )
2472 struct node *node = NULL, *parent;
2473 unsigned char type;
2474 WS_XML_UTF8_TEXT *utf8;
2475 INT32 val_int32;
2476 UINT8 val_uint8;
2477 UINT16 val_uint16;
2478 ULONG len, id;
2479 GUID uuid;
2480 HRESULT hr;
2482 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2483 if (!is_text_type( type ) || !(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2485 switch (type)
2487 case RECORD_ZERO_TEXT:
2488 case RECORD_ZERO_TEXT_WITH_ENDELEMENT:
2489 if (!(node = alloc_int32_text_node( 0 ))) return E_OUTOFMEMORY;
2490 break;
2492 case RECORD_ONE_TEXT:
2493 case RECORD_ONE_TEXT_WITH_ENDELEMENT:
2494 if (!(node = alloc_int32_text_node( 1 ))) return E_OUTOFMEMORY;
2495 break;
2497 case RECORD_FALSE_TEXT:
2498 case RECORD_FALSE_TEXT_WITH_ENDELEMENT:
2499 if (!(node = alloc_bool_text_node( FALSE ))) return E_OUTOFMEMORY;
2500 break;
2502 case RECORD_TRUE_TEXT:
2503 case RECORD_TRUE_TEXT_WITH_ENDELEMENT:
2504 if (!(node = alloc_bool_text_node( TRUE ))) return E_OUTOFMEMORY;
2505 break;
2507 case RECORD_INT8_TEXT:
2508 case RECORD_INT8_TEXT_WITH_ENDELEMENT:
2510 INT8 val_int8;
2511 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
2512 if (!(node = alloc_int32_text_node( val_int8 ))) return E_OUTOFMEMORY;
2513 break;
2515 case RECORD_INT16_TEXT:
2516 case RECORD_INT16_TEXT_WITH_ENDELEMENT:
2518 INT16 val_int16;
2519 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
2520 if (!(node = alloc_int32_text_node( val_int16 ))) return E_OUTOFMEMORY;
2521 break;
2523 case RECORD_INT32_TEXT:
2524 case RECORD_INT32_TEXT_WITH_ENDELEMENT:
2525 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2526 if (!(node = alloc_int32_text_node( val_int32 ))) return E_OUTOFMEMORY;
2527 break;
2529 case RECORD_INT64_TEXT:
2530 case RECORD_INT64_TEXT_WITH_ENDELEMENT:
2532 INT64 val_int64;
2533 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
2534 if (!(node = alloc_int64_text_node( val_int64 ))) return E_OUTOFMEMORY;
2535 break;
2537 case RECORD_FLOAT_TEXT:
2538 case RECORD_FLOAT_TEXT_WITH_ENDELEMENT:
2540 float val_float;
2541 if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
2542 if (!(node = alloc_float_text_node( val_float ))) return E_OUTOFMEMORY;
2543 break;
2545 case RECORD_DOUBLE_TEXT:
2546 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT:
2548 double val_double;
2549 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
2550 if (!(node = alloc_double_text_node( val_double ))) return E_OUTOFMEMORY;
2551 break;
2553 case RECORD_DATETIME_TEXT:
2554 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT:
2556 WS_DATETIME datetime;
2557 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
2558 if (!(node = alloc_datetime_text_node( &datetime ))) return E_OUTOFMEMORY;
2559 break;
2561 case RECORD_CHARS8_TEXT:
2562 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT:
2563 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
2564 len = val_uint8;
2565 break;
2567 case RECORD_CHARS16_TEXT:
2568 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT:
2569 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
2570 len = val_uint16;
2571 break;
2573 case RECORD_CHARS32_TEXT:
2574 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT:
2575 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2576 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
2577 len = val_int32;
2578 break;
2580 case RECORD_BYTES8_TEXT:
2581 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2582 case RECORD_BYTES16_TEXT:
2583 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2584 case RECORD_BYTES32_TEXT:
2585 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2586 return read_text_bytes( reader, type );
2588 case RECORD_EMPTY_TEXT:
2589 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT:
2590 len = 0;
2591 break;
2593 case RECORD_DICTIONARY_TEXT:
2594 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT:
2596 const WS_XML_STRING *str;
2597 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
2598 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
2599 if (!(node = alloc_utf8_text_node( str->bytes, str->length, NULL ))) return E_OUTOFMEMORY;
2600 break;
2602 case RECORD_UNIQUE_ID_TEXT:
2603 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT:
2604 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2605 if (!(node = alloc_unique_id_text_node( &uuid ))) return E_OUTOFMEMORY;
2606 break;
2608 case RECORD_GUID_TEXT:
2609 case RECORD_GUID_TEXT_WITH_ENDELEMENT:
2610 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2611 if (!(node = alloc_guid_text_node( &uuid ))) return E_OUTOFMEMORY;
2612 break;
2614 case RECORD_UINT64_TEXT:
2615 case RECORD_UINT64_TEXT_WITH_ENDELEMENT:
2617 UINT64 val_uint64;
2618 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
2619 if (!(node = alloc_uint64_text_node( val_uint64 ))) return E_OUTOFMEMORY;
2620 break;
2622 case RECORD_BOOL_TEXT:
2623 case RECORD_BOOL_TEXT_WITH_ENDELEMENT:
2625 BOOL val_bool;
2626 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
2627 if (!(node = alloc_bool_text_node( !!val_bool ))) return E_OUTOFMEMORY;
2628 break;
2630 default:
2631 ERR( "unhandled record type %02x\n", type );
2632 return WS_E_NOT_SUPPORTED;
2635 if (!node)
2637 if (!(node = alloc_utf8_text_node( NULL, len, &utf8 ))) return E_OUTOFMEMORY;
2638 if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
2639 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
2641 free_node( node );
2642 return hr;
2646 if (type & 1) node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2647 read_insert_node( reader, parent, node );
2648 reader->state = READER_STATE_TEXT;
2649 reader->text_conv_offset = 0;
2650 return S_OK;
2653 static HRESULT read_node_text( struct reader * );
2655 static HRESULT read_startelement_text( struct reader *reader )
2657 HRESULT hr;
2659 if (read_cmp( reader, "<?", 2 ) == S_OK)
2661 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
2663 read_skip_whitespace( reader );
2664 if (read_cmp( reader, "<", 1 ) == S_OK)
2666 if ((hr = read_element_text( reader )) != S_OK) return hr;
2668 if (read_cmp( reader, "/>", 2 ) == S_OK)
2670 read_skip( reader, 2 );
2671 reader->current = LIST_ENTRY( list_tail( &reader->current->children ), struct node, entry );
2672 reader->last = reader->current;
2673 reader->state = READER_STATE_ENDELEMENT;
2674 return S_OK;
2676 else if (read_cmp( reader, ">", 1 ) == S_OK)
2678 read_skip( reader, 1 );
2679 return read_node_text( reader );
2681 return WS_E_INVALID_FORMAT;
2684 static HRESULT read_node_bin( struct reader * );
2686 static HRESULT read_startelement_bin( struct reader *reader )
2688 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
2689 return read_node_bin( reader );
2692 static HRESULT read_startelement( struct reader *reader )
2694 switch (reader->input_enc)
2696 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_startelement_text( reader );
2697 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_startelement_bin( reader );
2698 default:
2699 ERR( "unhandled encoding %u\n", reader->input_enc );
2700 return WS_E_NOT_SUPPORTED;
2704 static HRESULT read_to_startelement_text( struct reader *reader, BOOL *found )
2706 HRESULT hr;
2708 switch (reader->state)
2710 case READER_STATE_INITIAL:
2711 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
2712 break;
2714 case READER_STATE_STARTELEMENT:
2715 if (found) *found = TRUE;
2716 return S_OK;
2718 default:
2719 break;
2722 read_skip_whitespace( reader );
2723 if ((hr = read_element_text( reader )) == S_OK && found)
2725 if (reader->state == READER_STATE_STARTELEMENT)
2726 *found = TRUE;
2727 else
2728 *found = FALSE;
2731 return hr;
2734 static HRESULT read_to_startelement_bin( struct reader *reader, BOOL *found )
2736 HRESULT hr;
2738 if (reader->state == READER_STATE_STARTELEMENT)
2740 if (found) *found = TRUE;
2741 return S_OK;
2744 if ((hr = read_element_bin( reader )) == S_OK && found)
2746 if (reader->state == READER_STATE_STARTELEMENT)
2747 *found = TRUE;
2748 else
2749 *found = FALSE;
2752 return hr;
2755 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
2757 switch (reader->input_enc)
2759 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_to_startelement_text( reader, found );
2760 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_to_startelement_bin( reader, found );
2761 default:
2762 ERR( "unhandled encoding %u\n", reader->input_enc );
2763 return WS_E_NOT_SUPPORTED;
2767 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
2769 ULONG i;
2770 if (len1 != len2) return 1;
2771 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
2772 return 0;
2775 static struct node *find_startelement( struct reader *reader, const WS_XML_STRING *prefix,
2776 const WS_XML_STRING *localname )
2778 struct node *parent;
2779 const WS_XML_STRING *str;
2781 for (parent = reader->current; parent; parent = parent->parent)
2783 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
2785 str = parent->hdr.prefix;
2786 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
2787 str = parent->hdr.localName;
2788 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
2789 return parent;
2792 return NULL;
2795 static HRESULT read_endelement_text( struct reader *reader )
2797 struct node *parent;
2798 unsigned int len = 0, ch, skip;
2799 const unsigned char *start;
2800 WS_XML_STRING prefix, localname;
2801 HRESULT hr;
2803 if ((hr = read_cmp( reader, "</", 2 )) != S_OK) return hr;
2804 read_skip( reader, 2 );
2806 start = read_current_ptr( reader );
2807 for (;;)
2809 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
2810 if (ch == '>')
2812 read_skip( reader, 1 );
2813 break;
2815 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
2816 read_skip( reader, skip );
2817 len += skip;
2820 if ((hr = split_qname( start, len, &prefix, &localname )) != S_OK) return hr;
2821 if (!(parent = find_startelement( reader, &prefix, &localname ))) return WS_E_INVALID_FORMAT;
2823 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2824 reader->last = reader->current;
2825 reader->state = READER_STATE_ENDELEMENT;
2826 return S_OK;
2829 static HRESULT read_endelement_bin( struct reader *reader )
2831 struct node *parent;
2832 unsigned char type;
2833 HRESULT hr;
2835 if (!(reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT))
2837 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2838 if (type != RECORD_ENDELEMENT) return WS_E_INVALID_FORMAT;
2840 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2842 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2843 reader->last = reader->current;
2844 reader->state = READER_STATE_ENDELEMENT;
2845 return S_OK;
2848 static HRESULT read_endelement( struct reader *reader )
2850 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2852 if (read_end_of_data( reader ))
2854 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2855 reader->last = reader->current;
2856 reader->state = READER_STATE_EOF;
2857 return S_OK;
2860 switch (reader->input_enc)
2862 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_endelement_text( reader );
2863 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_endelement_bin( reader );
2864 default:
2865 ERR( "unhandled encoding %u\n", reader->input_enc );
2866 return WS_E_NOT_SUPPORTED;
2870 static HRESULT read_comment_text( struct reader *reader )
2872 unsigned int len = 0, ch, skip;
2873 const unsigned char *start;
2874 struct node *node, *parent;
2875 WS_XML_COMMENT_NODE *comment;
2876 HRESULT hr;
2878 if ((hr = read_cmp( reader, "<!--", 4 )) != S_OK) return hr;
2879 read_skip( reader, 4 );
2881 start = read_current_ptr( reader );
2882 for (;;)
2884 if (read_cmp( reader, "-->", 3 ) == S_OK)
2886 read_skip( reader, 3 );
2887 break;
2889 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
2890 read_skip( reader, skip );
2891 len += skip;
2894 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2896 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2897 comment = (WS_XML_COMMENT_NODE *)node;
2898 if (!(comment->value.bytes = heap_alloc( len )))
2900 heap_free( node );
2901 return E_OUTOFMEMORY;
2903 memcpy( comment->value.bytes, start, len );
2904 comment->value.length = len;
2906 read_insert_node( reader, parent, node );
2907 reader->state = READER_STATE_COMMENT;
2908 return S_OK;
2911 static HRESULT read_comment_bin( struct reader *reader )
2913 struct node *node, *parent;
2914 WS_XML_COMMENT_NODE *comment;
2915 unsigned char type;
2916 ULONG len;
2917 HRESULT hr;
2919 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2920 if (type != RECORD_COMMENT) return WS_E_INVALID_FORMAT;
2921 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
2923 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2925 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2926 comment = (WS_XML_COMMENT_NODE *)node;
2927 if (!(comment->value.bytes = heap_alloc( len )))
2929 heap_free( node );
2930 return E_OUTOFMEMORY;
2932 if ((hr = read_bytes( reader, comment->value.bytes, len )) != S_OK)
2934 free_node( node );
2935 return E_OUTOFMEMORY;
2937 comment->value.length = len;
2939 read_insert_node( reader, parent, node );
2940 reader->state = READER_STATE_COMMENT;
2941 return S_OK;
2944 static HRESULT read_startcdata( struct reader *reader )
2946 struct node *node, *endnode, *parent;
2947 HRESULT hr;
2949 if ((hr = read_cmp( reader, "<![CDATA[", 9 )) != S_OK) return hr;
2950 read_skip( reader, 9 );
2952 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2954 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
2955 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_CDATA )))
2957 heap_free( node );
2958 return E_OUTOFMEMORY;
2960 list_add_tail( &node->children, &endnode->entry );
2961 endnode->parent = node;
2963 read_insert_node( reader, parent, node );
2964 reader->state = READER_STATE_STARTCDATA;
2965 return S_OK;
2968 static HRESULT read_cdata( struct reader *reader )
2970 unsigned int len = 0, ch, skip;
2971 const unsigned char *start;
2972 struct node *node;
2973 WS_XML_TEXT_NODE *text;
2974 WS_XML_UTF8_TEXT *utf8;
2975 HRESULT hr;
2977 start = read_current_ptr( reader );
2978 for (;;)
2980 if (read_cmp( reader, "]]>", 3 ) == S_OK) break;
2981 if ((hr = read_utf8_char( reader, &ch, &skip )) != S_OK) return hr;
2982 read_skip( reader, skip );
2983 len += skip;
2986 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2987 text = (WS_XML_TEXT_NODE *)node;
2988 if (!(utf8 = alloc_utf8_text( start, len )))
2990 heap_free( node );
2991 return E_OUTOFMEMORY;
2993 text->text = &utf8->text;
2995 read_insert_node( reader, reader->current, node );
2996 reader->state = READER_STATE_CDATA;
2997 return S_OK;
3000 static HRESULT read_endcdata( struct reader *reader )
3002 struct node *parent;
3003 HRESULT hr;
3005 if ((hr = read_cmp( reader, "]]>", 3 )) != S_OK) return hr;
3006 read_skip( reader, 3 );
3008 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT) parent = reader->current->parent;
3009 else parent = reader->current;
3011 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
3012 reader->last = reader->current;
3013 reader->state = READER_STATE_ENDCDATA;
3014 return S_OK;
3017 static HRESULT read_node_text( struct reader *reader )
3019 HRESULT hr;
3021 for (;;)
3023 if (read_end_of_data( reader ))
3025 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
3026 reader->last = reader->current;
3027 reader->state = READER_STATE_EOF;
3028 return S_OK;
3030 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
3031 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
3032 else if (read_cmp( reader, "<?", 2 ) == S_OK)
3034 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
3036 else if (read_cmp( reader, "</", 2 ) == S_OK) return read_endelement_text( reader );
3037 else if (read_cmp( reader, "<![CDATA[", 9 ) == S_OK) return read_startcdata( reader );
3038 else if (read_cmp( reader, "<!--", 4 ) == S_OK) return read_comment_text( reader );
3039 else if (read_cmp( reader, "<", 1 ) == S_OK) return read_element_text( reader );
3040 else if (read_cmp( reader, "/>", 2 ) == S_OK || read_cmp( reader, ">", 1 ) == S_OK)
3042 return read_startelement_text( reader );
3044 else return read_text_text( reader );
3048 static HRESULT read_node_bin( struct reader *reader )
3050 unsigned char type;
3051 HRESULT hr;
3053 if (reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT)
3055 reader->current = LIST_ENTRY( list_tail( &reader->current->parent->children ), struct node, entry );
3056 reader->last = reader->current;
3057 reader->state = READER_STATE_ENDELEMENT;
3058 return S_OK;
3060 if (read_end_of_data( reader ))
3062 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
3063 reader->last = reader->current;
3064 reader->state = READER_STATE_EOF;
3065 return S_OK;
3068 if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr;
3069 if (type == RECORD_ENDELEMENT)
3071 return read_endelement_bin( reader );
3073 else if (type == RECORD_COMMENT)
3075 return read_comment_bin( reader );
3077 else if (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z)
3079 return read_element_bin( reader );
3081 else if (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT)
3083 return read_text_bin( reader );
3085 FIXME( "unhandled record type %02x\n", type );
3086 return WS_E_NOT_SUPPORTED;
3089 static HRESULT read_node( struct reader *reader )
3091 switch (reader->input_enc)
3093 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_node_text( reader );
3094 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_node_bin( reader );
3095 default:
3096 ERR( "unhandled encoding %u\n", reader->input_enc );
3097 return WS_E_NOT_SUPPORTED;
3101 HRESULT copy_node( WS_XML_READER *handle, WS_XML_WRITER_ENCODING_TYPE enc, struct node **node )
3103 struct reader *reader = (struct reader *)handle;
3104 const struct list *ptr;
3105 const struct node *start;
3106 HRESULT hr;
3108 EnterCriticalSection( &reader->cs );
3110 if (reader->magic != READER_MAGIC)
3112 LeaveCriticalSection( &reader->cs );
3113 return E_INVALIDARG;
3116 if (reader->current != reader->root) ptr = &reader->current->entry;
3117 else /* copy whole tree */
3119 if (!read_end_of_data( reader ))
3121 for (;;)
3123 if ((hr = read_node( reader )) != S_OK) goto done;
3124 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) break;
3127 ptr = list_head( &reader->root->children );
3130 start = LIST_ENTRY( ptr, struct node, entry );
3131 if (node_type( start ) == WS_XML_NODE_TYPE_EOF) hr = WS_E_INVALID_OPERATION;
3132 else hr = dup_tree( start, enc, node );
3134 done:
3135 LeaveCriticalSection( &reader->cs );
3136 return hr;
3139 /**************************************************************************
3140 * WsReadEndElement [webservices.@]
3142 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
3144 struct reader *reader = (struct reader *)handle;
3145 HRESULT hr;
3147 TRACE( "%p %p\n", handle, error );
3148 if (error) FIXME( "ignoring error parameter\n" );
3150 if (!reader) return E_INVALIDARG;
3152 EnterCriticalSection( &reader->cs );
3154 if (reader->magic != READER_MAGIC)
3156 LeaveCriticalSection( &reader->cs );
3157 return E_INVALIDARG;
3160 hr = read_endelement( reader );
3162 LeaveCriticalSection( &reader->cs );
3163 TRACE( "returning %08x\n", hr );
3164 return hr;
3167 /**************************************************************************
3168 * WsReadNode [webservices.@]
3170 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
3172 struct reader *reader = (struct reader *)handle;
3173 HRESULT hr;
3175 TRACE( "%p %p\n", handle, error );
3176 if (error) FIXME( "ignoring error parameter\n" );
3178 if (!reader) return E_INVALIDARG;
3180 EnterCriticalSection( &reader->cs );
3182 if (reader->magic != READER_MAGIC)
3184 LeaveCriticalSection( &reader->cs );
3185 return E_INVALIDARG;
3188 hr = read_node( reader );
3190 LeaveCriticalSection( &reader->cs );
3191 TRACE( "returning %08x\n", hr );
3192 return hr;
3195 static HRESULT skip_node( struct reader *reader )
3197 const struct node *parent;
3198 HRESULT hr;
3200 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) return WS_E_INVALID_OPERATION;
3201 if (node_type( reader->current ) == WS_XML_NODE_TYPE_ELEMENT) parent = reader->current;
3202 else parent = NULL;
3204 for (;;)
3206 if ((hr = read_node( reader )) != S_OK || !parent) break;
3207 if (node_type( reader->current ) != WS_XML_NODE_TYPE_END_ELEMENT) continue;
3208 if (reader->current->parent == parent) return read_node( reader );
3211 return hr;
3214 /**************************************************************************
3215 * WsSkipNode [webservices.@]
3217 HRESULT WINAPI WsSkipNode( WS_XML_READER *handle, WS_ERROR *error )
3219 struct reader *reader = (struct reader *)handle;
3220 HRESULT hr;
3222 TRACE( "%p %p\n", handle, error );
3223 if (error) FIXME( "ignoring error parameter\n" );
3225 if (!reader) return E_INVALIDARG;
3227 EnterCriticalSection( &reader->cs );
3229 if (reader->magic != READER_MAGIC)
3231 LeaveCriticalSection( &reader->cs );
3232 return E_INVALIDARG;
3235 hr = skip_node( reader );
3237 LeaveCriticalSection( &reader->cs );
3238 TRACE( "returning %08x\n", hr );
3239 return hr;
3242 /**************************************************************************
3243 * WsReadStartElement [webservices.@]
3245 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
3247 struct reader *reader = (struct reader *)handle;
3248 HRESULT hr;
3250 TRACE( "%p %p\n", handle, error );
3251 if (error) FIXME( "ignoring error parameter\n" );
3253 if (!reader) return E_INVALIDARG;
3255 EnterCriticalSection( &reader->cs );
3257 if (reader->magic != READER_MAGIC)
3259 LeaveCriticalSection( &reader->cs );
3260 return E_INVALIDARG;
3263 hr = read_startelement( reader );
3265 LeaveCriticalSection( &reader->cs );
3266 TRACE( "returning %08x\n", hr );
3267 return hr;
3270 /**************************************************************************
3271 * WsReadToStartElement [webservices.@]
3273 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
3274 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
3276 struct reader *reader = (struct reader *)handle;
3277 HRESULT hr;
3279 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
3280 if (error) FIXME( "ignoring error parameter\n" );
3282 if (!reader) return E_INVALIDARG;
3283 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
3285 EnterCriticalSection( &reader->cs );
3287 if (reader->magic != READER_MAGIC)
3289 LeaveCriticalSection( &reader->cs );
3290 return E_INVALIDARG;
3293 hr = read_to_startelement( reader, found );
3295 LeaveCriticalSection( &reader->cs );
3296 TRACE( "returning %08x\n", hr );
3297 return hr;
3300 BOOL move_to_root_element( struct node *root, struct node **current )
3302 struct list *ptr;
3303 struct node *node;
3305 if (!(ptr = list_head( &root->children ))) return FALSE;
3306 node = LIST_ENTRY( ptr, struct node, entry );
3307 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
3309 *current = node;
3310 return TRUE;
3312 while ((ptr = list_next( &root->children, &node->entry )))
3314 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3315 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3317 *current = next;
3318 return TRUE;
3320 node = next;
3322 return FALSE;
3325 BOOL move_to_next_element( struct node **current )
3327 struct list *ptr;
3328 struct node *node = *current, *parent = (*current)->parent;
3330 if (!parent) return FALSE;
3331 while ((ptr = list_next( &parent->children, &node->entry )))
3333 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3334 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3336 *current = next;
3337 return TRUE;
3339 node = next;
3341 return FALSE;
3344 BOOL move_to_prev_element( struct node **current )
3346 struct list *ptr;
3347 struct node *node = *current, *parent = (*current)->parent;
3349 if (!parent) return FALSE;
3350 while ((ptr = list_prev( &parent->children, &node->entry )))
3352 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
3353 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
3355 *current = prev;
3356 return TRUE;
3358 node = prev;
3360 return FALSE;
3363 BOOL move_to_child_element( struct node **current )
3365 struct list *ptr;
3366 struct node *child, *node = *current;
3368 if (!(ptr = list_head( &node->children ))) return FALSE;
3369 child = LIST_ENTRY( ptr, struct node, entry );
3370 if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
3372 *current = child;
3373 return TRUE;
3375 while ((ptr = list_next( &node->children, &child->entry )))
3377 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3378 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3380 *current = next;
3381 return TRUE;
3383 child = next;
3385 return FALSE;
3388 BOOL move_to_end_element( struct node **current )
3390 struct list *ptr;
3391 struct node *node = *current;
3393 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3395 if ((ptr = list_tail( &node->children )))
3397 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
3398 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
3400 *current = tail;
3401 return TRUE;
3404 return FALSE;
3407 BOOL move_to_parent_element( struct node **current )
3409 struct node *parent = (*current)->parent;
3411 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
3412 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
3414 *current = parent;
3415 return TRUE;
3417 return FALSE;
3420 BOOL move_to_first_node( struct node **current )
3422 struct list *ptr;
3423 struct node *node = *current;
3425 if ((ptr = list_head( &node->parent->children )))
3427 *current = LIST_ENTRY( ptr, struct node, entry );
3428 return TRUE;
3430 return FALSE;
3433 BOOL move_to_next_node( struct node **current )
3435 struct list *ptr;
3436 struct node *node = *current;
3438 if ((ptr = list_next( &node->parent->children, &node->entry )))
3440 *current = LIST_ENTRY( ptr, struct node, entry );
3441 return TRUE;
3443 return FALSE;
3446 BOOL move_to_prev_node( struct node **current )
3448 struct list *ptr;
3449 struct node *node = *current;
3451 if ((ptr = list_prev( &node->parent->children, &node->entry )))
3453 *current = LIST_ENTRY( ptr, struct node, entry );
3454 return TRUE;
3456 return FALSE;
3459 BOOL move_to_bof( struct node *root, struct node **current )
3461 *current = root;
3462 return TRUE;
3465 BOOL move_to_eof( struct node *root, struct node **current )
3467 struct list *ptr;
3468 if ((ptr = list_tail( &root->children )))
3470 *current = LIST_ENTRY( ptr, struct node, entry );
3471 return TRUE;
3473 return FALSE;
3476 BOOL move_to_child_node( struct node **current )
3478 struct list *ptr;
3479 struct node *node = *current;
3481 if ((ptr = list_head( &node->children )))
3483 *current = LIST_ENTRY( ptr, struct node, entry );
3484 return TRUE;
3486 return FALSE;
3489 BOOL move_to_parent_node( struct node **current )
3491 struct node *parent = (*current)->parent;
3492 if (!parent) return FALSE;
3493 *current = parent;
3494 return TRUE;
3497 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
3499 BOOL success = FALSE;
3500 HRESULT hr = S_OK;
3502 if (!read_end_of_data( reader ))
3504 struct node *saved_current = reader->current;
3505 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
3506 if (hr != S_OK) return hr;
3507 reader->current = saved_current;
3509 switch (move)
3511 case WS_MOVE_TO_ROOT_ELEMENT:
3512 success = move_to_root_element( reader->root, &reader->current );
3513 break;
3515 case WS_MOVE_TO_NEXT_ELEMENT:
3516 success = move_to_next_element( &reader->current );
3517 break;
3519 case WS_MOVE_TO_PREVIOUS_ELEMENT:
3520 success = move_to_prev_element( &reader->current );
3521 break;
3523 case WS_MOVE_TO_CHILD_ELEMENT:
3524 success = move_to_child_element( &reader->current );
3525 break;
3527 case WS_MOVE_TO_END_ELEMENT:
3528 success = move_to_end_element( &reader->current );
3529 break;
3531 case WS_MOVE_TO_PARENT_ELEMENT:
3532 success = move_to_parent_element( &reader->current );
3533 break;
3535 case WS_MOVE_TO_FIRST_NODE:
3536 success = move_to_first_node( &reader->current );
3537 break;
3539 case WS_MOVE_TO_NEXT_NODE:
3540 success = move_to_next_node( &reader->current );
3541 break;
3543 case WS_MOVE_TO_PREVIOUS_NODE:
3544 success = move_to_prev_node( &reader->current );
3545 break;
3547 case WS_MOVE_TO_CHILD_NODE:
3548 success = move_to_child_node( &reader->current );
3549 break;
3551 case WS_MOVE_TO_BOF:
3552 success = move_to_bof( reader->root, &reader->current );
3553 break;
3555 case WS_MOVE_TO_EOF:
3556 success = move_to_eof( reader->root, &reader->current );
3557 break;
3559 default:
3560 FIXME( "unhandled move %u\n", move );
3561 return E_NOTIMPL;
3564 if (found)
3566 *found = success;
3567 return S_OK;
3569 return success ? S_OK : WS_E_INVALID_FORMAT;
3572 /**************************************************************************
3573 * WsMoveReader [webservices.@]
3575 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
3577 struct reader *reader = (struct reader *)handle;
3578 HRESULT hr;
3580 TRACE( "%p %u %p %p\n", handle, move, found, error );
3581 if (error) FIXME( "ignoring error parameter\n" );
3583 if (!reader) return E_INVALIDARG;
3585 EnterCriticalSection( &reader->cs );
3587 if (reader->magic != READER_MAGIC)
3589 LeaveCriticalSection( &reader->cs );
3590 return E_INVALIDARG;
3593 if (reader->input_type != WS_XML_READER_INPUT_TYPE_BUFFER) hr = WS_E_INVALID_OPERATION;
3594 else hr = read_move_to( reader, move, found );
3596 LeaveCriticalSection( &reader->cs );
3597 TRACE( "returning %08x\n", hr );
3598 return hr;
3601 /**************************************************************************
3602 * WsReadStartAttribute [webservices.@]
3604 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
3606 struct reader *reader = (struct reader *)handle;
3607 const WS_XML_ELEMENT_NODE *elem;
3608 HRESULT hr = S_OK;
3610 TRACE( "%p %u %p\n", handle, index, error );
3611 if (error) FIXME( "ignoring error parameter\n" );
3613 if (!reader) return E_INVALIDARG;
3615 EnterCriticalSection( &reader->cs );
3617 if (reader->magic != READER_MAGIC)
3619 LeaveCriticalSection( &reader->cs );
3620 return E_INVALIDARG;
3623 elem = &reader->current->hdr;
3624 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount) hr = WS_E_INVALID_FORMAT;
3625 else
3627 reader->current_attr = index;
3628 reader->state = READER_STATE_STARTATTRIBUTE;
3631 LeaveCriticalSection( &reader->cs );
3632 TRACE( "returning %08x\n", hr );
3633 return S_OK;
3636 /**************************************************************************
3637 * WsReadEndAttribute [webservices.@]
3639 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
3641 struct reader *reader = (struct reader *)handle;
3642 HRESULT hr = S_OK;
3644 TRACE( "%p %p\n", handle, error );
3645 if (error) FIXME( "ignoring error parameter\n" );
3647 if (!reader) return E_INVALIDARG;
3649 EnterCriticalSection( &reader->cs );
3651 if (reader->magic != READER_MAGIC)
3653 LeaveCriticalSection( &reader->cs );
3654 return E_INVALIDARG;
3657 if (reader->state != READER_STATE_STARTATTRIBUTE) hr = WS_E_INVALID_FORMAT;
3658 else reader->state = READER_STATE_STARTELEMENT;
3660 LeaveCriticalSection( &reader->cs );
3661 TRACE( "returning %08x\n", hr );
3662 return hr;
3665 static HRESULT str_to_bool( const unsigned char *str, ULONG len, BOOL *ret )
3667 if (len == 4 && !memcmp( str, "true", 4 )) *ret = TRUE;
3668 else if (len == 1 && !memcmp( str, "1", 1 )) *ret = TRUE;
3669 else if (len == 5 && !memcmp( str, "false", 5 )) *ret = FALSE;
3670 else if (len == 1 && !memcmp( str, "0", 1 )) *ret = FALSE;
3671 else return WS_E_INVALID_FORMAT;
3672 return S_OK;
3675 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
3677 BOOL negative = FALSE;
3678 const unsigned char *ptr = str;
3680 *ret = 0;
3681 while (len && read_isspace( *ptr )) { ptr++; len--; }
3682 while (len && read_isspace( ptr[len - 1] )) { len--; }
3683 if (!len) return WS_E_INVALID_FORMAT;
3685 if (*ptr == '-')
3687 negative = TRUE;
3688 ptr++;
3689 len--;
3691 if (!len) return WS_E_INVALID_FORMAT;
3693 while (len--)
3695 int val;
3697 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3698 val = *ptr - '0';
3699 if (negative) val = -val;
3701 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
3702 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
3704 return WS_E_NUMERIC_OVERFLOW;
3706 *ret = *ret * 10 + val;
3707 ptr++;
3710 return S_OK;
3713 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
3715 const unsigned char *ptr = str;
3717 *ret = 0;
3718 while (len && read_isspace( *ptr )) { ptr++; len--; }
3719 while (len && read_isspace( ptr[len - 1] )) { len--; }
3720 if (!len) return WS_E_INVALID_FORMAT;
3722 while (len--)
3724 unsigned int val;
3726 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3727 val = *ptr - '0';
3729 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
3730 *ret = *ret * 10 + val;
3731 ptr++;
3734 return S_OK;
3737 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
3739 BOOL found_sign = FALSE, found_exponent = FALSE, found_digit = FALSE, found_decimal = FALSE;
3740 static const unsigned __int64 nan = 0xfff8000000000000;
3741 static const unsigned __int64 inf = 0x7ff0000000000000;
3742 static const unsigned __int64 inf_min = 0xfff0000000000000;
3743 const char *p = (const char *)str;
3744 double tmp;
3745 ULONG i;
3747 while (len && read_isspace( *p )) { p++; len--; }
3748 while (len && read_isspace( p[len - 1] )) { len--; }
3749 if (!len) return WS_E_INVALID_FORMAT;
3751 if (len == 3 && !memcmp( p, "NaN", 3 ))
3753 *(unsigned __int64 *)ret = nan;
3754 return S_OK;
3756 if (len == 3 && !memcmp( p, "INF", 3 ))
3758 *(unsigned __int64 *)ret = inf;
3759 return S_OK;
3761 if (len == 4 && !memcmp( p, "-INF", 4 ))
3763 *(unsigned __int64 *)ret = inf_min;
3764 return S_OK;
3767 for (i = 0; i < len; i++)
3769 if (p[i] >= '0' && p[i] <= '9')
3771 found_digit = TRUE;
3772 continue;
3774 if (!found_sign && !found_digit && (p[i] == '+' || p[i] == '-'))
3776 found_sign = TRUE;
3777 continue;
3779 if (!found_exponent && found_digit && (p[i] == 'e' || p[i] == 'E'))
3781 found_exponent = found_decimal = TRUE;
3782 found_digit = found_sign = FALSE;
3783 continue;
3785 if (!found_decimal && p[i] == '.')
3787 found_decimal = TRUE;
3788 continue;
3790 return WS_E_INVALID_FORMAT;
3792 if (!found_digit && !found_exponent)
3794 *ret = 0;
3795 return S_OK;
3798 if (_snscanf_l( p, len, "%lf", c_locale, &tmp ) != 1) return WS_E_INVALID_FORMAT;
3799 *ret = tmp;
3800 return S_OK;
3803 static HRESULT str_to_float( const unsigned char *str, ULONG len, float *ret )
3805 static const unsigned int inf = 0x7f800000;
3806 static const unsigned int inf_min = 0xff800000;
3807 const unsigned char *p = str;
3808 double val;
3809 HRESULT hr;
3811 while (len && read_isspace( *p )) { p++; len--; }
3812 while (len && read_isspace( p[len - 1] )) { len--; }
3813 if (!len) return WS_E_INVALID_FORMAT;
3815 if (len == 3 && !memcmp( p, "INF", 3 ))
3817 *(unsigned int *)ret = inf;
3818 return S_OK;
3820 if (len == 4 && !memcmp( p, "-INF", 4 ))
3822 *(unsigned int *)ret = inf_min;
3823 return S_OK;
3826 if ((hr = str_to_double( p, len, &val )) != S_OK) return hr;
3827 *ret = val;
3828 return S_OK;
3831 HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
3833 static const unsigned char hex[] =
3835 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3836 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3837 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3838 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3839 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3840 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3841 0,10,11,12,13,14,15 /* 0x60 */
3843 const unsigned char *p = str;
3844 ULONG i;
3846 while (len && read_isspace( *p )) { p++; len--; }
3847 while (len && read_isspace( p[len - 1] )) { len--; }
3848 if (len != 36) return WS_E_INVALID_FORMAT;
3850 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
3851 return WS_E_INVALID_FORMAT;
3853 for (i = 0; i < 36; i++)
3855 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
3856 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
3859 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
3860 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
3862 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
3863 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
3865 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
3866 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
3867 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
3868 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
3869 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
3870 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
3871 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
3872 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
3874 return S_OK;
3877 static HRESULT str_to_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_STRING *ret )
3879 int len_utf16 = MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, NULL, 0 );
3880 if (!(ret->chars = ws_alloc( heap, len_utf16 * sizeof(WCHAR) ))) return WS_E_QUOTA_EXCEEDED;
3881 MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, ret->chars, len_utf16 );
3882 ret->length = len_utf16;
3883 return S_OK;
3886 static HRESULT str_to_unique_id( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_UNIQUE_ID *ret )
3888 if (len == 45 && !memcmp( str, "urn:uuid:", 9 ))
3890 ret->uri.length = 0;
3891 ret->uri.chars = NULL;
3892 return str_to_guid( str + 9, len - 9, &ret->guid );
3895 memset( &ret->guid, 0, sizeof(ret->guid) );
3896 return str_to_string( str, len, heap, &ret->uri );
3899 static inline unsigned char decode_char( unsigned char c )
3901 if (c >= 'A' && c <= 'Z') return c - 'A';
3902 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
3903 if (c >= '0' && c <= '9') return c - '0' + 52;
3904 if (c == '+') return 62;
3905 if (c == '/') return 63;
3906 return 64;
3909 static ULONG decode_base64( const unsigned char *base64, ULONG len, unsigned char *buf )
3911 ULONG i = 0;
3912 unsigned char c0, c1, c2, c3;
3913 const unsigned char *p = base64;
3915 while (len > 4)
3917 if ((c0 = decode_char( p[0] )) > 63) return 0;
3918 if ((c1 = decode_char( p[1] )) > 63) return 0;
3919 if ((c2 = decode_char( p[2] )) > 63) return 0;
3920 if ((c3 = decode_char( p[3] )) > 63) return 0;
3921 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3922 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3923 buf[i + 2] = (c2 << 6) | c3;
3924 len -= 4;
3925 i += 3;
3926 p += 4;
3928 if (p[2] == '=')
3930 if ((c0 = decode_char( p[0] )) > 63) return 0;
3931 if ((c1 = decode_char( p[1] )) > 63) return 0;
3932 buf[i] = (c0 << 2) | (c1 >> 4);
3933 i++;
3935 else if (p[3] == '=')
3937 if ((c0 = decode_char( p[0] )) > 63) return 0;
3938 if ((c1 = decode_char( p[1] )) > 63) return 0;
3939 if ((c2 = decode_char( p[2] )) > 63) return 0;
3940 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3941 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3942 i += 2;
3944 else
3946 if ((c0 = decode_char( p[0] )) > 63) return 0;
3947 if ((c1 = decode_char( p[1] )) > 63) return 0;
3948 if ((c2 = decode_char( p[2] )) > 63) return 0;
3949 if ((c3 = decode_char( p[3] )) > 63) return 0;
3950 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3951 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3952 buf[i + 2] = (c2 << 6) | c3;
3953 i += 3;
3955 return i;
3958 static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_BYTES *ret )
3960 const unsigned char *p = str;
3962 while (len && read_isspace( *p )) { p++; len--; }
3963 while (len && read_isspace( p[len - 1] )) { len--; }
3965 if (len % 4) return WS_E_INVALID_FORMAT;
3966 if (!(ret->bytes = ws_alloc( heap, len * 3 / 4 ))) return WS_E_QUOTA_EXCEEDED;
3967 ret->length = decode_base64( p, len, ret->bytes );
3968 return S_OK;
3971 static HRESULT str_to_xml_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_XML_STRING *ret )
3973 if (!(ret->bytes = ws_alloc( heap, len ))) return WS_E_QUOTA_EXCEEDED;
3974 memcpy( ret->bytes, str, len );
3975 ret->length = len;
3976 ret->dictionary = NULL;
3977 ret->id = 0;
3978 return S_OK;
3981 static HRESULT copy_xml_string( WS_HEAP *heap, const WS_XML_STRING *src, WS_XML_STRING *dst )
3983 if (!(dst->bytes = ws_alloc( heap, src->length ))) return WS_E_QUOTA_EXCEEDED;
3984 memcpy( dst->bytes, src->bytes, src->length );
3985 dst->length = src->length;
3986 return S_OK;
3989 static HRESULT str_to_qname( struct reader *reader, const unsigned char *str, ULONG len, WS_HEAP *heap,
3990 WS_XML_STRING *prefix_ret, WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
3992 const unsigned char *p = str;
3993 WS_XML_STRING prefix, localname;
3994 const WS_XML_STRING *ns;
3995 HRESULT hr;
3997 while (len && read_isspace( *p )) { p++; len--; }
3998 while (len && read_isspace( p[len - 1] )) { len--; }
4000 if ((hr = split_qname( p, len, &prefix, &localname )) != S_OK) return hr;
4001 if (!(ns = get_namespace( reader, &prefix ))) return WS_E_INVALID_FORMAT;
4003 if (prefix_ret && (hr = copy_xml_string( heap, &prefix, prefix_ret )) != S_OK) return hr;
4004 if ((hr = copy_xml_string( heap, &localname, localname_ret )) != S_OK)
4006 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
4007 return hr;
4009 if ((hr = copy_xml_string( heap, ns, ns_ret )) != S_OK)
4011 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
4012 ws_free( heap, localname_ret->bytes, localname_ret->length );
4013 return hr;
4015 return S_OK;
4018 static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix,
4019 WS_XML_STRING *localname, WS_XML_STRING *ns )
4021 const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
4022 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
4023 return str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap, prefix, localname, ns );
4026 /**************************************************************************
4027 * WsReadQualifiedName [webservices.@]
4029 HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
4030 WS_XML_STRING *localname, WS_XML_STRING *ns,
4031 WS_ERROR *error )
4033 struct reader *reader = (struct reader *)handle;
4034 HRESULT hr;
4036 TRACE( "%p %p %p %p %p %p\n", handle, heap, prefix, localname, ns, error );
4037 if (error) FIXME( "ignoring error parameter\n" );
4039 if (!reader || !heap) return E_INVALIDARG;
4041 EnterCriticalSection( &reader->cs );
4043 if (reader->magic != READER_MAGIC)
4045 LeaveCriticalSection( &reader->cs );
4046 return E_INVALIDARG;
4049 if (!reader->input_type) hr = WS_E_INVALID_OPERATION;
4050 else if (!localname) hr = E_INVALIDARG;
4051 else if (reader->state != READER_STATE_TEXT) hr = WS_E_INVALID_FORMAT;
4052 else hr = read_qualified_name( reader, heap, prefix, localname, ns );
4054 LeaveCriticalSection( &reader->cs );
4055 TRACE( "returning %08x\n", hr );
4056 return hr;
4059 static const int month_offsets[2][12] =
4061 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
4062 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
4065 static inline int valid_day( int year, int month, int day )
4067 return day > 0 && day <= month_days[leap_year( year )][month - 1];
4070 static inline int leap_days_before( int year )
4072 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
4075 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
4077 const unsigned char *p = bytes, *q;
4078 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
4080 while (len && read_isspace( *p )) { p++; len--; }
4081 while (len && read_isspace( p[len - 1] )) { len--; }
4083 q = p;
4084 while (len && isdigit( *q )) { q++; len--; };
4085 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
4086 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
4087 if (year < 1) return WS_E_INVALID_FORMAT;
4089 p = ++q; len--;
4090 while (len && isdigit( *q )) { q++; len--; };
4091 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
4092 month = (p[0] - '0') * 10 + p[1] - '0';
4093 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
4095 p = ++q; len--;
4096 while (len && isdigit( *q )) { q++; len--; };
4097 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
4098 day = (p[0] - '0') * 10 + p[1] - '0';
4099 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
4101 p = ++q; len--;
4102 while (len && isdigit( *q )) { q++; len--; };
4103 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4104 hour = (p[0] - '0') * 10 + p[1] - '0';
4105 if (hour > 24) return WS_E_INVALID_FORMAT;
4107 p = ++q; len--;
4108 while (len && isdigit( *q )) { q++; len--; };
4109 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4110 min = (p[0] - '0') * 10 + p[1] - '0';
4111 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
4113 p = ++q; len--;
4114 while (len && isdigit( *q )) { q++; len--; };
4115 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
4116 sec = (p[0] - '0') * 10 + p[1] - '0';
4117 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
4119 if (*q == '.')
4121 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
4122 p = ++q; len--;
4123 while (len && isdigit( *q )) { q++; len--; };
4124 nb_digits = q - p;
4125 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
4126 for (i = 0; i < nb_digits; i++)
4128 sec_frac += (p[i] - '0') * mul;
4129 mul /= 10;
4132 if (*q == 'Z')
4134 if (--len) return WS_E_INVALID_FORMAT;
4135 tz_hour = tz_min = tz_neg = 0;
4136 ret->format = WS_DATETIME_FORMAT_UTC;
4138 else if (*q == '+' || *q == '-')
4140 tz_neg = (*q == '-') ? 1 : 0;
4142 p = ++q; len--;
4143 while (len && isdigit( *q )) { q++; len--; };
4144 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4145 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
4146 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
4148 p = ++q; len--;
4149 while (len && isdigit( *q )) { q++; len--; };
4150 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
4151 tz_min = (p[0] - '0') * 10 + p[1] - '0';
4152 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
4154 ret->format = WS_DATETIME_FORMAT_LOCAL;
4156 else return WS_E_INVALID_FORMAT;
4158 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
4159 ret->ticks += month_offsets[leap_year( year )][month - 1] * TICKS_PER_DAY;
4160 ret->ticks += (day - 1) * TICKS_PER_DAY;
4161 ret->ticks += hour * TICKS_PER_HOUR;
4162 ret->ticks += min * TICKS_PER_MIN;
4163 ret->ticks += sec * TICKS_PER_SEC;
4164 ret->ticks += sec_frac;
4166 if (tz_neg)
4168 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
4169 return WS_E_INVALID_FORMAT;
4170 ret->ticks += tz_hour * TICKS_PER_HOUR;
4171 ret->ticks += tz_min * TICKS_PER_MIN;
4173 else
4175 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
4176 return WS_E_INVALID_FORMAT;
4177 ret->ticks -= tz_hour * TICKS_PER_HOUR;
4178 ret->ticks -= tz_min * TICKS_PER_MIN;
4181 return S_OK;
4184 /**************************************************************************
4185 * WsDateTimeToFileTime [webservices.@]
4187 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
4189 unsigned __int64 ticks;
4191 TRACE( "%p %p %p\n", dt, ft, error );
4192 if (error) FIXME( "ignoring error parameter\n" );
4194 if (!dt || !ft) return E_INVALIDARG;
4196 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
4197 ticks = dt->ticks - TICKS_1601_01_01;
4198 ft->dwHighDateTime = ticks >> 32;
4199 ft->dwLowDateTime = (DWORD)ticks;
4200 return S_OK;
4203 /**************************************************************************
4204 * WsFileTimeToDateTime [webservices.@]
4206 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
4208 unsigned __int64 ticks;
4210 TRACE( "%p %p %p\n", ft, dt, error );
4211 if (error) FIXME( "ignoring error parameter\n" );
4213 if (!dt || !ft) return E_INVALIDARG;
4215 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
4216 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
4217 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
4218 dt->ticks = ticks + TICKS_1601_01_01;
4219 dt->format = WS_DATETIME_FORMAT_UTC;
4220 return S_OK;
4223 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
4224 const WS_XML_STRING *ns, ULONG *index )
4226 ULONG i;
4227 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4229 if (!localname)
4231 *index = reader->current_attr;
4232 return TRUE;
4234 for (i = 0; i < elem->attributeCount; i++)
4236 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
4237 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
4239 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
4240 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
4242 *index = i;
4243 return TRUE;
4246 return FALSE;
4249 /**************************************************************************
4250 * WsFindAttribute [webservices.@]
4252 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
4253 const WS_XML_STRING *ns, BOOL required, ULONG *index,
4254 WS_ERROR *error )
4256 struct reader *reader = (struct reader *)handle;
4257 HRESULT hr = S_OK;
4259 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
4260 required, index, error );
4261 if (error) FIXME( "ignoring error parameter\n" );
4263 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
4265 EnterCriticalSection( &reader->cs );
4267 if (reader->magic != READER_MAGIC)
4269 LeaveCriticalSection( &reader->cs );
4270 return E_INVALIDARG;
4273 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) hr = WS_E_INVALID_OPERATION;
4274 else if (!find_attribute( reader, localname, ns, index ))
4276 if (required) hr = WS_E_INVALID_FORMAT;
4277 else
4279 *index = ~0u;
4280 hr = S_FALSE;
4284 LeaveCriticalSection( &reader->cs );
4285 TRACE( "returning %08x\n", hr );
4286 return hr;
4289 static HRESULT get_node_text( struct reader *reader, const WS_XML_TEXT **ret )
4291 WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
4292 *ret = node->text;
4293 return S_OK;
4296 static HRESULT get_attribute_text( struct reader *reader, ULONG index, const WS_XML_TEXT **ret )
4298 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4299 *ret = elem->attributes[index]->value;
4300 return S_OK;
4303 static BOOL match_element( const struct node *node, const WS_XML_STRING *localname, const WS_XML_STRING *ns )
4305 const WS_XML_ELEMENT_NODE *elem = (const WS_XML_ELEMENT_NODE *)node;
4306 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
4307 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
4308 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
4311 static HRESULT read_next_node( struct reader *reader )
4313 if (reader->current == reader->last) return read_node( reader );
4314 if (move_to_child_node( &reader->current )) return S_OK;
4315 if (move_to_next_node( &reader->current )) return S_OK;
4316 if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
4317 if (move_to_next_node( &reader->current )) return S_OK;
4318 return WS_E_INVALID_FORMAT;
4321 struct reader_pos
4323 struct node *node;
4324 ULONG attr;
4327 static void save_reader_position( const struct reader *reader, struct reader_pos *pos )
4329 pos->node = reader->current;
4330 pos->attr = reader->current_attr;
4333 static void restore_reader_position( struct reader *reader, const struct reader_pos *pos )
4335 reader->current = pos->node;
4336 reader->current_attr = pos->attr;
4339 static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
4340 const WS_XML_STRING *ns, const WS_XML_TEXT **ret, BOOL *found )
4342 switch (mapping)
4344 case WS_ATTRIBUTE_TYPE_MAPPING:
4346 ULONG i;
4347 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4349 *found = FALSE;
4350 for (i = 0; i < elem->attributeCount; i++)
4352 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
4353 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
4355 if (cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length )) continue;
4356 if (!ns->length || !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
4358 *found = TRUE;
4359 break;
4362 if (!*found) return S_OK;
4363 return get_attribute_text( reader, i, ret );
4365 case WS_ELEMENT_TYPE_MAPPING:
4366 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
4367 case WS_ANY_ELEMENT_TYPE_MAPPING:
4369 *found = TRUE;
4370 if (localname)
4372 struct reader_pos pos;
4373 HRESULT hr;
4375 if (!match_element( reader->current, localname, ns ))
4377 *found = FALSE;
4378 return S_OK;
4380 save_reader_position( reader, &pos );
4381 if ((hr = read_next_node( reader )) != S_OK) return hr;
4382 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4384 restore_reader_position( reader, &pos );
4385 *found = FALSE;
4386 return S_OK;
4389 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4391 *found = FALSE;
4392 return S_OK;
4394 return get_node_text( reader, ret );
4396 default:
4397 FIXME( "mapping %u not supported\n", mapping );
4398 return E_NOTIMPL;
4402 static HRESULT text_to_bool( const WS_XML_TEXT *text, BOOL *val )
4404 HRESULT hr;
4406 switch (text->textType)
4408 case WS_XML_TEXT_TYPE_UTF8:
4410 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4411 hr = str_to_bool( text_utf8->value.bytes, text_utf8->value.length, val );
4412 break;
4414 case WS_XML_TEXT_TYPE_BOOL:
4416 const WS_XML_BOOL_TEXT *text_bool = (const WS_XML_BOOL_TEXT *)text;
4417 *val = text_bool->value;
4418 hr = S_OK;
4419 break;
4421 default:
4422 FIXME( "unhandled text type %u\n", text->textType );
4423 return E_NOTIMPL;
4426 return hr;
4429 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
4430 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4431 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
4432 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4434 const WS_XML_TEXT *text;
4435 HRESULT hr;
4436 BOOL val = FALSE;
4438 if (desc)
4440 FIXME( "description not supported\n" );
4441 return E_NOTIMPL;
4443 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4444 if (*found && (hr = text_to_bool( text, &val )) != S_OK) return hr;
4446 switch (option)
4448 case WS_READ_REQUIRED_VALUE:
4449 if (!*found) return WS_E_INVALID_FORMAT;
4450 /* fall through */
4452 case WS_READ_NILLABLE_VALUE:
4453 if (size != sizeof(val)) return E_INVALIDARG;
4454 *(BOOL *)ret = val;
4455 break;
4457 case WS_READ_REQUIRED_POINTER:
4458 if (!*found) return WS_E_INVALID_FORMAT;
4459 /* fall through */
4461 case WS_READ_OPTIONAL_POINTER:
4462 case WS_READ_NILLABLE_POINTER:
4464 BOOL *heap_val = NULL;
4465 if (size != sizeof(heap_val)) return E_INVALIDARG;
4466 if (*found)
4468 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4469 *heap_val = val;
4471 *(BOOL **)ret = heap_val;
4472 break;
4474 default:
4475 FIXME( "read option %u not supported\n", option );
4476 return E_NOTIMPL;
4479 return S_OK;
4482 static HRESULT text_to_int8( const WS_XML_TEXT *text, INT64 *val )
4484 HRESULT hr;
4486 switch (text->textType)
4488 case WS_XML_TEXT_TYPE_UTF8:
4490 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4491 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT8, MAX_INT8, val );
4492 break;
4494 case WS_XML_TEXT_TYPE_INT32:
4496 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4497 assert( text_int32->value >= MIN_INT8 );
4498 assert( text_int32->value <= MAX_INT8 );
4499 *val = text_int32->value;
4500 hr = S_OK;
4501 break;
4503 default:
4504 FIXME( "unhandled text type %u\n", text->textType );
4505 return E_NOTIMPL;
4508 return hr;
4511 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
4512 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4513 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
4514 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4516 const WS_XML_TEXT *text;
4517 HRESULT hr;
4518 INT64 val = 0;
4520 if (desc)
4522 FIXME( "description not supported\n" );
4523 return E_NOTIMPL;
4525 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4526 if (*found && (hr = text_to_int8( text, &val )) != S_OK) return hr;
4528 switch (option)
4530 case WS_READ_REQUIRED_VALUE:
4531 if (!*found) return WS_E_INVALID_FORMAT;
4532 /* fall through */
4534 case WS_READ_NILLABLE_VALUE:
4535 if (size != sizeof(INT8)) return E_INVALIDARG;
4536 *(INT8 *)ret = val;
4537 break;
4539 case WS_READ_REQUIRED_POINTER:
4540 if (!*found) return WS_E_INVALID_FORMAT;
4541 /* fall through */
4543 case WS_READ_OPTIONAL_POINTER:
4544 case WS_READ_NILLABLE_POINTER:
4546 INT8 *heap_val = NULL;
4547 if (size != sizeof(heap_val)) return E_INVALIDARG;
4548 if (*found)
4550 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4551 *heap_val = val;
4553 *(INT8 **)ret = heap_val;
4554 break;
4556 default:
4557 FIXME( "read option %u not supported\n", option );
4558 return E_NOTIMPL;
4561 return S_OK;
4564 static HRESULT text_to_int16( const WS_XML_TEXT *text, INT64 *val )
4566 HRESULT hr;
4568 switch (text->textType)
4570 case WS_XML_TEXT_TYPE_UTF8:
4572 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4573 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT16, MAX_INT16, val );
4574 break;
4576 case WS_XML_TEXT_TYPE_INT32:
4578 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4579 assert( text_int32->value >= MIN_INT16 );
4580 assert( text_int32->value <= MAX_INT16 );
4581 *val = text_int32->value;
4582 hr = S_OK;
4583 break;
4585 default:
4586 FIXME( "unhandled text type %u\n", text->textType );
4587 return E_NOTIMPL;
4590 return hr;
4593 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
4594 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4595 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
4596 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4598 const WS_XML_TEXT *text;
4599 HRESULT hr;
4600 INT64 val = 0;
4602 if (desc)
4604 FIXME( "description not supported\n" );
4605 return E_NOTIMPL;
4607 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4608 if (*found && (hr = text_to_int16( text, &val )) != S_OK) return hr;
4610 switch (option)
4612 case WS_READ_REQUIRED_VALUE:
4613 if (!*found) return WS_E_INVALID_FORMAT;
4614 /* fall through */
4616 case WS_READ_NILLABLE_VALUE:
4617 if (size != sizeof(INT16)) return E_INVALIDARG;
4618 *(INT16 *)ret = val;
4619 break;
4621 case WS_READ_REQUIRED_POINTER:
4622 if (!*found) return WS_E_INVALID_FORMAT;
4623 /* fall through */
4625 case WS_READ_OPTIONAL_POINTER:
4626 case WS_READ_NILLABLE_POINTER:
4628 INT16 *heap_val = NULL;
4629 if (size != sizeof(heap_val)) return E_INVALIDARG;
4630 if (*found)
4632 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4633 *heap_val = val;
4635 *(INT16 **)ret = heap_val;
4636 break;
4638 default:
4639 FIXME( "read option %u not supported\n", option );
4640 return E_NOTIMPL;
4643 return S_OK;
4646 static HRESULT text_to_int32( const WS_XML_TEXT *text, INT64 *val )
4648 HRESULT hr;
4650 switch (text->textType)
4652 case WS_XML_TEXT_TYPE_UTF8:
4654 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4655 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT32, MAX_INT32, val );
4656 break;
4658 case WS_XML_TEXT_TYPE_INT32:
4660 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4661 *val = text_int32->value;
4662 hr = S_OK;
4663 break;
4665 default:
4666 FIXME( "unhandled text type %u\n", text->textType );
4667 return E_NOTIMPL;
4670 return hr;
4673 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
4674 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4675 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
4676 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4678 const WS_XML_TEXT *text;
4679 HRESULT hr;
4680 INT64 val = 0;
4682 if (desc)
4684 FIXME( "description not supported\n" );
4685 return E_NOTIMPL;
4687 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4688 if (*found && (hr = text_to_int32( text, &val )) != S_OK) return hr;
4690 switch (option)
4692 case WS_READ_REQUIRED_VALUE:
4693 if (!*found) return WS_E_INVALID_FORMAT;
4694 /* fall through */
4696 case WS_READ_NILLABLE_VALUE:
4697 if (size != sizeof(INT32)) return E_INVALIDARG;
4698 *(INT32 *)ret = val;
4699 break;
4701 case WS_READ_REQUIRED_POINTER:
4702 if (!*found) return WS_E_INVALID_FORMAT;
4703 /* fall through */
4705 case WS_READ_OPTIONAL_POINTER:
4706 case WS_READ_NILLABLE_POINTER:
4708 INT32 *heap_val = NULL;
4709 if (size != sizeof(heap_val)) return E_INVALIDARG;
4710 if (*found)
4712 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4713 *heap_val = val;
4715 *(INT32 **)ret = heap_val;
4716 break;
4718 default:
4719 FIXME( "read option %u not supported\n", option );
4720 return E_NOTIMPL;
4723 return S_OK;
4726 static HRESULT text_to_int64( const WS_XML_TEXT *text, INT64 *val )
4728 HRESULT hr;
4730 switch (text->textType)
4732 case WS_XML_TEXT_TYPE_UTF8:
4734 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4735 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT64, MAX_INT64, val );
4736 break;
4738 case WS_XML_TEXT_TYPE_INT64:
4740 const WS_XML_INT64_TEXT *text_int64 = (const WS_XML_INT64_TEXT *)text;
4741 *val = text_int64->value;
4742 hr = S_OK;
4743 break;
4745 default:
4746 FIXME( "unhandled text type %u\n", text->textType );
4747 return E_NOTIMPL;
4750 return hr;
4753 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
4754 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4755 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
4756 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4758 const WS_XML_TEXT *text;
4759 HRESULT hr;
4760 INT64 val = 0;
4762 if (desc)
4764 FIXME( "description not supported\n" );
4765 return E_NOTIMPL;
4767 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4768 if (*found && (hr = text_to_int64( text, &val )) != S_OK) return hr;
4770 switch (option)
4772 case WS_READ_REQUIRED_VALUE:
4773 if (!*found) return WS_E_INVALID_FORMAT;
4774 /* fall through */
4776 case WS_READ_NILLABLE_VALUE:
4777 if (size != sizeof(val)) return E_INVALIDARG;
4778 *(INT64 *)ret = val;
4779 break;
4781 case WS_READ_REQUIRED_POINTER:
4782 if (!*found) return WS_E_INVALID_FORMAT;
4783 /* fall through */
4785 case WS_READ_OPTIONAL_POINTER:
4786 case WS_READ_NILLABLE_POINTER:
4788 INT64 *heap_val = NULL;
4789 if (size != sizeof(heap_val)) return E_INVALIDARG;
4790 if (*found)
4792 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4793 *heap_val = val;
4795 *(INT64 **)ret = heap_val;
4796 break;
4798 default:
4799 FIXME( "read option %u not supported\n", option );
4800 return E_NOTIMPL;
4803 return S_OK;
4806 static HRESULT text_to_uint8( const WS_XML_TEXT *text, UINT64 *val )
4808 HRESULT hr;
4810 switch (text->textType)
4812 case WS_XML_TEXT_TYPE_UTF8:
4814 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4815 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT8, val );
4816 break;
4818 case WS_XML_TEXT_TYPE_UINT64:
4820 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4821 assert( text_uint64->value <= MAX_UINT8 );
4822 *val = text_uint64->value;
4823 hr = S_OK;
4824 break;
4826 default:
4827 FIXME( "unhandled text type %u\n", text->textType );
4828 return E_NOTIMPL;
4831 return hr;
4834 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
4835 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4836 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
4837 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4839 const WS_XML_TEXT *text;
4840 HRESULT hr;
4841 UINT64 val = 0;
4843 if (desc)
4845 FIXME( "description not supported\n" );
4846 return E_NOTIMPL;
4848 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4849 if (*found && (hr = text_to_uint8( text, &val )) != S_OK) return hr;
4851 switch (option)
4853 case WS_READ_REQUIRED_VALUE:
4854 if (!*found) return WS_E_INVALID_FORMAT;
4855 /* fall through */
4857 case WS_READ_NILLABLE_VALUE:
4858 if (size != sizeof(UINT8)) return E_INVALIDARG;
4859 *(UINT8 *)ret = val;
4860 break;
4862 case WS_READ_REQUIRED_POINTER:
4863 if (!*found) return WS_E_INVALID_FORMAT;
4864 /* fall through */
4866 case WS_READ_OPTIONAL_POINTER:
4867 case WS_READ_NILLABLE_POINTER:
4869 UINT8 *heap_val = NULL;
4870 if (size != sizeof(heap_val)) return E_INVALIDARG;
4871 if (*found)
4873 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4874 *heap_val = val;
4876 *(UINT8 **)ret = heap_val;
4877 break;
4879 default:
4880 FIXME( "read option %u not supported\n", option );
4881 return E_NOTIMPL;
4884 return S_OK;
4887 static HRESULT text_to_uint16( const WS_XML_TEXT *text, UINT64 *val )
4889 HRESULT hr;
4891 switch (text->textType)
4893 case WS_XML_TEXT_TYPE_UTF8:
4895 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4896 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT16, val );
4897 break;
4899 case WS_XML_TEXT_TYPE_INT32:
4901 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4902 assert( text_int32->value >= 0 );
4903 assert( text_int32->value <= MAX_UINT16 );
4904 *val = text_int32->value;
4905 hr = S_OK;
4906 break;
4908 case WS_XML_TEXT_TYPE_UINT64:
4910 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4911 assert( text_uint64->value <= MAX_UINT16 );
4912 *val = text_uint64->value;
4913 hr = S_OK;
4914 break;
4916 default:
4917 FIXME( "unhandled text type %u\n", text->textType );
4918 return E_NOTIMPL;
4921 return hr;
4924 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
4925 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4926 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
4927 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
4929 const WS_XML_TEXT *text;
4930 HRESULT hr;
4931 UINT64 val = 0;
4933 if (desc)
4935 FIXME( "description not supported\n" );
4936 return E_NOTIMPL;
4938 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
4939 if (*found && (hr = text_to_uint16( text, &val )) != S_OK) return hr;
4941 switch (option)
4943 case WS_READ_REQUIRED_VALUE:
4944 if (!*found) return WS_E_INVALID_FORMAT;
4945 /* fall through */
4947 case WS_READ_NILLABLE_VALUE:
4948 if (size != sizeof(UINT16)) return E_INVALIDARG;
4949 *(UINT16 *)ret = val;
4950 break;
4952 case WS_READ_REQUIRED_POINTER:
4953 if (!*found) return WS_E_INVALID_FORMAT;
4954 /* fall through */
4956 case WS_READ_OPTIONAL_POINTER:
4957 case WS_READ_NILLABLE_POINTER:
4959 UINT16 *heap_val = NULL;
4960 if (size != sizeof(heap_val)) return E_INVALIDARG;
4961 if (*found)
4963 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4964 *heap_val = val;
4966 *(UINT16 **)ret = heap_val;
4967 break;
4969 default:
4970 FIXME( "read option %u not supported\n", option );
4971 return E_NOTIMPL;
4974 return S_OK;
4977 static HRESULT text_to_uint32( const WS_XML_TEXT *text, UINT64 *val )
4979 HRESULT hr;
4981 switch (text->textType)
4983 case WS_XML_TEXT_TYPE_UTF8:
4985 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4986 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT32, val );
4987 break;
4989 case WS_XML_TEXT_TYPE_INT32:
4991 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4992 assert( text_int32->value >= 0 );
4993 *val = text_int32->value;
4994 hr = S_OK;
4995 break;
4997 case WS_XML_TEXT_TYPE_UINT64:
4999 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
5000 assert( text_uint64->value <= MAX_UINT32 );
5001 *val = text_uint64->value;
5002 hr = S_OK;
5003 break;
5005 default:
5006 FIXME( "unhandled text type %u\n", text->textType );
5007 return E_NOTIMPL;
5010 return hr;
5013 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
5014 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5015 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
5016 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5018 const WS_XML_TEXT *text;
5019 HRESULT hr;
5020 UINT64 val = 0;
5022 if (desc)
5024 FIXME( "description not supported\n" );
5025 return E_NOTIMPL;
5027 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5028 if (*found && (hr = text_to_uint32( text, &val )) != S_OK) return hr;
5030 switch (option)
5032 case WS_READ_REQUIRED_VALUE:
5033 if (!*found) return WS_E_INVALID_FORMAT;
5034 /* fall through */
5036 case WS_READ_NILLABLE_VALUE:
5037 if (size != sizeof(UINT32)) return E_INVALIDARG;
5038 *(UINT32 *)ret = val;
5039 break;
5041 case WS_READ_REQUIRED_POINTER:
5042 if (!*found) return WS_E_INVALID_FORMAT;
5043 /* fall through */
5045 case WS_READ_OPTIONAL_POINTER:
5046 case WS_READ_NILLABLE_POINTER:
5048 UINT32 *heap_val = NULL;
5049 if (size != sizeof(heap_val)) return E_INVALIDARG;
5050 if (*found)
5052 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5053 *heap_val = val;
5055 *(UINT32 **)ret = heap_val;
5056 break;
5058 default:
5059 FIXME( "read option %u not supported\n", option );
5060 return E_NOTIMPL;
5063 return S_OK;
5066 static HRESULT text_to_uint64( const WS_XML_TEXT *text, UINT64 *val )
5068 HRESULT hr;
5070 switch (text->textType)
5072 case WS_XML_TEXT_TYPE_UTF8:
5074 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5075 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT64, val );
5076 break;
5078 case WS_XML_TEXT_TYPE_INT32:
5080 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
5081 *val = text_int32->value;
5082 hr = S_OK;
5083 break;
5085 case WS_XML_TEXT_TYPE_INT64:
5087 const WS_XML_INT64_TEXT *text_int64 = (const WS_XML_INT64_TEXT *)text;
5088 *val = text_int64->value;
5089 hr = S_OK;
5090 break;
5092 case WS_XML_TEXT_TYPE_UINT64:
5094 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
5095 *val = text_uint64->value;
5096 hr = S_OK;
5097 break;
5099 default:
5100 FIXME( "unhandled text type %u\n", text->textType );
5101 return E_NOTIMPL;
5104 return hr;
5107 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
5108 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5109 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
5110 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5112 const WS_XML_TEXT *text;
5113 HRESULT hr;
5114 UINT64 val = 0;
5116 if (desc)
5118 FIXME( "description not supported\n" );
5119 return E_NOTIMPL;
5121 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5122 if (*found && (hr = text_to_uint64( text, &val )) != S_OK) return hr;
5124 switch (option)
5126 case WS_READ_REQUIRED_VALUE:
5127 if (!*found) return WS_E_INVALID_FORMAT;
5128 /* fall through */
5130 case WS_READ_NILLABLE_VALUE:
5131 if (size != sizeof(val)) return E_INVALIDARG;
5132 *(UINT64 *)ret = val;
5133 break;
5135 case WS_READ_REQUIRED_POINTER:
5136 if (!*found) return WS_E_INVALID_FORMAT;
5137 /* fall through */
5139 case WS_READ_OPTIONAL_POINTER:
5140 case WS_READ_NILLABLE_POINTER:
5142 UINT64 *heap_val = NULL;
5143 if (size != sizeof(heap_val)) return E_INVALIDARG;
5144 if (*found)
5146 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5147 *heap_val = val;
5149 *(UINT64 **)ret = heap_val;
5150 break;
5152 default:
5153 FIXME( "read option %u not supported\n", option );
5154 return E_NOTIMPL;
5157 return S_OK;
5160 static HRESULT text_to_float( const WS_XML_TEXT *text, float *val )
5162 HRESULT hr;
5164 switch (text->textType)
5166 case WS_XML_TEXT_TYPE_UTF8:
5168 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5169 hr = str_to_float( text_utf8->value.bytes, text_utf8->value.length, val );
5170 break;
5172 case WS_XML_TEXT_TYPE_FLOAT:
5174 const WS_XML_FLOAT_TEXT *text_float = (const WS_XML_FLOAT_TEXT *)text;
5175 *val = text_float->value;
5176 hr = S_OK;
5177 break;
5179 default:
5180 FIXME( "unhandled text type %u\n", text->textType );
5181 return E_NOTIMPL;
5184 return hr;
5187 static HRESULT read_type_float( struct reader *reader, WS_TYPE_MAPPING mapping,
5188 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5189 const WS_FLOAT_DESCRIPTION *desc, WS_READ_OPTION option,
5190 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5192 const WS_XML_TEXT *text;
5193 HRESULT hr;
5194 float val = 0.0;
5196 if (desc) FIXME( "ignoring description\n" );
5198 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5199 if (*found && (hr = text_to_float( text, &val )) != S_OK) return hr;
5201 switch (option)
5203 case WS_READ_REQUIRED_VALUE:
5204 if (!*found) return WS_E_INVALID_FORMAT;
5205 /* fall through */
5207 case WS_READ_NILLABLE_VALUE:
5208 if (size != sizeof(val)) return E_INVALIDARG;
5209 *(float *)ret = val;
5210 break;
5212 case WS_READ_REQUIRED_POINTER:
5213 if (!*found) return WS_E_INVALID_FORMAT;
5214 /* fall through */
5216 case WS_READ_OPTIONAL_POINTER:
5217 case WS_READ_NILLABLE_POINTER:
5219 float *heap_val = NULL;
5220 if (size != sizeof(heap_val)) return E_INVALIDARG;
5221 if (*found)
5223 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5224 *heap_val = val;
5226 *(float **)ret = heap_val;
5227 break;
5229 default:
5230 FIXME( "read option %u not supported\n", option );
5231 return E_NOTIMPL;
5234 return S_OK;
5237 static HRESULT text_to_double( const WS_XML_TEXT *text, double *val )
5239 HRESULT hr;
5241 switch (text->textType)
5243 case WS_XML_TEXT_TYPE_UTF8:
5245 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5246 hr = str_to_double( text_utf8->value.bytes, text_utf8->value.length, val );
5247 break;
5249 case WS_XML_TEXT_TYPE_DOUBLE:
5251 const WS_XML_DOUBLE_TEXT *text_double = (const WS_XML_DOUBLE_TEXT *)text;
5252 *val = text_double->value;
5253 hr = S_OK;
5254 break;
5256 default:
5257 FIXME( "unhandled text type %u\n", text->textType );
5258 return E_NOTIMPL;
5261 return hr;
5264 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
5265 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5266 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
5267 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5269 const WS_XML_TEXT *text;
5270 HRESULT hr;
5271 double val = 0.0;
5273 if (desc) FIXME( "ignoring description\n" );
5275 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5276 if (*found && (hr = text_to_double( text, &val )) != S_OK) return hr;
5278 switch (option)
5280 case WS_READ_REQUIRED_VALUE:
5281 if (!*found) return WS_E_INVALID_FORMAT;
5282 /* fall through */
5284 case WS_READ_NILLABLE_VALUE:
5285 if (size != sizeof(val)) return E_INVALIDARG;
5286 *(double *)ret = val;
5287 break;
5289 case WS_READ_REQUIRED_POINTER:
5290 if (!*found) return WS_E_INVALID_FORMAT;
5291 /* fall through */
5293 case WS_READ_OPTIONAL_POINTER:
5294 case WS_READ_NILLABLE_POINTER:
5296 double *heap_val = NULL;
5297 if (size != sizeof(heap_val)) return E_INVALIDARG;
5298 if (*found)
5300 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5301 *heap_val = val;
5303 *(double **)ret = heap_val;
5304 break;
5306 default:
5307 FIXME( "read option %u not supported\n", option );
5308 return E_NOTIMPL;
5311 return S_OK;
5314 static HRESULT text_to_wsz( const WS_XML_TEXT *text, WS_HEAP *heap, WCHAR **ret )
5316 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5317 int len;
5319 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5320 len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
5321 if (!(*ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
5322 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, *ret, len );
5323 (*ret)[len] = 0;
5324 return S_OK;
5327 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
5328 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5329 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
5330 WS_HEAP *heap, WCHAR **ret, ULONG size, BOOL *found )
5332 const WS_XML_TEXT *text;
5333 HRESULT hr;
5334 WCHAR *str = NULL;
5336 if (desc)
5338 FIXME( "description not supported\n" );
5339 return E_NOTIMPL;
5341 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5342 if (*found && (hr = text_to_wsz( text, heap, &str )) != S_OK) return hr;
5344 switch (option)
5346 case WS_READ_REQUIRED_POINTER:
5347 if (!str && !(str = ws_alloc_zero( heap, sizeof(*str) ))) return WS_E_QUOTA_EXCEEDED;
5348 /* fall through */
5350 case WS_READ_OPTIONAL_POINTER:
5351 case WS_READ_NILLABLE_POINTER:
5352 if (size != sizeof(str)) return E_INVALIDARG;
5353 *ret = str;
5354 break;
5356 default:
5357 FIXME( "read option %u not supported\n", option );
5358 return E_NOTIMPL;
5361 return S_OK;
5364 static HRESULT get_enum_value( const WS_XML_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
5366 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5367 ULONG i;
5369 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5370 for (i = 0; i < desc->valueCount; i++)
5372 if (WsXmlStringEquals( &utf8->value, desc->values[i].name, NULL ) == S_OK)
5374 *ret = desc->values[i].value;
5375 return S_OK;
5378 return WS_E_INVALID_FORMAT;
5381 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
5382 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5383 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
5384 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5386 const WS_XML_TEXT *text;
5387 HRESULT hr;
5388 int val = 0;
5390 if (!desc) return E_INVALIDARG;
5392 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5393 if (*found && (hr = get_enum_value( text, desc, &val )) != S_OK) return hr;
5395 switch (option)
5397 case WS_READ_REQUIRED_VALUE:
5398 if (!*found) return WS_E_INVALID_FORMAT;
5399 /* fall through */
5401 case WS_READ_NILLABLE_VALUE:
5402 if (size != sizeof(val)) return E_INVALIDARG;
5403 *(int *)ret = val;
5404 break;
5406 case WS_READ_REQUIRED_POINTER:
5407 if (!*found) return WS_E_INVALID_FORMAT;
5408 /* fall through */
5410 case WS_READ_OPTIONAL_POINTER:
5411 case WS_READ_NILLABLE_POINTER:
5413 int *heap_val = NULL;
5414 if (size != sizeof(heap_val)) return E_INVALIDARG;
5415 if (*found)
5417 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5418 *heap_val = val;
5420 *(int **)ret = heap_val;
5421 break;
5423 default:
5424 FIXME( "read option %u not supported\n", option );
5425 return E_NOTIMPL;
5428 return S_OK;
5431 static HRESULT text_to_datetime( const WS_XML_TEXT *text, WS_DATETIME *val )
5433 HRESULT hr;
5435 switch (text->textType)
5437 case WS_XML_TEXT_TYPE_UTF8:
5439 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5440 hr = str_to_datetime( text_utf8->value.bytes, text_utf8->value.length, val );
5441 break;
5443 case WS_XML_TEXT_TYPE_DATETIME:
5445 const WS_XML_DATETIME_TEXT *text_datetime = (const WS_XML_DATETIME_TEXT *)text;
5446 *val = text_datetime->value;
5447 hr = S_OK;
5448 break;
5450 default:
5451 FIXME( "unhandled text type %u\n", text->textType );
5452 return E_NOTIMPL;
5455 return hr;
5458 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
5459 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5460 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
5461 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5463 const WS_XML_TEXT *text;
5464 HRESULT hr;
5465 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
5467 if (desc) FIXME( "ignoring description\n" );
5469 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5470 if (*found && (hr = text_to_datetime( text, &val )) != S_OK) return hr;
5472 switch (option)
5474 case WS_READ_REQUIRED_VALUE:
5475 if (!*found) return WS_E_INVALID_FORMAT;
5476 /* fall through */
5478 case WS_READ_NILLABLE_VALUE:
5479 if (size != sizeof(val)) return E_INVALIDARG;
5480 *(WS_DATETIME *)ret = val;
5481 break;
5483 case WS_READ_REQUIRED_POINTER:
5484 if (!*found) return WS_E_INVALID_FORMAT;
5485 /* fall through */
5487 case WS_READ_OPTIONAL_POINTER:
5488 case WS_READ_NILLABLE_POINTER:
5490 WS_DATETIME *heap_val = NULL;
5491 if (size != sizeof(heap_val)) return E_INVALIDARG;
5492 if (*found)
5494 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5495 *heap_val = val;
5497 *(WS_DATETIME **)ret = heap_val;
5498 break;
5500 default:
5501 FIXME( "read option %u not supported\n", option );
5502 return E_NOTIMPL;
5505 return S_OK;
5508 static HRESULT text_to_guid( const WS_XML_TEXT *text, GUID *val )
5510 HRESULT hr;
5512 switch (text->textType)
5514 case WS_XML_TEXT_TYPE_UTF8:
5516 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5517 hr = str_to_guid( text_utf8->value.bytes, text_utf8->value.length, val );
5518 break;
5520 case WS_XML_TEXT_TYPE_GUID:
5522 const WS_XML_GUID_TEXT *text_guid = (const WS_XML_GUID_TEXT *)text;
5523 *val = text_guid->value;
5524 hr = S_OK;
5525 break;
5527 default:
5528 FIXME( "unhandled text type %u\n", text->textType );
5529 return E_NOTIMPL;
5532 return hr;
5535 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
5536 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5537 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
5538 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5540 const WS_XML_TEXT *text;
5541 GUID val = {0};
5542 HRESULT hr;
5544 if (desc) FIXME( "ignoring description\n" );
5546 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5547 if (*found && (hr = text_to_guid( text, &val )) != S_OK) return hr;
5549 switch (option)
5551 case WS_READ_REQUIRED_VALUE:
5552 if (!*found) return WS_E_INVALID_FORMAT;
5553 /* fall through */
5555 case WS_READ_NILLABLE_VALUE:
5556 if (size != sizeof(val)) return E_INVALIDARG;
5557 *(GUID *)ret = val;
5558 break;
5560 case WS_READ_REQUIRED_POINTER:
5561 if (!*found) return WS_E_INVALID_FORMAT;
5562 /* fall through */
5564 case WS_READ_OPTIONAL_POINTER:
5565 case WS_READ_NILLABLE_POINTER:
5567 GUID *heap_val = NULL;
5568 if (size != sizeof(heap_val)) return E_INVALIDARG;
5569 if (*found)
5571 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5572 *heap_val = val;
5574 *(GUID **)ret = heap_val;
5575 break;
5577 default:
5578 FIXME( "read option %u not supported\n", option );
5579 return E_NOTIMPL;
5582 return S_OK;
5585 static HRESULT text_to_unique_id( const WS_XML_TEXT *text, WS_HEAP *heap, WS_UNIQUE_ID *val )
5587 HRESULT hr;
5589 switch (text->textType)
5591 case WS_XML_TEXT_TYPE_UTF8:
5593 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5594 hr = str_to_unique_id( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5595 break;
5597 case WS_XML_TEXT_TYPE_UNIQUE_ID:
5599 const WS_XML_UNIQUE_ID_TEXT *text_unique_id = (const WS_XML_UNIQUE_ID_TEXT *)text;
5600 val->guid = text_unique_id->value;
5601 val->uri.length = 0;
5602 val->uri.chars = NULL;
5603 hr = S_OK;
5604 break;
5606 default:
5607 FIXME( "unhandled text type %u\n", text->textType );
5608 return E_NOTIMPL;
5611 return hr;
5614 static HRESULT read_type_unique_id( struct reader *reader, WS_TYPE_MAPPING mapping,
5615 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5616 const WS_UNIQUE_ID_DESCRIPTION *desc, WS_READ_OPTION option,
5617 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5619 const WS_XML_TEXT *text;
5620 WS_UNIQUE_ID val = {{0}};
5621 HRESULT hr;
5623 if (desc) FIXME( "ignoring description\n" );
5625 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5626 if (*found && (hr = text_to_unique_id( text, heap, &val )) != S_OK) return hr;
5628 switch (option)
5630 case WS_READ_REQUIRED_VALUE:
5631 if (!*found) return WS_E_INVALID_FORMAT;
5632 /* fall through */
5634 case WS_READ_NILLABLE_VALUE:
5635 if (size != sizeof(val)) return E_INVALIDARG;
5636 *(WS_UNIQUE_ID *)ret = val;
5637 break;
5639 case WS_READ_REQUIRED_POINTER:
5640 if (!*found) return WS_E_INVALID_FORMAT;
5641 /* fall through */
5643 case WS_READ_OPTIONAL_POINTER:
5644 case WS_READ_NILLABLE_POINTER:
5646 WS_UNIQUE_ID *heap_val = NULL;
5647 if (size != sizeof(heap_val)) return E_INVALIDARG;
5648 if (*found)
5650 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5651 *heap_val = val;
5653 *(WS_UNIQUE_ID **)ret = heap_val;
5654 break;
5656 default:
5657 FIXME( "read option %u not supported\n", option );
5658 return E_NOTIMPL;
5661 return S_OK;
5664 static HRESULT text_to_string( const WS_XML_TEXT *text, WS_HEAP *heap, WS_STRING *val )
5666 HRESULT hr;
5668 switch (text->textType)
5670 case WS_XML_TEXT_TYPE_UTF8:
5672 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5673 hr = str_to_string( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5674 break;
5676 case WS_XML_TEXT_TYPE_UTF16:
5678 const WS_XML_UTF16_TEXT *text_utf16 = (const WS_XML_UTF16_TEXT *)text;
5679 if (!(val->chars = ws_alloc( heap, text_utf16->byteCount ))) return WS_E_QUOTA_EXCEEDED;
5680 memcpy( val->chars, text_utf16->bytes, text_utf16->byteCount );
5681 val->length = text_utf16->byteCount / sizeof(WCHAR);
5682 hr = S_OK;
5683 break;
5685 default:
5686 FIXME( "unhandled text type %u\n", text->textType );
5687 return E_NOTIMPL;
5690 return hr;
5693 static HRESULT read_type_string( struct reader *reader, WS_TYPE_MAPPING mapping,
5694 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5695 const WS_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
5696 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5698 const WS_XML_TEXT *text;
5699 WS_STRING val = {0};
5700 HRESULT hr;
5702 if (desc) FIXME( "ignoring description\n" );
5704 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5705 if (*found && (hr = text_to_string( text, heap, &val )) != S_OK) return hr;
5707 switch (option)
5709 case WS_READ_REQUIRED_VALUE:
5710 case WS_READ_NILLABLE_VALUE:
5711 if (size != sizeof(val)) return E_INVALIDARG;
5712 *(WS_STRING *)ret = val;
5713 break;
5715 case WS_READ_REQUIRED_POINTER:
5717 WS_STRING *heap_val;
5718 if (size != sizeof(heap_val)) return E_INVALIDARG;
5719 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5720 *heap_val = val;
5721 *(WS_STRING **)ret = heap_val;
5722 break;
5724 case WS_READ_OPTIONAL_POINTER:
5725 case WS_READ_NILLABLE_POINTER:
5727 WS_STRING *heap_val = NULL;
5728 if (size != sizeof(heap_val)) return E_INVALIDARG;
5729 if (*found)
5731 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5732 *heap_val = val;
5734 *(WS_STRING **)ret = heap_val;
5735 break;
5737 default:
5738 FIXME( "read option %u not supported\n", option );
5739 return E_NOTIMPL;
5742 return S_OK;
5745 static HRESULT text_to_bytes( const WS_XML_TEXT *text, WS_HEAP *heap, WS_BYTES *val )
5747 HRESULT hr;
5749 switch (text->textType)
5751 case WS_XML_TEXT_TYPE_UTF8:
5753 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5754 hr = str_to_bytes( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5755 break;
5757 case WS_XML_TEXT_TYPE_BASE64:
5759 const WS_XML_BASE64_TEXT *text_base64 = (const WS_XML_BASE64_TEXT *)text;
5760 if (!(val->bytes = ws_alloc( heap, text_base64->length ))) return WS_E_QUOTA_EXCEEDED;
5761 memcpy( val->bytes, text_base64->bytes, text_base64->length );
5762 val->length = text_base64->length;
5763 hr = S_OK;
5764 break;
5766 default:
5767 FIXME( "unhandled text type %u\n", text->textType );
5768 return E_NOTIMPL;
5771 return hr;
5774 static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
5775 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5776 const WS_BYTES_DESCRIPTION *desc, WS_READ_OPTION option,
5777 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5779 const WS_XML_TEXT *text;
5780 WS_BYTES val = {0};
5781 HRESULT hr;
5783 if (desc) FIXME( "ignoring description\n" );
5785 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5786 if (*found && (hr = text_to_bytes( text, heap, &val )) != S_OK) return hr;
5788 switch (option)
5790 case WS_READ_REQUIRED_VALUE:
5791 case WS_READ_NILLABLE_VALUE:
5792 if (size != sizeof(val)) return E_INVALIDARG;
5793 *(WS_BYTES *)ret = val;
5794 break;
5796 case WS_READ_REQUIRED_POINTER:
5798 WS_BYTES *heap_val;
5799 if (size != sizeof(heap_val)) return E_INVALIDARG;
5800 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5801 *heap_val = val;
5802 *(WS_BYTES **)ret = heap_val;
5803 break;
5805 case WS_READ_OPTIONAL_POINTER:
5806 case WS_READ_NILLABLE_POINTER:
5808 WS_BYTES *heap_val = NULL;
5809 if (size != sizeof(heap_val)) return E_INVALIDARG;
5810 if (*found)
5812 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5813 *heap_val = val;
5815 *(WS_BYTES **)ret = heap_val;
5816 break;
5818 default:
5819 FIXME( "read option %u not supported\n", option );
5820 return E_NOTIMPL;
5823 return S_OK;
5826 static HRESULT text_to_xml_string( const WS_XML_TEXT *text, WS_HEAP *heap, WS_XML_STRING *val )
5828 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5829 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5830 return str_to_xml_string( utf8->value.bytes, utf8->value.length, heap, val );
5833 static HRESULT read_type_xml_string( struct reader *reader, WS_TYPE_MAPPING mapping,
5834 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5835 const WS_XML_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
5836 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5838 const WS_XML_TEXT *text;
5839 WS_XML_STRING val = {0};
5840 HRESULT hr;
5842 if (desc) FIXME( "ignoring description\n" );
5844 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5845 if (*found && (hr = text_to_xml_string( text, heap, &val )) != S_OK) return hr;
5847 switch (option)
5849 case WS_READ_REQUIRED_VALUE:
5850 case WS_READ_NILLABLE_VALUE:
5851 if (size != sizeof(val)) return E_INVALIDARG;
5852 *(WS_XML_STRING *)ret = val;
5853 break;
5855 case WS_READ_REQUIRED_POINTER:
5857 WS_XML_STRING *heap_val;
5858 if (size != sizeof(heap_val)) return E_INVALIDARG;
5859 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5860 *heap_val = val;
5861 *(WS_XML_STRING **)ret = heap_val;
5862 break;
5864 case WS_READ_OPTIONAL_POINTER:
5865 case WS_READ_NILLABLE_POINTER:
5867 WS_XML_STRING *heap_val = NULL;
5868 if (size != sizeof(heap_val)) return E_INVALIDARG;
5869 if (*found)
5871 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5872 *heap_val = val;
5874 *(WS_XML_STRING **)ret = heap_val;
5875 break;
5877 default:
5878 FIXME( "read option %u not supported\n", option );
5879 return E_NOTIMPL;
5882 return S_OK;
5885 static HRESULT text_to_qname( struct reader *reader, const WS_XML_TEXT *text, WS_HEAP *heap, WS_XML_QNAME *val )
5887 HRESULT hr;
5889 switch (text->textType)
5891 case WS_XML_TEXT_TYPE_UTF8:
5893 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5894 hr = str_to_qname( reader, text_utf8->value.bytes, text_utf8->value.length, heap, NULL,
5895 &val->localName, &val->ns );
5896 break;
5898 case WS_XML_TEXT_TYPE_QNAME:
5900 const WS_XML_QNAME_TEXT *text_qname = (const WS_XML_QNAME_TEXT *)text;
5901 if ((hr = copy_xml_string( heap, text_qname->localName, &val->localName )) != S_OK) return hr;
5902 if ((hr = copy_xml_string( heap, text_qname->ns, &val->ns )) != S_OK)
5904 ws_free( heap, val->localName.bytes, val->localName.length );
5905 return hr;
5907 break;
5909 default:
5910 FIXME( "unhandled text type %u\n", text->textType );
5911 return E_NOTIMPL;
5914 return hr;
5917 static HRESULT read_type_qname( struct reader *reader, WS_TYPE_MAPPING mapping,
5918 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5919 const WS_XML_QNAME_DESCRIPTION *desc, WS_READ_OPTION option,
5920 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
5922 const WS_XML_TEXT *text;
5923 WS_XML_QNAME val = {{0}};
5924 HRESULT hr;
5926 if (desc) FIXME( "ignoring description\n" );
5928 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
5929 if ((hr = read_startelement( reader )) != S_OK) return hr;
5930 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
5932 if ((hr = get_text( reader, mapping, localname, ns, &text, found )) != S_OK) return hr;
5933 if (*found && (hr = text_to_qname( reader, text, heap, &val )) != S_OK) return hr;
5935 switch (option)
5937 case WS_READ_REQUIRED_VALUE:
5938 if (!*found) return WS_E_INVALID_FORMAT;
5939 /* fall through */
5941 case WS_READ_NILLABLE_VALUE:
5942 if (size != sizeof(val)) return E_INVALIDARG;
5943 *(WS_XML_QNAME *)ret = val;
5944 break;
5946 case WS_READ_REQUIRED_POINTER:
5947 if (!*found) return WS_E_INVALID_FORMAT;
5948 /* fall through */
5950 case WS_READ_OPTIONAL_POINTER:
5951 case WS_READ_NILLABLE_POINTER:
5953 WS_XML_QNAME *heap_val = NULL;
5954 if (size != sizeof(heap_val)) return E_INVALIDARG;
5955 if (*found)
5957 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5958 *heap_val = val;
5960 *(WS_XML_QNAME **)ret = heap_val;
5961 break;
5963 default:
5964 FIXME( "read option %u not supported\n", option );
5965 return E_NOTIMPL;
5968 return S_OK;
5971 static BOOL is_empty_text_node( const struct node *node )
5973 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
5975 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
5976 switch (text->text->textType)
5978 case WS_XML_TEXT_TYPE_UTF8:
5980 ULONG i;
5981 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
5982 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
5983 return TRUE;
5985 case WS_XML_TEXT_TYPE_BASE64:
5987 const WS_XML_BASE64_TEXT *base64 = (const WS_XML_BASE64_TEXT *)text->text;
5988 return !base64->length;
5990 case WS_XML_TEXT_TYPE_BOOL:
5991 case WS_XML_TEXT_TYPE_INT32:
5992 case WS_XML_TEXT_TYPE_INT64:
5993 case WS_XML_TEXT_TYPE_UINT64:
5994 case WS_XML_TEXT_TYPE_FLOAT:
5995 case WS_XML_TEXT_TYPE_DOUBLE:
5996 case WS_XML_TEXT_TYPE_DECIMAL:
5997 case WS_XML_TEXT_TYPE_GUID:
5998 case WS_XML_TEXT_TYPE_UNIQUE_ID:
5999 case WS_XML_TEXT_TYPE_DATETIME:
6000 return FALSE;
6002 default:
6003 ERR( "unhandled text type %u\n", text->text->textType );
6004 return FALSE;
6008 /* skips comment and empty text nodes */
6009 static HRESULT read_type_next_node( struct reader *reader )
6011 for (;;)
6013 HRESULT hr;
6014 WS_XML_NODE_TYPE type;
6016 if ((hr = read_next_node( reader )) != S_OK) return hr;
6017 type = node_type( reader->current );
6018 if (type == WS_XML_NODE_TYPE_COMMENT ||
6019 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
6020 return S_OK;
6024 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
6025 const WS_XML_STRING *ns )
6027 struct reader_pos pos;
6028 HRESULT hr;
6030 if (!localname) return S_OK; /* assume reader is already correctly positioned */
6031 if (reader->current == reader->last)
6033 BOOL found;
6034 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
6035 if (!found) return WS_E_INVALID_FORMAT;
6037 if (match_element( reader->current, localname, ns )) return S_OK;
6039 save_reader_position( reader, &pos );
6040 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6041 if (match_element( reader->current, localname, ns )) return S_OK;
6042 restore_reader_position( reader, &pos );
6044 return WS_E_INVALID_FORMAT;
6047 ULONG get_type_size( WS_TYPE type, const void *desc )
6049 switch (type)
6051 case WS_INT8_TYPE:
6052 case WS_UINT8_TYPE:
6053 return sizeof(INT8);
6055 case WS_INT16_TYPE:
6056 case WS_UINT16_TYPE:
6057 return sizeof(INT16);
6059 case WS_BOOL_TYPE:
6060 case WS_INT32_TYPE:
6061 case WS_UINT32_TYPE:
6062 case WS_ENUM_TYPE:
6063 return sizeof(INT32);
6065 case WS_INT64_TYPE:
6066 case WS_UINT64_TYPE:
6067 return sizeof(INT64);
6069 case WS_FLOAT_TYPE:
6070 return sizeof(float);
6072 case WS_DOUBLE_TYPE:
6073 return sizeof(double);
6075 case WS_DATETIME_TYPE:
6076 return sizeof(WS_DATETIME);
6078 case WS_GUID_TYPE:
6079 return sizeof(GUID);
6081 case WS_UNIQUE_ID_TYPE:
6082 return sizeof(WS_UNIQUE_ID);
6084 case WS_STRING_TYPE:
6085 return sizeof(WS_STRING);
6087 case WS_WSZ_TYPE:
6088 return sizeof(WCHAR *);
6090 case WS_BYTES_TYPE:
6091 return sizeof(WS_BYTES);
6093 case WS_XML_STRING_TYPE:
6094 return sizeof(WS_XML_STRING);
6096 case WS_XML_QNAME_TYPE:
6097 return sizeof(WS_XML_QNAME);
6099 case WS_DESCRIPTION_TYPE:
6100 return sizeof(WS_STRUCT_DESCRIPTION *);
6102 case WS_STRUCT_TYPE:
6104 const WS_STRUCT_DESCRIPTION *desc_struct = desc;
6105 return desc_struct->size;
6107 case WS_UNION_TYPE:
6109 const WS_UNION_DESCRIPTION *desc_union = desc;
6110 return desc_union->size;
6112 case WS_ANY_ATTRIBUTES_TYPE:
6113 return 0;
6115 default:
6116 ERR( "unhandled type %u\n", type );
6117 return 0;
6121 static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
6123 if (options & WS_FIELD_POINTER)
6125 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
6126 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
6127 return WS_READ_REQUIRED_POINTER;
6130 switch (type)
6132 case WS_BOOL_TYPE:
6133 case WS_INT8_TYPE:
6134 case WS_INT16_TYPE:
6135 case WS_INT32_TYPE:
6136 case WS_INT64_TYPE:
6137 case WS_UINT8_TYPE:
6138 case WS_UINT16_TYPE:
6139 case WS_UINT32_TYPE:
6140 case WS_UINT64_TYPE:
6141 case WS_FLOAT_TYPE:
6142 case WS_DOUBLE_TYPE:
6143 case WS_DATETIME_TYPE:
6144 case WS_GUID_TYPE:
6145 case WS_UNIQUE_ID_TYPE:
6146 case WS_STRING_TYPE:
6147 case WS_BYTES_TYPE:
6148 case WS_XML_STRING_TYPE:
6149 case WS_XML_QNAME_TYPE:
6150 case WS_STRUCT_TYPE:
6151 case WS_ENUM_TYPE:
6152 case WS_UNION_TYPE:
6153 if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
6154 return WS_READ_REQUIRED_VALUE;
6156 case WS_WSZ_TYPE:
6157 case WS_DESCRIPTION_TYPE:
6158 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
6159 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
6160 return WS_READ_REQUIRED_POINTER;
6162 default:
6163 FIXME( "unhandled type %u\n", type );
6164 return 0;
6168 static HRESULT read_type_field( struct reader *, const WS_FIELD_DESCRIPTION *, WS_HEAP *, char *, ULONG );
6170 static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_HEAP *heap, void *ret,
6171 ULONG size, BOOL *found )
6173 struct reader_pos pos;
6174 HRESULT hr;
6175 ULONG i;
6177 if (size != desc->size) return E_INVALIDARG;
6179 save_reader_position( reader, &pos );
6180 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6182 for (i = 0; i < desc->fieldCount; i++)
6184 if ((*found = match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns )))
6185 break;
6188 if (!*found)
6190 *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
6191 restore_reader_position( reader, &pos );
6193 else
6195 ULONG offset = desc->fields[i]->field.offset;
6196 if ((hr = read_type_field( reader, &desc->fields[i]->field, heap, ret, offset )) != S_OK) return hr;
6197 *(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
6200 return S_OK;
6203 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
6204 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
6205 void *, ULONG, BOOL * );
6207 static HRESULT read_type_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
6208 void **ret, ULONG *count )
6210 HRESULT hr;
6211 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
6212 WS_READ_OPTION option;
6213 BOOL found;
6214 char *buf;
6216 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
6218 /* wrapper element */
6219 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
6220 return hr;
6222 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
6223 item_size = get_type_size( desc->type, desc->typeDescription );
6224 else
6225 item_size = sizeof(void *);
6227 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
6228 for (;;)
6230 if (nb_items >= nb_allocated)
6232 SIZE_T old_size = nb_allocated * item_size, new_size = old_size * 2;
6233 if (!(buf = ws_realloc_zero( heap, buf, old_size, new_size ))) return WS_E_QUOTA_EXCEEDED;
6234 nb_allocated *= 2;
6237 if (desc->type == WS_UNION_TYPE)
6239 hr = read_type_union( reader, desc->typeDescription, heap, buf + offset, item_size, &found );
6240 if (hr != S_OK)
6242 ws_free( heap, buf, nb_allocated * item_size );
6243 return hr;
6245 if (!found) break;
6247 else
6249 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
6250 desc->typeDescription, option, heap, buf + offset, item_size, &found );
6251 if (hr == WS_E_INVALID_FORMAT) break;
6252 if (hr != S_OK)
6254 ws_free( heap, buf, nb_allocated * item_size );
6255 return hr;
6259 offset += item_size;
6260 nb_items++;
6263 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
6265 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
6267 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
6268 desc->itemRange->maxItemCount );
6269 ws_free( heap, buf, nb_allocated * item_size );
6270 return WS_E_INVALID_FORMAT;
6273 *count = nb_items;
6274 *ret = buf;
6276 return S_OK;
6279 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
6280 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
6282 struct reader_pos pos;
6283 BOOL found;
6284 HRESULT hr;
6286 if (reader->current == reader->last)
6288 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
6289 if (!found) return WS_E_INVALID_FORMAT;
6292 save_reader_position( reader, &pos );
6293 if ((hr = read_next_node( reader )) != S_OK) return hr;
6294 hr = read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
6295 desc->typeDescription, option, heap, ret, size, &found );
6296 if (hr == S_OK && !found) restore_reader_position( reader, &pos );
6297 return hr;
6300 static HRESULT read_type_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, char *buf,
6301 ULONG offset )
6303 char *ptr;
6304 WS_READ_OPTION option;
6305 ULONG size;
6306 HRESULT hr;
6307 BOOL found;
6309 if (!desc) return E_INVALIDARG;
6310 if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE|WS_FIELD_NILLABLE_ITEM))
6312 FIXME( "options %08x not supported\n", desc->options );
6313 return E_NOTIMPL;
6315 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
6317 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
6318 size = get_type_size( desc->type, desc->typeDescription );
6319 else
6320 size = sizeof(void *);
6322 ptr = buf + offset;
6323 switch (desc->mapping)
6325 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING:
6326 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
6327 return S_OK;
6329 case WS_ATTRIBUTE_FIELD_MAPPING:
6330 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
6331 desc->typeDescription, option, heap, ptr, size, &found );
6332 break;
6334 case WS_ELEMENT_FIELD_MAPPING:
6335 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
6336 desc->typeDescription, option, heap, ptr, size, &found );
6337 break;
6339 case WS_ELEMENT_CHOICE_FIELD_MAPPING:
6341 if (desc->type != WS_UNION_TYPE || !desc->typeDescription ||
6342 (desc->options & (WS_FIELD_POINTER|WS_FIELD_NILLABLE))) return E_INVALIDARG;
6343 hr = read_type_union( reader, desc->typeDescription, heap, ptr, size, &found );
6344 break;
6346 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
6347 case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING:
6349 ULONG count;
6350 hr = read_type_array( reader, desc, heap, (void **)ptr, &count );
6351 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
6352 break;
6354 case WS_TEXT_FIELD_MAPPING:
6355 hr = read_type_text( reader, desc, option, heap, ptr, size );
6356 break;
6358 default:
6359 FIXME( "unhandled field mapping %u\n", desc->mapping );
6360 return E_NOTIMPL;
6363 if (hr == WS_E_INVALID_FORMAT)
6365 switch (option)
6367 case WS_READ_REQUIRED_VALUE:
6368 case WS_READ_REQUIRED_POINTER:
6369 return WS_E_INVALID_FORMAT;
6371 case WS_READ_NILLABLE_VALUE:
6372 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
6373 return S_OK;
6375 case WS_READ_OPTIONAL_POINTER:
6376 case WS_READ_NILLABLE_POINTER:
6377 *(void **)ptr = NULL;
6378 return S_OK;
6380 default:
6381 ERR( "unhandled option %u\n", option );
6382 return E_NOTIMPL;
6386 return hr;
6389 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
6390 const WS_XML_STRING *ns, const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
6391 WS_HEAP *heap, void *ret, ULONG size, BOOL *found )
6393 ULONG i, offset;
6394 HRESULT hr;
6395 char *buf;
6397 if (!desc) return E_INVALIDARG;
6398 if (desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6400 FIXME( "struct options %08x not supported\n",
6401 desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT );
6404 switch (option)
6406 case WS_READ_REQUIRED_POINTER:
6407 case WS_READ_OPTIONAL_POINTER:
6408 case WS_READ_NILLABLE_POINTER:
6409 if (size != sizeof(void *)) return E_INVALIDARG;
6410 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
6411 break;
6413 case WS_READ_REQUIRED_VALUE:
6414 case WS_READ_NILLABLE_VALUE:
6415 if (size != desc->size) return E_INVALIDARG;
6416 buf = ret;
6417 break;
6419 default:
6420 FIXME( "unhandled read option %u\n", option );
6421 return E_NOTIMPL;
6424 for (i = 0; i < desc->fieldCount; i++)
6426 offset = desc->fields[i]->offset;
6427 if ((hr = read_type_field( reader, desc->fields[i], heap, buf, offset )) != S_OK) break;
6430 switch (option)
6432 case WS_READ_REQUIRED_POINTER:
6433 if (hr != S_OK)
6435 ws_free( heap, buf, desc->size );
6436 return hr;
6438 *(char **)ret = buf;
6439 break;
6441 case WS_READ_OPTIONAL_POINTER:
6442 case WS_READ_NILLABLE_POINTER:
6443 if (is_nil_value( buf, desc->size ))
6445 ws_free( heap, buf, desc->size );
6446 buf = NULL;
6448 *(char **)ret = buf;
6449 break;
6451 case WS_READ_REQUIRED_VALUE:
6452 case WS_READ_NILLABLE_VALUE:
6453 if (hr != S_OK) return hr;
6454 break;
6456 default:
6457 ERR( "unhandled read option %u\n", option );
6458 return E_NOTIMPL;
6461 if (desc->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6463 struct node *parent = find_parent( reader );
6464 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
6467 *found = TRUE;
6468 return S_OK;
6471 static HRESULT start_mapping( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
6472 const WS_XML_STRING *ns )
6474 switch (mapping)
6476 case WS_ELEMENT_TYPE_MAPPING:
6477 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
6478 return read_type_next_element_node( reader, localname, ns );
6480 case WS_ANY_ELEMENT_TYPE_MAPPING:
6481 case WS_ATTRIBUTE_TYPE_MAPPING:
6482 return S_OK;
6484 default:
6485 FIXME( "unhandled mapping %u\n", mapping );
6486 return E_NOTIMPL;
6490 static HRESULT read_type_endelement_node( struct reader *reader )
6492 const struct node *parent = find_parent( reader );
6493 HRESULT hr;
6495 for (;;)
6497 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6498 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == parent)
6500 return S_OK;
6502 if (read_end_of_data( reader ) || !(parent->flags & NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT)) break;
6505 return WS_E_INVALID_FORMAT;
6508 static HRESULT end_mapping( struct reader *reader, WS_TYPE_MAPPING mapping )
6510 switch (mapping)
6512 case WS_ELEMENT_TYPE_MAPPING:
6513 return read_type_endelement_node( reader );
6515 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
6516 return read_type_next_node( reader );
6518 case WS_ATTRIBUTE_TYPE_MAPPING:
6519 default:
6520 return S_OK;
6524 static BOOL is_true_text( const WS_XML_TEXT *text )
6526 switch (text->textType)
6528 case WS_XML_TEXT_TYPE_UTF8:
6530 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
6531 if (text_utf8->value.length == 4 && !memcmp( text_utf8->value.bytes, "true", 4 )) return TRUE;
6532 return FALSE;
6534 case WS_XML_TEXT_TYPE_BOOL:
6536 const WS_XML_BOOL_TEXT *text_bool = (const WS_XML_BOOL_TEXT *)text;
6537 return text_bool->value;
6539 default:
6540 ERR( "unhandled text type %u\n", text->textType );
6541 return FALSE;
6545 static HRESULT is_nil_element( const WS_XML_ELEMENT_NODE *elem )
6547 static const WS_XML_STRING localname = {3, (BYTE *)"nil"};
6548 static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance"};
6549 ULONG i;
6551 for (i = 0; i < elem->attributeCount; i++)
6553 if (elem->attributes[i]->isXmlNs) continue;
6554 if (WsXmlStringEquals( elem->attributes[i]->localName, &localname, NULL ) == S_OK &&
6555 WsXmlStringEquals( elem->attributes[i]->ns, &ns, NULL ) == S_OK &&
6556 is_true_text( elem->attributes[i]->value )) return TRUE;
6558 return FALSE;
6561 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
6562 const WS_XML_STRING *localname, const WS_XML_STRING *ns, const void *desc,
6563 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size, BOOL *found )
6565 HRESULT hr;
6567 if ((hr = start_mapping( reader, mapping, localname, ns )) != S_OK) return hr;
6569 if (mapping == WS_ELEMENT_TYPE_MAPPING && is_nil_element( &reader->current->hdr ))
6571 if (option != WS_READ_NILLABLE_POINTER && option != WS_READ_NILLABLE_VALUE) return WS_E_INVALID_FORMAT;
6572 *found = TRUE;
6573 return end_mapping( reader, mapping );
6576 switch (type)
6578 case WS_BOOL_TYPE:
6579 hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6580 break;
6582 case WS_INT8_TYPE:
6583 hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6584 break;
6586 case WS_INT16_TYPE:
6587 hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6588 break;
6590 case WS_INT32_TYPE:
6591 hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6592 break;
6594 case WS_INT64_TYPE:
6595 hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6596 break;
6598 case WS_UINT8_TYPE:
6599 hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6600 break;
6602 case WS_UINT16_TYPE:
6603 hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6604 break;
6606 case WS_UINT32_TYPE:
6607 hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6608 break;
6610 case WS_UINT64_TYPE:
6611 hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6612 break;
6614 case WS_FLOAT_TYPE:
6615 hr = read_type_float( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6616 break;
6618 case WS_DOUBLE_TYPE:
6619 hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6620 break;
6622 case WS_DATETIME_TYPE:
6623 hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6624 break;
6626 case WS_GUID_TYPE:
6627 hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6628 break;
6630 case WS_UNIQUE_ID_TYPE:
6631 hr = read_type_unique_id( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6632 break;
6634 case WS_STRING_TYPE:
6635 hr = read_type_string( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6636 break;
6638 case WS_WSZ_TYPE:
6639 hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6640 break;
6642 case WS_BYTES_TYPE:
6643 hr = read_type_bytes( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6644 break;
6646 case WS_XML_STRING_TYPE:
6647 hr = read_type_xml_string( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6648 break;
6650 case WS_XML_QNAME_TYPE:
6651 hr = read_type_qname( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6652 break;
6654 case WS_STRUCT_TYPE:
6655 hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6656 break;
6658 case WS_ENUM_TYPE:
6659 hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size, found );
6660 break;
6662 default:
6663 FIXME( "type %u not supported\n", type );
6664 return E_NOTIMPL;
6667 if (hr != S_OK) return hr;
6668 return end_mapping( reader, mapping );
6671 /**************************************************************************
6672 * WsReadType [webservices.@]
6674 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
6675 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
6676 ULONG size, WS_ERROR *error )
6678 struct reader *reader = (struct reader *)handle;
6679 BOOL found;
6680 HRESULT hr;
6682 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
6683 size, error );
6684 if (error) FIXME( "ignoring error parameter\n" );
6686 if (!reader || !value) return E_INVALIDARG;
6688 EnterCriticalSection( &reader->cs );
6690 if (reader->magic != READER_MAGIC)
6692 LeaveCriticalSection( &reader->cs );
6693 return E_INVALIDARG;
6696 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size, &found )) == S_OK)
6698 switch (mapping)
6700 case WS_ELEMENT_TYPE_MAPPING:
6701 hr = read_node( reader );
6702 break;
6704 default:
6705 break;
6707 if (hr == S_OK && !read_end_of_data( reader )) hr = WS_E_INVALID_FORMAT;
6710 LeaveCriticalSection( &reader->cs );
6711 TRACE( "returning %08x\n", hr );
6712 return hr;
6715 HRESULT read_header( WS_XML_READER *handle, const WS_XML_STRING *localname, const WS_XML_STRING *ns,
6716 WS_TYPE type, const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
6717 ULONG size )
6719 struct reader *reader = (struct reader *)handle;
6720 BOOL found;
6721 HRESULT hr;
6723 EnterCriticalSection( &reader->cs );
6725 if (reader->magic != READER_MAGIC)
6727 LeaveCriticalSection( &reader->cs );
6728 return E_INVALIDARG;
6731 hr = read_type( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, localname, ns, desc, option, heap,
6732 value, size, &found );
6734 LeaveCriticalSection( &reader->cs );
6735 return hr;
6738 /**************************************************************************
6739 * WsReadElement [webservices.@]
6741 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
6742 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
6743 WS_ERROR *error )
6745 struct reader *reader = (struct reader *)handle;
6746 BOOL found;
6747 HRESULT hr;
6749 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
6750 if (error) FIXME( "ignoring error parameter\n" );
6752 if (!reader || !desc || !value) return E_INVALIDARG;
6754 EnterCriticalSection( &reader->cs );
6756 if (reader->magic != READER_MAGIC)
6758 LeaveCriticalSection( &reader->cs );
6759 return E_INVALIDARG;
6762 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
6763 desc->elementNs, desc->typeDescription, option, heap, value, size, &found );
6765 LeaveCriticalSection( &reader->cs );
6766 TRACE( "returning %08x\n", hr );
6767 return hr;
6770 /**************************************************************************
6771 * WsReadValue [webservices.@]
6773 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
6774 WS_ERROR *error )
6776 struct reader *reader = (struct reader *)handle;
6777 WS_TYPE type = map_value_type( value_type );
6778 BOOL found;
6779 HRESULT hr;
6781 TRACE( "%p %u %p %u %p\n", handle, type, value, size, error );
6782 if (error) FIXME( "ignoring error parameter\n" );
6784 if (!reader || !value || type == ~0u) return E_INVALIDARG;
6786 EnterCriticalSection( &reader->cs );
6788 if (reader->magic != READER_MAGIC)
6790 LeaveCriticalSection( &reader->cs );
6791 return E_INVALIDARG;
6794 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
6795 NULL, value, size, &found );
6797 LeaveCriticalSection( &reader->cs );
6798 TRACE( "returning %08x\n", hr );
6799 return hr;
6802 /**************************************************************************
6803 * WsReadAttribute [webservices.@]
6805 HRESULT WINAPI WsReadAttribute( WS_XML_READER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
6806 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
6807 WS_ERROR *error )
6809 struct reader *reader = (struct reader *)handle;
6810 BOOL found;
6811 HRESULT hr;
6813 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
6814 if (error) FIXME( "ignoring error parameter\n" );
6816 if (!reader || !desc || !value) return E_INVALIDARG;
6818 EnterCriticalSection( &reader->cs );
6820 if (reader->magic != READER_MAGIC)
6822 LeaveCriticalSection( &reader->cs );
6823 return E_INVALIDARG;
6826 if (!reader->input_type) hr = WS_E_INVALID_OPERATION;
6827 else hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->attributeLocalName,
6828 desc->attributeNs, desc->typeDescription, option, heap, value, size, &found );
6830 LeaveCriticalSection( &reader->cs );
6831 TRACE( "returning %08x\n", hr );
6832 return hr;
6835 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
6837 static const char bom[] = {0xef,0xbb,0xbf};
6838 return (size >= sizeof(bom) && !memcmp( data, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
6839 (size > 2 && !(*offset = 0));
6842 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
6844 static const char bom[] = {0xff,0xfe};
6845 return (size >= sizeof(bom) && !memcmp( data, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
6846 (size >= 4 && data[0] == '<' && !data[1] && !(*offset = 0));
6849 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
6851 WS_CHARSET ret = 0;
6853 /* FIXME: parse xml declaration */
6855 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
6856 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
6857 else
6859 FIXME( "charset not recognized\n" );
6860 return 0;
6863 TRACE( "detected charset %u\n", ret );
6864 return ret;
6867 static void set_input_buffer( struct reader *reader, const unsigned char *data, ULONG size )
6869 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
6870 reader->input_buf = NULL;
6871 reader->input_data = data;
6872 reader->input_size = size;
6874 reader->read_size = reader->input_size;
6875 reader->read_pos = 0;
6876 reader->read_bufptr = reader->input_data;
6878 reader->text_conv_offset = 0;
6881 static void set_input_stream( struct reader *reader, WS_READ_CALLBACK callback, void *state )
6883 reader->input_type = WS_XML_READER_INPUT_TYPE_STREAM;
6884 reader->input_cb = callback;
6885 reader->input_cb_state = state;
6886 reader->input_buf = NULL;
6887 reader->input_data = reader->stream_buf;
6888 reader->input_size = STREAM_BUFSIZE;
6890 if (reader->read_pos >= reader->read_size) reader->read_size = 0;
6891 else
6893 memmove( reader->stream_buf, reader->stream_buf + reader->read_pos, reader->read_size - reader->read_pos );
6894 reader->read_size -= reader->read_pos;
6896 reader->read_pos = 0;
6897 reader->read_bufptr = reader->input_data;
6899 reader->text_conv_offset = 0;
6902 /**************************************************************************
6903 * WsSetInput [webservices.@]
6905 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
6906 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
6907 ULONG count, WS_ERROR *error )
6909 struct reader *reader = (struct reader *)handle;
6910 struct node *node;
6911 ULONG i, offset = 0;
6912 HRESULT hr;
6914 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
6915 if (error) FIXME( "ignoring error parameter\n" );
6917 if (!reader) return E_INVALIDARG;
6919 EnterCriticalSection( &reader->cs );
6921 if (reader->magic != READER_MAGIC)
6923 LeaveCriticalSection( &reader->cs );
6924 return E_INVALIDARG;
6927 for (i = 0; i < count; i++)
6929 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
6930 properties[i].valueSize );
6931 if (hr != S_OK) goto done;
6934 if ((hr = init_reader( reader )) != S_OK) goto done;
6936 switch (encoding->encodingType)
6938 case WS_XML_READER_ENCODING_TYPE_TEXT:
6940 if (input->inputType == WS_XML_READER_INPUT_TYPE_BUFFER)
6942 const WS_XML_READER_TEXT_ENCODING *text = (const WS_XML_READER_TEXT_ENCODING *)encoding;
6943 const WS_XML_READER_BUFFER_INPUT *buf = (const WS_XML_READER_BUFFER_INPUT *)input;
6944 if (text->charSet != WS_CHARSET_AUTO) reader->input_charset = text->charSet;
6945 else reader->input_charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
6948 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
6949 break;
6951 case WS_XML_READER_ENCODING_TYPE_BINARY:
6953 const WS_XML_READER_BINARY_ENCODING *bin = (const WS_XML_READER_BINARY_ENCODING *)encoding;
6954 reader->input_enc = WS_XML_READER_ENCODING_TYPE_BINARY;
6955 reader->input_charset = 0;
6956 reader->dict_static = bin->staticDictionary ? bin->staticDictionary : &dict_builtin_static.dict;
6957 reader->dict = bin->dynamicDictionary ? bin->dynamicDictionary : &dict_builtin.dict;
6958 break;
6960 default:
6961 FIXME( "encoding type %u not supported\n", encoding->encodingType );
6962 hr = E_NOTIMPL;
6963 goto done;
6966 switch (input->inputType)
6968 case WS_XML_READER_INPUT_TYPE_BUFFER:
6970 const WS_XML_READER_BUFFER_INPUT *buf = (const WS_XML_READER_BUFFER_INPUT *)input;
6971 set_input_buffer( reader, (const unsigned char *)buf->encodedData + offset, buf->encodedDataSize - offset );
6972 break;
6974 case WS_XML_READER_INPUT_TYPE_STREAM:
6976 const WS_XML_READER_STREAM_INPUT *stream = (const WS_XML_READER_STREAM_INPUT *)input;
6977 if (!reader->stream_buf && !(reader->stream_buf = heap_alloc( STREAM_BUFSIZE )))
6979 hr = E_OUTOFMEMORY;
6980 goto done;
6982 set_input_stream( reader, stream->readCallback, stream->readCallbackState );
6983 break;
6985 default:
6986 FIXME( "input type %u not supported\n", input->inputType );
6987 hr = E_NOTIMPL;
6988 goto done;
6991 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
6992 else read_insert_bof( reader, node );
6994 done:
6995 LeaveCriticalSection( &reader->cs );
6996 TRACE( "returning %08x\n", hr );
6997 return hr;
7000 static void set_input_xml_buffer( struct reader *reader, struct xmlbuf *buf )
7002 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
7003 reader->input_buf = buf;
7004 reader->input_enc = buf->encoding;
7005 reader->input_charset = buf->charset;
7006 reader->input_data = buf->bytes.bytes;
7007 reader->input_size = buf->bytes.length;
7008 reader->dict_static = buf->dict_static;
7009 reader->dict = buf->dict;
7011 reader->read_size = reader->input_size;
7012 reader->read_pos = 0;
7013 reader->read_bufptr = reader->input_data;
7015 reader->text_conv_offset = 0;
7018 /**************************************************************************
7019 * WsSetInputToBuffer [webservices.@]
7021 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
7022 const WS_XML_READER_PROPERTY *properties, ULONG count,
7023 WS_ERROR *error )
7025 struct reader *reader = (struct reader *)handle;
7026 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
7027 struct node *node;
7028 HRESULT hr;
7029 ULONG i;
7031 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
7032 if (error) FIXME( "ignoring error parameter\n" );
7034 if (!reader || !xmlbuf) return E_INVALIDARG;
7036 EnterCriticalSection( &reader->cs );
7038 if (reader->magic != READER_MAGIC)
7040 LeaveCriticalSection( &reader->cs );
7041 return E_INVALIDARG;
7044 for (i = 0; i < count; i++)
7046 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
7047 properties[i].valueSize );
7048 if (hr != S_OK) goto done;
7051 if ((hr = init_reader( reader )) != S_OK) goto done;
7052 set_input_xml_buffer( reader, xmlbuf );
7054 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
7055 else read_insert_bof( reader, node );
7057 done:
7058 LeaveCriticalSection( &reader->cs );
7059 TRACE( "returning %08x\n", hr );
7060 return hr;
7063 /**************************************************************************
7064 * WsGetReaderPosition [webservices.@]
7066 HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
7068 struct reader *reader = (struct reader *)handle;
7069 HRESULT hr = S_OK;
7071 TRACE( "%p %p %p\n", handle, pos, error );
7072 if (error) FIXME( "ignoring error parameter\n" );
7074 if (!reader || !pos) return E_INVALIDARG;
7076 EnterCriticalSection( &reader->cs );
7078 if (reader->magic != READER_MAGIC)
7080 LeaveCriticalSection( &reader->cs );
7081 return E_INVALIDARG;
7084 if (!reader->input_buf) hr = WS_E_INVALID_OPERATION;
7085 else
7087 pos->buffer = (WS_XML_BUFFER *)reader->input_buf;
7088 pos->node = reader->current;
7091 LeaveCriticalSection( &reader->cs );
7092 TRACE( "returning %08x\n", hr );
7093 return hr;
7096 /**************************************************************************
7097 * WsSetReaderPosition [webservices.@]
7099 HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
7101 struct reader *reader = (struct reader *)handle;
7102 HRESULT hr = S_OK;
7104 TRACE( "%p %p %p\n", handle, pos, error );
7105 if (error) FIXME( "ignoring error parameter\n" );
7107 if (!reader || !pos) return E_INVALIDARG;
7109 EnterCriticalSection( &reader->cs );
7111 if (reader->magic != READER_MAGIC || (struct xmlbuf *)pos->buffer != reader->input_buf)
7113 LeaveCriticalSection( &reader->cs );
7114 return E_INVALIDARG;
7117 if (!reader->input_buf) hr = WS_E_INVALID_OPERATION;
7118 else reader->current = pos->node;
7120 LeaveCriticalSection( &reader->cs );
7121 TRACE( "returning %08x\n", hr );
7122 return hr;
7125 static HRESULT utf8_to_base64( const WS_XML_UTF8_TEXT *utf8, WS_XML_BASE64_TEXT *base64 )
7127 if (utf8->value.length % 4) return WS_E_INVALID_FORMAT;
7128 if (!(base64->bytes = heap_alloc( utf8->value.length * 3 / 4 ))) return E_OUTOFMEMORY;
7129 base64->length = decode_base64( utf8->value.bytes, utf8->value.length, base64->bytes );
7130 return S_OK;
7133 /**************************************************************************
7134 * WsReadBytes [webservices.@]
7136 HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
7138 struct reader *reader = (struct reader *)handle;
7139 HRESULT hr = S_OK;
7141 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
7142 if (error) FIXME( "ignoring error parameter\n" );
7144 if (!reader) return E_INVALIDARG;
7146 EnterCriticalSection( &reader->cs );
7148 if (reader->magic != READER_MAGIC)
7150 LeaveCriticalSection( &reader->cs );
7151 return E_INVALIDARG;
7154 if (!reader->input_type)
7156 hr = WS_E_INVALID_OPERATION;
7157 goto done;
7159 if (!count)
7161 hr = E_INVALIDARG;
7162 goto done;
7165 *count = 0;
7166 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
7168 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7169 WS_XML_BASE64_TEXT base64;
7171 if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK) goto done;
7172 if (reader->text_conv_offset == base64.length)
7174 heap_free( base64.bytes );
7175 hr = read_node( reader );
7176 goto done;
7178 *count = min( base64.length - reader->text_conv_offset, max_count );
7179 memcpy( bytes, base64.bytes + reader->text_conv_offset, *count );
7180 reader->text_conv_offset += *count;
7181 heap_free( base64.bytes );
7184 done:
7185 LeaveCriticalSection( &reader->cs );
7186 TRACE( "returning %08x\n", hr );
7187 return hr;
7190 static HRESULT utf8_to_utf16( const WS_XML_UTF8_TEXT *utf8, WS_XML_UTF16_TEXT *utf16 )
7192 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
7193 if (!(utf16->bytes = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
7194 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, (WCHAR *)utf16->bytes, len );
7195 utf16->byteCount = len * sizeof(WCHAR);
7196 return S_OK;
7199 /**************************************************************************
7200 * WsReadChars [webservices.@]
7202 HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count, ULONG *count, WS_ERROR *error )
7204 struct reader *reader = (struct reader *)handle;
7205 HRESULT hr = S_OK;
7207 TRACE( "%p %p %u %p %p\n", handle, chars, max_count, count, error );
7208 if (error) FIXME( "ignoring error parameter\n" );
7210 if (!reader) return E_INVALIDARG;
7212 EnterCriticalSection( &reader->cs );
7214 if (reader->magic != READER_MAGIC)
7216 LeaveCriticalSection( &reader->cs );
7217 return E_INVALIDARG;
7220 if (!reader->input_type)
7222 hr = WS_E_INVALID_OPERATION;
7223 goto done;
7225 if (!count)
7227 hr = E_INVALIDARG;
7228 goto done;
7231 *count = 0;
7232 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && chars)
7234 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7235 WS_XML_UTF16_TEXT utf16;
7236 HRESULT hr;
7238 if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK) goto done;
7239 if (reader->text_conv_offset == utf16.byteCount / sizeof(WCHAR))
7241 heap_free( utf16.bytes );
7242 hr = read_node( reader );
7243 goto done;
7245 *count = min( utf16.byteCount / sizeof(WCHAR) - reader->text_conv_offset, max_count );
7246 memcpy( chars, utf16.bytes + reader->text_conv_offset * sizeof(WCHAR), *count * sizeof(WCHAR) );
7247 reader->text_conv_offset += *count;
7248 heap_free( utf16.bytes );
7251 done:
7252 LeaveCriticalSection( &reader->cs );
7253 TRACE( "returning %08x\n", hr );
7254 return hr;
7257 /**************************************************************************
7258 * WsReadCharsUtf8 [webservices.@]
7260 HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
7262 struct reader *reader = (struct reader *)handle;
7263 HRESULT hr = S_OK;
7265 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
7266 if (error) FIXME( "ignoring error parameter\n" );
7268 if (!reader) return E_INVALIDARG;
7270 EnterCriticalSection( &reader->cs );
7272 if (reader->magic != READER_MAGIC)
7274 LeaveCriticalSection( &reader->cs );
7275 return E_INVALIDARG;
7278 if (!reader->input_type)
7280 hr = WS_E_INVALID_OPERATION;
7281 goto done;
7283 if (!count)
7285 hr = E_INVALIDARG;
7286 goto done;
7289 *count = 0;
7290 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
7292 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7293 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
7295 if (reader->text_conv_offset == utf8->value.length)
7297 hr = read_node( reader );
7298 goto done;
7300 *count = min( utf8->value.length - reader->text_conv_offset, max_count );
7301 memcpy( bytes, utf8->value.bytes + reader->text_conv_offset, *count );
7302 reader->text_conv_offset += *count;
7305 done:
7306 LeaveCriticalSection( &reader->cs );
7307 TRACE( "returning %08x\n", hr );
7308 return hr;
7311 static HRESULT move_to_element( struct reader *reader )
7313 HRESULT hr;
7314 if (node_type( reader->current ) == WS_XML_NODE_TYPE_BOF &&
7315 (hr = read_move_to( reader, WS_MOVE_TO_CHILD_NODE, NULL )) != S_OK) return hr;
7316 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return E_FAIL;
7317 return S_OK;
7320 static HRESULT copy_tree( struct reader *reader, WS_XML_WRITER *writer )
7322 const struct node *node, *parent;
7323 BOOL done = FALSE;
7324 HRESULT hr;
7326 if ((hr = move_to_element( reader )) != S_OK) return hr;
7327 parent = reader->current;
7328 for (;;)
7330 node = reader->current;
7331 if ((hr = WsWriteNode( writer, (const WS_XML_NODE *)node, NULL )) != S_OK) break;
7332 if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT && node->parent == parent) done = TRUE;
7333 if ((hr = read_next_node( reader )) != S_OK || done) break;
7335 return hr;
7338 /**************************************************************************
7339 * WsReadXmlBuffer [webservices.@]
7341 HRESULT WINAPI WsReadXmlBuffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret, WS_ERROR *error )
7343 struct reader *reader = (struct reader *)handle;
7344 WS_XML_WRITER *writer = NULL;
7345 WS_XML_BUFFER *buffer = NULL;
7346 HRESULT hr;
7348 TRACE( "%p %p %p %p\n", handle, heap, ret, error );
7349 if (error) FIXME( "ignoring error parameter\n" );
7351 if (!reader || !heap) return E_INVALIDARG;
7352 if (!ret) return E_FAIL;
7354 EnterCriticalSection( &reader->cs );
7356 if (reader->magic != READER_MAGIC)
7358 LeaveCriticalSection( &reader->cs );
7359 return E_INVALIDARG;
7362 if (!reader->input_type) hr = WS_E_INVALID_OPERATION;
7363 else
7365 if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
7366 if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL )) != S_OK) goto done;
7367 if ((hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL )) != S_OK) goto done;
7368 if ((hr = copy_tree( reader, writer )) == S_OK) *ret = buffer;
7371 done:
7372 if (hr != S_OK) free_xmlbuf( (struct xmlbuf *)buffer );
7373 WsFreeWriter( writer );
7374 LeaveCriticalSection( &reader->cs );
7375 TRACE( "returning %08x\n", hr );
7376 return hr;
7379 HRESULT create_header_buffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret )
7381 struct reader *reader = (struct reader *)handle;
7382 HRESULT hr = WS_E_QUOTA_EXCEEDED;
7383 struct xmlbuf *xmlbuf;
7385 EnterCriticalSection( &reader->cs );
7387 if (reader->magic != READER_MAGIC)
7389 LeaveCriticalSection( &reader->cs );
7390 return E_INVALIDARG;
7393 if ((xmlbuf = alloc_xmlbuf( heap, reader->read_pos, reader->input_enc, reader->input_charset,
7394 reader->dict_static, reader->dict )))
7396 memcpy( xmlbuf->bytes.bytes, reader->read_bufptr, reader->read_pos );
7397 xmlbuf->bytes.length = reader->read_pos;
7398 *ret = (WS_XML_BUFFER *)xmlbuf;
7399 hr = S_OK;
7402 LeaveCriticalSection( &reader->cs );
7403 return hr;
7406 HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *desc, USHORT index, const WS_FIELD_DESCRIPTION **ret )
7408 if (index >= desc->fieldCount) return E_INVALIDARG;
7409 *ret = desc->fields[index];
7410 return S_OK;
7413 static ULONG get_field_size( const WS_FIELD_DESCRIPTION *desc )
7415 if (desc->options & WS_FIELD_POINTER) return sizeof(void *);
7416 return get_type_size( desc->type, desc->typeDescription );
7419 static HRESULT read_param( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, void *ret )
7421 if (!ret && !(ret = ws_alloc_zero( heap, get_field_size(desc) ))) return WS_E_QUOTA_EXCEEDED;
7422 return read_type_field( reader, desc, heap, ret, 0 );
7425 static HRESULT read_param_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
7426 void **ret, ULONG *count )
7428 if (!ret && !(ret = ws_alloc_zero( heap, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED;
7429 return read_type_array( reader, desc, heap, ret, count );
7432 static void set_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, ULONG index, ULONG len,
7433 const void **args )
7435 ULONG i, *ptr;
7436 for (i = 0; i < count; i++)
7438 if (params[i].outputMessageIndex != index || params[i].parameterType != WS_PARAMETER_TYPE_ARRAY_COUNT)
7439 continue;
7440 if ((ptr = *(ULONG **)args[i])) *ptr = len;
7441 break;
7445 HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEMENT_DESCRIPTION *desc,
7446 const WS_PARAMETER_DESCRIPTION *params, ULONG count, const void **args )
7448 struct reader *reader = (struct reader *)handle;
7449 const WS_STRUCT_DESCRIPTION *desc_struct;
7450 const WS_FIELD_DESCRIPTION *desc_field;
7451 ULONG i, len;
7452 HRESULT hr;
7454 if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG;
7456 EnterCriticalSection( &reader->cs );
7458 if (reader->magic != READER_MAGIC)
7460 LeaveCriticalSection( &reader->cs );
7461 return E_INVALIDARG;
7464 if ((hr = start_mapping( reader, WS_ELEMENT_TYPE_MAPPING, desc->elementLocalName, desc->elementNs )) != S_OK)
7465 goto done;
7467 for (i = 0; i < count; i++)
7469 if (params[i].outputMessageIndex == INVALID_PARAMETER_INDEX) continue;
7470 if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES)
7472 FIXME( "messages type not supported\n" );
7473 hr = E_NOTIMPL;
7474 goto done;
7476 if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) goto done;
7477 if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL)
7479 void *ptr = *(void **)args[i];
7480 if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) goto done;
7482 else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY)
7484 void **ptr = *(void ***)args[i];
7485 if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) goto done;
7486 set_array_len( params, count, params[i].outputMessageIndex, len, args );
7490 if (desc_struct->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
7492 struct node *parent = find_parent( reader );
7493 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
7496 hr = end_mapping( reader, WS_ELEMENT_TYPE_MAPPING );
7498 done:
7499 LeaveCriticalSection( &reader->cs );
7500 return hr;