webservices: Add support for union types in the writer.
[wine.git] / dlls / webservices / reader.c
blob254efb9f0e0ab5fb946cd097a9b9a4c84ec8d77c
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_CHARSET input_charset;
369 WS_XML_READER_INPUT_TYPE input_type;
370 struct xmlbuf *input_buf;
371 const unsigned char *input_data;
372 ULONG input_size;
373 ULONG text_conv_offset;
374 const WS_XML_DICTIONARY *dict_static;
375 WS_XML_DICTIONARY *dict;
376 ULONG prop_count;
377 struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])];
380 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
382 static struct reader *alloc_reader(void)
384 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
385 struct reader *ret;
386 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
388 if (!(ret = heap_alloc_zero( size ))) return NULL;
389 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
391 heap_free( ret );
392 return NULL;
394 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
396 ret->magic = READER_MAGIC;
397 InitializeCriticalSection( &ret->cs );
398 ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": reader.cs");
400 prop_init( reader_props, count, ret->prop, &ret[1] );
401 ret->prop_count = count;
402 return ret;
405 static void clear_prefixes( struct prefix *prefixes, ULONG count )
407 ULONG i;
408 for (i = 0; i < count; i++)
410 free_xml_string( prefixes[i].str );
411 prefixes[i].str = NULL;
412 free_xml_string( prefixes[i].ns );
413 prefixes[i].ns = NULL;
417 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
419 if (str)
421 free_xml_string( prefix->str );
422 if (!(prefix->str = dup_xml_string( str ))) return E_OUTOFMEMORY;
424 if (prefix->ns) free_xml_string( prefix->ns );
425 if (!(prefix->ns = dup_xml_string( ns ))) return E_OUTOFMEMORY;
426 return S_OK;
429 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
431 ULONG i;
432 HRESULT hr;
434 for (i = 0; i < reader->nb_prefixes; i++)
436 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
437 return set_prefix( &reader->prefixes[i], NULL, ns );
439 if (i >= reader->nb_prefixes_allocated)
441 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
442 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
443 if (!tmp) return E_OUTOFMEMORY;
444 reader->prefixes = tmp;
445 reader->nb_prefixes_allocated *= 2;
447 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
448 reader->nb_prefixes++;
449 return S_OK;
452 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
454 ULONG i;
455 for (i = 0; i < reader->nb_prefixes; i++)
457 if (WsXmlStringEquals( prefix, reader->prefixes[i].str, NULL ) == S_OK)
458 return reader->prefixes[i].ns;
460 return NULL;
463 static void read_insert_eof( struct reader *reader, struct node *eof )
465 if (!reader->root) reader->root = eof;
466 else
468 eof->parent = reader->root;
469 list_add_tail( &reader->root->children, &eof->entry );
471 reader->current = reader->last = eof;
474 static void read_insert_bof( struct reader *reader, struct node *bof )
476 reader->root->parent = bof;
477 list_add_tail( &bof->children, &reader->root->entry );
478 reader->current = reader->last = reader->root = bof;
481 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
483 node->parent = parent;
484 list_add_before( list_tail( &parent->children ), &node->entry );
485 reader->current = reader->last = node;
488 static void free_reader( struct reader *reader )
490 destroy_nodes( reader->root );
491 clear_prefixes( reader->prefixes, reader->nb_prefixes );
492 heap_free( reader->prefixes );
493 reader->cs.DebugInfo->Spare[0] = 0;
494 DeleteCriticalSection( &reader->cs );
495 heap_free( reader );
498 static HRESULT init_reader( struct reader *reader )
500 static const WS_XML_STRING empty = {0, NULL};
501 struct node *node;
502 HRESULT hr;
504 reader->state = READER_STATE_INITIAL;
505 destroy_nodes( reader->root );
506 reader->root = reader->current = NULL;
507 reader->current_attr = 0;
508 clear_prefixes( reader->prefixes, reader->nb_prefixes );
509 reader->nb_prefixes = 1;
510 if ((hr = bind_prefix( reader, &empty, &empty )) != S_OK) return hr;
512 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
513 read_insert_eof( reader, node );
514 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
515 reader->input_charset = WS_CHARSET_UTF8;
516 reader->dict_static = NULL;
517 reader->dict = NULL;
518 return S_OK;
521 /**************************************************************************
522 * WsCreateReader [webservices.@]
524 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
525 WS_XML_READER **handle, WS_ERROR *error )
527 struct reader *reader;
528 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
529 BOOL read_decl = TRUE;
530 HRESULT hr;
532 TRACE( "%p %u %p %p\n", properties, count, handle, error );
533 if (error) FIXME( "ignoring error parameter\n" );
535 if (!handle) return E_INVALIDARG;
536 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
538 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
539 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
540 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
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 static HRESULT get_charset( struct reader *reader, void *buf, ULONG size )
724 if (!buf || size != sizeof(reader->input_charset)) return E_INVALIDARG;
725 if (!reader->input_charset) return WS_E_INVALID_FORMAT;
726 *(WS_CHARSET *)buf = reader->input_charset;
727 return S_OK;
730 /**************************************************************************
731 * WsGetReaderProperty [webservices.@]
733 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
734 void *buf, ULONG size, WS_ERROR *error )
736 struct reader *reader = (struct reader *)handle;
737 HRESULT hr;
739 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
740 if (error) FIXME( "ignoring error parameter\n" );
742 if (!reader) return E_INVALIDARG;
744 EnterCriticalSection( &reader->cs );
746 if (reader->magic != READER_MAGIC)
748 LeaveCriticalSection( &reader->cs );
749 return E_INVALIDARG;
752 if (!reader->input_type)
754 LeaveCriticalSection( &reader->cs );
755 return WS_E_INVALID_OPERATION;
758 if (id == WS_XML_READER_PROPERTY_CHARSET) hr = get_charset( reader, buf, size );
759 else hr = prop_get( reader->prop, reader->prop_count, id, buf, size );
761 LeaveCriticalSection( &reader->cs );
762 return hr;
765 /**************************************************************************
766 * WsGetXmlAttribute [webservices.@]
768 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
769 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
771 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
772 return E_NOTIMPL;
775 WS_XML_UTF8_TEXT *alloc_utf8_text( const BYTE *data, ULONG len )
777 WS_XML_UTF8_TEXT *ret;
779 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
780 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
781 ret->value.length = len;
782 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
783 ret->value.dictionary = NULL;
784 ret->value.id = 0;
785 if (data) memcpy( ret->value.bytes, data, len );
786 return ret;
789 static WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *data, ULONG len )
791 WS_XML_BASE64_TEXT *ret;
793 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
794 ret->text.textType = WS_XML_TEXT_TYPE_BASE64;
795 ret->length = len;
796 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
797 if (data) memcpy( ret->bytes, data, len );
798 return ret;
801 static inline BOOL read_end_of_data( struct reader *reader )
803 return reader->read_pos >= reader->read_size;
806 static inline const unsigned char *read_current_ptr( struct reader *reader )
808 return &reader->read_bufptr[reader->read_pos];
811 static inline HRESULT read_peek( struct reader *reader, unsigned char *byte )
813 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
814 *byte = reader->read_bufptr[reader->read_pos];
815 return S_OK;
818 static inline HRESULT read_byte( struct reader *reader, unsigned char *byte )
820 if (reader->read_pos >= reader->read_size) return WS_E_INVALID_FORMAT;
821 *byte = reader->read_bufptr[reader->read_pos++];
822 return S_OK;
825 static inline HRESULT read_bytes( struct reader *reader, unsigned char *bytes, unsigned int len )
827 if (reader->read_pos + len > reader->read_size) return WS_E_INVALID_FORMAT;
828 memcpy( bytes, reader->read_bufptr + reader->read_pos, len );
829 reader->read_pos += len;
830 return S_OK;
833 /* UTF-8 support based on libs/wine/utf8.c */
835 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
836 static const char utf8_length[128] =
838 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
839 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
840 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
841 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
842 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
843 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
844 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
845 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
848 /* first byte mask depending on UTF-8 sequence length */
849 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
851 /* minimum Unicode value depending on UTF-8 sequence length */
852 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
854 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
856 unsigned int len, res;
857 unsigned char ch = reader->read_bufptr[reader->read_pos];
858 const unsigned char *end;
860 if (reader->read_pos >= reader->read_size) return 0;
862 if (ch < 0x80)
864 *skip = 1;
865 return ch;
867 len = utf8_length[ch - 0x80];
868 if (reader->read_pos + len >= reader->read_size) return 0;
869 end = reader->read_bufptr + reader->read_pos + len + 1;
870 res = ch & utf8_mask[len];
872 switch (len)
874 case 3:
875 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
876 res = (res << 6) | ch;
877 case 2:
878 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
879 res = (res << 6) | ch;
880 case 1:
881 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
882 res = (res << 6) | ch;
883 if (res < utf8_minval[len]) break;
884 *skip = len + 1;
885 return res;
888 return 0;
891 static inline void read_skip( struct reader *reader, unsigned int count )
893 if (reader->read_pos + count > reader->read_size) return;
894 reader->read_pos += count;
897 static inline void read_rewind( struct reader *reader, unsigned int count )
899 reader->read_pos -= count;
902 static inline BOOL read_isnamechar( unsigned int ch )
904 /* FIXME: incomplete */
905 return (ch >= 'A' && ch <= 'Z') ||
906 (ch >= 'a' && ch <= 'z') ||
907 (ch >= '0' && ch <= '9') ||
908 ch == '_' || ch == '-' || ch == '.' || ch == ':';
911 static inline BOOL read_isspace( unsigned int ch )
913 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
916 static inline void read_skip_whitespace( struct reader *reader )
918 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
919 reader->read_pos++;
922 static inline int read_cmp( struct reader *reader, const char *str, int len )
924 const unsigned char *ptr = read_current_ptr( reader );
926 if (len < 0) len = strlen( str );
927 if (reader->read_pos + len > reader->read_size) return -1;
928 while (len--)
930 if (*str != *ptr) return *ptr - *str;
931 str++; ptr++;
933 return 0;
936 static HRESULT read_xmldecl( struct reader *reader )
938 if (!reader->read_size) return WS_E_INVALID_FORMAT;
940 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
942 reader->state = READER_STATE_BOF;
943 return S_OK;
945 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
946 read_skip( reader, 6 );
948 /* FIXME: parse attributes */
949 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
950 reader->read_pos++;
952 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
953 read_skip( reader, 2 );
955 reader->state = READER_STATE_BOF;
956 return S_OK;
959 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
961 if (elem->attributeCount)
963 WS_XML_ATTRIBUTE **tmp;
964 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
965 return E_OUTOFMEMORY;
966 elem->attributes = tmp;
968 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
969 elem->attributes[elem->attributeCount++] = attr;
970 return S_OK;
973 static inline void init_xml_string( BYTE *bytes, ULONG len, WS_XML_STRING *str )
975 str->length = len;
976 str->bytes = bytes;
977 str->dictionary = NULL;
978 str->id = 0;
981 static HRESULT split_qname( const BYTE *str, ULONG len, WS_XML_STRING *prefix, WS_XML_STRING *localname )
983 BYTE *prefix_bytes = NULL, *localname_bytes = (BYTE *)str, *ptr = (BYTE *)str;
984 ULONG prefix_len = 0, localname_len = len;
986 while (len--)
988 if (*ptr == ':')
990 if (ptr == str) return WS_E_INVALID_FORMAT;
991 prefix_bytes = (BYTE *)str;
992 prefix_len = ptr - str;
993 localname_bytes = ptr + 1;
994 localname_len = len;
995 break;
997 ptr++;
999 if (!localname_len) return WS_E_INVALID_FORMAT;
1001 init_xml_string( prefix_bytes, prefix_len, prefix );
1002 init_xml_string( localname_bytes, localname_len, localname );
1003 return S_OK;
1006 static HRESULT parse_qname( const BYTE *str, ULONG len, WS_XML_STRING **prefix_ret, WS_XML_STRING **localname_ret )
1008 WS_XML_STRING prefix, localname;
1009 HRESULT hr;
1011 if ((hr = split_qname( str, len, &prefix, &localname )) != S_OK) return hr;
1012 if (!(*prefix_ret = alloc_xml_string( NULL, prefix.length ))) return E_OUTOFMEMORY;
1013 if (!(*localname_ret = dup_xml_string( &localname )))
1015 free_xml_string( *prefix_ret );
1016 return E_OUTOFMEMORY;
1018 memcpy( (*prefix_ret)->bytes, prefix.bytes, prefix.length );
1019 if (prefix.length && add_xml_string( *prefix_ret ) != S_OK) WARN( "prefix not added to dictionary\n" );
1020 return S_OK;
1023 static int codepoint_to_utf8( int cp, unsigned char *dst )
1025 if (!cp) return -1;
1026 if (cp < 0x80)
1028 *dst = cp;
1029 return 1;
1031 if (cp < 0x800)
1033 dst[1] = 0x80 | (cp & 0x3f);
1034 cp >>= 6;
1035 dst[0] = 0xc0 | cp;
1036 return 2;
1038 if ((cp >= 0xd800 && cp <= 0xdfff) || cp == 0xfffe || cp == 0xffff) return -1;
1039 if (cp < 0x10000)
1041 dst[2] = 0x80 | (cp & 0x3f);
1042 cp >>= 6;
1043 dst[1] = 0x80 | (cp & 0x3f);
1044 cp >>= 6;
1045 dst[0] = 0xe0 | cp;
1046 return 3;
1048 if (cp >= 0x110000) return -1;
1049 dst[3] = 0x80 | (cp & 0x3f);
1050 cp >>= 6;
1051 dst[2] = 0x80 | (cp & 0x3f);
1052 cp >>= 6;
1053 dst[1] = 0x80 | (cp & 0x3f);
1054 cp >>= 6;
1055 dst[0] = 0xf0 | cp;
1056 return 4;
1059 static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char *ret, ULONG *ret_len )
1061 const unsigned char *p = str;
1062 unsigned char *q = ret;
1064 *ret_len = 0;
1065 while (len)
1067 if (*p == '&')
1069 p++; len--;
1070 if (!len) return WS_E_INVALID_FORMAT;
1072 if (len >= 3 && !memcmp( p, "lt;", 3 ))
1074 *q++ = '<';
1075 p += 3;
1076 len -= 3;
1078 else if (len >= 3 && !memcmp( p, "gt;", 3 ))
1080 *q++ = '>';
1081 p += 3;
1082 len -= 3;
1084 else if (len >= 5 && !memcmp( p, "quot;", 5 ))
1086 *q++ = '"';
1087 p += 5;
1088 len -= 5;
1090 else if (len >= 4 && !memcmp( p, "amp;", 4 ))
1092 *q++ = '&';
1093 p += 4;
1094 len -= 4;
1096 else if (len >= 5 && !memcmp( p, "apos;", 5 ))
1098 *q++ = '\'';
1099 p += 5;
1100 len -= 5;
1102 else if (*p == '#')
1104 ULONG start, nb_digits, i;
1105 int len_utf8, cp = 0;
1107 p++; len--;
1108 if (!len) return WS_E_INVALID_FORMAT;
1109 if (*p == 'x')
1111 p++; len--;
1113 start = len;
1114 while (len && isxdigit( *p )) { p++; len--; };
1115 if (!len) return WS_E_INVALID_FORMAT;
1117 p -= nb_digits = start - len;
1118 if (!nb_digits || nb_digits > 6 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1119 for (i = 0; i < nb_digits; i++)
1121 cp *= 16;
1122 if (*p >= '0' && *p <= '9') cp += *p - '0';
1123 else if (*p >= 'a' && *p <= 'f') cp += *p - 'a' + 10;
1124 else cp += *p - 'A' + 10;
1125 p++;
1128 else if (isdigit( *p ))
1130 while (len && *p == '0') { p++; len--; };
1131 if (!len) return WS_E_INVALID_FORMAT;
1133 start = len;
1134 while (len && isdigit( *p )) { p++; len--; };
1135 if (!len) return WS_E_INVALID_FORMAT;
1137 p -= nb_digits = start - len;
1138 if (!nb_digits || nb_digits > 7 || p[nb_digits] != ';') return WS_E_INVALID_FORMAT;
1139 for (i = 0; i < nb_digits; i++)
1141 cp *= 10;
1142 cp += *p - '0';
1143 p++;
1146 else return WS_E_INVALID_FORMAT;
1147 p++; len--;
1148 if ((len_utf8 = codepoint_to_utf8( cp, q )) < 0) return WS_E_INVALID_FORMAT;
1149 *ret_len += len_utf8;
1150 q += len_utf8;
1151 continue;
1153 else return WS_E_INVALID_FORMAT;
1155 else
1157 *q++ = *p++;
1158 len--;
1160 *ret_len += 1;
1162 return S_OK;
1165 static HRESULT read_attribute_value_text( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1167 WS_XML_UTF8_TEXT *utf8 = NULL;
1168 unsigned int len, ch, skip, quote;
1169 const unsigned char *start;
1170 HRESULT hr = E_OUTOFMEMORY;
1172 read_skip_whitespace( reader );
1173 if (read_cmp( reader, "=", 1 )) return WS_E_INVALID_FORMAT;
1174 read_skip( reader, 1 );
1176 read_skip_whitespace( reader );
1177 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) return WS_E_INVALID_FORMAT;
1178 quote = read_utf8_char( reader, &skip );
1179 read_skip( reader, 1 );
1181 len = 0;
1182 start = read_current_ptr( reader );
1183 for (;;)
1185 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1186 if (ch == quote) break;
1187 read_skip( reader, skip );
1188 len += skip;
1190 read_skip( reader, 1 );
1192 if (attr->isXmlNs)
1194 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1195 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1196 if (!(utf8 = alloc_utf8_text( NULL, 0 )))
1198 hr = E_OUTOFMEMORY;
1199 goto error;
1202 else
1204 if (!(utf8 = alloc_utf8_text( NULL, len ))) goto error;
1205 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK) goto error;
1208 attr->value = &utf8->text;
1209 attr->singleQuote = (quote == '\'');
1210 return S_OK;
1212 error:
1213 heap_free( utf8 );
1214 return hr;
1217 static inline BOOL is_text_type( unsigned char type )
1219 return (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT);
1222 static HRESULT read_int31( struct reader *reader, ULONG *len )
1224 unsigned char byte;
1225 HRESULT hr;
1227 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1228 *len = byte & 0x7f;
1229 if (!(byte & 0x80)) return S_OK;
1231 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1232 *len += (byte & 0x7f) << 7;
1233 if (!(byte & 0x80)) return S_OK;
1235 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1236 *len += (byte & 0x7f) << 14;
1237 if (!(byte & 0x80)) return S_OK;
1239 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1240 *len += (byte & 0x7f) << 21;
1241 if (!(byte & 0x80)) return S_OK;
1243 if ((hr = read_byte( reader, &byte )) != S_OK) return hr;
1244 *len += (byte & 0x07) << 28;
1245 return S_OK;
1248 static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
1250 ULONG len;
1251 HRESULT hr;
1252 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
1253 if (!(*str = alloc_xml_string( NULL, len ))) return E_OUTOFMEMORY;
1254 if ((hr = read_bytes( reader, (*str)->bytes, len )) == S_OK)
1256 if (add_xml_string( *str ) != S_OK) WARN( "string not added to dictionary\n" );
1257 return S_OK;
1259 free_xml_string( *str );
1260 return hr;
1263 static HRESULT read_dict_string( struct reader *reader, WS_XML_STRING **str )
1265 const WS_XML_DICTIONARY *dict;
1266 HRESULT hr;
1267 ULONG id;
1269 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1270 dict = (id & 1) ? reader->dict : reader->dict_static;
1271 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1272 if (!(*str = alloc_xml_string( NULL, 0 ))) return E_OUTOFMEMORY;
1273 *(*str) = dict->strings[id];
1274 return S_OK;
1277 static HRESULT read_datetime( struct reader *reader, WS_DATETIME *ret )
1279 UINT64 val;
1280 HRESULT hr;
1282 if ((hr = read_bytes( reader, (unsigned char *)&val, sizeof(val) )) != S_OK) return hr;
1284 if ((val & 0x03) == 1) ret->format = WS_DATETIME_FORMAT_UTC;
1285 else if ((val & 0x03) == 2) ret->format = WS_DATETIME_FORMAT_LOCAL;
1286 else ret->format = WS_DATETIME_FORMAT_NONE;
1288 if ((ret->ticks = val >> 2) > TICKS_MAX) return WS_E_INVALID_FORMAT;
1289 return S_OK;
1292 static HRESULT lookup_string( struct reader *reader, ULONG id, const WS_XML_STRING **ret )
1294 const WS_XML_DICTIONARY *dict = (id & 1) ? reader->dict : reader->dict_static;
1295 if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
1296 *ret = &dict->strings[id];
1297 return S_OK;
1300 static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
1302 static const unsigned char zero[] = {'0'}, one[] = {'1'};
1303 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1304 WS_XML_UTF8_TEXT *utf8 = NULL;
1305 WS_XML_BASE64_TEXT *base64;
1306 const WS_XML_STRING *str;
1307 unsigned char type, buf[46];
1308 BOOL val_bool;
1309 INT8 val_int8;
1310 INT16 val_int16;
1311 INT32 val_int32;
1312 INT64 val_int64;
1313 double val_double;
1314 UINT8 val_uint8;
1315 UINT16 val_uint16;
1316 UINT64 val_uint64;
1317 WS_DATETIME datetime;
1318 ULONG len, id;
1319 GUID uuid;
1320 HRESULT hr;
1322 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1323 if (!is_text_type( type )) return WS_E_INVALID_FORMAT;
1325 switch (type)
1327 case RECORD_ZERO_TEXT:
1328 if (!(utf8 = alloc_utf8_text( zero, sizeof(zero) ))) return E_OUTOFMEMORY;
1329 break;
1331 case RECORD_ONE_TEXT:
1332 if (!(utf8 = alloc_utf8_text( one, sizeof(one) ))) return E_OUTOFMEMORY;
1333 break;
1335 case RECORD_FALSE_TEXT:
1336 if (!(utf8 = alloc_utf8_text( false, sizeof(false) ))) return E_OUTOFMEMORY;
1337 break;
1339 case RECORD_TRUE_TEXT:
1340 if (!(utf8 = alloc_utf8_text( true, sizeof(true) ))) return E_OUTOFMEMORY;
1341 break;
1343 case RECORD_INT8_TEXT:
1344 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
1345 len = format_int8( &val_int8, buf );
1346 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1347 break;
1349 case RECORD_INT16_TEXT:
1350 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
1351 len = format_int16( &val_int16, buf );
1352 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1353 break;
1355 case RECORD_INT32_TEXT:
1356 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1357 len = format_int32( &val_int32, buf );
1358 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1359 break;
1361 case RECORD_INT64_TEXT:
1362 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
1363 len = format_int64( &val_int64, buf );
1364 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1365 break;
1367 case RECORD_DOUBLE_TEXT:
1368 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
1369 len = format_double( &val_double, buf );
1370 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1371 break;
1373 case RECORD_DATETIME_TEXT:
1374 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
1375 len = format_datetime( &datetime, buf );
1376 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1377 break;
1379 case RECORD_CHARS8_TEXT:
1380 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1381 len = val_uint8;
1382 break;
1384 case RECORD_CHARS16_TEXT:
1385 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1386 len = val_uint16;
1387 break;
1389 case RECORD_CHARS32_TEXT:
1390 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1391 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1392 len = val_int32;
1393 break;
1395 case RECORD_BYTES8_TEXT:
1396 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
1397 if (!(base64 = alloc_base64_text( NULL, val_uint8 ))) return E_OUTOFMEMORY;
1398 if ((hr = read_bytes( reader, base64->bytes, val_uint8 )) != S_OK)
1400 heap_free( base64 );
1401 return hr;
1403 break;
1405 case RECORD_BYTES16_TEXT:
1406 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
1407 if (!(base64 = alloc_base64_text( NULL, val_uint16 ))) return E_OUTOFMEMORY;
1408 if ((hr = read_bytes( reader, base64->bytes, val_uint16 )) != S_OK)
1410 heap_free( base64 );
1411 return hr;
1413 break;
1415 case RECORD_BYTES32_TEXT:
1416 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
1417 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
1418 if (!(base64 = alloc_base64_text( NULL, val_int32 ))) return E_OUTOFMEMORY;
1419 if ((hr = read_bytes( reader, base64->bytes, val_int32 )) != S_OK)
1421 heap_free( base64 );
1422 return hr;
1424 break;
1426 case RECORD_EMPTY_TEXT:
1427 len = 0;
1428 break;
1430 case RECORD_DICTIONARY_TEXT:
1431 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
1432 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
1433 if (!(utf8 = alloc_utf8_text( str->bytes, str->length ))) return E_OUTOFMEMORY;
1434 break;
1436 case RECORD_UNIQUEID_TEXT:
1437 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
1438 len = format_urn( &uuid, buf );
1439 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1440 break;
1442 case RECORD_UUID_TEXT:
1443 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
1444 len = format_guid( &uuid, buf );
1445 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1446 break;
1448 case RECORD_UINT64_TEXT:
1449 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
1450 len = format_uint64( &val_uint64, buf );
1451 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1452 break;
1454 case RECORD_BOOL_TEXT:
1455 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
1456 len = format_bool( &val_bool, buf );
1457 if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
1458 break;
1460 default:
1461 ERR( "unhandled record type %02x\n", type );
1462 return WS_E_NOT_SUPPORTED;
1465 if (type >= RECORD_BYTES8_TEXT && type <= RECORD_BYTES32_TEXT)
1467 attr->value = &base64->text;
1468 return S_OK;
1471 if (!utf8)
1473 if (!(utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
1474 if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
1475 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
1477 heap_free( utf8 );
1478 return hr;
1482 attr->value = &utf8->text;
1483 return S_OK;
1486 static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1488 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1489 WS_XML_ATTRIBUTE *attr;
1490 unsigned int len = 0, ch, skip;
1491 const unsigned char *start;
1492 WS_XML_STRING *prefix, *localname;
1493 HRESULT hr = WS_E_INVALID_FORMAT;
1495 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1497 start = read_current_ptr( reader );
1498 for (;;)
1500 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1501 if (!read_isnamechar( ch )) break;
1502 read_skip( reader, skip );
1503 len += skip;
1505 if (!len) goto error;
1507 if ((hr = parse_qname( start, len, &prefix, &localname )) != S_OK) goto error;
1508 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1510 free_xml_string( prefix );
1511 attr->isXmlNs = 1;
1512 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1514 free_xml_string( localname );
1515 hr = E_OUTOFMEMORY;
1516 goto error;
1518 attr->localName = localname;
1520 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1522 attr->isXmlNs = 1;
1523 attr->prefix = prefix;
1524 attr->localName = localname;
1526 else
1528 attr->prefix = prefix;
1529 attr->localName = localname;
1532 if ((hr = read_attribute_value_text( reader, attr )) != S_OK) goto error;
1534 *ret = attr;
1535 return S_OK;
1537 error:
1538 free_attribute( attr );
1539 return hr;
1542 static inline BOOL is_attribute_type( unsigned char type )
1544 return (type >= RECORD_SHORT_ATTRIBUTE && type <= RECORD_PREFIX_ATTRIBUTE_Z);
1547 static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1549 WS_XML_ATTRIBUTE *attr;
1550 unsigned char type = 0;
1551 HRESULT hr;
1553 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1554 if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT;
1555 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1557 if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z)
1559 unsigned char ch = type - RECORD_PREFIX_ATTRIBUTE_A + 'a';
1560 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1562 hr = E_OUTOFMEMORY;
1563 goto error;
1565 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1566 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1568 else if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
1570 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A + 'a';
1571 if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
1573 hr = E_OUTOFMEMORY;
1574 goto error;
1576 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1577 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1579 else
1581 switch (type)
1583 case RECORD_SHORT_ATTRIBUTE:
1584 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1586 hr = E_OUTOFMEMORY;
1587 goto error;
1589 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1590 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1591 break;
1593 case RECORD_ATTRIBUTE:
1594 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1595 if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
1596 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1597 break;
1599 case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
1600 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1602 hr = E_OUTOFMEMORY;
1603 goto error;
1605 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1606 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1607 break;
1609 case RECORD_DICTIONARY_ATTRIBUTE:
1610 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1611 if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
1612 if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
1613 break;
1615 case RECORD_SHORT_XMLNS_ATTRIBUTE:
1616 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1618 hr = E_OUTOFMEMORY;
1619 goto error;
1621 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1622 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1623 attr->isXmlNs = 1;
1624 break;
1626 case RECORD_XMLNS_ATTRIBUTE:
1627 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1628 if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
1629 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1630 attr->isXmlNs = 1;
1631 break;
1633 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
1634 if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
1636 hr = E_OUTOFMEMORY;
1637 goto error;
1639 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1640 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1641 attr->isXmlNs = 1;
1642 break;
1644 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
1645 if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
1646 if ((hr = read_dict_string( reader, &attr->ns )) != S_OK) goto error;
1647 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1648 attr->isXmlNs = 1;
1649 break;
1651 default:
1652 ERR( "unhandled record type %02x\n", type );
1653 return WS_E_NOT_SUPPORTED;
1657 *ret = attr;
1658 return S_OK;
1660 error:
1661 free_attribute( attr );
1662 return hr;
1665 static inline struct node *find_parent( struct reader *reader )
1667 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT)
1669 if (is_valid_parent( reader->current->parent->parent )) return reader->current->parent->parent;
1670 return NULL;
1672 if (is_valid_parent( reader->current )) return reader->current;
1673 if (is_valid_parent( reader->current->parent )) return reader->current->parent;
1674 return NULL;
1677 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1679 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1680 const WS_XML_STRING *ns;
1681 ULONG i;
1683 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1684 if (!(elem->ns = dup_xml_string( ns ))) return E_OUTOFMEMORY;
1686 for (i = 0; i < elem->attributeCount; i++)
1688 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1689 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1690 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1691 if (!(attr->ns = alloc_xml_string( NULL, ns->length ))) return E_OUTOFMEMORY;
1692 if (attr->ns->length) memcpy( attr->ns->bytes, ns->bytes, ns->length );
1694 return S_OK;
1697 static WS_XML_ELEMENT_NODE *alloc_element_pair(void)
1699 struct node *node, *end;
1700 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
1701 if (!(end = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT )))
1703 free_node( node );
1704 return NULL;
1706 list_add_tail( &node->children, &end->entry );
1707 end->parent = node;
1708 return &node->hdr;
1711 static HRESULT read_attributes_text( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1713 WS_XML_ATTRIBUTE *attr;
1714 HRESULT hr;
1716 reader->current_attr = 0;
1717 for (;;)
1719 read_skip_whitespace( reader );
1720 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1721 if ((hr = read_attribute_text( reader, &attr )) != S_OK) return hr;
1722 if ((hr = append_attribute( elem, attr )) != S_OK)
1724 free_attribute( attr );
1725 return hr;
1727 reader->current_attr++;
1729 return S_OK;
1732 static HRESULT read_element_text( struct reader *reader )
1734 unsigned int len = 0, ch, skip;
1735 const unsigned char *start;
1736 struct node *node = NULL, *parent;
1737 WS_XML_ELEMENT_NODE *elem;
1738 HRESULT hr = WS_E_INVALID_FORMAT;
1740 if (read_end_of_data( reader ))
1742 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
1743 reader->last = reader->current;
1744 reader->state = READER_STATE_EOF;
1745 return S_OK;
1748 if (read_cmp( reader, "<", 1 )) return WS_E_INVALID_FORMAT;
1749 read_skip( reader, 1 );
1750 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1752 read_rewind( reader, 1 );
1753 return WS_E_INVALID_FORMAT;
1756 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1757 node = (struct node *)elem;
1759 start = read_current_ptr( reader );
1760 for (;;)
1762 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1763 if (!read_isnamechar( ch )) break;
1764 read_skip( reader, skip );
1765 len += skip;
1767 if (!len) goto error;
1769 if (!(parent = find_parent( reader ))) goto error;
1770 if ((hr = parse_qname( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1771 if ((hr = read_attributes_text( reader, elem )) != S_OK) goto error;
1772 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1774 read_insert_node( reader, parent, node );
1775 reader->state = READER_STATE_STARTELEMENT;
1776 return S_OK;
1778 error:
1779 destroy_nodes( node );
1780 return hr;
1783 static inline BOOL is_element_type( unsigned char type )
1785 return (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z);
1788 static HRESULT read_attributes_bin( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1790 WS_XML_ATTRIBUTE *attr;
1791 unsigned char type;
1792 HRESULT hr;
1794 reader->current_attr = 0;
1795 for (;;)
1797 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
1798 if (!is_attribute_type( type )) break;
1799 if ((hr = read_attribute_bin( reader, &attr )) != S_OK) return hr;
1800 if ((hr = append_attribute( elem, attr )) != S_OK)
1802 free_attribute( attr );
1803 return hr;
1805 reader->current_attr++;
1807 return S_OK;
1810 static HRESULT read_element_bin( struct reader *reader )
1812 struct node *node = NULL, *parent;
1813 WS_XML_ELEMENT_NODE *elem;
1814 unsigned char type;
1815 HRESULT hr;
1817 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
1818 if (!is_element_type( type )) return WS_E_INVALID_FORMAT;
1820 if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY;
1821 node = (struct node *)elem;
1823 if (type >= RECORD_PREFIX_ELEMENT_A && type <= RECORD_PREFIX_ELEMENT_Z)
1825 unsigned char ch = type - RECORD_PREFIX_ELEMENT_A + 'a';
1826 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1828 hr = E_OUTOFMEMORY;
1829 goto error;
1831 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1833 else if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
1835 unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ELEMENT_A + 'a';
1836 if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
1838 hr = E_OUTOFMEMORY;
1839 goto error;
1841 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1843 else
1845 switch (type)
1847 case RECORD_SHORT_ELEMENT:
1848 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
1850 hr = E_OUTOFMEMORY;
1851 goto error;
1853 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1854 break;
1856 case RECORD_ELEMENT:
1857 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
1858 if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
1859 break;
1861 case RECORD_SHORT_DICTIONARY_ELEMENT:
1862 if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
1864 hr = E_OUTOFMEMORY;
1865 goto error;
1867 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1868 break;
1870 case RECORD_DICTIONARY_ELEMENT:
1871 if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
1872 if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
1873 break;
1875 default:
1876 ERR( "unhandled record type %02x\n", type );
1877 return WS_E_NOT_SUPPORTED;
1881 if (!(parent = find_parent( reader )))
1883 hr = WS_E_INVALID_FORMAT;
1884 goto error;
1887 if ((hr = read_attributes_bin( reader, elem )) != S_OK) goto error;
1888 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1890 read_insert_node( reader, parent, node );
1891 reader->state = READER_STATE_STARTELEMENT;
1892 return S_OK;
1894 error:
1895 destroy_nodes( node );
1896 return hr;
1899 static HRESULT read_text_text( struct reader *reader )
1901 unsigned int len = 0, ch, skip;
1902 const unsigned char *start;
1903 struct node *node, *parent;
1904 WS_XML_TEXT_NODE *text;
1905 WS_XML_UTF8_TEXT *utf8;
1906 HRESULT hr;
1908 start = read_current_ptr( reader );
1909 for (;;)
1911 if (read_end_of_data( reader )) break;
1912 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1913 if (ch == '<') break;
1914 read_skip( reader, skip );
1915 len += skip;
1918 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
1920 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1921 text = (WS_XML_TEXT_NODE *)node;
1922 if (!(utf8 = alloc_utf8_text( NULL, len )))
1924 heap_free( node );
1925 return E_OUTOFMEMORY;
1927 if ((hr = decode_text( start, len, utf8->value.bytes, &utf8->value.length )) != S_OK)
1929 heap_free( utf8 );
1930 heap_free( node );
1931 return hr;
1933 text->text = &utf8->text;
1935 read_insert_node( reader, parent, node );
1936 reader->state = READER_STATE_TEXT;
1937 reader->text_conv_offset = 0;
1938 return S_OK;
1941 static struct node *alloc_utf8_text_node( const BYTE *data, ULONG len, WS_XML_UTF8_TEXT **ret )
1943 struct node *node;
1944 WS_XML_UTF8_TEXT *utf8;
1945 WS_XML_TEXT_NODE *text;
1947 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
1948 if (!(utf8 = alloc_utf8_text( data, len )))
1950 heap_free( node );
1951 return NULL;
1953 text = (WS_XML_TEXT_NODE *)node;
1954 text->text = &utf8->text;
1955 if (ret) *ret = utf8;
1956 return node;
1959 static struct node *alloc_base64_text_node( const BYTE *data, ULONG len, WS_XML_BASE64_TEXT **ret )
1961 struct node *node;
1962 WS_XML_BASE64_TEXT *base64;
1963 WS_XML_TEXT_NODE *text;
1965 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
1966 if (!(base64 = alloc_base64_text( data, len )))
1968 heap_free( node );
1969 return NULL;
1971 text = (WS_XML_TEXT_NODE *)node;
1972 text->text = &base64->text;
1973 if (ret) *ret = base64;
1974 return node;
1977 static HRESULT read_text_bin( struct reader *reader )
1979 static const unsigned char zero[] = {'0'}, one[] = {'1'};
1980 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1981 unsigned char type, buf[46];
1982 struct node *node = NULL, *parent;
1983 WS_XML_UTF8_TEXT *utf8;
1984 WS_XML_BASE64_TEXT *base64;
1985 const WS_XML_STRING *str;
1986 BOOL val_bool;
1987 INT8 val_int8;
1988 INT16 val_int16;
1989 INT32 val_int32;
1990 INT64 val_int64;
1991 double val_double;
1992 UINT8 val_uint8;
1993 UINT16 val_uint16;
1994 UINT64 val_uint64;
1995 WS_DATETIME datetime;
1996 ULONG len, id;
1997 GUID uuid;
1998 HRESULT hr;
2000 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2001 if (!is_text_type( type ) || !(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2003 switch (type)
2005 case RECORD_ZERO_TEXT:
2006 case RECORD_ZERO_TEXT_WITH_ENDELEMENT:
2007 if (!(node = alloc_utf8_text_node( zero, sizeof(zero), NULL ))) return E_OUTOFMEMORY;
2008 break;
2010 case RECORD_ONE_TEXT:
2011 case RECORD_ONE_TEXT_WITH_ENDELEMENT:
2012 if (!(node = alloc_utf8_text_node( one, sizeof(one), NULL ))) return E_OUTOFMEMORY;
2013 break;
2015 case RECORD_FALSE_TEXT:
2016 case RECORD_FALSE_TEXT_WITH_ENDELEMENT:
2017 if (!(node = alloc_utf8_text_node( false, sizeof(false), NULL ))) return E_OUTOFMEMORY;
2018 break;
2020 case RECORD_TRUE_TEXT:
2021 case RECORD_TRUE_TEXT_WITH_ENDELEMENT:
2022 if (!(node = alloc_utf8_text_node( true, sizeof(true), NULL ))) return E_OUTOFMEMORY;
2023 break;
2025 case RECORD_INT8_TEXT:
2026 case RECORD_INT8_TEXT_WITH_ENDELEMENT:
2027 if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
2028 len = format_int8( &val_int8, buf );
2029 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2030 break;
2032 case RECORD_INT16_TEXT:
2033 case RECORD_INT16_TEXT_WITH_ENDELEMENT:
2034 if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
2035 len = format_int16( &val_int16, buf );
2036 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2037 break;
2039 case RECORD_INT32_TEXT:
2040 case RECORD_INT32_TEXT_WITH_ENDELEMENT:
2041 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2042 len = format_int32( &val_int32, buf );
2043 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2044 break;
2046 case RECORD_INT64_TEXT:
2047 case RECORD_INT64_TEXT_WITH_ENDELEMENT:
2048 if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
2049 len = format_int64( &val_int64, buf );
2050 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2051 break;
2053 case RECORD_DOUBLE_TEXT:
2054 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT:
2055 if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
2056 len = format_double( &val_double, buf );
2057 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2058 break;
2060 case RECORD_DATETIME_TEXT:
2061 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT:
2062 if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
2063 len = format_datetime( &datetime, buf );
2064 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2065 break;
2067 case RECORD_CHARS8_TEXT:
2068 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT:
2069 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
2070 len = val_uint8;
2071 break;
2073 case RECORD_CHARS16_TEXT:
2074 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT:
2075 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
2076 len = val_uint16;
2077 break;
2079 case RECORD_CHARS32_TEXT:
2080 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT:
2081 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2082 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
2083 len = val_int32;
2084 break;
2086 case RECORD_BYTES8_TEXT:
2087 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT:
2088 if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
2089 if (!(node = alloc_base64_text_node( NULL, val_uint8, &base64 ))) return E_OUTOFMEMORY;
2090 if ((hr = read_bytes( reader, base64->bytes, val_uint8 )) != S_OK)
2092 free_node( node );
2093 return hr;
2095 break;
2097 case RECORD_BYTES16_TEXT:
2098 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT:
2099 if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
2100 if (!(node = alloc_base64_text_node( NULL, val_uint16, &base64 ))) return E_OUTOFMEMORY;
2101 if ((hr = read_bytes( reader, base64->bytes, val_uint16 )) != S_OK)
2103 free_node( node );
2104 return hr;
2106 break;
2108 case RECORD_BYTES32_TEXT:
2109 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT:
2110 if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
2111 if (val_int32 < 0) return WS_E_INVALID_FORMAT;
2112 if (!(node = alloc_base64_text_node( NULL, val_int32, &base64 ))) return E_OUTOFMEMORY;
2113 if ((hr = read_bytes( reader, base64->bytes, val_int32 )) != S_OK)
2115 free_node( node );
2116 return hr;
2118 break;
2120 case RECORD_EMPTY_TEXT:
2121 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT:
2122 len = 0;
2123 break;
2125 case RECORD_DICTIONARY_TEXT:
2126 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT:
2127 if ((hr = read_int31( reader, &id )) != S_OK) return hr;
2128 if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
2129 if (!(node = alloc_utf8_text_node( str->bytes, str->length, NULL ))) return E_OUTOFMEMORY;
2130 break;
2132 case RECORD_UNIQUEID_TEXT:
2133 case RECORD_UNIQUEID_TEXT_WITH_ENDELEMENT:
2134 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2135 len = format_urn( &uuid, buf );
2136 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2137 break;
2139 case RECORD_UUID_TEXT:
2140 case RECORD_UUID_TEXT_WITH_ENDELEMENT:
2141 if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
2142 len = format_guid( &uuid, buf );
2143 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2144 break;
2146 case RECORD_UINT64_TEXT:
2147 case RECORD_UINT64_TEXT_WITH_ENDELEMENT:
2148 if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
2149 len = format_uint64( &val_uint64, buf );
2150 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2151 break;
2153 case RECORD_BOOL_TEXT:
2154 case RECORD_BOOL_TEXT_WITH_ENDELEMENT:
2155 if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
2156 len = format_bool( &val_bool, buf );
2157 if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
2158 break;
2160 default:
2161 ERR( "unhandled record type %02x\n", type );
2162 return WS_E_NOT_SUPPORTED;
2165 if (!node)
2167 if (!(node = alloc_utf8_text_node( NULL, len, &utf8 ))) return E_OUTOFMEMORY;
2168 if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
2170 free_node( node );
2171 return hr;
2175 if (type & 1) node->flags |= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT;
2176 read_insert_node( reader, parent, node );
2177 reader->state = READER_STATE_TEXT;
2178 reader->text_conv_offset = 0;
2179 return S_OK;
2182 static HRESULT read_node_text( struct reader * );
2184 static HRESULT read_startelement_text( struct reader *reader )
2186 read_skip_whitespace( reader );
2187 if (!read_cmp( reader, "/>", 2 ))
2189 read_skip( reader, 2 );
2190 reader->current = LIST_ENTRY( list_tail( &reader->current->children ), struct node, entry );
2191 reader->last = reader->current;
2192 reader->state = READER_STATE_ENDELEMENT;
2193 return S_OK;
2195 else if (!read_cmp( reader, ">", 1 ))
2197 read_skip( reader, 1 );
2198 return read_node_text( reader );
2200 return WS_E_INVALID_FORMAT;
2203 static HRESULT read_node_bin( struct reader * );
2205 static HRESULT read_startelement_bin( struct reader *reader )
2207 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
2208 return read_node_bin( reader );
2211 static HRESULT read_startelement( struct reader *reader )
2213 switch (reader->input_enc)
2215 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_startelement_text( reader );
2216 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_startelement_bin( reader );
2217 default:
2218 ERR( "unhandled encoding %u\n", reader->input_enc );
2219 return WS_E_NOT_SUPPORTED;
2223 static HRESULT read_to_startelement_text( struct reader *reader, BOOL *found )
2225 HRESULT hr;
2227 switch (reader->state)
2229 case READER_STATE_INITIAL:
2230 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
2231 break;
2233 case READER_STATE_STARTELEMENT:
2234 if (found) *found = TRUE;
2235 return S_OK;
2237 default:
2238 break;
2241 read_skip_whitespace( reader );
2242 if ((hr = read_element_text( reader )) == S_OK && found)
2244 if (reader->state == READER_STATE_STARTELEMENT)
2245 *found = TRUE;
2246 else
2247 *found = FALSE;
2250 return hr;
2253 static HRESULT read_to_startelement_bin( struct reader *reader, BOOL *found )
2255 HRESULT hr;
2257 if (reader->state == READER_STATE_STARTELEMENT)
2259 if (found) *found = TRUE;
2260 return S_OK;
2263 if ((hr = read_element_bin( reader )) == S_OK && found)
2265 if (reader->state == READER_STATE_STARTELEMENT)
2266 *found = TRUE;
2267 else
2268 *found = FALSE;
2271 return hr;
2274 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
2276 switch (reader->input_enc)
2278 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_to_startelement_text( reader, found );
2279 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_to_startelement_bin( reader, found );
2280 default:
2281 ERR( "unhandled encoding %u\n", reader->input_enc );
2282 return WS_E_NOT_SUPPORTED;
2286 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
2288 ULONG i;
2289 if (len1 != len2) return 1;
2290 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
2291 return 0;
2294 static struct node *find_startelement( struct reader *reader, const WS_XML_STRING *prefix,
2295 const WS_XML_STRING *localname )
2297 struct node *parent;
2298 const WS_XML_STRING *str;
2300 for (parent = reader->current; parent; parent = parent->parent)
2302 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
2304 str = parent->hdr.prefix;
2305 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
2306 str = parent->hdr.localName;
2307 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
2308 return parent;
2311 return NULL;
2314 static HRESULT read_endelement_text( struct reader *reader )
2316 struct node *parent;
2317 unsigned int len = 0, ch, skip;
2318 const unsigned char *start;
2319 WS_XML_STRING prefix, localname;
2320 HRESULT hr;
2322 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
2323 read_skip( reader, 2 );
2325 start = read_current_ptr( reader );
2326 for (;;)
2328 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2329 if (ch == '>')
2331 read_skip( reader, 1 );
2332 break;
2334 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
2335 read_skip( reader, skip );
2336 len += skip;
2339 if ((hr = split_qname( start, len, &prefix, &localname )) != S_OK) return hr;
2340 if (!(parent = find_startelement( reader, &prefix, &localname ))) return WS_E_INVALID_FORMAT;
2342 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2343 reader->last = reader->current;
2344 reader->state = READER_STATE_ENDELEMENT;
2345 return S_OK;
2348 static HRESULT read_endelement_bin( struct reader *reader )
2350 struct node *parent;
2351 unsigned char type;
2352 HRESULT hr;
2354 if (!(reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT))
2356 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2357 if (type != RECORD_ENDELEMENT) return WS_E_INVALID_FORMAT;
2359 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2361 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2362 reader->last = reader->current;
2363 reader->state = READER_STATE_ENDELEMENT;
2364 return S_OK;
2367 static HRESULT read_endelement( struct reader *reader )
2369 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
2371 if (read_end_of_data( reader ))
2373 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2374 reader->last = reader->current;
2375 reader->state = READER_STATE_EOF;
2376 return S_OK;
2379 switch (reader->input_enc)
2381 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_endelement_text( reader );
2382 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_endelement_bin( reader );
2383 default:
2384 ERR( "unhandled encoding %u\n", reader->input_enc );
2385 return WS_E_NOT_SUPPORTED;
2389 static HRESULT read_comment_text( struct reader *reader )
2391 unsigned int len = 0, ch, skip;
2392 const unsigned char *start;
2393 struct node *node, *parent;
2394 WS_XML_COMMENT_NODE *comment;
2396 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
2397 read_skip( reader, 4 );
2399 start = read_current_ptr( reader );
2400 for (;;)
2402 if (!read_cmp( reader, "-->", 3 ))
2404 read_skip( reader, 3 );
2405 break;
2407 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2408 read_skip( reader, skip );
2409 len += skip;
2412 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2414 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2415 comment = (WS_XML_COMMENT_NODE *)node;
2416 if (!(comment->value.bytes = heap_alloc( len )))
2418 heap_free( node );
2419 return E_OUTOFMEMORY;
2421 memcpy( comment->value.bytes, start, len );
2422 comment->value.length = len;
2424 read_insert_node( reader, parent, node );
2425 reader->state = READER_STATE_COMMENT;
2426 return S_OK;
2429 static HRESULT read_comment_bin( struct reader *reader )
2431 struct node *node, *parent;
2432 WS_XML_COMMENT_NODE *comment;
2433 unsigned char type;
2434 ULONG len;
2435 HRESULT hr;
2437 if ((hr = read_byte( reader, &type )) != S_OK) return hr;
2438 if (type != RECORD_COMMENT) return WS_E_INVALID_FORMAT;
2439 if ((hr = read_int31( reader, &len )) != S_OK) return hr;
2441 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2443 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
2444 comment = (WS_XML_COMMENT_NODE *)node;
2445 if (!(comment->value.bytes = heap_alloc( len )))
2447 heap_free( node );
2448 return E_OUTOFMEMORY;
2450 if ((hr = read_bytes( reader, comment->value.bytes, len )) != S_OK)
2452 free_node( node );
2453 return E_OUTOFMEMORY;
2455 comment->value.length = len;
2457 read_insert_node( reader, parent, node );
2458 reader->state = READER_STATE_COMMENT;
2459 return S_OK;
2462 static HRESULT read_startcdata( struct reader *reader )
2464 struct node *node, *endnode, *parent;
2466 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
2467 read_skip( reader, 9 );
2469 if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
2471 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
2472 if (!(endnode = alloc_node( WS_XML_NODE_TYPE_END_CDATA )))
2474 heap_free( node );
2475 return E_OUTOFMEMORY;
2477 list_add_tail( &node->children, &endnode->entry );
2478 endnode->parent = node;
2480 read_insert_node( reader, parent, node );
2481 reader->state = READER_STATE_STARTCDATA;
2482 return S_OK;
2485 static HRESULT read_cdata( struct reader *reader )
2487 unsigned int len = 0, ch, skip;
2488 const unsigned char *start;
2489 struct node *node;
2490 WS_XML_TEXT_NODE *text;
2491 WS_XML_UTF8_TEXT *utf8;
2493 start = read_current_ptr( reader );
2494 for (;;)
2496 if (!read_cmp( reader, "]]>", 3 )) break;
2497 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
2498 read_skip( reader, skip );
2499 len += skip;
2502 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
2503 text = (WS_XML_TEXT_NODE *)node;
2504 if (!(utf8 = alloc_utf8_text( start, len )))
2506 heap_free( node );
2507 return E_OUTOFMEMORY;
2509 text->text = &utf8->text;
2511 read_insert_node( reader, reader->current, node );
2512 reader->state = READER_STATE_CDATA;
2513 return S_OK;
2516 static HRESULT read_endcdata( struct reader *reader )
2518 struct node *parent;
2520 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
2521 read_skip( reader, 3 );
2523 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT) parent = reader->current->parent;
2524 else parent = reader->current;
2526 reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
2527 reader->last = reader->current;
2528 reader->state = READER_STATE_ENDCDATA;
2529 return S_OK;
2532 static HRESULT read_node_text( struct reader *reader )
2534 HRESULT hr;
2536 for (;;)
2538 if (read_end_of_data( reader ))
2540 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2541 reader->last = reader->current;
2542 reader->state = READER_STATE_EOF;
2543 return S_OK;
2545 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
2546 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
2547 else if (!read_cmp( reader, "<?", 2 ))
2549 hr = read_xmldecl( reader );
2550 if (FAILED( hr )) return hr;
2552 else if (!read_cmp( reader, "</", 2 )) return read_endelement_text( reader );
2553 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
2554 else if (!read_cmp( reader, "<!--", 4 )) return read_comment_text( reader );
2555 else if (!read_cmp( reader, "<", 1 )) return read_element_text( reader );
2556 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement_text( reader );
2557 else return read_text_text( reader );
2561 static HRESULT read_node_bin( struct reader *reader )
2563 unsigned char type;
2564 HRESULT hr;
2566 if (reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT)
2568 reader->current = LIST_ENTRY( list_tail( &reader->current->parent->children ), struct node, entry );
2569 reader->last = reader->current;
2570 reader->state = READER_STATE_ENDELEMENT;
2571 return S_OK;
2573 if (read_end_of_data( reader ))
2575 reader->current = LIST_ENTRY( list_tail( &reader->root->children ), struct node, entry );
2576 reader->last = reader->current;
2577 reader->state = READER_STATE_EOF;
2578 return S_OK;
2581 if ((hr = read_peek( reader, &type )) != S_OK) return hr;
2582 if (type == RECORD_ENDELEMENT)
2584 return read_endelement_bin( reader );
2586 else if (type == RECORD_COMMENT)
2588 return read_comment_bin( reader );
2590 else if (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z)
2592 return read_element_bin( reader );
2594 else if (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT)
2596 return read_text_bin( reader );
2598 FIXME( "unhandled record type %02x\n", type );
2599 return WS_E_NOT_SUPPORTED;
2602 static HRESULT read_node( struct reader *reader )
2604 switch (reader->input_enc)
2606 case WS_XML_READER_ENCODING_TYPE_TEXT: return read_node_text( reader );
2607 case WS_XML_READER_ENCODING_TYPE_BINARY: return read_node_bin( reader );
2608 default:
2609 ERR( "unhandled encoding %u\n", reader->input_enc );
2610 return WS_E_NOT_SUPPORTED;
2614 HRESULT copy_node( WS_XML_READER *handle, struct node **node )
2616 struct reader *reader = (struct reader *)handle;
2617 const struct list *ptr;
2618 const struct node *start;
2619 HRESULT hr;
2621 EnterCriticalSection( &reader->cs );
2623 if (reader->magic != READER_MAGIC)
2625 LeaveCriticalSection( &reader->cs );
2626 return E_INVALIDARG;
2629 if (reader->current != reader->root) ptr = &reader->current->entry;
2630 else /* copy whole tree */
2632 if (!read_end_of_data( reader ))
2634 for (;;)
2636 if ((hr = read_node( reader )) != S_OK) goto done;
2637 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) break;
2640 ptr = list_head( &reader->root->children );
2643 start = LIST_ENTRY( ptr, struct node, entry );
2644 if (node_type( start ) == WS_XML_NODE_TYPE_EOF) hr = WS_E_INVALID_OPERATION;
2645 else hr = dup_tree( node, start );
2647 done:
2648 LeaveCriticalSection( &reader->cs );
2649 return hr;
2652 /**************************************************************************
2653 * WsReadEndElement [webservices.@]
2655 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
2657 struct reader *reader = (struct reader *)handle;
2658 HRESULT hr;
2660 TRACE( "%p %p\n", handle, error );
2661 if (error) FIXME( "ignoring error parameter\n" );
2663 if (!reader) return E_INVALIDARG;
2665 EnterCriticalSection( &reader->cs );
2667 if (reader->magic != READER_MAGIC)
2669 LeaveCriticalSection( &reader->cs );
2670 return E_INVALIDARG;
2673 hr = read_endelement( reader );
2675 LeaveCriticalSection( &reader->cs );
2676 return hr;
2679 /**************************************************************************
2680 * WsReadNode [webservices.@]
2682 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
2684 struct reader *reader = (struct reader *)handle;
2685 HRESULT hr;
2687 TRACE( "%p %p\n", handle, error );
2688 if (error) FIXME( "ignoring error parameter\n" );
2690 if (!reader) return E_INVALIDARG;
2692 EnterCriticalSection( &reader->cs );
2694 if (reader->magic != READER_MAGIC)
2696 LeaveCriticalSection( &reader->cs );
2697 return E_INVALIDARG;
2700 hr = read_node( reader );
2702 LeaveCriticalSection( &reader->cs );
2703 return hr;
2706 static HRESULT skip_node( struct reader *reader )
2708 const struct node *parent;
2709 HRESULT hr;
2711 if (node_type( reader->current ) == WS_XML_NODE_TYPE_EOF) return WS_E_INVALID_OPERATION;
2712 if (node_type( reader->current ) == WS_XML_NODE_TYPE_ELEMENT) parent = reader->current;
2713 else parent = NULL;
2715 for (;;)
2717 if ((hr = read_node( reader ) != S_OK) || !parent) break;
2718 if (node_type( reader->current ) != WS_XML_NODE_TYPE_END_ELEMENT) continue;
2719 if (reader->current->parent == parent) return read_node( reader );
2722 return hr;
2725 /**************************************************************************
2726 * WsSkipNode [webservices.@]
2728 HRESULT WINAPI WsSkipNode( WS_XML_READER *handle, WS_ERROR *error )
2730 struct reader *reader = (struct reader *)handle;
2731 HRESULT hr;
2733 TRACE( "%p %p\n", handle, error );
2734 if (error) FIXME( "ignoring error parameter\n" );
2736 if (!reader) return E_INVALIDARG;
2738 EnterCriticalSection( &reader->cs );
2740 if (reader->magic != READER_MAGIC)
2742 LeaveCriticalSection( &reader->cs );
2743 return E_INVALIDARG;
2746 hr = skip_node( reader );
2748 LeaveCriticalSection( &reader->cs );
2749 return hr;
2752 /**************************************************************************
2753 * WsReadStartElement [webservices.@]
2755 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
2757 struct reader *reader = (struct reader *)handle;
2758 HRESULT hr;
2760 TRACE( "%p %p\n", handle, error );
2761 if (error) FIXME( "ignoring error parameter\n" );
2763 if (!reader) return E_INVALIDARG;
2765 EnterCriticalSection( &reader->cs );
2767 if (reader->magic != READER_MAGIC)
2769 LeaveCriticalSection( &reader->cs );
2770 return E_INVALIDARG;
2773 hr = read_startelement( reader );
2775 LeaveCriticalSection( &reader->cs );
2776 return hr;
2779 /**************************************************************************
2780 * WsReadToStartElement [webservices.@]
2782 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
2783 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
2785 struct reader *reader = (struct reader *)handle;
2786 HRESULT hr;
2788 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
2789 if (error) FIXME( "ignoring error parameter\n" );
2791 if (!reader) return E_INVALIDARG;
2792 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
2794 EnterCriticalSection( &reader->cs );
2796 if (reader->magic != READER_MAGIC)
2798 LeaveCriticalSection( &reader->cs );
2799 return E_INVALIDARG;
2802 hr = read_to_startelement( reader, found );
2804 LeaveCriticalSection( &reader->cs );
2805 return hr;
2808 BOOL move_to_root_element( struct node *root, struct node **current )
2810 struct list *ptr;
2811 struct node *node;
2813 if (!(ptr = list_head( &root->children ))) return FALSE;
2814 node = LIST_ENTRY( ptr, struct node, entry );
2815 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
2817 *current = node;
2818 return TRUE;
2820 while ((ptr = list_next( &root->children, &node->entry )))
2822 struct node *next = LIST_ENTRY( ptr, struct node, entry );
2823 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
2825 *current = next;
2826 return TRUE;
2828 node = next;
2830 return FALSE;
2833 BOOL move_to_next_element( struct node **current )
2835 struct list *ptr;
2836 struct node *node = *current, *parent = (*current)->parent;
2838 if (!parent) return FALSE;
2839 while ((ptr = list_next( &parent->children, &node->entry )))
2841 struct node *next = LIST_ENTRY( ptr, struct node, entry );
2842 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
2844 *current = next;
2845 return TRUE;
2847 node = next;
2849 return FALSE;
2852 BOOL move_to_prev_element( struct node **current )
2854 struct list *ptr;
2855 struct node *node = *current, *parent = (*current)->parent;
2857 if (!parent) return FALSE;
2858 while ((ptr = list_prev( &parent->children, &node->entry )))
2860 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
2861 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
2863 *current = prev;
2864 return TRUE;
2866 node = prev;
2868 return FALSE;
2871 BOOL move_to_child_element( struct node **current )
2873 struct list *ptr;
2874 struct node *child, *node = *current;
2876 if (!(ptr = list_head( &node->children ))) return FALSE;
2877 child = LIST_ENTRY( ptr, struct node, entry );
2878 if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
2880 *current = child;
2881 return TRUE;
2883 while ((ptr = list_next( &node->children, &child->entry )))
2885 struct node *next = LIST_ENTRY( ptr, struct node, entry );
2886 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
2888 *current = next;
2889 return TRUE;
2891 child = next;
2893 return FALSE;
2896 BOOL move_to_end_element( struct node **current )
2898 struct list *ptr;
2899 struct node *node = *current;
2901 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
2903 if ((ptr = list_tail( &node->children )))
2905 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
2906 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
2908 *current = tail;
2909 return TRUE;
2912 return FALSE;
2915 BOOL move_to_parent_element( struct node **current )
2917 struct node *parent = (*current)->parent;
2919 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
2920 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
2922 *current = parent;
2923 return TRUE;
2925 return FALSE;
2928 BOOL move_to_first_node( struct node **current )
2930 struct list *ptr;
2931 struct node *node = *current;
2933 if ((ptr = list_head( &node->parent->children )))
2935 *current = LIST_ENTRY( ptr, struct node, entry );
2936 return TRUE;
2938 return FALSE;
2941 BOOL move_to_next_node( struct node **current )
2943 struct list *ptr;
2944 struct node *node = *current;
2946 if ((ptr = list_next( &node->parent->children, &node->entry )))
2948 *current = LIST_ENTRY( ptr, struct node, entry );
2949 return TRUE;
2951 return FALSE;
2954 BOOL move_to_prev_node( struct node **current )
2956 struct list *ptr;
2957 struct node *node = *current;
2959 if ((ptr = list_prev( &node->parent->children, &node->entry )))
2961 *current = LIST_ENTRY( ptr, struct node, entry );
2962 return TRUE;
2964 return FALSE;
2967 BOOL move_to_bof( struct node *root, struct node **current )
2969 *current = root;
2970 return TRUE;
2973 BOOL move_to_eof( struct node *root, struct node **current )
2975 struct list *ptr;
2976 if ((ptr = list_tail( &root->children )))
2978 *current = LIST_ENTRY( ptr, struct node, entry );
2979 return TRUE;
2981 return FALSE;
2984 BOOL move_to_child_node( struct node **current )
2986 struct list *ptr;
2987 struct node *node = *current;
2989 if ((ptr = list_head( &node->children )))
2991 *current = LIST_ENTRY( ptr, struct node, entry );
2992 return TRUE;
2994 return FALSE;
2997 BOOL move_to_parent_node( struct node **current )
2999 struct node *parent = (*current)->parent;
3000 if (!parent) return FALSE;
3001 *current = parent;
3002 return TRUE;
3005 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
3007 BOOL success = FALSE;
3008 HRESULT hr = S_OK;
3010 if (!read_end_of_data( reader ))
3012 struct node *saved_current = reader->current;
3013 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
3014 if (hr != S_OK) return hr;
3015 reader->current = saved_current;
3017 switch (move)
3019 case WS_MOVE_TO_ROOT_ELEMENT:
3020 success = move_to_root_element( reader->root, &reader->current );
3021 break;
3023 case WS_MOVE_TO_NEXT_ELEMENT:
3024 success = move_to_next_element( &reader->current );
3025 break;
3027 case WS_MOVE_TO_PREVIOUS_ELEMENT:
3028 success = move_to_prev_element( &reader->current );
3029 break;
3031 case WS_MOVE_TO_CHILD_ELEMENT:
3032 success = move_to_child_element( &reader->current );
3033 break;
3035 case WS_MOVE_TO_END_ELEMENT:
3036 success = move_to_end_element( &reader->current );
3037 break;
3039 case WS_MOVE_TO_PARENT_ELEMENT:
3040 success = move_to_parent_element( &reader->current );
3041 break;
3043 case WS_MOVE_TO_FIRST_NODE:
3044 success = move_to_first_node( &reader->current );
3045 break;
3047 case WS_MOVE_TO_NEXT_NODE:
3048 success = move_to_next_node( &reader->current );
3049 break;
3051 case WS_MOVE_TO_PREVIOUS_NODE:
3052 success = move_to_prev_node( &reader->current );
3053 break;
3055 case WS_MOVE_TO_CHILD_NODE:
3056 success = move_to_child_node( &reader->current );
3057 break;
3059 case WS_MOVE_TO_BOF:
3060 success = move_to_bof( reader->root, &reader->current );
3061 break;
3063 case WS_MOVE_TO_EOF:
3064 success = move_to_eof( reader->root, &reader->current );
3065 break;
3067 default:
3068 FIXME( "unhandled move %u\n", move );
3069 return E_NOTIMPL;
3072 if (found)
3074 *found = success;
3075 return S_OK;
3077 return success ? S_OK : WS_E_INVALID_FORMAT;
3080 /**************************************************************************
3081 * WsMoveReader [webservices.@]
3083 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
3085 struct reader *reader = (struct reader *)handle;
3086 HRESULT hr;
3088 TRACE( "%p %u %p %p\n", handle, move, found, error );
3089 if (error) FIXME( "ignoring error parameter\n" );
3091 if (!reader) return E_INVALIDARG;
3093 EnterCriticalSection( &reader->cs );
3095 if (reader->magic != READER_MAGIC)
3097 LeaveCriticalSection( &reader->cs );
3098 return E_INVALIDARG;
3101 if (!reader->input_type)
3103 LeaveCriticalSection( &reader->cs );
3104 return WS_E_INVALID_OPERATION;
3107 hr = read_move_to( reader, move, found );
3109 LeaveCriticalSection( &reader->cs );
3110 return hr;
3113 /**************************************************************************
3114 * WsReadStartAttribute [webservices.@]
3116 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
3118 struct reader *reader = (struct reader *)handle;
3119 const WS_XML_ELEMENT_NODE *elem;
3121 TRACE( "%p %u %p\n", handle, index, error );
3122 if (error) FIXME( "ignoring error parameter\n" );
3124 if (!reader) return E_INVALIDARG;
3126 EnterCriticalSection( &reader->cs );
3128 if (reader->magic != READER_MAGIC)
3130 LeaveCriticalSection( &reader->cs );
3131 return E_INVALIDARG;
3134 elem = &reader->current->hdr;
3135 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
3137 LeaveCriticalSection( &reader->cs );
3138 return WS_E_INVALID_FORMAT;
3141 reader->current_attr = index;
3142 reader->state = READER_STATE_STARTATTRIBUTE;
3144 LeaveCriticalSection( &reader->cs );
3145 return S_OK;
3148 /**************************************************************************
3149 * WsReadEndAttribute [webservices.@]
3151 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
3153 struct reader *reader = (struct reader *)handle;
3155 TRACE( "%p %p\n", handle, error );
3156 if (error) FIXME( "ignoring error parameter\n" );
3158 if (!reader) return E_INVALIDARG;
3160 EnterCriticalSection( &reader->cs );
3162 if (reader->magic != READER_MAGIC)
3164 LeaveCriticalSection( &reader->cs );
3165 return E_INVALIDARG;
3168 if (reader->state != READER_STATE_STARTATTRIBUTE)
3170 LeaveCriticalSection( &reader->cs );
3171 return WS_E_INVALID_FORMAT;
3174 reader->state = READER_STATE_STARTELEMENT;
3176 LeaveCriticalSection( &reader->cs );
3177 return S_OK;
3180 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
3182 WCHAR *ret;
3184 switch (text->textType)
3186 case WS_XML_TEXT_TYPE_UTF8:
3188 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
3189 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
3190 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
3191 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
3192 ret[len] = 0;
3193 break;
3195 default:
3196 FIXME( "unhandled type %u\n", text->textType );
3197 return NULL;
3200 return ret;
3203 #define MAX_INT8 0x7f
3204 #define MIN_INT8 (-MAX_INT8 - 1)
3205 #define MAX_INT16 0x7fff
3206 #define MIN_INT16 (-MAX_INT16 - 1)
3207 #define MAX_INT32 0x7fffffff
3208 #define MIN_INT32 (-MAX_INT32 - 1)
3209 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
3210 #define MIN_INT64 (-MAX_INT64 - 1)
3211 #define MAX_UINT8 0xff
3212 #define MAX_UINT16 0xffff
3213 #define MAX_UINT32 0xffffffff
3214 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
3216 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
3218 BOOL negative = FALSE;
3219 const unsigned char *ptr = str;
3221 *ret = 0;
3222 while (len && read_isspace( *ptr )) { ptr++; len--; }
3223 while (len && read_isspace( ptr[len - 1] )) { len--; }
3224 if (!len) return WS_E_INVALID_FORMAT;
3226 if (*ptr == '-')
3228 negative = TRUE;
3229 ptr++;
3230 len--;
3232 if (!len) return WS_E_INVALID_FORMAT;
3234 while (len--)
3236 int val;
3238 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3239 val = *ptr - '0';
3240 if (negative) val = -val;
3242 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
3243 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
3245 return WS_E_NUMERIC_OVERFLOW;
3247 *ret = *ret * 10 + val;
3248 ptr++;
3251 return S_OK;
3254 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
3256 const unsigned char *ptr = str;
3258 *ret = 0;
3259 while (len && read_isspace( *ptr )) { ptr++; len--; }
3260 while (len && read_isspace( ptr[len - 1] )) { len--; }
3261 if (!len) return WS_E_INVALID_FORMAT;
3263 while (len--)
3265 unsigned int val;
3267 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
3268 val = *ptr - '0';
3270 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
3271 *ret = *ret * 10 + val;
3272 ptr++;
3275 return S_OK;
3278 BOOL set_fpword( unsigned short new, unsigned short *old )
3280 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3281 unsigned short fpword;
3283 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
3284 *old = fpword;
3285 fpword = new;
3286 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3287 return TRUE;
3288 #else
3289 FIXME( "not implemented\n" );
3290 return FALSE;
3291 #endif
3294 void restore_fpword( unsigned short fpword )
3296 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3297 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
3298 #else
3299 FIXME( "not implemented\n" );
3300 #endif
3303 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
3305 static const unsigned __int64 nan = 0xfff8000000000000;
3306 static const unsigned __int64 inf = 0x7ff0000000000000;
3307 static const unsigned __int64 inf_min = 0xfff0000000000000;
3308 HRESULT hr = WS_E_INVALID_FORMAT;
3309 const unsigned char *p = str, *q;
3310 int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
3311 unsigned __int64 val = 0, tmp;
3312 long double exp_val = 1.0, exp_mul = 10.0;
3313 unsigned short fpword;
3315 while (len && read_isspace( *p )) { p++; len--; }
3316 while (len && read_isspace( p[len - 1] )) { len--; }
3317 if (!len) return WS_E_INVALID_FORMAT;
3319 if (len == 3 && !memcmp( p, "NaN", 3 ))
3321 *(unsigned __int64 *)ret = nan;
3322 return S_OK;
3324 else if (len == 3 && !memcmp( p, "INF", 3 ))
3326 *(unsigned __int64 *)ret = inf;
3327 return S_OK;
3329 else if (len == 4 && !memcmp( p, "-INF", 4 ))
3331 *(unsigned __int64 *)ret = inf_min;
3332 return S_OK;
3335 *ret = 0.0;
3336 if (*p == '-')
3338 sign = -1;
3339 p++; len--;
3341 else if (*p == '+') { p++; len--; };
3342 if (!len) return S_OK;
3344 if (!set_fpword( 0x37f, &fpword )) return E_NOTIMPL;
3346 q = p;
3347 while (len && isdigit( *q )) { q++; len--; }
3348 have_digits = nb_digits = q - p;
3349 for (i = 0; i < nb_digits; i++)
3351 tmp = val * 10 + p[i] - '0';
3352 if (val > MAX_UINT64 / 10 || tmp < val)
3354 for (; i < nb_digits; i++) exp++;
3355 break;
3357 val = tmp;
3360 if (len)
3362 if (*q == '.')
3364 p = ++q; len--;
3365 while (len && isdigit( *q )) { q++; len--; };
3366 have_digits |= nb_digits = q - p;
3367 for (i = 0; i < nb_digits; i++)
3369 tmp = val * 10 + p[i] - '0';
3370 if (val > MAX_UINT64 / 10 || tmp < val) break;
3371 val = tmp;
3372 exp--;
3375 if (len > 1 && tolower(*q) == 'e')
3377 if (!have_digits) goto done;
3378 p = ++q; len--;
3379 if (*p == '-')
3381 exp_sign = -1;
3382 p++; len--;
3384 else if (*p == '+') { p++; len--; };
3386 q = p;
3387 while (len && isdigit( *q )) { q++; len--; };
3388 nb_digits = q - p;
3389 if (!nb_digits || len) goto done;
3390 for (i = 0; i < nb_digits; i++)
3392 if (exp_tmp > MAX_INT32 / 10 || (exp_tmp = exp_tmp * 10 + p[i] - '0') < 0)
3393 exp_tmp = MAX_INT32;
3395 exp_tmp *= exp_sign;
3397 if (exp < 0 && exp_tmp < 0 && exp + exp_tmp >= 0) exp = MIN_INT32;
3398 else if (exp > 0 && exp_tmp > 0 && exp + exp_tmp < 0) exp = MAX_INT32;
3399 else exp += exp_tmp;
3402 if (!have_digits || len) goto done;
3404 if ((neg_exp = exp < 0)) exp = -exp;
3405 for (; exp; exp >>= 1)
3407 if (exp & 1) exp_val *= exp_mul;
3408 exp_mul *= exp_mul;
3411 *ret = sign * (neg_exp ? val / exp_val : val * exp_val);
3412 hr = S_OK;
3414 done:
3415 restore_fpword( fpword );
3416 return hr;
3419 static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
3421 static const unsigned char hex[] =
3423 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3424 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3425 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3426 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3427 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3428 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3429 0,10,11,12,13,14,15 /* 0x60 */
3431 const unsigned char *p = str;
3432 ULONG i;
3434 while (len && read_isspace( *p )) { p++; len--; }
3435 while (len && read_isspace( p[len - 1] )) { len--; }
3436 if (len != 36) return WS_E_INVALID_FORMAT;
3438 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
3439 return WS_E_INVALID_FORMAT;
3441 for (i = 0; i < 36; i++)
3443 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
3444 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
3447 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
3448 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
3450 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
3451 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
3453 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
3454 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
3455 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
3456 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
3457 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
3458 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
3459 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
3460 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
3462 return S_OK;
3465 static HRESULT str_to_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_STRING *ret )
3467 int len_utf16 = MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, NULL, 0 );
3468 if (!(ret->chars = ws_alloc( heap, len_utf16 * sizeof(WCHAR) ))) return WS_E_QUOTA_EXCEEDED;
3469 MultiByteToWideChar( CP_UTF8, 0, (const char *)str, len, ret->chars, len_utf16 );
3470 ret->length = len_utf16;
3471 return S_OK;
3474 static HRESULT str_to_unique_id( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_UNIQUE_ID *ret )
3476 if (len == 45 && !memcmp( str, "urn:uuid:", 9 ))
3478 ret->uri.length = 0;
3479 ret->uri.chars = NULL;
3480 return str_to_guid( str + 9, len - 9, &ret->guid );
3483 memset( &ret->guid, 0, sizeof(ret->guid) );
3484 return str_to_string( str, len, heap, &ret->uri );
3487 static inline unsigned char decode_char( unsigned char c )
3489 if (c >= 'A' && c <= 'Z') return c - 'A';
3490 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
3491 if (c >= '0' && c <= '9') return c - '0' + 52;
3492 if (c == '+') return 62;
3493 if (c == '/') return 63;
3494 return 64;
3497 static ULONG decode_base64( const unsigned char *base64, ULONG len, unsigned char *buf )
3499 ULONG i = 0;
3500 unsigned char c0, c1, c2, c3;
3501 const unsigned char *p = base64;
3503 while (len > 4)
3505 if ((c0 = decode_char( p[0] )) > 63) return 0;
3506 if ((c1 = decode_char( p[1] )) > 63) return 0;
3507 if ((c2 = decode_char( p[2] )) > 63) return 0;
3508 if ((c3 = decode_char( p[3] )) > 63) return 0;
3509 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3510 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3511 buf[i + 2] = (c2 << 6) | c3;
3512 len -= 4;
3513 i += 3;
3514 p += 4;
3516 if (p[2] == '=')
3518 if ((c0 = decode_char( p[0] )) > 63) return 0;
3519 if ((c1 = decode_char( p[1] )) > 63) return 0;
3520 buf[i] = (c0 << 2) | (c1 >> 4);
3521 i++;
3523 else if (p[3] == '=')
3525 if ((c0 = decode_char( p[0] )) > 63) return 0;
3526 if ((c1 = decode_char( p[1] )) > 63) return 0;
3527 if ((c2 = decode_char( p[2] )) > 63) return 0;
3528 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3529 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3530 i += 2;
3532 else
3534 if ((c0 = decode_char( p[0] )) > 63) return 0;
3535 if ((c1 = decode_char( p[1] )) > 63) return 0;
3536 if ((c2 = decode_char( p[2] )) > 63) return 0;
3537 if ((c3 = decode_char( p[3] )) > 63) return 0;
3538 buf[i + 0] = (c0 << 2) | (c1 >> 4);
3539 buf[i + 1] = (c1 << 4) | (c2 >> 2);
3540 buf[i + 2] = (c2 << 6) | c3;
3541 i += 3;
3543 return i;
3546 static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_BYTES *ret )
3548 const unsigned char *p = str;
3550 while (len && read_isspace( *p )) { p++; len--; }
3551 while (len && read_isspace( p[len - 1] )) { len--; }
3553 if (len % 4) return WS_E_INVALID_FORMAT;
3554 if (!(ret->bytes = ws_alloc( heap, len * 3 / 4 ))) return WS_E_QUOTA_EXCEEDED;
3555 ret->length = decode_base64( p, len, ret->bytes );
3556 return S_OK;
3559 static HRESULT str_to_xml_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_XML_STRING *ret )
3561 if (!(ret->bytes = ws_alloc( heap, len ))) return WS_E_QUOTA_EXCEEDED;
3562 memcpy( ret->bytes, str, len );
3563 ret->length = len;
3564 ret->dictionary = NULL;
3565 ret->id = 0;
3566 return S_OK;
3569 static HRESULT copy_xml_string( WS_HEAP *heap, const WS_XML_STRING *src, WS_XML_STRING *dst )
3571 if (!(dst->bytes = ws_alloc( heap, src->length ))) return WS_E_QUOTA_EXCEEDED;
3572 memcpy( dst->bytes, src->bytes, src->length );
3573 dst->length = src->length;
3574 return S_OK;
3577 static HRESULT str_to_qname( struct reader *reader, const unsigned char *str, ULONG len, WS_HEAP *heap,
3578 WS_XML_STRING *prefix_ret, WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
3580 const unsigned char *p = str;
3581 WS_XML_STRING prefix, localname;
3582 const WS_XML_STRING *ns;
3583 HRESULT hr;
3585 while (len && read_isspace( *p )) { p++; len--; }
3586 while (len && read_isspace( p[len - 1] )) { len--; }
3588 if ((hr = split_qname( p, len, &prefix, &localname )) != S_OK) return hr;
3589 if (!(ns = get_namespace( reader, &prefix ))) return WS_E_INVALID_FORMAT;
3591 if (prefix_ret && (hr = copy_xml_string( heap, &prefix, prefix_ret )) != S_OK) return hr;
3592 if ((hr = copy_xml_string( heap, &localname, localname_ret )) != S_OK)
3594 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
3595 return hr;
3597 if ((hr = copy_xml_string( heap, ns, ns_ret )) != S_OK)
3599 ws_free( heap, prefix_ret->bytes, prefix_ret->length );
3600 ws_free( heap, localname_ret->bytes, localname_ret->length );
3601 return hr;
3603 return S_OK;
3606 static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix,
3607 WS_XML_STRING *localname, WS_XML_STRING *ns )
3609 const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
3610 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
3611 return str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap, prefix, localname, ns );
3614 /**************************************************************************
3615 * WsReadQualifiedName [webservices.@]
3617 HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
3618 WS_XML_STRING *localname, WS_XML_STRING *ns,
3619 WS_ERROR *error )
3621 struct reader *reader = (struct reader *)handle;
3622 HRESULT hr;
3624 TRACE( "%p %p %p %p %p %p\n", handle, heap, prefix, localname, ns, error );
3625 if (error) FIXME( "ignoring error parameter\n" );
3627 if (!reader || !heap) return E_INVALIDARG;
3629 EnterCriticalSection( &reader->cs );
3631 if (reader->magic != READER_MAGIC)
3633 LeaveCriticalSection( &reader->cs );
3634 return E_INVALIDARG;
3637 if (!reader->input_type)
3639 LeaveCriticalSection( &reader->cs );
3640 return WS_E_INVALID_OPERATION;
3643 if (!localname)
3645 LeaveCriticalSection( &reader->cs );
3646 return E_INVALIDARG;
3649 if (reader->state != READER_STATE_TEXT)
3651 LeaveCriticalSection( &reader->cs );
3652 return WS_E_INVALID_FORMAT;
3655 hr = read_qualified_name( reader, heap, prefix, localname, ns );
3657 LeaveCriticalSection( &reader->cs );
3658 return hr;
3661 static const int month_offsets[2][12] =
3663 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
3664 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
3667 static inline int valid_day( int year, int month, int day )
3669 return day > 0 && day <= month_days[leap_year( year )][month - 1];
3672 static inline int leap_days_before( int year )
3674 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
3677 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
3679 const unsigned char *p = bytes, *q;
3680 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
3682 while (len && read_isspace( *p )) { p++; len--; }
3683 while (len && read_isspace( p[len - 1] )) { len--; }
3685 q = p;
3686 while (len && isdigit( *q )) { q++; len--; };
3687 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
3688 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
3689 if (year < 1) return WS_E_INVALID_FORMAT;
3691 p = ++q; len--;
3692 while (len && isdigit( *q )) { q++; len--; };
3693 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
3694 month = (p[0] - '0') * 10 + p[1] - '0';
3695 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
3697 p = ++q; len--;
3698 while (len && isdigit( *q )) { q++; len--; };
3699 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
3700 day = (p[0] - '0') * 10 + p[1] - '0';
3701 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
3703 p = ++q; len--;
3704 while (len && isdigit( *q )) { q++; len--; };
3705 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
3706 hour = (p[0] - '0') * 10 + p[1] - '0';
3707 if (hour > 24) return WS_E_INVALID_FORMAT;
3709 p = ++q; len--;
3710 while (len && isdigit( *q )) { q++; len--; };
3711 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
3712 min = (p[0] - '0') * 10 + p[1] - '0';
3713 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
3715 p = ++q; len--;
3716 while (len && isdigit( *q )) { q++; len--; };
3717 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
3718 sec = (p[0] - '0') * 10 + p[1] - '0';
3719 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
3721 if (*q == '.')
3723 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
3724 p = ++q; len--;
3725 while (len && isdigit( *q )) { q++; len--; };
3726 nb_digits = q - p;
3727 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
3728 for (i = 0; i < nb_digits; i++)
3730 sec_frac += (p[i] - '0') * mul;
3731 mul /= 10;
3734 if (*q == 'Z')
3736 if (--len) return WS_E_INVALID_FORMAT;
3737 tz_hour = tz_min = tz_neg = 0;
3738 ret->format = WS_DATETIME_FORMAT_UTC;
3740 else if (*q == '+' || *q == '-')
3742 tz_neg = (*q == '-') ? 1 : 0;
3744 p = ++q; len--;
3745 while (len && isdigit( *q )) { q++; len--; };
3746 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
3747 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
3748 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
3750 p = ++q; len--;
3751 while (len && isdigit( *q )) { q++; len--; };
3752 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
3753 tz_min = (p[0] - '0') * 10 + p[1] - '0';
3754 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
3756 ret->format = WS_DATETIME_FORMAT_LOCAL;
3758 else return WS_E_INVALID_FORMAT;
3760 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
3761 ret->ticks += month_offsets[leap_year( year )][month - 1] * TICKS_PER_DAY;
3762 ret->ticks += (day - 1) * TICKS_PER_DAY;
3763 ret->ticks += hour * TICKS_PER_HOUR;
3764 ret->ticks += min * TICKS_PER_MIN;
3765 ret->ticks += sec * TICKS_PER_SEC;
3766 ret->ticks += sec_frac;
3768 if (tz_neg)
3770 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
3771 return WS_E_INVALID_FORMAT;
3772 ret->ticks += tz_hour * TICKS_PER_HOUR;
3773 ret->ticks += tz_min * TICKS_PER_MIN;
3775 else
3777 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
3778 return WS_E_INVALID_FORMAT;
3779 ret->ticks -= tz_hour * TICKS_PER_HOUR;
3780 ret->ticks -= tz_min * TICKS_PER_MIN;
3783 return S_OK;
3786 /**************************************************************************
3787 * WsDateTimeToFileTime [webservices.@]
3789 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
3791 unsigned __int64 ticks;
3793 TRACE( "%p %p %p\n", dt, ft, error );
3794 if (error) FIXME( "ignoring error parameter\n" );
3796 if (!dt || !ft) return E_INVALIDARG;
3798 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
3799 ticks = dt->ticks - TICKS_1601_01_01;
3800 ft->dwHighDateTime = ticks >> 32;
3801 ft->dwLowDateTime = (DWORD)ticks;
3802 return S_OK;
3805 /**************************************************************************
3806 * WsFileTimeToDateTime [webservices.@]
3808 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
3810 unsigned __int64 ticks;
3812 TRACE( "%p %p %p\n", ft, dt, error );
3813 if (error) FIXME( "ignoring error parameter\n" );
3815 if (!dt || !ft) return E_INVALIDARG;
3817 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
3818 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
3819 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
3820 dt->ticks = ticks + TICKS_1601_01_01;
3821 dt->format = WS_DATETIME_FORMAT_UTC;
3822 return S_OK;
3825 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
3827 WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
3828 if (node->text->textType != WS_XML_TEXT_TYPE_UTF8)
3830 FIXME( "text type %u not supported\n", node->text->textType );
3831 return E_NOTIMPL;
3833 *ret = (WS_XML_UTF8_TEXT *)node->text;
3834 return S_OK;
3837 static HRESULT read_get_attribute_text( struct reader *reader, ULONG index, WS_XML_UTF8_TEXT **ret )
3839 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3840 WS_XML_ATTRIBUTE *attr;
3842 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
3843 return WS_E_INVALID_FORMAT;
3845 attr = elem->attributes[index];
3846 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
3848 FIXME( "text type %u not supported\n", attr->value->textType );
3849 return E_NOTIMPL;
3851 *ret = (WS_XML_UTF8_TEXT *)attr->value;
3852 return S_OK;
3855 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
3856 const WS_XML_STRING *ns, ULONG *index )
3858 ULONG i;
3859 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3861 if (!localname)
3863 *index = reader->current_attr;
3864 return TRUE;
3866 for (i = 0; i < elem->attributeCount; i++)
3868 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
3869 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
3871 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
3872 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
3874 *index = i;
3875 return TRUE;
3878 return FALSE;
3881 /**************************************************************************
3882 * WsFindAttribute [webservices.@]
3884 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
3885 const WS_XML_STRING *ns, BOOL required, ULONG *index,
3886 WS_ERROR *error )
3888 struct reader *reader = (struct reader *)handle;
3889 HRESULT hr = S_OK;
3891 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
3892 required, index, error );
3893 if (error) FIXME( "ignoring error parameter\n" );
3895 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
3897 EnterCriticalSection( &reader->cs );
3899 if (reader->magic != READER_MAGIC)
3901 LeaveCriticalSection( &reader->cs );
3902 return E_INVALIDARG;
3905 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
3907 LeaveCriticalSection( &reader->cs );
3908 return WS_E_INVALID_OPERATION;
3911 if (!find_attribute( reader, localname, ns, index ))
3913 if (required) hr = WS_E_INVALID_FORMAT;
3914 else
3916 *index = ~0u;
3917 hr = S_FALSE;
3921 LeaveCriticalSection( &reader->cs );
3922 return hr;
3925 static BOOL match_element( const struct node *node, const WS_XML_STRING *localname, const WS_XML_STRING *ns )
3927 const WS_XML_ELEMENT_NODE *elem = (const WS_XML_ELEMENT_NODE *)node;
3928 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3929 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
3930 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
3933 static HRESULT read_next_node( struct reader *reader )
3935 if (reader->current == reader->last) return read_node( reader );
3936 if (move_to_child_node( &reader->current )) return S_OK;
3937 if (move_to_next_node( &reader->current )) return S_OK;
3938 if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
3939 if (move_to_next_node( &reader->current )) return S_OK;
3940 return WS_E_INVALID_FORMAT;
3943 static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
3944 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3945 WS_XML_UTF8_TEXT **ret, BOOL *found )
3947 switch (mapping)
3949 case WS_ATTRIBUTE_TYPE_MAPPING:
3951 ULONG index;
3952 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
3953 return read_get_attribute_text( reader, index, ret );
3955 case WS_ELEMENT_TYPE_MAPPING:
3956 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
3957 case WS_ANY_ELEMENT_TYPE_MAPPING:
3959 *found = TRUE;
3960 if (localname)
3962 HRESULT hr;
3963 if (!match_element( reader->current, localname, ns ))
3965 *found = FALSE;
3966 return S_OK;
3968 if ((hr = read_next_node( reader )) != S_OK) return hr;
3969 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
3971 if (!move_to_parent_element( &reader->current )) return WS_E_INVALID_FORMAT;
3972 *found = FALSE;
3973 return S_OK;
3976 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
3978 *found = FALSE;
3979 return S_OK;
3981 return read_get_node_text( reader, ret );
3983 default:
3984 FIXME( "mapping %u not supported\n", mapping );
3985 return E_NOTIMPL;
3989 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
3990 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3991 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
3992 WS_HEAP *heap, void *ret, ULONG size )
3994 WS_XML_UTF8_TEXT *utf8;
3995 HRESULT hr;
3996 BOOL found, val = FALSE;
3998 if (desc)
4000 FIXME( "description not supported\n" );
4001 return E_NOTIMPL;
4003 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4004 if (found)
4006 ULONG len = utf8->value.length;
4007 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
4008 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
4009 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
4010 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
4011 else return WS_E_INVALID_FORMAT;
4014 switch (option)
4016 case WS_READ_REQUIRED_VALUE:
4017 if (!found) return WS_E_INVALID_FORMAT;
4018 /* fall through */
4020 case WS_READ_NILLABLE_VALUE:
4021 if (size != sizeof(val)) return E_INVALIDARG;
4022 *(BOOL *)ret = val;
4023 break;
4025 case WS_READ_REQUIRED_POINTER:
4026 if (!found) return WS_E_INVALID_FORMAT;
4027 /* fall through */
4029 case WS_READ_OPTIONAL_POINTER:
4030 case WS_READ_NILLABLE_POINTER:
4032 BOOL *heap_val = NULL;
4033 if (size != sizeof(heap_val)) return E_INVALIDARG;
4034 if (found)
4036 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4037 *heap_val = val;
4039 *(BOOL **)ret = heap_val;
4040 break;
4042 default:
4043 FIXME( "read option %u not supported\n", option );
4044 return E_NOTIMPL;
4047 return S_OK;
4050 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
4051 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4052 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
4053 WS_HEAP *heap, void *ret, ULONG size )
4055 WS_XML_UTF8_TEXT *utf8;
4056 HRESULT hr;
4057 INT64 val = 0;
4058 BOOL found;
4060 if (desc)
4062 FIXME( "description not supported\n" );
4063 return E_NOTIMPL;
4065 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4066 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
4067 return hr;
4069 switch (option)
4071 case WS_READ_REQUIRED_VALUE:
4072 if (!found) return WS_E_INVALID_FORMAT;
4073 /* fall through */
4075 case WS_READ_NILLABLE_VALUE:
4076 if (size != sizeof(INT8)) return E_INVALIDARG;
4077 *(INT8 *)ret = val;
4078 break;
4080 case WS_READ_REQUIRED_POINTER:
4081 if (!found) return WS_E_INVALID_FORMAT;
4082 /* fall through */
4084 case WS_READ_OPTIONAL_POINTER:
4085 case WS_READ_NILLABLE_POINTER:
4087 INT8 *heap_val = NULL;
4088 if (size != sizeof(heap_val)) return E_INVALIDARG;
4089 if (found)
4091 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4092 *heap_val = val;
4094 *(INT8 **)ret = heap_val;
4095 break;
4097 default:
4098 FIXME( "read option %u not supported\n", option );
4099 return E_NOTIMPL;
4102 return S_OK;
4105 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
4106 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4107 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
4108 WS_HEAP *heap, void *ret, ULONG size )
4110 WS_XML_UTF8_TEXT *utf8;
4111 HRESULT hr;
4112 INT64 val = 0;
4113 BOOL found;
4115 if (desc)
4117 FIXME( "description not supported\n" );
4118 return E_NOTIMPL;
4120 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4121 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
4122 return hr;
4124 switch (option)
4126 case WS_READ_REQUIRED_VALUE:
4127 if (!found) return WS_E_INVALID_FORMAT;
4128 /* fall through */
4130 case WS_READ_NILLABLE_VALUE:
4131 if (size != sizeof(INT16)) return E_INVALIDARG;
4132 *(INT16 *)ret = val;
4133 break;
4135 case WS_READ_REQUIRED_POINTER:
4136 if (!found) return WS_E_INVALID_FORMAT;
4137 /* fall through */
4139 case WS_READ_OPTIONAL_POINTER:
4140 case WS_READ_NILLABLE_POINTER:
4142 INT16 *heap_val = NULL;
4143 if (size != sizeof(heap_val)) return E_INVALIDARG;
4144 if (found)
4146 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4147 *heap_val = val;
4149 *(INT16 **)ret = heap_val;
4150 break;
4152 default:
4153 FIXME( "read option %u not supported\n", option );
4154 return E_NOTIMPL;
4157 return S_OK;
4160 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
4161 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4162 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
4163 WS_HEAP *heap, void *ret, ULONG size )
4165 WS_XML_UTF8_TEXT *utf8;
4166 HRESULT hr;
4167 INT64 val = 0;
4168 BOOL found;
4170 if (desc)
4172 FIXME( "description not supported\n" );
4173 return E_NOTIMPL;
4175 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4176 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
4177 return hr;
4179 switch (option)
4181 case WS_READ_REQUIRED_VALUE:
4182 if (!found) return WS_E_INVALID_FORMAT;
4183 /* fall through */
4185 case WS_READ_NILLABLE_VALUE:
4186 if (size != sizeof(INT32)) return E_INVALIDARG;
4187 *(INT32 *)ret = val;
4188 break;
4190 case WS_READ_REQUIRED_POINTER:
4191 if (!found) return WS_E_INVALID_FORMAT;
4192 /* fall through */
4194 case WS_READ_OPTIONAL_POINTER:
4195 case WS_READ_NILLABLE_POINTER:
4197 INT32 *heap_val = NULL;
4198 if (size != sizeof(heap_val)) return E_INVALIDARG;
4199 if (found)
4201 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4202 *heap_val = val;
4204 *(INT32 **)ret = heap_val;
4205 break;
4207 default:
4208 FIXME( "read option %u not supported\n", option );
4209 return E_NOTIMPL;
4212 return S_OK;
4215 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
4216 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4217 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
4218 WS_HEAP *heap, void *ret, ULONG size )
4220 WS_XML_UTF8_TEXT *utf8;
4221 HRESULT hr;
4222 INT64 val = 0;
4223 BOOL found;
4225 if (desc)
4227 FIXME( "description not supported\n" );
4228 return E_NOTIMPL;
4230 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4231 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
4232 return hr;
4234 switch (option)
4236 case WS_READ_REQUIRED_VALUE:
4237 if (!found) return WS_E_INVALID_FORMAT;
4238 /* fall through */
4240 case WS_READ_NILLABLE_VALUE:
4241 if (size != sizeof(val)) return E_INVALIDARG;
4242 *(INT64 *)ret = val;
4243 break;
4245 case WS_READ_REQUIRED_POINTER:
4246 if (!found) return WS_E_INVALID_FORMAT;
4247 /* fall through */
4249 case WS_READ_OPTIONAL_POINTER:
4250 case WS_READ_NILLABLE_POINTER:
4252 INT64 *heap_val = NULL;
4253 if (size != sizeof(heap_val)) return E_INVALIDARG;
4254 if (found)
4256 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4257 *heap_val = val;
4259 *(INT64 **)ret = heap_val;
4260 break;
4262 default:
4263 FIXME( "read option %u not supported\n", option );
4264 return E_NOTIMPL;
4267 return S_OK;
4270 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
4271 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4272 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
4273 WS_HEAP *heap, void *ret, ULONG size )
4275 WS_XML_UTF8_TEXT *utf8;
4276 HRESULT hr;
4277 UINT64 val = 0;
4278 BOOL found;
4280 if (desc)
4282 FIXME( "description not supported\n" );
4283 return E_NOTIMPL;
4285 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4286 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
4287 return hr;
4289 switch (option)
4291 case WS_READ_REQUIRED_VALUE:
4292 if (!found) return WS_E_INVALID_FORMAT;
4293 /* fall through */
4295 case WS_READ_NILLABLE_VALUE:
4296 if (size != sizeof(UINT8)) return E_INVALIDARG;
4297 *(UINT8 *)ret = val;
4298 break;
4300 case WS_READ_REQUIRED_POINTER:
4301 if (!found) return WS_E_INVALID_FORMAT;
4302 /* fall through */
4304 case WS_READ_OPTIONAL_POINTER:
4305 case WS_READ_NILLABLE_POINTER:
4307 UINT8 *heap_val = NULL;
4308 if (size != sizeof(heap_val)) return E_INVALIDARG;
4309 if (found)
4311 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4312 *heap_val = val;
4314 *(UINT8 **)ret = heap_val;
4315 break;
4317 default:
4318 FIXME( "read option %u not supported\n", option );
4319 return E_NOTIMPL;
4322 return S_OK;
4325 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
4326 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4327 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
4328 WS_HEAP *heap, void *ret, ULONG size )
4330 WS_XML_UTF8_TEXT *utf8;
4331 HRESULT hr;
4332 UINT64 val = 0;
4333 BOOL found;
4335 if (desc)
4337 FIXME( "description not supported\n" );
4338 return E_NOTIMPL;
4340 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4341 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
4342 return hr;
4344 switch (option)
4346 case WS_READ_REQUIRED_VALUE:
4347 if (!found) return WS_E_INVALID_FORMAT;
4348 /* fall through */
4350 case WS_READ_NILLABLE_VALUE:
4351 if (size != sizeof(UINT16)) return E_INVALIDARG;
4352 *(UINT16 *)ret = val;
4353 break;
4355 case WS_READ_REQUIRED_POINTER:
4356 if (!found) return WS_E_INVALID_FORMAT;
4357 /* fall through */
4359 case WS_READ_OPTIONAL_POINTER:
4360 case WS_READ_NILLABLE_POINTER:
4362 UINT16 *heap_val = NULL;
4363 if (size != sizeof(heap_val)) return E_INVALIDARG;
4364 if (found)
4366 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4367 *heap_val = val;
4369 *(UINT16 **)ret = heap_val;
4370 break;
4372 default:
4373 FIXME( "read option %u not supported\n", option );
4374 return E_NOTIMPL;
4377 return S_OK;
4380 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
4381 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4382 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
4383 WS_HEAP *heap, void *ret, ULONG size )
4385 WS_XML_UTF8_TEXT *utf8;
4386 HRESULT hr;
4387 UINT64 val = 0;
4388 BOOL found;
4390 if (desc)
4392 FIXME( "description not supported\n" );
4393 return E_NOTIMPL;
4395 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4396 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
4397 return hr;
4399 switch (option)
4401 case WS_READ_REQUIRED_VALUE:
4402 if (!found) return WS_E_INVALID_FORMAT;
4403 /* fall through */
4405 case WS_READ_NILLABLE_VALUE:
4406 if (size != sizeof(UINT32)) return E_INVALIDARG;
4407 *(UINT32 *)ret = val;
4408 break;
4410 case WS_READ_REQUIRED_POINTER:
4411 if (!found) return WS_E_INVALID_FORMAT;
4412 /* fall through */
4414 case WS_READ_OPTIONAL_POINTER:
4415 case WS_READ_NILLABLE_POINTER:
4417 UINT32 *heap_val = NULL;
4418 if (size != sizeof(heap_val)) return E_INVALIDARG;
4419 if (found)
4421 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4422 *heap_val = val;
4424 *(UINT32 **)ret = heap_val;
4425 break;
4427 default:
4428 FIXME( "read option %u not supported\n", option );
4429 return E_NOTIMPL;
4432 return S_OK;
4435 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
4436 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4437 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
4438 WS_HEAP *heap, void *ret, ULONG size )
4440 WS_XML_UTF8_TEXT *utf8;
4441 HRESULT hr;
4442 UINT64 val = 0;
4443 BOOL found;
4445 if (desc)
4447 FIXME( "description not supported\n" );
4448 return E_NOTIMPL;
4450 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4451 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
4452 return hr;
4454 switch (option)
4456 case WS_READ_REQUIRED_VALUE:
4457 if (!found) return WS_E_INVALID_FORMAT;
4458 /* fall through */
4460 case WS_READ_NILLABLE_VALUE:
4461 if (size != sizeof(val)) return E_INVALIDARG;
4462 *(UINT64 *)ret = val;
4463 break;
4465 case WS_READ_REQUIRED_POINTER:
4466 if (!found) return WS_E_INVALID_FORMAT;
4467 /* fall through */
4469 case WS_READ_OPTIONAL_POINTER:
4470 case WS_READ_NILLABLE_POINTER:
4472 UINT64 *heap_val = NULL;
4473 if (size != sizeof(heap_val)) return E_INVALIDARG;
4474 if (found)
4476 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4477 *heap_val = val;
4479 *(UINT64 **)ret = heap_val;
4480 break;
4482 default:
4483 FIXME( "read option %u not supported\n", option );
4484 return E_NOTIMPL;
4487 return S_OK;
4490 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
4491 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4492 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
4493 WS_HEAP *heap, void *ret, ULONG size )
4495 WS_XML_UTF8_TEXT *utf8;
4496 HRESULT hr;
4497 double val = 0.0;
4498 BOOL found;
4500 if (desc) FIXME( "ignoring description\n" );
4502 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4503 if (found && (hr = str_to_double( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
4505 switch (option)
4507 case WS_READ_REQUIRED_VALUE:
4508 if (!found) return WS_E_INVALID_FORMAT;
4509 /* fall through */
4511 case WS_READ_NILLABLE_VALUE:
4512 if (size != sizeof(val)) return E_INVALIDARG;
4513 *(double *)ret = val;
4514 break;
4516 case WS_READ_REQUIRED_POINTER:
4517 if (!found) return WS_E_INVALID_FORMAT;
4518 /* fall through */
4520 case WS_READ_OPTIONAL_POINTER:
4521 case WS_READ_NILLABLE_POINTER:
4523 double *heap_val = NULL;
4524 if (size != sizeof(heap_val)) return E_INVALIDARG;
4525 if (found)
4527 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4528 *heap_val = val;
4530 *(double **)ret = heap_val;
4531 break;
4533 default:
4534 FIXME( "read option %u not supported\n", option );
4535 return E_NOTIMPL;
4538 return S_OK;
4541 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
4542 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4543 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
4544 WS_HEAP *heap, WCHAR **ret, ULONG size )
4546 WS_XML_UTF8_TEXT *utf8;
4547 HRESULT hr;
4548 WCHAR *str = NULL;
4549 BOOL found;
4551 if (desc)
4553 FIXME( "description not supported\n" );
4554 return E_NOTIMPL;
4556 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4557 if (found && !(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
4559 switch (option)
4561 case WS_READ_REQUIRED_POINTER:
4562 if (!found && !(str = ws_alloc_zero( heap, 1 ))) return WS_E_QUOTA_EXCEEDED;
4563 /* fall through */
4565 case WS_READ_OPTIONAL_POINTER:
4566 case WS_READ_NILLABLE_POINTER:
4567 if (size != sizeof(str)) return E_INVALIDARG;
4568 *ret = str;
4569 break;
4571 default:
4572 FIXME( "read option %u not supported\n", option );
4573 return E_NOTIMPL;
4576 return S_OK;
4579 static HRESULT get_enum_value( const WS_XML_UTF8_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
4581 ULONG i;
4582 for (i = 0; i < desc->valueCount; i++)
4584 if (WsXmlStringEquals( &text->value, desc->values[i].name, NULL ) == S_OK)
4586 *ret = desc->values[i].value;
4587 return S_OK;
4590 return WS_E_INVALID_FORMAT;
4593 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
4594 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4595 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
4596 WS_HEAP *heap, void *ret, ULONG size )
4598 WS_XML_UTF8_TEXT *utf8;
4599 HRESULT hr;
4600 int val = 0;
4601 BOOL found;
4603 if (!desc) return E_INVALIDARG;
4605 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4606 if (found && (hr = get_enum_value( utf8, desc, &val )) != S_OK) return hr;
4608 switch (option)
4610 case WS_READ_REQUIRED_VALUE:
4611 if (!found) return WS_E_INVALID_FORMAT;
4612 /* fall through */
4614 case WS_READ_NILLABLE_VALUE:
4615 if (size != sizeof(val)) return E_INVALIDARG;
4616 *(int *)ret = val;
4617 break;
4619 case WS_READ_REQUIRED_POINTER:
4620 if (!found) return WS_E_INVALID_FORMAT;
4621 /* fall through */
4623 case WS_READ_OPTIONAL_POINTER:
4624 case WS_READ_NILLABLE_POINTER:
4626 int *heap_val = NULL;
4627 if (size != sizeof(heap_val)) return E_INVALIDARG;
4628 if (found)
4630 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4631 *heap_val = val;
4633 *(int **)ret = heap_val;
4634 break;
4636 default:
4637 FIXME( "read option %u not supported\n", option );
4638 return E_NOTIMPL;
4641 return S_OK;
4644 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
4645 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4646 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
4647 WS_HEAP *heap, void *ret, ULONG size )
4649 WS_XML_UTF8_TEXT *utf8;
4650 HRESULT hr;
4651 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
4652 BOOL found;
4654 if (desc) FIXME( "ignoring description\n" );
4656 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4657 if (found && (hr = str_to_datetime( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
4659 switch (option)
4661 case WS_READ_REQUIRED_VALUE:
4662 if (!found) return WS_E_INVALID_FORMAT;
4663 /* fall through */
4665 case WS_READ_NILLABLE_VALUE:
4666 if (size != sizeof(val)) return E_INVALIDARG;
4667 *(WS_DATETIME *)ret = val;
4668 break;
4670 case WS_READ_REQUIRED_POINTER:
4671 if (!found) return WS_E_INVALID_FORMAT;
4672 /* fall through */
4674 case WS_READ_OPTIONAL_POINTER:
4675 case WS_READ_NILLABLE_POINTER:
4677 WS_DATETIME *heap_val = NULL;
4678 if (size != sizeof(heap_val)) return E_INVALIDARG;
4679 if (found)
4681 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4682 *heap_val = val;
4684 *(WS_DATETIME **)ret = heap_val;
4685 break;
4687 default:
4688 FIXME( "read option %u not supported\n", option );
4689 return E_NOTIMPL;
4692 return S_OK;
4695 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
4696 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4697 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
4698 WS_HEAP *heap, void *ret, ULONG size )
4700 WS_XML_UTF8_TEXT *utf8;
4701 GUID val = {0};
4702 HRESULT hr;
4703 BOOL found;
4705 if (desc) FIXME( "ignoring description\n" );
4707 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4708 if (found && (hr = str_to_guid( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
4710 switch (option)
4712 case WS_READ_REQUIRED_VALUE:
4713 if (!found) return WS_E_INVALID_FORMAT;
4714 /* fall through */
4716 case WS_READ_NILLABLE_VALUE:
4717 if (size != sizeof(val)) return E_INVALIDARG;
4718 *(GUID *)ret = val;
4719 break;
4721 case WS_READ_REQUIRED_POINTER:
4722 if (!found) return WS_E_INVALID_FORMAT;
4723 /* fall through */
4725 case WS_READ_OPTIONAL_POINTER:
4726 case WS_READ_NILLABLE_POINTER:
4728 GUID *heap_val = NULL;
4729 if (size != sizeof(heap_val)) return E_INVALIDARG;
4730 if (found)
4732 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4733 *heap_val = val;
4735 *(GUID **)ret = heap_val;
4736 break;
4738 default:
4739 FIXME( "read option %u not supported\n", option );
4740 return E_NOTIMPL;
4743 return S_OK;
4746 static HRESULT read_type_unique_id( struct reader *reader, WS_TYPE_MAPPING mapping,
4747 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4748 const WS_UNIQUE_ID_DESCRIPTION *desc, WS_READ_OPTION option,
4749 WS_HEAP *heap, void *ret, ULONG size )
4751 WS_XML_UTF8_TEXT *utf8;
4752 WS_UNIQUE_ID val = {{0}};
4753 HRESULT hr;
4754 BOOL found;
4756 if (desc) FIXME( "ignoring description\n" );
4758 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4759 if (found && (hr = str_to_unique_id( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK) return hr;
4761 switch (option)
4763 case WS_READ_REQUIRED_VALUE:
4764 if (!found) return WS_E_INVALID_FORMAT;
4765 /* fall through */
4767 case WS_READ_NILLABLE_VALUE:
4768 if (size != sizeof(val)) return E_INVALIDARG;
4769 *(WS_UNIQUE_ID *)ret = val;
4770 break;
4772 case WS_READ_REQUIRED_POINTER:
4773 if (!found) return WS_E_INVALID_FORMAT;
4774 /* fall through */
4776 case WS_READ_OPTIONAL_POINTER:
4777 case WS_READ_NILLABLE_POINTER:
4779 WS_UNIQUE_ID *heap_val = NULL;
4780 if (size != sizeof(heap_val)) return E_INVALIDARG;
4781 if (found)
4783 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4784 *heap_val = val;
4786 *(WS_UNIQUE_ID **)ret = heap_val;
4787 break;
4789 default:
4790 FIXME( "read option %u not supported\n", option );
4791 return E_NOTIMPL;
4794 return S_OK;
4797 static HRESULT read_type_string( struct reader *reader, WS_TYPE_MAPPING mapping,
4798 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4799 const WS_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
4800 WS_HEAP *heap, void *ret, ULONG size )
4802 WS_XML_UTF8_TEXT *utf8;
4803 WS_STRING val = {0};
4804 HRESULT hr;
4805 BOOL found;
4807 if (desc) FIXME( "ignoring description\n" );
4809 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4810 if (found && (hr = str_to_string( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
4811 return hr;
4813 switch (option)
4815 case WS_READ_REQUIRED_VALUE:
4816 case WS_READ_NILLABLE_VALUE:
4817 if (size != sizeof(val)) return E_INVALIDARG;
4818 *(WS_STRING *)ret = val;
4819 break;
4821 case WS_READ_REQUIRED_POINTER:
4823 WS_STRING *heap_val;
4824 if (size != sizeof(heap_val)) return E_INVALIDARG;
4825 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4826 *heap_val = val;
4827 *(WS_STRING **)ret = heap_val;
4828 break;
4830 case WS_READ_OPTIONAL_POINTER:
4831 case WS_READ_NILLABLE_POINTER:
4833 WS_STRING *heap_val = NULL;
4834 if (size != sizeof(heap_val)) return E_INVALIDARG;
4835 if (found)
4837 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4838 *heap_val = val;
4840 *(WS_STRING **)ret = heap_val;
4841 break;
4843 default:
4844 FIXME( "read option %u not supported\n", option );
4845 return E_NOTIMPL;
4848 return S_OK;
4851 static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
4852 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4853 const WS_BYTES_DESCRIPTION *desc, WS_READ_OPTION option,
4854 WS_HEAP *heap, void *ret, ULONG size )
4856 WS_XML_UTF8_TEXT *utf8;
4857 WS_BYTES val = {0};
4858 HRESULT hr;
4859 BOOL found;
4861 if (desc) FIXME( "ignoring description\n" );
4863 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4864 if (found && (hr = str_to_bytes( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
4865 return hr;
4867 switch (option)
4869 case WS_READ_REQUIRED_VALUE:
4870 case WS_READ_NILLABLE_VALUE:
4871 if (size != sizeof(val)) return E_INVALIDARG;
4872 *(WS_BYTES *)ret = val;
4873 break;
4875 case WS_READ_REQUIRED_POINTER:
4877 WS_BYTES *heap_val;
4878 if (size != sizeof(heap_val)) return E_INVALIDARG;
4879 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4880 *heap_val = val;
4881 *(WS_BYTES **)ret = heap_val;
4882 break;
4884 case WS_READ_OPTIONAL_POINTER:
4885 case WS_READ_NILLABLE_POINTER:
4887 WS_BYTES *heap_val = NULL;
4888 if (size != sizeof(heap_val)) return E_INVALIDARG;
4889 if (found)
4891 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4892 *heap_val = val;
4894 *(WS_BYTES **)ret = heap_val;
4895 break;
4897 default:
4898 FIXME( "read option %u not supported\n", option );
4899 return E_NOTIMPL;
4902 return S_OK;
4905 static HRESULT read_type_xml_string( struct reader *reader, WS_TYPE_MAPPING mapping,
4906 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4907 const WS_XML_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
4908 WS_HEAP *heap, void *ret, ULONG size )
4910 WS_XML_UTF8_TEXT *utf8;
4911 WS_XML_STRING val = {0};
4912 HRESULT hr;
4913 BOOL found;
4915 if (desc) FIXME( "ignoring description\n" );
4917 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4918 if (found && (hr = str_to_xml_string( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
4919 return hr;
4921 switch (option)
4923 case WS_READ_REQUIRED_VALUE:
4924 case WS_READ_NILLABLE_VALUE:
4925 if (size != sizeof(val)) return E_INVALIDARG;
4926 *(WS_XML_STRING *)ret = val;
4927 break;
4929 case WS_READ_REQUIRED_POINTER:
4931 WS_XML_STRING *heap_val;
4932 if (size != sizeof(heap_val)) return E_INVALIDARG;
4933 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4934 *heap_val = val;
4935 *(WS_XML_STRING **)ret = heap_val;
4936 break;
4938 case WS_READ_OPTIONAL_POINTER:
4939 case WS_READ_NILLABLE_POINTER:
4941 WS_XML_STRING *heap_val = NULL;
4942 if (size != sizeof(heap_val)) return E_INVALIDARG;
4943 if (found)
4945 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
4946 *heap_val = val;
4948 *(WS_XML_STRING **)ret = heap_val;
4949 break;
4951 default:
4952 FIXME( "read option %u not supported\n", option );
4953 return E_NOTIMPL;
4956 return S_OK;
4959 static HRESULT read_type_qname( struct reader *reader, WS_TYPE_MAPPING mapping,
4960 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
4961 const WS_XML_QNAME_DESCRIPTION *desc, WS_READ_OPTION option,
4962 WS_HEAP *heap, void *ret, ULONG size )
4964 WS_XML_UTF8_TEXT *utf8;
4965 WS_XML_QNAME val = {{0}};
4966 HRESULT hr;
4967 BOOL found;
4969 if (desc) FIXME( "ignoring description\n" );
4971 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
4972 if ((hr = read_startelement( reader )) != S_OK) return hr;
4973 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
4975 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
4976 if (found && (hr = str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap,
4977 NULL, &val.localName, &val.ns )) != S_OK) return hr;
4979 switch (option)
4981 case WS_READ_REQUIRED_VALUE:
4982 if (!found) return WS_E_INVALID_FORMAT;
4983 /* fall through */
4985 case WS_READ_NILLABLE_VALUE:
4986 if (size != sizeof(val)) return E_INVALIDARG;
4987 *(WS_XML_QNAME *)ret = val;
4988 break;
4990 case WS_READ_REQUIRED_POINTER:
4991 if (!found) return WS_E_INVALID_FORMAT;
4992 /* fall through */
4994 case WS_READ_OPTIONAL_POINTER:
4995 case WS_READ_NILLABLE_POINTER:
4997 WS_XML_QNAME *heap_val = NULL;
4998 if (size != sizeof(heap_val)) return E_INVALIDARG;
4999 if (found)
5001 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
5002 *heap_val = val;
5004 *(WS_XML_QNAME **)ret = heap_val;
5005 break;
5007 default:
5008 FIXME( "read option %u not supported\n", option );
5009 return E_NOTIMPL;
5012 return S_OK;
5015 static BOOL is_empty_text_node( const struct node *node )
5017 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
5018 const WS_XML_UTF8_TEXT *utf8;
5019 ULONG i;
5021 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
5022 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
5024 ERR( "unhandled text type %u\n", text->text->textType );
5025 return FALSE;
5027 utf8 = (const WS_XML_UTF8_TEXT *)text->text;
5028 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
5029 return TRUE;
5032 /* skips comment and empty text nodes */
5033 static HRESULT read_type_next_node( struct reader *reader )
5035 for (;;)
5037 HRESULT hr;
5038 WS_XML_NODE_TYPE type;
5040 if ((hr = read_next_node( reader )) != S_OK) return hr;
5041 type = node_type( reader->current );
5042 if (type == WS_XML_NODE_TYPE_COMMENT ||
5043 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
5044 return S_OK;
5048 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
5049 const WS_XML_STRING *ns )
5051 struct node *node;
5052 ULONG attr;
5053 HRESULT hr;
5055 if (!localname) return S_OK; /* assume reader is already correctly positioned */
5056 if (reader->current == reader->last)
5058 BOOL found;
5059 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
5060 if (!found) return WS_E_INVALID_FORMAT;
5062 if (match_element( reader->current, localname, ns )) return S_OK;
5064 node = reader->current;
5065 attr = reader->current_attr;
5067 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
5068 if (match_element( reader->current, localname, ns )) return S_OK;
5070 reader->current = node;
5071 reader->current_attr = attr;
5073 return WS_E_INVALID_FORMAT;
5076 ULONG get_type_size( WS_TYPE type, const void *desc )
5078 switch (type)
5080 case WS_INT8_TYPE:
5081 case WS_UINT8_TYPE:
5082 return sizeof(INT8);
5084 case WS_INT16_TYPE:
5085 case WS_UINT16_TYPE:
5086 return sizeof(INT16);
5088 case WS_BOOL_TYPE:
5089 case WS_INT32_TYPE:
5090 case WS_UINT32_TYPE:
5091 case WS_ENUM_TYPE:
5092 return sizeof(INT32);
5094 case WS_INT64_TYPE:
5095 case WS_UINT64_TYPE:
5096 return sizeof(INT64);
5098 case WS_DOUBLE_TYPE:
5099 return sizeof(double);
5101 case WS_DATETIME_TYPE:
5102 return sizeof(WS_DATETIME);
5104 case WS_GUID_TYPE:
5105 return sizeof(GUID);
5107 case WS_STRING_TYPE:
5108 return sizeof(WS_STRING);
5110 case WS_WSZ_TYPE:
5111 return sizeof(WCHAR *);
5113 case WS_BYTES_TYPE:
5114 return sizeof(WS_BYTES);
5116 case WS_XML_STRING_TYPE:
5117 return sizeof(WS_XML_STRING);
5119 case WS_XML_QNAME_TYPE:
5120 return sizeof(WS_XML_QNAME);
5122 case WS_DESCRIPTION_TYPE:
5123 return sizeof(WS_STRUCT_DESCRIPTION *);
5125 case WS_STRUCT_TYPE:
5127 const WS_STRUCT_DESCRIPTION *desc_struct = desc;
5128 return desc_struct->size;
5130 case WS_UNION_TYPE:
5132 const WS_UNION_DESCRIPTION *desc_union = desc;
5133 return desc_union->size;
5135 default:
5136 ERR( "unhandled type %u\n", type );
5137 return 0;
5141 static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
5143 if (options & WS_FIELD_POINTER)
5145 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
5146 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
5147 return WS_READ_REQUIRED_POINTER;
5150 switch (type)
5152 case WS_BOOL_TYPE:
5153 case WS_INT8_TYPE:
5154 case WS_INT16_TYPE:
5155 case WS_INT32_TYPE:
5156 case WS_INT64_TYPE:
5157 case WS_UINT8_TYPE:
5158 case WS_UINT16_TYPE:
5159 case WS_UINT32_TYPE:
5160 case WS_UINT64_TYPE:
5161 case WS_DOUBLE_TYPE:
5162 case WS_DATETIME_TYPE:
5163 case WS_GUID_TYPE:
5164 case WS_UNIQUE_ID_TYPE:
5165 case WS_STRING_TYPE:
5166 case WS_BYTES_TYPE:
5167 case WS_XML_STRING_TYPE:
5168 case WS_XML_QNAME_TYPE:
5169 case WS_STRUCT_TYPE:
5170 case WS_ENUM_TYPE:
5171 if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
5172 return WS_READ_REQUIRED_VALUE;
5174 case WS_WSZ_TYPE:
5175 case WS_DESCRIPTION_TYPE:
5176 if (options & WS_FIELD_NILLABLE) return WS_READ_NILLABLE_POINTER;
5177 if (options & WS_FIELD_OPTIONAL) return WS_READ_OPTIONAL_POINTER;
5178 return WS_READ_REQUIRED_POINTER;
5180 default:
5181 FIXME( "unhandled type %u\n", type );
5182 return 0;
5186 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
5187 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
5188 void *, ULONG );
5190 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
5191 WS_HEAP *heap, void **ret, ULONG *count )
5193 HRESULT hr;
5194 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
5195 WS_READ_OPTION option;
5196 char *buf;
5198 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
5200 /* wrapper element */
5201 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
5202 return hr;
5204 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
5205 item_size = get_type_size( desc->type, desc->typeDescription );
5206 else
5207 item_size = sizeof(void *);
5209 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
5210 for (;;)
5212 if (nb_items >= nb_allocated)
5214 SIZE_T old_size = nb_allocated * item_size, new_size = old_size * 2;
5215 if (!(buf = ws_realloc_zero( heap, buf, old_size, new_size )))
5216 return WS_E_QUOTA_EXCEEDED;
5217 nb_allocated *= 2;
5219 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
5220 desc->typeDescription, option, heap, buf + offset, item_size );
5221 if (hr == WS_E_INVALID_FORMAT) break;
5222 if (hr != S_OK)
5224 ws_free( heap, buf, nb_allocated * item_size );
5225 return hr;
5227 offset += item_size;
5228 nb_items++;
5231 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
5233 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
5235 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
5236 desc->itemRange->maxItemCount );
5237 ws_free( heap, buf, nb_allocated * item_size );
5238 return WS_E_INVALID_FORMAT;
5241 *count = nb_items;
5242 *ret = buf;
5244 return S_OK;
5247 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
5248 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
5250 HRESULT hr;
5251 if (reader->current == reader->last)
5253 BOOL found;
5254 if ((hr = read_to_startelement( reader, &found )) != S_OK) return S_OK;
5255 if (!found) return WS_E_INVALID_FORMAT;
5257 if ((hr = read_next_node( reader )) != S_OK) return hr;
5258 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
5260 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
5261 desc->typeDescription, option, heap, ret, size );
5264 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
5265 WS_HEAP *heap, char *buf, ULONG offset )
5267 char *ptr;
5268 WS_READ_OPTION option;
5269 ULONG size;
5270 HRESULT hr;
5272 if (!desc) return E_INVALIDARG;
5273 if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE|WS_FIELD_NILLABLE_ITEM))
5275 FIXME( "options %08x not supported\n", desc->options );
5276 return E_NOTIMPL;
5278 if (!(option = get_field_read_option( desc->type, desc->options ))) return E_INVALIDARG;
5280 if (option == WS_READ_REQUIRED_VALUE || option == WS_READ_NILLABLE_VALUE)
5281 size = get_type_size( desc->type, desc->typeDescription );
5282 else
5283 size = sizeof(void *);
5285 ptr = buf + offset;
5286 switch (desc->mapping)
5288 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING:
5289 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
5290 return S_OK;
5292 case WS_ATTRIBUTE_FIELD_MAPPING:
5293 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
5294 desc->typeDescription, option, heap, ptr, size );
5295 break;
5297 case WS_ELEMENT_FIELD_MAPPING:
5298 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
5299 desc->typeDescription, option, heap, ptr, size );
5300 break;
5302 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
5304 ULONG count;
5305 hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, &count );
5306 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
5307 break;
5309 case WS_TEXT_FIELD_MAPPING:
5310 hr = read_type_text( reader, desc, option, heap, ptr, size );
5311 break;
5313 default:
5314 FIXME( "unhandled field mapping %u\n", desc->mapping );
5315 return E_NOTIMPL;
5318 if (hr == WS_E_INVALID_FORMAT)
5320 switch (option)
5322 case WS_READ_REQUIRED_VALUE:
5323 case WS_READ_REQUIRED_POINTER:
5324 return WS_E_INVALID_FORMAT;
5326 case WS_READ_NILLABLE_VALUE:
5327 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
5328 return S_OK;
5330 case WS_READ_OPTIONAL_POINTER:
5331 case WS_READ_NILLABLE_POINTER:
5332 *(void **)ptr = NULL;
5333 return S_OK;
5335 default:
5336 ERR( "unhandled option %u\n", option );
5337 return E_NOTIMPL;
5341 return hr;
5344 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
5345 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5346 const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
5347 WS_HEAP *heap, void *ret, ULONG size )
5349 ULONG i, offset;
5350 HRESULT hr;
5351 char *buf;
5353 if (!desc) return E_INVALIDARG;
5354 if (desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
5356 FIXME( "struct options %08x not supported\n",
5357 desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT );
5360 switch (option)
5362 case WS_READ_REQUIRED_POINTER:
5363 case WS_READ_OPTIONAL_POINTER:
5364 case WS_READ_NILLABLE_POINTER:
5365 if (size != sizeof(void *)) return E_INVALIDARG;
5366 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
5367 break;
5369 case WS_READ_REQUIRED_VALUE:
5370 case WS_READ_NILLABLE_VALUE:
5371 if (size != desc->size) return E_INVALIDARG;
5372 buf = ret;
5373 break;
5375 default:
5376 FIXME( "unhandled read option %u\n", option );
5377 return E_NOTIMPL;
5380 for (i = 0; i < desc->fieldCount; i++)
5382 offset = desc->fields[i]->offset;
5383 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf, offset )) != S_OK)
5384 break;
5387 switch (option)
5389 case WS_READ_REQUIRED_POINTER:
5390 if (hr != S_OK)
5392 ws_free( heap, buf, desc->size );
5393 return hr;
5395 *(char **)ret = buf;
5396 break;
5398 case WS_READ_OPTIONAL_POINTER:
5399 case WS_READ_NILLABLE_POINTER:
5400 if (is_nil_value( buf, desc->size ))
5402 ws_free( heap, buf, desc->size );
5403 buf = NULL;
5405 *(char **)ret = buf;
5406 break;
5408 case WS_READ_REQUIRED_VALUE:
5409 case WS_READ_NILLABLE_VALUE:
5410 if (hr != S_OK) return hr;
5411 break;
5413 default:
5414 ERR( "unhandled read option %u\n", option );
5415 return E_NOTIMPL;
5418 if (desc->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
5420 struct node *parent = find_parent( reader );
5421 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
5423 return S_OK;
5426 static HRESULT start_mapping( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
5427 const WS_XML_STRING *ns )
5429 switch (mapping)
5431 case WS_ELEMENT_TYPE_MAPPING:
5432 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
5433 return read_type_next_element_node( reader, localname, ns );
5435 case WS_ANY_ELEMENT_TYPE_MAPPING:
5436 case WS_ATTRIBUTE_TYPE_MAPPING:
5437 return S_OK;
5439 default:
5440 FIXME( "unhandled mapping %u\n", mapping );
5441 return E_NOTIMPL;
5445 static HRESULT read_type_endelement_node( struct reader *reader )
5447 const struct node *parent = find_parent( reader );
5448 HRESULT hr;
5450 for (;;)
5452 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
5453 if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == parent)
5455 return S_OK;
5457 if (read_end_of_data( reader ) || !(parent->flags & NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT)) break;
5460 return WS_E_INVALID_FORMAT;
5463 static HRESULT end_mapping( struct reader *reader, WS_TYPE_MAPPING mapping )
5465 switch (mapping)
5467 case WS_ELEMENT_TYPE_MAPPING:
5468 return read_type_endelement_node( reader );
5470 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
5471 return read_type_next_node( reader );
5473 case WS_ATTRIBUTE_TYPE_MAPPING:
5474 default:
5475 return S_OK;
5479 static HRESULT is_nil_element( const WS_XML_ELEMENT_NODE *elem )
5481 static const WS_XML_STRING localname = {3, (BYTE *)"nil"};
5482 static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance"};
5483 ULONG i;
5485 for (i = 0; i < elem->attributeCount; i++)
5487 const WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)elem->attributes[i]->value;
5489 if (elem->attributes[i]->isXmlNs) continue;
5490 if (WsXmlStringEquals( elem->attributes[i]->localName, &localname, NULL ) == S_OK &&
5491 WsXmlStringEquals( elem->attributes[i]->ns, &ns, NULL ) == S_OK &&
5492 text->value.length == 4 && !memcmp( text->value.bytes, "true", 4 )) return TRUE;
5494 return FALSE;
5497 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
5498 const WS_XML_STRING *localname, const WS_XML_STRING *ns, const void *desc,
5499 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size )
5501 HRESULT hr;
5503 if ((hr = start_mapping( reader, mapping, localname, ns )) != S_OK) return hr;
5505 if (mapping == WS_ELEMENT_TYPE_MAPPING && is_nil_element( &reader->current->hdr ))
5507 if (option != WS_READ_NILLABLE_POINTER && option != WS_READ_NILLABLE_VALUE) return WS_E_INVALID_FORMAT;
5508 return end_mapping( reader, mapping );
5511 switch (type)
5513 case WS_BOOL_TYPE:
5514 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5515 return hr;
5516 break;
5518 case WS_INT8_TYPE:
5519 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5520 return hr;
5521 break;
5523 case WS_INT16_TYPE:
5524 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5525 return hr;
5526 break;
5528 case WS_INT32_TYPE:
5529 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5530 return hr;
5531 break;
5533 case WS_INT64_TYPE:
5534 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5535 return hr;
5536 break;
5538 case WS_UINT8_TYPE:
5539 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5540 return hr;
5541 break;
5543 case WS_UINT16_TYPE:
5544 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5545 return hr;
5546 break;
5548 case WS_UINT32_TYPE:
5549 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5550 return hr;
5551 break;
5553 case WS_UINT64_TYPE:
5554 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5555 return hr;
5556 break;
5558 case WS_DOUBLE_TYPE:
5559 if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5560 return hr;
5561 break;
5563 case WS_DATETIME_TYPE:
5564 if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5565 return hr;
5566 break;
5568 case WS_GUID_TYPE:
5569 if ((hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5570 return hr;
5571 break;
5573 case WS_UNIQUE_ID_TYPE:
5574 if ((hr = read_type_unique_id( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5575 return hr;
5576 break;
5578 case WS_STRING_TYPE:
5579 if ((hr = read_type_string( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5580 return hr;
5581 break;
5583 case WS_WSZ_TYPE:
5584 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5585 return hr;
5586 break;
5588 case WS_BYTES_TYPE:
5589 if ((hr = read_type_bytes( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5590 return hr;
5591 break;
5593 case WS_XML_STRING_TYPE:
5594 if ((hr = read_type_xml_string( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5595 return hr;
5596 break;
5598 case WS_XML_QNAME_TYPE:
5599 if ((hr = read_type_qname( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5600 return hr;
5601 break;
5603 case WS_STRUCT_TYPE:
5604 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5605 return hr;
5606 break;
5608 case WS_ENUM_TYPE:
5609 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
5610 return hr;
5611 break;
5613 default:
5614 FIXME( "type %u not supported\n", type );
5615 return E_NOTIMPL;
5618 return end_mapping( reader, mapping );
5621 /**************************************************************************
5622 * WsReadType [webservices.@]
5624 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
5625 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
5626 ULONG size, WS_ERROR *error )
5628 struct reader *reader = (struct reader *)handle;
5629 HRESULT hr;
5631 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
5632 size, error );
5633 if (error) FIXME( "ignoring error parameter\n" );
5635 if (!reader || !value) return E_INVALIDARG;
5637 EnterCriticalSection( &reader->cs );
5639 if (reader->magic != READER_MAGIC)
5641 LeaveCriticalSection( &reader->cs );
5642 return E_INVALIDARG;
5645 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
5647 LeaveCriticalSection( &reader->cs );
5648 return hr;
5651 switch (mapping)
5653 case WS_ELEMENT_TYPE_MAPPING:
5654 hr = read_node( reader );
5655 break;
5657 default:
5658 break;
5661 if (hr == S_OK && !read_end_of_data( reader )) hr = WS_E_INVALID_FORMAT;
5663 LeaveCriticalSection( &reader->cs );
5664 return hr;
5667 HRESULT read_header( WS_XML_READER *handle, const WS_XML_STRING *localname, const WS_XML_STRING *ns,
5668 WS_TYPE type, const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
5669 ULONG size )
5671 struct reader *reader = (struct reader *)handle;
5672 HRESULT hr;
5674 EnterCriticalSection( &reader->cs );
5676 if (reader->magic != READER_MAGIC)
5678 LeaveCriticalSection( &reader->cs );
5679 return E_INVALIDARG;
5682 hr = read_type( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, localname, ns, desc, option, heap,
5683 value, size );
5685 LeaveCriticalSection( &reader->cs );
5686 return hr;
5689 /**************************************************************************
5690 * WsReadElement [webservices.@]
5692 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
5693 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
5694 WS_ERROR *error )
5696 struct reader *reader = (struct reader *)handle;
5697 HRESULT hr;
5699 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
5700 if (error) FIXME( "ignoring error parameter\n" );
5702 if (!reader || !desc || !value) return E_INVALIDARG;
5704 EnterCriticalSection( &reader->cs );
5706 if (reader->magic != READER_MAGIC)
5708 LeaveCriticalSection( &reader->cs );
5709 return E_INVALIDARG;
5712 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
5713 desc->elementNs, desc->typeDescription, option, heap, value, size );
5715 LeaveCriticalSection( &reader->cs );
5716 return hr;
5719 /**************************************************************************
5720 * WsReadValue [webservices.@]
5722 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
5723 WS_ERROR *error )
5725 struct reader *reader = (struct reader *)handle;
5726 WS_TYPE type = map_value_type( value_type );
5727 HRESULT hr;
5729 TRACE( "%p %u %p %u %p\n", handle, type, value, size, error );
5730 if (error) FIXME( "ignoring error parameter\n" );
5732 if (!reader || !value || type == ~0u) return E_INVALIDARG;
5734 EnterCriticalSection( &reader->cs );
5736 if (reader->magic != READER_MAGIC)
5738 LeaveCriticalSection( &reader->cs );
5739 return E_INVALIDARG;
5742 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
5743 NULL, value, size );
5745 LeaveCriticalSection( &reader->cs );
5746 return hr;
5749 /**************************************************************************
5750 * WsReadAttribute [webservices.@]
5752 HRESULT WINAPI WsReadAttribute( WS_XML_READER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
5753 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
5754 WS_ERROR *error )
5756 struct reader *reader = (struct reader *)handle;
5757 HRESULT hr;
5759 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
5760 if (error) FIXME( "ignoring error parameter\n" );
5762 if (!reader || !desc || !value) return E_INVALIDARG;
5764 EnterCriticalSection( &reader->cs );
5766 if (reader->magic != READER_MAGIC)
5768 LeaveCriticalSection( &reader->cs );
5769 return E_INVALIDARG;
5772 if (!reader->input_type)
5774 LeaveCriticalSection( &reader->cs );
5775 return WS_E_INVALID_OPERATION;
5778 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->attributeLocalName,
5779 desc->attributeNs, desc->typeDescription, option, heap, value, size );
5781 LeaveCriticalSection( &reader->cs );
5782 return hr;
5785 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
5787 static const char bom[] = {0xef,0xbb,0xbf};
5788 const unsigned char *p = data;
5790 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
5791 (size > 2 && !(*offset = 0));
5794 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
5796 static const char bom[] = {0xff,0xfe};
5797 const unsigned char *p = data;
5799 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
5800 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
5803 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
5805 WS_CHARSET ret = 0;
5807 /* FIXME: parse xml declaration */
5809 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
5810 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
5811 else
5813 FIXME( "charset not recognized\n" );
5814 return 0;
5817 TRACE( "detected charset %u\n", ret );
5818 return ret;
5821 static void set_input_buffer( struct reader *reader, struct xmlbuf *buf, const unsigned char *data, ULONG size )
5823 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
5824 reader->input_buf = buf;
5825 reader->input_data = data;
5826 reader->input_size = size;
5828 reader->read_size = reader->input_size;
5829 reader->read_pos = 0;
5830 reader->read_bufptr = reader->input_data;
5832 reader->text_conv_offset = 0;
5835 /**************************************************************************
5836 * WsSetInput [webservices.@]
5838 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
5839 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
5840 ULONG count, WS_ERROR *error )
5842 struct reader *reader = (struct reader *)handle;
5843 struct node *node;
5844 ULONG i, offset = 0;
5845 HRESULT hr;
5847 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
5848 if (error) FIXME( "ignoring error parameter\n" );
5850 if (!reader) return E_INVALIDARG;
5852 EnterCriticalSection( &reader->cs );
5854 if (reader->magic != READER_MAGIC)
5856 LeaveCriticalSection( &reader->cs );
5857 return E_INVALIDARG;
5860 for (i = 0; i < count; i++)
5862 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
5863 properties[i].valueSize );
5864 if (hr != S_OK) goto done;
5867 if ((hr = init_reader( reader )) != S_OK) goto done;
5869 switch (encoding->encodingType)
5871 case WS_XML_READER_ENCODING_TYPE_TEXT:
5873 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
5874 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
5876 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
5878 FIXME( "charset detection on input type %u not supported\n", input->inputType );
5879 hr = E_NOTIMPL;
5880 goto done;
5883 if (text->charSet != WS_CHARSET_AUTO) reader->input_charset = text->charSet;
5884 else reader->input_charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
5886 reader->input_enc = WS_XML_READER_ENCODING_TYPE_TEXT;
5887 break;
5889 case WS_XML_READER_ENCODING_TYPE_BINARY:
5891 WS_XML_READER_BINARY_ENCODING *bin = (WS_XML_READER_BINARY_ENCODING *)encoding;
5892 reader->input_enc = WS_XML_READER_ENCODING_TYPE_BINARY;
5893 reader->input_charset = 0;
5894 reader->dict_static = bin->staticDictionary ? bin->staticDictionary : &dict_builtin_static.dict;
5895 reader->dict = bin->dynamicDictionary ? bin->dynamicDictionary : &dict_builtin.dict;
5896 break;
5898 default:
5899 FIXME( "encoding type %u not supported\n", encoding->encodingType );
5900 hr = E_NOTIMPL;
5901 goto done;
5904 switch (input->inputType)
5906 case WS_XML_READER_INPUT_TYPE_BUFFER:
5908 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
5909 set_input_buffer( reader, NULL, (const unsigned char *)buf->encodedData + offset,
5910 buf->encodedDataSize - offset );
5911 break;
5913 default:
5914 FIXME( "input type %u not supported\n", input->inputType );
5915 hr = E_NOTIMPL;
5916 goto done;
5919 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
5920 else read_insert_bof( reader, node );
5922 done:
5923 LeaveCriticalSection( &reader->cs );
5924 return hr;
5927 /**************************************************************************
5928 * WsSetInputToBuffer [webservices.@]
5930 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
5931 const WS_XML_READER_PROPERTY *properties, ULONG count,
5932 WS_ERROR *error )
5934 struct reader *reader = (struct reader *)handle;
5935 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
5936 struct node *node;
5937 HRESULT hr;
5938 ULONG i;
5940 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
5941 if (error) FIXME( "ignoring error parameter\n" );
5943 if (!reader || !xmlbuf) return E_INVALIDARG;
5945 EnterCriticalSection( &reader->cs );
5947 if (reader->magic != READER_MAGIC)
5949 LeaveCriticalSection( &reader->cs );
5950 return E_INVALIDARG;
5953 for (i = 0; i < count; i++)
5955 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
5956 properties[i].valueSize );
5957 if (hr != S_OK) goto done;
5960 if ((hr = init_reader( reader )) != S_OK) goto done;
5962 reader->input_enc = xmlbuf->encoding;
5963 reader->input_charset = xmlbuf->charset;
5964 set_input_buffer( reader, xmlbuf, xmlbuf->bytes.bytes, xmlbuf->bytes.length );
5966 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
5967 else read_insert_bof( reader, node );
5969 done:
5970 LeaveCriticalSection( &reader->cs );
5971 return hr;
5974 /**************************************************************************
5975 * WsGetReaderPosition [webservices.@]
5977 HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
5979 struct reader *reader = (struct reader *)handle;
5981 TRACE( "%p %p %p\n", handle, pos, error );
5982 if (error) FIXME( "ignoring error parameter\n" );
5984 if (!reader || !pos) return E_INVALIDARG;
5986 EnterCriticalSection( &reader->cs );
5988 if (reader->magic != READER_MAGIC)
5990 LeaveCriticalSection( &reader->cs );
5991 return E_INVALIDARG;
5994 if (!reader->input_buf)
5996 LeaveCriticalSection( &reader->cs );
5997 return WS_E_INVALID_OPERATION;
6000 pos->buffer = (WS_XML_BUFFER *)reader->input_buf;
6001 pos->node = reader->current;
6003 LeaveCriticalSection( &reader->cs );
6004 return S_OK;
6007 /**************************************************************************
6008 * WsSetReaderPosition [webservices.@]
6010 HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POSITION *pos, WS_ERROR *error )
6012 struct reader *reader = (struct reader *)handle;
6014 TRACE( "%p %p %p\n", handle, pos, error );
6015 if (error) FIXME( "ignoring error parameter\n" );
6017 if (!reader || !pos) return E_INVALIDARG;
6019 EnterCriticalSection( &reader->cs );
6021 if (reader->magic != READER_MAGIC || (struct xmlbuf *)pos->buffer != reader->input_buf)
6023 LeaveCriticalSection( &reader->cs );
6024 return E_INVALIDARG;
6027 if (!reader->input_buf)
6029 LeaveCriticalSection( &reader->cs );
6030 return WS_E_INVALID_OPERATION;
6033 reader->current = pos->node;
6035 LeaveCriticalSection( &reader->cs );
6036 return S_OK;
6039 static HRESULT utf8_to_base64( const WS_XML_UTF8_TEXT *utf8, WS_XML_BASE64_TEXT *base64 )
6041 if (utf8->value.length % 4) return WS_E_INVALID_FORMAT;
6042 if (!(base64->bytes = heap_alloc( utf8->value.length * 3 / 4 ))) return E_OUTOFMEMORY;
6043 base64->length = decode_base64( utf8->value.bytes, utf8->value.length, base64->bytes );
6044 return S_OK;
6047 /**************************************************************************
6048 * WsReadBytes [webservices.@]
6050 HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
6052 struct reader *reader = (struct reader *)handle;
6053 HRESULT hr;
6055 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
6056 if (error) FIXME( "ignoring error parameter\n" );
6058 if (!reader) return E_INVALIDARG;
6060 EnterCriticalSection( &reader->cs );
6062 if (reader->magic != READER_MAGIC)
6064 LeaveCriticalSection( &reader->cs );
6065 return E_INVALIDARG;
6068 if (!reader->input_type)
6070 LeaveCriticalSection( &reader->cs );
6071 return WS_E_INVALID_OPERATION;
6074 if (!count)
6076 LeaveCriticalSection( &reader->cs );
6077 return E_INVALIDARG;
6080 *count = 0;
6081 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
6083 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
6084 WS_XML_BASE64_TEXT base64;
6086 if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK)
6088 LeaveCriticalSection( &reader->cs );
6089 return hr;
6091 if (reader->text_conv_offset == base64.length)
6093 heap_free( base64.bytes );
6094 hr = read_node( reader );
6095 LeaveCriticalSection( &reader->cs );
6096 return hr;
6098 *count = min( base64.length - reader->text_conv_offset, max_count );
6099 memcpy( bytes, base64.bytes + reader->text_conv_offset, *count );
6100 reader->text_conv_offset += *count;
6101 heap_free( base64.bytes );
6104 LeaveCriticalSection( &reader->cs );
6105 return S_OK;
6108 static HRESULT utf8_to_utf16( const WS_XML_UTF8_TEXT *utf8, WS_XML_UTF16_TEXT *utf16 )
6110 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
6111 if (!(utf16->bytes = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
6112 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, (WCHAR *)utf16->bytes, len );
6113 utf16->byteCount = len * sizeof(WCHAR);
6114 return S_OK;
6117 /**************************************************************************
6118 * WsReadChars [webservices.@]
6120 HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count, ULONG *count, WS_ERROR *error )
6122 struct reader *reader = (struct reader *)handle;
6124 TRACE( "%p %p %u %p %p\n", handle, chars, max_count, count, error );
6125 if (error) FIXME( "ignoring error parameter\n" );
6127 if (!reader) return E_INVALIDARG;
6129 EnterCriticalSection( &reader->cs );
6131 if (reader->magic != READER_MAGIC)
6133 LeaveCriticalSection( &reader->cs );
6134 return E_INVALIDARG;
6137 if (!reader->input_type)
6139 LeaveCriticalSection( &reader->cs );
6140 return WS_E_INVALID_OPERATION;
6143 if (!count)
6145 LeaveCriticalSection( &reader->cs );
6146 return E_INVALIDARG;
6149 *count = 0;
6150 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && chars)
6152 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
6153 WS_XML_UTF16_TEXT utf16;
6154 HRESULT hr;
6156 if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK)
6158 LeaveCriticalSection( &reader->cs );
6159 return hr;
6161 if (reader->text_conv_offset == utf16.byteCount / sizeof(WCHAR))
6163 heap_free( utf16.bytes );
6164 hr = read_node( reader );
6165 LeaveCriticalSection( &reader->cs );
6166 return hr;
6168 *count = min( utf16.byteCount / sizeof(WCHAR) - reader->text_conv_offset, max_count );
6169 memcpy( chars, utf16.bytes + reader->text_conv_offset * sizeof(WCHAR), *count * sizeof(WCHAR) );
6170 reader->text_conv_offset += *count;
6171 heap_free( utf16.bytes );
6174 LeaveCriticalSection( &reader->cs );
6175 return S_OK;
6178 /**************************************************************************
6179 * WsReadCharsUtf8 [webservices.@]
6181 HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_count, ULONG *count, WS_ERROR *error )
6183 struct reader *reader = (struct reader *)handle;
6184 HRESULT hr;
6186 TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error );
6187 if (error) FIXME( "ignoring error parameter\n" );
6189 if (!reader) return E_INVALIDARG;
6191 EnterCriticalSection( &reader->cs );
6193 if (reader->magic != READER_MAGIC)
6195 LeaveCriticalSection( &reader->cs );
6196 return E_INVALIDARG;
6199 if (!reader->input_type)
6201 LeaveCriticalSection( &reader->cs );
6202 return WS_E_INVALID_OPERATION;
6205 if (!count)
6207 LeaveCriticalSection( &reader->cs );
6208 return E_INVALIDARG;
6211 *count = 0;
6212 if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes)
6214 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current;
6215 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text;
6217 if (reader->text_conv_offset == utf8->value.length)
6219 hr = read_node( reader );
6220 LeaveCriticalSection( &reader->cs );
6221 return hr;
6223 *count = min( utf8->value.length - reader->text_conv_offset, max_count );
6224 memcpy( bytes, utf8->value.bytes + reader->text_conv_offset, *count );
6225 reader->text_conv_offset += *count;
6228 LeaveCriticalSection( &reader->cs );
6229 return S_OK;
6232 static HRESULT move_to_element( struct reader *reader )
6234 HRESULT hr;
6235 if (node_type( reader->current ) == WS_XML_NODE_TYPE_BOF &&
6236 (hr = read_move_to( reader, WS_MOVE_TO_CHILD_NODE, NULL )) != S_OK) return hr;
6237 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return E_FAIL;
6238 return S_OK;
6241 static HRESULT copy_tree( struct reader *reader, WS_XML_WRITER *writer )
6243 const struct node *node, *parent;
6244 BOOL done = FALSE;
6245 HRESULT hr;
6247 if ((hr = move_to_element( reader )) != S_OK) return hr;
6248 parent = reader->current;
6249 for (;;)
6251 node = reader->current;
6252 if ((hr = WsWriteNode( writer, (const WS_XML_NODE *)node, NULL )) != S_OK) break;
6253 if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT && node->parent == parent) done = TRUE;
6254 if ((hr = read_next_node( reader )) != S_OK || done) break;
6256 return hr;
6259 /**************************************************************************
6260 * WsReadXmlBuffer [webservices.@]
6262 HRESULT WINAPI WsReadXmlBuffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret, WS_ERROR *error )
6264 struct reader *reader = (struct reader *)handle;
6265 WS_XML_WRITER *writer = NULL;
6266 WS_XML_BUFFER *buffer;
6267 HRESULT hr;
6269 TRACE( "%p %p %p %p\n", handle, heap, ret, error );
6270 if (error) FIXME( "ignoring error parameter\n" );
6272 if (!reader || !heap) return E_INVALIDARG;
6273 if (!ret) return E_FAIL;
6275 EnterCriticalSection( &reader->cs );
6277 if (reader->magic != READER_MAGIC)
6279 LeaveCriticalSection( &reader->cs );
6280 return E_INVALIDARG;
6283 if (!reader->input_type)
6285 LeaveCriticalSection( &reader->cs );
6286 return WS_E_INVALID_OPERATION;
6289 if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
6290 if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL )) != S_OK) goto done;
6291 if ((hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL )) != S_OK) goto done;
6292 if ((hr = copy_tree( reader, writer )) == S_OK) *ret = buffer;
6294 done:
6295 if (hr != S_OK) free_xmlbuf( (struct xmlbuf *)buffer );
6296 WsFreeWriter( writer );
6297 LeaveCriticalSection( &reader->cs );
6298 return hr;
6301 HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *desc, USHORT index, const WS_FIELD_DESCRIPTION **ret )
6303 if (index >= desc->fieldCount) return E_INVALIDARG;
6304 *ret = desc->fields[index];
6305 return S_OK;
6308 static ULONG get_field_size( const WS_FIELD_DESCRIPTION *desc )
6310 WS_READ_OPTION option;
6311 ULONG size;
6313 switch ((option = get_field_read_option( desc->type, desc->options )))
6315 case WS_READ_REQUIRED_POINTER:
6316 case WS_READ_OPTIONAL_POINTER:
6317 case WS_READ_NILLABLE_POINTER:
6318 size = sizeof(void *);
6319 break;
6321 case WS_READ_REQUIRED_VALUE:
6322 case WS_READ_NILLABLE_VALUE:
6323 size = get_type_size( desc->type, desc->typeDescription );
6324 break;
6326 default:
6327 WARN( "unhandled option %u\n", option );
6328 return 0;
6331 return size;
6334 static HRESULT read_param( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap, void *ret )
6336 if (!ret && !(ret = ws_alloc_zero( heap, get_field_size(desc) ))) return WS_E_QUOTA_EXCEEDED;
6337 return read_type_struct_field( reader, desc, heap, ret, 0 );
6340 static HRESULT read_param_array( struct reader *reader, const WS_FIELD_DESCRIPTION *desc, WS_HEAP *heap,
6341 void **ret, ULONG *count )
6343 if (!ret && !(ret = ws_alloc_zero( heap, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED;
6344 return read_type_repeating_element( reader, desc, heap, ret, count );
6347 static void set_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, ULONG index, ULONG len,
6348 const void **args )
6350 ULONG i, *ptr;
6351 for (i = 0; i < count; i++)
6353 if (params[i].outputMessageIndex != index || params[i].parameterType != WS_PARAMETER_TYPE_ARRAY_COUNT)
6354 continue;
6355 if ((ptr = *(ULONG **)args[i])) *ptr = len;
6356 break;
6360 HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEMENT_DESCRIPTION *desc,
6361 const WS_PARAMETER_DESCRIPTION *params, ULONG count, const void **args )
6363 struct reader *reader = (struct reader *)handle;
6364 const WS_STRUCT_DESCRIPTION *desc_struct;
6365 const WS_FIELD_DESCRIPTION *desc_field;
6366 ULONG i, len;
6367 HRESULT hr;
6369 if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG;
6371 EnterCriticalSection( &reader->cs );
6373 if (reader->magic != READER_MAGIC)
6375 LeaveCriticalSection( &reader->cs );
6376 return E_INVALIDARG;
6379 if ((hr = start_mapping( reader, WS_ELEMENT_TYPE_MAPPING, desc->elementLocalName, desc->elementNs )) != S_OK)
6380 goto done;
6382 for (i = 0; i < count; i++)
6384 if (params[i].outputMessageIndex == INVALID_PARAMETER_INDEX) continue;
6385 if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES)
6387 FIXME( "messages type not supported\n" );
6388 hr = E_NOTIMPL;
6389 goto done;
6391 if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) goto done;
6392 if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL)
6394 void *ptr = *(void **)args[i];
6395 if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) goto done;
6397 else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY)
6399 void **ptr = *(void ***)args[i];
6400 if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) goto done;
6401 set_array_len( params, count, params[i].outputMessageIndex, len, args );
6405 if (desc_struct->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT)
6407 struct node *parent = find_parent( reader );
6408 parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT;
6411 hr = end_mapping( reader, WS_ELEMENT_TYPE_MAPPING );
6413 done:
6414 LeaveCriticalSection( &reader->cs );
6415 return hr;