webservices: Implement WsReadXmlBuffer.
[wine.git] / dlls / webservices / reader.c
blob4a427cc47bea4939d546789d24da61b5240d8d4d
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>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winnls.h"
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "webservices_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
32 ULONG prop_size( const struct prop_desc *desc, ULONG count )
34 ULONG i, ret = count * sizeof(struct prop);
35 for (i = 0; i < count; i++) ret += desc[i].size;
36 return ret;
39 void prop_init( const struct prop_desc *desc, ULONG count, struct prop *prop, void *data )
41 ULONG i;
42 char *ptr = data;
43 for (i = 0; i < count; i++)
45 prop[i].value = ptr;
46 prop[i].size = desc[i].size;
47 prop[i].readonly = desc[i].readonly;
48 prop[i].writeonly = desc[i].writeonly;
49 ptr += prop[i].size;
53 HRESULT prop_set( const struct prop *prop, ULONG count, ULONG id, const void *value, ULONG size )
55 if (id >= count || size != prop[id].size || prop[id].readonly) return E_INVALIDARG;
56 memcpy( prop[id].value, value, size );
57 return S_OK;
60 HRESULT prop_get( const struct prop *prop, ULONG count, ULONG id, void *buf, ULONG size )
62 if (id >= count || size != prop[id].size || prop[id].writeonly) return E_INVALIDARG;
63 memcpy( buf, prop[id].value, prop[id].size );
64 return S_OK;
67 struct node *alloc_node( WS_XML_NODE_TYPE type )
69 struct node *ret;
71 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
72 ret->hdr.node.nodeType = type;
73 list_init( &ret->entry );
74 list_init( &ret->children );
75 return ret;
78 void free_attribute( WS_XML_ATTRIBUTE *attr )
80 if (!attr) return;
81 free_xml_string( attr->prefix );
82 free_xml_string( attr->localName );
83 free_xml_string( attr->ns );
84 heap_free( attr->value );
85 heap_free( attr );
88 void free_node( struct node *node )
90 if (!node) return;
91 switch (node_type( node ))
93 case WS_XML_NODE_TYPE_ELEMENT:
95 WS_XML_ELEMENT_NODE *elem = &node->hdr;
96 ULONG i;
98 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
99 heap_free( elem->attributes );
100 free_xml_string( elem->prefix );
101 free_xml_string( elem->localName );
102 free_xml_string( elem->ns );
103 break;
105 case WS_XML_NODE_TYPE_TEXT:
107 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
108 heap_free( text->text );
109 break;
111 case WS_XML_NODE_TYPE_COMMENT:
113 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
114 heap_free( comment->value.bytes );
115 break;
117 case WS_XML_NODE_TYPE_CDATA:
118 case WS_XML_NODE_TYPE_END_CDATA:
119 case WS_XML_NODE_TYPE_END_ELEMENT:
120 case WS_XML_NODE_TYPE_EOF:
121 case WS_XML_NODE_TYPE_BOF:
122 break;
124 default:
125 ERR( "unhandled type %u\n", node_type( node ) );
126 break;
128 heap_free( node );
131 void destroy_nodes( struct node *node )
133 struct list *ptr;
135 if (!node) return;
136 while ((ptr = list_head( &node->children )))
138 struct node *child = LIST_ENTRY( ptr, struct node, entry );
139 list_remove( &child->entry );
140 destroy_nodes( child );
142 free_node( node );
145 static WS_XML_ATTRIBUTE *dup_attribute( const WS_XML_ATTRIBUTE *src )
147 WS_XML_ATTRIBUTE *dst;
148 const WS_XML_STRING *prefix = src->prefix;
149 const WS_XML_STRING *localname = src->localName;
150 const WS_XML_STRING *ns = src->localName;
151 const WS_XML_TEXT *text = src->value;
153 if (!(dst = heap_alloc( sizeof(*dst) ))) return NULL;
154 dst->singleQuote = src->singleQuote;
155 dst->isXmlNs = src->isXmlNs;
157 if (!prefix) dst->prefix = NULL;
158 else if (!(dst->prefix = dup_xml_string( prefix ))) goto error;
159 if (!(dst->localName = dup_xml_string( localname ))) goto error;
160 if (!(dst->ns = dup_xml_string( ns ))) goto error;
162 if (text)
164 WS_XML_UTF8_TEXT *utf8;
165 const WS_XML_UTF8_TEXT *utf8_src = (const WS_XML_UTF8_TEXT *)text;
166 if (!(utf8 = alloc_utf8_text( utf8_src->value.bytes, utf8_src->value.length ))) goto error;
167 dst->value = &utf8->text;
170 return dst;
172 error:
173 free_attribute( dst );
174 return NULL;
177 static WS_XML_ATTRIBUTE **dup_attributes( WS_XML_ATTRIBUTE * const *src, ULONG count )
179 WS_XML_ATTRIBUTE **dst;
180 ULONG i;
182 if (!(dst = heap_alloc( sizeof(*dst) * count ))) return NULL;
183 for (i = 0; i < count; i++)
185 if (!(dst[i] = dup_attribute( src[i] )))
187 for (; i > 0; i--) free_attribute( dst[i - 1] );
188 heap_free( dst );
189 return NULL;
192 return dst;
195 static struct node *dup_element_node( const WS_XML_ELEMENT_NODE *src )
197 struct node *node;
198 WS_XML_ELEMENT_NODE *dst;
199 ULONG count = src->attributeCount;
200 WS_XML_ATTRIBUTE **attrs = src->attributes;
201 const WS_XML_STRING *prefix = (src->prefix && src->prefix->length) ? src->prefix : NULL;
202 const WS_XML_STRING *localname = src->localName;
203 const WS_XML_STRING *ns = src->ns;
205 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
206 dst = &node->hdr;
208 if (count && !(dst->attributes = dup_attributes( attrs, count ))) goto error;
209 dst->attributeCount = count;
211 if (prefix && !(dst->prefix = dup_xml_string( prefix ))) goto error;
212 if (localname && !(dst->localName = dup_xml_string( localname ))) goto error;
213 if (ns && !(dst->ns = dup_xml_string( ns ))) goto error;
214 return node;
216 error:
217 free_node( node );
218 return NULL;
221 static struct node *dup_text_node( const WS_XML_TEXT_NODE *src )
223 struct node *node;
224 WS_XML_TEXT_NODE *dst;
226 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
227 dst = (WS_XML_TEXT_NODE *)node;
229 if (src->text)
231 WS_XML_UTF8_TEXT *utf8;
232 const WS_XML_UTF8_TEXT *utf8_src = (const WS_XML_UTF8_TEXT *)src->text;
233 if (!(utf8 = alloc_utf8_text( utf8_src->value.bytes, utf8_src->value.length )))
235 free_node( node );
236 return NULL;
238 dst->text = &utf8->text;
240 return node;
243 static struct node *dup_comment_node( const WS_XML_COMMENT_NODE *src )
245 struct node *node;
246 WS_XML_COMMENT_NODE *dst;
248 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return NULL;
249 dst = (WS_XML_COMMENT_NODE *)node;
251 if (src->value.length && !(dst->value.bytes = heap_alloc( src->value.length )))
253 free_node( node );
254 return NULL;
256 memcpy( dst->value.bytes, src->value.bytes, src->value.length );
257 dst->value.length = src->value.length;
258 return node;
261 static struct node *dup_node( const struct node *src )
263 switch (node_type( src ))
265 case WS_XML_NODE_TYPE_ELEMENT:
266 return dup_element_node( &src->hdr );
268 case WS_XML_NODE_TYPE_TEXT:
269 return dup_text_node( (const WS_XML_TEXT_NODE *)src );
271 case WS_XML_NODE_TYPE_COMMENT:
272 return dup_comment_node( (const WS_XML_COMMENT_NODE *)src );
274 case WS_XML_NODE_TYPE_CDATA:
275 case WS_XML_NODE_TYPE_END_CDATA:
276 case WS_XML_NODE_TYPE_END_ELEMENT:
277 case WS_XML_NODE_TYPE_EOF:
278 case WS_XML_NODE_TYPE_BOF:
279 return alloc_node( node_type( src ) );
281 default:
282 ERR( "unhandled type %u\n", node_type( src ) );
283 break;
285 return NULL;
288 static HRESULT dup_tree( struct node **dst, const struct node *src )
290 struct node *parent;
291 const struct node *child;
293 if (!*dst && !(*dst = dup_node( src ))) return E_OUTOFMEMORY;
294 parent = *dst;
296 LIST_FOR_EACH_ENTRY( child, &src->children, struct node, entry )
298 HRESULT hr = E_OUTOFMEMORY;
299 struct node *new_child;
301 if (!(new_child = dup_node( child )) || (hr = dup_tree( &new_child, child )) != S_OK)
303 destroy_nodes( *dst );
304 return hr;
306 new_child->parent = parent;
307 list_add_tail( &parent->children, &new_child->entry );
309 return S_OK;
312 static const struct prop_desc reader_props[] =
314 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
315 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
316 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
317 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
318 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
319 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
320 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
321 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
322 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
323 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
324 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
325 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
326 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
327 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
328 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
331 enum reader_state
333 READER_STATE_INITIAL,
334 READER_STATE_BOF,
335 READER_STATE_STARTELEMENT,
336 READER_STATE_STARTATTRIBUTE,
337 READER_STATE_STARTCDATA,
338 READER_STATE_CDATA,
339 READER_STATE_TEXT,
340 READER_STATE_ENDELEMENT,
341 READER_STATE_ENDCDATA,
342 READER_STATE_COMMENT,
343 READER_STATE_EOF
346 struct prefix
348 WS_XML_STRING *str;
349 WS_XML_STRING *ns;
352 struct reader
354 ULONG magic;
355 CRITICAL_SECTION cs;
356 ULONG read_size;
357 ULONG read_pos;
358 const unsigned char *read_bufptr;
359 enum reader_state state;
360 struct node *root;
361 struct node *current;
362 ULONG current_attr;
363 struct node *last;
364 struct prefix *prefixes;
365 ULONG nb_prefixes;
366 ULONG nb_prefixes_allocated;
367 WS_XML_READER_ENCODING_TYPE input_enc;
368 WS_XML_READER_INPUT_TYPE input_type;
369 struct xmlbuf *input_buf;
370 const unsigned char *input_data;
371 ULONG input_size;
372 ULONG text_conv_offset;
373 const WS_XML_DICTIONARY *dict_static;
374 WS_XML_DICTIONARY *dict;
375 ULONG prop_count;
376 struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])];
379 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
381 static struct reader *alloc_reader(void)
383 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
384 struct reader *ret;
385 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
387 if (!(ret = heap_alloc_zero( size ))) return NULL;
388 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
390 heap_free( ret );
391 return NULL;
393 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
395 ret->magic = READER_MAGIC;
396 InitializeCriticalSection( &ret->cs );
397 ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": reader.cs");
399 prop_init( reader_props, count, ret->prop, &ret[1] );
400 ret->prop_count = count;
401 return ret;
404 static void clear_prefixes( struct prefix *prefixes, ULONG count )
406 ULONG i;
407 for (i = 0; i < count; i++)
409 free_xml_string( prefixes[i].str );
410 prefixes[i].str = NULL;
411 free_xml_string( prefixes[i].ns );
412 prefixes[i].ns = NULL;
416 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
418 if (str)
420 free_xml_string( prefix->str );
421 if (!(prefix->str = dup_xml_string( str ))) return E_OUTOFMEMORY;
423 if (prefix->ns) free_xml_string( prefix->ns );
424 if (!(prefix->ns = dup_xml_string( ns ))) return E_OUTOFMEMORY;
425 return S_OK;
428 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
430 ULONG i;
431 HRESULT hr;
433 for (i = 0; i < reader->nb_prefixes; i++)
435 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
436 return set_prefix( &reader->prefixes[i], NULL, ns );
438 if (i >= reader->nb_prefixes_allocated)
440 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
441 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
442 if (!tmp) return E_OUTOFMEMORY;
443 reader->prefixes = tmp;
444 reader->nb_prefixes_allocated *= 2;
446 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
447 reader->nb_prefixes++;
448 return S_OK;
451 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
453 ULONG i;
454 for (i = 0; i < reader->nb_prefixes; i++)
456 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
457 return reader->prefixes[i].ns;
459 return NULL;
462 static void read_insert_eof( struct reader *reader, struct node *eof )
464 if (!reader->root) reader->root = eof;
465 else
467 eof->parent = reader->root;
468 list_add_tail( &reader->root->children, &eof->entry );
470 reader->current = reader->last = eof;
473 static void read_insert_bof( struct reader *reader, struct node *bof )
475 reader->root->parent = bof;
476 list_add_tail( &bof->children, &reader->root->entry );
477 reader->current = reader->last = reader->root = bof;
480 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
482 node->parent = parent;
483 list_add_before( list_tail( &parent->children ), &node->entry );
484 reader->current = reader->last = node;
487 static void free_reader( struct reader *reader )
489 destroy_nodes( reader->root );
490 clear_prefixes( reader->prefixes, reader->nb_prefixes );
491 heap_free( reader->prefixes );
492 reader->cs.DebugInfo->Spare[0] = 0;
493 DeleteCriticalSection( &reader->cs );
494 heap_free( reader );
497 static HRESULT init_reader( struct reader *reader )
499 static const WS_XML_STRING empty = {0, NULL};
500 struct node *node;
501 HRESULT hr;
503 reader->state = READER_STATE_INITIAL;
504 destroy_nodes( reader->root );
505 reader->root = reader->current = NULL;
506 reader->current_attr = 0;
507 clear_prefixes( reader->prefixes, reader->nb_prefixes );
508 reader->nb_prefixes = 1;
509 if ((hr = bind_prefix( reader, &empty, &empty )) != S_OK) return hr;
511 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
512 read_insert_eof( reader, node );
513 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
514 reader->dict_static = NULL;
515 reader->dict = NULL;
516 return S_OK;
519 /**************************************************************************
520 * WsCreateReader [webservices.@]
522 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
523 WS_XML_READER **handle, WS_ERROR *error )
525 struct reader *reader;
526 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
527 WS_CHARSET charset = WS_CHARSET_UTF8;
528 BOOL read_decl = TRUE;
529 HRESULT hr;
531 TRACE( "%p %u %p %p\n", properties, count, handle, error );
532 if (error) FIXME( "ignoring error parameter\n" );
534 if (!handle) return E_INVALIDARG;
535 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
537 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
538 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
539 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
540 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
541 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
543 for (i = 0; i < count; i++)
545 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
546 properties[i].valueSize );
547 if (hr != S_OK)
549 free_reader( reader );
550 return hr;
554 if ((hr = init_reader( reader )) != S_OK)
556 free_reader( reader );
557 return hr;
560 *handle = (WS_XML_READER *)reader;
561 return S_OK;
564 /**************************************************************************
565 * WsFreeReader [webservices.@]
567 void WINAPI WsFreeReader( WS_XML_READER *handle )
569 struct reader *reader = (struct reader *)handle;
571 TRACE( "%p\n", handle );
573 if (!reader) return;
575 EnterCriticalSection( &reader->cs );
577 if (reader->magic != READER_MAGIC)
579 LeaveCriticalSection( &reader->cs );
580 return;
583 reader->magic = 0;
585 LeaveCriticalSection( &reader->cs );
586 free_reader( reader );
589 /**************************************************************************
590 * WsFillReader [webservices.@]
592 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
593 WS_ERROR *error )
595 struct reader *reader = (struct reader *)handle;
597 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
598 if (error) FIXME( "ignoring error parameter\n" );
600 if (!reader) return E_INVALIDARG;
602 EnterCriticalSection( &reader->cs );
604 if (reader->magic != READER_MAGIC)
606 LeaveCriticalSection( &reader->cs );
607 return E_INVALIDARG;
610 /* FIXME: add support for stream input */
611 reader->read_size = min( min_size, reader->input_size );
612 reader->read_pos = 0;
614 LeaveCriticalSection( &reader->cs );
615 return S_OK;
618 /**************************************************************************
619 * WsGetNamespaceFromPrefix [webservices.@]
621 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
622 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
624 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
625 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
626 static const WS_XML_STRING empty_ns = {0, NULL};
627 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
628 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
629 struct reader *reader = (struct reader *)handle;
630 BOOL found = FALSE;
632 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
633 if (error) FIXME( "ignoring error parameter\n" );
635 if (!reader || !prefix || !ns) return E_INVALIDARG;
637 EnterCriticalSection( &reader->cs );
639 if (reader->magic != READER_MAGIC)
641 LeaveCriticalSection( &reader->cs );
642 return E_INVALIDARG;
645 if (reader->state != READER_STATE_STARTELEMENT)
647 LeaveCriticalSection( &reader->cs );
648 return WS_E_INVALID_OPERATION;
651 if (!prefix->length)
653 *ns = &empty_ns;
654 found = TRUE;
656 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
658 *ns = &xml_ns;
659 found = TRUE;
661 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
663 *ns = &xmlns_ns;
664 found = TRUE;
666 else
668 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
669 ULONG i;
671 for (i = 0; i < elem->attributeCount; i++)
673 if (!elem->attributes[i]->isXmlNs) continue;
674 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
676 *ns = elem->attributes[i]->ns;
677 found = TRUE;
678 break;
683 LeaveCriticalSection( &reader->cs );
685 if (!found)
687 if (required) return WS_E_INVALID_FORMAT;
688 *ns = NULL;
689 return S_FALSE;
692 return S_OK;
695 /**************************************************************************
696 * WsGetReaderNode [webservices.@]
698 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
699 WS_ERROR *error )
701 struct reader *reader = (struct reader *)handle;
703 TRACE( "%p %p %p\n", handle, node, error );
704 if (error) FIXME( "ignoring error parameter\n" );
706 if (!reader || !node) return E_INVALIDARG;
708 EnterCriticalSection( &reader->cs );
710 if (reader->magic != READER_MAGIC)
712 LeaveCriticalSection( &reader->cs );
713 return E_INVALIDARG;
716 *node = &reader->current->hdr.node;
718 LeaveCriticalSection( &reader->cs );
719 return S_OK;
722 /**************************************************************************
723 * WsGetReaderProperty [webservices.@]
725 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
726 void *buf, ULONG size, WS_ERROR *error )
728 struct reader *reader = (struct reader *)handle;
729 HRESULT hr;
731 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
732 if (error) FIXME( "ignoring error parameter\n" );
734 if (!reader) return E_INVALIDARG;
736 EnterCriticalSection( &reader->cs );
738 if (reader->magic != READER_MAGIC)
740 LeaveCriticalSection( &reader->cs );
741 return E_INVALIDARG;
744 if (!reader->input_type)
746 LeaveCriticalSection( &reader->cs );
747 return WS_E_INVALID_OPERATION;
750 if (id == WS_XML_READER_PROPERTY_CHARSET)
752 WS_CHARSET charset;
753 if ((hr = prop_get( reader->prop, reader->prop_count, id, &charset, size )) != S_OK) goto done;
754 if (!charset)
756 hr = WS_E_INVALID_FORMAT;
757 goto done;
759 *(WS_CHARSET *)buf = charset;
760 hr = S_OK;
762 else hr = prop_get( reader->prop, reader->prop_count, id, buf, size );
764 done:
765 LeaveCriticalSection( &reader->cs );
766 return hr;
769 /**************************************************************************
770 * WsGetXmlAttribute [webservices.@]
772 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
773 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
775 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
776 return E_NOTIMPL;
779 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *data, ULONG len )
781 WS_XML_UTF8_TEXT *ret;
783 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
784 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
785 ret->value.length = len;
786 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
787 ret->value.dictionary = NULL;
788 ret->value.id = 0;
789 if (data) memcpy( ret->value.bytes, data, len );
790 return ret;
793 static inline BOOL read_end_of_data( struct reader *reader )
795 return reader->read_pos >= reader->read_size;
798 static inline const unsigned char *read_current_ptr( struct reader *reader )
800 return &reader->read_bufptr[reader->read_pos];
803 static inline HRESULT read_peek( struct reader *reader, unsigned char *byte )
805 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
806 *byte = reader->read_bufptr[reader->read_pos];
807 return S_OK;
810 static inline HRESULT read_byte( struct reader *reader, unsigned char *byte )
812 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
813 *byte = reader->read_bufptr[reader->read_pos++];
814 return S_OK;
817 static inline HRESULT read_bytes( struct reader *reader, unsigned char *bytes, unsigned int len )
819 if (reader->read_pos + len > reader->read_size) return WS_E_INVALID_FORMAT;
820 memcpy( bytes, reader->read_bufptr + reader->read_pos, len );
821 reader->read_pos += len;
822 return S_OK;
825 /* UTF-8 support based on libs/wine/utf8.c */
827 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
828 static const char utf8_length[128] =
830 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
831 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
832 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
833 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
834 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
835 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
836 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
837 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
840 /* first byte mask depending on UTF-8 sequence length */
841 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
843 /* minimum Unicode value depending on UTF-8 sequence length */
844 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
846 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
848 unsigned int len, res;
849 unsigned char ch = reader->read_bufptr[reader->read_pos];
850 const unsigned char *end;
852 if (reader->read_pos >= reader->read_size) return 0;
854 if (ch < 0x80)
856 *skip = 1;
857 return ch;
859 len = utf8_length[ch - 0x80];
860 if (reader->read_pos + len >= reader->read_size) return 0;
861 end = reader->read_bufptr + reader->read_pos + len + 1;
862 res = ch & utf8_mask[len];
864 switch (len)
866 case 3:
867 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
868 res = (res << 6) | ch;
869 case 2:
870 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
871 res = (res << 6) | ch;
872 case 1:
873 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
874 res = (res << 6) | ch;
875 if (res < utf8_minval[len]) break;
876 *skip = len + 1;
877 return res;
880 return 0;
883 static inline void read_skip( struct reader *reader, unsigned int count )
885 if (reader->read_pos + count > reader->read_size) return;
886 reader->read_pos += count;
889 static inline void read_rewind( struct reader *reader, unsigned int count )
891 reader->read_pos -= count;
894 static inline BOOL read_isnamechar( unsigned int ch )
896 /* FIXME: incomplete */
897 return (ch >= 'A' && ch <= 'Z') ||
898 (ch >= 'a' && ch <= 'z') ||
899 (ch >= '0' && ch <= '9') ||
900 ch == '_' || ch == '-' || ch == '.' || ch == ':';
903 static inline BOOL read_isspace( unsigned int ch )
905 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
908 static inline void read_skip_whitespace( struct reader *reader )
910 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
911 reader->read_pos++;
914 static inline int read_cmp( struct reader *reader, const char *str, int len )
916 const unsigned char *ptr = read_current_ptr( reader );
918 if (len < 0) len = strlen( str );
919 if (reader->read_pos + len > reader->read_size) return -1;
920 while (len--)
922 if (*str != *ptr) return *ptr - *str;
923 str++; ptr++;
925 return 0;
928 static HRESULT read_xmldecl( struct reader *reader )
930 if (!reader->read_size) return WS_E_INVALID_FORMAT;
932 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
934 reader->state = READER_STATE_BOF;
935 return S_OK;
937 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
938 read_skip( reader, 6 );
940 /* FIXME: parse attributes */
941 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
942 reader->read_pos++;
944 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
945 read_skip( reader, 2 );
947 reader->state = READER_STATE_BOF;
948 return S_OK;
951 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
953 if (elem->attributeCount)
955 WS_XML_ATTRIBUTE **tmp;
956 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
957 return E_OUTOFMEMORY;
958 elem->attributes = tmp;
960 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
961 elem->attributes[elem->attributeCount++] = attr;
962 return S_OK;
965 static HRESULT split_name( const unsigned char *str, ULONG len, const unsigned char **prefix,
966 ULONG *prefix_len, const unsigned char **localname, ULONG *localname_len )
968 const unsigned char *ptr = str;
970 *prefix = NULL;
971 *prefix_len = 0;
973 *localname = str;
974 *localname_len = len;
976 while (len--)
978 if (*ptr == ':')
980 if (ptr == str) return WS_E_INVALID_FORMAT;
981 *prefix = str;
982 *prefix_len = ptr - str;
983 *localname = ptr + 1;
984 *localname_len = len;
985 break;
987 ptr++;
989 return S_OK;
992 static HRESULT parse_name( const unsigned char *str, ULONG len, WS_XML_STRING **prefix, WS_XML_STRING **localname )
994 const unsigned char *localname_ptr, *prefix_ptr;
995 ULONG localname_len, prefix_len;
996 HRESULT hr;
998 if ((hr = split_name( str, len, &prefix_ptr, &prefix_len, &localname_ptr, &localname_len )) != S_OK) return hr;
999 if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
1000 if (!(*localname = alloc_xml_string( localname_ptr, localname_len )))
1002 free_xml_string( *prefix );
1003 *prefix = NULL;
1004 return E_OUTOFMEMORY;
1006 return S_OK;
1009 static int codepoint_to_utf8( int cp, unsigned char *dst )
1011 if (!cp) return -1;
1012 if (cp < 0x80)
1014 *dst = cp;
1015 return 1;
1017 if (cp < 0x800)
1019 dst[1] = 0x80 | (cp & 0x3f);
1020 cp >>= 6;
1021 dst[0] = 0xc0 | cp;
1022 return 2;
1024 if ((cp >= 0xd800 && cp <= 0xdfff) || cp == 0xfffe || cp == 0xffff) return -1;
1025 if (cp < 0x10000)
1027 dst[2] = 0x80 | (cp & 0x3f);
1028 cp >>= 6;
1029 dst[1] = 0x80 | (cp & 0x3f);
1030 cp >>= 6;
1031 dst[0] = 0xe0 | cp;
1032 return 3;
1034 if (cp >= 0x110000) return -1;
1035 dst[3] = 0x80 | (cp & 0x3f);
1036 cp >>= 6;
1037 dst[2] = 0x80 | (cp & 0x3f);
1038 cp >>= 6;
1039 dst[1] = 0x80 | (cp & 0x3f);
1040 cp >>= 6;
1041 dst[0] = 0xf0 | cp;
1042 return 4;
1045 static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char *ret, ULONG *ret_len )
1047 const unsigned char *p = str;
1048 unsigned char *q = ret;
1050 *ret_len = 0;
1051 while (len)
1053 if (*p == '&')
1055 p++; len--;
1056 if (!len) return WS_E_INVALID_FORMAT;
1058 if (len >= 3 && !memcmp( p, "lt;", 3 ))
1060 *q++ = '<';
1061 p += 3;
1062 len -= 3;
1064 else if (len >= 3 && !memcmp( p, "gt;", 3 ))
1066 *q++ = '>';
1067 p += 3;
1068 len -= 3;
1070 else if (len >= 5 && !memcmp( p, "quot;", 5 ))
1072 *q++ = '"';
1073 p += 5;
1074 len -= 5;
1076 else if (len >= 4 && !memcmp( p, "amp;", 4 ))
1078 *q++ = '&';
1079 p += 4;
1080 len -= 4;
1082 else if (len >= 5 && !memcmp( p, "apos;", 5 ))
1084 *q++ = '\'';
1085 p += 5;
1086 len -= 5;
1088 else if (*p == '#')
1090 ULONG start, nb_digits, i;
1091 int len_utf8, cp = 0;
1093 p++; len--;
1094 if (!len) return WS_E_INVALID_FORMAT;
1095 if (*p == 'x')
1097 p++; len--;
1099 start = len;
1100 while (len && isxdigit( *p )) { p++; len--; };
1101 if (!len) return WS_E_INVALID_FORMAT;
1103 p -= nb_digits = start - len;
1104 if (!nb_digits || nb_digits > 6 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1105 for (i = 0; i < nb_digits; i++)
1107 cp *= 16;
1108 if (*p >= '0' && *p <= '9') cp += *p - '0';
1109 else if (*p >= 'a' && *p <= 'f') cp += *p - 'a' + 10;
1110 else cp += *p - 'A' + 10;
1111 p++;
1114 else if (isdigit( *p ))
1116 while (len && *p == '0') { p++; len--; };
1117 if (!len) return WS_E_INVALID_FORMAT;
1119 start = len;
1120 while (len && isdigit( *p )) { p++; len--; };
1121 if (!len) return WS_E_INVALID_FORMAT;
1123 p -= nb_digits = start - len;
1124 if (!nb_digits || nb_digits > 7 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1125 for (i = 0; i < nb_digits; i++)
1127 cp *= 10;
1128 cp += *p - '0';
1129 p++;
1132 else return WS_E_INVALID_FORMAT;
1133 p++; len--;
1134 if ((len_utf8 = codepoint_to_utf8( cp, q )) < 0) return WS_E_INVALID_FORMAT;
1135 *ret_len += len_utf8;
1136 q += len_utf8;
1137 continue;
1139 else return WS_E_INVALID_FORMAT;
1141 else
1143 *q++ = *p++;
1144 len--;
1146 *ret_len += 1;
1148 return S_OK;
1151 static HRESULT read_attribute_value_text( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1153 WS_XML_UTF8_TEXT *utf8 = NULL;
1154 unsigned int len, ch, skip, quote;
1155 const unsigned char *start;
1156 HRESULT hr = E_OUTOFMEMORY;
1158 read_skip_whitespace( reader );
1159 if (read_cmp( reader, "=", 1 )) return WS_E_INVALID_FORMAT;
1160 read_skip( reader, 1 );
1162 read_skip_whitespace( reader );
1163 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) return WS_E_INVALID_FORMAT;
1164 quote = read_utf8_char( reader, &skip );
1165 read_skip( reader, 1 );
1167 len = 0;
1168 start = read_current_ptr( reader );
1169 for (;;)
1171 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1172 if (ch == quote) break;
1173 read_skip( reader, skip );
1174 len += skip;
1176 read_skip( reader, 1 );
1178 if (attr->isXmlNs)
1180 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1181 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1182 if (!(utf8 = alloc_utf8_text( NULL, 0 )))
1184 hr = E_OUTOFMEMORY;
1185 goto error;
1188 else
1190 if (!(utf8 = alloc_utf8_text( NULL, len ))) goto error;
1191 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK) goto error;
1194 attr->value = &utf8->text;
1195 attr->singleQuote = (quote == '\'');
1196 return S_OK;
1198 error:
1199 heap_free( utf8 );
1200 return hr;
1203 static inline BOOL is_text_type( unsigned char type )
1205 return (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT);
1208 static HRESULT read_int31( struct reader *reader, ULONG *len )
1210 unsigned char byte;
1211 HRESULT hr;
1213 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1214 *len = byte & 0x7f;
1215 if (!(byte & 0x80)) return S_OK;
1217 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1218 *len += (byte & 0x7f) << 7;
1219 if (!(byte & 0x80)) return S_OK;
1221 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1222 *len += (byte & 0x7f) << 14;
1223 if (!(byte & 0x80)) return S_OK;
1225 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1226 *len += (byte & 0x7f) << 21;
1227 if (!(byte & 0x80)) return S_OK;
1229 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1230 *len += (byte & 0x07) << 28;
1231 return S_OK;
1234 static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
1236 ULONG len;
1237 HRESULT hr;
1238 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
1239 if (!(*str = alloc_xml_string( NULL, len ))) return E_OUTOFMEMORY;
1240 if ((hr = read_bytes( reader, (*str)->bytes, len )) == S_OK)
1242 if (add_xml_string( *str ) != S_OK) WARN( "string not added to dictionary\n" );
1243 return S_OK;
1245 free_xml_string( *str );
1246 return hr;
1249 static HRESULT read_dict_string( struct reader *reader, WS_XML_STRING **str )
1251 const WS_XML_DICTIONARY *dict;
1252 HRESULT hr;
1253 ULONG id;
1255 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1256 dict = (id & 1) ? reader->dict : reader->dict_static;
1257 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1258 if (!(*str = alloc_xml_string( NULL, 0 ))) return E_OUTOFMEMORY;
1259 *(*str) = dict->strings[id];
1260 return S_OK;
1263 static HRESULT read_datetime( struct reader *reader, WS_DATETIME *ret )
1265 UINT64 val;
1266 HRESULT hr;
1268 if ((hr = read_bytes( reader, (unsigned char *)&val, sizeof(val) )) != S_OK) return hr;
1270 if ((val & 0x03) == 1) ret->format = WS_DATETIME_FORMAT_UTC;
1271 else if ((val & 0x03) == 2) ret->format = WS_DATETIME_FORMAT_LOCAL;
1272 else ret->format = WS_DATETIME_FORMAT_NONE;
1274 if ((ret->ticks = val >> 2) > TICKS_MAX) return WS_E_INVALID_FORMAT;
1275 return S_OK;
1278 static HRESULT read_encode_base64( struct reader *reader, ULONG len, unsigned char *buf, ULONG *ret_len )
1280 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1281 unsigned char byte;
1282 ULONG i = 0, x;
1283 HRESULT hr;
1285 while (len > 0)
1287 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1288 buf[i++] = base64[(byte & 0xfc) >> 2];
1289 x = (byte & 3) << 4;
1290 if (len == 1)
1292 buf[i++] = base64[x];
1293 buf[i++] = '=';
1294 buf[i++] = '=';
1295 break;
1297 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1298 buf[i++] = base64[x | ((byte & 0xf0) >> 4)];
1299 x = (byte & 0x0f) << 2;
1300 if (len == 2)
1302 buf[i++] = base64[x];
1303 buf[i++] = '=';
1304 break;
1306 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1307 buf[i++] = base64[x | ((byte & 0xc0) >> 6)];
1308 buf[i++] = base64[byte & 0x3f];
1309 len -= 3;
1311 *ret_len = i;
1312 return S_OK;
1315 static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1317 static const unsigned char zero[] = {'0'}, one[] = {'1'};
1318 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1319 WS_XML_UTF8_TEXT *utf8 = NULL;
1320 unsigned char type, buf[46];
1321 BOOL val_bool;
1322 INT8 val_int8;
1323 INT16 val_int16;
1324 INT32 val_int32;
1325 INT64 val_int64;
1326 double val_double;
1327 UINT8 val_uint8;
1328 UINT16 val_uint16;
1329 UINT64 val_uint64;
1330 WS_DATETIME datetime;
1331 ULONG len, id;
1332 GUID uuid;
1333 HRESULT hr;
1335 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1336 if (!is_text_type( type )) return WS_E_INVALID_FORMAT;
1338 switch (type)
1340 case RECORD_ZERO_TEXT:
1341 if (!(utf8 = alloc_utf8_text( zero, sizeof(zero) ))) return E_OUTOFMEMORY;
1342 break;
1344 case RECORD_ONE_TEXT:
1345 if (!(utf8 = alloc_utf8_text( one, sizeof(one) ))) return E_OUTOFMEMORY;
1346 break;
1348 case RECORD_FALSE_TEXT:
1349 if (!(utf8 = alloc_utf8_text( false, sizeof(false) ))) return E_OUTOFMEMORY;
1350 break;
1352 case RECORD_TRUE_TEXT:
1353 if (!(utf8 = alloc_utf8_text( true, sizeof(true) ))) return E_OUTOFMEMORY;
1354 break;
1356 case RECORD_INT8_TEXT:
1357 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
1358 len = format_int8( &val_int8, buf );
1359 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1360 break;
1362 case RECORD_INT16_TEXT:
1363 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
1364 len = format_int16( &val_int16, buf );
1365 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1366 break;
1368 case RECORD_INT32_TEXT:
1369 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1370 len = format_int32( &val_int32, buf );
1371 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1372 break;
1374 case RECORD_INT64_TEXT:
1375 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
1376 len = format_int64( &val_int64, buf );
1377 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1378 break;
1380 case RECORD_DOUBLE_TEXT:
1381 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
1382 len = format_double( &val_double, buf );
1383 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1384 break;
1386 case RECORD_DATETIME_TEXT:
1387 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
1388 len = format_datetime( &datetime, buf );
1389 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1390 break;
1392 case RECORD_CHARS8_TEXT:
1393 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1394 len = val_uint8;
1395 break;
1397 case RECORD_CHARS16_TEXT:
1398 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1399 len = val_uint16;
1400 break;
1402 case RECORD_CHARS32_TEXT:
1403 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1404 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1405 len = val_int32;
1406 break;
1408 case RECORD_BYTES8_TEXT:
1409 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1410 if (!(utf8 = alloc_utf8_text( NULL, ((4 * val_uint8 / 3) + 3) & ~3 ))) return E_OUTOFMEMORY;
1411 if ((hr = read_encode_base64( reader, val_uint8, utf8->value.bytes, &utf8->value.length )) != S_OK)
1413 heap_free( utf8 );
1414 return hr;
1416 break;
1418 case RECORD_BYTES16_TEXT:
1419 if ((hr = read_byte( reader, (unsigned char *)&val_uint16 )) != S_OK) return hr;
1420 if (!(utf8 = alloc_utf8_text( NULL, ((4 * val_uint16 / 3) + 3) & ~3 ))) return E_OUTOFMEMORY;
1421 if ((hr = read_encode_base64( reader, val_uint16, utf8->value.bytes, &utf8->value.length )) != S_OK)
1423 heap_free( utf8 );
1424 return hr;
1426 break;
1428 case RECORD_BYTES32_TEXT:
1429 if ((hr = read_byte( reader, (unsigned char *)&val_int32 )) != S_OK) return hr;
1430 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1431 if (!(utf8 = alloc_utf8_text( NULL, ((4 * val_int32 / 3) + 3) & ~3 ))) return E_OUTOFMEMORY;
1432 if ((hr = read_encode_base64( reader, val_int32, utf8->value.bytes, &utf8->value.length )) != S_OK)
1434 heap_free( utf8 );
1435 return hr;
1437 break;
1439 case RECORD_EMPTY_TEXT:
1440 len = 0;
1441 break;
1443 case RECORD_DICTIONARY_TEXT:
1444 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1445 if (!reader->dict || (id >>= 1) >= reader->dict->stringCount) return WS_E_INVALID_FORMAT;
1446 if (!(utf8 = alloc_utf8_text( reader->dict->strings[id].bytes, reader->dict->strings[id].length )))
1447 return E_OUTOFMEMORY;
1448 break;
1450 case RECORD_UNIQUEID_TEXT:
1451 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
1452 len = format_urn( &uuid, buf );
1453 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1454 break;
1456 case RECORD_UUID_TEXT:
1457 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
1458 len = format_guid( &uuid, buf );
1459 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1460 break;
1462 case RECORD_UINT64_TEXT:
1463 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
1464 len = format_uint64( &val_uint64, buf );
1465 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1466 break;
1468 case RECORD_BOOL_TEXT:
1469 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
1470 len = format_bool( &val_bool, buf );
1471 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1472 break;
1474 default:
1475 ERR( "unhandled record type %02x\n", type );
1476 return WS_E_NOT_SUPPORTED;
1479 if (!utf8)
1481 if (!(utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
1482 if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
1483 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
1485 heap_free( utf8 );
1486 return hr;
1490 attr->value = &utf8->text;
1491 return S_OK;
1494 static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1496 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1497 WS_XML_ATTRIBUTE *attr;
1498 unsigned int len = 0, ch, skip;
1499 const unsigned char *start;
1500 WS_XML_STRING *prefix, *localname;
1501 HRESULT hr = WS_E_INVALID_FORMAT;
1503 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1505 start = read_current_ptr( reader );
1506 for (;;)
1508 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1509 if (!read_isnamechar( ch )) break;
1510 read_skip( reader, skip );
1511 len += skip;
1513 if (!len) goto error;
1515 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) goto error;
1516 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1518 free_xml_string( prefix );
1519 attr->isXmlNs = 1;
1520 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1522 free_xml_string( localname );
1523 hr = E_OUTOFMEMORY;
1524 goto error;
1526 attr->localName = localname;
1528 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1530 attr->isXmlNs = 1;
1531 attr->prefix = prefix;
1532 attr->localName = localname;
1534 else
1536 attr->prefix = prefix;
1537 attr->localName = localname;
1540 if ((hr = read_attribute_value_text( reader, attr )) != S_OK) goto error;
1542 *ret = attr;
1543 return S_OK;
1545 error:
1546 free_attribute( attr );
1547 return hr;
1550 static inline BOOL is_attribute_type( unsigned char type )
1552 return (type >= RECORD_SHORT_ATTRIBUTE && type <= RECORD_PREFIX_ATTRIBUTE_Z);
1555 static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1557 WS_XML_ATTRIBUTE *attr;
1558 unsigned char type = 0;
1559 HRESULT hr;
1561 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1562 if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT;
1563 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1565 if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z)
1567 unsigned char ch = type - RECORD_PREFIX_ATTRIBUTE_A + 'a';
1568 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1570 hr = E_OUTOFMEMORY;
1571 goto error;
1573 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1574 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1576 else if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
1578 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A + 'a';
1579 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1581 hr = E_OUTOFMEMORY;
1582 goto error;
1584 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1585 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1587 else
1589 switch (type)
1591 case RECORD_SHORT_ATTRIBUTE:
1592 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1594 hr = E_OUTOFMEMORY;
1595 goto error;
1597 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1598 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1599 break;
1601 case RECORD_ATTRIBUTE:
1602 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1603 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1604 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1605 break;
1607 case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
1608 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1610 hr = E_OUTOFMEMORY;
1611 goto error;
1613 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1614 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1615 break;
1617 case RECORD_DICTIONARY_ATTRIBUTE:
1618 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1619 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1620 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1621 break;
1623 case RECORD_SHORT_XMLNS_ATTRIBUTE:
1624 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1626 hr = E_OUTOFMEMORY;
1627 goto error;
1629 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1630 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1631 attr->isXmlNs = 1;
1632 break;
1634 case RECORD_XMLNS_ATTRIBUTE:
1635 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1636 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1637 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1638 attr->isXmlNs = 1;
1639 break;
1641 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
1642 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1644 hr = E_OUTOFMEMORY;
1645 goto error;
1647 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1648 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1649 attr->isXmlNs = 1;
1650 break;
1652 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
1653 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1654 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1655 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1656 attr->isXmlNs = 1;
1657 break;
1659 default:
1660 ERR( "unhandled record type %02x\n", type );
1661 return WS_E_NOT_SUPPORTED;
1665 *ret = attr;
1666 return S_OK;
1668 error:
1669 free_attribute( attr );
1670 return hr;
1673 static inline struct node *find_parent( struct reader *reader )
1675 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT)
1677 if (is_valid_parent( reader->current->parent->parent )) return reader->current->parent->parent;
1678 return NULL;
1680 if (is_valid_parent( reader->current )) return reader->current;
1681 if (is_valid_parent( reader->current->parent )) return reader->current->parent;
1682 return NULL;
1685 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1687 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1688 const WS_XML_STRING *ns;
1689 ULONG i;
1691 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1692 if (!(elem->ns = dup_xml_string( ns ))) return E_OUTOFMEMORY;
1694 for (i = 0; i < elem->attributeCount; i++)
1696 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1697 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1698 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1699 if (!(attr->ns = alloc_xml_string( NULL, ns->length ))) return E_OUTOFMEMORY;
1700 if (attr->ns->length) memcpy( attr->ns->bytes, ns->bytes, ns->length );
1702 return S_OK;
1705 static WS_XML_ELEMENT_NODE *alloc_element_pair(void)
1707 struct node *node, *end;
1708 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
1709 if (!(end = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT )))
1711 free_node( node );
1712 return NULL;
1714 list_add_tail( &node->children, &end->entry );
1715 end->parent = node;
1716 return &node->hdr;
1719 static HRESULT read_attributes_text( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1721 WS_XML_ATTRIBUTE *attr;
1722 HRESULT hr;
1724 reader->current_attr = 0;
1725 for (;;)
1727 read_skip_whitespace( reader );
1728 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1729 if ((hr = read_attribute_text( reader, &attr )) != S_OK) return hr;
1730 if ((hr = append_attribute( elem, attr )) != S_OK)
1732 free_attribute( attr );
1733 return hr;
1735 reader->current_attr++;
1737 return S_OK;
1740 static HRESULT read_element_text( struct reader *reader )
1742 unsigned int len = 0, ch, skip;
1743 const unsigned char *start;
1744 struct node *node = NULL, *parent;
1745 WS_XML_ELEMENT_NODE *elem;
1746 HRESULT hr = WS_E_INVALID_FORMAT;
1748 if (read_end_of_data( reader ))
1750 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1751 reader->last = reader->current;
1752 reader->state = READER_STATE_EOF;
1753 return S_OK;
1756 if (read_cmp( reader, "<", 1 )) return WS_E_INVALID_FORMAT;
1757 read_skip( reader, 1 );
1758 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1760 read_rewind( reader, 1 );
1761 return WS_E_INVALID_FORMAT;
1764 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1765 node = (struct node *)elem;
1767 start = read_current_ptr( reader );
1768 for (;;)
1770 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1771 if (!read_isnamechar( ch )) break;
1772 read_skip( reader, skip );
1773 len += skip;
1775 if (!len) goto error;
1777 if (!(parent = find_parent( reader ))) goto error;
1778 if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1780 if ((hr = read_attributes_text( reader, elem )) != S_OK) goto error;
1781 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1783 read_insert_node( reader, parent, node );
1784 reader->state = READER_STATE_STARTELEMENT;
1785 return S_OK;
1787 error:
1788 destroy_nodes( node );
1789 return hr;
1792 static inline BOOL is_element_type( unsigned char type )
1794 return (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z);
1797 static HRESULT read_attributes_bin( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1799 WS_XML_ATTRIBUTE *attr;
1800 unsigned char type;
1801 HRESULT hr;
1803 reader->current_attr = 0;
1804 for (;;)
1806 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
1807 if (!is_attribute_type( type )) break;
1808 if ((hr = read_attribute_bin( reader, &attr )) != S_OK) return hr;
1809 if ((hr = append_attribute( elem, attr )) != S_OK)
1811 free_attribute( attr );
1812 return hr;
1814 reader->current_attr++;
1816 return S_OK;
1819 static HRESULT read_element_bin( struct reader *reader )
1821 struct node *node = NULL, *parent;
1822 WS_XML_ELEMENT_NODE *elem;
1823 unsigned char type;
1824 HRESULT hr;
1826 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1827 if (!is_element_type( type )) return WS_E_INVALID_FORMAT;
1829 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1830 node = (struct node *)elem;
1832 if (type >= RECORD_PREFIX_ELEMENT_A && type <= RECORD_PREFIX_ELEMENT_Z)
1834 unsigned char ch = type - RECORD_PREFIX_ELEMENT_A + 'a';
1835 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1837 hr = E_OUTOFMEMORY;
1838 goto error;
1840 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1842 else if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
1844 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ELEMENT_A + 'a';
1845 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1847 hr = E_OUTOFMEMORY;
1848 goto error;
1850 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1852 else
1854 switch (type)
1856 case RECORD_SHORT_ELEMENT:
1857 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
1859 hr = E_OUTOFMEMORY;
1860 goto error;
1862 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1863 break;
1865 case RECORD_ELEMENT:
1866 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
1867 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1868 break;
1870 case RECORD_SHORT_DICTIONARY_ELEMENT:
1871 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
1873 hr = E_OUTOFMEMORY;
1874 goto error;
1876 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1877 break;
1879 case RECORD_DICTIONARY_ELEMENT:
1880 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
1881 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1882 break;
1884 default:
1885 ERR( "unhandled record type %02x\n", type );
1886 return WS_E_NOT_SUPPORTED;
1890 if (!(parent = find_parent( reader )))
1892 hr = WS_E_INVALID_FORMAT;
1893 goto error;
1896 if ((hr = read_attributes_bin( reader, elem )) != S_OK) goto error;
1897 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1899 read_insert_node( reader, parent, node );
1900 reader->state = READER_STATE_STARTELEMENT;
1901 return S_OK;
1903 error:
1904 destroy_nodes( node );
1905 return hr;
1908 static HRESULT read_text_text( struct reader *reader )
1910 unsigned int len = 0, ch, skip;
1911 const unsigned char *start;
1912 struct node *node, *parent;
1913 WS_XML_TEXT_NODE *text;
1914 WS_XML_UTF8_TEXT *utf8;
1915 HRESULT hr;
1917 start = read_current_ptr( reader );
1918 for (;;)
1920 if (read_end_of_data( reader )) break;
1921 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1922 if (ch == '<') break;
1923 read_skip( reader, skip );
1924 len += skip;
1927 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
1929 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1930 text = (WS_XML_TEXT_NODE *)node;
1931 if (!(utf8 = alloc_utf8_text( NULL, len )))
1933 heap_free( node );
1934 return E_OUTOFMEMORY;
1936 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
1938 heap_free( utf8 );
1939 heap_free( node );
1940 return hr;
1942 text->text = &utf8->text;
1944 read_insert_node( reader, parent, node );
1945 reader->state = READER_STATE_TEXT;
1946 reader->text_conv_offset = 0;
1947 return S_OK;
1950 static struct node *alloc_text_node( const unsigned char *data, ULONG len, WS_XML_UTF8_TEXT **ret )
1952 struct node *node;
1953 WS_XML_UTF8_TEXT *utf8;
1954 WS_XML_TEXT_NODE *text;
1956 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
1957 if (!(utf8 = alloc_utf8_text( data, len )))
1959 heap_free( node );
1960 return NULL;
1962 text = (WS_XML_TEXT_NODE *)node;
1963 text->text = &utf8->text;
1964 if (ret) *ret = utf8;
1965 return node;
1968 static HRESULT read_text_bin( struct reader *reader )
1970 static const unsigned char zero[] = {'0'}, one[] = {'1'};
1971 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1972 unsigned char type, buf[46];
1973 struct node *node = NULL, *parent;
1974 WS_XML_UTF8_TEXT *utf8;
1975 BOOL val_bool;
1976 INT8 val_int8;
1977 INT16 val_int16;
1978 INT32 val_int32;
1979 INT64 val_int64;
1980 double val_double;
1981 UINT8 val_uint8;
1982 UINT16 val_uint16;
1983 UINT64 val_uint64;
1984 WS_DATETIME datetime;
1985 ULONG len, id;
1986 GUID uuid;
1987 HRESULT hr;
1989 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1990 if (!is_text_type( type ) || !(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
1992 switch (type)
1994 case RECORD_ZERO_TEXT:
1995 case RECORD_ZERO_TEXT_WITH_ENDELEMENT:
1996 if (!(node = alloc_text_node( zero, sizeof(zero), NULL ))) return E_OUTOFMEMORY;
1997 break;
1999 case RECORD_ONE_TEXT:
2000 case RECORD_ONE_TEXT_WITH_ENDELEMENT:
2001 if (!(node = alloc_text_node( one, sizeof(one), NULL ))) return E_OUTOFMEMORY;
2002 break;
2004 case RECORD_FALSE_TEXT:
2005 case RECORD_FALSE_TEXT_WITH_ENDELEMENT:
2006 if (!(node = alloc_text_node( false, sizeof(false), NULL ))) return E_OUTOFMEMORY;
2007 break;
2009 case RECORD_TRUE_TEXT:
2010 case RECORD_TRUE_TEXT_WITH_ENDELEMENT:
2011 if (!(node = alloc_text_node( true, sizeof(true), NULL ))) return E_OUTOFMEMORY;
2012 break;
2014 case RECORD_INT8_TEXT:
2015 case RECORD_INT8_TEXT_WITH_ENDELEMENT:
2016 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
2017 len = format_int8( &val_int8, buf );
2018 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2019 break;
2021 case RECORD_INT16_TEXT:
2022 case RECORD_INT16_TEXT_WITH_ENDELEMENT:
2023 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
2024 len = format_int16( &val_int16, buf );
2025 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2026 break;
2028 case RECORD_INT32_TEXT:
2029 case RECORD_INT32_TEXT_WITH_ENDELEMENT:
2030 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2031 len = format_int32( &val_int32, buf );
2032 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2033 break;
2035 case RECORD_INT64_TEXT:
2036 case RECORD_INT64_TEXT_WITH_ENDELEMENT:
2037 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
2038 len = format_int64( &val_int64, buf );
2039 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2040 break;
2042 case RECORD_DOUBLE_TEXT:
2043 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT:
2044 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
2045 len = format_double( &val_double, buf );
2046 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2047 break;
2049 case RECORD_DATETIME_TEXT:
2050 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT:
2051 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
2052 len = format_datetime( &datetime, buf );
2053 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2054 break;
2056 case RECORD_CHARS8_TEXT:
2057 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT:
2058 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
2059 len = val_uint8;
2060 break;
2062 case RECORD_CHARS16_TEXT:
2063 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT:
2064 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
2065 len = val_uint16;
2066 break;
2068 case RECORD_CHARS32_TEXT:
2069 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT:
2070 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2071 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
2072 len = val_int32;
2073 break;
2075 case RECORD_BYTES8_TEXT:
2076 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2077 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
2078 if (!(node = alloc_text_node( NULL, ((4 * val_uint8 / 3) + 3) & ~3, &utf8 ))) return E_OUTOFMEMORY;
2079 if ((hr = read_encode_base64( reader, val_uint8, utf8->value.bytes, &utf8->value.length )) != S_OK)
2081 free_node( node );
2082 return hr;
2084 break;
2086 case RECORD_BYTES16_TEXT:
2087 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2088 if ((hr = read_byte( reader, (unsigned char *)&val_uint16 )) != S_OK) return hr;
2089 if (!(node = alloc_text_node( NULL, ((4 * val_uint16 / 3) + 3) & ~3, &utf8 ))) return E_OUTOFMEMORY;
2090 if ((hr = read_encode_base64( reader, val_uint16, utf8->value.bytes, &utf8->value.length )) != S_OK)
2092 free_node( node );
2093 return hr;
2095 break;
2097 case RECORD_BYTES32_TEXT:
2098 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2099 if ((hr = read_byte( reader, (unsigned char *)&val_int32 )) != S_OK) return hr;
2100 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
2101 if (!(node = alloc_text_node( NULL, ((4 * val_int32 / 3) + 3) & ~3, &utf8 ))) return E_OUTOFMEMORY;
2102 if ((hr = read_encode_base64( reader, val_int32, utf8->value.bytes, &utf8->value.length )) != S_OK)
2104 free_node( node );
2105 return hr;
2107 break;
2109 case RECORD_EMPTY_TEXT:
2110 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT:
2111 len = 0;
2112 break;
2114 case RECORD_DICTIONARY_TEXT:
2115 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT:
2116 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
2117 if (!reader->dict || (id >>= 1) >= reader->dict->stringCount) return WS_E_INVALID_FORMAT;
2118 if (!(node = alloc_text_node( reader->dict->strings[id].bytes, reader->dict->strings[id].length, NULL )))
2119 return E_OUTOFMEMORY;
2120 break;
2122 case RECORD_UNIQUEID_TEXT:
2123 case RECORD_UNIQUEID_TEXT_WITH_ENDELEMENT:
2124 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2125 len = format_urn( &uuid, buf );
2126 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2127 break;
2129 case RECORD_UUID_TEXT:
2130 case RECORD_UUID_TEXT_WITH_ENDELEMENT:
2131 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2132 len = format_guid( &uuid, buf );
2133 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2134 break;
2136 case RECORD_UINT64_TEXT:
2137 case RECORD_UINT64_TEXT_WITH_ENDELEMENT:
2138 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
2139 len = format_uint64( &val_uint64, buf );
2140 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2141 break;
2143 case RECORD_BOOL_TEXT:
2144 case RECORD_BOOL_TEXT_WITH_ENDELEMENT:
2145 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
2146 len = format_bool( &val_bool, buf );
2147 if (!(node = alloc_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2148 break;
2150 default:
2151 ERR( "unhandled record type %02x\n", type );
2152 return WS_E_NOT_SUPPORTED;
2155 if (!node)
2157 if (!(node = alloc_text_node( NULL, len, &utf8 ))) return E_OUTOFMEMORY;
2158 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
2160 free_node( node );
2161 return hr;
2165 read_insert_node( reader, parent, node );
2166 reader->state = READER_STATE_TEXT;
2167 reader->text_conv_offset = 0;
2168 return S_OK;
2171 static HRESULT read_node_text( struct reader * );
2173 static HRESULT read_startelement_text( struct reader *reader )
2175 read_skip_whitespace( reader );
2176 if (!read_cmp( reader, "/>", 2 ))
2178 read_skip( reader, 2 );
2179 reader->current = LIST_ENTRY( list_tail( &reader->current->children ), struct node, entry );
2180 reader->last = reader->current;
2181 reader->state = READER_STATE_ENDELEMENT;
2182 return S_OK;
2184 else if (!read_cmp( reader, ">", 1 ))
2186 read_skip( reader, 1 );
2187 return read_node_text( reader );
2189 return WS_E_INVALID_FORMAT;
2192 static HRESULT read_node_bin( struct reader * );
2194 static HRESULT read_startelement_bin( struct reader *reader )
2196 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
2197 return read_node_bin( reader );
2200 static HRESULT read_startelement( struct reader *reader )
2202 switch (reader->input_enc)
2204 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_startelement_text( reader );
2205 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_startelement_bin( reader );
2206 default:
2207 ERR( "unhandled encoding %u\n", reader->input_enc );
2208 return WS_E_NOT_SUPPORTED;
2212 static HRESULT read_to_startelement_text( struct reader *reader, BOOL *found )
2214 HRESULT hr;
2216 switch (reader->state)
2218 case READER_STATE_INITIAL:
2219 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
2220 break;
2222 case READER_STATE_STARTELEMENT:
2223 if (found) *found = TRUE;
2224 return S_OK;
2226 default:
2227 break;
2230 read_skip_whitespace( reader );
2231 if ((hr = read_element_text( reader )) == S_OK && found)
2233 if (reader->state == READER_STATE_STARTELEMENT)
2234 *found = TRUE;
2235 else
2236 *found = FALSE;
2239 return hr;
2242 static HRESULT read_to_startelement_bin( struct reader *reader, BOOL *found )
2244 HRESULT hr;
2246 if (reader->state == READER_STATE_STARTELEMENT)
2248 if (found) *found = TRUE;
2249 return S_OK;
2252 if ((hr = read_element_bin( reader )) == S_OK && found)
2254 if (reader->state == READER_STATE_STARTELEMENT)
2255 *found = TRUE;
2256 else
2257 *found = FALSE;
2260 return hr;
2263 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
2265 switch (reader->input_enc)
2267 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_to_startelement_text( reader, found );
2268 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_to_startelement_bin( reader, found );
2269 default:
2270 ERR( "unhandled encoding %u\n", reader->input_enc );
2271 return WS_E_NOT_SUPPORTED;
2275 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
2277 ULONG i;
2278 if (len1 != len2) return 1;
2279 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
2280 return 0;
2283 static struct node *find_startelement( struct reader *reader, const WS_XML_STRING *prefix,
2284 const WS_XML_STRING *localname )
2286 struct node *parent;
2287 const WS_XML_STRING *str;
2289 for (parent = reader->current; parent; parent = parent->parent)
2291 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
2293 str = parent->hdr.prefix;
2294 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
2295 str = parent->hdr.localName;
2296 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
2297 return parent;
2300 return NULL;
2303 static HRESULT read_endelement_text( struct reader *reader )
2305 struct node *parent;
2306 unsigned int len = 0, ch, skip;
2307 const unsigned char *start;
2308 WS_XML_STRING *prefix, *localname;
2309 HRESULT hr;
2311 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
2312 read_skip( reader, 2 );
2314 start = read_current_ptr( reader );
2315 for (;;)
2317 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2318 if (ch == '>')
2320 read_skip( reader, 1 );
2321 break;
2323 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
2324 read_skip( reader, skip );
2325 len += skip;
2328 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
2329 parent = find_startelement( reader, prefix, localname );
2330 free_xml_string( prefix );
2331 free_xml_string( localname );
2332 if (!parent) return WS_E_INVALID_FORMAT;
2334 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2335 reader->last = reader->current;
2336 reader->state = READER_STATE_ENDELEMENT;
2337 return S_OK;
2340 static HRESULT read_endelement_bin( struct reader *reader )
2342 struct node *parent;
2343 unsigned char type;
2344 HRESULT hr;
2346 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2347 if (type != RECORD_ENDELEMENT) return WS_E_INVALID_FORMAT;
2349 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2351 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2352 reader->last = reader->current;
2353 reader->state = READER_STATE_ENDELEMENT;
2354 return S_OK;
2357 static HRESULT read_endelement( struct reader *reader )
2359 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2361 if (read_end_of_data( reader ))
2363 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2364 reader->last = reader->current;
2365 reader->state = READER_STATE_EOF;
2366 return S_OK;
2369 switch (reader->input_enc)
2371 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_endelement_text( reader );
2372 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_endelement_bin( reader );
2373 default:
2374 ERR( "unhandled encoding %u\n", reader->input_enc );
2375 return WS_E_NOT_SUPPORTED;
2379 static HRESULT read_comment_text( struct reader *reader )
2381 unsigned int len = 0, ch, skip;
2382 const unsigned char *start;
2383 struct node *node, *parent;
2384 WS_XML_COMMENT_NODE *comment;
2386 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
2387 read_skip( reader, 4 );
2389 start = read_current_ptr( reader );
2390 for (;;)
2392 if (!read_cmp( reader, "-->", 3 ))
2394 read_skip( reader, 3 );
2395 break;
2397 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2398 read_skip( reader, skip );
2399 len += skip;
2402 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2404 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2405 comment = (WS_XML_COMMENT_NODE *)node;
2406 if (!(comment->value.bytes = heap_alloc( len )))
2408 heap_free( node );
2409 return E_OUTOFMEMORY;
2411 memcpy( comment->value.bytes, start, len );
2412 comment->value.length = len;
2414 read_insert_node( reader, parent, node );
2415 reader->state = READER_STATE_COMMENT;
2416 return S_OK;
2419 static HRESULT read_comment_bin( struct reader *reader )
2421 struct node *node, *parent;
2422 WS_XML_COMMENT_NODE *comment;
2423 unsigned char type;
2424 ULONG len;
2425 HRESULT hr;
2427 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2428 if (type != RECORD_COMMENT) return WS_E_INVALID_FORMAT;
2429 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
2431 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2433 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2434 comment = (WS_XML_COMMENT_NODE *)node;
2435 if (!(comment->value.bytes = heap_alloc( len )))
2437 heap_free( node );
2438 return E_OUTOFMEMORY;
2440 if ((hr = read_bytes( reader, comment->value.bytes, len )) != S_OK)
2442 free_node( node );
2443 return E_OUTOFMEMORY;
2445 comment->value.length = len;
2447 read_insert_node( reader, parent, node );
2448 reader->state = READER_STATE_COMMENT;
2449 return S_OK;
2452 static HRESULT read_startcdata( struct reader *reader )
2454 struct node *node, *endnode, *parent;
2456 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
2457 read_skip( reader, 9 );
2459 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2461 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
2462 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_CDATA )))
2464 heap_free( node );
2465 return E_OUTOFMEMORY;
2467 list_add_tail( &node->children, &endnode->entry );
2468 endnode->parent = node;
2470 read_insert_node( reader, parent, node );
2471 reader->state = READER_STATE_STARTCDATA;
2472 return S_OK;
2475 static HRESULT read_cdata( struct reader *reader )
2477 unsigned int len = 0, ch, skip;
2478 const unsigned char *start;
2479 struct node *node;
2480 WS_XML_TEXT_NODE *text;
2481 WS_XML_UTF8_TEXT *utf8;
2483 start = read_current_ptr( reader );
2484 for (;;)
2486 if (!read_cmp( reader, "]]>", 3 )) break;
2487 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2488 read_skip( reader, skip );
2489 len += skip;
2492 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2493 text = (WS_XML_TEXT_NODE *)node;
2494 if (!(utf8 = alloc_utf8_text( start, len )))
2496 heap_free( node );
2497 return E_OUTOFMEMORY;
2499 text->text = &utf8->text;
2501 read_insert_node( reader, reader->current, node );
2502 reader->state = READER_STATE_CDATA;
2503 return S_OK;
2506 static HRESULT read_endcdata( struct reader *reader )
2508 struct node *parent;
2510 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
2511 read_skip( reader, 3 );
2513 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT) parent = reader->current->parent;
2514 else parent = reader->current;
2516 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2517 reader->last = reader->current;
2518 reader->state = READER_STATE_ENDCDATA;
2519 return S_OK;
2522 static HRESULT read_node_text( struct reader *reader )
2524 HRESULT hr;
2526 for (;;)
2528 if (read_end_of_data( reader ))
2530 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2531 reader->last = reader->current;
2532 reader->state = READER_STATE_EOF;
2533 return S_OK;
2535 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
2536 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
2537 else if (!read_cmp( reader, "<?", 2 ))
2539 hr = read_xmldecl( reader );
2540 if (FAILED( hr )) return hr;
2542 else if (!read_cmp( reader, "</", 2 )) return read_endelement_text( reader );
2543 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
2544 else if (!read_cmp( reader, "<!--", 4 )) return read_comment_text( reader );
2545 else if (!read_cmp( reader, "<", 1 )) return read_element_text( reader );
2546 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement_text( reader );
2547 else return read_text_text( reader );
2551 static HRESULT read_node_bin( struct reader *reader )
2553 unsigned char type;
2554 HRESULT hr;
2556 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT)
2558 reader->current = LIST_ENTRY( list_tail( &reader->current->parent->children ), struct node, entry );
2559 reader->last = reader->current;
2560 reader->state = READER_STATE_ENDELEMENT;
2561 return S_OK;
2563 if (read_end_of_data( reader ))
2565 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2566 reader->last = reader->current;
2567 reader->state = READER_STATE_EOF;
2568 return S_OK;
2571 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
2572 if (type == RECORD_ENDELEMENT)
2574 return read_endelement_bin( reader );
2576 else if (type == RECORD_COMMENT)
2578 return read_comment_bin( reader );
2580 else if (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z)
2582 return read_element_bin( reader );
2584 else if (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT)
2586 return read_text_bin( reader );
2588 FIXME( "unhandled record type %02x\n", type );
2589 return WS_E_NOT_SUPPORTED;
2592 static HRESULT read_node( struct reader *reader )
2594 switch (reader->input_enc)
2596 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_node_text( reader );
2597 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_node_bin( reader );
2598 default:
2599 ERR( "unhandled encoding %u\n", reader->input_enc );
2600 return WS_E_NOT_SUPPORTED;
2604 HRESULT copy_node( WS_XML_READER *handle, struct node **node )
2606 struct reader *reader = (struct reader *)handle;
2607 const struct list *ptr;
2608 const struct node *start;
2609 HRESULT hr;
2611 EnterCriticalSection( &reader->cs );
2613 if (reader->magic != READER_MAGIC)
2615 LeaveCriticalSection( &reader->cs );
2616 return E_INVALIDARG;
2619 if (reader->current != reader->root) ptr = &reader->current->entry;
2620 else /* copy whole tree */
2622 if (!read_end_of_data( reader ))
2624 for (;;)
2626 if ((hr = read_node( reader )) != S_OK) goto done;
2627 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) break;
2630 ptr = list_head( &reader->root->children );
2633 start = LIST_ENTRY( ptr, struct node, entry );
2634 if (node_type( start ) == WS_XML_NODE_TYPE_EOF) hr = WS_E_INVALID_OPERATION;
2635 else hr = dup_tree( node, start );
2637 done:
2638 LeaveCriticalSection( &reader->cs );
2639 return hr;
2642 /**************************************************************************
2643 * WsReadEndElement [webservices.@]
2645 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
2647 struct reader *reader = (struct reader *)handle;
2648 HRESULT hr;
2650 TRACE( "%p %p\n", handle, error );
2651 if (error) FIXME( "ignoring error parameter\n" );
2653 if (!reader) return E_INVALIDARG;
2655 EnterCriticalSection( &reader->cs );
2657 if (reader->magic != READER_MAGIC)
2659 LeaveCriticalSection( &reader->cs );
2660 return E_INVALIDARG;
2663 hr = read_endelement( reader );
2665 LeaveCriticalSection( &reader->cs );
2666 return hr;
2669 /**************************************************************************
2670 * WsReadNode [webservices.@]
2672 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
2674 struct reader *reader = (struct reader *)handle;
2675 HRESULT hr;
2677 TRACE( "%p %p\n", handle, error );
2678 if (error) FIXME( "ignoring error parameter\n" );
2680 if (!reader) return E_INVALIDARG;
2682 EnterCriticalSection( &reader->cs );
2684 if (reader->magic != READER_MAGIC)
2686 LeaveCriticalSection( &reader->cs );
2687 return E_INVALIDARG;
2690 hr = read_node( reader );
2692 LeaveCriticalSection( &reader->cs );
2693 return hr;
2696 static HRESULT skip_node( struct reader *reader )
2698 const struct node *parent;
2699 HRESULT hr;
2701 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) return WS_E_INVALID_OPERATION;
2702 if (node_type( reader->current ) == WS_XML_NODE_TYPE_ELEMENT) parent = reader->current;
2703 else parent = NULL;
2705 for (;;)
2707 if ((hr = read_node( reader ) != S_OK) || !parent) break;
2708 if (node_type( reader->current ) != WS_XML_NODE_TYPE_END_ELEMENT) continue;
2709 if (reader->current->parent == parent) return read_node( reader );
2712 return hr;
2715 /**************************************************************************
2716 * WsSkipNode [webservices.@]
2718 HRESULT WINAPI WsSkipNode( WS_XML_READER *handle, WS_ERROR *error )
2720 struct reader *reader = (struct reader *)handle;
2721 HRESULT hr;
2723 TRACE( "%p %p\n", handle, error );
2724 if (error) FIXME( "ignoring error parameter\n" );
2726 if (!reader) return E_INVALIDARG;
2728 EnterCriticalSection( &reader->cs );
2730 if (reader->magic != READER_MAGIC)
2732 LeaveCriticalSection( &reader->cs );
2733 return E_INVALIDARG;
2736 hr = skip_node( reader );
2738 LeaveCriticalSection( &reader->cs );
2739 return hr;
2742 /**************************************************************************
2743 * WsReadStartElement [webservices.@]
2745 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
2747 struct reader *reader = (struct reader *)handle;
2748 HRESULT hr;
2750 TRACE( "%p %p\n", handle, error );
2751 if (error) FIXME( "ignoring error parameter\n" );
2753 if (!reader) return E_INVALIDARG;
2755 EnterCriticalSection( &reader->cs );
2757 if (reader->magic != READER_MAGIC)
2759 LeaveCriticalSection( &reader->cs );
2760 return E_INVALIDARG;
2763 hr = read_startelement( reader );
2765 LeaveCriticalSection( &reader->cs );
2766 return hr;
2769 /**************************************************************************
2770 * WsReadToStartElement [webservices.@]
2772 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
2773 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
2775 struct reader *reader = (struct reader *)handle;
2776 HRESULT hr;
2778 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
2779 if (error) FIXME( "ignoring error parameter\n" );
2781 if (!reader) return E_INVALIDARG;
2782 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
2784 EnterCriticalSection( &reader->cs );
2786 if (reader->magic != READER_MAGIC)
2788 LeaveCriticalSection( &reader->cs );
2789 return E_INVALIDARG;
2792 hr = read_to_startelement( reader, found );
2794 LeaveCriticalSection( &reader->cs );
2795 return hr;
2798 BOOL move_to_root_element( struct node *root, struct node **current )
2800 struct list *ptr;
2801 struct node *node;
2803 if (!(ptr = list_head( &root->children ))) return FALSE;
2804 node = LIST_ENTRY( ptr, struct node, entry );
2805 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
2807 *current = node;
2808 return TRUE;
2810 while ((ptr = list_next( &root->children, &node->entry )))
2812 struct node *next = LIST_ENTRY( ptr, struct node, entry );
2813 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
2815 *current = next;
2816 return TRUE;
2818 node = next;
2820 return FALSE;
2823 BOOL move_to_next_element( struct node **current )
2825 struct list *ptr;
2826 struct node *node = *current, *parent = (*current)->parent;
2828 if (!parent) return FALSE;
2829 while ((ptr = list_next( &parent->children, &node->entry )))
2831 struct node *next = LIST_ENTRY( ptr, struct node, entry );
2832 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
2834 *current = next;
2835 return TRUE;
2837 node = next;
2839 return FALSE;
2842 BOOL move_to_prev_element( struct node **current )
2844 struct list *ptr;
2845 struct node *node = *current, *parent = (*current)->parent;
2847 if (!parent) return FALSE;
2848 while ((ptr = list_prev( &parent->children, &node->entry )))
2850 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
2851 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
2853 *current = prev;
2854 return TRUE;
2856 node = prev;
2858 return FALSE;
2861 BOOL move_to_child_element( struct node **current )
2863 struct list *ptr;
2864 struct node *child, *node = *current;
2866 if (!(ptr = list_head( &node->children ))) return FALSE;
2867 child = LIST_ENTRY( ptr, struct node, entry );
2868 if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
2870 *current = child;
2871 return TRUE;
2873 while ((ptr = list_next( &node->children, &child->entry )))
2875 struct node *next = LIST_ENTRY( ptr, struct node, entry );
2876 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
2878 *current = next;
2879 return TRUE;
2881 child = next;
2883 return FALSE;
2886 BOOL move_to_end_element( struct node **current )
2888 struct list *ptr;
2889 struct node *node = *current;
2891 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
2893 if ((ptr = list_tail( &node->children )))
2895 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
2896 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
2898 *current = tail;
2899 return TRUE;
2902 return FALSE;
2905 BOOL move_to_parent_element( struct node **current )
2907 struct node *parent = (*current)->parent;
2909 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
2910 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
2912 *current = parent;
2913 return TRUE;
2915 return FALSE;
2918 BOOL move_to_first_node( struct node **current )
2920 struct list *ptr;
2921 struct node *node = *current;
2923 if ((ptr = list_head( &node->parent->children )))
2925 *current = LIST_ENTRY( ptr, struct node, entry );
2926 return TRUE;
2928 return FALSE;
2931 BOOL move_to_next_node( struct node **current )
2933 struct list *ptr;
2934 struct node *node = *current;
2936 if ((ptr = list_next( &node->parent->children, &node->entry )))
2938 *current = LIST_ENTRY( ptr, struct node, entry );
2939 return TRUE;
2941 return FALSE;
2944 BOOL move_to_prev_node( struct node **current )
2946 struct list *ptr;
2947 struct node *node = *current;
2949 if ((ptr = list_prev( &node->parent->children, &node->entry )))
2951 *current = LIST_ENTRY( ptr, struct node, entry );
2952 return TRUE;
2954 return FALSE;
2957 BOOL move_to_bof( struct node *root, struct node **current )
2959 *current = root;
2960 return TRUE;
2963 BOOL move_to_eof( struct node *root, struct node **current )
2965 struct list *ptr;
2966 if ((ptr = list_tail( &root->children )))
2968 *current = LIST_ENTRY( ptr, struct node, entry );
2969 return TRUE;
2971 return FALSE;
2974 BOOL move_to_child_node( struct node **current )
2976 struct list *ptr;
2977 struct node *node = *current;
2979 if ((ptr = list_head( &node->children )))
2981 *current = LIST_ENTRY( ptr, struct node, entry );
2982 return TRUE;
2984 return FALSE;
2987 BOOL move_to_parent_node( struct node **current )
2989 struct node *parent = (*current)->parent;
2990 if (!parent) return FALSE;
2991 *current = parent;
2992 return TRUE;
2995 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
2997 BOOL success = FALSE;
2998 HRESULT hr = S_OK;
3000 if (!read_end_of_data( reader ))
3002 struct node *saved_current = reader->current;
3003 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
3004 if (hr != S_OK) return hr;
3005 reader->current = saved_current;
3007 switch (move)
3009 case WS_MOVE_TO_ROOT_ELEMENT:
3010 success = move_to_root_element( reader->root, &reader->current );
3011 break;
3013 case WS_MOVE_TO_NEXT_ELEMENT:
3014 success = move_to_next_element( &reader->current );
3015 break;
3017 case WS_MOVE_TO_PREVIOUS_ELEMENT:
3018 success = move_to_prev_element( &reader->current );
3019 break;
3021 case WS_MOVE_TO_CHILD_ELEMENT:
3022 success = move_to_child_element( &reader->current );
3023 break;
3025 case WS_MOVE_TO_END_ELEMENT:
3026 success = move_to_end_element( &reader->current );
3027 break;
3029 case WS_MOVE_TO_PARENT_ELEMENT:
3030 success = move_to_parent_element( &reader->current );
3031 break;
3033 case WS_MOVE_TO_FIRST_NODE:
3034 success = move_to_first_node( &reader->current );
3035 break;
3037 case WS_MOVE_TO_NEXT_NODE:
3038 success = move_to_next_node( &reader->current );
3039 break;
3041 case WS_MOVE_TO_PREVIOUS_NODE:
3042 success = move_to_prev_node( &reader->current );
3043 break;
3045 case WS_MOVE_TO_CHILD_NODE:
3046 success = move_to_child_node( &reader->current );
3047 break;
3049 case WS_MOVE_TO_BOF:
3050 success = move_to_bof( reader->root, &reader->current );
3051 break;
3053 case WS_MOVE_TO_EOF:
3054 success = move_to_eof( reader->root, &reader->current );
3055 break;
3057 default:
3058 FIXME( "unhandled move %u\n", move );
3059 return E_NOTIMPL;
3062 if (found)
3064 *found = success;
3065 return S_OK;
3067 return success ? S_OK : WS_E_INVALID_FORMAT;
3070 /**************************************************************************
3071 * WsMoveReader [webservices.@]
3073 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
3075 struct reader *reader = (struct reader *)handle;
3076 HRESULT hr;
3078 TRACE( "%p %u %p %p\n", handle, move, found, error );
3079 if (error) FIXME( "ignoring error parameter\n" );
3081 if (!reader) return E_INVALIDARG;
3083 EnterCriticalSection( &reader->cs );
3085 if (reader->magic != READER_MAGIC)
3087 LeaveCriticalSection( &reader->cs );
3088 return E_INVALIDARG;
3091 if (!reader->input_type)
3093 LeaveCriticalSection( &reader->cs );
3094 return WS_E_INVALID_OPERATION;
3097 hr = read_move_to( reader, move, found );
3099 LeaveCriticalSection( &reader->cs );
3100 return hr;
3103 /**************************************************************************
3104 * WsReadStartAttribute [webservices.@]
3106 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
3108 struct reader *reader = (struct reader *)handle;
3109 const WS_XML_ELEMENT_NODE *elem;
3111 TRACE( "%p %u %p\n", handle, index, error );
3112 if (error) FIXME( "ignoring error parameter\n" );
3114 if (!reader) return E_INVALIDARG;
3116 EnterCriticalSection( &reader->cs );
3118 if (reader->magic != READER_MAGIC)
3120 LeaveCriticalSection( &reader->cs );
3121 return E_INVALIDARG;
3124 elem = &reader->current->hdr;
3125 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
3127 LeaveCriticalSection( &reader->cs );
3128 return WS_E_INVALID_FORMAT;
3131 reader->current_attr = index;
3132 reader->state = READER_STATE_STARTATTRIBUTE;
3134 LeaveCriticalSection( &reader->cs );
3135 return S_OK;
3138 /**************************************************************************
3139 * WsReadEndAttribute [webservices.@]
3141 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
3143 struct reader *reader = (struct reader *)handle;
3145 TRACE( "%p %p\n", handle, error );
3146 if (error) FIXME( "ignoring error parameter\n" );
3148 if (!reader) return E_INVALIDARG;
3150 EnterCriticalSection( &reader->cs );
3152 if (reader->magic != READER_MAGIC)
3154 LeaveCriticalSection( &reader->cs );
3155 return E_INVALIDARG;
3158 if (reader->state != READER_STATE_STARTATTRIBUTE)
3160 LeaveCriticalSection( &reader->cs );
3161 return WS_E_INVALID_FORMAT;
3164 reader->state = READER_STATE_STARTELEMENT;
3166 LeaveCriticalSection( &reader->cs );
3167 return S_OK;
3170 static HRESULT find_namespace( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING **ns )
3172 const struct node *node;
3173 for (node = reader->current->parent; node_type( node ) == WS_XML_NODE_TYPE_ELEMENT; node = node->parent)
3175 const WS_XML_ELEMENT_NODE *elem = &node->hdr;
3176 ULONG i;
3177 for (i = 0; i < elem->attributeCount; i++)
3179 if (!elem->attributes[i]->isXmlNs) continue;
3180 if (WsXmlStringEquals( elem->attributes[i]->prefix, prefix, NULL ) != S_OK) continue;
3181 *ns = elem->attributes[i]->ns;
3182 return S_OK;
3185 return WS_E_INVALID_FORMAT;
3188 static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix_ret,
3189 WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
3191 const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
3192 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
3193 unsigned char *prefix_bytes, *localname_bytes, *ns_bytes;
3194 const unsigned char *ptr = utf8->value.bytes;
3195 WS_XML_STRING prefix, localname, empty = {0, NULL};
3196 const WS_XML_STRING *ns = &empty;
3197 ULONG len = utf8->value.length;
3198 HRESULT hr;
3200 while (len && read_isspace( *ptr )) { ptr++; len--; }
3201 while (len && read_isspace( ptr[len - 1] )) { len--; }
3202 if (!len) return WS_E_INVALID_FORMAT;
3204 if ((hr = split_name( ptr, len, (const unsigned char **)&prefix.bytes, &prefix.length,
3205 (const unsigned char **)&localname.bytes, &localname.length )) != S_OK) return hr;
3207 if (!localname.length) return WS_E_INVALID_FORMAT;
3208 if (prefix.length && (hr = find_namespace( reader, &prefix, &ns )) != S_OK) return hr;
3210 if (!(prefix_bytes = ws_alloc( heap, prefix.length ))) return WS_E_QUOTA_EXCEEDED;
3211 memcpy( prefix_bytes, prefix.bytes, prefix.length );
3213 if (!(localname_bytes = ws_alloc( heap, localname.length )))
3215 ws_free( heap, prefix_bytes, prefix.length );
3216 return WS_E_QUOTA_EXCEEDED;
3218 memcpy( localname_bytes, localname.bytes, localname.length );
3220 if (!(ns_bytes = ws_alloc( heap, ns->length )))
3222 ws_free( heap, prefix_bytes, prefix.length );
3223 ws_free( heap, localname_bytes, localname.length );
3224 return WS_E_QUOTA_EXCEEDED;
3226 memcpy( ns_bytes, ns->bytes, ns->length );
3228 prefix_ret->bytes = prefix_bytes;
3229 prefix_ret->length = prefix.length;
3231 localname_ret->bytes = localname_bytes;
3232 localname_ret->length = localname.length;
3234 ns_ret->bytes = ns_bytes;
3235 ns_ret->length = ns->length;
3237 return S_OK;
3240 /**************************************************************************
3241 * WsReadQualifiedName [webservices.@]
3243 HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
3244 WS_XML_STRING *localname, WS_XML_STRING *ns,
3245 WS_ERROR *error )
3247 struct reader *reader = (struct reader *)handle;
3248 HRESULT hr;
3250 TRACE( "%p %p %p %p %p %p\n", handle, heap, prefix, localname, ns, error );
3251 if (error) FIXME( "ignoring error parameter\n" );
3253 if (!reader || !heap) return E_INVALIDARG;
3255 EnterCriticalSection( &reader->cs );
3257 if (reader->magic != READER_MAGIC)
3259 LeaveCriticalSection( &reader->cs );
3260 return E_INVALIDARG;
3263 if (!reader->input_type)
3265 LeaveCriticalSection( &reader->cs );
3266 return WS_E_INVALID_OPERATION;
3269 if (!localname)
3271 LeaveCriticalSection( &reader->cs );
3272 return E_INVALIDARG;
3275 if (reader->state != READER_STATE_TEXT)
3277 LeaveCriticalSection( &reader->cs );
3278 return WS_E_INVALID_FORMAT;
3281 hr = read_qualified_name( reader, heap, prefix, localname, ns );
3283 LeaveCriticalSection( &reader->cs );
3284 return hr;
3287 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
3289 WCHAR *ret;
3291 switch (text->textType)
3293 case WS_XML_TEXT_TYPE_UTF8:
3295 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
3296 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
3297 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
3298 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
3299 ret[len] = 0;
3300 break;
3302 default:
3303 FIXME( "unhandled type %u\n", text->textType );
3304 return NULL;
3307 return ret;
3310 #define MAX_INT8 0x7f
3311 #define MIN_INT8 (-MAX_INT8 - 1)
3312 #define MAX_INT16 0x7fff
3313 #define MIN_INT16 (-MAX_INT16 - 1)
3314 #define MAX_INT32 0x7fffffff
3315 #define MIN_INT32 (-MAX_INT32 - 1)
3316 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
3317 #define MIN_INT64 (-MAX_INT64 - 1)
3318 #define MAX_UINT8 0xff
3319 #define MAX_UINT16 0xffff
3320 #define MAX_UINT32 0xffffffff
3321 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
3323 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
3325 BOOL negative = FALSE;
3326 const unsigned char *ptr = str;
3328 *ret = 0;
3329 while (len && read_isspace( *ptr )) { ptr++; len--; }
3330 while (len && read_isspace( ptr[len - 1] )) { len--; }
3331 if (!len) return WS_E_INVALID_FORMAT;
3333 if (*ptr == '-')
3335 negative = TRUE;
3336 ptr++;
3337 len--;
3339 if (!len) return WS_E_INVALID_FORMAT;
3341 while (len--)
3343 int val;
3345 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3346 val = *ptr - '0';
3347 if (negative) val = -val;
3349 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
3350 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
3352 return WS_E_NUMERIC_OVERFLOW;
3354 *ret = *ret * 10 + val;
3355 ptr++;
3358 return S_OK;
3361 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
3363 const unsigned char *ptr = str;
3365 *ret = 0;
3366 while (len && read_isspace( *ptr )) { ptr++; len--; }
3367 while (len && read_isspace( ptr[len - 1] )) { len--; }
3368 if (!len) return WS_E_INVALID_FORMAT;
3370 while (len--)
3372 unsigned int val;
3374 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3375 val = *ptr - '0';
3377 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
3378 *ret = *ret * 10 + val;
3379 ptr++;
3382 return S_OK;
3385 BOOL set_fpword( unsigned short new, unsigned short *old )
3387 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3388 unsigned short fpword;
3390 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
3391 *old = fpword;
3392 fpword = new;
3393 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3394 return TRUE;
3395 #else
3396 FIXME( "not implemented\n" );
3397 return FALSE;
3398 #endif
3401 void restore_fpword( unsigned short fpword )
3403 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3404 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3405 #else
3406 FIXME( "not implemented\n" );
3407 #endif
3410 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
3412 static const unsigned __int64 nan = 0xfff8000000000000;
3413 static const unsigned __int64 inf = 0x7ff0000000000000;
3414 static const unsigned __int64 inf_min = 0xfff0000000000000;
3415 HRESULT hr = WS_E_INVALID_FORMAT;
3416 const unsigned char *p = str, *q;
3417 int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
3418 unsigned __int64 val = 0, tmp;
3419 long double exp_val = 1.0, exp_mul = 10.0;
3420 unsigned short fpword;
3422 while (len && read_isspace( *p )) { p++; len--; }
3423 while (len && read_isspace( p[len - 1] )) { len--; }
3424 if (!len) return WS_E_INVALID_FORMAT;
3426 if (len == 3 && !memcmp( p, "NaN", 3 ))
3428 *(unsigned __int64 *)ret = nan;
3429 return S_OK;
3431 else if (len == 3 && !memcmp( p, "INF", 3 ))
3433 *(unsigned __int64 *)ret = inf;
3434 return S_OK;
3436 else if (len == 4 && !memcmp( p, "-INF", 4 ))
3438 *(unsigned __int64 *)ret = inf_min;
3439 return S_OK;
3442 *ret = 0.0;
3443 if (*p == '-')
3445 sign = -1;
3446 p++; len--;
3448 else if (*p == '+') { p++; len--; };
3449 if (!len) return S_OK;
3451 if (!set_fpword( 0x37f, &fpword )) return E_NOTIMPL;
3453 q = p;
3454 while (len && isdigit( *q )) { q++; len--; }
3455 have_digits = nb_digits = q - p;
3456 for (i = 0; i < nb_digits; i++)
3458 tmp = val * 10 + p[i] - '0';
3459 if (val > MAX_UINT64 / 10 || tmp < val)
3461 for (; i < nb_digits; i++) exp++;
3462 break;
3464 val = tmp;
3467 if (len)
3469 if (*q == '.')
3471 p = ++q; len--;
3472 while (len && isdigit( *q )) { q++; len--; };
3473 have_digits |= nb_digits = q - p;
3474 for (i = 0; i < nb_digits; i++)
3476 tmp = val * 10 + p[i] - '0';
3477 if (val > MAX_UINT64 / 10 || tmp < val) break;
3478 val = tmp;
3479 exp--;
3482 if (len > 1 && tolower(*q) == 'e')
3484 if (!have_digits) goto done;
3485 p = ++q; len--;
3486 if (*p == '-')
3488 exp_sign = -1;
3489 p++; len--;
3491 else if (*p == '+') { p++; len--; };
3493 q = p;
3494 while (len && isdigit( *q )) { q++; len--; };
3495 nb_digits = q - p;
3496 if (!nb_digits || len) goto done;
3497 for (i = 0; i < nb_digits; i++)
3499 if (exp_tmp > MAX_INT32 / 10 || (exp_tmp = exp_tmp * 10 + p[i] - '0') < 0)
3500 exp_tmp = MAX_INT32;
3502 exp_tmp *= exp_sign;
3504 if (exp < 0 && exp_tmp < 0 && exp + exp_tmp >= 0) exp = MIN_INT32;
3505 else if (exp > 0 && exp_tmp > 0 && exp + exp_tmp < 0) exp = MAX_INT32;
3506 else exp += exp_tmp;
3509 if (!have_digits || len) goto done;
3511 if ((neg_exp = exp < 0)) exp = -exp;
3512 for (; exp; exp >>= 1)
3514 if (exp & 1) exp_val *= exp_mul;
3515 exp_mul *= exp_mul;
3518 *ret = sign * (neg_exp ? val / exp_val : val * exp_val);
3519 hr = S_OK;
3521 done:
3522 restore_fpword( fpword );
3523 return hr;
3526 static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
3528 static const unsigned char hex[] =
3530 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3531 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3532 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3533 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3534 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3535 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3536 0,10,11,12,13,14,15 /* 0x60 */
3538 const unsigned char *p = str;
3539 ULONG i;
3541 while (len && read_isspace( *p )) { p++; len--; }
3542 while (len && read_isspace( p[len - 1] )) { len--; }
3543 if (len != 36) return WS_E_INVALID_FORMAT;
3545 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
3546 return WS_E_INVALID_FORMAT;
3548 for (i = 0; i < 36; i++)
3550 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
3551 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
3554 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
3555 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
3557 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
3558 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
3560 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
3561 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
3562 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
3563 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
3564 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
3565 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
3566 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
3567 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
3569 return S_OK;
3572 static inline unsigned char decode_char( unsigned char c )
3574 if (c >= 'A' && c <= 'Z') return c - 'A';
3575 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
3576 if (c >= '0' && c <= '9') return c - '0' + 52;
3577 if (c == '+') return 62;
3578 if (c == '/') return 63;
3579 return 64;
3582 static ULONG decode_base64( const unsigned char *base64, ULONG len, unsigned char *buf )
3584 ULONG i = 0;
3585 unsigned char c0, c1, c2, c3;
3586 const unsigned char *p = base64;
3588 while (len > 4)
3590 if ((c0 = decode_char( p[0] )) > 63) return 0;
3591 if ((c1 = decode_char( p[1] )) > 63) return 0;
3592 if ((c2 = decode_char( p[2] )) > 63) return 0;
3593 if ((c3 = decode_char( p[3] )) > 63) return 0;
3594 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3595 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3596 buf[i + 2] = (c2 << 6) | c3;
3597 len -= 4;
3598 i += 3;
3599 p += 4;
3601 if (p[2] == '=')
3603 if ((c0 = decode_char( p[0] )) > 63) return 0;
3604 if ((c1 = decode_char( p[1] )) > 63) return 0;
3605 buf[i] = (c0 << 2) | (c1 >> 4);
3606 i++;
3608 else if (p[3] == '=')
3610 if ((c0 = decode_char( p[0] )) > 63) return 0;
3611 if ((c1 = decode_char( p[1] )) > 63) return 0;
3612 if ((c2 = decode_char( p[2] )) > 63) return 0;
3613 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3614 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3615 i += 2;
3617 else
3619 if ((c0 = decode_char( p[0] )) > 63) return 0;
3620 if ((c1 = decode_char( p[1] )) > 63) return 0;
3621 if ((c2 = decode_char( p[2] )) > 63) return 0;
3622 if ((c3 = decode_char( p[3] )) > 63) return 0;
3623 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3624 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3625 buf[i + 2] = (c2 << 6) | c3;
3626 i += 3;
3628 return i;
3631 static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_BYTES *ret )
3633 const unsigned char *p = str;
3635 while (len && read_isspace( *p )) { p++; len--; }
3636 while (len && read_isspace( p[len - 1] )) { len--; }
3638 if (len % 4) return WS_E_INVALID_FORMAT;
3639 if (!(ret->bytes = ws_alloc( heap, len * 3 / 4 ))) return WS_E_QUOTA_EXCEEDED;
3640 ret->length = decode_base64( p, len, ret->bytes );
3641 return S_OK;
3644 static const int month_offsets[2][12] =
3646 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
3647 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
3650 static inline int valid_day( int year, int month, int day )
3652 return day > 0 && day <= month_days[leap_year( year )][month - 1];
3655 static inline int leap_days_before( int year )
3657 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
3660 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
3662 const unsigned char *p = bytes, *q;
3663 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
3665 while (len && read_isspace( *p )) { p++; len--; }
3666 while (len && read_isspace( p[len - 1] )) { len--; }
3668 q = p;
3669 while (len && isdigit( *q )) { q++; len--; };
3670 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
3671 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
3672 if (year < 1) return WS_E_INVALID_FORMAT;
3674 p = ++q; len--;
3675 while (len && isdigit( *q )) { q++; len--; };
3676 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
3677 month = (p[0] - '0') * 10 + p[1] - '0';
3678 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
3680 p = ++q; len--;
3681 while (len && isdigit( *q )) { q++; len--; };
3682 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
3683 day = (p[0] - '0') * 10 + p[1] - '0';
3684 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
3686 p = ++q; len--;
3687 while (len && isdigit( *q )) { q++; len--; };
3688 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
3689 hour = (p[0] - '0') * 10 + p[1] - '0';
3690 if (hour > 24) return WS_E_INVALID_FORMAT;
3692 p = ++q; len--;
3693 while (len && isdigit( *q )) { q++; len--; };
3694 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
3695 min = (p[0] - '0') * 10 + p[1] - '0';
3696 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
3698 p = ++q; len--;
3699 while (len && isdigit( *q )) { q++; len--; };
3700 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
3701 sec = (p[0] - '0') * 10 + p[1] - '0';
3702 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
3704 if (*q == '.')
3706 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
3707 p = ++q; len--;
3708 while (len && isdigit( *q )) { q++; len--; };
3709 nb_digits = q - p;
3710 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
3711 for (i = 0; i < nb_digits; i++)
3713 sec_frac += (p[i] - '0') * mul;
3714 mul /= 10;
3717 if (*q == 'Z')
3719 if (--len) return WS_E_INVALID_FORMAT;
3720 tz_hour = tz_min = tz_neg = 0;
3721 ret->format = WS_DATETIME_FORMAT_UTC;
3723 else if (*q == '+' || *q == '-')
3725 tz_neg = (*q == '-') ? 1 : 0;
3727 p = ++q; len--;
3728 while (len && isdigit( *q )) { q++; len--; };
3729 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
3730 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
3731 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
3733 p = ++q; len--;
3734 while (len && isdigit( *q )) { q++; len--; };
3735 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
3736 tz_min = (p[0] - '0') * 10 + p[1] - '0';
3737 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
3739 ret->format = WS_DATETIME_FORMAT_LOCAL;
3741 else return WS_E_INVALID_FORMAT;
3743 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
3744 ret->ticks += month_offsets[leap_year( year )][month - 1] * TICKS_PER_DAY;
3745 ret->ticks += (day - 1) * TICKS_PER_DAY;
3746 ret->ticks += hour * TICKS_PER_HOUR;
3747 ret->ticks += min * TICKS_PER_MIN;
3748 ret->ticks += sec * TICKS_PER_SEC;
3749 ret->ticks += sec_frac;
3751 if (tz_neg)
3753 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
3754 return WS_E_INVALID_FORMAT;
3755 ret->ticks += tz_hour * TICKS_PER_HOUR;
3756 ret->ticks += tz_min * TICKS_PER_MIN;
3758 else
3760 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
3761 return WS_E_INVALID_FORMAT;
3762 ret->ticks -= tz_hour * TICKS_PER_HOUR;
3763 ret->ticks -= tz_min * TICKS_PER_MIN;
3766 return S_OK;
3769 /**************************************************************************
3770 * WsDateTimeToFileTime [webservices.@]
3772 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
3774 unsigned __int64 ticks;
3776 TRACE( "%p %p %p\n", dt, ft, error );
3777 if (error) FIXME( "ignoring error parameter\n" );
3779 if (!dt || !ft) return E_INVALIDARG;
3781 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
3782 ticks = dt->ticks - TICKS_1601_01_01;
3783 ft->dwHighDateTime = ticks >> 32;
3784 ft->dwLowDateTime = (DWORD)ticks;
3785 return S_OK;
3788 /**************************************************************************
3789 * WsFileTimeToDateTime [webservices.@]
3791 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
3793 unsigned __int64 ticks;
3795 TRACE( "%p %p %p\n", ft, dt, error );
3796 if (error) FIXME( "ignoring error parameter\n" );
3798 if (!dt || !ft) return E_INVALIDARG;
3800 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
3801 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
3802 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
3803 dt->ticks = ticks + TICKS_1601_01_01;
3804 dt->format = WS_DATETIME_FORMAT_UTC;
3805 return S_OK;
3808 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
3810 WS_XML_TEXT_NODE *text;
3812 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
3813 return WS_E_INVALID_FORMAT;
3815 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
3816 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
3818 FIXME( "text type %u not supported\n", text->text->textType );
3819 return E_NOTIMPL;
3821 *ret = (WS_XML_UTF8_TEXT *)text->text;
3822 return S_OK;
3825 static HRESULT read_get_attribute_text( struct reader *reader, ULONG index, WS_XML_UTF8_TEXT **ret )
3827 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3828 WS_XML_ATTRIBUTE *attr;
3830 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
3831 return WS_E_INVALID_FORMAT;
3833 attr = elem->attributes[index];
3834 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
3836 FIXME( "text type %u not supported\n", attr->value->textType );
3837 return E_NOTIMPL;
3839 *ret = (WS_XML_UTF8_TEXT *)attr->value;
3840 return S_OK;
3843 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
3844 const WS_XML_STRING *ns, ULONG *index )
3846 ULONG i;
3847 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3849 if (!localname)
3851 *index = reader->current_attr;
3852 return TRUE;
3854 for (i = 0; i < elem->attributeCount; i++)
3856 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
3857 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
3859 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
3860 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
3862 *index = i;
3863 return TRUE;
3866 return FALSE;
3869 /**************************************************************************
3870 * WsFindAttribute [webservices.@]
3872 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
3873 const WS_XML_STRING *ns, BOOL required, ULONG *index,
3874 WS_ERROR *error )
3876 struct reader *reader = (struct reader *)handle;
3877 HRESULT hr = S_OK;
3879 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
3880 required, index, error );
3881 if (error) FIXME( "ignoring error parameter\n" );
3883 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
3885 EnterCriticalSection( &reader->cs );
3887 if (reader->magic != READER_MAGIC)
3889 LeaveCriticalSection( &reader->cs );
3890 return E_INVALIDARG;
3893 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
3895 LeaveCriticalSection( &reader->cs );
3896 return WS_E_INVALID_OPERATION;
3899 if (!find_attribute( reader, localname, ns, index ))
3901 if (required) hr = WS_E_INVALID_FORMAT;
3902 else
3904 *index = ~0u;
3905 hr = S_FALSE;
3909 LeaveCriticalSection( &reader->cs );
3910 return hr;
3913 static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
3914 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3915 WS_XML_UTF8_TEXT **ret, BOOL *found )
3917 switch (mapping)
3919 case WS_ATTRIBUTE_TYPE_MAPPING:
3921 ULONG index;
3922 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
3923 return read_get_attribute_text( reader, index, ret );
3925 case WS_ELEMENT_TYPE_MAPPING:
3926 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
3927 case WS_ANY_ELEMENT_TYPE_MAPPING:
3929 HRESULT hr;
3930 *found = TRUE;
3931 if (localname)
3933 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3935 if (WsXmlStringEquals( localname, elem->localName, NULL ) != S_OK ||
3936 WsXmlStringEquals( ns, elem->ns, NULL ) != S_OK)
3938 *found = FALSE;
3939 return S_OK;
3941 if ((hr = read_startelement( reader )) != S_OK) return hr;
3943 return read_get_node_text( reader, ret );
3945 default:
3946 FIXME( "mapping %u not supported\n", mapping );
3947 return E_NOTIMPL;
3951 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
3952 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3953 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
3954 WS_HEAP *heap, void *ret, ULONG size )
3956 WS_XML_UTF8_TEXT *utf8;
3957 HRESULT hr;
3958 BOOL found, val = FALSE;
3960 if (desc)
3962 FIXME( "description not supported\n" );
3963 return E_NOTIMPL;
3965 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3966 if (found)
3968 ULONG len = utf8->value.length;
3969 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
3970 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
3971 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
3972 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
3973 else return WS_E_INVALID_FORMAT;
3976 switch (option)
3978 case WS_READ_REQUIRED_VALUE:
3979 if (!found) return WS_E_INVALID_FORMAT;
3980 /* fall through */
3982 case WS_READ_NILLABLE_VALUE:
3983 if (size != sizeof(BOOL)) return E_INVALIDARG;
3984 *(BOOL *)ret = val;
3985 break;
3987 case WS_READ_REQUIRED_POINTER:
3988 if (!found) return WS_E_INVALID_FORMAT;
3989 /* fall through */
3991 case WS_READ_OPTIONAL_POINTER:
3992 case WS_READ_NILLABLE_POINTER:
3994 BOOL *heap_val = NULL;
3995 if (size != sizeof(heap_val)) return E_INVALIDARG;
3996 if (found)
3998 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3999 *heap_val = val;
4001 *(BOOL **)ret = heap_val;
4002 break;
4004 default:
4005 FIXME( "read option %u not supported\n", option );
4006 return E_NOTIMPL;
4009 return S_OK;
4012 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
4013 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4014 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
4015 WS_HEAP *heap, void *ret, ULONG size )
4017 WS_XML_UTF8_TEXT *utf8;
4018 HRESULT hr;
4019 INT64 val = 0;
4020 BOOL found;
4022 if (desc)
4024 FIXME( "description not supported\n" );
4025 return E_NOTIMPL;
4027 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4028 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
4029 return hr;
4031 switch (option)
4033 case WS_READ_REQUIRED_VALUE:
4034 if (!found) return WS_E_INVALID_FORMAT;
4035 /* fall through */
4037 case WS_READ_NILLABLE_VALUE:
4038 if (size != sizeof(INT8)) return E_INVALIDARG;
4039 *(INT8 *)ret = val;
4040 break;
4042 case WS_READ_REQUIRED_POINTER:
4043 if (!found) return WS_E_INVALID_FORMAT;
4044 /* fall through */
4046 case WS_READ_OPTIONAL_POINTER:
4047 case WS_READ_NILLABLE_POINTER:
4049 INT8 *heap_val = NULL;
4050 if (size != sizeof(heap_val)) return E_INVALIDARG;
4051 if (found)
4053 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4054 *heap_val = val;
4056 *(INT8 **)ret = heap_val;
4057 break;
4059 default:
4060 FIXME( "read option %u not supported\n", option );
4061 return E_NOTIMPL;
4064 return S_OK;
4067 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
4068 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4069 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
4070 WS_HEAP *heap, void *ret, ULONG size )
4072 WS_XML_UTF8_TEXT *utf8;
4073 HRESULT hr;
4074 INT64 val = 0;
4075 BOOL found;
4077 if (desc)
4079 FIXME( "description not supported\n" );
4080 return E_NOTIMPL;
4082 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4083 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
4084 return hr;
4086 switch (option)
4088 case WS_READ_REQUIRED_VALUE:
4089 if (!found) return WS_E_INVALID_FORMAT;
4090 /* fall through */
4092 case WS_READ_NILLABLE_VALUE:
4093 if (size != sizeof(INT16)) return E_INVALIDARG;
4094 *(INT16 *)ret = val;
4095 break;
4097 case WS_READ_REQUIRED_POINTER:
4098 if (!found) return WS_E_INVALID_FORMAT;
4099 /* fall through */
4101 case WS_READ_OPTIONAL_POINTER:
4102 case WS_READ_NILLABLE_POINTER:
4104 INT16 *heap_val = NULL;
4105 if (size != sizeof(heap_val)) return E_INVALIDARG;
4106 if (found)
4108 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4109 *heap_val = val;
4111 *(INT16 **)ret = heap_val;
4112 break;
4114 default:
4115 FIXME( "read option %u not supported\n", option );
4116 return E_NOTIMPL;
4119 return S_OK;
4122 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
4123 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4124 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
4125 WS_HEAP *heap, void *ret, ULONG size )
4127 WS_XML_UTF8_TEXT *utf8;
4128 HRESULT hr;
4129 INT64 val = 0;
4130 BOOL found;
4132 if (desc)
4134 FIXME( "description not supported\n" );
4135 return E_NOTIMPL;
4137 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4138 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
4139 return hr;
4141 switch (option)
4143 case WS_READ_REQUIRED_VALUE:
4144 if (!found) return WS_E_INVALID_FORMAT;
4145 /* fall through */
4147 case WS_READ_NILLABLE_VALUE:
4148 if (size != sizeof(INT32)) return E_INVALIDARG;
4149 *(INT32 *)ret = val;
4150 break;
4152 case WS_READ_REQUIRED_POINTER:
4153 if (!found) return WS_E_INVALID_FORMAT;
4154 /* fall through */
4156 case WS_READ_OPTIONAL_POINTER:
4157 case WS_READ_NILLABLE_POINTER:
4159 INT32 *heap_val = NULL;
4160 if (size != sizeof(heap_val)) return E_INVALIDARG;
4161 if (found)
4163 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4164 *heap_val = val;
4166 *(INT32 **)ret = heap_val;
4167 break;
4169 default:
4170 FIXME( "read option %u not supported\n", option );
4171 return E_NOTIMPL;
4174 return S_OK;
4177 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
4178 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4179 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
4180 WS_HEAP *heap, void *ret, ULONG size )
4182 WS_XML_UTF8_TEXT *utf8;
4183 HRESULT hr;
4184 INT64 val = 0;
4185 BOOL found;
4187 if (desc)
4189 FIXME( "description not supported\n" );
4190 return E_NOTIMPL;
4192 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4193 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
4194 return hr;
4196 switch (option)
4198 case WS_READ_REQUIRED_VALUE:
4199 if (!found) return WS_E_INVALID_FORMAT;
4200 /* fall through */
4202 case WS_READ_NILLABLE_VALUE:
4203 if (size != sizeof(INT64)) return E_INVALIDARG;
4204 *(INT64 *)ret = val;
4205 break;
4207 case WS_READ_REQUIRED_POINTER:
4208 if (!found) return WS_E_INVALID_FORMAT;
4209 /* fall through */
4211 case WS_READ_OPTIONAL_POINTER:
4212 case WS_READ_NILLABLE_POINTER:
4214 INT64 *heap_val = NULL;
4215 if (size != sizeof(heap_val)) return E_INVALIDARG;
4216 if (found)
4218 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4219 *heap_val = val;
4221 *(INT64 **)ret = heap_val;
4222 break;
4224 default:
4225 FIXME( "read option %u not supported\n", option );
4226 return E_NOTIMPL;
4229 return S_OK;
4232 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
4233 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4234 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
4235 WS_HEAP *heap, void *ret, ULONG size )
4237 WS_XML_UTF8_TEXT *utf8;
4238 HRESULT hr;
4239 UINT64 val = 0;
4240 BOOL found;
4242 if (desc)
4244 FIXME( "description not supported\n" );
4245 return E_NOTIMPL;
4247 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4248 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
4249 return hr;
4251 switch (option)
4253 case WS_READ_REQUIRED_VALUE:
4254 if (!found) return WS_E_INVALID_FORMAT;
4255 /* fall through */
4257 case WS_READ_NILLABLE_VALUE:
4258 if (size != sizeof(UINT8)) return E_INVALIDARG;
4259 *(UINT8 *)ret = val;
4260 break;
4262 case WS_READ_REQUIRED_POINTER:
4263 if (!found) return WS_E_INVALID_FORMAT;
4264 /* fall through */
4266 case WS_READ_OPTIONAL_POINTER:
4267 case WS_READ_NILLABLE_POINTER:
4269 UINT8 *heap_val = NULL;
4270 if (size != sizeof(heap_val)) return E_INVALIDARG;
4271 if (found)
4273 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4274 *heap_val = val;
4276 *(UINT8 **)ret = heap_val;
4277 break;
4279 default:
4280 FIXME( "read option %u not supported\n", option );
4281 return E_NOTIMPL;
4284 return S_OK;
4287 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
4288 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4289 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
4290 WS_HEAP *heap, void *ret, ULONG size )
4292 WS_XML_UTF8_TEXT *utf8;
4293 HRESULT hr;
4294 UINT64 val = 0;
4295 BOOL found;
4297 if (desc)
4299 FIXME( "description not supported\n" );
4300 return E_NOTIMPL;
4302 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4303 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
4304 return hr;
4306 switch (option)
4308 case WS_READ_REQUIRED_VALUE:
4309 if (!found) return WS_E_INVALID_FORMAT;
4310 /* fall through */
4312 case WS_READ_NILLABLE_VALUE:
4313 if (size != sizeof(UINT16)) return E_INVALIDARG;
4314 *(UINT16 *)ret = val;
4315 break;
4317 case WS_READ_REQUIRED_POINTER:
4318 if (!found) return WS_E_INVALID_FORMAT;
4319 /* fall through */
4321 case WS_READ_OPTIONAL_POINTER:
4322 case WS_READ_NILLABLE_POINTER:
4324 UINT16 *heap_val = NULL;
4325 if (size != sizeof(heap_val)) return E_INVALIDARG;
4326 if (found)
4328 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4329 *heap_val = val;
4331 *(UINT16 **)ret = heap_val;
4332 break;
4334 default:
4335 FIXME( "read option %u not supported\n", option );
4336 return E_NOTIMPL;
4339 return S_OK;
4342 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
4343 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4344 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
4345 WS_HEAP *heap, void *ret, ULONG size )
4347 WS_XML_UTF8_TEXT *utf8;
4348 HRESULT hr;
4349 UINT64 val = 0;
4350 BOOL found;
4352 if (desc)
4354 FIXME( "description not supported\n" );
4355 return E_NOTIMPL;
4357 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4358 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
4359 return hr;
4361 switch (option)
4363 case WS_READ_REQUIRED_VALUE:
4364 if (!found) return WS_E_INVALID_FORMAT;
4365 /* fall through */
4367 case WS_READ_NILLABLE_VALUE:
4368 if (size != sizeof(UINT32)) return E_INVALIDARG;
4369 *(UINT32 *)ret = val;
4370 break;
4372 case WS_READ_REQUIRED_POINTER:
4373 if (!found) return WS_E_INVALID_FORMAT;
4374 /* fall through */
4376 case WS_READ_OPTIONAL_POINTER:
4377 case WS_READ_NILLABLE_POINTER:
4379 UINT32 *heap_val = NULL;
4380 if (size != sizeof(heap_val)) return E_INVALIDARG;
4381 if (found)
4383 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4384 *heap_val = val;
4386 *(UINT32 **)ret = heap_val;
4387 break;
4389 default:
4390 FIXME( "read option %u not supported\n", option );
4391 return E_NOTIMPL;
4394 return S_OK;
4397 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
4398 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4399 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
4400 WS_HEAP *heap, void *ret, ULONG size )
4402 WS_XML_UTF8_TEXT *utf8;
4403 HRESULT hr;
4404 UINT64 val = 0;
4405 BOOL found;
4407 if (desc)
4409 FIXME( "description not supported\n" );
4410 return E_NOTIMPL;
4412 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4413 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
4414 return hr;
4416 switch (option)
4418 case WS_READ_REQUIRED_VALUE:
4419 if (!found) return WS_E_INVALID_FORMAT;
4420 /* fall through */
4422 case WS_READ_NILLABLE_VALUE:
4423 if (size != sizeof(UINT64)) return E_INVALIDARG;
4424 *(UINT64 *)ret = val;
4425 break;
4427 case WS_READ_REQUIRED_POINTER:
4428 if (!found) return WS_E_INVALID_FORMAT;
4429 /* fall through */
4431 case WS_READ_OPTIONAL_POINTER:
4432 case WS_READ_NILLABLE_POINTER:
4434 UINT64 *heap_val = NULL;
4435 if (size != sizeof(heap_val)) return E_INVALIDARG;
4436 if (found)
4438 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4439 *heap_val = val;
4441 *(UINT64 **)ret = heap_val;
4442 break;
4444 default:
4445 FIXME( "read option %u not supported\n", option );
4446 return E_NOTIMPL;
4449 return S_OK;
4452 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
4453 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4454 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
4455 WS_HEAP *heap, void *ret, ULONG size )
4457 WS_XML_UTF8_TEXT *utf8;
4458 HRESULT hr;
4459 double val = 0.0;
4460 BOOL found;
4462 if (desc) FIXME( "ignoring description\n" );
4464 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4465 if (found && (hr = str_to_double( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
4467 switch (option)
4469 case WS_READ_REQUIRED_VALUE:
4470 if (!found) return WS_E_INVALID_FORMAT;
4471 /* fall through */
4473 case WS_READ_NILLABLE_VALUE:
4474 if (size != sizeof(double)) return E_INVALIDARG;
4475 *(double *)ret = val;
4476 break;
4478 case WS_READ_REQUIRED_POINTER:
4479 if (!found) return WS_E_INVALID_FORMAT;
4480 /* fall through */
4482 case WS_READ_OPTIONAL_POINTER:
4483 case WS_READ_NILLABLE_POINTER:
4485 double *heap_val = NULL;
4486 if (size != sizeof(heap_val)) return E_INVALIDARG;
4487 if (found)
4489 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4490 *heap_val = val;
4492 *(double **)ret = heap_val;
4493 break;
4495 default:
4496 FIXME( "read option %u not supported\n", option );
4497 return E_NOTIMPL;
4500 return S_OK;
4503 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
4504 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4505 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
4506 WS_HEAP *heap, WCHAR **ret, ULONG size )
4508 WS_XML_UTF8_TEXT *utf8;
4509 HRESULT hr;
4510 WCHAR *str = NULL;
4511 BOOL found;
4513 if (desc)
4515 FIXME( "description not supported\n" );
4516 return E_NOTIMPL;
4518 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4519 if (found && !(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
4521 switch (option)
4523 case WS_READ_REQUIRED_POINTER:
4524 if (!found) return WS_E_INVALID_FORMAT;
4525 /* fall through */
4527 case WS_READ_OPTIONAL_POINTER:
4528 case WS_READ_NILLABLE_POINTER:
4529 if (size != sizeof(str)) return E_INVALIDARG;
4530 *ret = str;
4531 break;
4533 default:
4534 FIXME( "read option %u not supported\n", option );
4535 return E_NOTIMPL;
4538 return S_OK;
4541 static HRESULT get_enum_value( const WS_XML_UTF8_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
4543 ULONG i;
4544 for (i = 0; i < desc->valueCount; i++)
4546 if (WsXmlStringEquals( &text->value, desc->values[i].name, NULL ) == S_OK)
4548 *ret = desc->values[i].value;
4549 return S_OK;
4552 return WS_E_INVALID_FORMAT;
4555 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
4556 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4557 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
4558 WS_HEAP *heap, void *ret, ULONG size )
4560 WS_XML_UTF8_TEXT *utf8;
4561 HRESULT hr;
4562 int val = 0;
4563 BOOL found;
4565 if (!desc) return E_INVALIDARG;
4567 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4568 if (found && (hr = get_enum_value( utf8, desc, &val )) != S_OK) return hr;
4570 switch (option)
4572 case WS_READ_REQUIRED_VALUE:
4573 if (!found) return WS_E_INVALID_FORMAT;
4574 /* fall through */
4576 case WS_READ_NILLABLE_VALUE:
4577 if (size != sizeof(int)) return E_INVALIDARG;
4578 *(int *)ret = val;
4579 break;
4581 case WS_READ_REQUIRED_POINTER:
4582 if (!found) return WS_E_INVALID_FORMAT;
4583 /* fall through */
4585 case WS_READ_OPTIONAL_POINTER:
4586 case WS_READ_NILLABLE_POINTER:
4588 int *heap_val = NULL;
4589 if (size != sizeof(heap_val)) return E_INVALIDARG;
4590 if (found)
4592 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4593 *heap_val = val;
4595 *(int **)ret = heap_val;
4596 break;
4598 default:
4599 FIXME( "read option %u not supported\n", option );
4600 return E_NOTIMPL;
4603 return S_OK;
4606 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
4607 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4608 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
4609 WS_HEAP *heap, void *ret, ULONG size )
4611 WS_XML_UTF8_TEXT *utf8;
4612 HRESULT hr;
4613 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
4614 BOOL found;
4616 if (desc) FIXME( "ignoring description\n" );
4618 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4619 if (found && (hr = str_to_datetime( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
4621 switch (option)
4623 case WS_READ_REQUIRED_VALUE:
4624 if (!found) return WS_E_INVALID_FORMAT;
4625 /* fall through */
4627 case WS_READ_NILLABLE_VALUE:
4628 if (size != sizeof(WS_DATETIME)) return E_INVALIDARG;
4629 *(WS_DATETIME *)ret = val;
4630 break;
4632 case WS_READ_REQUIRED_POINTER:
4633 if (!found) return WS_E_INVALID_FORMAT;
4634 /* fall through */
4636 case WS_READ_OPTIONAL_POINTER:
4637 case WS_READ_NILLABLE_POINTER:
4639 WS_DATETIME *heap_val = NULL;
4640 if (size != sizeof(heap_val)) return E_INVALIDARG;
4641 if (found)
4643 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4644 *heap_val = val;
4646 *(WS_DATETIME **)ret = heap_val;
4647 break;
4649 default:
4650 FIXME( "read option %u not supported\n", option );
4651 return E_NOTIMPL;
4654 return S_OK;
4657 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
4658 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4659 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
4660 WS_HEAP *heap, void *ret, ULONG size )
4662 WS_XML_UTF8_TEXT *utf8;
4663 GUID val = {0};
4664 HRESULT hr;
4665 BOOL found;
4667 if (desc) FIXME( "ignoring description\n" );
4669 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4670 if (found && (hr = str_to_guid( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
4672 switch (option)
4674 case WS_READ_REQUIRED_VALUE:
4675 if (!found) return WS_E_INVALID_FORMAT;
4676 /* fall through */
4678 case WS_READ_NILLABLE_VALUE:
4679 if (size != sizeof(GUID)) return E_INVALIDARG;
4680 *(GUID *)ret = val;
4681 break;
4683 case WS_READ_REQUIRED_POINTER:
4684 if (!found) return WS_E_INVALID_FORMAT;
4685 /* fall through */
4687 case WS_READ_OPTIONAL_POINTER:
4688 case WS_READ_NILLABLE_POINTER:
4690 GUID *heap_val = NULL;
4691 if (size != sizeof(heap_val)) return E_INVALIDARG;
4692 if (found)
4694 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4695 *heap_val = val;
4697 *(GUID **)ret = heap_val;
4698 break;
4700 default:
4701 FIXME( "read option %u not supported\n", option );
4702 return E_NOTIMPL;
4705 return S_OK;
4708 static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
4709 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4710 const WS_BYTES_DESCRIPTION *desc, WS_READ_OPTION option,
4711 WS_HEAP *heap, void *ret, ULONG size )
4713 WS_XML_UTF8_TEXT *utf8;
4714 WS_BYTES val = {0};
4715 HRESULT hr;
4716 BOOL found;
4718 if (desc) FIXME( "ignoring description\n" );
4720 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4721 if (found && (hr = str_to_bytes( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
4722 return hr;
4724 switch (option)
4726 case WS_READ_REQUIRED_VALUE:
4727 if (!found) return WS_E_INVALID_FORMAT;
4728 /* fall through */
4730 case WS_READ_NILLABLE_VALUE:
4731 if (size != sizeof(WS_BYTES)) return E_INVALIDARG;
4732 *(WS_BYTES *)ret = val;
4733 break;
4735 case WS_READ_REQUIRED_POINTER:
4736 if (!found) return WS_E_INVALID_FORMAT;
4737 /* fall through */
4739 case WS_READ_OPTIONAL_POINTER:
4740 case WS_READ_NILLABLE_POINTER:
4742 WS_BYTES *heap_val = NULL;
4743 if (size != sizeof(heap_val)) return E_INVALIDARG;
4744 if (found)
4746 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4747 *heap_val = val;
4749 *(WS_BYTES **)ret = heap_val;
4750 break;
4752 default:
4753 FIXME( "read option %u not supported\n", option );
4754 return E_NOTIMPL;
4757 return S_OK;
4760 static BOOL is_empty_text_node( const struct node *node )
4762 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
4763 const WS_XML_UTF8_TEXT *utf8;
4764 ULONG i;
4766 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
4767 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
4769 ERR( "unhandled text type %u\n", text->text->textType );
4770 return FALSE;
4772 utf8 = (const WS_XML_UTF8_TEXT *)text->text;
4773 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
4774 return TRUE;
4777 static HRESULT read_next_node( struct reader *reader )
4779 if (reader->current == reader->last) return read_node( reader );
4780 if (move_to_child_node( &reader->current )) return S_OK;
4781 if (move_to_next_node( &reader->current )) return S_OK;
4782 if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
4783 if (move_to_next_node( &reader->current )) return S_OK;
4784 return WS_E_INVALID_FORMAT;
4787 /* skips comment and empty text nodes */
4788 static HRESULT read_type_next_node( struct reader *reader )
4790 for (;;)
4792 HRESULT hr;
4793 WS_XML_NODE_TYPE type;
4795 if ((hr = read_next_node( reader )) != S_OK) return hr;
4796 type = node_type( reader->current );
4797 if (type == WS_XML_NODE_TYPE_COMMENT ||
4798 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
4799 return S_OK;
4803 static BOOL match_current_element( struct reader *reader, const WS_XML_STRING *localname,
4804 const WS_XML_STRING *ns )
4806 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
4807 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
4808 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
4809 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
4812 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
4813 const WS_XML_STRING *ns )
4815 struct node *node;
4816 ULONG attr;
4817 HRESULT hr;
4819 if (!localname) return S_OK; /* assume reader is already correctly positioned */
4820 if (reader->current == reader->last)
4822 BOOL found;
4823 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
4824 if (!found) return WS_E_INVALID_FORMAT;
4826 if (match_current_element( reader, localname, ns )) return S_OK;
4828 node = reader->current;
4829 attr = reader->current_attr;
4831 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
4832 if (match_current_element( reader, localname, ns )) return S_OK;
4834 reader->current = node;
4835 reader->current_attr = attr;
4837 return WS_E_INVALID_FORMAT;
4840 ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
4842 switch (type)
4844 case WS_INT8_TYPE:
4845 case WS_UINT8_TYPE:
4846 return sizeof(INT8);
4848 case WS_INT16_TYPE:
4849 case WS_UINT16_TYPE:
4850 return sizeof(INT16);
4852 case WS_BOOL_TYPE:
4853 case WS_INT32_TYPE:
4854 case WS_UINT32_TYPE:
4855 case WS_ENUM_TYPE:
4856 return sizeof(INT32);
4858 case WS_INT64_TYPE:
4859 case WS_UINT64_TYPE:
4860 return sizeof(INT64);
4862 case WS_DOUBLE_TYPE:
4863 return sizeof(double);
4865 case WS_DATETIME_TYPE:
4866 return sizeof(WS_DATETIME);
4868 case WS_GUID_TYPE:
4869 return sizeof(GUID);
4871 case WS_STRING_TYPE:
4872 return sizeof(WS_STRING);
4874 case WS_WSZ_TYPE:
4875 return sizeof(WCHAR *);
4877 case WS_BYTES_TYPE:
4878 return sizeof(WS_BYTES);
4880 case WS_XML_STRING_TYPE:
4881 return sizeof(WS_XML_STRING);
4883 case WS_STRUCT_TYPE:
4884 return desc->size;
4886 case WS_DESCRIPTION_TYPE:
4887 return sizeof(WS_STRUCT_DESCRIPTION *);
4889 default:
4890 ERR( "unhandled type %u\n", type );
4891 return 0;
4895 static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
4897 if (options & WS_FIELD_POINTER)
4899 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
4900 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
4901 return WS_READ_REQUIRED_POINTER;
4904 switch (type)
4906 case WS_BOOL_TYPE:
4907 case WS_INT8_TYPE:
4908 case WS_INT16_TYPE:
4909 case WS_INT32_TYPE:
4910 case WS_INT64_TYPE:
4911 case WS_UINT8_TYPE:
4912 case WS_UINT16_TYPE:
4913 case WS_UINT32_TYPE:
4914 case WS_UINT64_TYPE:
4915 case WS_DOUBLE_TYPE:
4916 case WS_DATETIME_TYPE:
4917 case WS_GUID_TYPE:
4918 case WS_STRING_TYPE:
4919 case WS_BYTES_TYPE:
4920 case WS_XML_STRING_TYPE:
4921 case WS_STRUCT_TYPE:
4922 case WS_ENUM_TYPE:
4923 if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
4924 return WS_READ_REQUIRED_VALUE;
4926 case WS_WSZ_TYPE:
4927 case WS_DESCRIPTION_TYPE:
4928 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
4929 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
4930 return WS_READ_REQUIRED_POINTER;
4932 default:
4933 FIXME( "unhandled type %u\n", type );
4934 return 0;
4938 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
4939 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
4940 void *, ULONG );
4942 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
4943 WS_HEAP *heap, void **ret, ULONG *count )
4945 HRESULT hr;
4946 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
4947 WS_READ_OPTION option;
4948 char *buf;
4950 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
4952 /* wrapper element */
4953 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
4954 return hr;
4956 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
4957 item_size = get_type_size( desc->type, desc->typeDescription );
4958 else
4959 item_size = sizeof(void *);
4961 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
4962 for (;;)
4964 if (nb_items >= nb_allocated)
4966 SIZE_T old_size = nb_allocated * item_size, new_size = old_size * 2;
4967 if (!(buf = ws_realloc_zero( heap, buf, old_size, new_size )))
4968 return WS_E_QUOTA_EXCEEDED;
4969 nb_allocated *= 2;
4971 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
4972 desc->typeDescription, option, heap, buf + offset, item_size );
4973 if (hr == WS_E_INVALID_FORMAT) break;
4974 if (hr != S_OK)
4976 ws_free( heap, buf, nb_allocated * item_size );
4977 return hr;
4979 offset += item_size;
4980 nb_items++;
4983 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
4985 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
4987 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
4988 desc->itemRange->maxItemCount );
4989 ws_free( heap, buf, nb_allocated * item_size );
4990 return WS_E_INVALID_FORMAT;
4993 *count = nb_items;
4994 *ret = buf;
4996 return S_OK;
4999 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
5000 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
5002 HRESULT hr;
5003 if (reader->current == reader->last)
5005 BOOL found;
5006 if ((hr = read_to_startelement( reader, &found )) != S_OK) return S_OK;
5007 if (!found) return WS_E_INVALID_FORMAT;
5009 if ((hr = read_next_node( reader )) != S_OK) return hr;
5010 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
5012 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
5013 desc->typeDescription, option, heap, ret, size );
5016 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
5017 WS_HEAP *heap, char *buf, ULONG offset )
5019 char *ptr;
5020 WS_READ_OPTION option;
5021 ULONG size;
5022 HRESULT hr;
5024 if (!desc) return E_INVALIDARG;
5025 if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE|WS_FIELD_NILLABLE_ITEM))
5027 FIXME( "options %08x not supported\n", desc->options );
5028 return E_NOTIMPL;
5030 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
5032 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
5033 size = get_type_size( desc->type, desc->typeDescription );
5034 else
5035 size = sizeof(void *);
5037 ptr = buf + offset;
5038 switch (desc->mapping)
5040 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING:
5041 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
5042 return S_OK;
5044 case WS_ATTRIBUTE_FIELD_MAPPING:
5045 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
5046 desc->typeDescription, option, heap, ptr, size );
5047 break;
5049 case WS_ELEMENT_FIELD_MAPPING:
5050 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
5051 desc->typeDescription, option, heap, ptr, size );
5052 break;
5054 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
5056 ULONG count;
5057 hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, &count );
5058 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
5059 break;
5061 case WS_TEXT_FIELD_MAPPING:
5062 hr = read_type_text( reader, desc, option, heap, ptr, size );
5063 break;
5065 default:
5066 FIXME( "unhandled field mapping %u\n", desc->mapping );
5067 return E_NOTIMPL;
5070 if (hr == WS_E_INVALID_FORMAT)
5072 switch (option)
5074 case WS_READ_REQUIRED_VALUE:
5075 case WS_READ_REQUIRED_POINTER:
5076 return WS_E_INVALID_FORMAT;
5078 case WS_READ_NILLABLE_VALUE:
5079 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
5080 return S_OK;
5082 case WS_READ_OPTIONAL_POINTER:
5083 case WS_READ_NILLABLE_POINTER:
5084 *(void **)ptr = NULL;
5085 return S_OK;
5087 default:
5088 ERR( "unhandled option %u\n", option );
5089 return E_NOTIMPL;
5093 return hr;
5096 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
5097 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5098 const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
5099 WS_HEAP *heap, void *ret, ULONG size )
5101 ULONG i, offset;
5102 HRESULT hr;
5103 char *buf;
5105 if (!desc) return E_INVALIDARG;
5106 if (desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
5108 FIXME( "struct options %08x not supported\n",
5109 desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT );
5112 switch (option)
5114 case WS_READ_REQUIRED_POINTER:
5115 case WS_READ_OPTIONAL_POINTER:
5116 case WS_READ_NILLABLE_POINTER:
5117 if (size != sizeof(void *)) return E_INVALIDARG;
5118 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
5119 break;
5121 case WS_READ_REQUIRED_VALUE:
5122 case WS_READ_NILLABLE_VALUE:
5123 if (size != desc->size) return E_INVALIDARG;
5124 buf = ret;
5125 break;
5127 default:
5128 FIXME( "unhandled read option %u\n", option );
5129 return E_NOTIMPL;
5132 for (i = 0; i < desc->fieldCount; i++)
5134 offset = desc->fields[i]->offset;
5135 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf, offset )) != S_OK)
5136 break;
5139 switch (option)
5141 case WS_READ_REQUIRED_POINTER:
5142 if (hr != S_OK)
5144 ws_free( heap, buf, desc->size );
5145 return hr;
5147 *(char **)ret = buf;
5148 break;
5150 case WS_READ_OPTIONAL_POINTER:
5151 case WS_READ_NILLABLE_POINTER:
5152 if (is_nil_value( buf, desc->size ))
5154 ws_free( heap, buf, desc->size );
5155 buf = NULL;
5157 *(char **)ret = buf;
5158 break;
5160 case WS_READ_REQUIRED_VALUE:
5161 case WS_READ_NILLABLE_VALUE:
5162 if (hr != S_OK) return hr;
5163 break;
5165 default:
5166 ERR( "unhandled read option %u\n", option );
5167 return E_NOTIMPL;
5170 if (desc->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
5172 struct node *parent = find_parent( reader );
5173 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
5175 return S_OK;
5178 static HRESULT start_mapping( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
5179 const WS_XML_STRING *ns )
5181 switch (mapping)
5183 case WS_ELEMENT_TYPE_MAPPING:
5184 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
5185 return read_type_next_element_node( reader, localname, ns );
5187 case WS_ANY_ELEMENT_TYPE_MAPPING:
5188 case WS_ATTRIBUTE_TYPE_MAPPING:
5189 return S_OK;
5191 default:
5192 FIXME( "unhandled mapping %u\n", mapping );
5193 return E_NOTIMPL;
5197 static HRESULT read_type_endelement_node( struct reader *reader )
5199 const struct node *parent = find_parent( reader );
5200 HRESULT hr;
5202 for (;;)
5204 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
5205 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == parent)
5207 return S_OK;
5209 if (read_end_of_data( reader ) || !(parent->flags & NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT)) break;
5212 return WS_E_INVALID_FORMAT;
5215 static HRESULT end_mapping( struct reader *reader, WS_TYPE_MAPPING mapping )
5217 switch (mapping)
5219 case WS_ELEMENT_TYPE_MAPPING:
5220 return read_type_endelement_node( reader );
5222 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
5223 return read_type_next_node( reader );
5225 case WS_ATTRIBUTE_TYPE_MAPPING:
5226 default:
5227 return S_OK;
5231 static HRESULT is_nil_element( const WS_XML_ELEMENT_NODE *elem )
5233 static const WS_XML_STRING localname = {3, (BYTE *)"nil"};
5234 static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance"};
5235 ULONG i;
5237 for (i = 0; i < elem->attributeCount; i++)
5239 const WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)elem->attributes[i]->value;
5241 if (elem->attributes[i]->isXmlNs) continue;
5242 if (WsXmlStringEquals( elem->attributes[i]->localName, &localname, NULL ) == S_OK &&
5243 WsXmlStringEquals( elem->attributes[i]->ns, &ns, NULL ) == S_OK &&
5244 text->value.length == 4 && !memcmp( text->value.bytes, "true", 4 )) return TRUE;
5246 return FALSE;
5249 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
5250 const WS_XML_STRING *localname, const WS_XML_STRING *ns, const void *desc,
5251 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size )
5253 HRESULT hr;
5255 if ((hr = start_mapping( reader, mapping, localname, ns )) != S_OK) return hr;
5257 if (mapping == WS_ELEMENT_TYPE_MAPPING && is_nil_element( &reader->current->hdr ))
5259 if (option != WS_READ_NILLABLE_POINTER && option != WS_READ_NILLABLE_VALUE) return WS_E_INVALID_FORMAT;
5260 return end_mapping( reader, mapping );
5263 switch (type)
5265 case WS_BOOL_TYPE:
5266 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5267 return hr;
5268 break;
5270 case WS_INT8_TYPE:
5271 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5272 return hr;
5273 break;
5275 case WS_INT16_TYPE:
5276 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5277 return hr;
5278 break;
5280 case WS_INT32_TYPE:
5281 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5282 return hr;
5283 break;
5285 case WS_INT64_TYPE:
5286 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5287 return hr;
5288 break;
5290 case WS_UINT8_TYPE:
5291 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5292 return hr;
5293 break;
5295 case WS_UINT16_TYPE:
5296 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5297 return hr;
5298 break;
5300 case WS_UINT32_TYPE:
5301 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5302 return hr;
5303 break;
5305 case WS_UINT64_TYPE:
5306 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5307 return hr;
5308 break;
5310 case WS_DOUBLE_TYPE:
5311 if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5312 return hr;
5313 break;
5315 case WS_DATETIME_TYPE:
5316 if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5317 return hr;
5318 break;
5320 case WS_GUID_TYPE:
5321 if ((hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5322 return hr;
5323 break;
5325 case WS_WSZ_TYPE:
5326 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5327 return hr;
5328 break;
5330 case WS_BYTES_TYPE:
5331 if ((hr = read_type_bytes( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5332 return hr;
5333 break;
5335 case WS_STRUCT_TYPE:
5336 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5337 return hr;
5338 break;
5340 case WS_ENUM_TYPE:
5341 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5342 return hr;
5343 break;
5345 default:
5346 FIXME( "type %u not supported\n", type );
5347 return E_NOTIMPL;
5350 return end_mapping( reader, mapping );
5353 /**************************************************************************
5354 * WsReadType [webservices.@]
5356 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
5357 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
5358 ULONG size, WS_ERROR *error )
5360 struct reader *reader = (struct reader *)handle;
5361 HRESULT hr;
5363 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
5364 size, error );
5365 if (error) FIXME( "ignoring error parameter\n" );
5367 if (!reader || !value) return E_INVALIDARG;
5369 EnterCriticalSection( &reader->cs );
5371 if (reader->magic != READER_MAGIC)
5373 LeaveCriticalSection( &reader->cs );
5374 return E_INVALIDARG;
5377 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
5379 LeaveCriticalSection( &reader->cs );
5380 return hr;
5383 switch (mapping)
5385 case WS_ELEMENT_TYPE_MAPPING:
5386 hr = read_node( reader );
5387 break;
5389 default:
5390 break;
5393 if (hr == S_OK && !read_end_of_data( reader )) hr = WS_E_INVALID_FORMAT;
5395 LeaveCriticalSection( &reader->cs );
5396 return hr;
5399 HRESULT read_header( WS_XML_READER *handle, const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5400 WS_TYPE type, const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
5401 ULONG size )
5403 struct reader *reader = (struct reader *)handle;
5404 HRESULT hr;
5406 EnterCriticalSection( &reader->cs );
5408 if (reader->magic != READER_MAGIC)
5410 LeaveCriticalSection( &reader->cs );
5411 return E_INVALIDARG;
5414 hr = read_type( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, localname, ns, desc, option, heap,
5415 value, size );
5417 LeaveCriticalSection( &reader->cs );
5418 return hr;
5421 /**************************************************************************
5422 * WsReadElement [webservices.@]
5424 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
5425 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
5426 WS_ERROR *error )
5428 struct reader *reader = (struct reader *)handle;
5429 HRESULT hr;
5431 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
5432 if (error) FIXME( "ignoring error parameter\n" );
5434 if (!reader || !desc || !value) return E_INVALIDARG;
5436 EnterCriticalSection( &reader->cs );
5438 if (reader->magic != READER_MAGIC)
5440 LeaveCriticalSection( &reader->cs );
5441 return E_INVALIDARG;
5444 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
5445 desc->elementNs, desc->typeDescription, option, heap, value, size );
5447 LeaveCriticalSection( &reader->cs );
5448 return hr;
5451 /**************************************************************************
5452 * WsReadValue [webservices.@]
5454 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
5455 WS_ERROR *error )
5457 struct reader *reader = (struct reader *)handle;
5458 WS_TYPE type = map_value_type( value_type );
5459 HRESULT hr;
5461 TRACE( "%p %u %p %u %p\n", handle, type, value, size, error );
5462 if (error) FIXME( "ignoring error parameter\n" );
5464 if (!reader || !value || type == ~0u) return E_INVALIDARG;
5466 EnterCriticalSection( &reader->cs );
5468 if (reader->magic != READER_MAGIC)
5470 LeaveCriticalSection( &reader->cs );
5471 return E_INVALIDARG;
5474 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
5475 NULL, value, size );
5477 LeaveCriticalSection( &reader->cs );
5478 return hr;
5481 /**************************************************************************
5482 * WsReadAttribute [webservices.@]
5484 HRESULT WINAPI WsReadAttribute( WS_XML_READER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
5485 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
5486 WS_ERROR *error )
5488 struct reader *reader = (struct reader *)handle;
5489 HRESULT hr;
5491 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
5492 if (error) FIXME( "ignoring error parameter\n" );
5494 if (!reader || !desc || !value) return E_INVALIDARG;
5496 EnterCriticalSection( &reader->cs );
5498 if (reader->magic != READER_MAGIC)
5500 LeaveCriticalSection( &reader->cs );
5501 return E_INVALIDARG;
5504 if (!reader->input_type)
5506 LeaveCriticalSection( &reader->cs );
5507 return WS_E_INVALID_OPERATION;
5510 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->attributeLocalName,
5511 desc->attributeNs, desc->typeDescription, option, heap, value, size );
5513 LeaveCriticalSection( &reader->cs );
5514 return hr;
5517 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
5519 static const char bom[] = {0xef,0xbb,0xbf};
5520 const unsigned char *p = data;
5522 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
5523 (size > 2 && !(*offset = 0));
5526 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
5528 static const char bom[] = {0xff,0xfe};
5529 const unsigned char *p = data;
5531 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
5532 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
5535 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
5537 WS_CHARSET ret = 0;
5539 /* FIXME: parse xml declaration */
5541 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
5542 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
5543 else
5545 FIXME( "charset not recognized\n" );
5546 return 0;
5549 TRACE( "detected charset %u\n", ret );
5550 return ret;
5553 static void set_input_buffer( struct reader *reader, struct xmlbuf *buf, const unsigned char *data, ULONG size )
5555 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
5556 reader->input_buf = buf;
5557 reader->input_data = data;
5558 reader->input_size = size;
5560 reader->read_size = reader->input_size;
5561 reader->read_pos = 0;
5562 reader->read_bufptr = reader->input_data;
5564 reader->text_conv_offset = 0;
5567 /**************************************************************************
5568 * WsSetInput [webservices.@]
5570 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
5571 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
5572 ULONG count, WS_ERROR *error )
5574 struct reader *reader = (struct reader *)handle;
5575 struct node *node;
5576 ULONG i, offset = 0;
5577 HRESULT hr;
5579 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
5580 if (error) FIXME( "ignoring error parameter\n" );
5582 if (!reader) return E_INVALIDARG;
5584 EnterCriticalSection( &reader->cs );
5586 if (reader->magic != READER_MAGIC)
5588 LeaveCriticalSection( &reader->cs );
5589 return E_INVALIDARG;
5592 for (i = 0; i < count; i++)
5594 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
5595 properties[i].valueSize );
5596 if (hr != S_OK) goto done;
5599 if ((hr = init_reader( reader )) != S_OK) goto done;
5601 switch (encoding->encodingType)
5603 case WS_XML_READER_ENCODING_TYPE_TEXT:
5605 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
5606 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
5607 WS_CHARSET charset = text->charSet;
5609 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
5611 FIXME( "charset detection on input type %u not supported\n", input->inputType );
5612 hr = E_NOTIMPL;
5613 goto done;
5616 if (charset == WS_CHARSET_AUTO)
5617 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
5619 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
5620 &charset, sizeof(charset) );
5621 if (hr != S_OK) goto done;
5623 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
5624 break;
5626 case WS_XML_READER_ENCODING_TYPE_BINARY:
5628 WS_XML_READER_BINARY_ENCODING *bin = (WS_XML_READER_BINARY_ENCODING *)encoding;
5629 reader->input_enc = WS_XML_READER_ENCODING_TYPE_BINARY;
5630 reader->dict_static = bin->staticDictionary ? bin->staticDictionary : &dict_builtin_static;
5631 reader->dict = bin->dynamicDictionary ? bin->dynamicDictionary : &dict_builtin;
5632 break;
5634 default:
5635 FIXME( "encoding type %u not supported\n", encoding->encodingType );
5636 hr = E_NOTIMPL;
5637 goto done;
5640 switch (input->inputType)
5642 case WS_XML_READER_INPUT_TYPE_BUFFER:
5644 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
5645 set_input_buffer( reader, NULL, (const unsigned char *)buf->encodedData + offset,
5646 buf->encodedDataSize - offset );
5647 break;
5649 default:
5650 FIXME( "input type %u not supported\n", input->inputType );
5651 hr = E_NOTIMPL;
5652 goto done;
5655 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
5656 else read_insert_bof( reader, node );
5658 done:
5659 LeaveCriticalSection( &reader->cs );
5660 return hr;
5663 /**************************************************************************
5664 * WsSetInputToBuffer [webservices.@]
5666 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
5667 const WS_XML_READER_PROPERTY *properties, ULONG count,
5668 WS_ERROR *error )
5670 struct reader *reader = (struct reader *)handle;
5671 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
5672 WS_CHARSET charset;
5673 struct node *node;
5674 ULONG i, offset = 0;
5675 HRESULT hr;
5677 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
5678 if (error) FIXME( "ignoring error parameter\n" );
5680 if (!reader || !xmlbuf) return E_INVALIDARG;
5682 EnterCriticalSection( &reader->cs );
5684 if (reader->magic != READER_MAGIC)
5686 LeaveCriticalSection( &reader->cs );
5687 return E_INVALIDARG;
5690 for (i = 0; i < count; i++)
5692 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
5693 properties[i].valueSize );
5694 if (hr != S_OK) goto done;
5697 if ((hr = init_reader( reader )) != S_OK) goto done;
5699 charset = detect_charset( xmlbuf->bytes.bytes, xmlbuf->bytes.length, &offset );
5700 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset,
5701 sizeof(charset) );
5702 if (hr != S_OK) goto done;
5704 set_input_buffer( reader, xmlbuf, xmlbuf->bytes.bytes + offset, xmlbuf->bytes.length - offset );
5705 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
5706 else read_insert_bof( reader, node );
5708 done:
5709 LeaveCriticalSection( &reader->cs );
5710 return hr;
5713 /**************************************************************************
5714 * WsGetReaderPosition [webservices.@]
5716 HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
5718 struct reader *reader = (struct reader *)handle;
5720 TRACE( "%p %p %p\n", handle, pos, error );
5721 if (error) FIXME( "ignoring error parameter\n" );
5723 if (!reader || !pos) return E_INVALIDARG;
5725 EnterCriticalSection( &reader->cs );
5727 if (reader->magic != READER_MAGIC)
5729 LeaveCriticalSection( &reader->cs );
5730 return E_INVALIDARG;
5733 if (!reader->input_buf)
5735 LeaveCriticalSection( &reader->cs );
5736 return WS_E_INVALID_OPERATION;
5739 pos->buffer = (WS_XML_BUFFER *)reader->input_buf;
5740 pos->node = reader->current;
5742 LeaveCriticalSection( &reader->cs );
5743 return S_OK;
5746 /**************************************************************************
5747 * WsSetReaderPosition [webservices.@]
5749 HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
5751 struct reader *reader = (struct reader *)handle;
5753 TRACE( "%p %p %p\n", handle, pos, error );
5754 if (error) FIXME( "ignoring error parameter\n" );
5756 if (!reader || !pos) return E_INVALIDARG;
5758 EnterCriticalSection( &reader->cs );
5760 if (reader->magic != READER_MAGIC || (struct xmlbuf *)pos->buffer != reader->input_buf)
5762 LeaveCriticalSection( &reader->cs );
5763 return E_INVALIDARG;
5766 if (!reader->input_buf)
5768 LeaveCriticalSection( &reader->cs );
5769 return WS_E_INVALID_OPERATION;
5772 reader->current = pos->node;
5774 LeaveCriticalSection( &reader->cs );
5775 return S_OK;
5778 static HRESULT utf8_to_base64( const WS_XML_UTF8_TEXT *utf8, WS_XML_BASE64_TEXT *base64 )
5780 if (utf8->value.length % 4) return WS_E_INVALID_FORMAT;
5781 if (!(base64->bytes = heap_alloc( utf8->value.length * 3 / 4 ))) return E_OUTOFMEMORY;
5782 base64->length = decode_base64( utf8->value.bytes, utf8->value.length, base64->bytes );
5783 return S_OK;
5786 /**************************************************************************
5787 * WsReadBytes [webservices.@]
5789 HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
5791 struct reader *reader = (struct reader *)handle;
5792 HRESULT hr;
5794 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
5795 if (error) FIXME( "ignoring error parameter\n" );
5797 if (!reader) return E_INVALIDARG;
5799 EnterCriticalSection( &reader->cs );
5801 if (reader->magic != READER_MAGIC)
5803 LeaveCriticalSection( &reader->cs );
5804 return E_INVALIDARG;
5807 if (!reader->input_type)
5809 LeaveCriticalSection( &reader->cs );
5810 return WS_E_INVALID_OPERATION;
5813 if (!count)
5815 LeaveCriticalSection( &reader->cs );
5816 return E_INVALIDARG;
5819 *count = 0;
5820 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
5822 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
5823 WS_XML_BASE64_TEXT base64;
5825 if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK)
5827 LeaveCriticalSection( &reader->cs );
5828 return hr;
5830 if (reader->text_conv_offset == base64.length)
5832 heap_free( base64.bytes );
5833 hr = read_node( reader );
5834 LeaveCriticalSection( &reader->cs );
5835 return hr;
5837 *count = min( base64.length - reader->text_conv_offset, max_count );
5838 memcpy( bytes, base64.bytes + reader->text_conv_offset, *count );
5839 reader->text_conv_offset += *count;
5840 heap_free( base64.bytes );
5843 LeaveCriticalSection( &reader->cs );
5844 return S_OK;
5847 static HRESULT utf8_to_utf16( const WS_XML_UTF8_TEXT *utf8, WS_XML_UTF16_TEXT *utf16 )
5849 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
5850 if (!(utf16->bytes = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
5851 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, (WCHAR *)utf16->bytes, len );
5852 utf16->byteCount = len * sizeof(WCHAR);
5853 return S_OK;
5856 /**************************************************************************
5857 * WsReadChars [webservices.@]
5859 HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count, ULONG *count, WS_ERROR *error )
5861 struct reader *reader = (struct reader *)handle;
5863 TRACE( "%p %p %u %p %p\n", handle, chars, max_count, count, error );
5864 if (error) FIXME( "ignoring error parameter\n" );
5866 if (!reader) return E_INVALIDARG;
5868 EnterCriticalSection( &reader->cs );
5870 if (reader->magic != READER_MAGIC)
5872 LeaveCriticalSection( &reader->cs );
5873 return E_INVALIDARG;
5876 if (!reader->input_type)
5878 LeaveCriticalSection( &reader->cs );
5879 return WS_E_INVALID_OPERATION;
5882 if (!count)
5884 LeaveCriticalSection( &reader->cs );
5885 return E_INVALIDARG;
5888 *count = 0;
5889 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && chars)
5891 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
5892 WS_XML_UTF16_TEXT utf16;
5893 HRESULT hr;
5895 if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK)
5897 LeaveCriticalSection( &reader->cs );
5898 return hr;
5900 if (reader->text_conv_offset == utf16.byteCount / sizeof(WCHAR))
5902 heap_free( utf16.bytes );
5903 hr = read_node( reader );
5904 LeaveCriticalSection( &reader->cs );
5905 return hr;
5907 *count = min( utf16.byteCount / sizeof(WCHAR) - reader->text_conv_offset, max_count );
5908 memcpy( chars, utf16.bytes + reader->text_conv_offset * sizeof(WCHAR), *count * sizeof(WCHAR) );
5909 reader->text_conv_offset += *count;
5910 heap_free( utf16.bytes );
5913 LeaveCriticalSection( &reader->cs );
5914 return S_OK;
5917 /**************************************************************************
5918 * WsReadCharsUtf8 [webservices.@]
5920 HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
5922 struct reader *reader = (struct reader *)handle;
5923 HRESULT hr;
5925 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
5926 if (error) FIXME( "ignoring error parameter\n" );
5928 if (!reader) return E_INVALIDARG;
5930 EnterCriticalSection( &reader->cs );
5932 if (reader->magic != READER_MAGIC)
5934 LeaveCriticalSection( &reader->cs );
5935 return E_INVALIDARG;
5938 if (!reader->input_type)
5940 LeaveCriticalSection( &reader->cs );
5941 return WS_E_INVALID_OPERATION;
5944 if (!count)
5946 LeaveCriticalSection( &reader->cs );
5947 return E_INVALIDARG;
5950 *count = 0;
5951 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
5953 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
5954 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
5956 if (reader->text_conv_offset == utf8->value.length)
5958 hr = read_node( reader );
5959 LeaveCriticalSection( &reader->cs );
5960 return hr;
5962 *count = min( utf8->value.length - reader->text_conv_offset, max_count );
5963 memcpy( bytes, utf8->value.bytes + reader->text_conv_offset, *count );
5964 reader->text_conv_offset += *count;
5967 LeaveCriticalSection( &reader->cs );
5968 return S_OK;
5971 static HRESULT move_to_element( struct reader *reader )
5973 HRESULT hr;
5974 if (node_type( reader->current ) == WS_XML_NODE_TYPE_BOF &&
5975 (hr = read_move_to( reader, WS_MOVE_TO_CHILD_NODE, NULL )) != S_OK) return hr;
5976 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return E_FAIL;
5977 return S_OK;
5980 static HRESULT copy_tree( struct reader *reader, WS_XML_WRITER *writer )
5982 const struct node *node, *parent;
5983 BOOL done = FALSE;
5984 HRESULT hr;
5986 if ((hr = move_to_element( reader )) != S_OK) return hr;
5987 parent = reader->current;
5988 for (;;)
5990 node = reader->current;
5991 if ((hr = WsWriteNode( writer, (const WS_XML_NODE *)node, NULL )) != S_OK) break;
5992 if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT && node->parent == parent) done = TRUE;
5993 if ((hr = read_next_node( reader )) != S_OK || done) break;
5995 return hr;
5998 /**************************************************************************
5999 * WsReadXmlBuffer [webservices.@]
6001 HRESULT WINAPI WsReadXmlBuffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret, WS_ERROR *error )
6003 struct reader *reader = (struct reader *)handle;
6004 WS_XML_WRITER *writer = NULL;
6005 WS_XML_BUFFER *buffer;
6006 HRESULT hr;
6008 TRACE( "%p %p %p %p\n", handle, heap, ret, error );
6009 if (error) FIXME( "ignoring error parameter\n" );
6011 if (!reader || !heap) return E_INVALIDARG;
6012 if (!ret) return E_FAIL;
6014 EnterCriticalSection( &reader->cs );
6016 if (reader->magic != READER_MAGIC)
6018 LeaveCriticalSection( &reader->cs );
6019 return E_INVALIDARG;
6022 if (!reader->input_type)
6024 LeaveCriticalSection( &reader->cs );
6025 return WS_E_INVALID_OPERATION;
6028 if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
6029 if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL )) != S_OK) goto done;
6030 if ((hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL )) != S_OK) goto done;
6031 if ((hr = copy_tree( reader, writer )) == S_OK) *ret = buffer;
6033 done:
6034 if (hr != S_OK) free_xmlbuf( (struct xmlbuf *)buffer );
6035 WsFreeWriter( writer );
6036 LeaveCriticalSection( &reader->cs );
6037 return hr;
6040 HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *desc, USHORT index, const WS_FIELD_DESCRIPTION **ret )
6042 if (index >= desc->fieldCount) return E_INVALIDARG;
6043 *ret = desc->fields[index];
6044 return S_OK;
6047 static ULONG get_field_size( const WS_FIELD_DESCRIPTION *desc )
6049 WS_READ_OPTION option;
6050 ULONG size;
6052 switch ((option = get_field_read_option( desc->type, desc->options )))
6054 case WS_READ_REQUIRED_POINTER:
6055 case WS_READ_OPTIONAL_POINTER:
6056 case WS_READ_NILLABLE_POINTER:
6057 size = sizeof(void *);
6058 break;
6060 case WS_READ_REQUIRED_VALUE:
6061 case WS_READ_NILLABLE_VALUE:
6062 size = get_type_size( desc->type, desc->typeDescription );
6063 break;
6065 default:
6066 WARN( "unhandled option %u\n", option );
6067 return 0;
6070 return size;
6073 static HRESULT read_param( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, void *ret )
6075 if (!ret && !(ret = ws_alloc_zero( heap, get_field_size(desc) ))) return WS_E_QUOTA_EXCEEDED;
6076 return read_type_struct_field( reader, desc, heap, ret, 0 );
6079 static HRESULT read_param_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
6080 void **ret, ULONG *count )
6082 if (!ret && !(ret = ws_alloc_zero( heap, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED;
6083 return read_type_repeating_element( reader, desc, heap, ret, count );
6086 static void set_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, ULONG index, ULONG len,
6087 const void **args )
6089 ULONG i, *ptr;
6090 for (i = 0; i < count; i++)
6092 if (params[i].outputMessageIndex != index || params[i].parameterType != WS_PARAMETER_TYPE_ARRAY_COUNT)
6093 continue;
6094 if ((ptr = *(ULONG **)args[i])) *ptr = len;
6095 break;
6099 HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEMENT_DESCRIPTION *desc,
6100 const WS_PARAMETER_DESCRIPTION *params, ULONG count, const void **args )
6102 struct reader *reader = (struct reader *)handle;
6103 const WS_STRUCT_DESCRIPTION *desc_struct;
6104 const WS_FIELD_DESCRIPTION *desc_field;
6105 ULONG i, len;
6106 HRESULT hr;
6108 if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG;
6110 EnterCriticalSection( &reader->cs );
6112 if (reader->magic != READER_MAGIC)
6114 LeaveCriticalSection( &reader->cs );
6115 return E_INVALIDARG;
6118 if ((hr = start_mapping( reader, WS_ELEMENT_TYPE_MAPPING, desc->elementLocalName, desc->elementNs )) != S_OK)
6119 goto done;
6121 for (i = 0; i < count; i++)
6123 if (params[i].outputMessageIndex == INVALID_PARAMETER_INDEX) continue;
6124 if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES)
6126 FIXME( "messages type not supported\n" );
6127 hr = E_NOTIMPL;
6128 goto done;
6130 if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) goto done;
6131 if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL)
6133 void *ptr = *(void **)args[i];
6134 if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) goto done;
6136 else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY)
6138 void **ptr = *(void ***)args[i];
6139 if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) goto done;
6140 set_array_len( params, count, params[i].outputMessageIndex, len, args );
6144 if (desc_struct->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6146 struct node *parent = find_parent( reader );
6147 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
6150 hr = end_mapping( reader, WS_ELEMENT_TYPE_MAPPING );
6152 done:
6153 LeaveCriticalSection( &reader->cs );
6154 return hr;