gphoto2.ds: Set supported groups.
[wine.git] / dlls / webservices / reader.c
blob9d024a3446bba7e111141ec11ba71f904694f975
1 /*
2 * Copyright 2015, 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <assert.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winnls.h"
25 #include "webservices.h"
27 #include "wine/debug.h"
28 #include "wine/list.h"
29 #include "webservices_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
33 ULONG prop_size( const struct prop_desc *desc, ULONG count )
35 ULONG i, ret = count * sizeof(struct prop);
36 for (i = 0; i < count; i++) ret += desc[i].size;
37 return ret;
40 void prop_init( const struct prop_desc *desc, ULONG count, struct prop *prop, void *data )
42 ULONG i;
43 char *ptr = data;
44 for (i = 0; i < count; i++)
46 prop[i].value = ptr;
47 prop[i].size = desc[i].size;
48 prop[i].readonly = desc[i].readonly;
49 prop[i].writeonly = desc[i].writeonly;
50 ptr += prop[i].size;
54 HRESULT prop_set( const struct prop *prop, ULONG count, ULONG id, const void *value, ULONG size )
56 if (id >= count || size != prop[id].size || prop[id].readonly) return E_INVALIDARG;
57 memcpy( prop[id].value, value, size );
58 return S_OK;
61 HRESULT prop_get( const struct prop *prop, ULONG count, ULONG id, void *buf, ULONG size )
63 if (id >= count || size != prop[id].size || prop[id].writeonly) return E_INVALIDARG;
64 memcpy( buf, prop[id].value, prop[id].size );
65 return S_OK;
68 struct node *alloc_node( WS_XML_NODE_TYPE type )
70 struct node *ret;
72 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
73 ret->hdr.node.nodeType = type;
74 list_init( &ret->entry );
75 list_init( &ret->children );
76 return ret;
79 void free_attribute( WS_XML_ATTRIBUTE *attr )
81 if (!attr) return;
82 free_xml_string( attr->prefix );
83 free_xml_string( attr->localName );
84 free_xml_string( attr->ns );
85 heap_free( attr->value );
86 heap_free( attr );
89 void free_node( struct node *node )
91 if (!node) return;
92 switch (node_type( node ))
94 case WS_XML_NODE_TYPE_ELEMENT:
96 WS_XML_ELEMENT_NODE *elem = &node->hdr;
97 ULONG i;
99 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
100 heap_free( elem->attributes );
101 free_xml_string( elem->prefix );
102 free_xml_string( elem->localName );
103 free_xml_string( elem->ns );
104 break;
106 case WS_XML_NODE_TYPE_TEXT:
108 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
109 heap_free( text->text );
110 break;
112 case WS_XML_NODE_TYPE_COMMENT:
114 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
115 heap_free( comment->value.bytes );
116 break;
118 case WS_XML_NODE_TYPE_CDATA:
119 case WS_XML_NODE_TYPE_END_CDATA:
120 case WS_XML_NODE_TYPE_END_ELEMENT:
121 case WS_XML_NODE_TYPE_EOF:
122 case WS_XML_NODE_TYPE_BOF:
123 break;
125 default:
126 ERR( "unhandled type %u\n", node_type( node ) );
127 break;
129 heap_free( node );
132 void destroy_nodes( struct node *node )
134 struct list *ptr;
136 if (!node) return;
137 while ((ptr = list_head( &node->children )))
139 struct node *child = LIST_ENTRY( ptr, struct node, entry );
140 list_remove( &child->entry );
141 destroy_nodes( child );
143 free_node( node );
146 static WS_XML_ATTRIBUTE *dup_attribute( const WS_XML_ATTRIBUTE *src )
148 WS_XML_ATTRIBUTE *dst;
149 const WS_XML_STRING *prefix = src->prefix;
150 const WS_XML_STRING *localname = src->localName;
151 const WS_XML_STRING *ns = src->localName;
152 const WS_XML_TEXT *text = src->value;
154 if (!(dst = heap_alloc( sizeof(*dst) ))) return NULL;
155 dst->singleQuote = src->singleQuote;
156 dst->isXmlNs = src->isXmlNs;
158 if (!prefix) dst->prefix = NULL;
159 else if (!(dst->prefix = dup_xml_string( prefix, FALSE ))) goto error;
160 if (!(dst->localName = dup_xml_string( localname, FALSE ))) goto error;
161 if (!(dst->ns = dup_xml_string( ns, FALSE ))) goto error;
163 if (text)
165 WS_XML_UTF8_TEXT *utf8;
166 const WS_XML_UTF8_TEXT *utf8_src = (const WS_XML_UTF8_TEXT *)text;
167 if (!(utf8 = alloc_utf8_text( utf8_src->value.bytes, utf8_src->value.length ))) goto error;
168 dst->value = &utf8->text;
171 return dst;
173 error:
174 free_attribute( dst );
175 return NULL;
178 static WS_XML_ATTRIBUTE **dup_attributes( WS_XML_ATTRIBUTE * const *src, ULONG count )
180 WS_XML_ATTRIBUTE **dst;
181 ULONG i;
183 if (!(dst = heap_alloc( sizeof(*dst) * count ))) return NULL;
184 for (i = 0; i < count; i++)
186 if (!(dst[i] = dup_attribute( src[i] )))
188 for (; i > 0; i--) free_attribute( dst[i - 1] );
189 heap_free( dst );
190 return NULL;
193 return dst;
196 static struct node *dup_element_node( const WS_XML_ELEMENT_NODE *src )
198 struct node *node;
199 WS_XML_ELEMENT_NODE *dst;
200 ULONG count = src->attributeCount;
201 WS_XML_ATTRIBUTE **attrs = src->attributes;
202 const WS_XML_STRING *prefix = (src->prefix && src->prefix->length) ? src->prefix : NULL;
203 const WS_XML_STRING *localname = src->localName;
204 const WS_XML_STRING *ns = src->ns;
206 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
207 dst = &node->hdr;
209 if (count && !(dst->attributes = dup_attributes( attrs, count ))) goto error;
210 dst->attributeCount = count;
212 if (prefix && !(dst->prefix = dup_xml_string( prefix, FALSE ))) goto error;
213 if (localname && !(dst->localName = dup_xml_string( localname, FALSE ))) goto error;
214 if (ns && !(dst->ns = dup_xml_string( ns, FALSE ))) goto error;
215 return node;
217 error:
218 free_node( node );
219 return NULL;
222 static struct node *dup_text_node( const WS_XML_TEXT_NODE *src )
224 struct node *node;
225 WS_XML_TEXT_NODE *dst;
227 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
228 dst = (WS_XML_TEXT_NODE *)node;
230 if (src->text)
232 WS_XML_UTF8_TEXT *utf8;
233 const WS_XML_UTF8_TEXT *utf8_src = (const WS_XML_UTF8_TEXT *)src->text;
234 if (!(utf8 = alloc_utf8_text( utf8_src->value.bytes, utf8_src->value.length )))
236 free_node( node );
237 return NULL;
239 dst->text = &utf8->text;
241 return node;
244 static struct node *dup_comment_node( const WS_XML_COMMENT_NODE *src )
246 struct node *node;
247 WS_XML_COMMENT_NODE *dst;
249 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return NULL;
250 dst = (WS_XML_COMMENT_NODE *)node;
252 if (src->value.length && !(dst->value.bytes = heap_alloc( src->value.length )))
254 free_node( node );
255 return NULL;
257 memcpy( dst->value.bytes, src->value.bytes, src->value.length );
258 dst->value.length = src->value.length;
259 return node;
262 static struct node *dup_node( const struct node *src )
264 switch (node_type( src ))
266 case WS_XML_NODE_TYPE_ELEMENT:
267 return dup_element_node( &src->hdr );
269 case WS_XML_NODE_TYPE_TEXT:
270 return dup_text_node( (const WS_XML_TEXT_NODE *)src );
272 case WS_XML_NODE_TYPE_COMMENT:
273 return dup_comment_node( (const WS_XML_COMMENT_NODE *)src );
275 case WS_XML_NODE_TYPE_CDATA:
276 case WS_XML_NODE_TYPE_END_CDATA:
277 case WS_XML_NODE_TYPE_END_ELEMENT:
278 case WS_XML_NODE_TYPE_EOF:
279 case WS_XML_NODE_TYPE_BOF:
280 return alloc_node( node_type( src ) );
282 default:
283 ERR( "unhandled type %u\n", node_type( src ) );
284 break;
286 return NULL;
289 static HRESULT dup_tree( struct node **dst, const struct node *src )
291 struct node *parent;
292 const struct node *child;
294 if (!*dst && !(*dst = dup_node( src ))) return E_OUTOFMEMORY;
295 parent = *dst;
297 LIST_FOR_EACH_ENTRY( child, &src->children, struct node, entry )
299 HRESULT hr = E_OUTOFMEMORY;
300 struct node *new_child;
302 if (!(new_child = dup_node( child )) || (hr = dup_tree( &new_child, child )) != S_OK)
304 destroy_nodes( *dst );
305 return hr;
307 new_child->parent = parent;
308 list_add_tail( &parent->children, &new_child->entry );
310 return S_OK;
313 static const struct prop_desc reader_props[] =
315 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
316 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
317 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
318 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
319 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
320 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
321 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
322 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
323 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
324 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
325 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
326 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
327 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
328 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
329 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
332 enum reader_state
334 READER_STATE_INITIAL,
335 READER_STATE_BOF,
336 READER_STATE_STARTELEMENT,
337 READER_STATE_STARTATTRIBUTE,
338 READER_STATE_STARTCDATA,
339 READER_STATE_CDATA,
340 READER_STATE_TEXT,
341 READER_STATE_ENDELEMENT,
342 READER_STATE_ENDCDATA,
343 READER_STATE_COMMENT,
344 READER_STATE_EOF
347 struct prefix
349 WS_XML_STRING *str;
350 WS_XML_STRING *ns;
353 struct reader
355 ULONG magic;
356 CRITICAL_SECTION cs;
357 ULONG read_size;
358 ULONG read_pos;
359 const unsigned char *read_bufptr;
360 enum reader_state state;
361 struct node *root;
362 struct node *current;
363 ULONG current_attr;
364 struct node *last;
365 struct prefix *prefixes;
366 ULONG nb_prefixes;
367 ULONG nb_prefixes_allocated;
368 WS_XML_READER_ENCODING_TYPE input_enc;
369 WS_CHARSET input_charset;
370 WS_XML_READER_INPUT_TYPE input_type;
371 struct xmlbuf *input_buf;
372 const unsigned char *input_data;
373 ULONG input_size;
374 ULONG text_conv_offset;
375 const WS_XML_DICTIONARY *dict_static;
376 WS_XML_DICTIONARY *dict;
377 ULONG prop_count;
378 struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])];
381 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
383 static struct reader *alloc_reader(void)
385 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
386 struct reader *ret;
387 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
389 if (!(ret = heap_alloc_zero( size ))) return NULL;
390 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
392 heap_free( ret );
393 return NULL;
395 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
397 ret->magic = READER_MAGIC;
398 InitializeCriticalSection( &ret->cs );
399 ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": reader.cs");
401 prop_init( reader_props, count, ret->prop, &ret[1] );
402 ret->prop_count = count;
403 return ret;
406 static void clear_prefixes( struct prefix *prefixes, ULONG count )
408 ULONG i;
409 for (i = 0; i < count; i++)
411 free_xml_string( prefixes[i].str );
412 prefixes[i].str = NULL;
413 free_xml_string( prefixes[i].ns );
414 prefixes[i].ns = NULL;
418 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
420 if (str)
422 free_xml_string( prefix->str );
423 if (!(prefix->str = dup_xml_string( str, FALSE ))) return E_OUTOFMEMORY;
425 if (prefix->ns) free_xml_string( prefix->ns );
426 if (!(prefix->ns = dup_xml_string( ns, FALSE ))) return E_OUTOFMEMORY;
427 return S_OK;
430 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
432 ULONG i;
433 HRESULT hr;
435 for (i = 0; i < reader->nb_prefixes; i++)
437 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
438 return set_prefix( &reader->prefixes[i], NULL, ns );
440 if (i >= reader->nb_prefixes_allocated)
442 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
443 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
444 if (!tmp) return E_OUTOFMEMORY;
445 reader->prefixes = tmp;
446 reader->nb_prefixes_allocated *= 2;
448 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
449 reader->nb_prefixes++;
450 return S_OK;
453 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
455 ULONG i;
456 for (i = 0; i < reader->nb_prefixes; i++)
458 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
459 return reader->prefixes[i].ns;
461 return NULL;
464 static void read_insert_eof( struct reader *reader, struct node *eof )
466 if (!reader->root) reader->root = eof;
467 else
469 eof->parent = reader->root;
470 list_add_tail( &reader->root->children, &eof->entry );
472 reader->current = reader->last = eof;
475 static void read_insert_bof( struct reader *reader, struct node *bof )
477 reader->root->parent = bof;
478 list_add_tail( &bof->children, &reader->root->entry );
479 reader->current = reader->last = reader->root = bof;
482 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
484 node->parent = parent;
485 list_add_before( list_tail( &parent->children ), &node->entry );
486 reader->current = reader->last = node;
489 static void free_reader( struct reader *reader )
491 destroy_nodes( reader->root );
492 clear_prefixes( reader->prefixes, reader->nb_prefixes );
493 heap_free( reader->prefixes );
494 reader->cs.DebugInfo->Spare[0] = 0;
495 DeleteCriticalSection( &reader->cs );
496 heap_free( reader );
499 static HRESULT init_reader( struct reader *reader )
501 static const WS_XML_STRING empty = {0, NULL};
502 struct node *node;
503 HRESULT hr;
505 reader->state = READER_STATE_INITIAL;
506 destroy_nodes( reader->root );
507 reader->root = reader->current = NULL;
508 reader->current_attr = 0;
509 clear_prefixes( reader->prefixes, reader->nb_prefixes );
510 reader->nb_prefixes = 1;
511 if ((hr = bind_prefix( reader, &empty, &empty )) != S_OK) return hr;
513 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
514 read_insert_eof( reader, node );
515 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
516 reader->input_charset = WS_CHARSET_UTF8;
517 reader->dict_static = NULL;
518 reader->dict = NULL;
519 return S_OK;
522 /**************************************************************************
523 * WsCreateReader [webservices.@]
525 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
526 WS_XML_READER **handle, WS_ERROR *error )
528 struct reader *reader;
529 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
530 BOOL read_decl = TRUE;
531 HRESULT hr;
533 TRACE( "%p %u %p %p\n", properties, count, handle, error );
534 if (error) FIXME( "ignoring error parameter\n" );
536 if (!handle) return E_INVALIDARG;
537 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
539 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
540 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
541 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
542 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
544 for (i = 0; i < count; i++)
546 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
547 properties[i].valueSize );
548 if (hr != S_OK)
550 free_reader( reader );
551 return hr;
555 if ((hr = init_reader( reader )) != S_OK)
557 free_reader( reader );
558 return hr;
561 TRACE( "created %p\n", reader );
562 *handle = (WS_XML_READER *)reader;
563 return S_OK;
566 /**************************************************************************
567 * WsFreeReader [webservices.@]
569 void WINAPI WsFreeReader( WS_XML_READER *handle )
571 struct reader *reader = (struct reader *)handle;
573 TRACE( "%p\n", handle );
575 if (!reader) return;
577 EnterCriticalSection( &reader->cs );
579 if (reader->magic != READER_MAGIC)
581 LeaveCriticalSection( &reader->cs );
582 return;
585 reader->magic = 0;
587 LeaveCriticalSection( &reader->cs );
588 free_reader( reader );
591 /**************************************************************************
592 * WsFillReader [webservices.@]
594 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
595 WS_ERROR *error )
597 struct reader *reader = (struct reader *)handle;
599 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
600 if (error) FIXME( "ignoring error parameter\n" );
602 if (!reader) return E_INVALIDARG;
604 EnterCriticalSection( &reader->cs );
606 if (reader->magic != READER_MAGIC)
608 LeaveCriticalSection( &reader->cs );
609 return E_INVALIDARG;
612 /* FIXME: add support for stream input */
613 reader->read_size = min( min_size, reader->input_size );
614 reader->read_pos = 0;
616 LeaveCriticalSection( &reader->cs );
617 return S_OK;
620 /**************************************************************************
621 * WsGetNamespaceFromPrefix [webservices.@]
623 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
624 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
626 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
627 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
628 static const WS_XML_STRING empty_ns = {0, NULL};
629 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
630 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
631 struct reader *reader = (struct reader *)handle;
632 BOOL found = FALSE;
634 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
635 if (error) FIXME( "ignoring error parameter\n" );
637 if (!reader || !prefix || !ns) return E_INVALIDARG;
639 EnterCriticalSection( &reader->cs );
641 if (reader->magic != READER_MAGIC)
643 LeaveCriticalSection( &reader->cs );
644 return E_INVALIDARG;
647 if (reader->state != READER_STATE_STARTELEMENT)
649 LeaveCriticalSection( &reader->cs );
650 return WS_E_INVALID_OPERATION;
653 if (!prefix->length)
655 *ns = &empty_ns;
656 found = TRUE;
658 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
660 *ns = &xml_ns;
661 found = TRUE;
663 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
665 *ns = &xmlns_ns;
666 found = TRUE;
668 else
670 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
671 ULONG i;
673 for (i = 0; i < elem->attributeCount; i++)
675 if (!elem->attributes[i]->isXmlNs) continue;
676 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
678 *ns = elem->attributes[i]->ns;
679 found = TRUE;
680 break;
685 LeaveCriticalSection( &reader->cs );
687 if (!found)
689 if (required) return WS_E_INVALID_FORMAT;
690 *ns = NULL;
691 return S_FALSE;
694 return S_OK;
697 /**************************************************************************
698 * WsGetReaderNode [webservices.@]
700 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
701 WS_ERROR *error )
703 struct reader *reader = (struct reader *)handle;
705 TRACE( "%p %p %p\n", handle, node, error );
706 if (error) FIXME( "ignoring error parameter\n" );
708 if (!reader || !node) return E_INVALIDARG;
710 EnterCriticalSection( &reader->cs );
712 if (reader->magic != READER_MAGIC)
714 LeaveCriticalSection( &reader->cs );
715 return E_INVALIDARG;
718 *node = &reader->current->hdr.node;
720 LeaveCriticalSection( &reader->cs );
721 return S_OK;
724 static HRESULT get_charset( struct reader *reader, void *buf, ULONG size )
726 if (!buf || size != sizeof(reader->input_charset)) return E_INVALIDARG;
727 if (!reader->input_charset) return WS_E_INVALID_FORMAT;
728 *(WS_CHARSET *)buf = reader->input_charset;
729 return S_OK;
732 /**************************************************************************
733 * WsGetReaderProperty [webservices.@]
735 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
736 void *buf, ULONG size, WS_ERROR *error )
738 struct reader *reader = (struct reader *)handle;
739 HRESULT hr;
741 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
742 if (error) FIXME( "ignoring error parameter\n" );
744 if (!reader) return E_INVALIDARG;
746 EnterCriticalSection( &reader->cs );
748 if (reader->magic != READER_MAGIC)
750 LeaveCriticalSection( &reader->cs );
751 return E_INVALIDARG;
754 if (!reader->input_type)
756 LeaveCriticalSection( &reader->cs );
757 return WS_E_INVALID_OPERATION;
760 if (id == WS_XML_READER_PROPERTY_CHARSET) hr = get_charset( reader, buf, size );
761 else hr = prop_get( reader->prop, reader->prop_count, id, buf, size );
763 LeaveCriticalSection( &reader->cs );
764 return hr;
767 /**************************************************************************
768 * WsGetXmlAttribute [webservices.@]
770 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
771 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
773 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
774 return E_NOTIMPL;
777 WS_XML_UTF8_TEXT *alloc_utf8_text( const BYTE *data, ULONG len )
779 WS_XML_UTF8_TEXT *ret;
781 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
782 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
783 ret->value.length = len;
784 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
785 ret->value.dictionary = NULL;
786 ret->value.id = 0;
787 if (data) memcpy( ret->value.bytes, data, len );
788 return ret;
791 WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *data, ULONG len )
793 WS_XML_BASE64_TEXT *ret;
795 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
796 ret->text.textType = WS_XML_TEXT_TYPE_BASE64;
797 ret->length = len;
798 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
799 if (data) memcpy( ret->bytes, data, len );
800 return ret;
803 WS_XML_BOOL_TEXT *alloc_bool_text( BOOL value )
805 WS_XML_BOOL_TEXT *ret;
807 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
808 ret->text.textType = WS_XML_TEXT_TYPE_BOOL;
809 ret->value = value;
810 return ret;
813 WS_XML_INT32_TEXT *alloc_int32_text( INT32 value )
815 WS_XML_INT32_TEXT *ret;
817 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
818 ret->text.textType = WS_XML_TEXT_TYPE_INT32;
819 ret->value = value;
820 return ret;
823 WS_XML_INT64_TEXT *alloc_int64_text( INT64 value )
825 WS_XML_INT64_TEXT *ret;
827 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
828 ret->text.textType = WS_XML_TEXT_TYPE_INT64;
829 ret->value = value;
830 return ret;
833 WS_XML_UINT64_TEXT *alloc_uint64_text( UINT64 value )
835 WS_XML_UINT64_TEXT *ret;
837 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
838 ret->text.textType = WS_XML_TEXT_TYPE_UINT64;
839 ret->value = value;
840 return ret;
843 WS_XML_FLOAT_TEXT *alloc_float_text( float value )
845 WS_XML_FLOAT_TEXT *ret;
847 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
848 ret->text.textType = WS_XML_TEXT_TYPE_FLOAT;
849 ret->value = value;
850 return ret;
853 WS_XML_DOUBLE_TEXT *alloc_double_text( double value )
855 WS_XML_DOUBLE_TEXT *ret;
857 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
858 ret->text.textType = WS_XML_TEXT_TYPE_DOUBLE;
859 ret->value = value;
860 return ret;
863 WS_XML_GUID_TEXT *alloc_guid_text( const GUID *value )
865 WS_XML_GUID_TEXT *ret;
867 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
868 ret->text.textType = WS_XML_TEXT_TYPE_GUID;
869 ret->value = *value;
870 return ret;
873 WS_XML_UNIQUE_ID_TEXT *alloc_unique_id_text( const GUID *value )
875 WS_XML_UNIQUE_ID_TEXT *ret;
877 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
878 ret->text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID;
879 ret->value = *value;
880 return ret;
883 WS_XML_DATETIME_TEXT *alloc_datetime_text( const WS_DATETIME *value )
885 WS_XML_DATETIME_TEXT *ret;
887 if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
888 ret->text.textType = WS_XML_TEXT_TYPE_DATETIME;
889 ret->value = *value;
890 return ret;
893 static inline BOOL read_end_of_data( struct reader *reader )
895 return reader->read_pos >= reader->read_size;
898 static inline const unsigned char *read_current_ptr( struct reader *reader )
900 return &reader->read_bufptr[reader->read_pos];
903 static inline HRESULT read_peek( struct reader *reader, unsigned char *byte )
905 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
906 *byte = reader->read_bufptr[reader->read_pos];
907 return S_OK;
910 static inline HRESULT read_byte( struct reader *reader, unsigned char *byte )
912 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
913 *byte = reader->read_bufptr[reader->read_pos++];
914 return S_OK;
917 static inline HRESULT read_bytes( struct reader *reader, unsigned char *bytes, unsigned int len )
919 if (reader->read_pos + len > reader->read_size) return WS_E_INVALID_FORMAT;
920 memcpy( bytes, reader->read_bufptr + reader->read_pos, len );
921 reader->read_pos += len;
922 return S_OK;
925 /* UTF-8 support based on libs/wine/utf8.c */
927 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
928 static const char utf8_length[128] =
930 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
931 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
932 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
933 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
934 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
935 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
936 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
937 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
940 /* first byte mask depending on UTF-8 sequence length */
941 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
943 /* minimum Unicode value depending on UTF-8 sequence length */
944 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
946 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
948 unsigned int len, res;
949 unsigned char ch = reader->read_bufptr[reader->read_pos];
950 const unsigned char *end;
952 if (reader->read_pos >= reader->read_size) return 0;
954 if (ch < 0x80)
956 *skip = 1;
957 return ch;
959 len = utf8_length[ch - 0x80];
960 if (reader->read_pos + len >= reader->read_size) return 0;
961 end = reader->read_bufptr + reader->read_pos + len + 1;
962 res = ch & utf8_mask[len];
964 switch (len)
966 case 3:
967 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
968 res = (res << 6) | ch;
969 case 2:
970 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
971 res = (res << 6) | ch;
972 case 1:
973 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
974 res = (res << 6) | ch;
975 if (res < utf8_minval[len]) break;
976 *skip = len + 1;
977 return res;
980 return 0;
983 static inline void read_skip( struct reader *reader, unsigned int count )
985 if (reader->read_pos + count > reader->read_size) return;
986 reader->read_pos += count;
989 static inline void read_rewind( struct reader *reader, unsigned int count )
991 reader->read_pos -= count;
994 static inline BOOL read_isnamechar( unsigned int ch )
996 /* FIXME: incomplete */
997 return (ch >= 'A' && ch <= 'Z') ||
998 (ch >= 'a' && ch <= 'z') ||
999 (ch >= '0' && ch <= '9') ||
1000 ch == '_' || ch == '-' || ch == '.' || ch == ':';
1003 static inline BOOL read_isspace( unsigned int ch )
1005 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
1008 static inline void read_skip_whitespace( struct reader *reader )
1010 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
1011 reader->read_pos++;
1014 static inline int read_cmp( struct reader *reader, const char *str, int len )
1016 const unsigned char *ptr = read_current_ptr( reader );
1018 if (len < 0) len = strlen( str );
1019 if (reader->read_pos + len > reader->read_size) return -1;
1020 while (len--)
1022 if (*str != *ptr) return *ptr - *str;
1023 str++; ptr++;
1025 return 0;
1028 static HRESULT read_xmldecl( struct reader *reader )
1030 if (!reader->read_size) return WS_E_INVALID_FORMAT;
1032 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
1034 reader->state = READER_STATE_BOF;
1035 return S_OK;
1037 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
1038 read_skip( reader, 6 );
1040 /* FIXME: parse attributes */
1041 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
1042 reader->read_pos++;
1044 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
1045 read_skip( reader, 2 );
1047 reader->state = READER_STATE_BOF;
1048 return S_OK;
1051 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
1053 if (elem->attributeCount)
1055 WS_XML_ATTRIBUTE **tmp;
1056 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
1057 return E_OUTOFMEMORY;
1058 elem->attributes = tmp;
1060 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
1061 elem->attributes[elem->attributeCount++] = attr;
1062 return S_OK;
1065 static inline void init_xml_string( BYTE *bytes, ULONG len, WS_XML_STRING *str )
1067 str->length = len;
1068 str->bytes = bytes;
1069 str->dictionary = NULL;
1070 str->id = 0;
1073 static HRESULT split_qname( const BYTE *str, ULONG len, WS_XML_STRING *prefix, WS_XML_STRING *localname )
1075 BYTE *prefix_bytes = NULL, *localname_bytes = (BYTE *)str, *ptr = (BYTE *)str;
1076 ULONG prefix_len = 0, localname_len = len;
1078 while (len--)
1080 if (*ptr == ':')
1082 if (ptr == str) return WS_E_INVALID_FORMAT;
1083 prefix_bytes = (BYTE *)str;
1084 prefix_len = ptr - str;
1085 localname_bytes = ptr + 1;
1086 localname_len = len;
1087 break;
1089 ptr++;
1091 if (!localname_len) return WS_E_INVALID_FORMAT;
1093 init_xml_string( prefix_bytes, prefix_len, prefix );
1094 init_xml_string( localname_bytes, localname_len, localname );
1095 return S_OK;
1098 static HRESULT parse_qname( const BYTE *str, ULONG len, WS_XML_STRING **prefix_ret, WS_XML_STRING **localname_ret )
1100 WS_XML_STRING prefix, localname;
1101 HRESULT hr;
1103 if ((hr = split_qname( str, len, &prefix, &localname )) != S_OK) return hr;
1104 if (!(*prefix_ret = alloc_xml_string( NULL, prefix.length ))) return E_OUTOFMEMORY;
1105 if (!(*localname_ret = dup_xml_string( &localname, FALSE )))
1107 free_xml_string( *prefix_ret );
1108 return E_OUTOFMEMORY;
1110 memcpy( (*prefix_ret)->bytes, prefix.bytes, prefix.length );
1111 if (prefix.length && add_xml_string( *prefix_ret ) != S_OK) WARN( "prefix not added to dictionary\n" );
1112 return S_OK;
1115 static int codepoint_to_utf8( int cp, unsigned char *dst )
1117 if (!cp) return -1;
1118 if (cp < 0x80)
1120 *dst = cp;
1121 return 1;
1123 if (cp < 0x800)
1125 dst[1] = 0x80 | (cp & 0x3f);
1126 cp >>= 6;
1127 dst[0] = 0xc0 | cp;
1128 return 2;
1130 if ((cp >= 0xd800 && cp <= 0xdfff) || cp == 0xfffe || cp == 0xffff) return -1;
1131 if (cp < 0x10000)
1133 dst[2] = 0x80 | (cp & 0x3f);
1134 cp >>= 6;
1135 dst[1] = 0x80 | (cp & 0x3f);
1136 cp >>= 6;
1137 dst[0] = 0xe0 | cp;
1138 return 3;
1140 if (cp >= 0x110000) return -1;
1141 dst[3] = 0x80 | (cp & 0x3f);
1142 cp >>= 6;
1143 dst[2] = 0x80 | (cp & 0x3f);
1144 cp >>= 6;
1145 dst[1] = 0x80 | (cp & 0x3f);
1146 cp >>= 6;
1147 dst[0] = 0xf0 | cp;
1148 return 4;
1151 static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char *ret, ULONG *ret_len )
1153 const unsigned char *p = str;
1154 unsigned char *q = ret;
1156 *ret_len = 0;
1157 while (len)
1159 if (*p == '&')
1161 p++; len--;
1162 if (!len) return WS_E_INVALID_FORMAT;
1164 if (len >= 3 && !memcmp( p, "lt;", 3 ))
1166 *q++ = '<';
1167 p += 3;
1168 len -= 3;
1170 else if (len >= 3 && !memcmp( p, "gt;", 3 ))
1172 *q++ = '>';
1173 p += 3;
1174 len -= 3;
1176 else if (len >= 5 && !memcmp( p, "quot;", 5 ))
1178 *q++ = '"';
1179 p += 5;
1180 len -= 5;
1182 else if (len >= 4 && !memcmp( p, "amp;", 4 ))
1184 *q++ = '&';
1185 p += 4;
1186 len -= 4;
1188 else if (len >= 5 && !memcmp( p, "apos;", 5 ))
1190 *q++ = '\'';
1191 p += 5;
1192 len -= 5;
1194 else if (*p == '#')
1196 ULONG start, nb_digits, i;
1197 int len_utf8, cp = 0;
1199 p++; len--;
1200 if (!len) return WS_E_INVALID_FORMAT;
1201 if (*p == 'x')
1203 p++; len--;
1205 start = len;
1206 while (len && isxdigit( *p )) { p++; len--; };
1207 if (!len) return WS_E_INVALID_FORMAT;
1209 p -= nb_digits = start - len;
1210 if (!nb_digits || nb_digits > 6 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1211 for (i = 0; i < nb_digits; i++)
1213 cp *= 16;
1214 if (*p >= '0' && *p <= '9') cp += *p - '0';
1215 else if (*p >= 'a' && *p <= 'f') cp += *p - 'a' + 10;
1216 else cp += *p - 'A' + 10;
1217 p++;
1220 else if (isdigit( *p ))
1222 while (len && *p == '0') { p++; len--; };
1223 if (!len) return WS_E_INVALID_FORMAT;
1225 start = len;
1226 while (len && isdigit( *p )) { p++; len--; };
1227 if (!len) return WS_E_INVALID_FORMAT;
1229 p -= nb_digits = start - len;
1230 if (!nb_digits || nb_digits > 7 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1231 for (i = 0; i < nb_digits; i++)
1233 cp *= 10;
1234 cp += *p - '0';
1235 p++;
1238 else return WS_E_INVALID_FORMAT;
1239 p++; len--;
1240 if ((len_utf8 = codepoint_to_utf8( cp, q )) < 0) return WS_E_INVALID_FORMAT;
1241 *ret_len += len_utf8;
1242 q += len_utf8;
1243 continue;
1245 else return WS_E_INVALID_FORMAT;
1247 else
1249 *q++ = *p++;
1250 len--;
1252 *ret_len += 1;
1254 return S_OK;
1257 static HRESULT read_attribute_value_text( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1259 WS_XML_UTF8_TEXT *utf8 = NULL;
1260 unsigned int len, ch, skip, quote;
1261 const unsigned char *start;
1262 HRESULT hr = E_OUTOFMEMORY;
1264 read_skip_whitespace( reader );
1265 if (read_cmp( reader, "=", 1 )) return WS_E_INVALID_FORMAT;
1266 read_skip( reader, 1 );
1268 read_skip_whitespace( reader );
1269 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) return WS_E_INVALID_FORMAT;
1270 quote = read_utf8_char( reader, &skip );
1271 read_skip( reader, 1 );
1273 len = 0;
1274 start = read_current_ptr( reader );
1275 for (;;)
1277 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1278 if (ch == quote) break;
1279 read_skip( reader, skip );
1280 len += skip;
1282 read_skip( reader, 1 );
1284 if (attr->isXmlNs)
1286 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1287 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1288 if (!(utf8 = alloc_utf8_text( NULL, 0 )))
1290 hr = E_OUTOFMEMORY;
1291 goto error;
1294 else
1296 if (!(utf8 = alloc_utf8_text( NULL, len ))) goto error;
1297 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK) goto error;
1300 attr->value = &utf8->text;
1301 attr->singleQuote = (quote == '\'');
1302 return S_OK;
1304 error:
1305 heap_free( utf8 );
1306 return hr;
1309 static inline BOOL is_text_type( unsigned char type )
1311 return (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT);
1314 static HRESULT read_int31( struct reader *reader, ULONG *len )
1316 unsigned char byte;
1317 HRESULT hr;
1319 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1320 *len = byte & 0x7f;
1321 if (!(byte & 0x80)) return S_OK;
1323 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1324 *len += (byte & 0x7f) << 7;
1325 if (!(byte & 0x80)) return S_OK;
1327 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1328 *len += (byte & 0x7f) << 14;
1329 if (!(byte & 0x80)) return S_OK;
1331 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1332 *len += (byte & 0x7f) << 21;
1333 if (!(byte & 0x80)) return S_OK;
1335 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1336 *len += (byte & 0x07) << 28;
1337 return S_OK;
1340 static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
1342 ULONG len;
1343 HRESULT hr;
1344 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
1345 if (!(*str = alloc_xml_string( NULL, len ))) return E_OUTOFMEMORY;
1346 if ((hr = read_bytes( reader, (*str)->bytes, len )) == S_OK)
1348 if (add_xml_string( *str ) != S_OK) WARN( "string not added to dictionary\n" );
1349 return S_OK;
1351 free_xml_string( *str );
1352 return hr;
1355 static HRESULT read_dict_string( struct reader *reader, WS_XML_STRING **str )
1357 const WS_XML_DICTIONARY *dict;
1358 HRESULT hr;
1359 ULONG id;
1361 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1362 dict = (id & 1) ? reader->dict : reader->dict_static;
1363 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1364 if (!(*str = alloc_xml_string( NULL, 0 ))) return E_OUTOFMEMORY;
1365 *(*str) = dict->strings[id];
1366 return S_OK;
1369 static HRESULT read_datetime( struct reader *reader, WS_DATETIME *ret )
1371 UINT64 val;
1372 HRESULT hr;
1374 if ((hr = read_bytes( reader, (unsigned char *)&val, sizeof(val) )) != S_OK) return hr;
1376 if ((val & 0x03) == 1) ret->format = WS_DATETIME_FORMAT_UTC;
1377 else if ((val & 0x03) == 2) ret->format = WS_DATETIME_FORMAT_LOCAL;
1378 else ret->format = WS_DATETIME_FORMAT_NONE;
1380 if ((ret->ticks = val >> 2) > TICKS_MAX) return WS_E_INVALID_FORMAT;
1381 return S_OK;
1384 static HRESULT lookup_string( struct reader *reader, ULONG id, const WS_XML_STRING **ret )
1386 const WS_XML_DICTIONARY *dict = (id & 1) ? reader->dict : reader->dict_static;
1387 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1388 *ret = &dict->strings[id];
1389 return S_OK;
1392 static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1394 WS_XML_UTF8_TEXT *text_utf8 = NULL;
1395 WS_XML_BASE64_TEXT *text_base64 = NULL;
1396 WS_XML_INT32_TEXT *text_int32;
1397 WS_XML_INT64_TEXT *text_int64;
1398 WS_XML_BOOL_TEXT *text_bool;
1399 const WS_XML_STRING *str;
1400 unsigned char type;
1401 UINT8 val_uint8;
1402 UINT16 val_uint16;
1403 INT32 val_int32;
1404 ULONG len = 0, id;
1405 GUID guid;
1406 HRESULT hr;
1408 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1409 if (!is_text_type( type )) return WS_E_INVALID_FORMAT;
1411 switch (type)
1413 case RECORD_ZERO_TEXT:
1415 if (!(text_int32 = alloc_int32_text( 0 ))) return E_OUTOFMEMORY;
1416 attr->value = &text_int32->text;
1417 return S_OK;
1419 case RECORD_ONE_TEXT:
1421 if (!(text_int32 = alloc_int32_text( 1 ))) return E_OUTOFMEMORY;
1422 attr->value = &text_int32->text;
1423 return S_OK;
1425 case RECORD_FALSE_TEXT:
1427 if (!(text_bool = alloc_bool_text( FALSE ))) return E_OUTOFMEMORY;
1428 attr->value = &text_bool->text;
1429 return S_OK;
1431 case RECORD_TRUE_TEXT:
1433 if (!(text_bool = alloc_bool_text( TRUE ))) return E_OUTOFMEMORY;
1434 attr->value = &text_bool->text;
1435 return S_OK;
1437 case RECORD_INT8_TEXT:
1439 INT8 val_int8;
1440 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
1441 if (!(text_int64 = alloc_int64_text( val_int8 ))) return E_OUTOFMEMORY;
1442 attr->value = &text_int64->text;
1443 return S_OK;
1445 case RECORD_INT16_TEXT:
1447 INT16 val_int16;
1448 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
1449 if (!(text_int64 = alloc_int64_text( val_int16 ))) return E_OUTOFMEMORY;
1450 attr->value = &text_int64->text;
1451 return S_OK;
1453 case RECORD_INT32_TEXT:
1454 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1455 if (!(text_int64 = alloc_int64_text( val_int32 ))) return E_OUTOFMEMORY;
1456 attr->value = &text_int64->text;
1457 return S_OK;
1459 case RECORD_INT64_TEXT:
1461 INT64 val_int64;
1462 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
1463 if (!(text_int64 = alloc_int64_text( val_int64 ))) return E_OUTOFMEMORY;
1464 attr->value = &text_int64->text;
1465 return S_OK;
1467 case RECORD_FLOAT_TEXT:
1469 WS_XML_FLOAT_TEXT *text_float;
1470 float val_float;
1472 if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
1473 if (!(text_float = alloc_float_text( val_float ))) return E_OUTOFMEMORY;
1474 attr->value = &text_float->text;
1475 return S_OK;
1477 case RECORD_DOUBLE_TEXT:
1479 WS_XML_DOUBLE_TEXT *text_double;
1480 double val_double;
1482 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
1483 if (!(text_double = alloc_double_text( val_double ))) return E_OUTOFMEMORY;
1484 attr->value = &text_double->text;
1485 return S_OK;
1487 case RECORD_DATETIME_TEXT:
1489 WS_XML_DATETIME_TEXT *text_datetime;
1490 WS_DATETIME datetime;
1492 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
1493 if (!(text_datetime = alloc_datetime_text( &datetime ))) return E_OUTOFMEMORY;
1494 attr->value = &text_datetime->text;
1495 return S_OK;
1497 case RECORD_CHARS8_TEXT:
1498 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1499 len = val_uint8;
1500 break;
1502 case RECORD_CHARS16_TEXT:
1503 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1504 len = val_uint16;
1505 break;
1507 case RECORD_CHARS32_TEXT:
1508 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1509 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1510 len = val_int32;
1511 break;
1513 case RECORD_BYTES8_TEXT:
1514 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1515 if (!(text_base64 = alloc_base64_text( NULL, val_uint8 ))) return E_OUTOFMEMORY;
1516 if ((hr = read_bytes( reader, text_base64->bytes, val_uint8 )) != S_OK)
1518 heap_free( text_base64 );
1519 return hr;
1521 break;
1523 case RECORD_BYTES16_TEXT:
1524 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1525 if (!(text_base64 = alloc_base64_text( NULL, val_uint16 ))) return E_OUTOFMEMORY;
1526 if ((hr = read_bytes( reader, text_base64->bytes, val_uint16 )) != S_OK)
1528 heap_free( text_base64 );
1529 return hr;
1531 break;
1533 case RECORD_BYTES32_TEXT:
1534 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1535 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1536 if (!(text_base64 = alloc_base64_text( NULL, val_int32 ))) return E_OUTOFMEMORY;
1537 if ((hr = read_bytes( reader, text_base64->bytes, val_int32 )) != S_OK)
1539 heap_free( text_base64 );
1540 return hr;
1542 break;
1544 case RECORD_EMPTY_TEXT:
1545 break;
1547 case RECORD_DICTIONARY_TEXT:
1548 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1549 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
1550 if (!(text_utf8 = alloc_utf8_text( str->bytes, str->length ))) return E_OUTOFMEMORY;
1551 break;
1553 case RECORD_UNIQUE_ID_TEXT:
1555 WS_XML_UNIQUE_ID_TEXT *text_unique_id;
1556 if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
1557 if (!(text_unique_id = alloc_unique_id_text( &guid ))) return E_OUTOFMEMORY;
1558 attr->value = &text_unique_id->text;
1559 return S_OK;
1561 case RECORD_GUID_TEXT:
1563 WS_XML_GUID_TEXT *guid_text;
1564 if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
1565 if (!(guid_text = alloc_guid_text( &guid ))) return E_OUTOFMEMORY;
1566 attr->value = &guid_text->text;
1567 return S_OK;
1569 case RECORD_UINT64_TEXT:
1571 WS_XML_UINT64_TEXT *text_uint64;
1572 UINT64 val_uint64;
1574 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
1575 if (!(text_uint64 = alloc_uint64_text( val_uint64 ))) return E_OUTOFMEMORY;
1576 attr->value = &text_uint64->text;
1577 return S_OK;
1579 case RECORD_BOOL_TEXT:
1581 WS_XML_BOOL_TEXT *text_bool;
1582 BOOL val_bool;
1584 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
1585 if (!(text_bool = alloc_bool_text( !!val_bool ))) return E_OUTOFMEMORY;
1586 attr->value = &text_bool->text;
1587 return S_OK;
1589 default:
1590 ERR( "unhandled record type %02x\n", type );
1591 return WS_E_NOT_SUPPORTED;
1594 if (type >= RECORD_BYTES8_TEXT && type <= RECORD_BYTES32_TEXT)
1596 attr->value = &text_base64->text;
1597 return S_OK;
1600 if (!text_utf8)
1602 if (!(text_utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
1603 if (!len) text_utf8->value.bytes = (BYTE *)(text_utf8 + 1); /* quirk */
1604 if ((hr = read_bytes( reader, text_utf8->value.bytes, len )) != S_OK)
1606 heap_free( text_utf8 );
1607 return hr;
1611 attr->value = &text_utf8->text;
1612 return S_OK;
1615 static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1617 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1618 WS_XML_ATTRIBUTE *attr;
1619 unsigned int len = 0, ch, skip;
1620 const unsigned char *start;
1621 WS_XML_STRING *prefix, *localname;
1622 HRESULT hr = WS_E_INVALID_FORMAT;
1624 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1626 start = read_current_ptr( reader );
1627 for (;;)
1629 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1630 if (!read_isnamechar( ch )) break;
1631 read_skip( reader, skip );
1632 len += skip;
1634 if (!len) goto error;
1636 if ((hr = parse_qname( start, len, &prefix, &localname )) != S_OK) goto error;
1637 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1639 free_xml_string( prefix );
1640 attr->isXmlNs = 1;
1641 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1643 free_xml_string( localname );
1644 hr = E_OUTOFMEMORY;
1645 goto error;
1647 attr->localName = localname;
1649 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1651 attr->isXmlNs = 1;
1652 attr->prefix = prefix;
1653 attr->localName = localname;
1655 else
1657 attr->prefix = prefix;
1658 attr->localName = localname;
1661 if ((hr = read_attribute_value_text( reader, attr )) != S_OK) goto error;
1663 *ret = attr;
1664 return S_OK;
1666 error:
1667 free_attribute( attr );
1668 return hr;
1671 static inline BOOL is_attribute_type( unsigned char type )
1673 return (type >= RECORD_SHORT_ATTRIBUTE && type <= RECORD_PREFIX_ATTRIBUTE_Z);
1676 static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1678 WS_XML_ATTRIBUTE *attr;
1679 unsigned char type = 0;
1680 HRESULT hr;
1682 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1683 if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT;
1684 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1686 if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z)
1688 unsigned char ch = type - RECORD_PREFIX_ATTRIBUTE_A + 'a';
1689 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1691 hr = E_OUTOFMEMORY;
1692 goto error;
1694 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1695 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1697 else if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
1699 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A + 'a';
1700 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1702 hr = E_OUTOFMEMORY;
1703 goto error;
1705 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1706 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1708 else
1710 switch (type)
1712 case RECORD_SHORT_ATTRIBUTE:
1713 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1715 hr = E_OUTOFMEMORY;
1716 goto error;
1718 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1719 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1720 break;
1722 case RECORD_ATTRIBUTE:
1723 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1724 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1725 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1726 break;
1728 case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
1729 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1731 hr = E_OUTOFMEMORY;
1732 goto error;
1734 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1735 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1736 break;
1738 case RECORD_DICTIONARY_ATTRIBUTE:
1739 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1740 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1741 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1742 break;
1744 case RECORD_SHORT_XMLNS_ATTRIBUTE:
1745 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1747 hr = E_OUTOFMEMORY;
1748 goto error;
1750 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1751 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1752 attr->isXmlNs = 1;
1753 break;
1755 case RECORD_XMLNS_ATTRIBUTE:
1756 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1757 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1758 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1759 attr->isXmlNs = 1;
1760 break;
1762 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
1763 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1765 hr = E_OUTOFMEMORY;
1766 goto error;
1768 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1769 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1770 attr->isXmlNs = 1;
1771 break;
1773 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
1774 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1775 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1776 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1777 attr->isXmlNs = 1;
1778 break;
1780 default:
1781 ERR( "unhandled record type %02x\n", type );
1782 return WS_E_NOT_SUPPORTED;
1786 *ret = attr;
1787 return S_OK;
1789 error:
1790 free_attribute( attr );
1791 return hr;
1794 static inline struct node *find_parent( struct reader *reader )
1796 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT)
1798 if (is_valid_parent( reader->current->parent->parent )) return reader->current->parent->parent;
1799 return NULL;
1801 if (is_valid_parent( reader->current )) return reader->current;
1802 if (is_valid_parent( reader->current->parent )) return reader->current->parent;
1803 return NULL;
1806 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1808 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1809 const WS_XML_STRING *ns;
1810 ULONG i;
1812 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1813 if (!(elem->ns = dup_xml_string( ns, FALSE ))) return E_OUTOFMEMORY;
1815 for (i = 0; i < elem->attributeCount; i++)
1817 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1818 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1819 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1820 if (!(attr->ns = alloc_xml_string( NULL, ns->length ))) return E_OUTOFMEMORY;
1821 if (attr->ns->length) memcpy( attr->ns->bytes, ns->bytes, ns->length );
1823 return S_OK;
1826 static WS_XML_ELEMENT_NODE *alloc_element_pair(void)
1828 struct node *node, *end;
1829 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
1830 if (!(end = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT )))
1832 free_node( node );
1833 return NULL;
1835 list_add_tail( &node->children, &end->entry );
1836 end->parent = node;
1837 return &node->hdr;
1840 static HRESULT read_attributes_text( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1842 WS_XML_ATTRIBUTE *attr;
1843 HRESULT hr;
1845 reader->current_attr = 0;
1846 for (;;)
1848 read_skip_whitespace( reader );
1849 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1850 if ((hr = read_attribute_text( reader, &attr )) != S_OK) return hr;
1851 if ((hr = append_attribute( elem, attr )) != S_OK)
1853 free_attribute( attr );
1854 return hr;
1856 reader->current_attr++;
1858 return S_OK;
1861 static HRESULT read_element_text( struct reader *reader )
1863 unsigned int len = 0, ch, skip;
1864 const unsigned char *start;
1865 struct node *node = NULL, *parent;
1866 WS_XML_ELEMENT_NODE *elem;
1867 HRESULT hr = WS_E_INVALID_FORMAT;
1869 if (read_end_of_data( reader ))
1871 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1872 reader->last = reader->current;
1873 reader->state = READER_STATE_EOF;
1874 return S_OK;
1877 if (read_cmp( reader, "<", 1 )) return WS_E_INVALID_FORMAT;
1878 read_skip( reader, 1 );
1879 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1881 read_rewind( reader, 1 );
1882 return WS_E_INVALID_FORMAT;
1885 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1886 node = (struct node *)elem;
1888 start = read_current_ptr( reader );
1889 for (;;)
1891 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1892 if (!read_isnamechar( ch )) break;
1893 read_skip( reader, skip );
1894 len += skip;
1896 if (!len) goto error;
1898 if (!(parent = find_parent( reader ))) goto error;
1899 if ((hr = parse_qname( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1900 if ((hr = read_attributes_text( reader, elem )) != S_OK) goto error;
1901 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1903 read_insert_node( reader, parent, node );
1904 reader->state = READER_STATE_STARTELEMENT;
1905 return S_OK;
1907 error:
1908 destroy_nodes( node );
1909 return hr;
1912 static inline BOOL is_element_type( unsigned char type )
1914 return (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z);
1917 static HRESULT read_attributes_bin( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1919 WS_XML_ATTRIBUTE *attr;
1920 unsigned char type;
1921 HRESULT hr;
1923 reader->current_attr = 0;
1924 for (;;)
1926 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
1927 if (!is_attribute_type( type )) break;
1928 if ((hr = read_attribute_bin( reader, &attr )) != S_OK) return hr;
1929 if ((hr = append_attribute( elem, attr )) != S_OK)
1931 free_attribute( attr );
1932 return hr;
1934 reader->current_attr++;
1936 return S_OK;
1939 static HRESULT read_element_bin( struct reader *reader )
1941 struct node *node = NULL, *parent;
1942 WS_XML_ELEMENT_NODE *elem;
1943 unsigned char type;
1944 HRESULT hr;
1946 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1947 if (!is_element_type( type )) return WS_E_INVALID_FORMAT;
1949 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1950 node = (struct node *)elem;
1952 if (type >= RECORD_PREFIX_ELEMENT_A && type <= RECORD_PREFIX_ELEMENT_Z)
1954 unsigned char ch = type - RECORD_PREFIX_ELEMENT_A + 'a';
1955 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1957 hr = E_OUTOFMEMORY;
1958 goto error;
1960 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1962 else if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
1964 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ELEMENT_A + 'a';
1965 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1967 hr = E_OUTOFMEMORY;
1968 goto error;
1970 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1972 else
1974 switch (type)
1976 case RECORD_SHORT_ELEMENT:
1977 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
1979 hr = E_OUTOFMEMORY;
1980 goto error;
1982 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1983 break;
1985 case RECORD_ELEMENT:
1986 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
1987 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1988 break;
1990 case RECORD_SHORT_DICTIONARY_ELEMENT:
1991 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
1993 hr = E_OUTOFMEMORY;
1994 goto error;
1996 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1997 break;
1999 case RECORD_DICTIONARY_ELEMENT:
2000 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
2001 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
2002 break;
2004 default:
2005 ERR( "unhandled record type %02x\n", type );
2006 return WS_E_NOT_SUPPORTED;
2010 if (!(parent = find_parent( reader )))
2012 hr = WS_E_INVALID_FORMAT;
2013 goto error;
2016 if ((hr = read_attributes_bin( reader, elem )) != S_OK) goto error;
2017 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
2019 read_insert_node( reader, parent, node );
2020 reader->state = READER_STATE_STARTELEMENT;
2021 return S_OK;
2023 error:
2024 destroy_nodes( node );
2025 return hr;
2028 static HRESULT read_text_text( struct reader *reader )
2030 unsigned int len = 0, ch, skip;
2031 const unsigned char *start;
2032 struct node *node, *parent;
2033 WS_XML_TEXT_NODE *text;
2034 WS_XML_UTF8_TEXT *utf8;
2035 HRESULT hr;
2037 start = read_current_ptr( reader );
2038 for (;;)
2040 if (read_end_of_data( reader )) break;
2041 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2042 if (ch == '<') break;
2043 read_skip( reader, skip );
2044 len += skip;
2047 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2049 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2050 text = (WS_XML_TEXT_NODE *)node;
2051 if (!(utf8 = alloc_utf8_text( NULL, len )))
2053 heap_free( node );
2054 return E_OUTOFMEMORY;
2056 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
2058 heap_free( utf8 );
2059 heap_free( node );
2060 return hr;
2062 text->text = &utf8->text;
2064 read_insert_node( reader, parent, node );
2065 reader->state = READER_STATE_TEXT;
2066 reader->text_conv_offset = 0;
2067 return S_OK;
2070 static struct node *alloc_utf8_text_node( const BYTE *data, ULONG len, WS_XML_UTF8_TEXT **ret )
2072 struct node *node;
2073 WS_XML_UTF8_TEXT *utf8;
2074 WS_XML_TEXT_NODE *text;
2076 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2077 if (!(utf8 = alloc_utf8_text( data, len )))
2079 heap_free( node );
2080 return NULL;
2082 text = (WS_XML_TEXT_NODE *)node;
2083 text->text = &utf8->text;
2084 if (ret) *ret = utf8;
2085 return node;
2088 static struct node *alloc_base64_text_node( const BYTE *data, ULONG len, WS_XML_BASE64_TEXT **ret )
2090 struct node *node;
2091 WS_XML_BASE64_TEXT *base64;
2092 WS_XML_TEXT_NODE *text;
2094 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2095 if (!(base64 = alloc_base64_text( data, len )))
2097 heap_free( node );
2098 return NULL;
2100 text = (WS_XML_TEXT_NODE *)node;
2101 text->text = &base64->text;
2102 if (ret) *ret = base64;
2103 return node;
2106 static struct node *alloc_bool_text_node( BOOL value )
2108 struct node *node;
2109 WS_XML_BOOL_TEXT *text_bool;
2110 WS_XML_TEXT_NODE *text;
2112 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2113 if (!(text_bool = alloc_bool_text( value )))
2115 heap_free( node );
2116 return NULL;
2118 text = (WS_XML_TEXT_NODE *)node;
2119 text->text = &text_bool->text;
2120 return node;
2123 static struct node *alloc_int32_text_node( INT32 value )
2125 struct node *node;
2126 WS_XML_INT32_TEXT *text_int32;
2127 WS_XML_TEXT_NODE *text;
2129 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2130 if (!(text_int32 = alloc_int32_text( value )))
2132 heap_free( node );
2133 return NULL;
2135 text = (WS_XML_TEXT_NODE *)node;
2136 text->text = &text_int32->text;
2137 return node;
2140 static struct node *alloc_int64_text_node( INT64 value )
2142 struct node *node;
2143 WS_XML_INT64_TEXT *text_int64;
2144 WS_XML_TEXT_NODE *text;
2146 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2147 if (!(text_int64 = alloc_int64_text( value )))
2149 heap_free( node );
2150 return NULL;
2152 text = (WS_XML_TEXT_NODE *)node;
2153 text->text = &text_int64->text;
2154 return node;
2157 static struct node *alloc_float_text_node( float value )
2159 struct node *node;
2160 WS_XML_FLOAT_TEXT *text_float;
2161 WS_XML_TEXT_NODE *text;
2163 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2164 if (!(text_float = alloc_float_text( value )))
2166 heap_free( node );
2167 return NULL;
2169 text = (WS_XML_TEXT_NODE *)node;
2170 text->text = &text_float->text;
2171 return node;
2174 static struct node *alloc_double_text_node( double value )
2176 struct node *node;
2177 WS_XML_DOUBLE_TEXT *text_double;
2178 WS_XML_TEXT_NODE *text;
2180 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2181 if (!(text_double = alloc_double_text( value )))
2183 heap_free( node );
2184 return NULL;
2186 text = (WS_XML_TEXT_NODE *)node;
2187 text->text = &text_double->text;
2188 return node;
2191 static struct node *alloc_datetime_text_node( const WS_DATETIME *value )
2193 struct node *node;
2194 WS_XML_DATETIME_TEXT *text_datetime;
2195 WS_XML_TEXT_NODE *text;
2197 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2198 if (!(text_datetime = alloc_datetime_text( value )))
2200 heap_free( node );
2201 return NULL;
2203 text = (WS_XML_TEXT_NODE *)node;
2204 text->text = &text_datetime->text;
2205 return node;
2208 static struct node *alloc_unique_id_text_node( const GUID *value )
2210 struct node *node;
2211 WS_XML_UNIQUE_ID_TEXT *text_unique_id;
2212 WS_XML_TEXT_NODE *text;
2214 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2215 if (!(text_unique_id = alloc_unique_id_text( value )))
2217 heap_free( node );
2218 return NULL;
2220 text = (WS_XML_TEXT_NODE *)node;
2221 text->text = &text_unique_id->text;
2222 return node;
2225 static struct node *alloc_guid_text_node( const GUID *value )
2227 struct node *node;
2228 WS_XML_GUID_TEXT *text_guid;
2229 WS_XML_TEXT_NODE *text;
2231 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2232 if (!(text_guid = alloc_guid_text( value )))
2234 heap_free( node );
2235 return NULL;
2237 text = (WS_XML_TEXT_NODE *)node;
2238 text->text = &text_guid->text;
2239 return node;
2242 static struct node *alloc_uint64_text_node( UINT64 value )
2244 struct node *node;
2245 WS_XML_UINT64_TEXT *text_uint64;
2246 WS_XML_TEXT_NODE *text;
2248 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
2249 if (!(text_uint64 = alloc_uint64_text( value )))
2251 heap_free( node );
2252 return NULL;
2254 text = (WS_XML_TEXT_NODE *)node;
2255 text->text = &text_uint64->text;
2256 return node;
2259 static HRESULT append_text_bytes( struct reader *reader, WS_XML_TEXT_NODE *node, ULONG len )
2261 WS_XML_BASE64_TEXT *new, *old = (WS_XML_BASE64_TEXT *)node->text;
2262 HRESULT hr;
2264 if (!(new = alloc_base64_text( NULL, old->length + len ))) return E_OUTOFMEMORY;
2265 memcpy( new->bytes, old->bytes, old->length );
2266 if ((hr = read_bytes( reader, new->bytes + old->length, len )) != S_OK) return hr;
2267 heap_free( old );
2268 node->text = &new->text;
2269 return S_OK;
2272 static HRESULT read_text_bytes( struct reader *reader, unsigned char type )
2274 struct node *node = NULL, *parent;
2275 WS_XML_BASE64_TEXT *base64;
2276 HRESULT hr;
2277 ULONG len;
2279 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2280 for (;;)
2282 switch (type)
2284 case RECORD_BYTES8_TEXT:
2285 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2287 UINT8 len_uint8;
2288 if ((hr = read_byte( reader, (unsigned char *)&len_uint8 )) != S_OK) goto error;
2289 len = len_uint8;
2290 break;
2292 case RECORD_BYTES16_TEXT:
2293 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2295 UINT16 len_uint16;
2296 if ((hr = read_bytes( reader, (unsigned char *)&len_uint16, sizeof(len_uint16) )) != S_OK) goto error;
2297 len = len_uint16;
2298 break;
2300 case RECORD_BYTES32_TEXT:
2301 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2303 INT32 len_int32;
2304 if ((hr = read_bytes( reader, (unsigned char *)&len_int32, sizeof(len_int32) )) != S_OK) goto error;
2305 if (len_int32 < 0)
2307 hr = WS_E_INVALID_FORMAT;
2308 goto error;
2310 len = len_int32;
2311 break;
2313 default:
2314 ERR( "unexpected type %u\n", type );
2315 hr = E_INVALIDARG;
2316 goto error;
2319 if (!node)
2321 if (!(node = alloc_base64_text_node( NULL, len, &base64 ))) return E_OUTOFMEMORY;
2322 if ((hr = read_bytes( reader, base64->bytes, len )) != S_OK) goto error;
2324 else if ((hr = append_text_bytes( reader, (WS_XML_TEXT_NODE *)node, len )) != S_OK) goto error;
2326 if (type & 1)
2328 node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2329 break;
2331 if ((hr = read_peek( reader, &type )) != S_OK) goto error;
2332 if (type < RECORD_BYTES8_TEXT || type > RECORD_BYTES32_TEXT_WITH_ENDELEMENT) break;
2333 read_skip( reader, 1 );
2336 read_insert_node( reader, parent, node );
2337 reader->state = READER_STATE_TEXT;
2338 reader->text_conv_offset = 0;
2339 return S_OK;
2341 error:
2342 free_node( node );
2343 return hr;
2346 static HRESULT read_text_bin( struct reader *reader )
2348 struct node *node = NULL, *parent;
2349 unsigned char type;
2350 WS_XML_UTF8_TEXT *utf8;
2351 INT32 val_int32;
2352 UINT8 val_uint8;
2353 UINT16 val_uint16;
2354 ULONG len, id;
2355 GUID uuid;
2356 HRESULT hr;
2358 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2359 if (!is_text_type( type ) || !(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2361 switch (type)
2363 case RECORD_ZERO_TEXT:
2364 case RECORD_ZERO_TEXT_WITH_ENDELEMENT:
2365 if (!(node = alloc_int32_text_node( 0 ))) return E_OUTOFMEMORY;
2366 break;
2368 case RECORD_ONE_TEXT:
2369 case RECORD_ONE_TEXT_WITH_ENDELEMENT:
2370 if (!(node = alloc_int32_text_node( 1 ))) return E_OUTOFMEMORY;
2371 break;
2373 case RECORD_FALSE_TEXT:
2374 case RECORD_FALSE_TEXT_WITH_ENDELEMENT:
2375 if (!(node = alloc_bool_text_node( FALSE ))) return E_OUTOFMEMORY;
2376 break;
2378 case RECORD_TRUE_TEXT:
2379 case RECORD_TRUE_TEXT_WITH_ENDELEMENT:
2380 if (!(node = alloc_bool_text_node( TRUE ))) return E_OUTOFMEMORY;
2381 break;
2383 case RECORD_INT8_TEXT:
2384 case RECORD_INT8_TEXT_WITH_ENDELEMENT:
2386 INT8 val_int8;
2387 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
2388 if (!(node = alloc_int32_text_node( val_int8 ))) return E_OUTOFMEMORY;
2389 break;
2391 case RECORD_INT16_TEXT:
2392 case RECORD_INT16_TEXT_WITH_ENDELEMENT:
2394 INT16 val_int16;
2395 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
2396 if (!(node = alloc_int32_text_node( val_int16 ))) return E_OUTOFMEMORY;
2397 break;
2399 case RECORD_INT32_TEXT:
2400 case RECORD_INT32_TEXT_WITH_ENDELEMENT:
2401 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2402 if (!(node = alloc_int32_text_node( val_int32 ))) return E_OUTOFMEMORY;
2403 break;
2405 case RECORD_INT64_TEXT:
2406 case RECORD_INT64_TEXT_WITH_ENDELEMENT:
2408 INT64 val_int64;
2409 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
2410 if (!(node = alloc_int64_text_node( val_int64 ))) return E_OUTOFMEMORY;
2411 break;
2413 case RECORD_FLOAT_TEXT:
2414 case RECORD_FLOAT_TEXT_WITH_ENDELEMENT:
2416 float val_float;
2417 if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
2418 if (!(node = alloc_float_text_node( val_float ))) return E_OUTOFMEMORY;
2419 break;
2421 case RECORD_DOUBLE_TEXT:
2422 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT:
2424 double val_double;
2425 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
2426 if (!(node = alloc_double_text_node( val_double ))) return E_OUTOFMEMORY;
2427 break;
2429 case RECORD_DATETIME_TEXT:
2430 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT:
2432 WS_DATETIME datetime;
2433 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
2434 if (!(node = alloc_datetime_text_node( &datetime ))) return E_OUTOFMEMORY;
2435 break;
2437 case RECORD_CHARS8_TEXT:
2438 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT:
2439 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
2440 len = val_uint8;
2441 break;
2443 case RECORD_CHARS16_TEXT:
2444 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT:
2445 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
2446 len = val_uint16;
2447 break;
2449 case RECORD_CHARS32_TEXT:
2450 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT:
2451 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2452 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
2453 len = val_int32;
2454 break;
2456 case RECORD_BYTES8_TEXT:
2457 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2458 case RECORD_BYTES16_TEXT:
2459 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2460 case RECORD_BYTES32_TEXT:
2461 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2462 return read_text_bytes( reader, type );
2464 case RECORD_EMPTY_TEXT:
2465 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT:
2466 len = 0;
2467 break;
2469 case RECORD_DICTIONARY_TEXT:
2470 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT:
2472 const WS_XML_STRING *str;
2473 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
2474 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
2475 if (!(node = alloc_utf8_text_node( str->bytes, str->length, NULL ))) return E_OUTOFMEMORY;
2476 break;
2478 case RECORD_UNIQUE_ID_TEXT:
2479 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT:
2480 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2481 if (!(node = alloc_unique_id_text_node( &uuid ))) return E_OUTOFMEMORY;
2482 break;
2484 case RECORD_GUID_TEXT:
2485 case RECORD_GUID_TEXT_WITH_ENDELEMENT:
2486 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2487 if (!(node = alloc_guid_text_node( &uuid ))) return E_OUTOFMEMORY;
2488 break;
2490 case RECORD_UINT64_TEXT:
2491 case RECORD_UINT64_TEXT_WITH_ENDELEMENT:
2493 UINT64 val_uint64;
2494 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
2495 if (!(node = alloc_uint64_text_node( val_uint64 ))) return E_OUTOFMEMORY;
2496 break;
2498 case RECORD_BOOL_TEXT:
2499 case RECORD_BOOL_TEXT_WITH_ENDELEMENT:
2501 BOOL val_bool;
2502 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
2503 if (!(node = alloc_bool_text_node( !!val_bool ))) return E_OUTOFMEMORY;
2504 break;
2506 default:
2507 ERR( "unhandled record type %02x\n", type );
2508 return WS_E_NOT_SUPPORTED;
2511 if (!node)
2513 if (!(node = alloc_utf8_text_node( NULL, len, &utf8 ))) return E_OUTOFMEMORY;
2514 if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
2515 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
2517 free_node( node );
2518 return hr;
2522 if (type & 1) node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2523 read_insert_node( reader, parent, node );
2524 reader->state = READER_STATE_TEXT;
2525 reader->text_conv_offset = 0;
2526 return S_OK;
2529 static HRESULT read_node_text( struct reader * );
2531 static HRESULT read_startelement_text( struct reader *reader )
2533 read_skip_whitespace( reader );
2534 if (!read_cmp( reader, "/>", 2 ))
2536 read_skip( reader, 2 );
2537 reader->current = LIST_ENTRY( list_tail( &reader->current->children ), struct node, entry );
2538 reader->last = reader->current;
2539 reader->state = READER_STATE_ENDELEMENT;
2540 return S_OK;
2542 else if (!read_cmp( reader, ">", 1 ))
2544 read_skip( reader, 1 );
2545 return read_node_text( reader );
2547 return WS_E_INVALID_FORMAT;
2550 static HRESULT read_node_bin( struct reader * );
2552 static HRESULT read_startelement_bin( struct reader *reader )
2554 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
2555 return read_node_bin( reader );
2558 static HRESULT read_startelement( struct reader *reader )
2560 switch (reader->input_enc)
2562 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_startelement_text( reader );
2563 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_startelement_bin( reader );
2564 default:
2565 ERR( "unhandled encoding %u\n", reader->input_enc );
2566 return WS_E_NOT_SUPPORTED;
2570 static HRESULT read_to_startelement_text( struct reader *reader, BOOL *found )
2572 HRESULT hr;
2574 switch (reader->state)
2576 case READER_STATE_INITIAL:
2577 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
2578 break;
2580 case READER_STATE_STARTELEMENT:
2581 if (found) *found = TRUE;
2582 return S_OK;
2584 default:
2585 break;
2588 read_skip_whitespace( reader );
2589 if ((hr = read_element_text( reader )) == S_OK && found)
2591 if (reader->state == READER_STATE_STARTELEMENT)
2592 *found = TRUE;
2593 else
2594 *found = FALSE;
2597 return hr;
2600 static HRESULT read_to_startelement_bin( struct reader *reader, BOOL *found )
2602 HRESULT hr;
2604 if (reader->state == READER_STATE_STARTELEMENT)
2606 if (found) *found = TRUE;
2607 return S_OK;
2610 if ((hr = read_element_bin( reader )) == S_OK && found)
2612 if (reader->state == READER_STATE_STARTELEMENT)
2613 *found = TRUE;
2614 else
2615 *found = FALSE;
2618 return hr;
2621 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
2623 switch (reader->input_enc)
2625 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_to_startelement_text( reader, found );
2626 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_to_startelement_bin( reader, found );
2627 default:
2628 ERR( "unhandled encoding %u\n", reader->input_enc );
2629 return WS_E_NOT_SUPPORTED;
2633 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
2635 ULONG i;
2636 if (len1 != len2) return 1;
2637 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
2638 return 0;
2641 static struct node *find_startelement( struct reader *reader, const WS_XML_STRING *prefix,
2642 const WS_XML_STRING *localname )
2644 struct node *parent;
2645 const WS_XML_STRING *str;
2647 for (parent = reader->current; parent; parent = parent->parent)
2649 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
2651 str = parent->hdr.prefix;
2652 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
2653 str = parent->hdr.localName;
2654 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
2655 return parent;
2658 return NULL;
2661 static HRESULT read_endelement_text( struct reader *reader )
2663 struct node *parent;
2664 unsigned int len = 0, ch, skip;
2665 const unsigned char *start;
2666 WS_XML_STRING prefix, localname;
2667 HRESULT hr;
2669 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
2670 read_skip( reader, 2 );
2672 start = read_current_ptr( reader );
2673 for (;;)
2675 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2676 if (ch == '>')
2678 read_skip( reader, 1 );
2679 break;
2681 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
2682 read_skip( reader, skip );
2683 len += skip;
2686 if ((hr = split_qname( start, len, &prefix, &localname )) != S_OK) return hr;
2687 if (!(parent = find_startelement( reader, &prefix, &localname ))) return WS_E_INVALID_FORMAT;
2689 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2690 reader->last = reader->current;
2691 reader->state = READER_STATE_ENDELEMENT;
2692 return S_OK;
2695 static HRESULT read_endelement_bin( struct reader *reader )
2697 struct node *parent;
2698 unsigned char type;
2699 HRESULT hr;
2701 if (!(reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT))
2703 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2704 if (type != RECORD_ENDELEMENT) return WS_E_INVALID_FORMAT;
2706 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2708 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2709 reader->last = reader->current;
2710 reader->state = READER_STATE_ENDELEMENT;
2711 return S_OK;
2714 static HRESULT read_endelement( struct reader *reader )
2716 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2718 if (read_end_of_data( reader ))
2720 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2721 reader->last = reader->current;
2722 reader->state = READER_STATE_EOF;
2723 return S_OK;
2726 switch (reader->input_enc)
2728 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_endelement_text( reader );
2729 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_endelement_bin( reader );
2730 default:
2731 ERR( "unhandled encoding %u\n", reader->input_enc );
2732 return WS_E_NOT_SUPPORTED;
2736 static HRESULT read_comment_text( struct reader *reader )
2738 unsigned int len = 0, ch, skip;
2739 const unsigned char *start;
2740 struct node *node, *parent;
2741 WS_XML_COMMENT_NODE *comment;
2743 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
2744 read_skip( reader, 4 );
2746 start = read_current_ptr( reader );
2747 for (;;)
2749 if (!read_cmp( reader, "-->", 3 ))
2751 read_skip( reader, 3 );
2752 break;
2754 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2755 read_skip( reader, skip );
2756 len += skip;
2759 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2761 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2762 comment = (WS_XML_COMMENT_NODE *)node;
2763 if (!(comment->value.bytes = heap_alloc( len )))
2765 heap_free( node );
2766 return E_OUTOFMEMORY;
2768 memcpy( comment->value.bytes, start, len );
2769 comment->value.length = len;
2771 read_insert_node( reader, parent, node );
2772 reader->state = READER_STATE_COMMENT;
2773 return S_OK;
2776 static HRESULT read_comment_bin( struct reader *reader )
2778 struct node *node, *parent;
2779 WS_XML_COMMENT_NODE *comment;
2780 unsigned char type;
2781 ULONG len;
2782 HRESULT hr;
2784 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2785 if (type != RECORD_COMMENT) return WS_E_INVALID_FORMAT;
2786 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
2788 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2790 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2791 comment = (WS_XML_COMMENT_NODE *)node;
2792 if (!(comment->value.bytes = heap_alloc( len )))
2794 heap_free( node );
2795 return E_OUTOFMEMORY;
2797 if ((hr = read_bytes( reader, comment->value.bytes, len )) != S_OK)
2799 free_node( node );
2800 return E_OUTOFMEMORY;
2802 comment->value.length = len;
2804 read_insert_node( reader, parent, node );
2805 reader->state = READER_STATE_COMMENT;
2806 return S_OK;
2809 static HRESULT read_startcdata( struct reader *reader )
2811 struct node *node, *endnode, *parent;
2813 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
2814 read_skip( reader, 9 );
2816 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2818 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
2819 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_CDATA )))
2821 heap_free( node );
2822 return E_OUTOFMEMORY;
2824 list_add_tail( &node->children, &endnode->entry );
2825 endnode->parent = node;
2827 read_insert_node( reader, parent, node );
2828 reader->state = READER_STATE_STARTCDATA;
2829 return S_OK;
2832 static HRESULT read_cdata( struct reader *reader )
2834 unsigned int len = 0, ch, skip;
2835 const unsigned char *start;
2836 struct node *node;
2837 WS_XML_TEXT_NODE *text;
2838 WS_XML_UTF8_TEXT *utf8;
2840 start = read_current_ptr( reader );
2841 for (;;)
2843 if (!read_cmp( reader, "]]>", 3 )) break;
2844 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2845 read_skip( reader, skip );
2846 len += skip;
2849 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2850 text = (WS_XML_TEXT_NODE *)node;
2851 if (!(utf8 = alloc_utf8_text( start, len )))
2853 heap_free( node );
2854 return E_OUTOFMEMORY;
2856 text->text = &utf8->text;
2858 read_insert_node( reader, reader->current, node );
2859 reader->state = READER_STATE_CDATA;
2860 return S_OK;
2863 static HRESULT read_endcdata( struct reader *reader )
2865 struct node *parent;
2867 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
2868 read_skip( reader, 3 );
2870 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT) parent = reader->current->parent;
2871 else parent = reader->current;
2873 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2874 reader->last = reader->current;
2875 reader->state = READER_STATE_ENDCDATA;
2876 return S_OK;
2879 static HRESULT read_node_text( struct reader *reader )
2881 HRESULT hr;
2883 for (;;)
2885 if (read_end_of_data( reader ))
2887 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2888 reader->last = reader->current;
2889 reader->state = READER_STATE_EOF;
2890 return S_OK;
2892 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
2893 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
2894 else if (!read_cmp( reader, "<?", 2 ))
2896 hr = read_xmldecl( reader );
2897 if (FAILED( hr )) return hr;
2899 else if (!read_cmp( reader, "</", 2 )) return read_endelement_text( reader );
2900 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
2901 else if (!read_cmp( reader, "<!--", 4 )) return read_comment_text( reader );
2902 else if (!read_cmp( reader, "<", 1 )) return read_element_text( reader );
2903 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement_text( reader );
2904 else return read_text_text( reader );
2908 static HRESULT read_node_bin( struct reader *reader )
2910 unsigned char type;
2911 HRESULT hr;
2913 if (reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT)
2915 reader->current = LIST_ENTRY( list_tail( &reader->current->parent->children ), struct node, entry );
2916 reader->last = reader->current;
2917 reader->state = READER_STATE_ENDELEMENT;
2918 return S_OK;
2920 if (read_end_of_data( reader ))
2922 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2923 reader->last = reader->current;
2924 reader->state = READER_STATE_EOF;
2925 return S_OK;
2928 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
2929 if (type == RECORD_ENDELEMENT)
2931 return read_endelement_bin( reader );
2933 else if (type == RECORD_COMMENT)
2935 return read_comment_bin( reader );
2937 else if (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z)
2939 return read_element_bin( reader );
2941 else if (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT)
2943 return read_text_bin( reader );
2945 FIXME( "unhandled record type %02x\n", type );
2946 return WS_E_NOT_SUPPORTED;
2949 static HRESULT read_node( struct reader *reader )
2951 switch (reader->input_enc)
2953 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_node_text( reader );
2954 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_node_bin( reader );
2955 default:
2956 ERR( "unhandled encoding %u\n", reader->input_enc );
2957 return WS_E_NOT_SUPPORTED;
2961 HRESULT copy_node( WS_XML_READER *handle, struct node **node )
2963 struct reader *reader = (struct reader *)handle;
2964 const struct list *ptr;
2965 const struct node *start;
2966 HRESULT hr;
2968 EnterCriticalSection( &reader->cs );
2970 if (reader->magic != READER_MAGIC)
2972 LeaveCriticalSection( &reader->cs );
2973 return E_INVALIDARG;
2976 if (reader->current != reader->root) ptr = &reader->current->entry;
2977 else /* copy whole tree */
2979 if (!read_end_of_data( reader ))
2981 for (;;)
2983 if ((hr = read_node( reader )) != S_OK) goto done;
2984 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) break;
2987 ptr = list_head( &reader->root->children );
2990 start = LIST_ENTRY( ptr, struct node, entry );
2991 if (node_type( start ) == WS_XML_NODE_TYPE_EOF) hr = WS_E_INVALID_OPERATION;
2992 else hr = dup_tree( node, start );
2994 done:
2995 LeaveCriticalSection( &reader->cs );
2996 return hr;
2999 /**************************************************************************
3000 * WsReadEndElement [webservices.@]
3002 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
3004 struct reader *reader = (struct reader *)handle;
3005 HRESULT hr;
3007 TRACE( "%p %p\n", handle, error );
3008 if (error) FIXME( "ignoring error parameter\n" );
3010 if (!reader) return E_INVALIDARG;
3012 EnterCriticalSection( &reader->cs );
3014 if (reader->magic != READER_MAGIC)
3016 LeaveCriticalSection( &reader->cs );
3017 return E_INVALIDARG;
3020 hr = read_endelement( reader );
3022 LeaveCriticalSection( &reader->cs );
3023 return hr;
3026 /**************************************************************************
3027 * WsReadNode [webservices.@]
3029 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
3031 struct reader *reader = (struct reader *)handle;
3032 HRESULT hr;
3034 TRACE( "%p %p\n", handle, error );
3035 if (error) FIXME( "ignoring error parameter\n" );
3037 if (!reader) return E_INVALIDARG;
3039 EnterCriticalSection( &reader->cs );
3041 if (reader->magic != READER_MAGIC)
3043 LeaveCriticalSection( &reader->cs );
3044 return E_INVALIDARG;
3047 hr = read_node( reader );
3049 LeaveCriticalSection( &reader->cs );
3050 return hr;
3053 static HRESULT skip_node( struct reader *reader )
3055 const struct node *parent;
3056 HRESULT hr;
3058 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) return WS_E_INVALID_OPERATION;
3059 if (node_type( reader->current ) == WS_XML_NODE_TYPE_ELEMENT) parent = reader->current;
3060 else parent = NULL;
3062 for (;;)
3064 if ((hr = read_node( reader )) != S_OK || !parent) break;
3065 if (node_type( reader->current ) != WS_XML_NODE_TYPE_END_ELEMENT) continue;
3066 if (reader->current->parent == parent) return read_node( reader );
3069 return hr;
3072 /**************************************************************************
3073 * WsSkipNode [webservices.@]
3075 HRESULT WINAPI WsSkipNode( WS_XML_READER *handle, WS_ERROR *error )
3077 struct reader *reader = (struct reader *)handle;
3078 HRESULT hr;
3080 TRACE( "%p %p\n", handle, error );
3081 if (error) FIXME( "ignoring error parameter\n" );
3083 if (!reader) return E_INVALIDARG;
3085 EnterCriticalSection( &reader->cs );
3087 if (reader->magic != READER_MAGIC)
3089 LeaveCriticalSection( &reader->cs );
3090 return E_INVALIDARG;
3093 hr = skip_node( reader );
3095 LeaveCriticalSection( &reader->cs );
3096 return hr;
3099 /**************************************************************************
3100 * WsReadStartElement [webservices.@]
3102 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
3104 struct reader *reader = (struct reader *)handle;
3105 HRESULT hr;
3107 TRACE( "%p %p\n", handle, error );
3108 if (error) FIXME( "ignoring error parameter\n" );
3110 if (!reader) return E_INVALIDARG;
3112 EnterCriticalSection( &reader->cs );
3114 if (reader->magic != READER_MAGIC)
3116 LeaveCriticalSection( &reader->cs );
3117 return E_INVALIDARG;
3120 hr = read_startelement( reader );
3122 LeaveCriticalSection( &reader->cs );
3123 return hr;
3126 /**************************************************************************
3127 * WsReadToStartElement [webservices.@]
3129 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
3130 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
3132 struct reader *reader = (struct reader *)handle;
3133 HRESULT hr;
3135 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
3136 if (error) FIXME( "ignoring error parameter\n" );
3138 if (!reader) return E_INVALIDARG;
3139 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
3141 EnterCriticalSection( &reader->cs );
3143 if (reader->magic != READER_MAGIC)
3145 LeaveCriticalSection( &reader->cs );
3146 return E_INVALIDARG;
3149 hr = read_to_startelement( reader, found );
3151 LeaveCriticalSection( &reader->cs );
3152 return hr;
3155 BOOL move_to_root_element( struct node *root, struct node **current )
3157 struct list *ptr;
3158 struct node *node;
3160 if (!(ptr = list_head( &root->children ))) return FALSE;
3161 node = LIST_ENTRY( ptr, struct node, entry );
3162 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
3164 *current = node;
3165 return TRUE;
3167 while ((ptr = list_next( &root->children, &node->entry )))
3169 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3170 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3172 *current = next;
3173 return TRUE;
3175 node = next;
3177 return FALSE;
3180 BOOL move_to_next_element( struct node **current )
3182 struct list *ptr;
3183 struct node *node = *current, *parent = (*current)->parent;
3185 if (!parent) return FALSE;
3186 while ((ptr = list_next( &parent->children, &node->entry )))
3188 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3189 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3191 *current = next;
3192 return TRUE;
3194 node = next;
3196 return FALSE;
3199 BOOL move_to_prev_element( struct node **current )
3201 struct list *ptr;
3202 struct node *node = *current, *parent = (*current)->parent;
3204 if (!parent) return FALSE;
3205 while ((ptr = list_prev( &parent->children, &node->entry )))
3207 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
3208 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
3210 *current = prev;
3211 return TRUE;
3213 node = prev;
3215 return FALSE;
3218 BOOL move_to_child_element( struct node **current )
3220 struct list *ptr;
3221 struct node *child, *node = *current;
3223 if (!(ptr = list_head( &node->children ))) return FALSE;
3224 child = LIST_ENTRY( ptr, struct node, entry );
3225 if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
3227 *current = child;
3228 return TRUE;
3230 while ((ptr = list_next( &node->children, &child->entry )))
3232 struct node *next = LIST_ENTRY( ptr, struct node, entry );
3233 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
3235 *current = next;
3236 return TRUE;
3238 child = next;
3240 return FALSE;
3243 BOOL move_to_end_element( struct node **current )
3245 struct list *ptr;
3246 struct node *node = *current;
3248 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3250 if ((ptr = list_tail( &node->children )))
3252 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
3253 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
3255 *current = tail;
3256 return TRUE;
3259 return FALSE;
3262 BOOL move_to_parent_element( struct node **current )
3264 struct node *parent = (*current)->parent;
3266 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
3267 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
3269 *current = parent;
3270 return TRUE;
3272 return FALSE;
3275 BOOL move_to_first_node( struct node **current )
3277 struct list *ptr;
3278 struct node *node = *current;
3280 if ((ptr = list_head( &node->parent->children )))
3282 *current = LIST_ENTRY( ptr, struct node, entry );
3283 return TRUE;
3285 return FALSE;
3288 BOOL move_to_next_node( struct node **current )
3290 struct list *ptr;
3291 struct node *node = *current;
3293 if ((ptr = list_next( &node->parent->children, &node->entry )))
3295 *current = LIST_ENTRY( ptr, struct node, entry );
3296 return TRUE;
3298 return FALSE;
3301 BOOL move_to_prev_node( struct node **current )
3303 struct list *ptr;
3304 struct node *node = *current;
3306 if ((ptr = list_prev( &node->parent->children, &node->entry )))
3308 *current = LIST_ENTRY( ptr, struct node, entry );
3309 return TRUE;
3311 return FALSE;
3314 BOOL move_to_bof( struct node *root, struct node **current )
3316 *current = root;
3317 return TRUE;
3320 BOOL move_to_eof( struct node *root, struct node **current )
3322 struct list *ptr;
3323 if ((ptr = list_tail( &root->children )))
3325 *current = LIST_ENTRY( ptr, struct node, entry );
3326 return TRUE;
3328 return FALSE;
3331 BOOL move_to_child_node( struct node **current )
3333 struct list *ptr;
3334 struct node *node = *current;
3336 if ((ptr = list_head( &node->children )))
3338 *current = LIST_ENTRY( ptr, struct node, entry );
3339 return TRUE;
3341 return FALSE;
3344 BOOL move_to_parent_node( struct node **current )
3346 struct node *parent = (*current)->parent;
3347 if (!parent) return FALSE;
3348 *current = parent;
3349 return TRUE;
3352 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
3354 BOOL success = FALSE;
3355 HRESULT hr = S_OK;
3357 if (!read_end_of_data( reader ))
3359 struct node *saved_current = reader->current;
3360 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
3361 if (hr != S_OK) return hr;
3362 reader->current = saved_current;
3364 switch (move)
3366 case WS_MOVE_TO_ROOT_ELEMENT:
3367 success = move_to_root_element( reader->root, &reader->current );
3368 break;
3370 case WS_MOVE_TO_NEXT_ELEMENT:
3371 success = move_to_next_element( &reader->current );
3372 break;
3374 case WS_MOVE_TO_PREVIOUS_ELEMENT:
3375 success = move_to_prev_element( &reader->current );
3376 break;
3378 case WS_MOVE_TO_CHILD_ELEMENT:
3379 success = move_to_child_element( &reader->current );
3380 break;
3382 case WS_MOVE_TO_END_ELEMENT:
3383 success = move_to_end_element( &reader->current );
3384 break;
3386 case WS_MOVE_TO_PARENT_ELEMENT:
3387 success = move_to_parent_element( &reader->current );
3388 break;
3390 case WS_MOVE_TO_FIRST_NODE:
3391 success = move_to_first_node( &reader->current );
3392 break;
3394 case WS_MOVE_TO_NEXT_NODE:
3395 success = move_to_next_node( &reader->current );
3396 break;
3398 case WS_MOVE_TO_PREVIOUS_NODE:
3399 success = move_to_prev_node( &reader->current );
3400 break;
3402 case WS_MOVE_TO_CHILD_NODE:
3403 success = move_to_child_node( &reader->current );
3404 break;
3406 case WS_MOVE_TO_BOF:
3407 success = move_to_bof( reader->root, &reader->current );
3408 break;
3410 case WS_MOVE_TO_EOF:
3411 success = move_to_eof( reader->root, &reader->current );
3412 break;
3414 default:
3415 FIXME( "unhandled move %u\n", move );
3416 return E_NOTIMPL;
3419 if (found)
3421 *found = success;
3422 return S_OK;
3424 return success ? S_OK : WS_E_INVALID_FORMAT;
3427 /**************************************************************************
3428 * WsMoveReader [webservices.@]
3430 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
3432 struct reader *reader = (struct reader *)handle;
3433 HRESULT hr;
3435 TRACE( "%p %u %p %p\n", handle, move, found, error );
3436 if (error) FIXME( "ignoring error parameter\n" );
3438 if (!reader) return E_INVALIDARG;
3440 EnterCriticalSection( &reader->cs );
3442 if (reader->magic != READER_MAGIC)
3444 LeaveCriticalSection( &reader->cs );
3445 return E_INVALIDARG;
3448 if (!reader->input_type)
3450 LeaveCriticalSection( &reader->cs );
3451 return WS_E_INVALID_OPERATION;
3454 hr = read_move_to( reader, move, found );
3456 LeaveCriticalSection( &reader->cs );
3457 return hr;
3460 /**************************************************************************
3461 * WsReadStartAttribute [webservices.@]
3463 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
3465 struct reader *reader = (struct reader *)handle;
3466 const WS_XML_ELEMENT_NODE *elem;
3468 TRACE( "%p %u %p\n", handle, index, error );
3469 if (error) FIXME( "ignoring error parameter\n" );
3471 if (!reader) return E_INVALIDARG;
3473 EnterCriticalSection( &reader->cs );
3475 if (reader->magic != READER_MAGIC)
3477 LeaveCriticalSection( &reader->cs );
3478 return E_INVALIDARG;
3481 elem = &reader->current->hdr;
3482 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
3484 LeaveCriticalSection( &reader->cs );
3485 return WS_E_INVALID_FORMAT;
3488 reader->current_attr = index;
3489 reader->state = READER_STATE_STARTATTRIBUTE;
3491 LeaveCriticalSection( &reader->cs );
3492 return S_OK;
3495 /**************************************************************************
3496 * WsReadEndAttribute [webservices.@]
3498 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
3500 struct reader *reader = (struct reader *)handle;
3502 TRACE( "%p %p\n", handle, error );
3503 if (error) FIXME( "ignoring error parameter\n" );
3505 if (!reader) return E_INVALIDARG;
3507 EnterCriticalSection( &reader->cs );
3509 if (reader->magic != READER_MAGIC)
3511 LeaveCriticalSection( &reader->cs );
3512 return E_INVALIDARG;
3515 if (reader->state != READER_STATE_STARTATTRIBUTE)
3517 LeaveCriticalSection( &reader->cs );
3518 return WS_E_INVALID_FORMAT;
3521 reader->state = READER_STATE_STARTELEMENT;
3523 LeaveCriticalSection( &reader->cs );
3524 return S_OK;
3527 static HRESULT str_to_bool( const unsigned char *str, ULONG len, BOOL *ret )
3529 if (len == 4 && !memcmp( str, "true", 4 )) *ret = TRUE;
3530 else if (len == 1 && !memcmp( str, "1", 1 )) *ret = TRUE;
3531 else if (len == 5 && !memcmp( str, "false", 5 )) *ret = FALSE;
3532 else if (len == 1 && !memcmp( str, "0", 1 )) *ret = FALSE;
3533 else return WS_E_INVALID_FORMAT;
3534 return S_OK;
3537 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
3539 BOOL negative = FALSE;
3540 const unsigned char *ptr = str;
3542 *ret = 0;
3543 while (len && read_isspace( *ptr )) { ptr++; len--; }
3544 while (len && read_isspace( ptr[len - 1] )) { len--; }
3545 if (!len) return WS_E_INVALID_FORMAT;
3547 if (*ptr == '-')
3549 negative = TRUE;
3550 ptr++;
3551 len--;
3553 if (!len) return WS_E_INVALID_FORMAT;
3555 while (len--)
3557 int val;
3559 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3560 val = *ptr - '0';
3561 if (negative) val = -val;
3563 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
3564 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
3566 return WS_E_NUMERIC_OVERFLOW;
3568 *ret = *ret * 10 + val;
3569 ptr++;
3572 return S_OK;
3575 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
3577 const unsigned char *ptr = str;
3579 *ret = 0;
3580 while (len && read_isspace( *ptr )) { ptr++; len--; }
3581 while (len && read_isspace( ptr[len - 1] )) { len--; }
3582 if (!len) return WS_E_INVALID_FORMAT;
3584 while (len--)
3586 unsigned int val;
3588 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3589 val = *ptr - '0';
3591 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
3592 *ret = *ret * 10 + val;
3593 ptr++;
3596 return S_OK;
3599 BOOL set_fpword( unsigned short new, unsigned short *old )
3601 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3602 unsigned short fpword;
3604 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
3605 *old = fpword;
3606 fpword = new;
3607 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3608 return TRUE;
3609 #else
3610 FIXME( "not implemented\n" );
3611 return FALSE;
3612 #endif
3615 void restore_fpword( unsigned short fpword )
3617 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3618 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3619 #else
3620 FIXME( "not implemented\n" );
3621 #endif
3624 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
3626 static const unsigned __int64 nan = 0xfff8000000000000;
3627 static const unsigned __int64 inf = 0x7ff0000000000000;
3628 static const unsigned __int64 inf_min = 0xfff0000000000000;
3629 HRESULT hr = WS_E_INVALID_FORMAT;
3630 const unsigned char *p = str, *q;
3631 int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
3632 unsigned __int64 val = 0, tmp;
3633 long double exp_val = 1.0, exp_mul = 10.0;
3634 unsigned short fpword;
3636 while (len && read_isspace( *p )) { p++; len--; }
3637 while (len && read_isspace( p[len - 1] )) { len--; }
3638 if (!len) return WS_E_INVALID_FORMAT;
3640 if (len == 3 && !memcmp( p, "NaN", 3 ))
3642 *(unsigned __int64 *)ret = nan;
3643 return S_OK;
3645 if (len == 3 && !memcmp( p, "INF", 3 ))
3647 *(unsigned __int64 *)ret = inf;
3648 return S_OK;
3650 if (len == 4 && !memcmp( p, "-INF", 4 ))
3652 *(unsigned __int64 *)ret = inf_min;
3653 return S_OK;
3656 *ret = 0.0;
3657 if (*p == '-')
3659 sign = -1;
3660 p++; len--;
3662 else if (*p == '+') { p++; len--; };
3663 if (!len) return S_OK;
3665 if (!set_fpword( 0x37f, &fpword )) return E_NOTIMPL;
3667 q = p;
3668 while (len && isdigit( *q )) { q++; len--; }
3669 have_digits = nb_digits = q - p;
3670 for (i = 0; i < nb_digits; i++)
3672 tmp = val * 10 + p[i] - '0';
3673 if (val > MAX_UINT64 / 10 || tmp < val)
3675 for (; i < nb_digits; i++) exp++;
3676 break;
3678 val = tmp;
3681 if (len)
3683 if (*q == '.')
3685 p = ++q; len--;
3686 while (len && isdigit( *q )) { q++; len--; };
3687 have_digits |= nb_digits = q - p;
3688 for (i = 0; i < nb_digits; i++)
3690 tmp = val * 10 + p[i] - '0';
3691 if (val > MAX_UINT64 / 10 || tmp < val) break;
3692 val = tmp;
3693 exp--;
3696 if (len > 1 && tolower(*q) == 'e')
3698 if (!have_digits) goto done;
3699 p = ++q; len--;
3700 if (*p == '-')
3702 exp_sign = -1;
3703 p++; len--;
3705 else if (*p == '+') { p++; len--; };
3707 q = p;
3708 while (len && isdigit( *q )) { q++; len--; };
3709 nb_digits = q - p;
3710 if (!nb_digits || len) goto done;
3711 for (i = 0; i < nb_digits; i++)
3713 if (exp_tmp > MAX_INT32 / 10 || (exp_tmp = exp_tmp * 10 + p[i] - '0') < 0)
3714 exp_tmp = MAX_INT32;
3716 exp_tmp *= exp_sign;
3718 if (exp < 0 && exp_tmp < 0 && exp + exp_tmp >= 0) exp = MIN_INT32;
3719 else if (exp > 0 && exp_tmp > 0 && exp + exp_tmp < 0) exp = MAX_INT32;
3720 else exp += exp_tmp;
3723 if (!have_digits || len) goto done;
3725 if ((neg_exp = exp < 0)) exp = -exp;
3726 for (; exp; exp >>= 1)
3728 if (exp & 1) exp_val *= exp_mul;
3729 exp_mul *= exp_mul;
3732 *ret = sign * (neg_exp ? val / exp_val : val * exp_val);
3733 hr = S_OK;
3735 done:
3736 restore_fpword( fpword );
3737 return hr;
3740 static HRESULT str_to_float( const unsigned char *str, ULONG len, float *ret )
3742 static const unsigned int inf = 0x7f800000;
3743 static const unsigned int inf_min = 0xff800000;
3744 const unsigned char *p = str;
3745 double val;
3746 HRESULT hr;
3748 while (len && read_isspace( *p )) { p++; len--; }
3749 while (len && read_isspace( p[len - 1] )) { len--; }
3750 if (!len) return WS_E_INVALID_FORMAT;
3752 if (len == 3 && !memcmp( p, "INF", 3 ))
3754 *(unsigned int *)ret = inf;
3755 return S_OK;
3757 if (len == 4 && !memcmp( p, "-INF", 4 ))
3759 *(unsigned int *)ret = inf_min;
3760 return S_OK;
3763 if ((hr = str_to_double( p, len, &val )) != S_OK) return hr;
3764 *ret = val;
3765 return S_OK;
3768 static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
3770 static const unsigned char hex[] =
3772 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3773 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3774 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3775 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3776 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3777 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3778 0,10,11,12,13,14,15 /* 0x60 */
3780 const unsigned char *p = str;
3781 ULONG i;
3783 while (len && read_isspace( *p )) { p++; len--; }
3784 while (len && read_isspace( p[len - 1] )) { len--; }
3785 if (len != 36) return WS_E_INVALID_FORMAT;
3787 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
3788 return WS_E_INVALID_FORMAT;
3790 for (i = 0; i < 36; i++)
3792 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
3793 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
3796 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
3797 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
3799 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
3800 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
3802 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
3803 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
3804 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
3805 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
3806 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
3807 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
3808 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
3809 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
3811 return S_OK;
3814 static HRESULT str_to_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_STRING *ret )
3816 int len_utf16 = MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, NULL, 0 );
3817 if (!(ret->chars = ws_alloc( heap, len_utf16 * sizeof(WCHAR) ))) return WS_E_QUOTA_EXCEEDED;
3818 MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, ret->chars, len_utf16 );
3819 ret->length = len_utf16;
3820 return S_OK;
3823 static HRESULT str_to_unique_id( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_UNIQUE_ID *ret )
3825 if (len == 45 && !memcmp( str, "urn:uuid:", 9 ))
3827 ret->uri.length = 0;
3828 ret->uri.chars = NULL;
3829 return str_to_guid( str + 9, len - 9, &ret->guid );
3832 memset( &ret->guid, 0, sizeof(ret->guid) );
3833 return str_to_string( str, len, heap, &ret->uri );
3836 static inline unsigned char decode_char( unsigned char c )
3838 if (c >= 'A' && c <= 'Z') return c - 'A';
3839 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
3840 if (c >= '0' && c <= '9') return c - '0' + 52;
3841 if (c == '+') return 62;
3842 if (c == '/') return 63;
3843 return 64;
3846 static ULONG decode_base64( const unsigned char *base64, ULONG len, unsigned char *buf )
3848 ULONG i = 0;
3849 unsigned char c0, c1, c2, c3;
3850 const unsigned char *p = base64;
3852 while (len > 4)
3854 if ((c0 = decode_char( p[0] )) > 63) return 0;
3855 if ((c1 = decode_char( p[1] )) > 63) return 0;
3856 if ((c2 = decode_char( p[2] )) > 63) return 0;
3857 if ((c3 = decode_char( p[3] )) > 63) return 0;
3858 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3859 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3860 buf[i + 2] = (c2 << 6) | c3;
3861 len -= 4;
3862 i += 3;
3863 p += 4;
3865 if (p[2] == '=')
3867 if ((c0 = decode_char( p[0] )) > 63) return 0;
3868 if ((c1 = decode_char( p[1] )) > 63) return 0;
3869 buf[i] = (c0 << 2) | (c1 >> 4);
3870 i++;
3872 else if (p[3] == '=')
3874 if ((c0 = decode_char( p[0] )) > 63) return 0;
3875 if ((c1 = decode_char( p[1] )) > 63) return 0;
3876 if ((c2 = decode_char( p[2] )) > 63) return 0;
3877 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3878 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3879 i += 2;
3881 else
3883 if ((c0 = decode_char( p[0] )) > 63) return 0;
3884 if ((c1 = decode_char( p[1] )) > 63) return 0;
3885 if ((c2 = decode_char( p[2] )) > 63) return 0;
3886 if ((c3 = decode_char( p[3] )) > 63) return 0;
3887 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3888 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3889 buf[i + 2] = (c2 << 6) | c3;
3890 i += 3;
3892 return i;
3895 static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_BYTES *ret )
3897 const unsigned char *p = str;
3899 while (len && read_isspace( *p )) { p++; len--; }
3900 while (len && read_isspace( p[len - 1] )) { len--; }
3902 if (len % 4) return WS_E_INVALID_FORMAT;
3903 if (!(ret->bytes = ws_alloc( heap, len * 3 / 4 ))) return WS_E_QUOTA_EXCEEDED;
3904 ret->length = decode_base64( p, len, ret->bytes );
3905 return S_OK;
3908 static HRESULT str_to_xml_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_XML_STRING *ret )
3910 if (!(ret->bytes = ws_alloc( heap, len ))) return WS_E_QUOTA_EXCEEDED;
3911 memcpy( ret->bytes, str, len );
3912 ret->length = len;
3913 ret->dictionary = NULL;
3914 ret->id = 0;
3915 return S_OK;
3918 static HRESULT copy_xml_string( WS_HEAP *heap, const WS_XML_STRING *src, WS_XML_STRING *dst )
3920 if (!(dst->bytes = ws_alloc( heap, src->length ))) return WS_E_QUOTA_EXCEEDED;
3921 memcpy( dst->bytes, src->bytes, src->length );
3922 dst->length = src->length;
3923 return S_OK;
3926 static HRESULT str_to_qname( struct reader *reader, const unsigned char *str, ULONG len, WS_HEAP *heap,
3927 WS_XML_STRING *prefix_ret, WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
3929 const unsigned char *p = str;
3930 WS_XML_STRING prefix, localname;
3931 const WS_XML_STRING *ns;
3932 HRESULT hr;
3934 while (len && read_isspace( *p )) { p++; len--; }
3935 while (len && read_isspace( p[len - 1] )) { len--; }
3937 if ((hr = split_qname( p, len, &prefix, &localname )) != S_OK) return hr;
3938 if (!(ns = get_namespace( reader, &prefix ))) return WS_E_INVALID_FORMAT;
3940 if (prefix_ret && (hr = copy_xml_string( heap, &prefix, prefix_ret )) != S_OK) return hr;
3941 if ((hr = copy_xml_string( heap, &localname, localname_ret )) != S_OK)
3943 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
3944 return hr;
3946 if ((hr = copy_xml_string( heap, ns, ns_ret )) != S_OK)
3948 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
3949 ws_free( heap, localname_ret->bytes, localname_ret->length );
3950 return hr;
3952 return S_OK;
3955 static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix,
3956 WS_XML_STRING *localname, WS_XML_STRING *ns )
3958 const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
3959 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
3960 return str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap, prefix, localname, ns );
3963 /**************************************************************************
3964 * WsReadQualifiedName [webservices.@]
3966 HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
3967 WS_XML_STRING *localname, WS_XML_STRING *ns,
3968 WS_ERROR *error )
3970 struct reader *reader = (struct reader *)handle;
3971 HRESULT hr;
3973 TRACE( "%p %p %p %p %p %p\n", handle, heap, prefix, localname, ns, error );
3974 if (error) FIXME( "ignoring error parameter\n" );
3976 if (!reader || !heap) return E_INVALIDARG;
3978 EnterCriticalSection( &reader->cs );
3980 if (reader->magic != READER_MAGIC)
3982 LeaveCriticalSection( &reader->cs );
3983 return E_INVALIDARG;
3986 if (!reader->input_type)
3988 LeaveCriticalSection( &reader->cs );
3989 return WS_E_INVALID_OPERATION;
3992 if (!localname)
3994 LeaveCriticalSection( &reader->cs );
3995 return E_INVALIDARG;
3998 if (reader->state != READER_STATE_TEXT)
4000 LeaveCriticalSection( &reader->cs );
4001 return WS_E_INVALID_FORMAT;
4004 hr = read_qualified_name( reader, heap, prefix, localname, ns );
4006 LeaveCriticalSection( &reader->cs );
4007 return hr;
4010 static const int month_offsets[2][12] =
4012 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
4013 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
4016 static inline int valid_day( int year, int month, int day )
4018 return day > 0 && day <= month_days[leap_year( year )][month - 1];
4021 static inline int leap_days_before( int year )
4023 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
4026 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
4028 const unsigned char *p = bytes, *q;
4029 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
4031 while (len && read_isspace( *p )) { p++; len--; }
4032 while (len && read_isspace( p[len - 1] )) { len--; }
4034 q = p;
4035 while (len && isdigit( *q )) { q++; len--; };
4036 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
4037 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
4038 if (year < 1) return WS_E_INVALID_FORMAT;
4040 p = ++q; len--;
4041 while (len && isdigit( *q )) { q++; len--; };
4042 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
4043 month = (p[0] - '0') * 10 + p[1] - '0';
4044 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
4046 p = ++q; len--;
4047 while (len && isdigit( *q )) { q++; len--; };
4048 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
4049 day = (p[0] - '0') * 10 + p[1] - '0';
4050 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
4052 p = ++q; len--;
4053 while (len && isdigit( *q )) { q++; len--; };
4054 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4055 hour = (p[0] - '0') * 10 + p[1] - '0';
4056 if (hour > 24) return WS_E_INVALID_FORMAT;
4058 p = ++q; len--;
4059 while (len && isdigit( *q )) { q++; len--; };
4060 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4061 min = (p[0] - '0') * 10 + p[1] - '0';
4062 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
4064 p = ++q; len--;
4065 while (len && isdigit( *q )) { q++; len--; };
4066 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
4067 sec = (p[0] - '0') * 10 + p[1] - '0';
4068 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
4070 if (*q == '.')
4072 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
4073 p = ++q; len--;
4074 while (len && isdigit( *q )) { q++; len--; };
4075 nb_digits = q - p;
4076 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
4077 for (i = 0; i < nb_digits; i++)
4079 sec_frac += (p[i] - '0') * mul;
4080 mul /= 10;
4083 if (*q == 'Z')
4085 if (--len) return WS_E_INVALID_FORMAT;
4086 tz_hour = tz_min = tz_neg = 0;
4087 ret->format = WS_DATETIME_FORMAT_UTC;
4089 else if (*q == '+' || *q == '-')
4091 tz_neg = (*q == '-') ? 1 : 0;
4093 p = ++q; len--;
4094 while (len && isdigit( *q )) { q++; len--; };
4095 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
4096 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
4097 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
4099 p = ++q; len--;
4100 while (len && isdigit( *q )) { q++; len--; };
4101 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
4102 tz_min = (p[0] - '0') * 10 + p[1] - '0';
4103 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
4105 ret->format = WS_DATETIME_FORMAT_LOCAL;
4107 else return WS_E_INVALID_FORMAT;
4109 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
4110 ret->ticks += month_offsets[leap_year( year )][month - 1] * TICKS_PER_DAY;
4111 ret->ticks += (day - 1) * TICKS_PER_DAY;
4112 ret->ticks += hour * TICKS_PER_HOUR;
4113 ret->ticks += min * TICKS_PER_MIN;
4114 ret->ticks += sec * TICKS_PER_SEC;
4115 ret->ticks += sec_frac;
4117 if (tz_neg)
4119 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
4120 return WS_E_INVALID_FORMAT;
4121 ret->ticks += tz_hour * TICKS_PER_HOUR;
4122 ret->ticks += tz_min * TICKS_PER_MIN;
4124 else
4126 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
4127 return WS_E_INVALID_FORMAT;
4128 ret->ticks -= tz_hour * TICKS_PER_HOUR;
4129 ret->ticks -= tz_min * TICKS_PER_MIN;
4132 return S_OK;
4135 /**************************************************************************
4136 * WsDateTimeToFileTime [webservices.@]
4138 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
4140 unsigned __int64 ticks;
4142 TRACE( "%p %p %p\n", dt, ft, error );
4143 if (error) FIXME( "ignoring error parameter\n" );
4145 if (!dt || !ft) return E_INVALIDARG;
4147 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
4148 ticks = dt->ticks - TICKS_1601_01_01;
4149 ft->dwHighDateTime = ticks >> 32;
4150 ft->dwLowDateTime = (DWORD)ticks;
4151 return S_OK;
4154 /**************************************************************************
4155 * WsFileTimeToDateTime [webservices.@]
4157 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
4159 unsigned __int64 ticks;
4161 TRACE( "%p %p %p\n", ft, dt, error );
4162 if (error) FIXME( "ignoring error parameter\n" );
4164 if (!dt || !ft) return E_INVALIDARG;
4166 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
4167 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
4168 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
4169 dt->ticks = ticks + TICKS_1601_01_01;
4170 dt->format = WS_DATETIME_FORMAT_UTC;
4171 return S_OK;
4174 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
4175 const WS_XML_STRING *ns, ULONG *index )
4177 ULONG i;
4178 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4180 if (!localname)
4182 *index = reader->current_attr;
4183 return TRUE;
4185 for (i = 0; i < elem->attributeCount; i++)
4187 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
4188 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
4190 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
4191 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
4193 *index = i;
4194 return TRUE;
4197 return FALSE;
4200 /**************************************************************************
4201 * WsFindAttribute [webservices.@]
4203 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
4204 const WS_XML_STRING *ns, BOOL required, ULONG *index,
4205 WS_ERROR *error )
4207 struct reader *reader = (struct reader *)handle;
4208 HRESULT hr = S_OK;
4210 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
4211 required, index, error );
4212 if (error) FIXME( "ignoring error parameter\n" );
4214 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
4216 EnterCriticalSection( &reader->cs );
4218 if (reader->magic != READER_MAGIC)
4220 LeaveCriticalSection( &reader->cs );
4221 return E_INVALIDARG;
4224 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
4226 LeaveCriticalSection( &reader->cs );
4227 return WS_E_INVALID_OPERATION;
4230 if (!find_attribute( reader, localname, ns, index ))
4232 if (required) hr = WS_E_INVALID_FORMAT;
4233 else
4235 *index = ~0u;
4236 hr = S_FALSE;
4240 LeaveCriticalSection( &reader->cs );
4241 return hr;
4244 static HRESULT get_node_text( struct reader *reader, const WS_XML_TEXT **ret )
4246 WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
4247 *ret = node->text;
4248 return S_OK;
4251 static HRESULT get_attribute_text( struct reader *reader, ULONG index, const WS_XML_TEXT **ret )
4253 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4254 *ret = elem->attributes[index]->value;
4255 return S_OK;
4258 static BOOL match_element( const struct node *node, const WS_XML_STRING *localname, const WS_XML_STRING *ns )
4260 const WS_XML_ELEMENT_NODE *elem = (const WS_XML_ELEMENT_NODE *)node;
4261 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
4262 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
4263 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
4266 static HRESULT read_next_node( struct reader *reader )
4268 if (reader->current == reader->last) return read_node( reader );
4269 if (move_to_child_node( &reader->current )) return S_OK;
4270 if (move_to_next_node( &reader->current )) return S_OK;
4271 if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
4272 if (move_to_next_node( &reader->current )) return S_OK;
4273 return WS_E_INVALID_FORMAT;
4276 static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
4277 const WS_XML_STRING *ns, const WS_XML_TEXT **ret, BOOL *found )
4279 switch (mapping)
4281 case WS_ATTRIBUTE_TYPE_MAPPING:
4283 ULONG index;
4284 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
4285 return get_attribute_text( reader, index, ret );
4287 case WS_ELEMENT_TYPE_MAPPING:
4288 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
4289 case WS_ANY_ELEMENT_TYPE_MAPPING:
4291 *found = TRUE;
4292 if (localname)
4294 HRESULT hr;
4295 if (!match_element( reader->current, localname, ns ))
4297 *found = FALSE;
4298 return S_OK;
4300 if ((hr = read_next_node( reader )) != S_OK) return hr;
4301 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4303 if (!move_to_parent_element( &reader->current )) return WS_E_INVALID_FORMAT;
4304 *found = FALSE;
4305 return S_OK;
4308 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
4310 *found = FALSE;
4311 return S_OK;
4313 return get_node_text( reader, ret );
4315 default:
4316 FIXME( "mapping %u not supported\n", mapping );
4317 return E_NOTIMPL;
4321 static HRESULT text_to_bool( const WS_XML_TEXT *text, BOOL *val )
4323 HRESULT hr;
4325 switch (text->textType)
4327 case WS_XML_TEXT_TYPE_UTF8:
4329 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4330 hr = str_to_bool( text_utf8->value.bytes, text_utf8->value.length, val );
4331 break;
4333 case WS_XML_TEXT_TYPE_BOOL:
4335 const WS_XML_BOOL_TEXT *text_bool = (const WS_XML_BOOL_TEXT *)text;
4336 *val = text_bool->value;
4337 hr = S_OK;
4338 break;
4340 default:
4341 FIXME( "unhandled text type %u\n", text->textType );
4342 return E_NOTIMPL;
4345 return hr;
4348 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
4349 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4350 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
4351 WS_HEAP *heap, void *ret, ULONG size )
4353 const WS_XML_TEXT *text;
4354 HRESULT hr;
4355 BOOL found, val = FALSE;
4357 if (desc)
4359 FIXME( "description not supported\n" );
4360 return E_NOTIMPL;
4362 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4363 if (found && (hr = text_to_bool( text, &val )) != S_OK) return hr;
4365 switch (option)
4367 case WS_READ_REQUIRED_VALUE:
4368 if (!found) return WS_E_INVALID_FORMAT;
4369 /* fall through */
4371 case WS_READ_NILLABLE_VALUE:
4372 if (size != sizeof(val)) return E_INVALIDARG;
4373 *(BOOL *)ret = val;
4374 break;
4376 case WS_READ_REQUIRED_POINTER:
4377 if (!found) return WS_E_INVALID_FORMAT;
4378 /* fall through */
4380 case WS_READ_OPTIONAL_POINTER:
4381 case WS_READ_NILLABLE_POINTER:
4383 BOOL *heap_val = NULL;
4384 if (size != sizeof(heap_val)) return E_INVALIDARG;
4385 if (found)
4387 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4388 *heap_val = val;
4390 *(BOOL **)ret = heap_val;
4391 break;
4393 default:
4394 FIXME( "read option %u not supported\n", option );
4395 return E_NOTIMPL;
4398 return S_OK;
4401 static HRESULT text_to_int8( const WS_XML_TEXT *text, INT64 *val )
4403 HRESULT hr;
4405 switch (text->textType)
4407 case WS_XML_TEXT_TYPE_UTF8:
4409 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4410 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT8, MAX_INT8, val );
4411 break;
4413 case WS_XML_TEXT_TYPE_INT32:
4415 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4416 assert( text_int32->value >= MIN_INT8 );
4417 assert( text_int32->value <= MAX_INT8 );
4418 *val = text_int32->value;
4419 hr = S_OK;
4420 break;
4422 default:
4423 FIXME( "unhandled text type %u\n", text->textType );
4424 return E_NOTIMPL;
4427 return hr;
4430 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
4431 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4432 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
4433 WS_HEAP *heap, void *ret, ULONG size )
4435 const WS_XML_TEXT *text;
4436 HRESULT hr;
4437 INT64 val = 0;
4438 BOOL found;
4440 if (desc)
4442 FIXME( "description not supported\n" );
4443 return E_NOTIMPL;
4445 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4446 if (found && (hr = text_to_int8( text, &val )) != S_OK) return hr;
4448 switch (option)
4450 case WS_READ_REQUIRED_VALUE:
4451 if (!found) return WS_E_INVALID_FORMAT;
4452 /* fall through */
4454 case WS_READ_NILLABLE_VALUE:
4455 if (size != sizeof(INT8)) return E_INVALIDARG;
4456 *(INT8 *)ret = val;
4457 break;
4459 case WS_READ_REQUIRED_POINTER:
4460 if (!found) return WS_E_INVALID_FORMAT;
4461 /* fall through */
4463 case WS_READ_OPTIONAL_POINTER:
4464 case WS_READ_NILLABLE_POINTER:
4466 INT8 *heap_val = NULL;
4467 if (size != sizeof(heap_val)) return E_INVALIDARG;
4468 if (found)
4470 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4471 *heap_val = val;
4473 *(INT8 **)ret = heap_val;
4474 break;
4476 default:
4477 FIXME( "read option %u not supported\n", option );
4478 return E_NOTIMPL;
4481 return S_OK;
4484 static HRESULT text_to_int16( const WS_XML_TEXT *text, INT64 *val )
4486 HRESULT hr;
4488 switch (text->textType)
4490 case WS_XML_TEXT_TYPE_UTF8:
4492 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4493 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT16, MAX_INT16, val );
4494 break;
4496 case WS_XML_TEXT_TYPE_INT32:
4498 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4499 assert( text_int32->value >= MIN_INT16 );
4500 assert( text_int32->value <= MAX_INT16 );
4501 *val = text_int32->value;
4502 hr = S_OK;
4503 break;
4505 default:
4506 FIXME( "unhandled text type %u\n", text->textType );
4507 return E_NOTIMPL;
4510 return hr;
4513 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
4514 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4515 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
4516 WS_HEAP *heap, void *ret, ULONG size )
4518 const WS_XML_TEXT *text;
4519 HRESULT hr;
4520 INT64 val = 0;
4521 BOOL found;
4523 if (desc)
4525 FIXME( "description not supported\n" );
4526 return E_NOTIMPL;
4528 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4529 if (found && (hr = text_to_int16( text, &val )) != S_OK) return hr;
4531 switch (option)
4533 case WS_READ_REQUIRED_VALUE:
4534 if (!found) return WS_E_INVALID_FORMAT;
4535 /* fall through */
4537 case WS_READ_NILLABLE_VALUE:
4538 if (size != sizeof(INT16)) return E_INVALIDARG;
4539 *(INT16 *)ret = val;
4540 break;
4542 case WS_READ_REQUIRED_POINTER:
4543 if (!found) return WS_E_INVALID_FORMAT;
4544 /* fall through */
4546 case WS_READ_OPTIONAL_POINTER:
4547 case WS_READ_NILLABLE_POINTER:
4549 INT16 *heap_val = NULL;
4550 if (size != sizeof(heap_val)) return E_INVALIDARG;
4551 if (found)
4553 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4554 *heap_val = val;
4556 *(INT16 **)ret = heap_val;
4557 break;
4559 default:
4560 FIXME( "read option %u not supported\n", option );
4561 return E_NOTIMPL;
4564 return S_OK;
4567 static HRESULT text_to_int32( const WS_XML_TEXT *text, INT64 *val )
4569 HRESULT hr;
4571 switch (text->textType)
4573 case WS_XML_TEXT_TYPE_UTF8:
4575 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4576 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT32, MAX_INT32, val );
4577 break;
4579 case WS_XML_TEXT_TYPE_INT32:
4581 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4582 *val = text_int32->value;
4583 hr = S_OK;
4584 break;
4586 default:
4587 FIXME( "unhandled text type %u\n", text->textType );
4588 return E_NOTIMPL;
4591 return hr;
4594 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
4595 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4596 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
4597 WS_HEAP *heap, void *ret, ULONG size )
4599 const WS_XML_TEXT *text;
4600 HRESULT hr;
4601 INT64 val = 0;
4602 BOOL found;
4604 if (desc)
4606 FIXME( "description not supported\n" );
4607 return E_NOTIMPL;
4609 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4610 if (found && (hr = text_to_int32( text, &val )) != S_OK) return hr;
4612 switch (option)
4614 case WS_READ_REQUIRED_VALUE:
4615 if (!found) return WS_E_INVALID_FORMAT;
4616 /* fall through */
4618 case WS_READ_NILLABLE_VALUE:
4619 if (size != sizeof(INT32)) return E_INVALIDARG;
4620 *(INT32 *)ret = val;
4621 break;
4623 case WS_READ_REQUIRED_POINTER:
4624 if (!found) return WS_E_INVALID_FORMAT;
4625 /* fall through */
4627 case WS_READ_OPTIONAL_POINTER:
4628 case WS_READ_NILLABLE_POINTER:
4630 INT32 *heap_val = NULL;
4631 if (size != sizeof(heap_val)) return E_INVALIDARG;
4632 if (found)
4634 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4635 *heap_val = val;
4637 *(INT32 **)ret = heap_val;
4638 break;
4640 default:
4641 FIXME( "read option %u not supported\n", option );
4642 return E_NOTIMPL;
4645 return S_OK;
4648 static HRESULT text_to_int64( const WS_XML_TEXT *text, INT64 *val )
4650 HRESULT hr;
4652 switch (text->textType)
4654 case WS_XML_TEXT_TYPE_UTF8:
4656 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4657 hr = str_to_int64( text_utf8->value.bytes, text_utf8->value.length, MIN_INT64, MAX_INT64, val );
4658 break;
4660 case WS_XML_TEXT_TYPE_INT64:
4662 const WS_XML_INT64_TEXT *text_int64 = (const WS_XML_INT64_TEXT *)text;
4663 *val = text_int64->value;
4664 hr = S_OK;
4665 break;
4667 default:
4668 FIXME( "unhandled text type %u\n", text->textType );
4669 return E_NOTIMPL;
4672 return hr;
4675 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
4676 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4677 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
4678 WS_HEAP *heap, void *ret, ULONG size )
4680 const WS_XML_TEXT *text;
4681 HRESULT hr;
4682 INT64 val = 0;
4683 BOOL found;
4685 if (desc)
4687 FIXME( "description not supported\n" );
4688 return E_NOTIMPL;
4690 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4691 if (found && (hr = text_to_int64( text, &val )) != S_OK) return hr;
4693 switch (option)
4695 case WS_READ_REQUIRED_VALUE:
4696 if (!found) return WS_E_INVALID_FORMAT;
4697 /* fall through */
4699 case WS_READ_NILLABLE_VALUE:
4700 if (size != sizeof(val)) return E_INVALIDARG;
4701 *(INT64 *)ret = val;
4702 break;
4704 case WS_READ_REQUIRED_POINTER:
4705 if (!found) return WS_E_INVALID_FORMAT;
4706 /* fall through */
4708 case WS_READ_OPTIONAL_POINTER:
4709 case WS_READ_NILLABLE_POINTER:
4711 INT64 *heap_val = NULL;
4712 if (size != sizeof(heap_val)) return E_INVALIDARG;
4713 if (found)
4715 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4716 *heap_val = val;
4718 *(INT64 **)ret = heap_val;
4719 break;
4721 default:
4722 FIXME( "read option %u not supported\n", option );
4723 return E_NOTIMPL;
4726 return S_OK;
4729 static HRESULT text_to_uint8( const WS_XML_TEXT *text, UINT64 *val )
4731 HRESULT hr;
4733 switch (text->textType)
4735 case WS_XML_TEXT_TYPE_UTF8:
4737 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4738 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT8, val );
4739 break;
4741 case WS_XML_TEXT_TYPE_UINT64:
4743 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4744 assert( text_uint64->value <= MAX_UINT8 );
4745 *val = text_uint64->value;
4746 hr = S_OK;
4747 break;
4749 default:
4750 FIXME( "unhandled text type %u\n", text->textType );
4751 return E_NOTIMPL;
4754 return hr;
4757 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
4758 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4759 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
4760 WS_HEAP *heap, void *ret, ULONG size )
4762 const WS_XML_TEXT *text;
4763 HRESULT hr;
4764 UINT64 val = 0;
4765 BOOL found;
4767 if (desc)
4769 FIXME( "description not supported\n" );
4770 return E_NOTIMPL;
4772 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4773 if (found && (hr = text_to_uint8( text, &val )) != S_OK) return hr;
4775 switch (option)
4777 case WS_READ_REQUIRED_VALUE:
4778 if (!found) return WS_E_INVALID_FORMAT;
4779 /* fall through */
4781 case WS_READ_NILLABLE_VALUE:
4782 if (size != sizeof(UINT8)) return E_INVALIDARG;
4783 *(UINT8 *)ret = val;
4784 break;
4786 case WS_READ_REQUIRED_POINTER:
4787 if (!found) return WS_E_INVALID_FORMAT;
4788 /* fall through */
4790 case WS_READ_OPTIONAL_POINTER:
4791 case WS_READ_NILLABLE_POINTER:
4793 UINT8 *heap_val = NULL;
4794 if (size != sizeof(heap_val)) return E_INVALIDARG;
4795 if (found)
4797 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4798 *heap_val = val;
4800 *(UINT8 **)ret = heap_val;
4801 break;
4803 default:
4804 FIXME( "read option %u not supported\n", option );
4805 return E_NOTIMPL;
4808 return S_OK;
4811 static HRESULT text_to_uint16( const WS_XML_TEXT *text, UINT64 *val )
4813 HRESULT hr;
4815 switch (text->textType)
4817 case WS_XML_TEXT_TYPE_UTF8:
4819 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4820 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT16, val );
4821 break;
4823 case WS_XML_TEXT_TYPE_INT32:
4825 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4826 assert( text_int32->value >= 0 );
4827 assert( text_int32->value <= MAX_UINT16 );
4828 *val = text_int32->value;
4829 hr = S_OK;
4830 break;
4832 case WS_XML_TEXT_TYPE_UINT64:
4834 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4835 assert( text_uint64->value <= MAX_UINT16 );
4836 *val = text_uint64->value;
4837 hr = S_OK;
4838 break;
4840 default:
4841 FIXME( "unhandled text type %u\n", text->textType );
4842 return E_NOTIMPL;
4845 return hr;
4848 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
4849 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4850 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
4851 WS_HEAP *heap, void *ret, ULONG size )
4853 const WS_XML_TEXT *text;
4854 HRESULT hr;
4855 UINT64 val = 0;
4856 BOOL found;
4858 if (desc)
4860 FIXME( "description not supported\n" );
4861 return E_NOTIMPL;
4863 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4864 if (found && (hr = text_to_uint16( text, &val )) != S_OK) return hr;
4866 switch (option)
4868 case WS_READ_REQUIRED_VALUE:
4869 if (!found) return WS_E_INVALID_FORMAT;
4870 /* fall through */
4872 case WS_READ_NILLABLE_VALUE:
4873 if (size != sizeof(UINT16)) return E_INVALIDARG;
4874 *(UINT16 *)ret = val;
4875 break;
4877 case WS_READ_REQUIRED_POINTER:
4878 if (!found) return WS_E_INVALID_FORMAT;
4879 /* fall through */
4881 case WS_READ_OPTIONAL_POINTER:
4882 case WS_READ_NILLABLE_POINTER:
4884 UINT16 *heap_val = NULL;
4885 if (size != sizeof(heap_val)) return E_INVALIDARG;
4886 if (found)
4888 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4889 *heap_val = val;
4891 *(UINT16 **)ret = heap_val;
4892 break;
4894 default:
4895 FIXME( "read option %u not supported\n", option );
4896 return E_NOTIMPL;
4899 return S_OK;
4902 static HRESULT text_to_uint32( const WS_XML_TEXT *text, UINT64 *val )
4904 HRESULT hr;
4906 switch (text->textType)
4908 case WS_XML_TEXT_TYPE_UTF8:
4910 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
4911 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT32, val );
4912 break;
4914 case WS_XML_TEXT_TYPE_INT32:
4916 const WS_XML_INT32_TEXT *text_int32 = (const WS_XML_INT32_TEXT *)text;
4917 assert( text_int32->value >= 0 );
4918 *val = text_int32->value;
4919 hr = S_OK;
4920 break;
4922 case WS_XML_TEXT_TYPE_UINT64:
4924 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
4925 assert( text_uint64->value <= MAX_UINT32 );
4926 *val = text_uint64->value;
4927 hr = S_OK;
4928 break;
4930 default:
4931 FIXME( "unhandled text type %u\n", text->textType );
4932 return E_NOTIMPL;
4935 return hr;
4938 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
4939 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4940 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
4941 WS_HEAP *heap, void *ret, ULONG size )
4943 const WS_XML_TEXT *text;
4944 HRESULT hr;
4945 UINT64 val = 0;
4946 BOOL found;
4948 if (desc)
4950 FIXME( "description not supported\n" );
4951 return E_NOTIMPL;
4953 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
4954 if (found && (hr = text_to_uint32( text, &val )) != S_OK) return hr;
4956 switch (option)
4958 case WS_READ_REQUIRED_VALUE:
4959 if (!found) return WS_E_INVALID_FORMAT;
4960 /* fall through */
4962 case WS_READ_NILLABLE_VALUE:
4963 if (size != sizeof(UINT32)) return E_INVALIDARG;
4964 *(UINT32 *)ret = val;
4965 break;
4967 case WS_READ_REQUIRED_POINTER:
4968 if (!found) return WS_E_INVALID_FORMAT;
4969 /* fall through */
4971 case WS_READ_OPTIONAL_POINTER:
4972 case WS_READ_NILLABLE_POINTER:
4974 UINT32 *heap_val = NULL;
4975 if (size != sizeof(heap_val)) return E_INVALIDARG;
4976 if (found)
4978 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4979 *heap_val = val;
4981 *(UINT32 **)ret = heap_val;
4982 break;
4984 default:
4985 FIXME( "read option %u not supported\n", option );
4986 return E_NOTIMPL;
4989 return S_OK;
4992 static HRESULT text_to_uint64( const WS_XML_TEXT *text, UINT64 *val )
4994 HRESULT hr;
4996 switch (text->textType)
4998 case WS_XML_TEXT_TYPE_UTF8:
5000 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5001 hr = str_to_uint64( text_utf8->value.bytes, text_utf8->value.length, MAX_UINT64, val );
5002 break;
5004 case WS_XML_TEXT_TYPE_UINT64:
5006 const WS_XML_UINT64_TEXT *text_uint64 = (const WS_XML_UINT64_TEXT *)text;
5007 *val = text_uint64->value;
5008 hr = S_OK;
5009 break;
5011 default:
5012 FIXME( "unhandled text type %u\n", text->textType );
5013 return E_NOTIMPL;
5016 return hr;
5019 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
5020 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5021 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
5022 WS_HEAP *heap, void *ret, ULONG size )
5024 const WS_XML_TEXT *text;
5025 HRESULT hr;
5026 UINT64 val = 0;
5027 BOOL found;
5029 if (desc)
5031 FIXME( "description not supported\n" );
5032 return E_NOTIMPL;
5034 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5035 if (found && (hr = text_to_uint64( text, &val )) != S_OK) return hr;
5037 switch (option)
5039 case WS_READ_REQUIRED_VALUE:
5040 if (!found) return WS_E_INVALID_FORMAT;
5041 /* fall through */
5043 case WS_READ_NILLABLE_VALUE:
5044 if (size != sizeof(val)) return E_INVALIDARG;
5045 *(UINT64 *)ret = val;
5046 break;
5048 case WS_READ_REQUIRED_POINTER:
5049 if (!found) return WS_E_INVALID_FORMAT;
5050 /* fall through */
5052 case WS_READ_OPTIONAL_POINTER:
5053 case WS_READ_NILLABLE_POINTER:
5055 UINT64 *heap_val = NULL;
5056 if (size != sizeof(heap_val)) return E_INVALIDARG;
5057 if (found)
5059 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5060 *heap_val = val;
5062 *(UINT64 **)ret = heap_val;
5063 break;
5065 default:
5066 FIXME( "read option %u not supported\n", option );
5067 return E_NOTIMPL;
5070 return S_OK;
5073 static HRESULT text_to_float( const WS_XML_TEXT *text, float *val )
5075 HRESULT hr;
5077 switch (text->textType)
5079 case WS_XML_TEXT_TYPE_UTF8:
5081 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5082 hr = str_to_float( text_utf8->value.bytes, text_utf8->value.length, val );
5083 break;
5085 case WS_XML_TEXT_TYPE_FLOAT:
5087 const WS_XML_FLOAT_TEXT *text_float = (const WS_XML_FLOAT_TEXT *)text;
5088 *val = text_float->value;
5089 hr = S_OK;
5090 break;
5092 default:
5093 FIXME( "unhandled text type %u\n", text->textType );
5094 return E_NOTIMPL;
5097 return hr;
5100 static HRESULT read_type_float( struct reader *reader, WS_TYPE_MAPPING mapping,
5101 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5102 const WS_FLOAT_DESCRIPTION *desc, WS_READ_OPTION option,
5103 WS_HEAP *heap, void *ret, ULONG size )
5105 const WS_XML_TEXT *text;
5106 HRESULT hr;
5107 float val = 0.0;
5108 BOOL found;
5110 if (desc) FIXME( "ignoring description\n" );
5112 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5113 if (found && (hr = text_to_float( text, &val )) != S_OK) return hr;
5115 switch (option)
5117 case WS_READ_REQUIRED_VALUE:
5118 if (!found) return WS_E_INVALID_FORMAT;
5119 /* fall through */
5121 case WS_READ_NILLABLE_VALUE:
5122 if (size != sizeof(val)) return E_INVALIDARG;
5123 *(float *)ret = val;
5124 break;
5126 case WS_READ_REQUIRED_POINTER:
5127 if (!found) return WS_E_INVALID_FORMAT;
5128 /* fall through */
5130 case WS_READ_OPTIONAL_POINTER:
5131 case WS_READ_NILLABLE_POINTER:
5133 float *heap_val = NULL;
5134 if (size != sizeof(heap_val)) return E_INVALIDARG;
5135 if (found)
5137 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5138 *heap_val = val;
5140 *(float **)ret = heap_val;
5141 break;
5143 default:
5144 FIXME( "read option %u not supported\n", option );
5145 return E_NOTIMPL;
5148 return S_OK;
5151 static HRESULT text_to_double( const WS_XML_TEXT *text, double *val )
5153 HRESULT hr;
5155 switch (text->textType)
5157 case WS_XML_TEXT_TYPE_UTF8:
5159 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5160 hr = str_to_double( text_utf8->value.bytes, text_utf8->value.length, val );
5161 break;
5163 case WS_XML_TEXT_TYPE_DOUBLE:
5165 const WS_XML_DOUBLE_TEXT *text_double = (const WS_XML_DOUBLE_TEXT *)text;
5166 *val = text_double->value;
5167 hr = S_OK;
5168 break;
5170 default:
5171 FIXME( "unhandled text type %u\n", text->textType );
5172 return E_NOTIMPL;
5175 return hr;
5178 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
5179 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5180 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
5181 WS_HEAP *heap, void *ret, ULONG size )
5183 const WS_XML_TEXT *text;
5184 HRESULT hr;
5185 double val = 0.0;
5186 BOOL found;
5188 if (desc) FIXME( "ignoring description\n" );
5190 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5191 if (found && (hr = text_to_double( text, &val )) != S_OK) return hr;
5193 switch (option)
5195 case WS_READ_REQUIRED_VALUE:
5196 if (!found) return WS_E_INVALID_FORMAT;
5197 /* fall through */
5199 case WS_READ_NILLABLE_VALUE:
5200 if (size != sizeof(val)) return E_INVALIDARG;
5201 *(double *)ret = val;
5202 break;
5204 case WS_READ_REQUIRED_POINTER:
5205 if (!found) return WS_E_INVALID_FORMAT;
5206 /* fall through */
5208 case WS_READ_OPTIONAL_POINTER:
5209 case WS_READ_NILLABLE_POINTER:
5211 double *heap_val = NULL;
5212 if (size != sizeof(heap_val)) return E_INVALIDARG;
5213 if (found)
5215 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5216 *heap_val = val;
5218 *(double **)ret = heap_val;
5219 break;
5221 default:
5222 FIXME( "read option %u not supported\n", option );
5223 return E_NOTIMPL;
5226 return S_OK;
5229 static HRESULT text_to_wsz( const WS_XML_TEXT *text, WS_HEAP *heap, WCHAR **ret )
5231 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5232 int len;
5234 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5235 len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
5236 if (!(*ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
5237 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, *ret, len );
5238 (*ret)[len] = 0;
5239 return S_OK;
5242 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
5243 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5244 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
5245 WS_HEAP *heap, WCHAR **ret, ULONG size )
5247 const WS_XML_TEXT *text;
5248 HRESULT hr;
5249 WCHAR *str = NULL;
5250 BOOL found;
5252 if (desc)
5254 FIXME( "description not supported\n" );
5255 return E_NOTIMPL;
5257 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5258 if (found && (hr = text_to_wsz( text, heap, &str )) != S_OK) return hr;
5260 switch (option)
5262 case WS_READ_REQUIRED_POINTER:
5263 if (!str && !(str = ws_alloc_zero( heap, sizeof(*str) ))) return WS_E_QUOTA_EXCEEDED;
5264 /* fall through */
5266 case WS_READ_OPTIONAL_POINTER:
5267 case WS_READ_NILLABLE_POINTER:
5268 if (size != sizeof(str)) return E_INVALIDARG;
5269 *ret = str;
5270 break;
5272 default:
5273 FIXME( "read option %u not supported\n", option );
5274 return E_NOTIMPL;
5277 return S_OK;
5280 static HRESULT get_enum_value( const WS_XML_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
5282 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5283 ULONG i;
5285 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5286 for (i = 0; i < desc->valueCount; i++)
5288 if (WsXmlStringEquals( &utf8->value, desc->values[i].name, NULL ) == S_OK)
5290 *ret = desc->values[i].value;
5291 return S_OK;
5294 return WS_E_INVALID_FORMAT;
5297 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
5298 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5299 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
5300 WS_HEAP *heap, void *ret, ULONG size )
5302 const WS_XML_TEXT *text;
5303 HRESULT hr;
5304 int val = 0;
5305 BOOL found;
5307 if (!desc) return E_INVALIDARG;
5309 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5310 if (found && (hr = get_enum_value( text, desc, &val )) != S_OK) return hr;
5312 switch (option)
5314 case WS_READ_REQUIRED_VALUE:
5315 if (!found) return WS_E_INVALID_FORMAT;
5316 /* fall through */
5318 case WS_READ_NILLABLE_VALUE:
5319 if (size != sizeof(val)) return E_INVALIDARG;
5320 *(int *)ret = val;
5321 break;
5323 case WS_READ_REQUIRED_POINTER:
5324 if (!found) return WS_E_INVALID_FORMAT;
5325 /* fall through */
5327 case WS_READ_OPTIONAL_POINTER:
5328 case WS_READ_NILLABLE_POINTER:
5330 int *heap_val = NULL;
5331 if (size != sizeof(heap_val)) return E_INVALIDARG;
5332 if (found)
5334 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5335 *heap_val = val;
5337 *(int **)ret = heap_val;
5338 break;
5340 default:
5341 FIXME( "read option %u not supported\n", option );
5342 return E_NOTIMPL;
5345 return S_OK;
5348 static HRESULT text_to_datetime( const WS_XML_TEXT *text, WS_DATETIME *val )
5350 HRESULT hr;
5352 switch (text->textType)
5354 case WS_XML_TEXT_TYPE_UTF8:
5356 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5357 hr = str_to_datetime( text_utf8->value.bytes, text_utf8->value.length, val );
5358 break;
5360 case WS_XML_TEXT_TYPE_DATETIME:
5362 const WS_XML_DATETIME_TEXT *text_datetime = (const WS_XML_DATETIME_TEXT *)text;
5363 *val = text_datetime->value;
5364 hr = S_OK;
5365 break;
5367 default:
5368 FIXME( "unhandled text type %u\n", text->textType );
5369 return E_NOTIMPL;
5372 return hr;
5375 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
5376 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5377 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
5378 WS_HEAP *heap, void *ret, ULONG size )
5380 const WS_XML_TEXT *text;
5381 HRESULT hr;
5382 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
5383 BOOL found;
5385 if (desc) FIXME( "ignoring description\n" );
5387 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5388 if (found && (hr = text_to_datetime( text, &val )) != S_OK) return hr;
5390 switch (option)
5392 case WS_READ_REQUIRED_VALUE:
5393 if (!found) return WS_E_INVALID_FORMAT;
5394 /* fall through */
5396 case WS_READ_NILLABLE_VALUE:
5397 if (size != sizeof(val)) return E_INVALIDARG;
5398 *(WS_DATETIME *)ret = val;
5399 break;
5401 case WS_READ_REQUIRED_POINTER:
5402 if (!found) return WS_E_INVALID_FORMAT;
5403 /* fall through */
5405 case WS_READ_OPTIONAL_POINTER:
5406 case WS_READ_NILLABLE_POINTER:
5408 WS_DATETIME *heap_val = NULL;
5409 if (size != sizeof(heap_val)) return E_INVALIDARG;
5410 if (found)
5412 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5413 *heap_val = val;
5415 *(WS_DATETIME **)ret = heap_val;
5416 break;
5418 default:
5419 FIXME( "read option %u not supported\n", option );
5420 return E_NOTIMPL;
5423 return S_OK;
5426 static HRESULT text_to_guid( const WS_XML_TEXT *text, GUID *val )
5428 HRESULT hr;
5430 switch (text->textType)
5432 case WS_XML_TEXT_TYPE_UTF8:
5434 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5435 hr = str_to_guid( text_utf8->value.bytes, text_utf8->value.length, val );
5436 break;
5438 case WS_XML_TEXT_TYPE_GUID:
5440 const WS_XML_GUID_TEXT *text_guid = (const WS_XML_GUID_TEXT *)text;
5441 *val = text_guid->value;
5442 hr = S_OK;
5443 break;
5445 default:
5446 FIXME( "unhandled text type %u\n", text->textType );
5447 return E_NOTIMPL;
5450 return hr;
5453 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
5454 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5455 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
5456 WS_HEAP *heap, void *ret, ULONG size )
5458 const WS_XML_TEXT *text;
5459 GUID val = {0};
5460 HRESULT hr;
5461 BOOL found;
5463 if (desc) FIXME( "ignoring description\n" );
5465 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5466 if (found && (hr = text_to_guid( text, &val )) != S_OK) return hr;
5468 switch (option)
5470 case WS_READ_REQUIRED_VALUE:
5471 if (!found) return WS_E_INVALID_FORMAT;
5472 /* fall through */
5474 case WS_READ_NILLABLE_VALUE:
5475 if (size != sizeof(val)) return E_INVALIDARG;
5476 *(GUID *)ret = val;
5477 break;
5479 case WS_READ_REQUIRED_POINTER:
5480 if (!found) return WS_E_INVALID_FORMAT;
5481 /* fall through */
5483 case WS_READ_OPTIONAL_POINTER:
5484 case WS_READ_NILLABLE_POINTER:
5486 GUID *heap_val = NULL;
5487 if (size != sizeof(heap_val)) return E_INVALIDARG;
5488 if (found)
5490 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5491 *heap_val = val;
5493 *(GUID **)ret = heap_val;
5494 break;
5496 default:
5497 FIXME( "read option %u not supported\n", option );
5498 return E_NOTIMPL;
5501 return S_OK;
5504 static HRESULT text_to_unique_id( const WS_XML_TEXT *text, WS_HEAP *heap, WS_UNIQUE_ID *val )
5506 HRESULT hr;
5508 switch (text->textType)
5510 case WS_XML_TEXT_TYPE_UTF8:
5512 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5513 hr = str_to_unique_id( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5514 break;
5516 case WS_XML_TEXT_TYPE_UNIQUE_ID:
5518 const WS_XML_UNIQUE_ID_TEXT *text_unique_id = (const WS_XML_UNIQUE_ID_TEXT *)text;
5519 val->guid = text_unique_id->value;
5520 val->uri.length = 0;
5521 val->uri.chars = NULL;
5522 hr = S_OK;
5523 break;
5525 default:
5526 FIXME( "unhandled text type %u\n", text->textType );
5527 return E_NOTIMPL;
5530 return hr;
5533 static HRESULT read_type_unique_id( struct reader *reader, WS_TYPE_MAPPING mapping,
5534 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5535 const WS_UNIQUE_ID_DESCRIPTION *desc, WS_READ_OPTION option,
5536 WS_HEAP *heap, void *ret, ULONG size )
5538 const WS_XML_TEXT *text;
5539 WS_UNIQUE_ID val = {{0}};
5540 HRESULT hr;
5541 BOOL found;
5543 if (desc) FIXME( "ignoring description\n" );
5545 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5546 if (found && (hr = text_to_unique_id( text, heap, &val )) != S_OK) return hr;
5548 switch (option)
5550 case WS_READ_REQUIRED_VALUE:
5551 if (!found) return WS_E_INVALID_FORMAT;
5552 /* fall through */
5554 case WS_READ_NILLABLE_VALUE:
5555 if (size != sizeof(val)) return E_INVALIDARG;
5556 *(WS_UNIQUE_ID *)ret = val;
5557 break;
5559 case WS_READ_REQUIRED_POINTER:
5560 if (!found) return WS_E_INVALID_FORMAT;
5561 /* fall through */
5563 case WS_READ_OPTIONAL_POINTER:
5564 case WS_READ_NILLABLE_POINTER:
5566 WS_UNIQUE_ID *heap_val = NULL;
5567 if (size != sizeof(heap_val)) return E_INVALIDARG;
5568 if (found)
5570 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5571 *heap_val = val;
5573 *(WS_UNIQUE_ID **)ret = heap_val;
5574 break;
5576 default:
5577 FIXME( "read option %u not supported\n", option );
5578 return E_NOTIMPL;
5581 return S_OK;
5584 static HRESULT text_to_string( const WS_XML_TEXT *text, WS_HEAP *heap, WS_STRING *val )
5586 HRESULT hr;
5588 switch (text->textType)
5590 case WS_XML_TEXT_TYPE_UTF8:
5592 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5593 hr = str_to_string( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5594 break;
5596 case WS_XML_TEXT_TYPE_UTF16:
5598 const WS_XML_UTF16_TEXT *text_utf16 = (const WS_XML_UTF16_TEXT *)text;
5599 if (!(val->chars = ws_alloc( heap, text_utf16->byteCount ))) return WS_E_QUOTA_EXCEEDED;
5600 memcpy( val->chars, text_utf16->bytes, text_utf16->byteCount );
5601 val->length = text_utf16->byteCount / sizeof(WCHAR);
5602 hr = S_OK;
5603 break;
5605 default:
5606 FIXME( "unhandled text type %u\n", text->textType );
5607 return E_NOTIMPL;
5610 return hr;
5613 static HRESULT read_type_string( struct reader *reader, WS_TYPE_MAPPING mapping,
5614 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5615 const WS_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
5616 WS_HEAP *heap, void *ret, ULONG size )
5618 const WS_XML_TEXT *text;
5619 WS_STRING val = {0};
5620 HRESULT hr;
5621 BOOL found;
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_string( text, heap, &val )) != S_OK) return hr;
5628 switch (option)
5630 case WS_READ_REQUIRED_VALUE:
5631 case WS_READ_NILLABLE_VALUE:
5632 if (size != sizeof(val)) return E_INVALIDARG;
5633 *(WS_STRING *)ret = val;
5634 break;
5636 case WS_READ_REQUIRED_POINTER:
5638 WS_STRING *heap_val;
5639 if (size != sizeof(heap_val)) return E_INVALIDARG;
5640 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5641 *heap_val = val;
5642 *(WS_STRING **)ret = heap_val;
5643 break;
5645 case WS_READ_OPTIONAL_POINTER:
5646 case WS_READ_NILLABLE_POINTER:
5648 WS_STRING *heap_val = NULL;
5649 if (size != sizeof(heap_val)) return E_INVALIDARG;
5650 if (found)
5652 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5653 *heap_val = val;
5655 *(WS_STRING **)ret = heap_val;
5656 break;
5658 default:
5659 FIXME( "read option %u not supported\n", option );
5660 return E_NOTIMPL;
5663 return S_OK;
5666 static HRESULT text_to_bytes( const WS_XML_TEXT *text, WS_HEAP *heap, WS_BYTES *val )
5668 HRESULT hr;
5670 switch (text->textType)
5672 case WS_XML_TEXT_TYPE_UTF8:
5674 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5675 hr = str_to_bytes( text_utf8->value.bytes, text_utf8->value.length, heap, val );
5676 break;
5678 case WS_XML_TEXT_TYPE_BASE64:
5680 const WS_XML_BASE64_TEXT *text_base64 = (const WS_XML_BASE64_TEXT *)text;
5681 if (!(val->bytes = ws_alloc( heap, text_base64->length ))) return WS_E_QUOTA_EXCEEDED;
5682 memcpy( val->bytes, text_base64->bytes, text_base64->length );
5683 val->length = text_base64->length;
5684 hr = S_OK;
5685 break;
5687 default:
5688 FIXME( "unhandled text type %u\n", text->textType );
5689 return E_NOTIMPL;
5692 return hr;
5695 static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
5696 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5697 const WS_BYTES_DESCRIPTION *desc, WS_READ_OPTION option,
5698 WS_HEAP *heap, void *ret, ULONG size )
5700 const WS_XML_TEXT *text;
5701 WS_BYTES val = {0};
5702 HRESULT hr;
5703 BOOL found;
5705 if (desc) FIXME( "ignoring description\n" );
5707 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5708 if (found && (hr = text_to_bytes( text, heap, &val )) != S_OK) return hr;
5710 switch (option)
5712 case WS_READ_REQUIRED_VALUE:
5713 case WS_READ_NILLABLE_VALUE:
5714 if (size != sizeof(val)) return E_INVALIDARG;
5715 *(WS_BYTES *)ret = val;
5716 break;
5718 case WS_READ_REQUIRED_POINTER:
5720 WS_BYTES *heap_val;
5721 if (size != sizeof(heap_val)) return E_INVALIDARG;
5722 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5723 *heap_val = val;
5724 *(WS_BYTES **)ret = heap_val;
5725 break;
5727 case WS_READ_OPTIONAL_POINTER:
5728 case WS_READ_NILLABLE_POINTER:
5730 WS_BYTES *heap_val = NULL;
5731 if (size != sizeof(heap_val)) return E_INVALIDARG;
5732 if (found)
5734 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5735 *heap_val = val;
5737 *(WS_BYTES **)ret = heap_val;
5738 break;
5740 default:
5741 FIXME( "read option %u not supported\n", option );
5742 return E_NOTIMPL;
5745 return S_OK;
5748 static HRESULT text_to_xml_string( const WS_XML_TEXT *text, WS_HEAP *heap, WS_XML_STRING *val )
5750 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
5751 assert( text->textType == WS_XML_TEXT_TYPE_UTF8 );
5752 return str_to_xml_string( utf8->value.bytes, utf8->value.length, heap, val );
5755 static HRESULT read_type_xml_string( struct reader *reader, WS_TYPE_MAPPING mapping,
5756 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5757 const WS_XML_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
5758 WS_HEAP *heap, void *ret, ULONG size )
5760 const WS_XML_TEXT *text;
5761 WS_XML_STRING val = {0};
5762 HRESULT hr;
5763 BOOL found;
5765 if (desc) FIXME( "ignoring description\n" );
5767 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5768 if (found && (hr = text_to_xml_string( text, heap, &val )) != S_OK) return hr;
5770 switch (option)
5772 case WS_READ_REQUIRED_VALUE:
5773 case WS_READ_NILLABLE_VALUE:
5774 if (size != sizeof(val)) return E_INVALIDARG;
5775 *(WS_XML_STRING *)ret = val;
5776 break;
5778 case WS_READ_REQUIRED_POINTER:
5780 WS_XML_STRING *heap_val;
5781 if (size != sizeof(heap_val)) return E_INVALIDARG;
5782 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5783 *heap_val = val;
5784 *(WS_XML_STRING **)ret = heap_val;
5785 break;
5787 case WS_READ_OPTIONAL_POINTER:
5788 case WS_READ_NILLABLE_POINTER:
5790 WS_XML_STRING *heap_val = NULL;
5791 if (size != sizeof(heap_val)) return E_INVALIDARG;
5792 if (found)
5794 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5795 *heap_val = val;
5797 *(WS_XML_STRING **)ret = heap_val;
5798 break;
5800 default:
5801 FIXME( "read option %u not supported\n", option );
5802 return E_NOTIMPL;
5805 return S_OK;
5808 static HRESULT text_to_qname( struct reader *reader, const WS_XML_TEXT *text, WS_HEAP *heap, WS_XML_QNAME *val )
5810 HRESULT hr;
5812 switch (text->textType)
5814 case WS_XML_TEXT_TYPE_UTF8:
5816 const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
5817 hr = str_to_qname( reader, text_utf8->value.bytes, text_utf8->value.length, heap, NULL,
5818 &val->localName, &val->ns );
5819 break;
5821 case WS_XML_TEXT_TYPE_QNAME:
5823 const WS_XML_QNAME_TEXT *text_qname = (const WS_XML_QNAME_TEXT *)text;
5824 if ((hr = copy_xml_string( heap, text_qname->localName, &val->localName )) != S_OK) return hr;
5825 if ((hr = copy_xml_string( heap, text_qname->ns, &val->ns )) != S_OK)
5827 ws_free( heap, val->localName.bytes, val->localName.length );
5828 return hr;
5830 break;
5832 default:
5833 FIXME( "unhandled text type %u\n", text->textType );
5834 return E_NOTIMPL;
5837 return hr;
5840 static HRESULT read_type_qname( struct reader *reader, WS_TYPE_MAPPING mapping,
5841 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5842 const WS_XML_QNAME_DESCRIPTION *desc, WS_READ_OPTION option,
5843 WS_HEAP *heap, void *ret, ULONG size )
5845 const WS_XML_TEXT *text;
5846 WS_XML_QNAME val = {{0}};
5847 HRESULT hr;
5848 BOOL found;
5850 if (desc) FIXME( "ignoring description\n" );
5852 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
5853 if ((hr = read_startelement( reader )) != S_OK) return hr;
5854 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
5856 if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
5857 if (found && (hr = text_to_qname( reader, text, heap, &val )) != S_OK) return hr;
5859 switch (option)
5861 case WS_READ_REQUIRED_VALUE:
5862 if (!found) return WS_E_INVALID_FORMAT;
5863 /* fall through */
5865 case WS_READ_NILLABLE_VALUE:
5866 if (size != sizeof(val)) return E_INVALIDARG;
5867 *(WS_XML_QNAME *)ret = val;
5868 break;
5870 case WS_READ_REQUIRED_POINTER:
5871 if (!found) return WS_E_INVALID_FORMAT;
5872 /* fall through */
5874 case WS_READ_OPTIONAL_POINTER:
5875 case WS_READ_NILLABLE_POINTER:
5877 WS_XML_QNAME *heap_val = NULL;
5878 if (size != sizeof(heap_val)) return E_INVALIDARG;
5879 if (found)
5881 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5882 *heap_val = val;
5884 *(WS_XML_QNAME **)ret = heap_val;
5885 break;
5887 default:
5888 FIXME( "read option %u not supported\n", option );
5889 return E_NOTIMPL;
5892 return S_OK;
5895 static BOOL is_empty_text_node( const struct node *node )
5897 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
5899 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
5900 switch (text->text->textType)
5902 case WS_XML_TEXT_TYPE_UTF8:
5904 ULONG i;
5905 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
5906 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
5907 return TRUE;
5909 case WS_XML_TEXT_TYPE_BASE64:
5911 const WS_XML_BASE64_TEXT *base64 = (const WS_XML_BASE64_TEXT *)text->text;
5912 return !base64->length;
5914 case WS_XML_TEXT_TYPE_BOOL:
5915 case WS_XML_TEXT_TYPE_INT32:
5916 case WS_XML_TEXT_TYPE_INT64:
5917 case WS_XML_TEXT_TYPE_UINT64:
5918 case WS_XML_TEXT_TYPE_FLOAT:
5919 case WS_XML_TEXT_TYPE_DOUBLE:
5920 case WS_XML_TEXT_TYPE_DECIMAL:
5921 case WS_XML_TEXT_TYPE_GUID:
5922 case WS_XML_TEXT_TYPE_UNIQUE_ID:
5923 case WS_XML_TEXT_TYPE_DATETIME:
5924 return FALSE;
5926 default:
5927 ERR( "unhandled text type %u\n", text->text->textType );
5928 return FALSE;
5932 /* skips comment and empty text nodes */
5933 static HRESULT read_type_next_node( struct reader *reader )
5935 for (;;)
5937 HRESULT hr;
5938 WS_XML_NODE_TYPE type;
5940 if ((hr = read_next_node( reader )) != S_OK) return hr;
5941 type = node_type( reader->current );
5942 if (type == WS_XML_NODE_TYPE_COMMENT ||
5943 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
5944 return S_OK;
5948 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
5949 const WS_XML_STRING *ns )
5951 struct node *node;
5952 ULONG attr;
5953 HRESULT hr;
5955 if (!localname) return S_OK; /* assume reader is already correctly positioned */
5956 if (reader->current == reader->last)
5958 BOOL found;
5959 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
5960 if (!found) return WS_E_INVALID_FORMAT;
5962 if (match_element( reader->current, localname, ns )) return S_OK;
5964 node = reader->current;
5965 attr = reader->current_attr;
5967 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
5968 if (match_element( reader->current, localname, ns )) return S_OK;
5970 reader->current = node;
5971 reader->current_attr = attr;
5973 return WS_E_INVALID_FORMAT;
5976 ULONG get_type_size( WS_TYPE type, const void *desc )
5978 switch (type)
5980 case WS_INT8_TYPE:
5981 case WS_UINT8_TYPE:
5982 return sizeof(INT8);
5984 case WS_INT16_TYPE:
5985 case WS_UINT16_TYPE:
5986 return sizeof(INT16);
5988 case WS_BOOL_TYPE:
5989 case WS_INT32_TYPE:
5990 case WS_UINT32_TYPE:
5991 case WS_ENUM_TYPE:
5992 return sizeof(INT32);
5994 case WS_INT64_TYPE:
5995 case WS_UINT64_TYPE:
5996 return sizeof(INT64);
5998 case WS_FLOAT_TYPE:
5999 return sizeof(float);
6001 case WS_DOUBLE_TYPE:
6002 return sizeof(double);
6004 case WS_DATETIME_TYPE:
6005 return sizeof(WS_DATETIME);
6007 case WS_GUID_TYPE:
6008 return sizeof(GUID);
6010 case WS_UNIQUE_ID_TYPE:
6011 return sizeof(WS_UNIQUE_ID);
6013 case WS_STRING_TYPE:
6014 return sizeof(WS_STRING);
6016 case WS_WSZ_TYPE:
6017 return sizeof(WCHAR *);
6019 case WS_BYTES_TYPE:
6020 return sizeof(WS_BYTES);
6022 case WS_XML_STRING_TYPE:
6023 return sizeof(WS_XML_STRING);
6025 case WS_XML_QNAME_TYPE:
6026 return sizeof(WS_XML_QNAME);
6028 case WS_DESCRIPTION_TYPE:
6029 return sizeof(WS_STRUCT_DESCRIPTION *);
6031 case WS_STRUCT_TYPE:
6033 const WS_STRUCT_DESCRIPTION *desc_struct = desc;
6034 return desc_struct->size;
6036 case WS_UNION_TYPE:
6038 const WS_UNION_DESCRIPTION *desc_union = desc;
6039 return desc_union->size;
6041 default:
6042 ERR( "unhandled type %u\n", type );
6043 return 0;
6047 static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
6049 if (options & WS_FIELD_POINTER)
6051 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
6052 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
6053 return WS_READ_REQUIRED_POINTER;
6056 switch (type)
6058 case WS_BOOL_TYPE:
6059 case WS_INT8_TYPE:
6060 case WS_INT16_TYPE:
6061 case WS_INT32_TYPE:
6062 case WS_INT64_TYPE:
6063 case WS_UINT8_TYPE:
6064 case WS_UINT16_TYPE:
6065 case WS_UINT32_TYPE:
6066 case WS_UINT64_TYPE:
6067 case WS_FLOAT_TYPE:
6068 case WS_DOUBLE_TYPE:
6069 case WS_DATETIME_TYPE:
6070 case WS_GUID_TYPE:
6071 case WS_UNIQUE_ID_TYPE:
6072 case WS_STRING_TYPE:
6073 case WS_BYTES_TYPE:
6074 case WS_XML_STRING_TYPE:
6075 case WS_XML_QNAME_TYPE:
6076 case WS_STRUCT_TYPE:
6077 case WS_ENUM_TYPE:
6078 case WS_UNION_TYPE:
6079 if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
6080 return WS_READ_REQUIRED_VALUE;
6082 case WS_WSZ_TYPE:
6083 case WS_DESCRIPTION_TYPE:
6084 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
6085 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
6086 return WS_READ_REQUIRED_POINTER;
6088 default:
6089 FIXME( "unhandled type %u\n", type );
6090 return 0;
6094 static HRESULT read_type_field( struct reader *, const WS_FIELD_DESCRIPTION *, WS_HEAP *, char *, ULONG );
6096 static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_READ_OPTION option,
6097 WS_HEAP *heap, void *ret, ULONG size )
6099 BOOL found = FALSE;
6100 HRESULT hr;
6101 ULONG i;
6103 switch (option)
6105 case WS_READ_REQUIRED_VALUE:
6106 case WS_READ_NILLABLE_VALUE:
6107 if (size != desc->size) return E_INVALIDARG;
6108 break;
6110 default:
6111 return E_INVALIDARG;
6114 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6115 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
6116 for (i = 0; i < desc->fieldCount; i++)
6118 if ((found = match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns )))
6119 break;
6122 if (!found) *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
6123 else
6125 ULONG offset = desc->fields[i]->field.offset;
6126 if ((hr = read_type_field( reader, &desc->fields[i]->field, heap, ret, offset )) == S_OK)
6127 *(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
6130 switch (option)
6132 case WS_READ_NILLABLE_VALUE:
6133 if (!found) move_to_parent_element( &reader->current );
6134 break;
6136 case WS_READ_REQUIRED_VALUE:
6137 if (!found) hr = WS_E_INVALID_FORMAT;
6138 break;
6140 default:
6141 return E_INVALIDARG;
6144 return hr;
6147 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
6148 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
6149 void *, ULONG );
6151 static HRESULT read_type_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
6152 void **ret, ULONG *count )
6154 HRESULT hr;
6155 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
6156 WS_READ_OPTION option;
6157 char *buf;
6159 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
6161 /* wrapper element */
6162 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
6163 return hr;
6165 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
6166 item_size = get_type_size( desc->type, desc->typeDescription );
6167 else
6168 item_size = sizeof(void *);
6170 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
6171 for (;;)
6173 if (nb_items >= nb_allocated)
6175 SIZE_T old_size = nb_allocated * item_size, new_size = old_size * 2;
6176 if (!(buf = ws_realloc_zero( heap, buf, old_size, new_size ))) return WS_E_QUOTA_EXCEEDED;
6177 nb_allocated *= 2;
6180 if (desc->type == WS_UNION_TYPE)
6181 hr = read_type_union( reader, desc->typeDescription, option, heap, buf + offset, item_size );
6182 else
6183 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
6184 desc->typeDescription, option, heap, buf + offset, item_size );
6186 if (hr == WS_E_INVALID_FORMAT) break;
6187 if (hr != S_OK)
6189 ws_free( heap, buf, nb_allocated * item_size );
6190 return hr;
6192 offset += item_size;
6193 nb_items++;
6196 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
6198 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
6200 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
6201 desc->itemRange->maxItemCount );
6202 ws_free( heap, buf, nb_allocated * item_size );
6203 return WS_E_INVALID_FORMAT;
6206 *count = nb_items;
6207 *ret = buf;
6209 return S_OK;
6212 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
6213 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
6215 HRESULT hr;
6216 if (reader->current == reader->last)
6218 BOOL found;
6219 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
6220 if (!found) return WS_E_INVALID_FORMAT;
6222 if ((hr = read_next_node( reader )) != S_OK) return hr;
6223 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
6225 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
6226 desc->typeDescription, option, heap, ret, size );
6229 static HRESULT read_type_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, char *buf,
6230 ULONG offset )
6232 char *ptr;
6233 WS_READ_OPTION option;
6234 ULONG size;
6235 HRESULT hr;
6237 if (!desc) return E_INVALIDARG;
6238 if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE|WS_FIELD_NILLABLE_ITEM))
6240 FIXME( "options %08x not supported\n", desc->options );
6241 return E_NOTIMPL;
6243 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
6245 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
6246 size = get_type_size( desc->type, desc->typeDescription );
6247 else
6248 size = sizeof(void *);
6250 ptr = buf + offset;
6251 switch (desc->mapping)
6253 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING:
6254 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
6255 return S_OK;
6257 case WS_ATTRIBUTE_FIELD_MAPPING:
6258 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
6259 desc->typeDescription, option, heap, ptr, size );
6260 break;
6262 case WS_ELEMENT_FIELD_MAPPING:
6263 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
6264 desc->typeDescription, option, heap, ptr, size );
6265 break;
6267 case WS_ELEMENT_CHOICE_FIELD_MAPPING:
6268 if (desc->type != WS_UNION_TYPE || !desc->typeDescription ||
6269 (desc->options & (WS_FIELD_POINTER|WS_FIELD_NILLABLE))) return E_INVALIDARG;
6270 hr = read_type_union( reader, desc->typeDescription, option, heap, ptr, size );
6271 break;
6273 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
6274 case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING:
6276 ULONG count;
6277 hr = read_type_array( reader, desc, heap, (void **)ptr, &count );
6278 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
6279 break;
6281 case WS_TEXT_FIELD_MAPPING:
6282 hr = read_type_text( reader, desc, option, heap, ptr, size );
6283 break;
6285 default:
6286 FIXME( "unhandled field mapping %u\n", desc->mapping );
6287 return E_NOTIMPL;
6290 if (hr == WS_E_INVALID_FORMAT)
6292 switch (option)
6294 case WS_READ_REQUIRED_VALUE:
6295 case WS_READ_REQUIRED_POINTER:
6296 return WS_E_INVALID_FORMAT;
6298 case WS_READ_NILLABLE_VALUE:
6299 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
6300 return S_OK;
6302 case WS_READ_OPTIONAL_POINTER:
6303 case WS_READ_NILLABLE_POINTER:
6304 *(void **)ptr = NULL;
6305 return S_OK;
6307 default:
6308 ERR( "unhandled option %u\n", option );
6309 return E_NOTIMPL;
6313 return hr;
6316 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
6317 const WS_XML_STRING *ns, const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
6318 WS_HEAP *heap, void *ret, ULONG size )
6320 ULONG i, offset;
6321 HRESULT hr;
6322 char *buf;
6324 if (!desc) return E_INVALIDARG;
6325 if (desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6327 FIXME( "struct options %08x not supported\n",
6328 desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT );
6331 switch (option)
6333 case WS_READ_REQUIRED_POINTER:
6334 case WS_READ_OPTIONAL_POINTER:
6335 case WS_READ_NILLABLE_POINTER:
6336 if (size != sizeof(void *)) return E_INVALIDARG;
6337 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
6338 break;
6340 case WS_READ_REQUIRED_VALUE:
6341 case WS_READ_NILLABLE_VALUE:
6342 if (size != desc->size) return E_INVALIDARG;
6343 buf = ret;
6344 break;
6346 default:
6347 FIXME( "unhandled read option %u\n", option );
6348 return E_NOTIMPL;
6351 for (i = 0; i < desc->fieldCount; i++)
6353 offset = desc->fields[i]->offset;
6354 if ((hr = read_type_field( reader, desc->fields[i], heap, buf, offset )) != S_OK) break;
6357 switch (option)
6359 case WS_READ_REQUIRED_POINTER:
6360 if (hr != S_OK)
6362 ws_free( heap, buf, desc->size );
6363 return hr;
6365 *(char **)ret = buf;
6366 break;
6368 case WS_READ_OPTIONAL_POINTER:
6369 case WS_READ_NILLABLE_POINTER:
6370 if (is_nil_value( buf, desc->size ))
6372 ws_free( heap, buf, desc->size );
6373 buf = NULL;
6375 *(char **)ret = buf;
6376 break;
6378 case WS_READ_REQUIRED_VALUE:
6379 case WS_READ_NILLABLE_VALUE:
6380 if (hr != S_OK) return hr;
6381 break;
6383 default:
6384 ERR( "unhandled read option %u\n", option );
6385 return E_NOTIMPL;
6388 if (desc->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6390 struct node *parent = find_parent( reader );
6391 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
6393 return S_OK;
6396 static HRESULT start_mapping( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
6397 const WS_XML_STRING *ns )
6399 switch (mapping)
6401 case WS_ELEMENT_TYPE_MAPPING:
6402 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
6403 return read_type_next_element_node( reader, localname, ns );
6405 case WS_ANY_ELEMENT_TYPE_MAPPING:
6406 case WS_ATTRIBUTE_TYPE_MAPPING:
6407 return S_OK;
6409 default:
6410 FIXME( "unhandled mapping %u\n", mapping );
6411 return E_NOTIMPL;
6415 static HRESULT read_type_endelement_node( struct reader *reader )
6417 const struct node *parent = find_parent( reader );
6418 HRESULT hr;
6420 for (;;)
6422 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
6423 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == parent)
6425 return S_OK;
6427 if (read_end_of_data( reader ) || !(parent->flags & NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT)) break;
6430 return WS_E_INVALID_FORMAT;
6433 static HRESULT end_mapping( struct reader *reader, WS_TYPE_MAPPING mapping )
6435 switch (mapping)
6437 case WS_ELEMENT_TYPE_MAPPING:
6438 return read_type_endelement_node( reader );
6440 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
6441 return read_type_next_node( reader );
6443 case WS_ATTRIBUTE_TYPE_MAPPING:
6444 default:
6445 return S_OK;
6449 static HRESULT is_nil_element( const WS_XML_ELEMENT_NODE *elem )
6451 static const WS_XML_STRING localname = {3, (BYTE *)"nil"};
6452 static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance"};
6453 ULONG i;
6455 for (i = 0; i < elem->attributeCount; i++)
6457 const WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)elem->attributes[i]->value;
6459 if (elem->attributes[i]->isXmlNs) continue;
6460 if (WsXmlStringEquals( elem->attributes[i]->localName, &localname, NULL ) == S_OK &&
6461 WsXmlStringEquals( elem->attributes[i]->ns, &ns, NULL ) == S_OK &&
6462 text->value.length == 4 && !memcmp( text->value.bytes, "true", 4 )) return TRUE;
6464 return FALSE;
6467 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
6468 const WS_XML_STRING *localname, const WS_XML_STRING *ns, const void *desc,
6469 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size )
6471 HRESULT hr;
6473 if ((hr = start_mapping( reader, mapping, localname, ns )) != S_OK) return hr;
6475 if (mapping == WS_ELEMENT_TYPE_MAPPING && is_nil_element( &reader->current->hdr ))
6477 if (option != WS_READ_NILLABLE_POINTER && option != WS_READ_NILLABLE_VALUE) return WS_E_INVALID_FORMAT;
6478 return end_mapping( reader, mapping );
6481 switch (type)
6483 case WS_BOOL_TYPE:
6484 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6485 return hr;
6486 break;
6488 case WS_INT8_TYPE:
6489 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6490 return hr;
6491 break;
6493 case WS_INT16_TYPE:
6494 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6495 return hr;
6496 break;
6498 case WS_INT32_TYPE:
6499 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6500 return hr;
6501 break;
6503 case WS_INT64_TYPE:
6504 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6505 return hr;
6506 break;
6508 case WS_UINT8_TYPE:
6509 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6510 return hr;
6511 break;
6513 case WS_UINT16_TYPE:
6514 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6515 return hr;
6516 break;
6518 case WS_UINT32_TYPE:
6519 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6520 return hr;
6521 break;
6523 case WS_UINT64_TYPE:
6524 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6525 return hr;
6526 break;
6528 case WS_FLOAT_TYPE:
6529 if ((hr = read_type_float( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6530 return hr;
6531 break;
6533 case WS_DOUBLE_TYPE:
6534 if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6535 return hr;
6536 break;
6538 case WS_DATETIME_TYPE:
6539 if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6540 return hr;
6541 break;
6543 case WS_GUID_TYPE:
6544 if ((hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6545 return hr;
6546 break;
6548 case WS_UNIQUE_ID_TYPE:
6549 if ((hr = read_type_unique_id( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6550 return hr;
6551 break;
6553 case WS_STRING_TYPE:
6554 if ((hr = read_type_string( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6555 return hr;
6556 break;
6558 case WS_WSZ_TYPE:
6559 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6560 return hr;
6561 break;
6563 case WS_BYTES_TYPE:
6564 if ((hr = read_type_bytes( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6565 return hr;
6566 break;
6568 case WS_XML_STRING_TYPE:
6569 if ((hr = read_type_xml_string( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6570 return hr;
6571 break;
6573 case WS_XML_QNAME_TYPE:
6574 if ((hr = read_type_qname( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6575 return hr;
6576 break;
6578 case WS_STRUCT_TYPE:
6579 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6580 return hr;
6581 break;
6583 case WS_ENUM_TYPE:
6584 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
6585 return hr;
6586 break;
6588 default:
6589 FIXME( "type %u not supported\n", type );
6590 return E_NOTIMPL;
6593 return end_mapping( reader, mapping );
6596 /**************************************************************************
6597 * WsReadType [webservices.@]
6599 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
6600 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
6601 ULONG size, WS_ERROR *error )
6603 struct reader *reader = (struct reader *)handle;
6604 HRESULT hr;
6606 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
6607 size, error );
6608 if (error) FIXME( "ignoring error parameter\n" );
6610 if (!reader || !value) return E_INVALIDARG;
6612 EnterCriticalSection( &reader->cs );
6614 if (reader->magic != READER_MAGIC)
6616 LeaveCriticalSection( &reader->cs );
6617 return E_INVALIDARG;
6620 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
6622 LeaveCriticalSection( &reader->cs );
6623 return hr;
6626 switch (mapping)
6628 case WS_ELEMENT_TYPE_MAPPING:
6629 hr = read_node( reader );
6630 break;
6632 default:
6633 break;
6636 if (hr == S_OK && !read_end_of_data( reader )) hr = WS_E_INVALID_FORMAT;
6638 LeaveCriticalSection( &reader->cs );
6639 return hr;
6642 HRESULT read_header( WS_XML_READER *handle, const WS_XML_STRING *localname, const WS_XML_STRING *ns,
6643 WS_TYPE type, const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
6644 ULONG size )
6646 struct reader *reader = (struct reader *)handle;
6647 HRESULT hr;
6649 EnterCriticalSection( &reader->cs );
6651 if (reader->magic != READER_MAGIC)
6653 LeaveCriticalSection( &reader->cs );
6654 return E_INVALIDARG;
6657 hr = read_type( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, localname, ns, desc, option, heap,
6658 value, size );
6660 LeaveCriticalSection( &reader->cs );
6661 return hr;
6664 /**************************************************************************
6665 * WsReadElement [webservices.@]
6667 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
6668 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
6669 WS_ERROR *error )
6671 struct reader *reader = (struct reader *)handle;
6672 HRESULT hr;
6674 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
6675 if (error) FIXME( "ignoring error parameter\n" );
6677 if (!reader || !desc || !value) return E_INVALIDARG;
6679 EnterCriticalSection( &reader->cs );
6681 if (reader->magic != READER_MAGIC)
6683 LeaveCriticalSection( &reader->cs );
6684 return E_INVALIDARG;
6687 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
6688 desc->elementNs, desc->typeDescription, option, heap, value, size );
6690 LeaveCriticalSection( &reader->cs );
6691 return hr;
6694 /**************************************************************************
6695 * WsReadValue [webservices.@]
6697 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
6698 WS_ERROR *error )
6700 struct reader *reader = (struct reader *)handle;
6701 WS_TYPE type = map_value_type( value_type );
6702 HRESULT hr;
6704 TRACE( "%p %u %p %u %p\n", handle, type, value, size, error );
6705 if (error) FIXME( "ignoring error parameter\n" );
6707 if (!reader || !value || type == ~0u) return E_INVALIDARG;
6709 EnterCriticalSection( &reader->cs );
6711 if (reader->magic != READER_MAGIC)
6713 LeaveCriticalSection( &reader->cs );
6714 return E_INVALIDARG;
6717 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
6718 NULL, value, size );
6720 LeaveCriticalSection( &reader->cs );
6721 return hr;
6724 /**************************************************************************
6725 * WsReadAttribute [webservices.@]
6727 HRESULT WINAPI WsReadAttribute( WS_XML_READER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
6728 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
6729 WS_ERROR *error )
6731 struct reader *reader = (struct reader *)handle;
6732 HRESULT hr;
6734 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
6735 if (error) FIXME( "ignoring error parameter\n" );
6737 if (!reader || !desc || !value) return E_INVALIDARG;
6739 EnterCriticalSection( &reader->cs );
6741 if (reader->magic != READER_MAGIC)
6743 LeaveCriticalSection( &reader->cs );
6744 return E_INVALIDARG;
6747 if (!reader->input_type)
6749 LeaveCriticalSection( &reader->cs );
6750 return WS_E_INVALID_OPERATION;
6753 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->attributeLocalName,
6754 desc->attributeNs, desc->typeDescription, option, heap, value, size );
6756 LeaveCriticalSection( &reader->cs );
6757 return hr;
6760 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
6762 static const char bom[] = {0xef,0xbb,0xbf};
6763 const unsigned char *p = data;
6765 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
6766 (size > 2 && !(*offset = 0));
6769 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
6771 static const char bom[] = {0xff,0xfe};
6772 const unsigned char *p = data;
6774 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
6775 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
6778 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
6780 WS_CHARSET ret = 0;
6782 /* FIXME: parse xml declaration */
6784 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
6785 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
6786 else
6788 FIXME( "charset not recognized\n" );
6789 return 0;
6792 TRACE( "detected charset %u\n", ret );
6793 return ret;
6796 static void set_input_buffer( struct reader *reader, struct xmlbuf *buf, const unsigned char *data, ULONG size )
6798 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
6799 reader->input_buf = buf;
6800 reader->input_data = data;
6801 reader->input_size = size;
6803 reader->read_size = reader->input_size;
6804 reader->read_pos = 0;
6805 reader->read_bufptr = reader->input_data;
6807 reader->text_conv_offset = 0;
6810 /**************************************************************************
6811 * WsSetInput [webservices.@]
6813 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
6814 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
6815 ULONG count, WS_ERROR *error )
6817 struct reader *reader = (struct reader *)handle;
6818 struct node *node;
6819 ULONG i, offset = 0;
6820 HRESULT hr;
6822 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
6823 if (error) FIXME( "ignoring error parameter\n" );
6825 if (!reader) return E_INVALIDARG;
6827 EnterCriticalSection( &reader->cs );
6829 if (reader->magic != READER_MAGIC)
6831 LeaveCriticalSection( &reader->cs );
6832 return E_INVALIDARG;
6835 for (i = 0; i < count; i++)
6837 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
6838 properties[i].valueSize );
6839 if (hr != S_OK) goto done;
6842 if ((hr = init_reader( reader )) != S_OK) goto done;
6844 switch (encoding->encodingType)
6846 case WS_XML_READER_ENCODING_TYPE_TEXT:
6848 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
6849 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
6851 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
6853 FIXME( "charset detection on input type %u not supported\n", input->inputType );
6854 hr = E_NOTIMPL;
6855 goto done;
6858 if (text->charSet != WS_CHARSET_AUTO) reader->input_charset = text->charSet;
6859 else reader->input_charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
6861 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
6862 break;
6864 case WS_XML_READER_ENCODING_TYPE_BINARY:
6866 WS_XML_READER_BINARY_ENCODING *bin = (WS_XML_READER_BINARY_ENCODING *)encoding;
6867 reader->input_enc = WS_XML_READER_ENCODING_TYPE_BINARY;
6868 reader->input_charset = 0;
6869 reader->dict_static = bin->staticDictionary ? bin->staticDictionary : &dict_builtin_static.dict;
6870 reader->dict = bin->dynamicDictionary ? bin->dynamicDictionary : &dict_builtin.dict;
6871 break;
6873 default:
6874 FIXME( "encoding type %u not supported\n", encoding->encodingType );
6875 hr = E_NOTIMPL;
6876 goto done;
6879 switch (input->inputType)
6881 case WS_XML_READER_INPUT_TYPE_BUFFER:
6883 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
6884 set_input_buffer( reader, NULL, (const unsigned char *)buf->encodedData + offset,
6885 buf->encodedDataSize - offset );
6886 break;
6888 default:
6889 FIXME( "input type %u not supported\n", input->inputType );
6890 hr = E_NOTIMPL;
6891 goto done;
6894 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
6895 else read_insert_bof( reader, node );
6897 done:
6898 LeaveCriticalSection( &reader->cs );
6899 return hr;
6902 /**************************************************************************
6903 * WsSetInputToBuffer [webservices.@]
6905 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
6906 const WS_XML_READER_PROPERTY *properties, ULONG count,
6907 WS_ERROR *error )
6909 struct reader *reader = (struct reader *)handle;
6910 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
6911 struct node *node;
6912 HRESULT hr;
6913 ULONG i;
6915 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
6916 if (error) FIXME( "ignoring error parameter\n" );
6918 if (!reader || !xmlbuf) return E_INVALIDARG;
6920 EnterCriticalSection( &reader->cs );
6922 if (reader->magic != READER_MAGIC)
6924 LeaveCriticalSection( &reader->cs );
6925 return E_INVALIDARG;
6928 for (i = 0; i < count; i++)
6930 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
6931 properties[i].valueSize );
6932 if (hr != S_OK) goto done;
6935 if ((hr = init_reader( reader )) != S_OK) goto done;
6937 reader->input_enc = xmlbuf->encoding;
6938 reader->input_charset = xmlbuf->charset;
6939 reader->dict_static = xmlbuf->dict_static;
6940 reader->dict = xmlbuf->dict;
6941 set_input_buffer( reader, xmlbuf, xmlbuf->bytes.bytes, xmlbuf->bytes.length );
6943 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
6944 else read_insert_bof( reader, node );
6946 done:
6947 LeaveCriticalSection( &reader->cs );
6948 return hr;
6951 /**************************************************************************
6952 * WsGetReaderPosition [webservices.@]
6954 HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
6956 struct reader *reader = (struct reader *)handle;
6958 TRACE( "%p %p %p\n", handle, pos, error );
6959 if (error) FIXME( "ignoring error parameter\n" );
6961 if (!reader || !pos) return E_INVALIDARG;
6963 EnterCriticalSection( &reader->cs );
6965 if (reader->magic != READER_MAGIC)
6967 LeaveCriticalSection( &reader->cs );
6968 return E_INVALIDARG;
6971 if (!reader->input_buf)
6973 LeaveCriticalSection( &reader->cs );
6974 return WS_E_INVALID_OPERATION;
6977 pos->buffer = (WS_XML_BUFFER *)reader->input_buf;
6978 pos->node = reader->current;
6980 LeaveCriticalSection( &reader->cs );
6981 return S_OK;
6984 /**************************************************************************
6985 * WsSetReaderPosition [webservices.@]
6987 HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
6989 struct reader *reader = (struct reader *)handle;
6991 TRACE( "%p %p %p\n", handle, pos, error );
6992 if (error) FIXME( "ignoring error parameter\n" );
6994 if (!reader || !pos) return E_INVALIDARG;
6996 EnterCriticalSection( &reader->cs );
6998 if (reader->magic != READER_MAGIC || (struct xmlbuf *)pos->buffer != reader->input_buf)
7000 LeaveCriticalSection( &reader->cs );
7001 return E_INVALIDARG;
7004 if (!reader->input_buf)
7006 LeaveCriticalSection( &reader->cs );
7007 return WS_E_INVALID_OPERATION;
7010 reader->current = pos->node;
7012 LeaveCriticalSection( &reader->cs );
7013 return S_OK;
7016 static HRESULT utf8_to_base64( const WS_XML_UTF8_TEXT *utf8, WS_XML_BASE64_TEXT *base64 )
7018 if (utf8->value.length % 4) return WS_E_INVALID_FORMAT;
7019 if (!(base64->bytes = heap_alloc( utf8->value.length * 3 / 4 ))) return E_OUTOFMEMORY;
7020 base64->length = decode_base64( utf8->value.bytes, utf8->value.length, base64->bytes );
7021 return S_OK;
7024 /**************************************************************************
7025 * WsReadBytes [webservices.@]
7027 HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
7029 struct reader *reader = (struct reader *)handle;
7030 HRESULT hr;
7032 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
7033 if (error) FIXME( "ignoring error parameter\n" );
7035 if (!reader) return E_INVALIDARG;
7037 EnterCriticalSection( &reader->cs );
7039 if (reader->magic != READER_MAGIC)
7041 LeaveCriticalSection( &reader->cs );
7042 return E_INVALIDARG;
7045 if (!reader->input_type)
7047 LeaveCriticalSection( &reader->cs );
7048 return WS_E_INVALID_OPERATION;
7051 if (!count)
7053 LeaveCriticalSection( &reader->cs );
7054 return E_INVALIDARG;
7057 *count = 0;
7058 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
7060 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7061 WS_XML_BASE64_TEXT base64;
7063 if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK)
7065 LeaveCriticalSection( &reader->cs );
7066 return hr;
7068 if (reader->text_conv_offset == base64.length)
7070 heap_free( base64.bytes );
7071 hr = read_node( reader );
7072 LeaveCriticalSection( &reader->cs );
7073 return hr;
7075 *count = min( base64.length - reader->text_conv_offset, max_count );
7076 memcpy( bytes, base64.bytes + reader->text_conv_offset, *count );
7077 reader->text_conv_offset += *count;
7078 heap_free( base64.bytes );
7081 LeaveCriticalSection( &reader->cs );
7082 return S_OK;
7085 static HRESULT utf8_to_utf16( const WS_XML_UTF8_TEXT *utf8, WS_XML_UTF16_TEXT *utf16 )
7087 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
7088 if (!(utf16->bytes = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
7089 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, (WCHAR *)utf16->bytes, len );
7090 utf16->byteCount = len * sizeof(WCHAR);
7091 return S_OK;
7094 /**************************************************************************
7095 * WsReadChars [webservices.@]
7097 HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count, ULONG *count, WS_ERROR *error )
7099 struct reader *reader = (struct reader *)handle;
7101 TRACE( "%p %p %u %p %p\n", handle, chars, max_count, count, error );
7102 if (error) FIXME( "ignoring error parameter\n" );
7104 if (!reader) return E_INVALIDARG;
7106 EnterCriticalSection( &reader->cs );
7108 if (reader->magic != READER_MAGIC)
7110 LeaveCriticalSection( &reader->cs );
7111 return E_INVALIDARG;
7114 if (!reader->input_type)
7116 LeaveCriticalSection( &reader->cs );
7117 return WS_E_INVALID_OPERATION;
7120 if (!count)
7122 LeaveCriticalSection( &reader->cs );
7123 return E_INVALIDARG;
7126 *count = 0;
7127 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && chars)
7129 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7130 WS_XML_UTF16_TEXT utf16;
7131 HRESULT hr;
7133 if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK)
7135 LeaveCriticalSection( &reader->cs );
7136 return hr;
7138 if (reader->text_conv_offset == utf16.byteCount / sizeof(WCHAR))
7140 heap_free( utf16.bytes );
7141 hr = read_node( reader );
7142 LeaveCriticalSection( &reader->cs );
7143 return hr;
7145 *count = min( utf16.byteCount / sizeof(WCHAR) - reader->text_conv_offset, max_count );
7146 memcpy( chars, utf16.bytes + reader->text_conv_offset * sizeof(WCHAR), *count * sizeof(WCHAR) );
7147 reader->text_conv_offset += *count;
7148 heap_free( utf16.bytes );
7151 LeaveCriticalSection( &reader->cs );
7152 return S_OK;
7155 /**************************************************************************
7156 * WsReadCharsUtf8 [webservices.@]
7158 HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
7160 struct reader *reader = (struct reader *)handle;
7161 HRESULT hr;
7163 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
7164 if (error) FIXME( "ignoring error parameter\n" );
7166 if (!reader) return E_INVALIDARG;
7168 EnterCriticalSection( &reader->cs );
7170 if (reader->magic != READER_MAGIC)
7172 LeaveCriticalSection( &reader->cs );
7173 return E_INVALIDARG;
7176 if (!reader->input_type)
7178 LeaveCriticalSection( &reader->cs );
7179 return WS_E_INVALID_OPERATION;
7182 if (!count)
7184 LeaveCriticalSection( &reader->cs );
7185 return E_INVALIDARG;
7188 *count = 0;
7189 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
7191 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
7192 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
7194 if (reader->text_conv_offset == utf8->value.length)
7196 hr = read_node( reader );
7197 LeaveCriticalSection( &reader->cs );
7198 return hr;
7200 *count = min( utf8->value.length - reader->text_conv_offset, max_count );
7201 memcpy( bytes, utf8->value.bytes + reader->text_conv_offset, *count );
7202 reader->text_conv_offset += *count;
7205 LeaveCriticalSection( &reader->cs );
7206 return S_OK;
7209 static HRESULT move_to_element( struct reader *reader )
7211 HRESULT hr;
7212 if (node_type( reader->current ) == WS_XML_NODE_TYPE_BOF &&
7213 (hr = read_move_to( reader, WS_MOVE_TO_CHILD_NODE, NULL )) != S_OK) return hr;
7214 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return E_FAIL;
7215 return S_OK;
7218 static HRESULT copy_tree( struct reader *reader, WS_XML_WRITER *writer )
7220 const struct node *node, *parent;
7221 BOOL done = FALSE;
7222 HRESULT hr;
7224 if ((hr = move_to_element( reader )) != S_OK) return hr;
7225 parent = reader->current;
7226 for (;;)
7228 node = reader->current;
7229 if ((hr = WsWriteNode( writer, (const WS_XML_NODE *)node, NULL )) != S_OK) break;
7230 if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT && node->parent == parent) done = TRUE;
7231 if ((hr = read_next_node( reader )) != S_OK || done) break;
7233 return hr;
7236 /**************************************************************************
7237 * WsReadXmlBuffer [webservices.@]
7239 HRESULT WINAPI WsReadXmlBuffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret, WS_ERROR *error )
7241 struct reader *reader = (struct reader *)handle;
7242 WS_XML_WRITER *writer = NULL;
7243 WS_XML_BUFFER *buffer;
7244 HRESULT hr;
7246 TRACE( "%p %p %p %p\n", handle, heap, ret, error );
7247 if (error) FIXME( "ignoring error parameter\n" );
7249 if (!reader || !heap) return E_INVALIDARG;
7250 if (!ret) return E_FAIL;
7252 EnterCriticalSection( &reader->cs );
7254 if (reader->magic != READER_MAGIC)
7256 LeaveCriticalSection( &reader->cs );
7257 return E_INVALIDARG;
7260 if (!reader->input_type)
7262 LeaveCriticalSection( &reader->cs );
7263 return WS_E_INVALID_OPERATION;
7266 if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
7267 if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL )) != S_OK) goto done;
7268 if ((hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL )) != S_OK) goto done;
7269 if ((hr = copy_tree( reader, writer )) == S_OK) *ret = buffer;
7271 done:
7272 if (hr != S_OK) free_xmlbuf( (struct xmlbuf *)buffer );
7273 WsFreeWriter( writer );
7274 LeaveCriticalSection( &reader->cs );
7275 return hr;
7278 HRESULT create_header_buffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret )
7280 struct reader *reader = (struct reader *)handle;
7281 HRESULT hr = WS_E_QUOTA_EXCEEDED;
7282 struct xmlbuf *xmlbuf;
7284 EnterCriticalSection( &reader->cs );
7286 if (reader->magic != READER_MAGIC)
7288 LeaveCriticalSection( &reader->cs );
7289 return E_INVALIDARG;
7292 if ((xmlbuf = alloc_xmlbuf( heap, reader->read_pos, reader->input_enc, reader->input_charset,
7293 reader->dict_static, reader->dict )))
7295 memcpy( xmlbuf->bytes.bytes, reader->read_bufptr, reader->read_pos );
7296 xmlbuf->bytes.length = reader->read_pos;
7297 *ret = (WS_XML_BUFFER *)xmlbuf;
7298 hr = S_OK;
7301 LeaveCriticalSection( &reader->cs );
7302 return hr;
7305 HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *desc, USHORT index, const WS_FIELD_DESCRIPTION **ret )
7307 if (index >= desc->fieldCount) return E_INVALIDARG;
7308 *ret = desc->fields[index];
7309 return S_OK;
7312 static ULONG get_field_size( const WS_FIELD_DESCRIPTION *desc )
7314 if (desc->options & WS_FIELD_POINTER) return sizeof(void *);
7315 return get_type_size( desc->type, desc->typeDescription );
7318 static HRESULT read_param( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, void *ret )
7320 if (!ret && !(ret = ws_alloc_zero( heap, get_field_size(desc) ))) return WS_E_QUOTA_EXCEEDED;
7321 return read_type_field( reader, desc, heap, ret, 0 );
7324 static HRESULT read_param_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
7325 void **ret, ULONG *count )
7327 if (!ret && !(ret = ws_alloc_zero( heap, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED;
7328 return read_type_array( reader, desc, heap, ret, count );
7331 static void set_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, ULONG index, ULONG len,
7332 const void **args )
7334 ULONG i, *ptr;
7335 for (i = 0; i < count; i++)
7337 if (params[i].outputMessageIndex != index || params[i].parameterType != WS_PARAMETER_TYPE_ARRAY_COUNT)
7338 continue;
7339 if ((ptr = *(ULONG **)args[i])) *ptr = len;
7340 break;
7344 HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEMENT_DESCRIPTION *desc,
7345 const WS_PARAMETER_DESCRIPTION *params, ULONG count, const void **args )
7347 struct reader *reader = (struct reader *)handle;
7348 const WS_STRUCT_DESCRIPTION *desc_struct;
7349 const WS_FIELD_DESCRIPTION *desc_field;
7350 ULONG i, len;
7351 HRESULT hr;
7353 if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG;
7355 EnterCriticalSection( &reader->cs );
7357 if (reader->magic != READER_MAGIC)
7359 LeaveCriticalSection( &reader->cs );
7360 return E_INVALIDARG;
7363 if ((hr = start_mapping( reader, WS_ELEMENT_TYPE_MAPPING, desc->elementLocalName, desc->elementNs )) != S_OK)
7364 goto done;
7366 for (i = 0; i < count; i++)
7368 if (params[i].outputMessageIndex == INVALID_PARAMETER_INDEX) continue;
7369 if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES)
7371 FIXME( "messages type not supported\n" );
7372 hr = E_NOTIMPL;
7373 goto done;
7375 if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) goto done;
7376 if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL)
7378 void *ptr = *(void **)args[i];
7379 if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) goto done;
7381 else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY)
7383 void **ptr = *(void ***)args[i];
7384 if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) goto done;
7385 set_array_len( params, count, params[i].outputMessageIndex, len, args );
7389 if (desc_struct->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
7391 struct node *parent = find_parent( reader );
7392 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
7395 hr = end_mapping( reader, WS_ELEMENT_TYPE_MAPPING );
7397 done:
7398 LeaveCriticalSection( &reader->cs );
7399 return hr;