webservices: Accept zero write option in WsWriteType.
[wine.git] / dlls / webservices / reader.c
blobca8f1bd6998fdd30c5b72849b441ccf9608d90a1
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 const char *debugstr_xmlstr( const WS_XML_STRING *str )
34 if (!str) return "(null)";
35 return debugstr_an( (const char *)str->bytes, str->length );
38 ULONG prop_size( const struct prop_desc *desc, ULONG count )
40 ULONG i, ret = count * sizeof(struct prop);
41 for (i = 0; i < count; i++) ret += desc[i].size;
42 return ret;
45 void prop_init( const struct prop_desc *desc, ULONG count, struct prop *prop, void *data )
47 ULONG i;
48 char *ptr = data;
49 for (i = 0; i < count; i++)
51 prop[i].value = ptr;
52 prop[i].size = desc[i].size;
53 prop[i].readonly = desc[i].readonly;
54 prop[i].writeonly = desc[i].writeonly;
55 ptr += prop[i].size;
59 HRESULT prop_set( const struct prop *prop, ULONG count, ULONG id, const void *value, ULONG size )
61 if (id >= count || size != prop[id].size || prop[id].readonly) return E_INVALIDARG;
62 memcpy( prop[id].value, value, size );
63 return S_OK;
66 HRESULT prop_get( const struct prop *prop, ULONG count, ULONG id, void *buf, ULONG size )
68 if (id >= count || size != prop[id].size || prop[id].writeonly) return E_INVALIDARG;
69 memcpy( buf, prop[id].value, prop[id].size );
70 return S_OK;
73 static const struct prop_desc error_props[] =
75 { sizeof(ULONG), TRUE }, /* WS_ERROR_PROPERTY_STRING_COUNT */
76 { sizeof(ULONG), FALSE }, /* WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE */
77 { sizeof(LANGID), FALSE } /* WS_ERROR_PROPERTY_LANGID */
80 struct error
82 ULONG prop_count;
83 struct prop prop[sizeof(error_props)/sizeof(error_props[0])];
86 static struct error *alloc_error(void)
88 static const ULONG count = sizeof(error_props)/sizeof(error_props[0]);
89 struct error *ret;
90 ULONG size = sizeof(*ret) + prop_size( error_props, count );
92 if (!(ret = heap_alloc_zero( size ))) return NULL;
93 prop_init( error_props, count, ret->prop, &ret[1] );
94 ret->prop_count = count;
95 return ret;
98 /**************************************************************************
99 * WsCreateError [webservices.@]
101 HRESULT WINAPI WsCreateError( const WS_ERROR_PROPERTY *properties, ULONG count, WS_ERROR **handle )
103 struct error *error;
104 LANGID langid = GetUserDefaultUILanguage();
105 HRESULT hr;
106 ULONG i;
108 TRACE( "%p %u %p\n", properties, count, handle );
110 if (!handle) return E_INVALIDARG;
111 if (!(error = alloc_error())) return E_OUTOFMEMORY;
113 prop_set( error->prop, error->prop_count, WS_ERROR_PROPERTY_LANGID, &langid, sizeof(langid) );
114 for (i = 0; i < count; i++)
116 if (properties[i].id == WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE)
118 heap_free( error );
119 return E_INVALIDARG;
121 hr = prop_set( error->prop, error->prop_count, properties[i].id, properties[i].value,
122 properties[i].valueSize );
123 if (hr != S_OK)
125 heap_free( error );
126 return hr;
130 *handle = (WS_ERROR *)error;
131 return S_OK;
134 /**************************************************************************
135 * WsFreeError [webservices.@]
137 void WINAPI WsFreeError( WS_ERROR *handle )
139 struct error *error = (struct error *)handle;
141 TRACE( "%p\n", handle );
142 heap_free( error );
145 /**************************************************************************
146 * WsResetError [webservices.@]
148 HRESULT WINAPI WsResetError( WS_ERROR *handle )
150 struct error *error = (struct error *)handle;
151 ULONG code;
153 TRACE( "%p\n", handle );
155 if (!handle) return E_INVALIDARG;
157 /* FIXME: release strings added with WsAddErrorString when it's implemented, reset string count */
158 code = 0;
159 return prop_set( error->prop, error->prop_count, WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE, &code, sizeof(code) );
162 static const struct prop_desc heap_props[] =
164 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_MAX_SIZE */
165 { sizeof(SIZE_T), FALSE }, /* WS_HEAP_PROPERTY_TRIM_SIZE */
166 { sizeof(SIZE_T), TRUE }, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
167 { sizeof(SIZE_T), TRUE } /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
170 struct heap
172 HANDLE handle;
173 ULONG prop_count;
174 struct prop prop[sizeof(heap_props)/sizeof(heap_props[0])];
177 static BOOL ensure_heap( struct heap *heap )
179 SIZE_T size;
180 if (heap->handle) return TRUE;
181 if (prop_get( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_MAX_SIZE, &size, sizeof(size) ) != S_OK)
182 return FALSE;
183 if (!(heap->handle = HeapCreate( 0, 0, size ))) return FALSE;
184 return TRUE;
187 void *ws_alloc( WS_HEAP *handle, SIZE_T size )
189 struct heap *heap = (struct heap *)handle;
190 if (!ensure_heap( heap )) return NULL;
191 return HeapAlloc( heap->handle, 0, size );
194 static void *ws_alloc_zero( WS_HEAP *handle, SIZE_T size )
196 struct heap *heap = (struct heap *)handle;
197 if (!ensure_heap( heap )) return NULL;
198 return HeapAlloc( heap->handle, HEAP_ZERO_MEMORY, size );
201 void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
203 struct heap *heap = (struct heap *)handle;
204 if (!ensure_heap( heap )) return NULL;
205 return HeapReAlloc( heap->handle, 0, ptr, size );
208 static void *ws_realloc_zero( WS_HEAP *handle, void *ptr, SIZE_T size )
210 struct heap *heap = (struct heap *)handle;
211 if (!ensure_heap( heap )) return NULL;
212 return HeapReAlloc( heap->handle, HEAP_ZERO_MEMORY, ptr, size );
215 void ws_free( WS_HEAP *handle, void *ptr )
217 struct heap *heap = (struct heap *)handle;
218 if (!heap->handle) return;
219 HeapFree( heap->handle, 0, ptr );
222 /**************************************************************************
223 * WsAlloc [webservices.@]
225 HRESULT WINAPI WsAlloc( WS_HEAP *handle, SIZE_T size, void **ptr, WS_ERROR *error )
227 void *mem;
229 TRACE( "%p %u %p %p\n", handle, (ULONG)size, ptr, error );
230 if (error) FIXME( "ignoring error parameter\n" );
232 if (!handle || !ptr) return E_INVALIDARG;
234 if (!(mem = ws_alloc( handle, size ))) return E_OUTOFMEMORY;
235 *ptr = mem;
236 return S_OK;
239 static struct heap *alloc_heap(void)
241 static const ULONG count = sizeof(heap_props)/sizeof(heap_props[0]);
242 struct heap *ret;
243 ULONG size = sizeof(*ret) + prop_size( heap_props, count );
245 if (!(ret = heap_alloc_zero( size ))) return NULL;
246 prop_init( heap_props, count, ret->prop, &ret[1] );
247 ret->prop_count = count;
248 return ret;
251 /**************************************************************************
252 * WsCreateHeap [webservices.@]
254 HRESULT WINAPI WsCreateHeap( SIZE_T max_size, SIZE_T trim_size, const WS_HEAP_PROPERTY *properties,
255 ULONG count, WS_HEAP **handle, WS_ERROR *error )
257 struct heap *heap;
259 TRACE( "%u %u %p %u %p %p\n", (ULONG)max_size, (ULONG)trim_size, properties, count, handle, error );
260 if (error) FIXME( "ignoring error parameter\n" );
262 if (!handle || count) return E_INVALIDARG;
263 if (!(heap = alloc_heap())) return E_OUTOFMEMORY;
265 prop_set( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_MAX_SIZE, &max_size, sizeof(max_size) );
266 prop_set( heap->prop, heap->prop_count, WS_HEAP_PROPERTY_TRIM_SIZE, &trim_size, sizeof(trim_size) );
268 *handle = (WS_HEAP *)heap;
269 return S_OK;
272 /**************************************************************************
273 * WsFreeHeap [webservices.@]
275 void WINAPI WsFreeHeap( WS_HEAP *handle )
277 struct heap *heap = (struct heap *)handle;
279 TRACE( "%p\n", handle );
281 if (!heap) return;
282 HeapDestroy( heap->handle );
283 heap_free( heap );
286 /**************************************************************************
287 * WsResetHeap [webservices.@]
289 HRESULT WINAPI WsResetHeap( WS_HEAP *handle, WS_ERROR *error )
291 struct heap *heap = (struct heap *)handle;
293 TRACE( "%p %p\n", handle, error );
294 if (error) FIXME( "ignoring error parameter\n" );
296 if (!heap) return E_INVALIDARG;
298 HeapDestroy( heap->handle );
299 heap->handle = NULL;
300 return S_OK;
303 struct node *alloc_node( WS_XML_NODE_TYPE type )
305 struct node *ret;
307 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
308 ret->hdr.node.nodeType = type;
309 list_init( &ret->entry );
310 list_init( &ret->children );
311 return ret;
314 void free_attribute( WS_XML_ATTRIBUTE *attr )
316 if (!attr) return;
317 heap_free( attr->prefix );
318 heap_free( attr->localName );
319 heap_free( attr->ns );
320 heap_free( attr->value );
321 heap_free( attr );
324 void free_node( struct node *node )
326 if (!node) return;
327 switch (node_type( node ))
329 case WS_XML_NODE_TYPE_ELEMENT:
331 WS_XML_ELEMENT_NODE *elem = &node->hdr;
332 ULONG i;
334 for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
335 heap_free( elem->attributes );
336 heap_free( elem->prefix );
337 heap_free( elem->localName );
338 heap_free( elem->ns );
339 break;
341 case WS_XML_NODE_TYPE_TEXT:
343 WS_XML_TEXT_NODE *text = (WS_XML_TEXT_NODE *)node;
344 heap_free( text->text );
345 break;
347 case WS_XML_NODE_TYPE_COMMENT:
349 WS_XML_COMMENT_NODE *comment = (WS_XML_COMMENT_NODE *)node;
350 heap_free( comment->value.bytes );
351 break;
353 case WS_XML_NODE_TYPE_CDATA:
354 case WS_XML_NODE_TYPE_END_CDATA:
355 case WS_XML_NODE_TYPE_END_ELEMENT:
356 case WS_XML_NODE_TYPE_EOF:
357 case WS_XML_NODE_TYPE_BOF:
358 break;
360 default:
361 ERR( "unhandled type %u\n", node_type( node ) );
362 break;
364 heap_free( node );
367 void destroy_nodes( struct node *node )
369 struct list *ptr;
371 if (!node) return;
372 while ((ptr = list_head( &node->children )))
374 struct node *child = LIST_ENTRY( ptr, struct node, entry );
375 list_remove( &child->entry );
376 destroy_nodes( child );
378 free_node( node );
381 static const struct prop_desc reader_props[] =
383 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
384 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
385 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
386 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
387 { sizeof(WS_CHARSET), FALSE }, /* WS_XML_READER_PROPERTY_CHARSET */
388 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_ROW */
389 { sizeof(ULONGLONG), TRUE }, /* WS_XML_READER_PROPERTY_COLUMN */
390 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
391 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
392 { sizeof(BOOL), TRUE }, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
393 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
394 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
395 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
396 { sizeof(BOOL), FALSE }, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
397 { sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
400 enum reader_state
402 READER_STATE_INITIAL,
403 READER_STATE_BOF,
404 READER_STATE_STARTELEMENT,
405 READER_STATE_STARTATTRIBUTE,
406 READER_STATE_STARTCDATA,
407 READER_STATE_CDATA,
408 READER_STATE_TEXT,
409 READER_STATE_ENDELEMENT,
410 READER_STATE_ENDCDATA,
411 READER_STATE_COMMENT,
412 READER_STATE_EOF
415 struct prefix
417 WS_XML_STRING str;
418 WS_XML_STRING ns;
421 struct reader
423 ULONG read_size;
424 ULONG read_pos;
425 const unsigned char *read_bufptr;
426 enum reader_state state;
427 struct node *root;
428 struct node *current;
429 ULONG current_attr;
430 struct node *last;
431 struct prefix *prefixes;
432 ULONG nb_prefixes;
433 ULONG nb_prefixes_allocated;
434 WS_XML_READER_INPUT_TYPE input_type;
435 const unsigned char *input_data;
436 ULONG input_size;
437 ULONG prop_count;
438 struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])];
441 static struct reader *alloc_reader(void)
443 static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]);
444 struct reader *ret;
445 ULONG size = sizeof(*ret) + prop_size( reader_props, count );
447 if (!(ret = heap_alloc_zero( size ))) return NULL;
448 if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
450 heap_free( ret );
451 return NULL;
453 ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
455 prop_init( reader_props, count, ret->prop, &ret[1] );
456 ret->prop_count = count;
457 return ret;
460 static void clear_prefixes( struct prefix *prefixes, ULONG count )
462 ULONG i;
463 for (i = 0; i < count; i++)
465 heap_free( prefixes[i].str.bytes );
466 prefixes[i].str.bytes = NULL;
467 prefixes[i].str.length = 0;
469 heap_free( prefixes[i].ns.bytes );
470 prefixes[i].ns.bytes = NULL;
471 prefixes[i].ns.length = 0;
475 static void free_reader( struct reader *reader )
477 if (!reader) return;
478 destroy_nodes( reader->root );
479 clear_prefixes( reader->prefixes, reader->nb_prefixes );
480 heap_free( reader->prefixes );
481 heap_free( reader );
484 static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
486 if (str)
488 heap_free( prefix->str.bytes );
489 if (!(prefix->str.bytes = heap_alloc( str->length ))) return E_OUTOFMEMORY;
490 memcpy( prefix->str.bytes, str->bytes, str->length );
491 prefix->str.length = str->length;
494 heap_free( prefix->ns.bytes );
495 if (!(prefix->ns.bytes = heap_alloc( ns->length ))) return E_OUTOFMEMORY;
496 memcpy( prefix->ns.bytes, ns->bytes, ns->length );
497 prefix->ns.length = ns->length;
499 return S_OK;
502 static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
504 ULONG i;
505 HRESULT hr;
507 for (i = 0; i < reader->nb_prefixes; i++)
509 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
510 return set_prefix( &reader->prefixes[i], NULL, ns );
512 if (i >= reader->nb_prefixes_allocated)
514 ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
515 struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
516 if (!tmp) return E_OUTOFMEMORY;
517 reader->prefixes = tmp;
518 reader->nb_prefixes_allocated *= 2;
521 if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
522 reader->nb_prefixes++;
523 return S_OK;
526 static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
528 ULONG i;
529 for (i = 0; i < reader->nb_prefixes; i++)
531 if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
532 return &reader->prefixes[i].ns;
534 return NULL;
537 static void read_insert_eof( struct reader *reader, struct node *eof )
539 if (!reader->root) reader->root = eof;
540 else
542 eof->parent = reader->root;
543 list_add_tail( &reader->root->children, &eof->entry );
545 reader->current = reader->last = eof;
548 static void read_insert_bof( struct reader *reader, struct node *bof )
550 reader->root->parent = bof;
551 list_add_tail( &bof->children, &reader->root->entry );
552 reader->current = reader->last = reader->root = bof;
555 static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
557 node->parent = parent;
558 if (node->parent == reader->root)
560 struct list *eof = list_tail( &reader->root->children );
561 list_add_before( eof, &node->entry );
563 else list_add_tail( &parent->children, &node->entry );
564 reader->current = reader->last = node;
567 static HRESULT read_init_state( struct reader *reader )
569 struct node *node;
571 destroy_nodes( reader->root );
572 reader->root = NULL;
573 clear_prefixes( reader->prefixes, reader->nb_prefixes );
574 reader->nb_prefixes = 1;
575 if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
576 read_insert_eof( reader, node );
577 reader->state = READER_STATE_INITIAL;
578 return S_OK;
581 /**************************************************************************
582 * WsCreateReader [webservices.@]
584 HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG count,
585 WS_XML_READER **handle, WS_ERROR *error )
587 struct reader *reader;
588 ULONG i, max_depth = 32, max_attrs = 128, max_ns = 32;
589 WS_CHARSET charset = WS_CHARSET_UTF8;
590 BOOL read_decl = TRUE;
591 HRESULT hr;
593 TRACE( "%p %u %p %p\n", properties, count, handle, error );
594 if (error) FIXME( "ignoring error parameter\n" );
596 if (!handle) return E_INVALIDARG;
597 if (!(reader = alloc_reader())) return E_OUTOFMEMORY;
599 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_DEPTH, &max_depth, sizeof(max_depth) );
600 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES, &max_attrs, sizeof(max_attrs) );
601 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_READ_DECLARATION, &read_decl, sizeof(read_decl) );
602 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
603 prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_MAX_NAMESPACES, &max_ns, sizeof(max_ns) );
605 for (i = 0; i < count; i++)
607 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
608 properties[i].valueSize );
609 if (hr != S_OK)
611 free_reader( reader );
612 return hr;
616 if ((hr = read_init_state( reader )) != S_OK)
618 free_reader( reader );
619 return hr;
622 *handle = (WS_XML_READER *)reader;
623 return S_OK;
626 /**************************************************************************
627 * WsFreeReader [webservices.@]
629 void WINAPI WsFreeReader( WS_XML_READER *handle )
631 struct reader *reader = (struct reader *)handle;
633 TRACE( "%p\n", handle );
634 free_reader( reader );
637 /**************************************************************************
638 * WsFillReader [webservices.@]
640 HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASYNC_CONTEXT *ctx,
641 WS_ERROR *error )
643 struct reader *reader = (struct reader *)handle;
645 TRACE( "%p %u %p %p\n", handle, min_size, ctx, error );
646 if (error) FIXME( "ignoring error parameter\n" );
648 if (!reader) return E_INVALIDARG;
650 /* FIXME: add support for stream input */
651 reader->read_size = min( min_size, reader->input_size );
652 reader->read_pos = 0;
654 return S_OK;
657 /**************************************************************************
658 * WsGetErrorProperty [webservices.@]
660 HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf,
661 ULONG size )
663 struct error *error = (struct error *)handle;
665 TRACE( "%p %u %p %u\n", handle, id, buf, size );
666 return prop_get( error->prop, error->prop_count, id, buf, size );
669 /**************************************************************************
670 * WsGetErrorString [webservices.@]
672 HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str )
674 FIXME( "%p %u %p: stub\n", handle, index, str );
675 return E_NOTIMPL;
678 /**************************************************************************
679 * WsGetHeapProperty [webservices.@]
681 HRESULT WINAPI WsGetHeapProperty( WS_HEAP *handle, WS_HEAP_PROPERTY_ID id, void *buf,
682 ULONG size, WS_ERROR *error )
684 struct heap *heap = (struct heap *)handle;
686 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
687 if (error) FIXME( "ignoring error parameter\n" );
689 return prop_get( heap->prop, heap->prop_count, id, buf, size );
692 /**************************************************************************
693 * WsGetNamespaceFromPrefix [webservices.@]
695 HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STRING *prefix,
696 BOOL required, const WS_XML_STRING **ns, WS_ERROR *error )
698 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
699 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
700 static const WS_XML_STRING empty_ns = {0, NULL};
701 static const WS_XML_STRING xml_ns = {36, (BYTE *)"http://www.w3.org/XML/1998/namespace"};
702 static const WS_XML_STRING xmlns_ns = {29, (BYTE *)"http://www.w3.org/2000/xmlns/"};
703 struct reader *reader = (struct reader *)handle;
704 BOOL found = FALSE;
706 TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(prefix), required, ns, error );
707 if (error) FIXME( "ignoring error parameter\n" );
709 if (!reader || !prefix || !ns) return E_INVALIDARG;
710 if (reader->state != READER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
712 if (!prefix->length)
714 *ns = &empty_ns;
715 found = TRUE;
717 else if (WsXmlStringEquals( prefix, &xml, NULL ) == S_OK)
719 *ns = &xml_ns;
720 found = TRUE;
722 else if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
724 *ns = &xmlns_ns;
725 found = TRUE;
727 else
729 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
730 ULONG i;
732 for (i = 0; i < elem->attributeCount; i++)
734 if (!elem->attributes[i]->isXmlNs) continue;
735 if (WsXmlStringEquals( prefix, elem->attributes[i]->prefix, NULL ) == S_OK)
737 *ns = elem->attributes[i]->ns;
738 found = TRUE;
739 break;
744 if (!found)
746 if (required) return WS_E_INVALID_FORMAT;
747 *ns = NULL;
748 return S_FALSE;
750 return S_OK;
753 /**************************************************************************
754 * WsGetReaderNode [webservices.@]
756 HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node,
757 WS_ERROR *error )
759 struct reader *reader = (struct reader *)handle;
761 TRACE( "%p %p %p\n", handle, node, error );
762 if (error) FIXME( "ignoring error parameter\n" );
764 if (!reader || !node) return E_INVALIDARG;
766 *node = &reader->current->hdr.node;
767 return S_OK;
770 /**************************************************************************
771 * WsGetReaderProperty [webservices.@]
773 HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERTY_ID id,
774 void *buf, ULONG size, WS_ERROR *error )
776 struct reader *reader = (struct reader *)handle;
778 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
779 if (error) FIXME( "ignoring error parameter\n" );
781 if (!reader->input_type) return WS_E_INVALID_OPERATION;
783 if (id == WS_XML_READER_PROPERTY_CHARSET)
785 WS_CHARSET charset;
786 HRESULT hr;
788 if ((hr = prop_get( reader->prop, reader->prop_count, id, &charset, size )) != S_OK) return hr;
789 if (!charset) return WS_E_INVALID_FORMAT;
790 *(WS_CHARSET *)buf = charset;
791 return S_OK;
793 return prop_get( reader->prop, reader->prop_count, id, buf, size );
796 /**************************************************************************
797 * WsGetXmlAttribute [webservices.@]
799 HRESULT WINAPI WsGetXmlAttribute( WS_XML_READER *handle, const WS_XML_STRING *attr,
800 WS_HEAP *heap, WCHAR **str, ULONG *len, WS_ERROR *error )
802 FIXME( "%p %s %p %p %p %p: stub\n", handle, debugstr_xmlstr(attr), heap, str, len, error );
803 return E_NOTIMPL;
806 WS_XML_STRING *alloc_xml_string( const unsigned char *data, ULONG len )
808 WS_XML_STRING *ret;
810 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
811 ret->length = len;
812 ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
813 ret->dictionary = NULL;
814 ret->id = 0;
815 if (data) memcpy( ret->bytes, data, len );
816 return ret;
819 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *data, ULONG len )
821 WS_XML_UTF8_TEXT *ret;
823 if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
824 ret->text.textType = WS_XML_TEXT_TYPE_UTF8;
825 ret->value.length = len;
826 ret->value.bytes = len ? (BYTE *)(ret + 1) : NULL;
827 ret->value.dictionary = NULL;
828 ret->value.id = 0;
829 if (data) memcpy( ret->value.bytes, data, len );
830 return ret;
833 static inline BOOL read_end_of_data( struct reader *reader )
835 return reader->read_pos >= reader->read_size;
838 static inline const unsigned char *read_current_ptr( struct reader *reader )
840 return &reader->read_bufptr[reader->read_pos];
843 /* UTF-8 support based on libs/wine/utf8.c */
845 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
846 static const char utf8_length[128] =
848 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
849 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
850 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
851 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
852 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
853 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
854 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
855 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
858 /* first byte mask depending on UTF-8 sequence length */
859 static const unsigned char utf8_mask[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
861 /* minimum Unicode value depending on UTF-8 sequence length */
862 static const unsigned int utf8_minval[4] = { 0x0, 0x80, 0x800, 0x10000 };
864 static inline unsigned int read_utf8_char( struct reader *reader, unsigned int *skip )
866 unsigned int len, res;
867 unsigned char ch = reader->read_bufptr[reader->read_pos];
868 const unsigned char *end;
870 if (reader->read_pos >= reader->read_size) return 0;
872 if (ch < 0x80)
874 *skip = 1;
875 return ch;
877 len = utf8_length[ch - 0x80];
878 if (reader->read_pos + len >= reader->read_size) return 0;
879 end = reader->read_bufptr + reader->read_pos + len;
880 res = ch & utf8_mask[len];
882 switch (len)
884 case 3:
885 if ((ch = end[-3] ^ 0x80) >= 0x40) break;
886 res = (res << 6) | ch;
887 case 2:
888 if ((ch = end[-2] ^ 0x80) >= 0x40) break;
889 res = (res << 6) | ch;
890 case 1:
891 if ((ch = end[-1] ^ 0x80) >= 0x40) break;
892 res = (res << 6) | ch;
893 if (res < utf8_minval[len]) break;
894 *skip = len + 1;
895 return res;
898 return 0;
901 static inline void read_skip( struct reader *reader, unsigned int count )
903 if (reader->read_pos + count > reader->read_size) return;
904 reader->read_pos += count;
907 static inline void read_rewind( struct reader *reader, unsigned int count )
909 reader->read_pos -= count;
912 static inline BOOL read_isnamechar( unsigned int ch )
914 /* FIXME: incomplete */
915 return (ch >= 'A' && ch <= 'Z') ||
916 (ch >= 'a' && ch <= 'z') ||
917 (ch >= '0' && ch <= '9') ||
918 ch == '_' || ch == '-' || ch == '.' || ch == ':';
921 static inline BOOL read_isspace( unsigned int ch )
923 return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
926 static inline void read_skip_whitespace( struct reader *reader )
928 while (reader->read_pos < reader->read_size && read_isspace( reader->read_bufptr[reader->read_pos] ))
929 reader->read_pos++;
932 static inline int read_cmp( struct reader *reader, const char *str, int len )
934 const unsigned char *ptr = read_current_ptr( reader );
936 if (len < 0) len = strlen( str );
937 if (reader->read_pos + len > reader->read_size) return -1;
938 while (len--)
940 if (*str != *ptr) return *ptr - *str;
941 str++; ptr++;
943 return 0;
946 static HRESULT read_xmldecl( struct reader *reader )
948 if (!reader->read_size) return WS_E_INVALID_FORMAT;
950 if (read_cmp( reader, "<", 1 ) || read_cmp( reader, "<?", 2 ))
952 reader->state = READER_STATE_BOF;
953 return S_OK;
955 if (read_cmp( reader, "<?xml ", 6 )) return WS_E_INVALID_FORMAT;
956 read_skip( reader, 6 );
958 /* FIXME: parse attributes */
959 while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '?')
960 reader->read_pos++;
962 if (read_cmp( reader, "?>", 2 )) return WS_E_INVALID_FORMAT;
963 read_skip( reader, 2 );
965 reader->state = READER_STATE_BOF;
966 return S_OK;
969 HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
971 if (elem->attributeCount)
973 WS_XML_ATTRIBUTE **tmp;
974 if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
975 return E_OUTOFMEMORY;
976 elem->attributes = tmp;
978 else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
979 elem->attributes[elem->attributeCount++] = attr;
980 return S_OK;
983 static HRESULT parse_name( const unsigned char *str, unsigned int len,
984 WS_XML_STRING **prefix, WS_XML_STRING **localname )
986 const unsigned char *name_ptr = str, *prefix_ptr = NULL;
987 unsigned int i, name_len = len, prefix_len = 0;
989 for (i = 0; i < len; i++)
991 if (str[i] == ':')
993 prefix_ptr = str;
994 prefix_len = i;
995 name_ptr = &str[i + 1];
996 name_len -= i + 1;
997 break;
1000 if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
1001 if (!(*localname = alloc_xml_string( name_ptr, name_len )))
1003 heap_free( *prefix );
1004 return E_OUTOFMEMORY;
1006 return S_OK;
1009 static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
1011 static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
1012 WS_XML_ATTRIBUTE *attr;
1013 WS_XML_UTF8_TEXT *text;
1014 unsigned int len = 0, ch, skip, quote;
1015 const unsigned char *start;
1016 WS_XML_STRING *prefix, *localname;
1017 HRESULT hr = WS_E_INVALID_FORMAT;
1019 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
1021 start = read_current_ptr( reader );
1022 for (;;)
1024 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1025 if (!read_isnamechar( ch )) break;
1026 read_skip( reader, skip );
1027 len += skip;
1029 if (!len) goto error;
1031 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) goto error;
1032 hr = E_OUTOFMEMORY;
1033 if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
1035 heap_free( prefix );
1036 attr->isXmlNs = 1;
1037 if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
1039 heap_free( localname );
1040 goto error;
1042 attr->localName = localname;
1044 else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
1046 attr->isXmlNs = 1;
1047 attr->prefix = prefix;
1048 attr->localName = localname;
1050 else
1052 attr->prefix = prefix;
1053 attr->localName = localname;
1056 hr = WS_E_INVALID_FORMAT;
1057 read_skip_whitespace( reader );
1058 if (read_cmp( reader, "=", 1 )) goto error;
1059 read_skip( reader, 1 );
1061 read_skip_whitespace( reader );
1062 if (read_cmp( reader, "\"", 1 ) && read_cmp( reader, "'", 1 )) goto error;
1063 quote = read_utf8_char( reader, &skip );
1064 read_skip( reader, 1 );
1066 len = 0;
1067 start = read_current_ptr( reader );
1068 for (;;)
1070 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1071 if (ch == quote) break;
1072 read_skip( reader, skip );
1073 len += skip;
1075 read_skip( reader, 1 );
1077 hr = E_OUTOFMEMORY;
1078 if (attr->isXmlNs)
1080 if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
1081 if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
1082 if (!(text = alloc_utf8_text( NULL, 0 ))) goto error;
1084 else if (!(text = alloc_utf8_text( start, len ))) goto error;
1086 attr->value = &text->text;
1087 attr->singleQuote = (quote == '\'');
1089 *ret = attr;
1090 return S_OK;
1092 error:
1093 free_attribute( attr );
1094 return hr;
1097 static inline BOOL is_valid_parent( const struct node *node )
1099 if (!node) return FALSE;
1100 return node_type( node ) == WS_XML_NODE_TYPE_ELEMENT || node_type( node ) == WS_XML_NODE_TYPE_BOF;
1103 static struct node *read_find_parent( struct reader *reader )
1105 struct node *node = reader->current;
1106 if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT)
1108 if (!node->parent || !is_valid_parent( node->parent->parent )) return NULL;
1109 return node->parent->parent;
1111 else if (is_valid_parent( node )) return node;
1112 else if (is_valid_parent( node->parent )) return node->parent;
1113 return NULL;
1116 static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
1118 static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
1119 const WS_XML_STRING *ns;
1120 ULONG i;
1122 if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
1123 if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1124 if (!elem->ns->length) elem->ns->bytes = (BYTE *)(elem->ns + 1); /* quirk */
1126 for (i = 0; i < elem->attributeCount; i++)
1128 WS_XML_ATTRIBUTE *attr = elem->attributes[i];
1129 if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
1130 if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
1131 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
1133 return S_OK;
1136 static HRESULT read_element( struct reader *reader )
1138 unsigned int len = 0, ch, skip;
1139 const unsigned char *start;
1140 struct node *node = NULL, *parent;
1141 WS_XML_ELEMENT_NODE *elem;
1142 WS_XML_ATTRIBUTE *attr = NULL;
1143 HRESULT hr = WS_E_INVALID_FORMAT;
1145 if (read_end_of_data( reader ))
1147 struct list *eof = list_tail( &reader->root->children );
1148 reader->current = LIST_ENTRY( eof, struct node, entry );
1149 reader->state = READER_STATE_EOF;
1150 return S_OK;
1153 if (read_cmp( reader, "<", 1 )) goto error;
1154 read_skip( reader, 1 );
1155 if (!read_isnamechar( read_utf8_char( reader, &skip )))
1157 read_rewind( reader, 1 );
1158 goto error;
1161 start = read_current_ptr( reader );
1162 for (;;)
1164 if (!(ch = read_utf8_char( reader, &skip ))) goto error;
1165 if (!read_isnamechar( ch )) break;
1166 read_skip( reader, skip );
1167 len += skip;
1169 if (!len) goto error;
1171 if (!(parent = read_find_parent( reader ))) goto error;
1173 hr = E_OUTOFMEMORY;
1174 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error;
1175 elem = (WS_XML_ELEMENT_NODE *)node;
1176 if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
1178 reader->current_attr = 0;
1179 for (;;)
1181 read_skip_whitespace( reader );
1182 if (!read_cmp( reader, ">", 1 ) || !read_cmp( reader, "/>", 2 )) break;
1183 if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
1184 if ((hr = append_attribute( elem, attr )) != S_OK)
1186 free_attribute( attr );
1187 goto error;
1189 reader->current_attr++;
1191 if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
1193 read_insert_node( reader, parent, node );
1194 reader->state = READER_STATE_STARTELEMENT;
1195 return S_OK;
1197 error:
1198 free_node( node );
1199 return hr;
1202 static HRESULT read_text( struct reader *reader )
1204 unsigned int len = 0, ch, skip;
1205 const unsigned char *start;
1206 struct node *node, *parent;
1207 WS_XML_TEXT_NODE *text;
1208 WS_XML_UTF8_TEXT *utf8;
1210 start = read_current_ptr( reader );
1211 for (;;)
1213 if (read_end_of_data( reader )) break;
1214 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1215 if (ch == '<') break;
1216 read_skip( reader, skip );
1217 len += skip;
1220 if (!(parent = read_find_parent( reader ))) return WS_E_INVALID_FORMAT;
1222 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1223 text = (WS_XML_TEXT_NODE *)node;
1224 if (!(utf8 = alloc_utf8_text( start, len )))
1226 heap_free( node );
1227 return E_OUTOFMEMORY;
1229 text->text = &utf8->text;
1231 read_insert_node( reader, parent, node );
1232 reader->state = READER_STATE_TEXT;
1233 return S_OK;
1236 static HRESULT read_node( struct reader * );
1238 static HRESULT read_startelement( struct reader *reader )
1240 struct node *node;
1242 read_skip_whitespace( reader );
1243 if (!read_cmp( reader, "/>", 2 ))
1245 read_skip( reader, 2 );
1246 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1247 read_insert_node( reader, reader->current, node );
1248 reader->state = READER_STATE_ENDELEMENT;
1249 return S_OK;
1251 else if (!read_cmp( reader, ">", 1 ))
1253 read_skip( reader, 1 );
1254 return read_node( reader );
1256 return WS_E_INVALID_FORMAT;
1259 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
1261 HRESULT hr;
1263 switch (reader->state)
1265 case READER_STATE_INITIAL:
1266 if ((hr = read_xmldecl( reader )) != S_OK) return hr;
1267 break;
1269 case READER_STATE_STARTELEMENT:
1270 if (found) *found = TRUE;
1271 return S_OK;
1273 default:
1274 break;
1277 read_skip_whitespace( reader );
1278 if ((hr = read_element( reader )) == S_OK && found)
1280 if (reader->state == READER_STATE_STARTELEMENT)
1281 *found = TRUE;
1282 else
1283 *found = FALSE;
1286 return hr;
1289 static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
1291 ULONG i;
1292 if (len1 != len2) return 1;
1293 for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
1294 return 0;
1297 static struct node *read_find_start_element( struct reader *reader, const WS_XML_STRING *prefix,
1298 const WS_XML_STRING *localname )
1300 struct node *parent;
1301 const WS_XML_STRING *str;
1303 for (parent = reader->current; parent; parent = parent->parent)
1305 if (node_type( parent ) == WS_XML_NODE_TYPE_BOF) return NULL;
1306 if (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT)
1308 str = parent->hdr.prefix;
1309 if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
1310 str = parent->hdr.localName;
1311 if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
1312 return parent;
1316 return NULL;
1319 static HRESULT read_endelement( struct reader *reader )
1321 struct node *node, *parent;
1322 unsigned int len = 0, ch, skip;
1323 const unsigned char *start;
1324 WS_XML_STRING *prefix, *localname;
1325 HRESULT hr;
1327 if (reader->state == READER_STATE_EOF) return WS_E_INVALID_FORMAT;
1329 if (read_end_of_data( reader ))
1331 struct list *eof = list_tail( &reader->root->children );
1332 reader->current = LIST_ENTRY( eof, struct node, entry );
1333 reader->state = READER_STATE_EOF;
1334 return S_OK;
1337 if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
1338 read_skip( reader, 2 );
1340 start = read_current_ptr( reader );
1341 for (;;)
1343 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1344 if (ch == '>')
1346 read_skip( reader, 1 );
1347 break;
1349 if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
1350 read_skip( reader, skip );
1351 len += skip;
1354 if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
1355 parent = read_find_start_element( reader, prefix, localname );
1356 heap_free( prefix );
1357 heap_free( localname );
1358 if (!parent) return WS_E_INVALID_FORMAT;
1360 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
1361 read_insert_node( reader, parent, node );
1362 reader->state = READER_STATE_ENDELEMENT;
1363 return S_OK;
1366 static HRESULT read_comment( struct reader *reader )
1368 unsigned int len = 0, ch, skip;
1369 const unsigned char *start;
1370 struct node *node, *parent;
1371 WS_XML_COMMENT_NODE *comment;
1373 if (read_cmp( reader, "<!--", 4 )) return WS_E_INVALID_FORMAT;
1374 read_skip( reader, 4 );
1376 start = read_current_ptr( reader );
1377 for (;;)
1379 if (!read_cmp( reader, "-->", 3 ))
1381 read_skip( reader, 3 );
1382 break;
1384 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1385 read_skip( reader, skip );
1386 len += skip;
1389 if (!(parent = read_find_parent( reader ))) return WS_E_INVALID_FORMAT;
1391 if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return E_OUTOFMEMORY;
1392 comment = (WS_XML_COMMENT_NODE *)node;
1393 if (!(comment->value.bytes = heap_alloc( len )))
1395 heap_free( node );
1396 return E_OUTOFMEMORY;
1398 memcpy( comment->value.bytes, start, len );
1399 comment->value.length = len;
1401 read_insert_node( reader, parent, node );
1402 reader->state = READER_STATE_COMMENT;
1403 return S_OK;
1406 static HRESULT read_startcdata( struct reader *reader )
1408 struct node *node, *parent;
1410 if (read_cmp( reader, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT;
1411 read_skip( reader, 9 );
1413 if (!(parent = read_find_parent( reader ))) return WS_E_INVALID_FORMAT;
1415 if (!(node = alloc_node( WS_XML_NODE_TYPE_CDATA ))) return E_OUTOFMEMORY;
1416 read_insert_node( reader, parent, node );
1417 reader->state = READER_STATE_STARTCDATA;
1418 return S_OK;
1421 static HRESULT read_cdata( struct reader *reader )
1423 unsigned int len = 0, ch, skip;
1424 const unsigned char *start;
1425 struct node *node;
1426 WS_XML_TEXT_NODE *text;
1427 WS_XML_UTF8_TEXT *utf8;
1429 start = read_current_ptr( reader );
1430 for (;;)
1432 if (!read_cmp( reader, "]]>", 3 )) break;
1433 if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
1434 read_skip( reader, skip );
1435 len += skip;
1438 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1439 text = (WS_XML_TEXT_NODE *)node;
1440 if (!(utf8 = alloc_utf8_text( start, len )))
1442 heap_free( node );
1443 return E_OUTOFMEMORY;
1445 text->text = &utf8->text;
1447 read_insert_node( reader, reader->current, node );
1448 reader->state = READER_STATE_CDATA;
1449 return S_OK;
1452 static HRESULT read_endcdata( struct reader *reader )
1454 struct node *node;
1456 if (read_cmp( reader, "]]>", 3 )) return WS_E_INVALID_FORMAT;
1457 read_skip( reader, 3 );
1459 if (!(node = alloc_node( WS_XML_NODE_TYPE_END_CDATA ))) return E_OUTOFMEMORY;
1460 read_insert_node( reader, reader->current->parent, node );
1461 reader->state = READER_STATE_ENDCDATA;
1462 return S_OK;
1465 static HRESULT read_node( struct reader *reader )
1467 HRESULT hr;
1469 for (;;)
1471 if (read_end_of_data( reader ))
1473 struct list *eof = list_tail( &reader->root->children );
1474 reader->current = LIST_ENTRY( eof, struct node, entry );
1475 reader->state = READER_STATE_EOF;
1476 return S_OK;
1478 if (reader->state == READER_STATE_STARTCDATA) return read_cdata( reader );
1479 else if (reader->state == READER_STATE_CDATA) return read_endcdata( reader );
1480 else if (!read_cmp( reader, "<?", 2 ))
1482 hr = read_xmldecl( reader );
1483 if (FAILED( hr )) return hr;
1485 else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
1486 else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
1487 else if (!read_cmp( reader, "<!--", 4 )) return read_comment( reader );
1488 else if (!read_cmp( reader, "<", 1 )) return read_element( reader );
1489 else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement( reader );
1490 else return read_text( reader );
1494 /**************************************************************************
1495 * WsReadEndElement [webservices.@]
1497 HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
1499 struct reader *reader = (struct reader *)handle;
1501 TRACE( "%p %p\n", handle, error );
1502 if (error) FIXME( "ignoring error parameter\n" );
1504 if (!reader) return E_INVALIDARG;
1505 return read_endelement( reader );
1508 /**************************************************************************
1509 * WsReadNode [webservices.@]
1511 HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
1513 struct reader *reader = (struct reader *)handle;
1515 TRACE( "%p %p\n", handle, error );
1516 if (error) FIXME( "ignoring error parameter\n" );
1518 if (!reader) return E_INVALIDARG;
1519 return read_node( reader );
1522 /**************************************************************************
1523 * WsReadStartElement [webservices.@]
1525 HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
1527 struct reader *reader = (struct reader *)handle;
1529 TRACE( "%p %p\n", handle, error );
1530 if (error) FIXME( "ignoring error parameter\n" );
1532 if (!reader) return E_INVALIDARG;
1533 return read_startelement( reader );
1536 /**************************************************************************
1537 * WsReadToStartElement [webservices.@]
1539 HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING *localname,
1540 const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error )
1542 struct reader *reader = (struct reader *)handle;
1544 TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error );
1545 if (error) FIXME( "ignoring error parameter\n" );
1547 if (!reader) return E_INVALIDARG;
1548 if (localname || ns) FIXME( "name and/or namespace not verified\n" );
1550 return read_to_startelement( reader, found );
1553 static BOOL move_to_root_element( struct reader *reader )
1555 struct list *ptr;
1556 struct node *node;
1558 if (!(ptr = list_head( &reader->root->children ))) return FALSE;
1559 node = LIST_ENTRY( ptr, struct node, entry );
1560 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1562 reader->current = node;
1563 return TRUE;
1565 while ((ptr = list_next( &reader->root->children, &node->entry )))
1567 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1568 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1570 reader->current = next;
1571 return TRUE;
1573 node = next;
1575 return FALSE;
1578 static BOOL move_to_next_element( struct reader *reader )
1580 struct list *ptr;
1581 struct node *node = reader->current;
1583 while ((ptr = list_next( &node->parent->children, &node->entry )))
1585 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1586 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1588 reader->current = next;
1589 return TRUE;
1591 node = next;
1593 return FALSE;
1596 static BOOL move_to_prev_element( struct reader *reader )
1598 struct list *ptr;
1599 struct node *node = reader->current;
1601 while ((ptr = list_prev( &node->parent->children, &node->entry )))
1603 struct node *prev = LIST_ENTRY( ptr, struct node, entry );
1604 if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
1606 reader->current = prev;
1607 return TRUE;
1609 node = prev;
1611 return FALSE;
1614 static BOOL move_to_child_element( struct reader *reader )
1616 struct list *ptr;
1617 struct node *node;
1619 if (!(ptr = list_head( &reader->current->children ))) return FALSE;
1620 node = LIST_ENTRY( ptr, struct node, entry );
1621 if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
1623 reader->current = node;
1624 return TRUE;
1626 while ((ptr = list_next( &reader->current->children, &node->entry )))
1628 struct node *next = LIST_ENTRY( ptr, struct node, entry );
1629 if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
1631 reader->current = next;
1632 return TRUE;
1634 node = next;
1636 return FALSE;
1639 static BOOL move_to_end_element( struct reader *reader )
1641 struct list *ptr;
1642 struct node *node = reader->current;
1644 if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
1646 if ((ptr = list_tail( &node->children )))
1648 struct node *tail = LIST_ENTRY( ptr, struct node, entry );
1649 if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
1651 reader->current = tail;
1652 return TRUE;
1655 return FALSE;
1658 static BOOL move_to_parent_element( struct reader *reader )
1660 struct node *parent = reader->current->parent;
1662 if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
1663 node_type( parent ) == WS_XML_NODE_TYPE_BOF))
1665 reader->current = parent;
1666 return TRUE;
1668 return FALSE;
1671 static BOOL move_to_first_node( struct reader *reader )
1673 struct list *ptr;
1674 if ((ptr = list_head( &reader->current->parent->children )))
1676 reader->current = LIST_ENTRY( ptr, struct node, entry );
1677 return TRUE;
1679 return FALSE;
1682 static BOOL move_to_next_node( struct reader *reader )
1684 struct list *ptr;
1685 if ((ptr = list_next( &reader->current->parent->children, &reader->current->entry )))
1687 reader->current = LIST_ENTRY( ptr, struct node, entry );
1688 return TRUE;
1690 return FALSE;
1693 static BOOL move_to_prev_node( struct reader *reader )
1695 struct list *ptr;
1696 if ((ptr = list_prev( &reader->current->parent->children, &reader->current->entry )))
1698 reader->current = LIST_ENTRY( ptr, struct node, entry );
1699 return TRUE;
1701 return FALSE;
1704 static BOOL move_to_child_node( struct reader *reader )
1706 struct list *ptr;
1707 if ((ptr = list_head( &reader->current->children )))
1709 reader->current = LIST_ENTRY( ptr, struct node, entry );
1710 return TRUE;
1712 return FALSE;
1715 static BOOL move_to_parent_node( struct reader *reader )
1717 struct node *parent = reader->current->parent;
1718 if (!parent) return FALSE;
1719 reader->current = parent;
1720 return TRUE;
1723 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
1725 struct list *ptr;
1726 BOOL success = FALSE;
1727 HRESULT hr = S_OK;
1729 if (!read_end_of_data( reader ))
1731 while (reader->state != READER_STATE_EOF && (hr = read_node( reader )) == S_OK) { /* nothing */ };
1732 if (hr != S_OK) return hr;
1734 switch (move)
1736 case WS_MOVE_TO_ROOT_ELEMENT:
1737 success = move_to_root_element( reader );
1738 break;
1740 case WS_MOVE_TO_NEXT_ELEMENT:
1741 success = move_to_next_element( reader );
1742 break;
1744 case WS_MOVE_TO_PREVIOUS_ELEMENT:
1745 success = move_to_prev_element( reader );
1746 break;
1748 case WS_MOVE_TO_CHILD_ELEMENT:
1749 success = move_to_child_element( reader );
1750 break;
1752 case WS_MOVE_TO_END_ELEMENT:
1753 success = move_to_end_element( reader );
1754 break;
1756 case WS_MOVE_TO_PARENT_ELEMENT:
1757 success = move_to_parent_element( reader );
1758 break;
1760 case WS_MOVE_TO_FIRST_NODE:
1761 success = move_to_first_node( reader );
1762 break;
1764 case WS_MOVE_TO_NEXT_NODE:
1765 success = move_to_next_node( reader );
1766 break;
1768 case WS_MOVE_TO_PREVIOUS_NODE:
1769 success = move_to_prev_node( reader );
1770 break;
1772 case WS_MOVE_TO_CHILD_NODE:
1773 success = move_to_child_node( reader );
1774 break;
1776 case WS_MOVE_TO_BOF:
1777 reader->current = reader->root;
1778 success = TRUE;
1779 break;
1781 case WS_MOVE_TO_EOF:
1782 if ((ptr = list_tail( &reader->root->children )))
1784 reader->current = LIST_ENTRY( ptr, struct node, entry );
1785 success = TRUE;
1787 break;
1789 default:
1790 FIXME( "unhandled move %u\n", move );
1791 return E_NOTIMPL;
1794 if (found)
1796 *found = success;
1797 return S_OK;
1799 return success ? S_OK : WS_E_INVALID_FORMAT;
1802 /**************************************************************************
1803 * WsMoveReader [webservices.@]
1805 HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
1807 struct reader *reader = (struct reader *)handle;
1809 TRACE( "%p %u %p %p\n", handle, move, found, error );
1810 if (error) FIXME( "ignoring error parameter\n" );
1812 if (!reader) return E_INVALIDARG;
1813 if (!reader->input_type) return WS_E_INVALID_OPERATION;
1815 return read_move_to( reader, move, found );
1818 /**************************************************************************
1819 * WsReadStartAttribute [webservices.@]
1821 HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error )
1823 struct reader *reader = (struct reader *)handle;
1824 WS_XML_ELEMENT_NODE *elem;
1826 TRACE( "%p %u %p\n", handle, index, error );
1827 if (error) FIXME( "ignoring error parameter\n" );
1829 if (!reader) return E_INVALIDARG;
1831 elem = &reader->current->hdr;
1832 if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount)
1833 return WS_E_INVALID_FORMAT;
1835 reader->current_attr = index;
1836 reader->state = READER_STATE_STARTATTRIBUTE;
1837 return S_OK;
1840 /**************************************************************************
1841 * WsReadEndAttribute [webservices.@]
1843 HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
1845 struct reader *reader = (struct reader *)handle;
1847 TRACE( "%p %p\n", handle, error );
1848 if (error) FIXME( "ignoring error parameter\n" );
1850 if (!reader) return E_INVALIDARG;
1852 if (reader->state != READER_STATE_STARTATTRIBUTE)
1853 return WS_E_INVALID_FORMAT;
1855 reader->state = READER_STATE_STARTELEMENT;
1856 return S_OK;
1859 static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
1861 WCHAR *ret;
1863 switch (text->textType)
1865 case WS_XML_TEXT_TYPE_UTF8:
1867 const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
1868 int len = MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, NULL, 0 );
1869 if (!(ret = ws_alloc( heap, (len + 1) * sizeof(WCHAR) ))) return NULL;
1870 MultiByteToWideChar( CP_UTF8, 0, (char *)utf8->value.bytes, utf8->value.length, ret, len );
1871 ret[len] = 0;
1872 break;
1874 default:
1875 FIXME( "unhandled type %u\n", text->textType );
1876 return NULL;
1879 return ret;
1882 #define MAX_INT8 0x7f
1883 #define MIN_INT8 (-MAX_INT8 - 1)
1884 #define MAX_INT16 0x7fff
1885 #define MIN_INT16 (-MAX_INT16 - 1)
1886 #define MAX_INT32 0x7fffffff
1887 #define MIN_INT32 (-MAX_INT32 - 1)
1888 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
1889 #define MIN_INT64 (-MAX_INT64 - 1)
1890 #define MAX_UINT8 0xff
1891 #define MAX_UINT16 0xffff
1892 #define MAX_UINT32 0xffffffff
1893 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
1895 static HRESULT str_to_int64( const unsigned char *str, ULONG len, INT64 min, INT64 max, INT64 *ret )
1897 BOOL negative = FALSE;
1898 const unsigned char *ptr = str;
1900 *ret = 0;
1901 while (len && read_isspace( *ptr )) { ptr++; len--; }
1902 while (len && read_isspace( ptr[len - 1] )) { len--; }
1903 if (!len) return WS_E_INVALID_FORMAT;
1905 if (*ptr == '-')
1907 negative = TRUE;
1908 ptr++;
1909 len--;
1911 if (!len) return WS_E_INVALID_FORMAT;
1913 while (len--)
1915 int val;
1917 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1918 val = *ptr - '0';
1919 if (negative) val = -val;
1921 if ((!negative && (*ret > max / 10 || *ret * 10 > max - val)) ||
1922 (negative && (*ret < min / 10 || *ret * 10 < min - val)))
1924 return WS_E_NUMERIC_OVERFLOW;
1926 *ret = *ret * 10 + val;
1927 ptr++;
1930 return S_OK;
1933 static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, UINT64 *ret )
1935 const unsigned char *ptr = str;
1937 *ret = 0;
1938 while (len && read_isspace( *ptr )) { ptr++; len--; }
1939 while (len && read_isspace( ptr[len - 1] )) { len--; }
1940 if (!len) return WS_E_INVALID_FORMAT;
1942 while (len--)
1944 unsigned int val;
1946 if (!isdigit( *ptr )) return WS_E_INVALID_FORMAT;
1947 val = *ptr - '0';
1949 if ((*ret > max / 10 || *ret * 10 > max - val)) return WS_E_NUMERIC_OVERFLOW;
1950 *ret = *ret * 10 + val;
1951 ptr++;
1954 return S_OK;
1957 #if defined(__i386__) || defined(__x86_64__)
1959 #define RC_DOWN 0x100;
1960 static BOOL set_fp_rounding( unsigned short *save )
1962 #ifdef __GNUC__
1963 unsigned short fpword;
1965 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
1966 *save = fpword;
1967 fpword |= RC_DOWN;
1968 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
1969 return TRUE;
1970 #else
1971 FIXME( "not implemented\n" );
1972 return FALSE;
1973 #endif
1975 static void restore_fp_rounding( unsigned short fpword )
1977 #ifdef __GNUC__
1978 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
1979 #else
1980 FIXME( "not implemented\n" );
1981 #endif
1983 #else
1984 static BOOL set_fp_rounding( unsigned short *save )
1986 FIXME( "not implemented\n" );
1987 return FALSE;
1989 static void restore_fp_rounding( unsigned short fpword )
1991 FIXME( "not implemented\n" );
1993 #endif
1995 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
1997 static const unsigned __int64 nan = 0xfff8000000000000;
1998 static const unsigned __int64 inf = 0x7ff0000000000000;
1999 static const unsigned __int64 inf_min = 0xfff0000000000000;
2000 HRESULT hr = WS_E_INVALID_FORMAT;
2001 const unsigned char *p = str, *q;
2002 int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
2003 unsigned __int64 val = 0, tmp;
2004 long double exp_val = 1.0, exp_mul = 10.0;
2005 unsigned short fpword;
2007 while (len && read_isspace( *p )) { p++; len--; }
2008 while (len && read_isspace( p[len - 1] )) { len--; }
2009 if (!len) return WS_E_INVALID_FORMAT;
2011 if (len == 3 && !memcmp( p, "NaN", 3 ))
2013 *(unsigned __int64 *)ret = nan;
2014 return S_OK;
2016 else if (len == 3 && !memcmp( p, "INF", 3 ))
2018 *(unsigned __int64 *)ret = inf;
2019 return S_OK;
2021 else if (len == 4 && !memcmp( p, "-INF", 4 ))
2023 *(unsigned __int64 *)ret = inf_min;
2024 return S_OK;
2027 *ret = 0.0;
2028 if (*p == '-')
2030 sign = -1;
2031 p++; len--;
2033 else if (*p == '+') { p++; len--; };
2034 if (!len) return S_OK;
2036 if (!set_fp_rounding( &fpword )) return E_NOTIMPL;
2038 q = p;
2039 while (len && isdigit( *q )) { q++; len--; }
2040 have_digits = nb_digits = q - p;
2041 for (i = 0; i < nb_digits; i++)
2043 tmp = val * 10 + p[i] - '0';
2044 if (val > MAX_UINT64 / 10 || tmp < val)
2046 for (; i < nb_digits; i++) exp++;
2047 break;
2049 val = tmp;
2052 if (len)
2054 if (*q == '.')
2056 p = ++q; len--;
2057 while (len && isdigit( *q )) { q++; len--; };
2058 have_digits |= nb_digits = q - p;
2059 for (i = 0; i < nb_digits; i++)
2061 tmp = val * 10 + p[i] - '0';
2062 if (val > MAX_UINT64 / 10 || tmp < val) break;
2063 val = tmp;
2064 exp--;
2067 if (len > 1 && tolower(*q) == 'e')
2069 if (!have_digits) goto done;
2070 p = ++q; len--;
2071 if (*p == '-')
2073 exp_sign = -1;
2074 p++; len--;
2076 else if (*p == '+') { p++; len--; };
2078 q = p;
2079 while (len && isdigit( *q )) { q++; len--; };
2080 nb_digits = q - p;
2081 if (!nb_digits || len) goto done;
2082 for (i = 0; i < nb_digits; i++)
2084 if (exp_tmp > MAX_INT32 / 10 || (exp_tmp = exp_tmp * 10 + p[i] - '0') < 0)
2085 exp_tmp = MAX_INT32;
2087 exp_tmp *= exp_sign;
2089 if (exp < 0 && exp_tmp < 0 && exp + exp_tmp >= 0) exp = MIN_INT32;
2090 else if (exp > 0 && exp_tmp > 0 && exp + exp_tmp < 0) exp = MAX_INT32;
2091 else exp += exp_tmp;
2094 if (!have_digits || len) goto done;
2096 if ((neg_exp = exp < 0)) exp = -exp;
2097 for (; exp; exp >>= 1)
2099 if (exp & 1) exp_val *= exp_mul;
2100 exp_mul *= exp_mul;
2103 *ret = sign * (neg_exp ? val / exp_val : val * exp_val);
2104 hr = S_OK;
2106 done:
2107 restore_fp_rounding( fpword );
2108 return hr;
2111 static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
2113 static const unsigned char hex[] =
2115 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
2116 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
2117 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
2118 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
2119 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
2120 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
2121 0,10,11,12,13,14,15 /* 0x60 */
2123 const unsigned char *p = str;
2124 ULONG i;
2126 while (len && read_isspace( *p )) { p++; len--; }
2127 while (len && read_isspace( p[len - 1] )) { len--; }
2128 if (len != 36) return WS_E_INVALID_FORMAT;
2130 if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-')
2131 return WS_E_INVALID_FORMAT;
2133 for (i = 0; i < 36; i++)
2135 if (i == 8 || i == 13 || i == 18 || i == 23) continue;
2136 if (p[i] > 'f' || (!hex[p[i]] && p[i] != '0')) return WS_E_INVALID_FORMAT;
2139 ret->Data1 = hex[p[0]] << 28 | hex[p[1]] << 24 | hex[p[2]] << 20 | hex[p[3]] << 16 |
2140 hex[p[4]] << 12 | hex[p[5]] << 8 | hex[p[6]] << 4 | hex[p[7]];
2142 ret->Data2 = hex[p[9]] << 12 | hex[p[10]] << 8 | hex[p[11]] << 4 | hex[p[12]];
2143 ret->Data3 = hex[p[14]] << 12 | hex[p[15]] << 8 | hex[p[16]] << 4 | hex[p[17]];
2145 ret->Data4[0] = hex[p[19]] << 4 | hex[p[20]];
2146 ret->Data4[1] = hex[p[21]] << 4 | hex[p[22]];
2147 ret->Data4[2] = hex[p[24]] << 4 | hex[p[25]];
2148 ret->Data4[3] = hex[p[26]] << 4 | hex[p[27]];
2149 ret->Data4[4] = hex[p[28]] << 4 | hex[p[29]];
2150 ret->Data4[5] = hex[p[30]] << 4 | hex[p[31]];
2151 ret->Data4[6] = hex[p[32]] << 4 | hex[p[33]];
2152 ret->Data4[7] = hex[p[34]] << 4 | hex[p[35]];
2154 return S_OK;
2157 #define TICKS_PER_SEC 10000000
2158 #define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
2159 #define TICKS_PER_HOUR (3600 * (ULONGLONG)TICKS_PER_SEC)
2160 #define TICKS_PER_DAY (86400 * (ULONGLONG)TICKS_PER_SEC)
2161 #define TICKS_MAX 3155378975999999999
2163 static const int month_offsets[2][12] =
2165 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
2166 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
2169 static const int month_days[2][12] =
2171 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
2172 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
2175 static inline int is_leap_year( int year )
2177 return !(year % 4) && (year % 100 || !(year % 400));
2180 static inline int valid_day( int year, int month, int day )
2182 return day > 0 && day <= month_days[is_leap_year( year )][month - 1];
2185 static inline int leap_days_before( int year )
2187 return (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
2190 static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETIME *ret )
2192 const unsigned char *p = bytes, *q;
2193 int year, month, day, hour, min, sec, sec_frac = 0, tz_hour, tz_min, tz_neg;
2195 while (len && read_isspace( *p )) { p++; len--; }
2196 while (len && read_isspace( p[len - 1] )) { len--; }
2198 q = p;
2199 while (len && isdigit( *q )) { q++; len--; };
2200 if (q - p != 4 || !len || *q != '-') return WS_E_INVALID_FORMAT;
2201 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
2202 if (year < 1) return WS_E_INVALID_FORMAT;
2204 p = ++q; len--;
2205 while (len && isdigit( *q )) { q++; len--; };
2206 if (q - p != 2 || !len || *q != '-') return WS_E_INVALID_FORMAT;
2207 month = (p[0] - '0') * 10 + p[1] - '0';
2208 if (month < 1 || month > 12) return WS_E_INVALID_FORMAT;
2210 p = ++q; len--;
2211 while (len && isdigit( *q )) { q++; len--; };
2212 if (q - p != 2 || !len || *q != 'T') return WS_E_INVALID_FORMAT;
2213 day = (p[0] - '0') * 10 + p[1] - '0';
2214 if (!valid_day( year, month, day )) return WS_E_INVALID_FORMAT;
2216 p = ++q; len--;
2217 while (len && isdigit( *q )) { q++; len--; };
2218 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2219 hour = (p[0] - '0') * 10 + p[1] - '0';
2220 if (hour > 24) return WS_E_INVALID_FORMAT;
2222 p = ++q; len--;
2223 while (len && isdigit( *q )) { q++; len--; };
2224 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2225 min = (p[0] - '0') * 10 + p[1] - '0';
2226 if (min > 59 || (min > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
2228 p = ++q; len--;
2229 while (len && isdigit( *q )) { q++; len--; };
2230 if (q - p != 2 || !len) return WS_E_INVALID_FORMAT;
2231 sec = (p[0] - '0') * 10 + p[1] - '0';
2232 if (sec > 59 || (sec > 0 && hour == 24)) return WS_E_INVALID_FORMAT;
2234 if (*q == '.')
2236 unsigned int i, nb_digits, mul = TICKS_PER_SEC / 10;
2237 p = ++q; len--;
2238 while (len && isdigit( *q )) { q++; len--; };
2239 nb_digits = q - p;
2240 if (nb_digits < 1 || nb_digits > 7) return WS_E_INVALID_FORMAT;
2241 for (i = 0; i < nb_digits; i++)
2243 sec_frac += (p[i] - '0') * mul;
2244 mul /= 10;
2247 if (*q == 'Z')
2249 if (--len) return WS_E_INVALID_FORMAT;
2250 tz_hour = tz_min = tz_neg = 0;
2251 ret->format = WS_DATETIME_FORMAT_UTC;
2253 else if (*q == '+' || *q == '-')
2255 tz_neg = (*q == '-') ? 1 : 0;
2257 p = ++q; len--;
2258 while (len && isdigit( *q )) { q++; len--; };
2259 if (q - p != 2 || !len || *q != ':') return WS_E_INVALID_FORMAT;
2260 tz_hour = (p[0] - '0') * 10 + p[1] - '0';
2261 if (tz_hour > 14) return WS_E_INVALID_FORMAT;
2263 p = ++q; len--;
2264 while (len && isdigit( *q )) { q++; len--; };
2265 if (q - p != 2 || len) return WS_E_INVALID_FORMAT;
2266 tz_min = (p[0] - '0') * 10 + p[1] - '0';
2267 if (tz_min > 59 || (tz_min > 0 && tz_hour == 14)) return WS_E_INVALID_FORMAT;
2269 ret->format = WS_DATETIME_FORMAT_LOCAL;
2271 else return WS_E_INVALID_FORMAT;
2273 ret->ticks = ((year - 1) * 365 + leap_days_before( year )) * TICKS_PER_DAY;
2274 ret->ticks += month_offsets[is_leap_year( year )][month - 1] * TICKS_PER_DAY;
2275 ret->ticks += (day - 1) * TICKS_PER_DAY;
2276 ret->ticks += hour * TICKS_PER_HOUR;
2277 ret->ticks += min * TICKS_PER_MIN;
2278 ret->ticks += sec * TICKS_PER_SEC;
2279 ret->ticks += sec_frac;
2281 if (tz_neg)
2283 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN + ret->ticks > TICKS_MAX)
2284 return WS_E_INVALID_FORMAT;
2285 ret->ticks += tz_hour * TICKS_PER_HOUR;
2286 ret->ticks += tz_min * TICKS_PER_MIN;
2288 else
2290 if (tz_hour * TICKS_PER_HOUR + tz_min * TICKS_PER_MIN > ret->ticks)
2291 return WS_E_INVALID_FORMAT;
2292 ret->ticks -= tz_hour * TICKS_PER_HOUR;
2293 ret->ticks -= tz_min * TICKS_PER_MIN;
2296 return S_OK;
2299 #define TICKS_1601_01_01 504911232000000000
2301 /**************************************************************************
2302 * WsDateTimeToFileTime [webservices.@]
2304 HRESULT WINAPI WsDateTimeToFileTime( const WS_DATETIME *dt, FILETIME *ft, WS_ERROR *error )
2306 unsigned __int64 ticks;
2308 TRACE( "%p %p %p\n", dt, ft, error );
2309 if (error) FIXME( "ignoring error parameter\n" );
2311 if (!dt || !ft) return E_INVALIDARG;
2313 if (dt->ticks < TICKS_1601_01_01) return WS_E_INVALID_FORMAT;
2314 ticks = dt->ticks - TICKS_1601_01_01;
2315 ft->dwHighDateTime = ticks >> 32;
2316 ft->dwLowDateTime = (DWORD)ticks;
2317 return S_OK;
2320 /**************************************************************************
2321 * WsFileTimeToDateTime [webservices.@]
2323 HRESULT WINAPI WsFileTimeToDateTime( const FILETIME *ft, WS_DATETIME *dt, WS_ERROR *error )
2325 unsigned __int64 ticks;
2327 TRACE( "%p %p %p\n", ft, dt, error );
2328 if (error) FIXME( "ignoring error parameter\n" );
2330 if (!dt || !ft) return E_INVALIDARG;
2332 ticks = ((unsigned __int64)ft->dwHighDateTime << 32) | ft->dwLowDateTime;
2333 if (ticks > MAX_UINT64 - TICKS_1601_01_01) return WS_E_NUMERIC_OVERFLOW;
2334 if (ticks + TICKS_1601_01_01 > TICKS_MAX) return WS_E_INVALID_FORMAT;
2335 dt->ticks = ticks + TICKS_1601_01_01;
2336 dt->format = WS_DATETIME_FORMAT_UTC;
2337 return S_OK;
2340 static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
2342 WS_XML_TEXT_NODE *text;
2344 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
2345 return WS_E_INVALID_FORMAT;
2347 text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
2348 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
2350 FIXME( "text type %u not supported\n", text->text->textType );
2351 return E_NOTIMPL;
2353 *ret = (WS_XML_UTF8_TEXT *)text->text;
2354 return S_OK;
2357 static HRESULT read_get_attribute_text( struct reader *reader, ULONG index, WS_XML_UTF8_TEXT **ret )
2359 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2360 WS_XML_ATTRIBUTE *attr;
2362 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
2363 return WS_E_INVALID_FORMAT;
2365 attr = elem->attributes[index];
2366 if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
2368 FIXME( "text type %u not supported\n", attr->value->textType );
2369 return E_NOTIMPL;
2371 *ret = (WS_XML_UTF8_TEXT *)attr->value;
2372 return S_OK;
2375 static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname,
2376 const WS_XML_STRING *ns, ULONG *index )
2378 ULONG i;
2379 WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2381 if (!localname)
2383 *index = reader->current_attr;
2384 return TRUE;
2386 for (i = 0; i < elem->attributeCount; i++)
2388 const WS_XML_STRING *localname2 = elem->attributes[i]->localName;
2389 const WS_XML_STRING *ns2 = elem->attributes[i]->ns;
2391 if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) &&
2392 !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length ))
2394 *index = i;
2395 return TRUE;
2398 return FALSE;
2401 /**************************************************************************
2402 * WsFindAttribute [webservices.@]
2404 HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname,
2405 const WS_XML_STRING *ns, BOOL required, ULONG *index,
2406 WS_ERROR *error )
2408 struct reader *reader = (struct reader *)handle;
2410 TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns),
2411 required, index, error );
2412 if (error) FIXME( "ignoring error parameter\n" );
2414 if (!reader || !localname || !ns || !index) return E_INVALIDARG;
2416 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT)
2417 return WS_E_INVALID_OPERATION;
2419 if (!find_attribute( reader, localname, ns, index ))
2421 if (required) return WS_E_INVALID_FORMAT;
2422 *index = ~0u;
2423 return S_FALSE;
2425 return S_OK;
2428 static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
2429 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2430 WS_XML_UTF8_TEXT **ret, BOOL *found )
2432 switch (mapping)
2434 case WS_ATTRIBUTE_TYPE_MAPPING:
2436 ULONG index;
2437 if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
2438 return read_get_attribute_text( reader, index, ret );
2440 case WS_ELEMENT_TYPE_MAPPING:
2441 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
2442 case WS_ANY_ELEMENT_TYPE_MAPPING:
2444 HRESULT hr;
2445 *found = TRUE;
2446 if (localname)
2448 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
2450 if (WsXmlStringEquals( localname, elem->localName, NULL ) != S_OK ||
2451 WsXmlStringEquals( ns, elem->ns, NULL ) != S_OK)
2453 *found = FALSE;
2454 return S_OK;
2456 if ((hr = read_startelement( reader )) != S_OK) return hr;
2458 return read_get_node_text( reader, ret );
2460 default:
2461 FIXME( "mapping %u not supported\n", mapping );
2462 return E_NOTIMPL;
2466 static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
2467 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2468 const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
2469 WS_HEAP *heap, void *ret, ULONG size )
2471 WS_XML_UTF8_TEXT *utf8;
2472 HRESULT hr;
2473 BOOL found, val = FALSE;
2475 if (desc)
2477 FIXME( "description not supported\n" );
2478 return E_NOTIMPL;
2480 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2481 if (found)
2483 ULONG len = utf8->value.length;
2484 if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
2485 else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
2486 else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
2487 else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
2488 else return WS_E_INVALID_FORMAT;
2491 switch (option)
2493 case WS_READ_REQUIRED_VALUE:
2494 if (!found) return WS_E_INVALID_FORMAT;
2495 if (size != sizeof(BOOL)) return E_INVALIDARG;
2496 *(BOOL *)ret = val;
2497 break;
2499 case WS_READ_REQUIRED_POINTER:
2500 if (!found) return WS_E_INVALID_FORMAT;
2501 /* fall through */
2503 case WS_READ_OPTIONAL_POINTER:
2505 BOOL *heap_val = NULL;
2506 if (size != sizeof(heap_val)) return E_INVALIDARG;
2507 if (found)
2509 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2510 *heap_val = val;
2512 *(BOOL **)ret = heap_val;
2513 break;
2515 default:
2516 FIXME( "read option %u not supported\n", option );
2517 return E_NOTIMPL;
2520 return S_OK;
2523 static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
2524 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2525 const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
2526 WS_HEAP *heap, void *ret, ULONG size )
2528 WS_XML_UTF8_TEXT *utf8;
2529 HRESULT hr;
2530 INT64 val;
2531 BOOL found;
2533 if (desc)
2535 FIXME( "description not supported\n" );
2536 return E_NOTIMPL;
2538 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2539 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
2540 return hr;
2542 switch (option)
2544 case WS_READ_REQUIRED_VALUE:
2545 if (!found) return WS_E_INVALID_FORMAT;
2546 if (size != sizeof(INT8)) return E_INVALIDARG;
2547 *(INT8 *)ret = val;
2548 break;
2550 case WS_READ_REQUIRED_POINTER:
2551 if (!found) return WS_E_INVALID_FORMAT;
2552 /* fall through */
2554 case WS_READ_OPTIONAL_POINTER:
2556 INT8 *heap_val = NULL;
2557 if (size != sizeof(heap_val)) return E_INVALIDARG;
2558 if (found)
2560 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2561 *heap_val = val;
2563 *(INT8 **)ret = heap_val;
2564 break;
2566 default:
2567 FIXME( "read option %u not supported\n", option );
2568 return E_NOTIMPL;
2571 return S_OK;
2574 static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
2575 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2576 const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
2577 WS_HEAP *heap, void *ret, ULONG size )
2579 WS_XML_UTF8_TEXT *utf8;
2580 HRESULT hr;
2581 INT64 val;
2582 BOOL found;
2584 if (desc)
2586 FIXME( "description not supported\n" );
2587 return E_NOTIMPL;
2589 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2590 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
2591 return hr;
2593 switch (option)
2595 case WS_READ_REQUIRED_VALUE:
2596 if (!found) return WS_E_INVALID_FORMAT;
2597 if (size != sizeof(INT16)) return E_INVALIDARG;
2598 *(INT16 *)ret = val;
2599 break;
2601 case WS_READ_REQUIRED_POINTER:
2602 if (!found) return WS_E_INVALID_FORMAT;
2603 /* fall through */
2605 case WS_READ_OPTIONAL_POINTER:
2607 INT16 *heap_val = NULL;
2608 if (size != sizeof(heap_val)) return E_INVALIDARG;
2609 if (found)
2611 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2612 *heap_val = val;
2614 *(INT16 **)ret = heap_val;
2615 break;
2617 default:
2618 FIXME( "read option %u not supported\n", option );
2619 return E_NOTIMPL;
2622 return S_OK;
2625 static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
2626 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2627 const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
2628 WS_HEAP *heap, void *ret, ULONG size )
2630 WS_XML_UTF8_TEXT *utf8;
2631 HRESULT hr;
2632 INT64 val;
2633 BOOL found;
2635 if (desc)
2637 FIXME( "description not supported\n" );
2638 return E_NOTIMPL;
2640 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2641 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
2642 return hr;
2644 switch (option)
2646 case WS_READ_REQUIRED_VALUE:
2647 if (!found) return WS_E_INVALID_FORMAT;
2648 if (size != sizeof(INT32)) return E_INVALIDARG;
2649 *(INT32 *)ret = val;
2650 break;
2652 case WS_READ_REQUIRED_POINTER:
2653 if (!found) return WS_E_INVALID_FORMAT;
2654 /* fall through */
2656 case WS_READ_OPTIONAL_POINTER:
2658 INT32 *heap_val = NULL;
2659 if (size != sizeof(heap_val)) return E_INVALIDARG;
2660 if (found)
2662 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2663 *heap_val = val;
2665 *(INT32 **)ret = heap_val;
2666 break;
2668 default:
2669 FIXME( "read option %u not supported\n", option );
2670 return E_NOTIMPL;
2673 return S_OK;
2676 static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
2677 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2678 const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
2679 WS_HEAP *heap, void *ret, ULONG size )
2681 WS_XML_UTF8_TEXT *utf8;
2682 HRESULT hr;
2683 INT64 val;
2684 BOOL found;
2686 if (desc)
2688 FIXME( "description not supported\n" );
2689 return E_NOTIMPL;
2691 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2692 if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
2693 return hr;
2695 switch (option)
2697 case WS_READ_REQUIRED_VALUE:
2698 if (!found) return WS_E_INVALID_FORMAT;
2699 if (size != sizeof(INT64)) return E_INVALIDARG;
2700 *(INT64 *)ret = val;
2701 break;
2703 case WS_READ_REQUIRED_POINTER:
2704 if (!found) return WS_E_INVALID_FORMAT;
2705 /* fall through */
2707 case WS_READ_OPTIONAL_POINTER:
2709 INT64 *heap_val = NULL;
2710 if (size != sizeof(heap_val)) return E_INVALIDARG;
2711 if (found)
2713 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2714 *heap_val = val;
2716 *(INT64 **)ret = heap_val;
2717 break;
2719 default:
2720 FIXME( "read option %u not supported\n", option );
2721 return E_NOTIMPL;
2724 return S_OK;
2727 static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
2728 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2729 const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
2730 WS_HEAP *heap, void *ret, ULONG size )
2732 WS_XML_UTF8_TEXT *utf8;
2733 HRESULT hr;
2734 UINT64 val;
2735 BOOL found;
2737 if (desc)
2739 FIXME( "description not supported\n" );
2740 return E_NOTIMPL;
2742 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2743 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
2744 return hr;
2746 switch (option)
2748 case WS_READ_REQUIRED_VALUE:
2749 if (!found) return WS_E_INVALID_FORMAT;
2750 if (size != sizeof(UINT8)) return E_INVALIDARG;
2751 *(UINT8 *)ret = val;
2752 break;
2754 case WS_READ_REQUIRED_POINTER:
2755 if (!found) return WS_E_INVALID_FORMAT;
2756 /* fall through */
2758 case WS_READ_OPTIONAL_POINTER:
2760 UINT8 *heap_val = NULL;
2761 if (size != sizeof(heap_val)) return E_INVALIDARG;
2762 if (found)
2764 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2765 *heap_val = val;
2767 *(UINT8 **)ret = heap_val;
2768 break;
2770 default:
2771 FIXME( "read option %u not supported\n", option );
2772 return E_NOTIMPL;
2775 return S_OK;
2778 static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
2779 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2780 const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
2781 WS_HEAP *heap, void *ret, ULONG size )
2783 WS_XML_UTF8_TEXT *utf8;
2784 HRESULT hr;
2785 UINT64 val;
2786 BOOL found;
2788 if (desc)
2790 FIXME( "description not supported\n" );
2791 return E_NOTIMPL;
2793 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2794 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
2795 return hr;
2797 switch (option)
2799 case WS_READ_REQUIRED_VALUE:
2800 if (!found) return WS_E_INVALID_FORMAT;
2801 if (size != sizeof(UINT16)) return E_INVALIDARG;
2802 *(UINT16 *)ret = val;
2803 break;
2805 case WS_READ_REQUIRED_POINTER:
2806 if (!found) return WS_E_INVALID_FORMAT;
2807 /* fall through */
2809 case WS_READ_OPTIONAL_POINTER:
2811 UINT16 *heap_val = NULL;
2812 if (size != sizeof(heap_val)) return E_INVALIDARG;
2813 if (found)
2815 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2816 *heap_val = val;
2818 *(UINT16 **)ret = heap_val;
2819 break;
2821 default:
2822 FIXME( "read option %u not supported\n", option );
2823 return E_NOTIMPL;
2826 return S_OK;
2829 static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
2830 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2831 const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
2832 WS_HEAP *heap, void *ret, ULONG size )
2834 WS_XML_UTF8_TEXT *utf8;
2835 HRESULT hr;
2836 UINT64 val;
2837 BOOL found;
2839 if (desc)
2841 FIXME( "description not supported\n" );
2842 return E_NOTIMPL;
2844 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2845 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
2846 return hr;
2848 switch (option)
2850 case WS_READ_REQUIRED_VALUE:
2851 if (!found) return WS_E_INVALID_FORMAT;
2852 if (size != sizeof(UINT32)) return E_INVALIDARG;
2853 *(UINT32 *)ret = val;
2854 break;
2856 case WS_READ_REQUIRED_POINTER:
2857 if (!found) return WS_E_INVALID_FORMAT;
2858 /* fall through */
2860 case WS_READ_OPTIONAL_POINTER:
2862 UINT32 *heap_val = NULL;
2863 if (size != sizeof(heap_val)) return E_INVALIDARG;
2864 if (found)
2866 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2867 *heap_val = val;
2869 *(UINT32 **)ret = heap_val;
2870 break;
2872 default:
2873 FIXME( "read option %u not supported\n", option );
2874 return E_NOTIMPL;
2877 return S_OK;
2880 static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
2881 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2882 const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
2883 WS_HEAP *heap, void *ret, ULONG size )
2885 WS_XML_UTF8_TEXT *utf8;
2886 HRESULT hr;
2887 UINT64 val;
2888 BOOL found;
2890 if (desc)
2892 FIXME( "description not supported\n" );
2893 return E_NOTIMPL;
2895 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2896 if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
2897 return hr;
2899 switch (option)
2901 case WS_READ_REQUIRED_VALUE:
2902 if (!found) return WS_E_INVALID_FORMAT;
2903 if (size != sizeof(UINT64)) return E_INVALIDARG;
2904 *(UINT64 *)ret = val;
2905 break;
2907 case WS_READ_REQUIRED_POINTER:
2908 if (!found) return WS_E_INVALID_FORMAT;
2909 /* fall through */
2911 case WS_READ_OPTIONAL_POINTER:
2913 UINT64 *heap_val = NULL;
2914 if (size != sizeof(heap_val)) return E_INVALIDARG;
2915 if (found)
2917 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2918 *heap_val = val;
2920 *(UINT64 **)ret = heap_val;
2921 break;
2923 default:
2924 FIXME( "read option %u not supported\n", option );
2925 return E_NOTIMPL;
2928 return S_OK;
2931 static HRESULT read_type_double( struct reader *reader, WS_TYPE_MAPPING mapping,
2932 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2933 const WS_DOUBLE_DESCRIPTION *desc, WS_READ_OPTION option,
2934 WS_HEAP *heap, void *ret, ULONG size )
2936 WS_XML_UTF8_TEXT *utf8;
2937 HRESULT hr;
2938 double val = 0.0;
2939 BOOL found;
2941 if (desc) FIXME( "ignoring description\n" );
2943 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2944 if (found && (hr = str_to_double( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
2946 switch (option)
2948 case WS_READ_REQUIRED_VALUE:
2949 if (!found) return WS_E_INVALID_FORMAT;
2950 if (size != sizeof(double)) return E_INVALIDARG;
2951 *(double *)ret = val;
2952 break;
2954 case WS_READ_REQUIRED_POINTER:
2955 if (!found) return WS_E_INVALID_FORMAT;
2956 /* fall through */
2958 case WS_READ_OPTIONAL_POINTER:
2960 double *heap_val = NULL;
2961 if (size != sizeof(heap_val)) return E_INVALIDARG;
2962 if (found)
2964 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
2965 *heap_val = val;
2967 *(double **)ret = heap_val;
2968 break;
2970 default:
2971 FIXME( "read option %u not supported\n", option );
2972 return E_NOTIMPL;
2975 return S_OK;
2978 static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
2979 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
2980 const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
2981 WS_HEAP *heap, WCHAR **ret, ULONG size )
2983 WS_XML_UTF8_TEXT *utf8;
2984 HRESULT hr;
2985 WCHAR *str = NULL;
2986 BOOL found;
2988 if (desc)
2990 FIXME( "description not supported\n" );
2991 return E_NOTIMPL;
2993 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
2994 if (found && !(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
2996 switch (option)
2998 case WS_READ_REQUIRED_POINTER:
2999 if (!found) return WS_E_INVALID_FORMAT;
3000 /* fall through */
3002 case WS_READ_OPTIONAL_POINTER:
3003 if (size != sizeof(str)) return E_INVALIDARG;
3004 *ret = str;
3005 break;
3007 default:
3008 FIXME( "read option %u not supported\n", option );
3009 return E_NOTIMPL;
3012 return S_OK;
3015 static HRESULT get_enum_value( const WS_XML_UTF8_TEXT *text, const WS_ENUM_DESCRIPTION *desc, int *ret )
3017 ULONG i;
3018 for (i = 0; i < desc->valueCount; i++)
3020 if (WsXmlStringEquals( &text->value, desc->values[i].name, NULL ) == S_OK)
3022 *ret = desc->values[i].value;
3023 return S_OK;
3026 return WS_E_INVALID_FORMAT;
3029 static HRESULT read_type_enum( struct reader *reader, WS_TYPE_MAPPING mapping,
3030 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3031 const WS_ENUM_DESCRIPTION *desc, WS_READ_OPTION option,
3032 WS_HEAP *heap, void *ret, ULONG size )
3034 WS_XML_UTF8_TEXT *utf8;
3035 HRESULT hr;
3036 int val = 0;
3037 BOOL found;
3039 if (!desc) return E_INVALIDARG;
3041 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3042 if (found && (hr = get_enum_value( utf8, desc, &val )) != S_OK) return hr;
3044 switch (option)
3046 case WS_READ_REQUIRED_VALUE:
3047 if (!found) return WS_E_INVALID_FORMAT;
3048 if (size != sizeof(int)) return E_INVALIDARG;
3049 *(int *)ret = val;
3050 break;
3052 case WS_READ_REQUIRED_POINTER:
3053 if (!found) return WS_E_INVALID_FORMAT;
3054 /* fall through */
3056 case WS_READ_OPTIONAL_POINTER:
3058 int *heap_val = NULL;
3059 if (size != sizeof(heap_val)) return E_INVALIDARG;
3060 if (found)
3062 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3063 *heap_val = val;
3065 *(int **)ret = heap_val;
3066 break;
3068 default:
3069 FIXME( "read option %u not supported\n", option );
3070 return E_NOTIMPL;
3073 return S_OK;
3076 static HRESULT read_type_datetime( struct reader *reader, WS_TYPE_MAPPING mapping,
3077 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3078 const WS_DATETIME_DESCRIPTION *desc, WS_READ_OPTION option,
3079 WS_HEAP *heap, void *ret, ULONG size )
3081 WS_XML_UTF8_TEXT *utf8;
3082 HRESULT hr;
3083 WS_DATETIME val = {0, WS_DATETIME_FORMAT_UTC};
3084 BOOL found;
3086 if (desc) FIXME( "ignoring description\n" );
3088 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3089 if (found && (hr = str_to_datetime( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
3091 switch (option)
3093 case WS_READ_REQUIRED_VALUE:
3094 if (!found) return WS_E_INVALID_FORMAT;
3095 if (size != sizeof(WS_DATETIME)) return E_INVALIDARG;
3096 *(WS_DATETIME *)ret = val;
3097 break;
3099 case WS_READ_REQUIRED_POINTER:
3100 if (!found) return WS_E_INVALID_FORMAT;
3101 /* fall through */
3103 case WS_READ_OPTIONAL_POINTER:
3105 WS_DATETIME *heap_val = NULL;
3106 if (size != sizeof(heap_val)) return E_INVALIDARG;
3107 if (found)
3109 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3110 *heap_val = val;
3112 *(WS_DATETIME **)ret = heap_val;
3113 break;
3115 default:
3116 FIXME( "read option %u not supported\n", option );
3117 return E_NOTIMPL;
3120 return S_OK;
3123 static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
3124 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3125 const WS_GUID_DESCRIPTION *desc, WS_READ_OPTION option,
3126 WS_HEAP *heap, void *ret, ULONG size )
3128 WS_XML_UTF8_TEXT *utf8;
3129 GUID val;
3130 HRESULT hr;
3131 BOOL found;
3133 if (desc) FIXME( "ignoring description\n" );
3135 if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
3136 if (found && (hr = str_to_guid( utf8->value.bytes, utf8->value.length, &val )) != S_OK) return hr;
3138 switch (option)
3140 case WS_READ_REQUIRED_VALUE:
3141 if (!found) return WS_E_INVALID_FORMAT;
3142 if (size != sizeof(GUID)) return E_INVALIDARG;
3143 *(GUID *)ret = val;
3144 break;
3146 case WS_READ_REQUIRED_POINTER:
3147 if (!found) return WS_E_INVALID_FORMAT;
3148 /* fall through */
3150 case WS_READ_OPTIONAL_POINTER:
3152 GUID *heap_val = NULL;
3153 if (size != sizeof(heap_val)) return E_INVALIDARG;
3154 if (found)
3156 if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
3157 *heap_val = val;
3159 *(GUID **)ret = heap_val;
3160 break;
3162 default:
3163 FIXME( "read option %u not supported\n", option );
3164 return E_NOTIMPL;
3167 return S_OK;
3170 static BOOL is_empty_text_node( const struct node *node )
3172 const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
3173 const WS_XML_UTF8_TEXT *utf8;
3174 ULONG i;
3176 if (node_type( node ) != WS_XML_NODE_TYPE_TEXT) return FALSE;
3177 if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
3179 ERR( "unhandled text type %u\n", text->text->textType );
3180 return FALSE;
3182 utf8 = (const WS_XML_UTF8_TEXT *)text->text;
3183 for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
3184 return TRUE;
3187 static HRESULT read_next_node( struct reader *reader )
3189 if (reader->current == reader->last) return read_node( reader );
3190 if (move_to_child_node( reader )) return S_OK;
3191 if (move_to_next_node( reader )) return S_OK;
3192 if (!move_to_parent_node( reader )) return WS_E_INVALID_FORMAT;
3193 if (move_to_next_node( reader )) return S_OK;
3194 return WS_E_INVALID_FORMAT;
3197 /* skips comment and empty text nodes */
3198 static HRESULT read_type_next_node( struct reader *reader )
3200 for (;;)
3202 HRESULT hr;
3203 WS_XML_NODE_TYPE type;
3205 if ((hr = read_next_node( reader )) != S_OK) return hr;
3206 type = node_type( reader->current );
3207 if (type == WS_XML_NODE_TYPE_COMMENT ||
3208 (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
3209 return S_OK;
3213 static BOOL match_current_element( struct reader *reader, const WS_XML_STRING *localname,
3214 const WS_XML_STRING *ns )
3216 const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
3217 if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
3218 return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
3219 WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK;
3222 static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
3223 const WS_XML_STRING *ns )
3225 struct node *node;
3226 ULONG attr;
3227 HRESULT hr;
3229 if (!localname) return S_OK; /* assume reader is already correctly positioned */
3230 if (reader->current == reader->last)
3232 BOOL found;
3233 if ((hr = read_to_startelement( reader, &found )) != S_OK) return hr;
3234 if (!found) return WS_E_INVALID_FORMAT;
3236 if (match_current_element( reader, localname, ns )) return S_OK;
3238 node = reader->current;
3239 attr = reader->current_attr;
3241 if ((hr = read_type_next_node( reader )) != S_OK) return hr;
3242 if (match_current_element( reader, localname, ns )) return S_OK;
3244 reader->current = node;
3245 reader->current_attr = attr;
3247 return WS_E_INVALID_FORMAT;
3250 static ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
3252 switch (type)
3254 case WS_INT8_TYPE:
3255 case WS_UINT8_TYPE:
3256 return sizeof(INT8);
3258 case WS_INT16_TYPE:
3259 case WS_UINT16_TYPE:
3260 return sizeof(INT16);
3262 case WS_BOOL_TYPE:
3263 case WS_INT32_TYPE:
3264 case WS_UINT32_TYPE:
3265 case WS_ENUM_TYPE:
3266 return sizeof(INT32);
3268 case WS_INT64_TYPE:
3269 case WS_UINT64_TYPE:
3270 return sizeof(INT64);
3272 case WS_DOUBLE_TYPE:
3273 return sizeof(double);
3275 case WS_DATETIME_TYPE:
3276 return sizeof(WS_DATETIME);
3278 case WS_GUID_TYPE:
3279 return sizeof(GUID);
3281 case WS_WSZ_TYPE:
3282 return sizeof(WCHAR *);
3284 case WS_STRUCT_TYPE:
3285 return desc->size;
3287 default:
3288 ERR( "unhandled type %u\n", type );
3289 return 0;
3293 static WS_READ_OPTION get_array_read_option( WS_TYPE type )
3295 switch (type)
3297 case WS_BOOL_TYPE:
3298 case WS_INT8_TYPE:
3299 case WS_INT16_TYPE:
3300 case WS_INT32_TYPE:
3301 case WS_INT64_TYPE:
3302 case WS_UINT8_TYPE:
3303 case WS_UINT16_TYPE:
3304 case WS_UINT32_TYPE:
3305 case WS_UINT64_TYPE:
3306 case WS_DOUBLE_TYPE:
3307 case WS_ENUM_TYPE:
3308 case WS_STRUCT_TYPE:
3309 case WS_DATETIME_TYPE:
3310 case WS_GUID_TYPE:
3311 return WS_READ_REQUIRED_VALUE;
3313 case WS_WSZ_TYPE:
3314 return WS_READ_REQUIRED_POINTER;
3316 default:
3317 FIXME( "unhandled type %u\n", type );
3318 return 0;
3322 static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
3323 const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
3324 void *, ULONG );
3326 static HRESULT read_type_repeating_element( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3327 WS_HEAP *heap, void **ret, ULONG size, ULONG *count )
3329 HRESULT hr;
3330 ULONG item_size, nb_items = 0, nb_allocated = 1, offset = 0;
3331 WS_READ_OPTION option;
3332 char *buf;
3334 if (size != sizeof(void *) || !(option = get_array_read_option( desc->type ))) return E_INVALIDARG;
3336 /* wrapper element */
3337 if (desc->localName && ((hr = read_type_next_element_node( reader, desc->localName, desc->ns )) != S_OK))
3338 return hr;
3340 if (option == WS_READ_REQUIRED_VALUE)
3341 item_size = get_type_size( desc->type, desc->typeDescription );
3342 else
3343 item_size = sizeof(void *);
3345 if (!(buf = ws_alloc_zero( heap, item_size ))) return WS_E_QUOTA_EXCEEDED;
3346 for (;;)
3348 if (nb_items >= nb_allocated)
3350 if (!(buf = ws_realloc_zero( heap, buf, nb_allocated * 2 * item_size )))
3351 return WS_E_QUOTA_EXCEEDED;
3352 nb_allocated *= 2;
3354 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
3355 desc->typeDescription, option, heap, buf + offset, item_size );
3356 if (hr == WS_E_INVALID_FORMAT) break;
3357 if (hr != S_OK)
3359 ws_free( heap, buf );
3360 return hr;
3362 offset += item_size;
3363 nb_items++;
3366 if (desc->localName && ((hr = read_type_next_node( reader )) != S_OK)) return hr;
3368 if (desc->itemRange && (nb_items < desc->itemRange->minItemCount || nb_items > desc->itemRange->maxItemCount))
3370 TRACE( "number of items %u out of range (%u-%u)\n", nb_items, desc->itemRange->minItemCount,
3371 desc->itemRange->maxItemCount );
3372 ws_free( heap, buf );
3373 return WS_E_INVALID_FORMAT;
3376 *count = nb_items;
3377 *ret = buf;
3379 return S_OK;
3382 static HRESULT read_type_text( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3383 WS_READ_OPTION option, WS_HEAP *heap, void *ret, ULONG size )
3385 HRESULT hr;
3386 if (reader->current == reader->last)
3388 BOOL found;
3389 if ((hr = read_to_startelement( reader, &found )) != S_OK) return S_OK;
3390 if (!found) return WS_E_INVALID_FORMAT;
3392 if ((hr = read_next_node( reader )) != S_OK) return hr;
3393 if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
3395 return read_type( reader, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, NULL, NULL,
3396 desc->typeDescription, option, heap, ret, size );
3399 static WS_READ_OPTION get_field_read_option( WS_TYPE type )
3401 switch (type)
3403 case WS_BOOL_TYPE:
3404 case WS_INT8_TYPE:
3405 case WS_INT16_TYPE:
3406 case WS_INT32_TYPE:
3407 case WS_INT64_TYPE:
3408 case WS_UINT8_TYPE:
3409 case WS_UINT16_TYPE:
3410 case WS_UINT32_TYPE:
3411 case WS_UINT64_TYPE:
3412 case WS_DOUBLE_TYPE:
3413 case WS_ENUM_TYPE:
3414 case WS_DATETIME_TYPE:
3415 case WS_GUID_TYPE:
3416 return WS_READ_REQUIRED_VALUE;
3418 case WS_WSZ_TYPE:
3419 case WS_STRUCT_TYPE:
3420 return WS_READ_REQUIRED_POINTER;
3422 default:
3423 FIXME( "unhandled type %u\n", type );
3424 return 0;
3428 static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
3429 WS_HEAP *heap, char *buf )
3431 char *ptr;
3432 WS_READ_OPTION option;
3433 ULONG size;
3434 HRESULT hr;
3436 if (!desc) return E_INVALIDARG;
3437 if (desc->options & ~(WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
3439 FIXME( "options %08x not supported\n", desc->options );
3440 return E_NOTIMPL;
3442 if (!(option = get_field_read_option( desc->type ))) return E_INVALIDARG;
3444 if (option == WS_READ_REQUIRED_VALUE)
3445 size = get_type_size( desc->type, desc->typeDescription );
3446 else
3447 size = sizeof(void *);
3449 ptr = buf + desc->offset;
3450 switch (desc->mapping)
3452 case WS_ATTRIBUTE_FIELD_MAPPING:
3453 hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
3454 desc->typeDescription, option, heap, ptr, size );
3455 break;
3457 case WS_ELEMENT_FIELD_MAPPING:
3458 hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
3459 desc->typeDescription, option, heap, ptr, size );
3460 break;
3462 case WS_REPEATING_ELEMENT_FIELD_MAPPING:
3464 ULONG count;
3465 hr = read_type_repeating_element( reader, desc, heap, (void **)ptr, size, &count );
3466 if (hr == S_OK) *(ULONG *)(buf + desc->countOffset) = count;
3467 break;
3469 case WS_TEXT_FIELD_MAPPING:
3470 hr = read_type_text( reader, desc, option, heap, ptr, size );
3471 break;
3473 default:
3474 FIXME( "unhandled field mapping %u\n", desc->mapping );
3475 return E_NOTIMPL;
3478 if (hr == WS_E_INVALID_FORMAT && desc->options & WS_FIELD_OPTIONAL)
3480 switch (option)
3482 case WS_READ_REQUIRED_VALUE:
3483 if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
3484 else memset( ptr, 0, size );
3485 return S_OK;
3487 case WS_READ_REQUIRED_POINTER:
3488 *(void **)ptr = NULL;
3489 return S_OK;
3491 default:
3492 ERR( "unhandled option %u\n", option );
3493 return E_NOTIMPL;
3497 return hr;
3500 static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
3501 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3502 const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
3503 WS_HEAP *heap, void *ret, ULONG size )
3505 ULONG i;
3506 HRESULT hr;
3507 char *buf;
3509 if (!desc) return E_INVALIDARG;
3511 if (desc->structOptions)
3513 FIXME( "struct options %08x not supported\n", desc->structOptions );
3514 return E_NOTIMPL;
3517 switch (option)
3519 case WS_READ_REQUIRED_POINTER:
3520 case WS_READ_OPTIONAL_POINTER:
3521 if (size != sizeof(void *)) return E_INVALIDARG;
3522 if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
3523 break;
3525 case WS_READ_REQUIRED_VALUE:
3526 if (size != desc->size) return E_INVALIDARG;
3527 buf = ret;
3528 break;
3530 default:
3531 FIXME( "unhandled read option %u\n", option );
3532 return E_NOTIMPL;
3535 for (i = 0; i < desc->fieldCount; i++)
3537 if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
3538 break;
3541 switch (option)
3543 case WS_READ_REQUIRED_POINTER:
3544 if (hr != S_OK)
3546 ws_free( heap, buf );
3547 return hr;
3549 *(char **)ret = buf;
3550 return S_OK;
3552 case WS_READ_OPTIONAL_POINTER:
3553 if (hr != S_OK)
3555 ws_free( heap, buf );
3556 buf = NULL;
3558 *(char **)ret = buf;
3559 return S_OK;
3561 case WS_READ_REQUIRED_VALUE:
3562 return hr;
3564 default:
3565 ERR( "unhandled read option %u\n", option );
3566 return E_NOTIMPL;
3570 static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
3571 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
3572 const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
3573 void *value, ULONG size )
3575 HRESULT hr;
3577 switch (mapping)
3579 case WS_ELEMENT_TYPE_MAPPING:
3580 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
3581 if ((hr = read_type_next_element_node( reader, localname, ns )) != S_OK) return hr;
3582 break;
3584 case WS_ANY_ELEMENT_TYPE_MAPPING:
3585 case WS_ATTRIBUTE_TYPE_MAPPING:
3586 break;
3588 default:
3589 FIXME( "unhandled mapping %u\n", mapping );
3590 return E_NOTIMPL;
3593 switch (type)
3595 case WS_STRUCT_TYPE:
3596 if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3597 return hr;
3598 break;
3600 case WS_BOOL_TYPE:
3601 if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3602 return hr;
3603 break;
3605 case WS_INT8_TYPE:
3606 if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3607 return hr;
3608 break;
3610 case WS_INT16_TYPE:
3611 if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3612 return hr;
3613 break;
3615 case WS_INT32_TYPE:
3616 if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3617 return hr;
3618 break;
3620 case WS_INT64_TYPE:
3621 if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3622 return hr;
3623 break;
3625 case WS_UINT8_TYPE:
3626 if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3627 return hr;
3628 break;
3630 case WS_UINT16_TYPE:
3631 if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3632 return hr;
3633 break;
3635 case WS_UINT32_TYPE:
3636 if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3637 return hr;
3638 break;
3640 case WS_UINT64_TYPE:
3641 if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3642 return hr;
3643 break;
3645 case WS_DOUBLE_TYPE:
3646 if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3647 return hr;
3648 break;
3650 case WS_WSZ_TYPE:
3651 if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3652 return hr;
3653 break;
3655 case WS_ENUM_TYPE:
3656 if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3657 return hr;
3658 break;
3660 case WS_DATETIME_TYPE:
3661 if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3662 return hr;
3663 break;
3665 case WS_GUID_TYPE:
3666 if ((hr = read_type_guid( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
3667 return hr;
3668 break;
3670 default:
3671 FIXME( "type %u not supported\n", type );
3672 return E_NOTIMPL;
3675 switch (mapping)
3677 case WS_ELEMENT_TYPE_MAPPING:
3678 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
3679 return read_type_next_node( reader );
3681 case WS_ATTRIBUTE_TYPE_MAPPING:
3682 default:
3683 return S_OK;
3687 /**************************************************************************
3688 * WsReadType [webservices.@]
3690 HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
3691 const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
3692 ULONG size, WS_ERROR *error )
3694 struct reader *reader = (struct reader *)handle;
3695 HRESULT hr;
3697 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
3698 size, error );
3699 if (error) FIXME( "ignoring error parameter\n" );
3701 if (!reader || !value) return E_INVALIDARG;
3703 if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
3704 return hr;
3706 switch (mapping)
3708 case WS_ELEMENT_TYPE_MAPPING:
3709 if ((hr = read_node( reader )) != S_OK) return hr;
3710 break;
3712 default:
3713 break;
3716 if (!read_end_of_data( reader )) return WS_E_INVALID_FORMAT;
3717 return S_OK;
3720 /**************************************************************************
3721 * WsReadElement [webservices.@]
3723 HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTION *desc,
3724 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size,
3725 WS_ERROR *error )
3727 struct reader *reader = (struct reader *)handle;
3729 TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error );
3730 if (error) FIXME( "ignoring error parameter\n" );
3732 if (!reader || !desc || !value) return E_INVALIDARG;
3734 return read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName,
3735 desc->elementNs, desc->typeDescription, option, heap, value, size );
3738 /**************************************************************************
3739 * WsReadValue [webservices.@]
3741 HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, void *value, ULONG size,
3742 WS_ERROR *error )
3744 struct reader *reader = (struct reader *)handle;
3745 WS_TYPE type = map_value_type( value_type );
3747 TRACE( "%p %u %p %u %p\n", handle, type, value, size, error );
3748 if (error) FIXME( "ignoring error parameter\n" );
3750 if (!reader || !value || type == ~0u) return E_INVALIDARG;
3752 return read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE,
3753 NULL, value, size );
3756 /**************************************************************************
3757 * WsSetErrorProperty [webservices.@]
3759 HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value,
3760 ULONG size )
3762 struct error *error = (struct error *)handle;
3764 TRACE( "%p %u %p %u\n", handle, id, value, size );
3766 if (id == WS_ERROR_PROPERTY_LANGID) return WS_E_INVALID_OPERATION;
3767 return prop_set( error->prop, error->prop_count, id, value, size );
3770 static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset )
3772 static const char bom[] = {0xef,0xbb,0xbf};
3773 const unsigned char *p = data;
3775 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
3776 (size > 2 && !(*offset = 0));
3779 static inline BOOL is_utf16le( const unsigned char *data, ULONG size, ULONG *offset )
3781 static const char bom[] = {0xff,0xfe};
3782 const unsigned char *p = data;
3784 return (size >= sizeof(bom) && !memcmp( p, bom, sizeof(bom) ) && (*offset = sizeof(bom))) ||
3785 (size >= 4 && p[0] == '<' && !p[1] && !(*offset = 0));
3788 static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *offset )
3790 WS_CHARSET ret = 0;
3792 /* FIXME: parse xml declaration */
3794 if (is_utf16le( data, size, offset )) ret = WS_CHARSET_UTF16LE;
3795 else if (is_utf8( data, size, offset )) ret = WS_CHARSET_UTF8;
3796 else
3798 FIXME( "charset not recognized\n" );
3799 return 0;
3802 TRACE( "detected charset %u\n", ret );
3803 return ret;
3806 static void set_input_buffer( struct reader *reader, const unsigned char *data, ULONG size )
3808 reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
3809 reader->input_data = data;
3810 reader->input_size = size;
3812 reader->read_size = reader->input_size;
3813 reader->read_pos = 0;
3814 reader->read_bufptr = reader->input_data;
3817 /**************************************************************************
3818 * WsSetInput [webservices.@]
3820 HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *encoding,
3821 const WS_XML_READER_INPUT *input, const WS_XML_READER_PROPERTY *properties,
3822 ULONG count, WS_ERROR *error )
3824 struct reader *reader = (struct reader *)handle;
3825 struct node *node;
3826 HRESULT hr;
3827 ULONG i, offset = 0;
3829 TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error );
3830 if (error) FIXME( "ignoring error parameter\n" );
3832 if (!reader) return E_INVALIDARG;
3834 for (i = 0; i < count; i++)
3836 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
3837 properties[i].valueSize );
3838 if (hr != S_OK) return hr;
3841 if ((hr = read_init_state( reader )) != S_OK) return hr;
3843 switch (encoding->encodingType)
3845 case WS_XML_READER_ENCODING_TYPE_TEXT:
3847 WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
3848 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
3849 WS_CHARSET charset = text->charSet;
3851 if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
3853 FIXME( "charset detection on input type %u not supported\n", input->inputType );
3854 return E_NOTIMPL;
3857 if (charset == WS_CHARSET_AUTO)
3858 charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
3860 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
3861 &charset, sizeof(charset) );
3862 if (hr != S_OK) return hr;
3863 break;
3865 default:
3866 FIXME( "encoding type %u not supported\n", encoding->encodingType );
3867 return E_NOTIMPL;
3869 switch (input->inputType)
3871 case WS_XML_READER_INPUT_TYPE_BUFFER:
3873 WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
3874 set_input_buffer( reader, (const unsigned char *)buf->encodedData + offset, buf->encodedDataSize - offset );
3875 break;
3877 default:
3878 FIXME( "input type %u not supported\n", input->inputType );
3879 return E_NOTIMPL;
3882 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
3883 read_insert_bof( reader, node );
3884 return S_OK;
3887 /**************************************************************************
3888 * WsSetInputToBuffer [webservices.@]
3890 HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
3891 const WS_XML_READER_PROPERTY *properties, ULONG count,
3892 WS_ERROR *error )
3894 struct reader *reader = (struct reader *)handle;
3895 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
3896 WS_CHARSET charset;
3897 struct node *node;
3898 HRESULT hr;
3899 ULONG i, offset = 0;
3901 TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error );
3902 if (error) FIXME( "ignoring error parameter\n" );
3904 if (!reader || !xmlbuf) return E_INVALIDARG;
3906 for (i = 0; i < count; i++)
3908 hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value,
3909 properties[i].valueSize );
3910 if (hr != S_OK) return hr;
3913 if ((hr = read_init_state( reader )) != S_OK) return hr;
3915 charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
3916 hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET,
3917 &charset, sizeof(charset) );
3918 if (hr != S_OK) return hr;
3920 set_input_buffer( reader, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
3921 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
3922 read_insert_bof( reader, node );
3923 return S_OK;
3926 /**************************************************************************
3927 * WsXmlStringEquals [webservices.@]
3929 HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
3931 TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
3932 if (error) FIXME( "ignoring error parameter\n" );
3934 if (!str1 || !str2) return E_INVALIDARG;
3936 if (str1->length != str2->length) return S_FALSE;
3937 if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
3938 return S_FALSE;