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
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
;
45 void prop_init( const struct prop_desc
*desc
, ULONG count
, struct prop
*prop
, void *data
)
49 for (i
= 0; i
< count
; i
++)
52 prop
[i
].size
= desc
[i
].size
;
53 prop
[i
].readonly
= desc
[i
].readonly
;
54 prop
[i
].writeonly
= desc
[i
].writeonly
;
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
);
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
);
73 struct node
*alloc_node( WS_XML_NODE_TYPE type
)
77 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
78 ret
->hdr
.node
.nodeType
= type
;
79 list_init( &ret
->entry
);
80 list_init( &ret
->children
);
84 void free_attribute( WS_XML_ATTRIBUTE
*attr
)
87 heap_free( attr
->prefix
);
88 heap_free( attr
->localName
);
89 heap_free( attr
->ns
);
90 heap_free( attr
->value
);
94 void free_node( struct node
*node
)
97 switch (node_type( node
))
99 case WS_XML_NODE_TYPE_ELEMENT
:
101 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
104 for (i
= 0; i
< elem
->attributeCount
; i
++) free_attribute( elem
->attributes
[i
] );
105 heap_free( elem
->attributes
);
106 heap_free( elem
->prefix
);
107 heap_free( elem
->localName
);
108 heap_free( elem
->ns
);
111 case WS_XML_NODE_TYPE_TEXT
:
113 WS_XML_TEXT_NODE
*text
= (WS_XML_TEXT_NODE
*)node
;
114 heap_free( text
->text
);
117 case WS_XML_NODE_TYPE_COMMENT
:
119 WS_XML_COMMENT_NODE
*comment
= (WS_XML_COMMENT_NODE
*)node
;
120 heap_free( comment
->value
.bytes
);
123 case WS_XML_NODE_TYPE_CDATA
:
124 case WS_XML_NODE_TYPE_END_CDATA
:
125 case WS_XML_NODE_TYPE_END_ELEMENT
:
126 case WS_XML_NODE_TYPE_EOF
:
127 case WS_XML_NODE_TYPE_BOF
:
131 ERR( "unhandled type %u\n", node_type( node
) );
137 void destroy_nodes( struct node
*node
)
142 while ((ptr
= list_head( &node
->children
)))
144 struct node
*child
= LIST_ENTRY( ptr
, struct node
, entry
);
145 list_remove( &child
->entry
);
146 destroy_nodes( child
);
151 static WS_XML_ATTRIBUTE
*dup_attribute( const WS_XML_ATTRIBUTE
*src
)
153 WS_XML_ATTRIBUTE
*dst
;
154 const WS_XML_STRING
*prefix
= (src
->prefix
&& src
->prefix
->length
) ? src
->prefix
: NULL
;
155 const WS_XML_STRING
*localname
= src
->localName
;
156 const WS_XML_STRING
*ns
= src
->localName
;
158 if (!(dst
= heap_alloc( sizeof(*dst
) ))) return NULL
;
159 dst
->singleQuote
= src
->singleQuote
;
160 dst
->isXmlNs
= src
->isXmlNs
;
161 if (prefix
&& !(dst
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
))) goto error
;
162 if (localname
&& !(dst
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
))) goto error
;
163 if (ns
&& !(dst
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) goto error
;
167 free_attribute( dst
);
171 static WS_XML_ATTRIBUTE
**dup_attributes( WS_XML_ATTRIBUTE
* const *src
, ULONG count
)
173 WS_XML_ATTRIBUTE
**dst
;
176 if (!(dst
= heap_alloc( sizeof(*dst
) * count
))) return NULL
;
177 for (i
= 0; i
< count
; i
++)
179 if (!(dst
[i
] = dup_attribute( src
[i
] )))
181 for (; i
> 0; i
--) free_attribute( dst
[i
- 1] );
189 static struct node
*dup_element_node( const WS_XML_ELEMENT_NODE
*src
)
192 WS_XML_ELEMENT_NODE
*dst
;
193 ULONG count
= src
->attributeCount
;
194 WS_XML_ATTRIBUTE
**attrs
= src
->attributes
;
195 const WS_XML_STRING
*prefix
= (src
->prefix
&& src
->prefix
->length
) ? src
->prefix
: NULL
;
196 const WS_XML_STRING
*localname
= src
->localName
;
197 const WS_XML_STRING
*ns
= src
->ns
;
199 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
202 if (count
&& !(dst
->attributes
= dup_attributes( attrs
, count
))) goto error
;
203 dst
->attributeCount
= count
;
205 if (prefix
&& !(dst
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
))) goto error
;
206 if (localname
&& !(dst
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
))) goto error
;
207 if (ns
&& !(dst
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) goto error
;
215 static struct node
*dup_text_node( const WS_XML_TEXT_NODE
*src
)
218 WS_XML_TEXT_NODE
*dst
;
220 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
221 dst
= (WS_XML_TEXT_NODE
*)node
;
225 WS_XML_UTF8_TEXT
*utf8
;
226 const WS_XML_UTF8_TEXT
*utf8_src
= (WS_XML_UTF8_TEXT
*)src
->text
;
227 if (!(utf8
= alloc_utf8_text( utf8_src
->value
.bytes
, utf8_src
->value
.length
)))
232 dst
->text
= &utf8
->text
;
237 static struct node
*dup_comment_node( const WS_XML_COMMENT_NODE
*src
)
240 WS_XML_COMMENT_NODE
*dst
;
242 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return NULL
;
243 dst
= (WS_XML_COMMENT_NODE
*)node
;
245 if (src
->value
.length
&& !(dst
->value
.bytes
= heap_alloc( src
->value
.length
)))
250 memcpy( dst
->value
.bytes
, src
->value
.bytes
, src
->value
.length
);
251 dst
->value
.length
= src
->value
.length
;
255 static struct node
*dup_node( const struct node
*src
)
257 switch (node_type( src
))
259 case WS_XML_NODE_TYPE_ELEMENT
:
260 return dup_element_node( &src
->hdr
);
262 case WS_XML_NODE_TYPE_TEXT
:
263 return dup_text_node( (const WS_XML_TEXT_NODE
*)src
);
265 case WS_XML_NODE_TYPE_COMMENT
:
266 return dup_comment_node( (const WS_XML_COMMENT_NODE
*)src
);
268 case WS_XML_NODE_TYPE_CDATA
:
269 case WS_XML_NODE_TYPE_END_CDATA
:
270 case WS_XML_NODE_TYPE_END_ELEMENT
:
271 case WS_XML_NODE_TYPE_EOF
:
272 case WS_XML_NODE_TYPE_BOF
:
273 return alloc_node( node_type( src
) );
276 ERR( "unhandled type %u\n", node_type( src
) );
282 static HRESULT
dup_tree( struct node
**dst
, const struct node
*src
)
285 const struct node
*child
;
287 if (!*dst
&& !(*dst
= dup_node( src
))) return E_OUTOFMEMORY
;
290 LIST_FOR_EACH_ENTRY( child
, &src
->children
, struct node
, entry
)
292 HRESULT hr
= E_OUTOFMEMORY
;
293 struct node
*new_child
;
295 if (!(new_child
= dup_node( child
)) || (hr
= dup_tree( &new_child
, child
)) != S_OK
)
297 destroy_nodes( *dst
);
300 new_child
->parent
= parent
;
301 list_add_tail( &parent
->children
, &new_child
->entry
);
306 static const struct prop_desc reader_props
[] =
308 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
309 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
310 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
311 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
312 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
313 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
314 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
315 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
316 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
317 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
318 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
319 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
320 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
321 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
322 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
327 READER_STATE_INITIAL
,
329 READER_STATE_STARTELEMENT
,
330 READER_STATE_STARTATTRIBUTE
,
331 READER_STATE_STARTCDATA
,
334 READER_STATE_ENDELEMENT
,
335 READER_STATE_ENDCDATA
,
336 READER_STATE_COMMENT
,
352 const unsigned char *read_bufptr
;
353 enum reader_state state
;
355 struct node
*current
;
358 struct prefix
*prefixes
;
360 ULONG nb_prefixes_allocated
;
361 WS_XML_READER_INPUT_TYPE input_type
;
362 struct xmlbuf
*input_buf
;
363 const unsigned char *input_data
;
365 ULONG text_conv_offset
;
367 struct prop prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
370 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
372 static struct reader
*alloc_reader(void)
374 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
376 ULONG size
= sizeof(*ret
) + prop_size( reader_props
, count
);
378 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
379 if (!(ret
->prefixes
= heap_alloc_zero( sizeof(*ret
->prefixes
) )))
384 ret
->nb_prefixes
= ret
->nb_prefixes_allocated
= 1;
386 ret
->magic
= READER_MAGIC
;
387 InitializeCriticalSection( &ret
->cs
);
388 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": reader.cs");
390 prop_init( reader_props
, count
, ret
->prop
, &ret
[1] );
391 ret
->prop_count
= count
;
395 static void clear_prefixes( struct prefix
*prefixes
, ULONG count
)
398 for (i
= 0; i
< count
; i
++)
400 heap_free( prefixes
[i
].str
.bytes
);
401 prefixes
[i
].str
.bytes
= NULL
;
402 prefixes
[i
].str
.length
= 0;
404 heap_free( prefixes
[i
].ns
.bytes
);
405 prefixes
[i
].ns
.bytes
= NULL
;
406 prefixes
[i
].ns
.length
= 0;
410 HRESULT
copy_node( WS_XML_READER
*handle
, struct node
**node
)
412 struct reader
*reader
= (struct reader
*)handle
;
415 EnterCriticalSection( &reader
->cs
);
417 if (reader
->magic
!= READER_MAGIC
)
419 LeaveCriticalSection( &reader
->cs
);
423 hr
= dup_tree( node
, reader
->current
);
425 LeaveCriticalSection( &reader
->cs
);
429 static HRESULT
set_prefix( struct prefix
*prefix
, const WS_XML_STRING
*str
, const WS_XML_STRING
*ns
)
433 heap_free( prefix
->str
.bytes
);
434 if (!(prefix
->str
.bytes
= heap_alloc( str
->length
))) return E_OUTOFMEMORY
;
435 memcpy( prefix
->str
.bytes
, str
->bytes
, str
->length
);
436 prefix
->str
.length
= str
->length
;
439 heap_free( prefix
->ns
.bytes
);
440 if (!(prefix
->ns
.bytes
= heap_alloc( ns
->length
))) return E_OUTOFMEMORY
;
441 memcpy( prefix
->ns
.bytes
, ns
->bytes
, ns
->length
);
442 prefix
->ns
.length
= ns
->length
;
447 static HRESULT
bind_prefix( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
*ns
)
452 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
454 if (WsXmlStringEquals( prefix
, &reader
->prefixes
[i
].str
, NULL
) == S_OK
)
455 return set_prefix( &reader
->prefixes
[i
], NULL
, ns
);
457 if (i
>= reader
->nb_prefixes_allocated
)
459 ULONG new_size
= reader
->nb_prefixes_allocated
* sizeof(*reader
->prefixes
) * 2;
460 struct prefix
*tmp
= heap_realloc_zero( reader
->prefixes
, new_size
);
461 if (!tmp
) return E_OUTOFMEMORY
;
462 reader
->prefixes
= tmp
;
463 reader
->nb_prefixes_allocated
*= 2;
466 if ((hr
= set_prefix( &reader
->prefixes
[i
], prefix
, ns
)) != S_OK
) return hr
;
467 reader
->nb_prefixes
++;
471 static const WS_XML_STRING
*get_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
)
474 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
476 if (WsXmlStringEquals( prefix
, &reader
->prefixes
[i
].str
, NULL
) == S_OK
)
477 return &reader
->prefixes
[i
].ns
;
482 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
484 if (!reader
->root
) reader
->root
= eof
;
487 eof
->parent
= reader
->root
;
488 list_add_tail( &reader
->root
->children
, &eof
->entry
);
490 reader
->current
= reader
->last
= eof
;
493 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
495 reader
->root
->parent
= bof
;
496 list_add_tail( &bof
->children
, &reader
->root
->entry
);
497 reader
->current
= reader
->last
= reader
->root
= bof
;
500 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
502 node
->parent
= parent
;
503 list_add_before( list_tail( &parent
->children
), &node
->entry
);
504 reader
->current
= reader
->last
= node
;
507 static void free_reader( struct reader
*reader
)
509 destroy_nodes( reader
->root
);
510 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
511 heap_free( reader
->prefixes
);
512 reader
->cs
.DebugInfo
->Spare
[0] = 0;
513 DeleteCriticalSection( &reader
->cs
);
517 static HRESULT
init_reader( struct reader
*reader
)
521 reader
->state
= READER_STATE_INITIAL
;
522 destroy_nodes( reader
->root
);
523 reader
->root
= reader
->current
= NULL
;
524 reader
->current_attr
= 0;
525 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
526 reader
->nb_prefixes
= 1;
527 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
528 read_insert_eof( reader
, node
);
532 /**************************************************************************
533 * WsCreateReader [webservices.@]
535 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
536 WS_XML_READER
**handle
, WS_ERROR
*error
)
538 struct reader
*reader
;
539 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
540 WS_CHARSET charset
= WS_CHARSET_UTF8
;
541 BOOL read_decl
= TRUE
;
544 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
545 if (error
) FIXME( "ignoring error parameter\n" );
547 if (!handle
) return E_INVALIDARG
;
548 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
550 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
551 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
552 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
553 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
554 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
556 for (i
= 0; i
< count
; i
++)
558 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
559 properties
[i
].valueSize
);
562 free_reader( reader
);
567 if ((hr
= init_reader( reader
)) != S_OK
)
569 free_reader( reader
);
573 *handle
= (WS_XML_READER
*)reader
;
577 /**************************************************************************
578 * WsFreeReader [webservices.@]
580 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
582 struct reader
*reader
= (struct reader
*)handle
;
584 TRACE( "%p\n", handle
);
588 EnterCriticalSection( &reader
->cs
);
590 if (reader
->magic
!= READER_MAGIC
)
592 LeaveCriticalSection( &reader
->cs
);
598 LeaveCriticalSection( &reader
->cs
);
599 free_reader( reader
);
602 /**************************************************************************
603 * WsFillReader [webservices.@]
605 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
608 struct reader
*reader
= (struct reader
*)handle
;
610 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
611 if (error
) FIXME( "ignoring error parameter\n" );
613 if (!reader
) return E_INVALIDARG
;
615 EnterCriticalSection( &reader
->cs
);
617 if (reader
->magic
!= READER_MAGIC
)
619 LeaveCriticalSection( &reader
->cs
);
623 /* FIXME: add support for stream input */
624 reader
->read_size
= min( min_size
, reader
->input_size
);
625 reader
->read_pos
= 0;
627 LeaveCriticalSection( &reader
->cs
);
631 /**************************************************************************
632 * WsGetNamespaceFromPrefix [webservices.@]
634 HRESULT WINAPI
WsGetNamespaceFromPrefix( WS_XML_READER
*handle
, const WS_XML_STRING
*prefix
,
635 BOOL required
, const WS_XML_STRING
**ns
, WS_ERROR
*error
)
637 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
638 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
639 static const WS_XML_STRING empty_ns
= {0, NULL
};
640 static const WS_XML_STRING xml_ns
= {36, (BYTE
*)"http://www.w3.org/XML/1998/namespace"};
641 static const WS_XML_STRING xmlns_ns
= {29, (BYTE
*)"http://www.w3.org/2000/xmlns/"};
642 struct reader
*reader
= (struct reader
*)handle
;
645 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(prefix
), required
, ns
, error
);
646 if (error
) FIXME( "ignoring error parameter\n" );
648 if (!reader
|| !prefix
|| !ns
) return E_INVALIDARG
;
650 EnterCriticalSection( &reader
->cs
);
652 if (reader
->magic
!= READER_MAGIC
)
654 LeaveCriticalSection( &reader
->cs
);
658 if (reader
->state
!= READER_STATE_STARTELEMENT
)
660 LeaveCriticalSection( &reader
->cs
);
661 return WS_E_INVALID_OPERATION
;
669 else if (WsXmlStringEquals( prefix
, &xml
, NULL
) == S_OK
)
674 else if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
681 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
684 for (i
= 0; i
< elem
->attributeCount
; i
++)
686 if (!elem
->attributes
[i
]->isXmlNs
) continue;
687 if (WsXmlStringEquals( prefix
, elem
->attributes
[i
]->prefix
, NULL
) == S_OK
)
689 *ns
= elem
->attributes
[i
]->ns
;
696 LeaveCriticalSection( &reader
->cs
);
700 if (required
) return WS_E_INVALID_FORMAT
;
708 /**************************************************************************
709 * WsGetReaderNode [webservices.@]
711 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
714 struct reader
*reader
= (struct reader
*)handle
;
716 TRACE( "%p %p %p\n", handle
, node
, error
);
717 if (error
) FIXME( "ignoring error parameter\n" );
719 if (!reader
|| !node
) return E_INVALIDARG
;
721 EnterCriticalSection( &reader
->cs
);
723 if (reader
->magic
!= READER_MAGIC
)
725 LeaveCriticalSection( &reader
->cs
);
729 *node
= &reader
->current
->hdr
.node
;
731 LeaveCriticalSection( &reader
->cs
);
735 /**************************************************************************
736 * WsGetReaderProperty [webservices.@]
738 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
739 void *buf
, ULONG size
, WS_ERROR
*error
)
741 struct reader
*reader
= (struct reader
*)handle
;
744 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
745 if (error
) FIXME( "ignoring error parameter\n" );
747 if (!reader
) return E_INVALIDARG
;
749 EnterCriticalSection( &reader
->cs
);
751 if (reader
->magic
!= READER_MAGIC
)
753 LeaveCriticalSection( &reader
->cs
);
757 if (!reader
->input_type
)
759 LeaveCriticalSection( &reader
->cs
);
760 return WS_E_INVALID_OPERATION
;
763 if (id
== WS_XML_READER_PROPERTY_CHARSET
)
766 if ((hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, &charset
, size
)) != S_OK
) goto done
;
769 hr
= WS_E_INVALID_FORMAT
;
772 *(WS_CHARSET
*)buf
= charset
;
775 else hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, buf
, size
);
778 LeaveCriticalSection( &reader
->cs
);
782 /**************************************************************************
783 * WsGetXmlAttribute [webservices.@]
785 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
786 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
788 FIXME( "%p %s %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
792 WS_XML_STRING
*alloc_xml_string( const unsigned char *data
, ULONG len
)
796 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
798 ret
->bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
799 ret
->dictionary
= NULL
;
801 if (data
) memcpy( ret
->bytes
, data
, len
);
805 WS_XML_UTF8_TEXT
*alloc_utf8_text( const unsigned char *data
, ULONG len
)
807 WS_XML_UTF8_TEXT
*ret
;
809 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
810 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
811 ret
->value
.length
= len
;
812 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
813 ret
->value
.dictionary
= NULL
;
815 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
819 static inline BOOL
read_end_of_data( struct reader
*reader
)
821 return reader
->read_pos
>= reader
->read_size
;
824 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
826 return &reader
->read_bufptr
[reader
->read_pos
];
829 /* UTF-8 support based on libs/wine/utf8.c */
831 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
832 static const char utf8_length
[128] =
834 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
835 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
836 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
837 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
838 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
839 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
840 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
841 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
844 /* first byte mask depending on UTF-8 sequence length */
845 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
847 /* minimum Unicode value depending on UTF-8 sequence length */
848 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
850 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
852 unsigned int len
, res
;
853 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
854 const unsigned char *end
;
856 if (reader
->read_pos
>= reader
->read_size
) return 0;
863 len
= utf8_length
[ch
- 0x80];
864 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
865 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
+ 1;
866 res
= ch
& utf8_mask
[len
];
871 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
872 res
= (res
<< 6) | ch
;
874 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
875 res
= (res
<< 6) | ch
;
877 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
878 res
= (res
<< 6) | ch
;
879 if (res
< utf8_minval
[len
]) break;
887 static inline void read_skip( struct reader
*reader
, unsigned int count
)
889 if (reader
->read_pos
+ count
> reader
->read_size
) return;
890 reader
->read_pos
+= count
;
893 static inline void read_rewind( struct reader
*reader
, unsigned int count
)
895 reader
->read_pos
-= count
;
898 static inline BOOL
read_isnamechar( unsigned int ch
)
900 /* FIXME: incomplete */
901 return (ch
>= 'A' && ch
<= 'Z') ||
902 (ch
>= 'a' && ch
<= 'z') ||
903 (ch
>= '0' && ch
<= '9') ||
904 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
907 static inline BOOL
read_isspace( unsigned int ch
)
909 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
912 static inline void read_skip_whitespace( struct reader
*reader
)
914 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
918 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
920 const unsigned char *ptr
= read_current_ptr( reader
);
922 if (len
< 0) len
= strlen( str
);
923 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
926 if (*str
!= *ptr
) return *ptr
- *str
;
932 static HRESULT
read_xmldecl( struct reader
*reader
)
934 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
936 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
938 reader
->state
= READER_STATE_BOF
;
941 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
942 read_skip( reader
, 6 );
944 /* FIXME: parse attributes */
945 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
948 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
949 read_skip( reader
, 2 );
951 reader
->state
= READER_STATE_BOF
;
955 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
957 if (elem
->attributeCount
)
959 WS_XML_ATTRIBUTE
**tmp
;
960 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
961 return E_OUTOFMEMORY
;
962 elem
->attributes
= tmp
;
964 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
965 elem
->attributes
[elem
->attributeCount
++] = attr
;
969 static HRESULT
split_name( const unsigned char *str
, ULONG len
, const unsigned char **prefix
,
970 ULONG
*prefix_len
, const unsigned char **localname
, ULONG
*localname_len
)
972 const unsigned char *ptr
= str
;
978 *localname_len
= len
;
984 if (ptr
== str
) return WS_E_INVALID_FORMAT
;
986 *prefix_len
= ptr
- str
;
987 *localname
= ptr
+ 1;
988 *localname_len
= len
;
996 static HRESULT
parse_name( const unsigned char *str
, ULONG len
, WS_XML_STRING
**prefix
, WS_XML_STRING
**localname
)
998 const unsigned char *localname_ptr
, *prefix_ptr
;
999 ULONG localname_len
, prefix_len
;
1002 if ((hr
= split_name( str
, len
, &prefix_ptr
, &prefix_len
, &localname_ptr
, &localname_len
)) != S_OK
) return hr
;
1003 if (!(*prefix
= alloc_xml_string( prefix_ptr
, prefix_len
))) return E_OUTOFMEMORY
;
1004 if (!(*localname
= alloc_xml_string( localname_ptr
, localname_len
)))
1006 heap_free( *prefix
);
1008 return E_OUTOFMEMORY
;
1013 static int codepoint_to_utf8( int cp
, unsigned char *dst
)
1023 dst
[1] = 0x80 | (cp
& 0x3f);
1028 if ((cp
>= 0xd800 && cp
<= 0xdfff) || cp
== 0xfffe || cp
== 0xffff) return -1;
1031 dst
[2] = 0x80 | (cp
& 0x3f);
1033 dst
[1] = 0x80 | (cp
& 0x3f);
1038 if (cp
>= 0x110000) return -1;
1039 dst
[3] = 0x80 | (cp
& 0x3f);
1041 dst
[2] = 0x80 | (cp
& 0x3f);
1043 dst
[1] = 0x80 | (cp
& 0x3f);
1049 static HRESULT
decode_text( const unsigned char *str
, ULONG len
, unsigned char *ret
, ULONG
*ret_len
)
1051 const unsigned char *p
= str
;
1052 unsigned char *q
= ret
;
1060 if (!len
) return WS_E_INVALID_FORMAT
;
1062 if (len
>= 3 && !memcmp( p
, "lt;", 3 ))
1068 else if (len
>= 3 && !memcmp( p
, "gt;", 3 ))
1074 else if (len
>= 5 && !memcmp( p
, "quot;", 5 ))
1080 else if (len
>= 4 && !memcmp( p
, "amp;", 4 ))
1086 else if (len
>= 5 && !memcmp( p
, "apos;", 5 ))
1094 ULONG start
, nb_digits
, i
;
1095 int len_utf8
, cp
= 0;
1098 if (!len
) return WS_E_INVALID_FORMAT
;
1104 while (len
&& isxdigit( *p
)) { p
++; len
--; };
1105 if (!len
) return WS_E_INVALID_FORMAT
;
1107 p
-= nb_digits
= start
- len
;
1108 if (!nb_digits
|| nb_digits
> 6 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1109 for (i
= 0; i
< nb_digits
; i
++)
1112 if (*p
>= '0' && *p
<= '9') cp
+= *p
- '0';
1113 else if (*p
>= 'a' && *p
<= 'f') cp
+= *p
- 'a' + 10;
1114 else cp
+= *p
- 'A' + 10;
1118 else if (isdigit( *p
))
1120 while (len
&& *p
== '0') { p
++; len
--; };
1121 if (!len
) return WS_E_INVALID_FORMAT
;
1124 while (len
&& isdigit( *p
)) { p
++; len
--; };
1125 if (!len
) return WS_E_INVALID_FORMAT
;
1127 p
-= nb_digits
= start
- len
;
1128 if (!nb_digits
|| nb_digits
> 7 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1129 for (i
= 0; i
< nb_digits
; i
++)
1136 else return WS_E_INVALID_FORMAT
;
1138 if ((len_utf8
= codepoint_to_utf8( cp
, q
)) < 0) return WS_E_INVALID_FORMAT
;
1139 *ret_len
+= len_utf8
;
1143 else return WS_E_INVALID_FORMAT
;
1155 static HRESULT
read_attribute( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1157 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1158 WS_XML_ATTRIBUTE
*attr
;
1159 WS_XML_UTF8_TEXT
*text
= NULL
;
1160 unsigned int len
= 0, ch
, skip
, quote
;
1161 const unsigned char *start
;
1162 WS_XML_STRING
*prefix
, *localname
;
1163 HRESULT hr
= WS_E_INVALID_FORMAT
;
1165 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1167 start
= read_current_ptr( reader
);
1170 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1171 if (!read_isnamechar( ch
)) break;
1172 read_skip( reader
, skip
);
1175 if (!len
) goto error
;
1177 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1179 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1181 heap_free( prefix
);
1183 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1185 heap_free( localname
);
1188 attr
->localName
= localname
;
1190 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1193 attr
->prefix
= prefix
;
1194 attr
->localName
= localname
;
1198 attr
->prefix
= prefix
;
1199 attr
->localName
= localname
;
1202 hr
= WS_E_INVALID_FORMAT
;
1203 read_skip_whitespace( reader
);
1204 if (read_cmp( reader
, "=", 1 )) goto error
;
1205 read_skip( reader
, 1 );
1207 read_skip_whitespace( reader
);
1208 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) goto error
;
1209 quote
= read_utf8_char( reader
, &skip
);
1210 read_skip( reader
, 1 );
1213 start
= read_current_ptr( reader
);
1216 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1217 if (ch
== quote
) break;
1218 read_skip( reader
, skip
);
1221 read_skip( reader
, 1 );
1226 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1227 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1228 if (!(text
= alloc_utf8_text( NULL
, 0 ))) goto error
;
1232 if (!(text
= alloc_utf8_text( NULL
, len
))) goto error
;
1233 if ((hr
= decode_text( start
, len
, text
->value
.bytes
, &text
->value
.length
)) != S_OK
) goto error
;
1236 attr
->value
= &text
->text
;
1237 attr
->singleQuote
= (quote
== '\'');
1244 free_attribute( attr
);
1248 static struct node
*find_parent( struct reader
*reader
)
1250 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1252 if (is_valid_parent( reader
->current
->parent
->parent
)) return reader
->current
->parent
->parent
;
1255 else if (is_valid_parent( reader
->current
)) return reader
->current
;
1256 else if (is_valid_parent( reader
->current
->parent
)) return reader
->current
->parent
;
1260 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1262 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1263 const WS_XML_STRING
*ns
;
1266 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1267 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1268 if (!elem
->ns
->length
) elem
->ns
->bytes
= (BYTE
*)(elem
->ns
+ 1); /* quirk */
1270 for (i
= 0; i
< elem
->attributeCount
; i
++)
1272 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1273 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1274 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1275 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
1280 static HRESULT
read_element( struct reader
*reader
)
1282 unsigned int len
= 0, ch
, skip
;
1283 const unsigned char *start
;
1284 struct node
*node
= NULL
, *endnode
, *parent
;
1285 WS_XML_ELEMENT_NODE
*elem
;
1286 WS_XML_ATTRIBUTE
*attr
= NULL
;
1287 HRESULT hr
= WS_E_INVALID_FORMAT
;
1289 if (read_end_of_data( reader
))
1291 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1292 reader
->last
= reader
->current
;
1293 reader
->state
= READER_STATE_EOF
;
1297 if (read_cmp( reader
, "<", 1 )) goto error
;
1298 read_skip( reader
, 1 );
1299 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1301 read_rewind( reader
, 1 );
1305 start
= read_current_ptr( reader
);
1308 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1309 if (!read_isnamechar( ch
)) break;
1310 read_skip( reader
, skip
);
1313 if (!len
) goto error
;
1315 if (!(parent
= find_parent( reader
))) goto error
;
1318 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) goto error
;
1319 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) goto error
;
1320 list_add_tail( &node
->children
, &endnode
->entry
);
1321 endnode
->parent
= node
;
1323 elem
= (WS_XML_ELEMENT_NODE
*)node
;
1324 if ((hr
= parse_name( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1326 reader
->current_attr
= 0;
1329 read_skip_whitespace( reader
);
1330 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1331 if ((hr
= read_attribute( reader
, &attr
)) != S_OK
) goto error
;
1332 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1334 free_attribute( attr
);
1337 reader
->current_attr
++;
1339 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1341 read_insert_node( reader
, parent
, node
);
1342 reader
->state
= READER_STATE_STARTELEMENT
;
1346 destroy_nodes( node
);
1350 static HRESULT
read_text( struct reader
*reader
)
1352 unsigned int len
= 0, ch
, skip
;
1353 const unsigned char *start
;
1354 struct node
*node
, *parent
;
1355 WS_XML_TEXT_NODE
*text
;
1356 WS_XML_UTF8_TEXT
*utf8
;
1359 start
= read_current_ptr( reader
);
1362 if (read_end_of_data( reader
)) break;
1363 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1364 if (ch
== '<') break;
1365 read_skip( reader
, skip
);
1369 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1371 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1372 text
= (WS_XML_TEXT_NODE
*)node
;
1373 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
1376 return E_OUTOFMEMORY
;
1378 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1384 text
->text
= &utf8
->text
;
1386 read_insert_node( reader
, parent
, node
);
1387 reader
->state
= READER_STATE_TEXT
;
1388 reader
->text_conv_offset
= 0;
1392 static HRESULT
read_node( struct reader
* );
1394 static HRESULT
read_startelement( struct reader
*reader
)
1396 read_skip_whitespace( reader
);
1397 if (!read_cmp( reader
, "/>", 2 ))
1399 read_skip( reader
, 2 );
1400 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->children
), struct node
, entry
);
1401 reader
->last
= reader
->current
;
1402 reader
->state
= READER_STATE_ENDELEMENT
;
1405 else if (!read_cmp( reader
, ">", 1 ))
1407 read_skip( reader
, 1 );
1408 return read_node( reader
);
1410 return WS_E_INVALID_FORMAT
;
1413 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
1417 switch (reader
->state
)
1419 case READER_STATE_INITIAL
:
1420 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
1423 case READER_STATE_STARTELEMENT
:
1424 if (found
) *found
= TRUE
;
1431 read_skip_whitespace( reader
);
1432 if ((hr
= read_element( reader
)) == S_OK
&& found
)
1434 if (reader
->state
== READER_STATE_STARTELEMENT
)
1443 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
1446 if (len1
!= len2
) return 1;
1447 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
1451 static struct node
*read_find_startelement( struct reader
*reader
, const WS_XML_STRING
*prefix
,
1452 const WS_XML_STRING
*localname
)
1454 struct node
*parent
;
1455 const WS_XML_STRING
*str
;
1457 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
1459 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1461 str
= parent
->hdr
.prefix
;
1462 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
1463 str
= parent
->hdr
.localName
;
1464 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
1471 static HRESULT
read_endelement( struct reader
*reader
)
1473 struct node
*parent
;
1474 unsigned int len
= 0, ch
, skip
;
1475 const unsigned char *start
;
1476 WS_XML_STRING
*prefix
, *localname
;
1479 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
1481 if (read_end_of_data( reader
))
1483 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1484 reader
->last
= reader
->current
;
1485 reader
->state
= READER_STATE_EOF
;
1489 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
1490 read_skip( reader
, 2 );
1492 start
= read_current_ptr( reader
);
1495 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1498 read_skip( reader
, 1 );
1501 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
1502 read_skip( reader
, skip
);
1506 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
1507 parent
= read_find_startelement( reader
, prefix
, localname
);
1508 heap_free( prefix
);
1509 heap_free( localname
);
1510 if (!parent
) return WS_E_INVALID_FORMAT
;
1512 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
1513 reader
->last
= reader
->current
;
1514 reader
->state
= READER_STATE_ENDELEMENT
;
1518 static HRESULT
read_comment( struct reader
*reader
)
1520 unsigned int len
= 0, ch
, skip
;
1521 const unsigned char *start
;
1522 struct node
*node
, *parent
;
1523 WS_XML_COMMENT_NODE
*comment
;
1525 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
1526 read_skip( reader
, 4 );
1528 start
= read_current_ptr( reader
);
1531 if (!read_cmp( reader
, "-->", 3 ))
1533 read_skip( reader
, 3 );
1536 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1537 read_skip( reader
, skip
);
1541 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1543 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
1544 comment
= (WS_XML_COMMENT_NODE
*)node
;
1545 if (!(comment
->value
.bytes
= heap_alloc( len
)))
1548 return E_OUTOFMEMORY
;
1550 memcpy( comment
->value
.bytes
, start
, len
);
1551 comment
->value
.length
= len
;
1553 read_insert_node( reader
, parent
, node
);
1554 reader
->state
= READER_STATE_COMMENT
;
1558 static HRESULT
read_startcdata( struct reader
*reader
)
1560 struct node
*node
, *endnode
, *parent
;
1562 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
1563 read_skip( reader
, 9 );
1565 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1567 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1568 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
)))
1571 return E_OUTOFMEMORY
;
1573 list_add_tail( &node
->children
, &endnode
->entry
);
1574 endnode
->parent
= node
;
1576 read_insert_node( reader
, parent
, node
);
1577 reader
->state
= READER_STATE_STARTCDATA
;
1581 static HRESULT
read_cdata( struct reader
*reader
)
1583 unsigned int len
= 0, ch
, skip
;
1584 const unsigned char *start
;
1586 WS_XML_TEXT_NODE
*text
;
1587 WS_XML_UTF8_TEXT
*utf8
;
1589 start
= read_current_ptr( reader
);
1592 if (!read_cmp( reader
, "]]>", 3 )) break;
1593 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1594 read_skip( reader
, skip
);
1598 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1599 text
= (WS_XML_TEXT_NODE
*)node
;
1600 if (!(utf8
= alloc_utf8_text( start
, len
)))
1603 return E_OUTOFMEMORY
;
1605 text
->text
= &utf8
->text
;
1607 read_insert_node( reader
, reader
->current
, node
);
1608 reader
->state
= READER_STATE_CDATA
;
1612 static HRESULT
read_endcdata( struct reader
*reader
)
1614 struct node
*parent
;
1616 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
1617 read_skip( reader
, 3 );
1619 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
) parent
= reader
->current
->parent
;
1620 else parent
= reader
->current
;
1622 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
1623 reader
->last
= reader
->current
;
1624 reader
->state
= READER_STATE_ENDCDATA
;
1628 static HRESULT
read_node( struct reader
*reader
)
1634 if (read_end_of_data( reader
))
1636 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1637 reader
->last
= reader
->current
;
1638 reader
->state
= READER_STATE_EOF
;
1641 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
1642 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
1643 else if (!read_cmp( reader
, "<?", 2 ))
1645 hr
= read_xmldecl( reader
);
1646 if (FAILED( hr
)) return hr
;
1648 else if (!read_cmp( reader
, "</", 2 )) return read_endelement( reader
);
1649 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
1650 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment( reader
);
1651 else if (!read_cmp( reader
, "<", 1 )) return read_element( reader
);
1652 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement( reader
);
1653 else return read_text( reader
);
1657 /**************************************************************************
1658 * WsReadEndElement [webservices.@]
1660 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1662 struct reader
*reader
= (struct reader
*)handle
;
1665 TRACE( "%p %p\n", handle
, error
);
1666 if (error
) FIXME( "ignoring error parameter\n" );
1668 if (!reader
) return E_INVALIDARG
;
1670 EnterCriticalSection( &reader
->cs
);
1672 if (reader
->magic
!= READER_MAGIC
)
1674 LeaveCriticalSection( &reader
->cs
);
1675 return E_INVALIDARG
;
1678 hr
= read_endelement( reader
);
1680 LeaveCriticalSection( &reader
->cs
);
1684 /**************************************************************************
1685 * WsReadNode [webservices.@]
1687 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
1689 struct reader
*reader
= (struct reader
*)handle
;
1692 TRACE( "%p %p\n", handle
, error
);
1693 if (error
) FIXME( "ignoring error parameter\n" );
1695 if (!reader
) return E_INVALIDARG
;
1697 EnterCriticalSection( &reader
->cs
);
1699 if (reader
->magic
!= READER_MAGIC
)
1701 LeaveCriticalSection( &reader
->cs
);
1702 return E_INVALIDARG
;
1705 hr
= read_node( reader
);
1707 LeaveCriticalSection( &reader
->cs
);
1711 /**************************************************************************
1712 * WsReadStartElement [webservices.@]
1714 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
1716 struct reader
*reader
= (struct reader
*)handle
;
1719 TRACE( "%p %p\n", handle
, error
);
1720 if (error
) FIXME( "ignoring error parameter\n" );
1722 if (!reader
) return E_INVALIDARG
;
1724 EnterCriticalSection( &reader
->cs
);
1726 if (reader
->magic
!= READER_MAGIC
)
1728 LeaveCriticalSection( &reader
->cs
);
1729 return E_INVALIDARG
;
1732 hr
= read_startelement( reader
);
1734 LeaveCriticalSection( &reader
->cs
);
1738 /**************************************************************************
1739 * WsReadToStartElement [webservices.@]
1741 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
1742 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
1744 struct reader
*reader
= (struct reader
*)handle
;
1747 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
1748 if (error
) FIXME( "ignoring error parameter\n" );
1750 if (!reader
) return E_INVALIDARG
;
1751 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
1753 EnterCriticalSection( &reader
->cs
);
1755 if (reader
->magic
!= READER_MAGIC
)
1757 LeaveCriticalSection( &reader
->cs
);
1758 return E_INVALIDARG
;
1761 hr
= read_to_startelement( reader
, found
);
1763 LeaveCriticalSection( &reader
->cs
);
1767 BOOL
move_to_root_element( struct node
*root
, struct node
**current
)
1772 if (!(ptr
= list_head( &root
->children
))) return FALSE
;
1773 node
= LIST_ENTRY( ptr
, struct node
, entry
);
1774 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
1779 while ((ptr
= list_next( &root
->children
, &node
->entry
)))
1781 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1782 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1792 BOOL
move_to_next_element( struct node
**current
)
1795 struct node
*node
= *current
, *parent
= (*current
)->parent
;
1797 if (!parent
) return FALSE
;
1798 while ((ptr
= list_next( &parent
->children
, &node
->entry
)))
1800 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1801 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1811 BOOL
move_to_prev_element( struct node
**current
)
1814 struct node
*node
= *current
, *parent
= (*current
)->parent
;
1816 if (!parent
) return FALSE
;
1817 while ((ptr
= list_prev( &parent
->children
, &node
->entry
)))
1819 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
1820 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
1830 BOOL
move_to_child_element( struct node
**current
)
1833 struct node
*child
, *node
= *current
;
1835 if (!(ptr
= list_head( &node
->children
))) return FALSE
;
1836 child
= LIST_ENTRY( ptr
, struct node
, entry
);
1837 if (node_type( child
) == WS_XML_NODE_TYPE_ELEMENT
)
1842 while ((ptr
= list_next( &node
->children
, &child
->entry
)))
1844 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
1845 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
1855 BOOL
move_to_end_element( struct node
**current
)
1858 struct node
*node
= *current
;
1860 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
1862 if ((ptr
= list_tail( &node
->children
)))
1864 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
1865 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1874 BOOL
move_to_parent_element( struct node
**current
)
1876 struct node
*parent
= (*current
)->parent
;
1878 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
1879 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
1887 BOOL
move_to_first_node( struct node
**current
)
1890 struct node
*node
= *current
;
1892 if ((ptr
= list_head( &node
->parent
->children
)))
1894 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
1900 BOOL
move_to_next_node( struct node
**current
)
1903 struct node
*node
= *current
;
1905 if ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
1907 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
1913 BOOL
move_to_prev_node( struct node
**current
)
1916 struct node
*node
= *current
;
1918 if ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
1920 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
1926 BOOL
move_to_bof( struct node
*root
, struct node
**current
)
1932 BOOL
move_to_eof( struct node
*root
, struct node
**current
)
1935 if ((ptr
= list_tail( &root
->children
)))
1937 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
1943 BOOL
move_to_child_node( struct node
**current
)
1946 struct node
*node
= *current
;
1948 if ((ptr
= list_head( &node
->children
)))
1950 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
1956 BOOL
move_to_parent_node( struct node
**current
)
1958 struct node
*parent
= (*current
)->parent
;
1959 if (!parent
) return FALSE
;
1964 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
1966 BOOL success
= FALSE
;
1969 if (!read_end_of_data( reader
))
1971 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
1972 if (hr
!= S_OK
) return hr
;
1976 case WS_MOVE_TO_ROOT_ELEMENT
:
1977 success
= move_to_root_element( reader
->root
, &reader
->current
);
1980 case WS_MOVE_TO_NEXT_ELEMENT
:
1981 success
= move_to_next_element( &reader
->current
);
1984 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
1985 success
= move_to_prev_element( &reader
->current
);
1988 case WS_MOVE_TO_CHILD_ELEMENT
:
1989 success
= move_to_child_element( &reader
->current
);
1992 case WS_MOVE_TO_END_ELEMENT
:
1993 success
= move_to_end_element( &reader
->current
);
1996 case WS_MOVE_TO_PARENT_ELEMENT
:
1997 success
= move_to_parent_element( &reader
->current
);
2000 case WS_MOVE_TO_FIRST_NODE
:
2001 success
= move_to_first_node( &reader
->current
);
2004 case WS_MOVE_TO_NEXT_NODE
:
2005 success
= move_to_next_node( &reader
->current
);
2008 case WS_MOVE_TO_PREVIOUS_NODE
:
2009 success
= move_to_prev_node( &reader
->current
);
2012 case WS_MOVE_TO_CHILD_NODE
:
2013 success
= move_to_child_node( &reader
->current
);
2016 case WS_MOVE_TO_BOF
:
2017 success
= move_to_bof( reader
->root
, &reader
->current
);
2020 case WS_MOVE_TO_EOF
:
2021 success
= move_to_eof( reader
->root
, &reader
->current
);
2025 FIXME( "unhandled move %u\n", move
);
2034 return success
? S_OK
: WS_E_INVALID_FORMAT
;
2037 /**************************************************************************
2038 * WsMoveReader [webservices.@]
2040 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
2042 struct reader
*reader
= (struct reader
*)handle
;
2045 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
2046 if (error
) FIXME( "ignoring error parameter\n" );
2048 if (!reader
) return E_INVALIDARG
;
2050 EnterCriticalSection( &reader
->cs
);
2052 if (reader
->magic
!= READER_MAGIC
)
2054 LeaveCriticalSection( &reader
->cs
);
2055 return E_INVALIDARG
;
2058 if (!reader
->input_type
)
2060 LeaveCriticalSection( &reader
->cs
);
2061 return WS_E_INVALID_OPERATION
;
2064 hr
= read_move_to( reader
, move
, found
);
2066 LeaveCriticalSection( &reader
->cs
);
2070 /**************************************************************************
2071 * WsReadStartAttribute [webservices.@]
2073 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
2075 struct reader
*reader
= (struct reader
*)handle
;
2076 const WS_XML_ELEMENT_NODE
*elem
;
2078 TRACE( "%p %u %p\n", handle
, index
, error
);
2079 if (error
) FIXME( "ignoring error parameter\n" );
2081 if (!reader
) return E_INVALIDARG
;
2083 EnterCriticalSection( &reader
->cs
);
2085 if (reader
->magic
!= READER_MAGIC
)
2087 LeaveCriticalSection( &reader
->cs
);
2088 return E_INVALIDARG
;
2091 elem
= &reader
->current
->hdr
;
2092 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
2094 LeaveCriticalSection( &reader
->cs
);
2095 return WS_E_INVALID_FORMAT
;
2098 reader
->current_attr
= index
;
2099 reader
->state
= READER_STATE_STARTATTRIBUTE
;
2101 LeaveCriticalSection( &reader
->cs
);
2105 /**************************************************************************
2106 * WsReadEndAttribute [webservices.@]
2108 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
2110 struct reader
*reader
= (struct reader
*)handle
;
2112 TRACE( "%p %p\n", handle
, error
);
2113 if (error
) FIXME( "ignoring error parameter\n" );
2115 if (!reader
) return E_INVALIDARG
;
2117 EnterCriticalSection( &reader
->cs
);
2119 if (reader
->magic
!= READER_MAGIC
)
2121 LeaveCriticalSection( &reader
->cs
);
2122 return E_INVALIDARG
;
2125 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
2127 LeaveCriticalSection( &reader
->cs
);
2128 return WS_E_INVALID_FORMAT
;
2131 reader
->state
= READER_STATE_STARTELEMENT
;
2133 LeaveCriticalSection( &reader
->cs
);
2137 static HRESULT
find_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
**ns
)
2139 const struct node
*node
;
2140 for (node
= reader
->current
->parent
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
2142 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
2144 for (i
= 0; i
< elem
->attributeCount
; i
++)
2146 if (!elem
->attributes
[i
]->isXmlNs
) continue;
2147 if (WsXmlStringEquals( elem
->attributes
[i
]->prefix
, prefix
, NULL
) != S_OK
) continue;
2148 *ns
= elem
->attributes
[i
]->ns
;
2152 return WS_E_INVALID_FORMAT
;
2155 static HRESULT
read_qualified_name( struct reader
*reader
, WS_HEAP
*heap
, WS_XML_STRING
*prefix_ret
,
2156 WS_XML_STRING
*localname_ret
, WS_XML_STRING
*ns_ret
)
2158 const WS_XML_TEXT_NODE
*node
= (const WS_XML_TEXT_NODE
*)reader
->current
;
2159 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)node
->text
;
2160 unsigned char *prefix_bytes
, *localname_bytes
, *ns_bytes
;
2161 const unsigned char *ptr
= utf8
->value
.bytes
;
2162 WS_XML_STRING prefix
, localname
, empty
= {0, NULL
};
2163 const WS_XML_STRING
*ns
= &empty
;
2164 ULONG len
= utf8
->value
.length
;
2167 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
2168 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
2169 if (!len
) return WS_E_INVALID_FORMAT
;
2171 if ((hr
= split_name( ptr
, len
, (const unsigned char **)&prefix
.bytes
, &prefix
.length
,
2172 (const unsigned char **)&localname
.bytes
, &localname
.length
)) != S_OK
) return hr
;
2174 if (!localname
.length
) return WS_E_INVALID_FORMAT
;
2175 if (prefix
.length
&& (hr
= find_namespace( reader
, &prefix
, &ns
)) != S_OK
) return hr
;
2177 if (!(prefix_bytes
= ws_alloc( heap
, prefix
.length
))) return WS_E_QUOTA_EXCEEDED
;
2178 memcpy( prefix_bytes
, prefix
.bytes
, prefix
.length
);
2180 if (!(localname_bytes
= ws_alloc( heap
, localname
.length
)))
2182 ws_free( heap
, prefix_bytes
, prefix
.length
);
2183 return WS_E_QUOTA_EXCEEDED
;
2185 memcpy( localname_bytes
, localname
.bytes
, localname
.length
);
2187 if (!(ns_bytes
= ws_alloc( heap
, ns
->length
)))
2189 ws_free( heap
, prefix_bytes
, prefix
.length
);
2190 ws_free( heap
, localname_bytes
, localname
.length
);
2191 return WS_E_QUOTA_EXCEEDED
;
2193 memcpy( ns_bytes
, ns
->bytes
, ns
->length
);
2195 prefix_ret
->bytes
= prefix_bytes
;
2196 prefix_ret
->length
= prefix
.length
;
2198 localname_ret
->bytes
= localname_bytes
;
2199 localname_ret
->length
= localname
.length
;
2201 ns_ret
->bytes
= ns_bytes
;
2202 ns_ret
->length
= ns
->length
;
2207 /**************************************************************************
2208 * WsReadQualifiedName [webservices.@]
2210 HRESULT WINAPI
WsReadQualifiedName( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
2211 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
,
2214 struct reader
*reader
= (struct reader
*)handle
;
2217 TRACE( "%p %p %p %p %p %p\n", handle
, heap
, prefix
, localname
, ns
, error
);
2218 if (error
) FIXME( "ignoring error parameter\n" );
2220 if (!reader
|| !heap
) return E_INVALIDARG
;
2222 EnterCriticalSection( &reader
->cs
);
2224 if (reader
->magic
!= READER_MAGIC
)
2226 LeaveCriticalSection( &reader
->cs
);
2227 return E_INVALIDARG
;
2230 if (!reader
->input_type
)
2232 LeaveCriticalSection( &reader
->cs
);
2233 return WS_E_INVALID_OPERATION
;
2238 LeaveCriticalSection( &reader
->cs
);
2239 return E_INVALIDARG
;
2242 if (reader
->state
!= READER_STATE_TEXT
)
2244 LeaveCriticalSection( &reader
->cs
);
2245 return WS_E_INVALID_FORMAT
;
2248 hr
= read_qualified_name( reader
, heap
, prefix
, localname
, ns
);
2250 LeaveCriticalSection( &reader
->cs
);
2254 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
2258 switch (text
->textType
)
2260 case WS_XML_TEXT_TYPE_UTF8
:
2262 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2263 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
2264 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
2265 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
2270 FIXME( "unhandled type %u\n", text
->textType
);
2277 #define MAX_INT8 0x7f
2278 #define MIN_INT8 (-MAX_INT8 - 1)
2279 #define MAX_INT16 0x7fff
2280 #define MIN_INT16 (-MAX_INT16 - 1)
2281 #define MAX_INT32 0x7fffffff
2282 #define MIN_INT32 (-MAX_INT32 - 1)
2283 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
2284 #define MIN_INT64 (-MAX_INT64 - 1)
2285 #define MAX_UINT8 0xff
2286 #define MAX_UINT16 0xffff
2287 #define MAX_UINT32 0xffffffff
2288 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
2290 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
2292 BOOL negative
= FALSE
;
2293 const unsigned char *ptr
= str
;
2296 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
2297 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
2298 if (!len
) return WS_E_INVALID_FORMAT
;
2306 if (!len
) return WS_E_INVALID_FORMAT
;
2312 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
2314 if (negative
) val
= -val
;
2316 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
2317 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
2319 return WS_E_NUMERIC_OVERFLOW
;
2321 *ret
= *ret
* 10 + val
;
2328 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
2330 const unsigned char *ptr
= str
;
2333 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
2334 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
2335 if (!len
) return WS_E_INVALID_FORMAT
;
2341 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
2344 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
2345 *ret
= *ret
* 10 + val
;
2352 BOOL
set_fpword( unsigned short new, unsigned short *old
)
2354 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2355 unsigned short fpword
;
2357 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
2360 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
2363 FIXME( "not implemented\n" );
2368 void restore_fpword( unsigned short fpword
)
2370 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2371 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
2373 FIXME( "not implemented\n" );
2377 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
2379 static const unsigned __int64 nan
= 0xfff8000000000000;
2380 static const unsigned __int64 inf
= 0x7ff0000000000000;
2381 static const unsigned __int64 inf_min
= 0xfff0000000000000;
2382 HRESULT hr
= WS_E_INVALID_FORMAT
;
2383 const unsigned char *p
= str
, *q
;
2384 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
2385 unsigned __int64 val
= 0, tmp
;
2386 long double exp_val
= 1.0, exp_mul
= 10.0;
2387 unsigned short fpword
;
2389 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2390 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2391 if (!len
) return WS_E_INVALID_FORMAT
;
2393 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
2395 *(unsigned __int64
*)ret
= nan
;
2398 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
2400 *(unsigned __int64
*)ret
= inf
;
2403 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
2405 *(unsigned __int64
*)ret
= inf_min
;
2415 else if (*p
== '+') { p
++; len
--; };
2416 if (!len
) return S_OK
;
2418 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
2421 while (len
&& isdigit( *q
)) { q
++; len
--; }
2422 have_digits
= nb_digits
= q
- p
;
2423 for (i
= 0; i
< nb_digits
; i
++)
2425 tmp
= val
* 10 + p
[i
] - '0';
2426 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
2428 for (; i
< nb_digits
; i
++) exp
++;
2439 while (len
&& isdigit( *q
)) { q
++; len
--; };
2440 have_digits
|= nb_digits
= q
- p
;
2441 for (i
= 0; i
< nb_digits
; i
++)
2443 tmp
= val
* 10 + p
[i
] - '0';
2444 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
2449 if (len
> 1 && tolower(*q
) == 'e')
2451 if (!have_digits
) goto done
;
2458 else if (*p
== '+') { p
++; len
--; };
2461 while (len
&& isdigit( *q
)) { q
++; len
--; };
2463 if (!nb_digits
|| len
) goto done
;
2464 for (i
= 0; i
< nb_digits
; i
++)
2466 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
2467 exp_tmp
= MAX_INT32
;
2469 exp_tmp
*= exp_sign
;
2471 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
2472 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
2473 else exp
+= exp_tmp
;
2476 if (!have_digits
|| len
) goto done
;
2478 if ((neg_exp
= exp
< 0)) exp
= -exp
;
2479 for (; exp
; exp
>>= 1)
2481 if (exp
& 1) exp_val
*= exp_mul
;
2485 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
2489 restore_fpword( fpword
);
2493 static HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
2495 static const unsigned char hex
[] =
2497 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
2498 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
2499 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
2500 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
2501 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
2502 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
2503 0,10,11,12,13,14,15 /* 0x60 */
2505 const unsigned char *p
= str
;
2508 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2509 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2510 if (len
!= 36) return WS_E_INVALID_FORMAT
;
2512 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
2513 return WS_E_INVALID_FORMAT
;
2515 for (i
= 0; i
< 36; i
++)
2517 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
2518 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
2521 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
2522 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
2524 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
2525 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
2527 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
2528 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
2529 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
2530 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
2531 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
2532 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
2533 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
2534 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
2539 static inline unsigned char decode_char( unsigned char c
)
2541 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
2542 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
2543 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
2544 if (c
== '+') return 62;
2545 if (c
== '/') return 63;
2549 static ULONG
decode_base64( const unsigned char *base64
, ULONG len
, unsigned char *buf
)
2552 unsigned char c0
, c1
, c2
, c3
;
2553 const unsigned char *p
= base64
;
2557 if ((c0
= decode_char( p
[0] )) > 63) return 0;
2558 if ((c1
= decode_char( p
[1] )) > 63) return 0;
2559 if ((c2
= decode_char( p
[2] )) > 63) return 0;
2560 if ((c3
= decode_char( p
[3] )) > 63) return 0;
2561 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
2562 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
2563 buf
[i
+ 2] = (c2
<< 6) | c3
;
2570 if ((c0
= decode_char( p
[0] )) > 63) return 0;
2571 if ((c1
= decode_char( p
[1] )) > 63) return 0;
2572 buf
[i
] = (c0
<< 2) | (c1
>> 4);
2575 else if (p
[3] == '=')
2577 if ((c0
= decode_char( p
[0] )) > 63) return 0;
2578 if ((c1
= decode_char( p
[1] )) > 63) return 0;
2579 if ((c2
= decode_char( p
[2] )) > 63) return 0;
2580 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
2581 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
2586 if ((c0
= decode_char( p
[0] )) > 63) return 0;
2587 if ((c1
= decode_char( p
[1] )) > 63) return 0;
2588 if ((c2
= decode_char( p
[2] )) > 63) return 0;
2589 if ((c3
= decode_char( p
[3] )) > 63) return 0;
2590 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
2591 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
2592 buf
[i
+ 2] = (c2
<< 6) | c3
;
2598 static HRESULT
str_to_bytes( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_BYTES
*ret
)
2600 const unsigned char *p
= str
;
2602 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2603 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2605 if (len
% 4) return WS_E_INVALID_FORMAT
;
2606 if (!(ret
->bytes
= ws_alloc( heap
, len
* 3 / 4 ))) return WS_E_QUOTA_EXCEEDED
;
2607 ret
->length
= decode_base64( p
, len
, ret
->bytes
);
2611 static const int month_offsets
[2][12] =
2613 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
2614 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
2617 static inline int valid_day( int year
, int month
, int day
)
2619 return day
> 0 && day
<= month_days
[leap_year( year
)][month
- 1];
2622 static inline int leap_days_before( int year
)
2624 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
2627 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
2629 const unsigned char *p
= bytes
, *q
;
2630 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
2632 while (len
&& read_isspace( *p
)) { p
++; len
--; }
2633 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
2636 while (len
&& isdigit( *q
)) { q
++; len
--; };
2637 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2638 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
2639 if (year
< 1) return WS_E_INVALID_FORMAT
;
2642 while (len
&& isdigit( *q
)) { q
++; len
--; };
2643 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
2644 month
= (p
[0] - '0') * 10 + p
[1] - '0';
2645 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
2648 while (len
&& isdigit( *q
)) { q
++; len
--; };
2649 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
2650 day
= (p
[0] - '0') * 10 + p
[1] - '0';
2651 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
2654 while (len
&& isdigit( *q
)) { q
++; len
--; };
2655 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2656 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2657 if (hour
> 24) return WS_E_INVALID_FORMAT
;
2660 while (len
&& isdigit( *q
)) { q
++; len
--; };
2661 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2662 min
= (p
[0] - '0') * 10 + p
[1] - '0';
2663 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2666 while (len
&& isdigit( *q
)) { q
++; len
--; };
2667 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
2668 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
2669 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
2673 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
2675 while (len
&& isdigit( *q
)) { q
++; len
--; };
2677 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
2678 for (i
= 0; i
< nb_digits
; i
++)
2680 sec_frac
+= (p
[i
] - '0') * mul
;
2686 if (--len
) return WS_E_INVALID_FORMAT
;
2687 tz_hour
= tz_min
= tz_neg
= 0;
2688 ret
->format
= WS_DATETIME_FORMAT_UTC
;
2690 else if (*q
== '+' || *q
== '-')
2692 tz_neg
= (*q
== '-') ? 1 : 0;
2695 while (len
&& isdigit( *q
)) { q
++; len
--; };
2696 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
2697 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
2698 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
2701 while (len
&& isdigit( *q
)) { q
++; len
--; };
2702 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
2703 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
2704 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
2706 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
2708 else return WS_E_INVALID_FORMAT
;
2710 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
2711 ret
->ticks
+= month_offsets
[leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
2712 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
2713 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
2714 ret
->ticks
+= min
* TICKS_PER_MIN
;
2715 ret
->ticks
+= sec
* TICKS_PER_SEC
;
2716 ret
->ticks
+= sec_frac
;
2720 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
2721 return WS_E_INVALID_FORMAT
;
2722 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
2723 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
2727 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
2728 return WS_E_INVALID_FORMAT
;
2729 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
2730 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
2736 /**************************************************************************
2737 * WsDateTimeToFileTime [webservices.@]
2739 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
2741 unsigned __int64 ticks
;
2743 TRACE( "%p %p %p\n", dt
, ft
, error
);
2744 if (error
) FIXME( "ignoring error parameter\n" );
2746 if (!dt
|| !ft
) return E_INVALIDARG
;
2748 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
2749 ticks
= dt
->ticks
- TICKS_1601_01_01
;
2750 ft
->dwHighDateTime
= ticks
>> 32;
2751 ft
->dwLowDateTime
= (DWORD
)ticks
;
2755 /**************************************************************************
2756 * WsFileTimeToDateTime [webservices.@]
2758 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
2760 unsigned __int64 ticks
;
2762 TRACE( "%p %p %p\n", ft
, dt
, error
);
2763 if (error
) FIXME( "ignoring error parameter\n" );
2765 if (!dt
|| !ft
) return E_INVALIDARG
;
2767 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
2768 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
2769 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
2770 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
2771 dt
->format
= WS_DATETIME_FORMAT_UTC
;
2775 static HRESULT
read_get_node_text( struct reader
*reader
, WS_XML_UTF8_TEXT
**ret
)
2777 WS_XML_TEXT_NODE
*text
;
2779 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
2780 return WS_E_INVALID_FORMAT
;
2782 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
2783 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2785 FIXME( "text type %u not supported\n", text
->text
->textType
);
2788 *ret
= (WS_XML_UTF8_TEXT
*)text
->text
;
2792 static HRESULT
read_get_attribute_text( struct reader
*reader
, ULONG index
, WS_XML_UTF8_TEXT
**ret
)
2794 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2795 WS_XML_ATTRIBUTE
*attr
;
2797 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2798 return WS_E_INVALID_FORMAT
;
2800 attr
= elem
->attributes
[index
];
2801 if (attr
->value
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
2803 FIXME( "text type %u not supported\n", attr
->value
->textType
);
2806 *ret
= (WS_XML_UTF8_TEXT
*)attr
->value
;
2810 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
2811 const WS_XML_STRING
*ns
, ULONG
*index
)
2814 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2818 *index
= reader
->current_attr
;
2821 for (i
= 0; i
< elem
->attributeCount
; i
++)
2823 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
2824 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
2826 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
2827 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
2836 /**************************************************************************
2837 * WsFindAttribute [webservices.@]
2839 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2840 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
2843 struct reader
*reader
= (struct reader
*)handle
;
2846 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
2847 required
, index
, error
);
2848 if (error
) FIXME( "ignoring error parameter\n" );
2850 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
2852 EnterCriticalSection( &reader
->cs
);
2854 if (reader
->magic
!= READER_MAGIC
)
2856 LeaveCriticalSection( &reader
->cs
);
2857 return E_INVALIDARG
;
2860 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
2862 LeaveCriticalSection( &reader
->cs
);
2863 return WS_E_INVALID_OPERATION
;
2866 if (!find_attribute( reader
, localname
, ns
, index
))
2868 if (required
) hr
= WS_E_INVALID_FORMAT
;
2876 LeaveCriticalSection( &reader
->cs
);
2880 static HRESULT
read_get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2881 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2882 WS_XML_UTF8_TEXT
**ret
, BOOL
*found
)
2886 case WS_ATTRIBUTE_TYPE_MAPPING
:
2889 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
2890 return read_get_attribute_text( reader
, index
, ret
);
2892 case WS_ELEMENT_TYPE_MAPPING
:
2893 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2894 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2900 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
2902 if (WsXmlStringEquals( localname
, elem
->localName
, NULL
) != S_OK
||
2903 WsXmlStringEquals( ns
, elem
->ns
, NULL
) != S_OK
)
2908 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
2910 return read_get_node_text( reader
, ret
);
2913 FIXME( "mapping %u not supported\n", mapping
);
2918 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2919 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2920 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2921 WS_HEAP
*heap
, void *ret
, ULONG size
)
2923 WS_XML_UTF8_TEXT
*utf8
;
2925 BOOL found
, val
= FALSE
;
2929 FIXME( "description not supported\n" );
2932 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2935 ULONG len
= utf8
->value
.length
;
2936 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
2937 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
2938 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
2939 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
2940 else return WS_E_INVALID_FORMAT
;
2945 case WS_READ_REQUIRED_VALUE
:
2946 if (!found
) return WS_E_INVALID_FORMAT
;
2949 case WS_READ_NILLABLE_VALUE
:
2950 if (size
!= sizeof(BOOL
)) return E_INVALIDARG
;
2954 case WS_READ_REQUIRED_POINTER
:
2955 if (!found
) return WS_E_INVALID_FORMAT
;
2958 case WS_READ_OPTIONAL_POINTER
:
2959 case WS_READ_NILLABLE_POINTER
:
2961 BOOL
*heap_val
= NULL
;
2962 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
2965 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
2968 *(BOOL
**)ret
= heap_val
;
2972 FIXME( "read option %u not supported\n", option
);
2979 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
2980 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2981 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
2982 WS_HEAP
*heap
, void *ret
, ULONG size
)
2984 WS_XML_UTF8_TEXT
*utf8
;
2991 FIXME( "description not supported\n" );
2994 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
2995 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
3000 case WS_READ_REQUIRED_VALUE
:
3001 if (!found
) return WS_E_INVALID_FORMAT
;
3004 case WS_READ_NILLABLE_VALUE
:
3005 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
3009 case WS_READ_REQUIRED_POINTER
:
3010 if (!found
) return WS_E_INVALID_FORMAT
;
3013 case WS_READ_OPTIONAL_POINTER
:
3014 case WS_READ_NILLABLE_POINTER
:
3016 INT8
*heap_val
= NULL
;
3017 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3020 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3023 *(INT8
**)ret
= heap_val
;
3027 FIXME( "read option %u not supported\n", option
);
3034 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3035 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3036 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3037 WS_HEAP
*heap
, void *ret
, ULONG size
)
3039 WS_XML_UTF8_TEXT
*utf8
;
3046 FIXME( "description not supported\n" );
3049 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3050 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
3055 case WS_READ_REQUIRED_VALUE
:
3056 if (!found
) return WS_E_INVALID_FORMAT
;
3059 case WS_READ_NILLABLE_VALUE
:
3060 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
3061 *(INT16
*)ret
= val
;
3064 case WS_READ_REQUIRED_POINTER
:
3065 if (!found
) return WS_E_INVALID_FORMAT
;
3068 case WS_READ_OPTIONAL_POINTER
:
3069 case WS_READ_NILLABLE_POINTER
:
3071 INT16
*heap_val
= NULL
;
3072 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3075 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3078 *(INT16
**)ret
= heap_val
;
3082 FIXME( "read option %u not supported\n", option
);
3089 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3090 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3091 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3092 WS_HEAP
*heap
, void *ret
, ULONG size
)
3094 WS_XML_UTF8_TEXT
*utf8
;
3101 FIXME( "description not supported\n" );
3104 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3105 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
3110 case WS_READ_REQUIRED_VALUE
:
3111 if (!found
) return WS_E_INVALID_FORMAT
;
3114 case WS_READ_NILLABLE_VALUE
:
3115 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
3116 *(INT32
*)ret
= val
;
3119 case WS_READ_REQUIRED_POINTER
:
3120 if (!found
) return WS_E_INVALID_FORMAT
;
3123 case WS_READ_OPTIONAL_POINTER
:
3124 case WS_READ_NILLABLE_POINTER
:
3126 INT32
*heap_val
= NULL
;
3127 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3130 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3133 *(INT32
**)ret
= heap_val
;
3137 FIXME( "read option %u not supported\n", option
);
3144 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3145 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3146 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3147 WS_HEAP
*heap
, void *ret
, ULONG size
)
3149 WS_XML_UTF8_TEXT
*utf8
;
3156 FIXME( "description not supported\n" );
3159 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3160 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
3165 case WS_READ_REQUIRED_VALUE
:
3166 if (!found
) return WS_E_INVALID_FORMAT
;
3169 case WS_READ_NILLABLE_VALUE
:
3170 if (size
!= sizeof(INT64
)) return E_INVALIDARG
;
3171 *(INT64
*)ret
= val
;
3174 case WS_READ_REQUIRED_POINTER
:
3175 if (!found
) return WS_E_INVALID_FORMAT
;
3178 case WS_READ_OPTIONAL_POINTER
:
3179 case WS_READ_NILLABLE_POINTER
:
3181 INT64
*heap_val
= NULL
;
3182 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3185 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3188 *(INT64
**)ret
= heap_val
;
3192 FIXME( "read option %u not supported\n", option
);
3199 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3200 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3201 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3202 WS_HEAP
*heap
, void *ret
, ULONG size
)
3204 WS_XML_UTF8_TEXT
*utf8
;
3211 FIXME( "description not supported\n" );
3214 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3215 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
3220 case WS_READ_REQUIRED_VALUE
:
3221 if (!found
) return WS_E_INVALID_FORMAT
;
3224 case WS_READ_NILLABLE_VALUE
:
3225 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
3226 *(UINT8
*)ret
= val
;
3229 case WS_READ_REQUIRED_POINTER
:
3230 if (!found
) return WS_E_INVALID_FORMAT
;
3233 case WS_READ_OPTIONAL_POINTER
:
3234 case WS_READ_NILLABLE_POINTER
:
3236 UINT8
*heap_val
= NULL
;
3237 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3240 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3243 *(UINT8
**)ret
= heap_val
;
3247 FIXME( "read option %u not supported\n", option
);
3254 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3255 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3256 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3257 WS_HEAP
*heap
, void *ret
, ULONG size
)
3259 WS_XML_UTF8_TEXT
*utf8
;
3266 FIXME( "description not supported\n" );
3269 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3270 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
3275 case WS_READ_REQUIRED_VALUE
:
3276 if (!found
) return WS_E_INVALID_FORMAT
;
3279 case WS_READ_NILLABLE_VALUE
:
3280 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
3281 *(UINT16
*)ret
= val
;
3284 case WS_READ_REQUIRED_POINTER
:
3285 if (!found
) return WS_E_INVALID_FORMAT
;
3288 case WS_READ_OPTIONAL_POINTER
:
3289 case WS_READ_NILLABLE_POINTER
:
3291 UINT16
*heap_val
= NULL
;
3292 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3295 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3298 *(UINT16
**)ret
= heap_val
;
3302 FIXME( "read option %u not supported\n", option
);
3309 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3310 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3311 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3312 WS_HEAP
*heap
, void *ret
, ULONG size
)
3314 WS_XML_UTF8_TEXT
*utf8
;
3321 FIXME( "description not supported\n" );
3324 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3325 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
3330 case WS_READ_REQUIRED_VALUE
:
3331 if (!found
) return WS_E_INVALID_FORMAT
;
3334 case WS_READ_NILLABLE_VALUE
:
3335 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
3336 *(UINT32
*)ret
= val
;
3339 case WS_READ_REQUIRED_POINTER
:
3340 if (!found
) return WS_E_INVALID_FORMAT
;
3343 case WS_READ_OPTIONAL_POINTER
:
3344 case WS_READ_NILLABLE_POINTER
:
3346 UINT32
*heap_val
= NULL
;
3347 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3350 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3353 *(UINT32
**)ret
= heap_val
;
3357 FIXME( "read option %u not supported\n", option
);
3364 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3365 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3366 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3367 WS_HEAP
*heap
, void *ret
, ULONG size
)
3369 WS_XML_UTF8_TEXT
*utf8
;
3376 FIXME( "description not supported\n" );
3379 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3380 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
)) != S_OK
)
3385 case WS_READ_REQUIRED_VALUE
:
3386 if (!found
) return WS_E_INVALID_FORMAT
;
3389 case WS_READ_NILLABLE_VALUE
:
3390 if (size
!= sizeof(UINT64
)) return E_INVALIDARG
;
3391 *(UINT64
*)ret
= val
;
3394 case WS_READ_REQUIRED_POINTER
:
3395 if (!found
) return WS_E_INVALID_FORMAT
;
3398 case WS_READ_OPTIONAL_POINTER
:
3399 case WS_READ_NILLABLE_POINTER
:
3401 UINT64
*heap_val
= NULL
;
3402 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3405 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3408 *(UINT64
**)ret
= heap_val
;
3412 FIXME( "read option %u not supported\n", option
);
3419 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3420 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3421 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3422 WS_HEAP
*heap
, void *ret
, ULONG size
)
3424 WS_XML_UTF8_TEXT
*utf8
;
3429 if (desc
) FIXME( "ignoring description\n" );
3431 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3432 if (found
&& (hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3436 case WS_READ_REQUIRED_VALUE
:
3437 if (!found
) return WS_E_INVALID_FORMAT
;
3440 case WS_READ_NILLABLE_VALUE
:
3441 if (size
!= sizeof(double)) return E_INVALIDARG
;
3442 *(double *)ret
= val
;
3445 case WS_READ_REQUIRED_POINTER
:
3446 if (!found
) return WS_E_INVALID_FORMAT
;
3449 case WS_READ_OPTIONAL_POINTER
:
3450 case WS_READ_NILLABLE_POINTER
:
3452 double *heap_val
= NULL
;
3453 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3456 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3459 *(double **)ret
= heap_val
;
3463 FIXME( "read option %u not supported\n", option
);
3470 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3471 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3472 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3473 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
3475 WS_XML_UTF8_TEXT
*utf8
;
3482 FIXME( "description not supported\n" );
3485 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3486 if (found
&& !(str
= xmltext_to_widechar( heap
, &utf8
->text
))) return WS_E_QUOTA_EXCEEDED
;
3490 case WS_READ_REQUIRED_POINTER
:
3491 if (!found
) return WS_E_INVALID_FORMAT
;
3494 case WS_READ_OPTIONAL_POINTER
:
3495 case WS_READ_NILLABLE_POINTER
:
3496 if (size
!= sizeof(str
)) return E_INVALIDARG
;
3501 FIXME( "read option %u not supported\n", option
);
3508 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
3511 for (i
= 0; i
< desc
->valueCount
; i
++)
3513 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
3515 *ret
= desc
->values
[i
].value
;
3519 return WS_E_INVALID_FORMAT
;
3522 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3523 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3524 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3525 WS_HEAP
*heap
, void *ret
, ULONG size
)
3527 WS_XML_UTF8_TEXT
*utf8
;
3532 if (!desc
) return E_INVALIDARG
;
3534 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3535 if (found
&& (hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
3539 case WS_READ_REQUIRED_VALUE
:
3540 if (!found
) return WS_E_INVALID_FORMAT
;
3543 case WS_READ_NILLABLE_VALUE
:
3544 if (size
!= sizeof(int)) return E_INVALIDARG
;
3548 case WS_READ_REQUIRED_POINTER
:
3549 if (!found
) return WS_E_INVALID_FORMAT
;
3552 case WS_READ_OPTIONAL_POINTER
:
3553 case WS_READ_NILLABLE_POINTER
:
3555 int *heap_val
= NULL
;
3556 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3559 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3562 *(int **)ret
= heap_val
;
3566 FIXME( "read option %u not supported\n", option
);
3573 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3574 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3575 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3576 WS_HEAP
*heap
, void *ret
, ULONG size
)
3578 WS_XML_UTF8_TEXT
*utf8
;
3580 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
3583 if (desc
) FIXME( "ignoring description\n" );
3585 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3586 if (found
&& (hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3590 case WS_READ_REQUIRED_VALUE
:
3591 if (!found
) return WS_E_INVALID_FORMAT
;
3594 case WS_READ_NILLABLE_VALUE
:
3595 if (size
!= sizeof(WS_DATETIME
)) return E_INVALIDARG
;
3596 *(WS_DATETIME
*)ret
= val
;
3599 case WS_READ_REQUIRED_POINTER
:
3600 if (!found
) return WS_E_INVALID_FORMAT
;
3603 case WS_READ_OPTIONAL_POINTER
:
3604 case WS_READ_NILLABLE_POINTER
:
3606 WS_DATETIME
*heap_val
= NULL
;
3607 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3610 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3613 *(WS_DATETIME
**)ret
= heap_val
;
3617 FIXME( "read option %u not supported\n", option
);
3624 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3625 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3626 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3627 WS_HEAP
*heap
, void *ret
, ULONG size
)
3629 WS_XML_UTF8_TEXT
*utf8
;
3634 if (desc
) FIXME( "ignoring description\n" );
3636 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3637 if (found
&& (hr
= str_to_guid( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
3641 case WS_READ_REQUIRED_VALUE
:
3642 if (!found
) return WS_E_INVALID_FORMAT
;
3645 case WS_READ_NILLABLE_VALUE
:
3646 if (size
!= sizeof(GUID
)) return E_INVALIDARG
;
3650 case WS_READ_REQUIRED_POINTER
:
3651 if (!found
) return WS_E_INVALID_FORMAT
;
3654 case WS_READ_OPTIONAL_POINTER
:
3655 case WS_READ_NILLABLE_POINTER
:
3657 GUID
*heap_val
= NULL
;
3658 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3661 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3664 *(GUID
**)ret
= heap_val
;
3668 FIXME( "read option %u not supported\n", option
);
3675 static HRESULT
read_type_bytes( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3676 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3677 const WS_BYTES_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3678 WS_HEAP
*heap
, void *ret
, ULONG size
)
3680 WS_XML_UTF8_TEXT
*utf8
;
3685 if (desc
) FIXME( "ignoring description\n" );
3687 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3688 if (found
&& (hr
= str_to_bytes( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
3693 case WS_READ_REQUIRED_VALUE
:
3694 if (!found
) return WS_E_INVALID_FORMAT
;
3697 case WS_READ_NILLABLE_VALUE
:
3698 if (size
!= sizeof(WS_BYTES
)) return E_INVALIDARG
;
3699 *(WS_BYTES
*)ret
= val
;
3702 case WS_READ_REQUIRED_POINTER
:
3703 if (!found
) return WS_E_INVALID_FORMAT
;
3706 case WS_READ_OPTIONAL_POINTER
:
3707 case WS_READ_NILLABLE_POINTER
:
3709 WS_BYTES
*heap_val
= NULL
;
3710 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3713 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
3716 *(WS_BYTES
**)ret
= heap_val
;
3720 FIXME( "read option %u not supported\n", option
);
3727 static BOOL
is_empty_text_node( const struct node
*node
)
3729 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
3730 const WS_XML_UTF8_TEXT
*utf8
;
3733 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
3734 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3736 ERR( "unhandled text type %u\n", text
->text
->textType
);
3739 utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
3740 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
3744 static HRESULT
read_next_node( struct reader
*reader
)
3746 if (reader
->current
== reader
->last
) return read_node( reader
);
3747 if (move_to_child_node( &reader
->current
)) return S_OK
;
3748 if (move_to_next_node( &reader
->current
)) return S_OK
;
3749 if (!move_to_parent_node( &reader
->current
)) return WS_E_INVALID_FORMAT
;
3750 if (move_to_next_node( &reader
->current
)) return S_OK
;
3751 return WS_E_INVALID_FORMAT
;
3754 /* skips comment and empty text nodes */
3755 static HRESULT
read_type_next_node( struct reader
*reader
)
3760 WS_XML_NODE_TYPE type
;
3762 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3763 type
= node_type( reader
->current
);
3764 if (type
== WS_XML_NODE_TYPE_COMMENT
||
3765 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
3770 static BOOL
match_current_element( struct reader
*reader
, const WS_XML_STRING
*localname
,
3771 const WS_XML_STRING
*ns
)
3773 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3774 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
3775 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
3776 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
3779 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
3780 const WS_XML_STRING
*ns
)
3786 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
3787 if (reader
->current
== reader
->last
)
3790 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
3791 if (!found
) return WS_E_INVALID_FORMAT
;
3793 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3795 node
= reader
->current
;
3796 attr
= reader
->current_attr
;
3798 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
3799 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
3801 reader
->current
= node
;
3802 reader
->current_attr
= attr
;
3804 return WS_E_INVALID_FORMAT
;
3807 ULONG
get_type_size( WS_TYPE type
, const WS_STRUCT_DESCRIPTION
*desc
)
3813 return sizeof(INT8
);
3816 case WS_UINT16_TYPE
:
3817 return sizeof(INT16
);
3821 case WS_UINT32_TYPE
:
3823 return sizeof(INT32
);
3826 case WS_UINT64_TYPE
:
3827 return sizeof(INT64
);
3829 case WS_DOUBLE_TYPE
:
3830 return sizeof(double);
3832 case WS_DATETIME_TYPE
:
3833 return sizeof(WS_DATETIME
);
3836 return sizeof(GUID
);
3838 case WS_STRING_TYPE
:
3839 return sizeof(WS_STRING
);
3842 return sizeof(WCHAR
*);
3845 return sizeof(WS_BYTES
);
3847 case WS_XML_STRING_TYPE
:
3848 return sizeof(WS_XML_STRING
);
3850 case WS_STRUCT_TYPE
:
3853 case WS_DESCRIPTION_TYPE
:
3854 return sizeof(WS_STRUCT_DESCRIPTION
*);
3857 ERR( "unhandled type %u\n", type
);
3862 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
, ULONG options
)
3864 if (options
& WS_FIELD_POINTER
)
3866 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
3867 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
3868 return WS_READ_REQUIRED_POINTER
;
3879 case WS_UINT16_TYPE
:
3880 case WS_UINT32_TYPE
:
3881 case WS_UINT64_TYPE
:
3882 case WS_DOUBLE_TYPE
:
3883 case WS_DATETIME_TYPE
:
3885 case WS_STRING_TYPE
:
3887 case WS_XML_STRING_TYPE
:
3888 case WS_STRUCT_TYPE
:
3890 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_READ_NILLABLE_VALUE
;
3891 return WS_READ_REQUIRED_VALUE
;
3894 case WS_DESCRIPTION_TYPE
:
3895 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
3896 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
3897 return WS_READ_REQUIRED_POINTER
;
3900 FIXME( "unhandled type %u\n", type
);
3905 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
3906 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
3909 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3910 WS_HEAP
*heap
, void **ret
, ULONG
*count
)
3913 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
3914 WS_READ_OPTION option
;
3917 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3919 /* wrapper element */
3920 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
3923 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
3924 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
3926 item_size
= sizeof(void *);
3928 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
3931 if (nb_items
>= nb_allocated
)
3933 SIZE_T old_size
= nb_allocated
* item_size
, new_size
= old_size
* 2;
3934 if (!(buf
= ws_realloc_zero( heap
, buf
, old_size
, new_size
)))
3935 return WS_E_QUOTA_EXCEEDED
;
3938 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
3939 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
3940 if (hr
== WS_E_INVALID_FORMAT
) break;
3943 ws_free( heap
, buf
, nb_allocated
* item_size
);
3946 offset
+= item_size
;
3950 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
3952 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
3954 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
3955 desc
->itemRange
->maxItemCount
);
3956 ws_free( heap
, buf
, nb_allocated
* item_size
);
3957 return WS_E_INVALID_FORMAT
;
3966 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3967 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
3970 if (reader
->current
== reader
->last
)
3973 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
3974 if (!found
) return WS_E_INVALID_FORMAT
;
3976 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3977 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
3979 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
3980 desc
->typeDescription
, option
, heap
, ret
, size
);
3983 static HRESULT
read_type_struct_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
3984 WS_HEAP
*heap
, char *buf
, ULONG offset
)
3987 WS_READ_OPTION option
;
3991 if (!desc
) return E_INVALIDARG
;
3992 if (desc
->options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
3994 FIXME( "options %08x not supported\n", desc
->options
);
3997 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3999 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
4000 size
= get_type_size( desc
->type
, desc
->typeDescription
);
4002 size
= sizeof(void *);
4005 switch (desc
->mapping
)
4007 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING
:
4008 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
4011 case WS_ATTRIBUTE_FIELD_MAPPING
:
4012 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
4013 desc
->typeDescription
, option
, heap
, ptr
, size
);
4016 case WS_ELEMENT_FIELD_MAPPING
:
4017 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
4018 desc
->typeDescription
, option
, heap
, ptr
, size
);
4021 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
4024 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, &count
);
4025 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
4028 case WS_TEXT_FIELD_MAPPING
:
4029 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
4033 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
4037 if (hr
== WS_E_INVALID_FORMAT
)
4041 case WS_READ_REQUIRED_VALUE
:
4042 case WS_READ_REQUIRED_POINTER
:
4043 return WS_E_INVALID_FORMAT
;
4045 case WS_READ_NILLABLE_VALUE
:
4046 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
4049 case WS_READ_OPTIONAL_POINTER
:
4050 case WS_READ_NILLABLE_POINTER
:
4051 *(void **)ptr
= NULL
;
4055 ERR( "unhandled option %u\n", option
);
4063 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4064 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4065 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4066 WS_HEAP
*heap
, void *ret
, ULONG size
)
4072 if (!desc
) return E_INVALIDARG
;
4073 if (desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
4075 FIXME( "struct options %08x not supported\n",
4076 desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
);
4081 case WS_READ_REQUIRED_POINTER
:
4082 case WS_READ_OPTIONAL_POINTER
:
4083 case WS_READ_NILLABLE_POINTER
:
4084 if (size
!= sizeof(void *)) return E_INVALIDARG
;
4085 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
4088 case WS_READ_REQUIRED_VALUE
:
4089 case WS_READ_NILLABLE_VALUE
:
4090 if (size
!= desc
->size
) return E_INVALIDARG
;
4095 FIXME( "unhandled read option %u\n", option
);
4099 for (i
= 0; i
< desc
->fieldCount
; i
++)
4101 offset
= desc
->fields
[i
]->offset
;
4102 if ((hr
= read_type_struct_field( reader
, desc
->fields
[i
], heap
, buf
, offset
)) != S_OK
)
4108 case WS_READ_REQUIRED_POINTER
:
4111 ws_free( heap
, buf
, desc
->size
);
4114 *(char **)ret
= buf
;
4117 case WS_READ_OPTIONAL_POINTER
:
4118 case WS_READ_NILLABLE_POINTER
:
4119 if (is_nil_value( buf
, desc
->size
))
4121 ws_free( heap
, buf
, desc
->size
);
4124 *(char **)ret
= buf
;
4127 case WS_READ_REQUIRED_VALUE
:
4128 case WS_READ_NILLABLE_VALUE
:
4129 if (hr
!= S_OK
) return hr
;
4133 ERR( "unhandled read option %u\n", option
);
4137 if (desc
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
4139 struct node
*parent
= find_parent( reader
);
4140 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
4145 static HRESULT
start_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
4146 const WS_XML_STRING
*ns
)
4150 case WS_ELEMENT_TYPE_MAPPING
:
4151 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
4152 return read_type_next_element_node( reader
, localname
, ns
);
4154 case WS_ANY_ELEMENT_TYPE_MAPPING
:
4155 case WS_ATTRIBUTE_TYPE_MAPPING
:
4159 FIXME( "unhandled mapping %u\n", mapping
);
4164 static HRESULT
read_type_endelement_node( struct reader
*reader
)
4166 const struct node
*parent
= find_parent( reader
);
4171 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
4172 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
&& reader
->current
->parent
== parent
)
4176 if (read_end_of_data( reader
) || !(parent
->flags
& NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
)) break;
4179 return WS_E_INVALID_FORMAT
;
4182 static HRESULT
end_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
)
4186 case WS_ELEMENT_TYPE_MAPPING
:
4187 return read_type_endelement_node( reader
);
4189 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
4190 return read_type_next_node( reader
);
4192 case WS_ATTRIBUTE_TYPE_MAPPING
:
4198 static HRESULT
is_nil_element( const WS_XML_ELEMENT_NODE
*elem
)
4200 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
4201 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
4204 for (i
= 0; i
< elem
->attributeCount
; i
++)
4206 const WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[i
]->value
;
4208 if (elem
->attributes
[i
]->isXmlNs
) continue;
4209 if (WsXmlStringEquals( elem
->attributes
[i
]->localName
, &localname
, NULL
) == S_OK
&&
4210 WsXmlStringEquals( elem
->attributes
[i
]->ns
, &ns
, NULL
) == S_OK
&&
4211 text
->value
.length
== 4 && !memcmp( text
->value
.bytes
, "true", 4 )) return TRUE
;
4216 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
4217 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
, const void *desc
,
4218 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
)
4222 if ((hr
= start_mapping( reader
, mapping
, localname
, ns
)) != S_OK
) return hr
;
4224 if (mapping
== WS_ELEMENT_TYPE_MAPPING
&& is_nil_element( &reader
->current
->hdr
))
4226 if (option
!= WS_READ_NILLABLE_POINTER
&& option
!= WS_READ_NILLABLE_VALUE
) return WS_E_INVALID_FORMAT
;
4227 return end_mapping( reader
, mapping
);
4233 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4238 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4243 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4248 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4253 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4258 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4262 case WS_UINT16_TYPE
:
4263 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4267 case WS_UINT32_TYPE
:
4268 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4272 case WS_UINT64_TYPE
:
4273 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4277 case WS_DOUBLE_TYPE
:
4278 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4282 case WS_DATETIME_TYPE
:
4283 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4288 if ((hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4293 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4298 if ((hr
= read_type_bytes( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4302 case WS_STRUCT_TYPE
:
4303 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4308 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
4313 FIXME( "type %u not supported\n", type
);
4317 return end_mapping( reader
, mapping
);
4320 /**************************************************************************
4321 * WsReadType [webservices.@]
4323 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
4324 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
4325 ULONG size
, WS_ERROR
*error
)
4327 struct reader
*reader
= (struct reader
*)handle
;
4330 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
4332 if (error
) FIXME( "ignoring error parameter\n" );
4334 if (!reader
|| !value
) return E_INVALIDARG
;
4336 EnterCriticalSection( &reader
->cs
);
4338 if (reader
->magic
!= READER_MAGIC
)
4340 LeaveCriticalSection( &reader
->cs
);
4341 return E_INVALIDARG
;
4344 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
4346 LeaveCriticalSection( &reader
->cs
);
4352 case WS_ELEMENT_TYPE_MAPPING
:
4353 hr
= read_node( reader
);
4360 if (hr
== S_OK
&& !read_end_of_data( reader
)) hr
= WS_E_INVALID_FORMAT
;
4362 LeaveCriticalSection( &reader
->cs
);
4366 /**************************************************************************
4367 * WsReadElement [webservices.@]
4369 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4370 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
4373 struct reader
*reader
= (struct reader
*)handle
;
4376 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
4377 if (error
) FIXME( "ignoring error parameter\n" );
4379 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
4381 EnterCriticalSection( &reader
->cs
);
4383 if (reader
->magic
!= READER_MAGIC
)
4385 LeaveCriticalSection( &reader
->cs
);
4386 return E_INVALIDARG
;
4389 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
4390 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
4392 LeaveCriticalSection( &reader
->cs
);
4396 /**************************************************************************
4397 * WsReadValue [webservices.@]
4399 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
4402 struct reader
*reader
= (struct reader
*)handle
;
4403 WS_TYPE type
= map_value_type( value_type
);
4406 TRACE( "%p %u %p %u %p\n", handle
, type
, value
, size
, error
);
4407 if (error
) FIXME( "ignoring error parameter\n" );
4409 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
4411 EnterCriticalSection( &reader
->cs
);
4413 if (reader
->magic
!= READER_MAGIC
)
4415 LeaveCriticalSection( &reader
->cs
);
4416 return E_INVALIDARG
;
4419 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
4420 NULL
, value
, size
);
4422 LeaveCriticalSection( &reader
->cs
);
4426 /**************************************************************************
4427 * WsReadAttribute [webservices.@]
4429 HRESULT WINAPI
WsReadAttribute( WS_XML_READER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
4430 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
4433 struct reader
*reader
= (struct reader
*)handle
;
4436 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
4437 if (error
) FIXME( "ignoring error parameter\n" );
4439 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
4441 EnterCriticalSection( &reader
->cs
);
4443 if (reader
->magic
!= READER_MAGIC
)
4445 LeaveCriticalSection( &reader
->cs
);
4446 return E_INVALIDARG
;
4449 if (!reader
->input_type
)
4451 LeaveCriticalSection( &reader
->cs
);
4452 return WS_E_INVALID_OPERATION
;
4455 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->attributeLocalName
,
4456 desc
->attributeNs
, desc
->typeDescription
, option
, heap
, value
, size
);
4458 LeaveCriticalSection( &reader
->cs
);
4462 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
4464 static const char bom
[] = {0xef,0xbb,0xbf};
4465 const unsigned char *p
= data
;
4467 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
4468 (size
> 2 && !(*offset
= 0));
4471 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
4473 static const char bom
[] = {0xff,0xfe};
4474 const unsigned char *p
= data
;
4476 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
4477 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
4480 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
4484 /* FIXME: parse xml declaration */
4486 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
4487 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
4490 FIXME( "charset not recognized\n" );
4494 TRACE( "detected charset %u\n", ret
);
4498 static void set_input_buffer( struct reader
*reader
, struct xmlbuf
*buf
, const unsigned char *data
, ULONG size
)
4500 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
4501 reader
->input_buf
= buf
;
4502 reader
->input_data
= data
;
4503 reader
->input_size
= size
;
4505 reader
->read_size
= reader
->input_size
;
4506 reader
->read_pos
= 0;
4507 reader
->read_bufptr
= reader
->input_data
;
4509 reader
->text_conv_offset
= 0;
4512 /**************************************************************************
4513 * WsSetInput [webservices.@]
4515 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
4516 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
4517 ULONG count
, WS_ERROR
*error
)
4519 struct reader
*reader
= (struct reader
*)handle
;
4521 ULONG i
, offset
= 0;
4524 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
4525 if (error
) FIXME( "ignoring error parameter\n" );
4527 if (!reader
) return E_INVALIDARG
;
4529 EnterCriticalSection( &reader
->cs
);
4531 if (reader
->magic
!= READER_MAGIC
)
4533 LeaveCriticalSection( &reader
->cs
);
4534 return E_INVALIDARG
;
4537 for (i
= 0; i
< count
; i
++)
4539 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4540 properties
[i
].valueSize
);
4541 if (hr
!= S_OK
) goto done
;
4544 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
4546 switch (encoding
->encodingType
)
4548 case WS_XML_READER_ENCODING_TYPE_TEXT
:
4550 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
4551 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
4552 WS_CHARSET charset
= text
->charSet
;
4554 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
4556 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
4561 if (charset
== WS_CHARSET_AUTO
)
4562 charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
4564 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
4565 &charset
, sizeof(charset
) );
4566 if (hr
!= S_OK
) goto done
;
4570 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4575 switch (input
->inputType
)
4577 case WS_XML_READER_INPUT_TYPE_BUFFER
:
4579 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
4580 set_input_buffer( reader
, NULL
, (const unsigned char *)buf
->encodedData
+ offset
,
4581 buf
->encodedDataSize
- offset
);
4585 FIXME( "input type %u not supported\n", input
->inputType
);
4590 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
4591 else read_insert_bof( reader
, node
);
4594 LeaveCriticalSection( &reader
->cs
);
4598 /**************************************************************************
4599 * WsSetInputToBuffer [webservices.@]
4601 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
4602 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
4605 struct reader
*reader
= (struct reader
*)handle
;
4606 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4609 ULONG i
, offset
= 0;
4612 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
4613 if (error
) FIXME( "ignoring error parameter\n" );
4615 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
4617 EnterCriticalSection( &reader
->cs
);
4619 if (reader
->magic
!= READER_MAGIC
)
4621 LeaveCriticalSection( &reader
->cs
);
4622 return E_INVALIDARG
;
4625 for (i
= 0; i
< count
; i
++)
4627 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4628 properties
[i
].valueSize
);
4629 if (hr
!= S_OK
) goto done
;
4632 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
4634 charset
= detect_charset( xmlbuf
->ptr
, xmlbuf
->size
, &offset
);
4635 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
, &charset
,
4637 if (hr
!= S_OK
) goto done
;
4639 set_input_buffer( reader
, xmlbuf
, (const unsigned char *)xmlbuf
->ptr
+ offset
, xmlbuf
->size
- offset
);
4640 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
4641 else read_insert_bof( reader
, node
);
4644 LeaveCriticalSection( &reader
->cs
);
4648 /**************************************************************************
4649 * WsXmlStringEquals [webservices.@]
4651 HRESULT WINAPI
WsXmlStringEquals( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
, WS_ERROR
*error
)
4653 TRACE( "%s %s %p\n", debugstr_xmlstr(str1
), debugstr_xmlstr(str2
), error
);
4654 if (error
) FIXME( "ignoring error parameter\n" );
4656 if (!str1
|| !str2
) return E_INVALIDARG
;
4658 if (str1
->length
!= str2
->length
) return S_FALSE
;
4659 if (!memcmp( str1
->bytes
, str2
->bytes
, str1
->length
)) return S_OK
;
4663 /**************************************************************************
4664 * WsGetReaderPosition [webservices.@]
4666 HRESULT WINAPI
WsGetReaderPosition( WS_XML_READER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4668 struct reader
*reader
= (struct reader
*)handle
;
4670 TRACE( "%p %p %p\n", handle
, pos
, error
);
4671 if (error
) FIXME( "ignoring error parameter\n" );
4673 if (!reader
|| !pos
) return E_INVALIDARG
;
4675 EnterCriticalSection( &reader
->cs
);
4677 if (reader
->magic
!= READER_MAGIC
)
4679 LeaveCriticalSection( &reader
->cs
);
4680 return E_INVALIDARG
;
4683 if (!reader
->input_buf
)
4685 LeaveCriticalSection( &reader
->cs
);
4686 return WS_E_INVALID_OPERATION
;
4689 pos
->buffer
= (WS_XML_BUFFER
*)reader
->input_buf
;
4690 pos
->node
= reader
->current
;
4692 LeaveCriticalSection( &reader
->cs
);
4696 /**************************************************************************
4697 * WsSetReaderPosition [webservices.@]
4699 HRESULT WINAPI
WsSetReaderPosition( WS_XML_READER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4701 struct reader
*reader
= (struct reader
*)handle
;
4703 TRACE( "%p %p %p\n", handle
, pos
, error
);
4704 if (error
) FIXME( "ignoring error parameter\n" );
4706 if (!reader
|| !pos
) return E_INVALIDARG
;
4708 EnterCriticalSection( &reader
->cs
);
4710 if (reader
->magic
!= READER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= reader
->input_buf
)
4712 LeaveCriticalSection( &reader
->cs
);
4713 return E_INVALIDARG
;
4716 if (!reader
->input_buf
)
4718 LeaveCriticalSection( &reader
->cs
);
4719 return WS_E_INVALID_OPERATION
;
4722 reader
->current
= pos
->node
;
4724 LeaveCriticalSection( &reader
->cs
);
4728 static HRESULT
utf8_to_base64( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_BASE64_TEXT
*base64
)
4730 if (utf8
->value
.length
% 4) return WS_E_INVALID_FORMAT
;
4731 if (!(base64
->bytes
= heap_alloc( utf8
->value
.length
* 3 / 4 ))) return E_OUTOFMEMORY
;
4732 base64
->length
= decode_base64( utf8
->value
.bytes
, utf8
->value
.length
, base64
->bytes
);
4736 /**************************************************************************
4737 * WsReadBytes [webservices.@]
4739 HRESULT WINAPI
WsReadBytes( WS_XML_READER
*handle
, void *bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
4741 struct reader
*reader
= (struct reader
*)handle
;
4744 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
4745 if (error
) FIXME( "ignoring error parameter\n" );
4747 if (!reader
) return E_INVALIDARG
;
4749 EnterCriticalSection( &reader
->cs
);
4751 if (reader
->magic
!= READER_MAGIC
)
4753 LeaveCriticalSection( &reader
->cs
);
4754 return E_INVALIDARG
;
4757 if (!reader
->input_type
)
4759 LeaveCriticalSection( &reader
->cs
);
4760 return WS_E_INVALID_OPERATION
;
4765 LeaveCriticalSection( &reader
->cs
);
4766 return E_INVALIDARG
;
4770 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
4772 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
4773 WS_XML_BASE64_TEXT base64
;
4775 if ((hr
= utf8_to_base64( (const WS_XML_UTF8_TEXT
*)text
->text
, &base64
)) != S_OK
)
4777 LeaveCriticalSection( &reader
->cs
);
4780 if (reader
->text_conv_offset
== base64
.length
)
4782 heap_free( base64
.bytes
);
4783 hr
= read_node( reader
);
4784 LeaveCriticalSection( &reader
->cs
);
4787 *count
= min( base64
.length
- reader
->text_conv_offset
, max_count
);
4788 memcpy( bytes
, base64
.bytes
+ reader
->text_conv_offset
, *count
);
4789 reader
->text_conv_offset
+= *count
;
4790 heap_free( base64
.bytes
);
4793 LeaveCriticalSection( &reader
->cs
);
4797 static HRESULT
utf8_to_utf16( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_UTF16_TEXT
*utf16
)
4799 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
4800 if (!(utf16
->bytes
= heap_alloc( len
* sizeof(WCHAR
) ))) return E_OUTOFMEMORY
;
4801 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, (WCHAR
*)utf16
->bytes
, len
);
4802 utf16
->byteCount
= len
* sizeof(WCHAR
);
4806 /**************************************************************************
4807 * WsReadChars [webservices.@]
4809 HRESULT WINAPI
WsReadChars( WS_XML_READER
*handle
, WCHAR
*chars
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
4811 struct reader
*reader
= (struct reader
*)handle
;
4813 TRACE( "%p %p %u %p %p\n", handle
, chars
, max_count
, count
, error
);
4814 if (error
) FIXME( "ignoring error parameter\n" );
4816 if (!reader
) return E_INVALIDARG
;
4818 EnterCriticalSection( &reader
->cs
);
4820 if (reader
->magic
!= READER_MAGIC
)
4822 LeaveCriticalSection( &reader
->cs
);
4823 return E_INVALIDARG
;
4826 if (!reader
->input_type
)
4828 LeaveCriticalSection( &reader
->cs
);
4829 return WS_E_INVALID_OPERATION
;
4834 LeaveCriticalSection( &reader
->cs
);
4835 return E_INVALIDARG
;
4839 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& chars
)
4841 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
4842 WS_XML_UTF16_TEXT utf16
;
4845 if ((hr
= utf8_to_utf16( (const WS_XML_UTF8_TEXT
*)text
->text
, &utf16
)) != S_OK
)
4847 LeaveCriticalSection( &reader
->cs
);
4850 if (reader
->text_conv_offset
== utf16
.byteCount
/ sizeof(WCHAR
))
4852 heap_free( utf16
.bytes
);
4853 hr
= read_node( reader
);
4854 LeaveCriticalSection( &reader
->cs
);
4857 *count
= min( utf16
.byteCount
/ sizeof(WCHAR
) - reader
->text_conv_offset
, max_count
);
4858 memcpy( chars
, utf16
.bytes
+ reader
->text_conv_offset
* sizeof(WCHAR
), *count
* sizeof(WCHAR
) );
4859 reader
->text_conv_offset
+= *count
;
4860 heap_free( utf16
.bytes
);
4863 LeaveCriticalSection( &reader
->cs
);
4867 /**************************************************************************
4868 * WsReadCharsUtf8 [webservices.@]
4870 HRESULT WINAPI
WsReadCharsUtf8( WS_XML_READER
*handle
, BYTE
*bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
4872 struct reader
*reader
= (struct reader
*)handle
;
4875 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
4876 if (error
) FIXME( "ignoring error parameter\n" );
4878 if (!reader
) return E_INVALIDARG
;
4880 EnterCriticalSection( &reader
->cs
);
4882 if (reader
->magic
!= READER_MAGIC
)
4884 LeaveCriticalSection( &reader
->cs
);
4885 return E_INVALIDARG
;
4888 if (!reader
->input_type
)
4890 LeaveCriticalSection( &reader
->cs
);
4891 return WS_E_INVALID_OPERATION
;
4896 LeaveCriticalSection( &reader
->cs
);
4897 return E_INVALIDARG
;
4901 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
4903 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
4904 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
4906 if (reader
->text_conv_offset
== utf8
->value
.length
)
4908 hr
= read_node( reader
);
4909 LeaveCriticalSection( &reader
->cs
);
4912 *count
= min( utf8
->value
.length
- reader
->text_conv_offset
, max_count
);
4913 memcpy( bytes
, utf8
->value
.bytes
+ reader
->text_conv_offset
, *count
);
4914 reader
->text_conv_offset
+= *count
;
4917 LeaveCriticalSection( &reader
->cs
);
4921 HRESULT
get_param_desc( const WS_STRUCT_DESCRIPTION
*desc
, USHORT index
, const WS_FIELD_DESCRIPTION
**ret
)
4923 if (index
>= desc
->fieldCount
) return E_INVALIDARG
;
4924 *ret
= desc
->fields
[index
];
4928 static ULONG
get_field_size( const WS_FIELD_DESCRIPTION
*desc
)
4930 WS_READ_OPTION option
;
4933 switch ((option
= get_field_read_option( desc
->type
, desc
->options
)))
4935 case WS_READ_REQUIRED_POINTER
:
4936 case WS_READ_OPTIONAL_POINTER
:
4937 case WS_READ_NILLABLE_POINTER
:
4938 size
= sizeof(void *);
4941 case WS_READ_REQUIRED_VALUE
:
4942 case WS_READ_NILLABLE_VALUE
:
4943 size
= get_type_size( desc
->type
, desc
->typeDescription
);
4947 WARN( "unhandled option %u\n", option
);
4954 static HRESULT
read_param( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
, void *ret
)
4956 if (!ret
&& !(ret
= ws_alloc_zero( heap
, get_field_size(desc
) ))) return WS_E_QUOTA_EXCEEDED
;
4957 return read_type_struct_field( reader
, desc
, heap
, ret
, 0 );
4960 static HRESULT
read_param_array( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
,
4961 void **ret
, ULONG
*count
)
4963 if (!ret
&& !(ret
= ws_alloc_zero( heap
, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED
;
4964 return read_type_repeating_element( reader
, desc
, heap
, ret
, count
);
4967 static void set_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, ULONG len
,
4971 for (i
= 0; i
< count
; i
++)
4973 if (params
[i
].outputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4975 if ((ptr
= *(ULONG
**)args
[i
])) *ptr
= len
;
4980 HRESULT
read_output_params( WS_XML_READER
*handle
, WS_HEAP
*heap
, const WS_ELEMENT_DESCRIPTION
*desc
,
4981 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4983 struct reader
*reader
= (struct reader
*)handle
;
4984 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4985 const WS_FIELD_DESCRIPTION
*desc_field
;
4989 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4991 EnterCriticalSection( &reader
->cs
);
4993 if (reader
->magic
!= READER_MAGIC
)
4995 LeaveCriticalSection( &reader
->cs
);
4996 return E_INVALIDARG
;
4999 if ((hr
= start_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
)
5002 for (i
= 0; i
< count
; i
++)
5004 if (params
[i
].outputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
5005 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
5007 FIXME( "messages type not supported\n" );
5011 if ((hr
= get_param_desc( desc_struct
, params
[i
].outputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
5012 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
5014 void *ptr
= *(void **)args
[i
];
5015 if ((hr
= read_param( reader
, desc_field
, heap
, ptr
)) != S_OK
) goto done
;
5017 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
5019 void **ptr
= *(void ***)args
[i
];
5020 if ((hr
= read_param_array( reader
, desc_field
, heap
, ptr
, &len
)) != S_OK
) goto done
;
5021 set_array_len( params
, count
, params
[i
].outputMessageIndex
, len
, args
);
5025 if (desc_struct
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5027 struct node
*parent
= find_parent( reader
);
5028 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
5031 hr
= end_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
);
5034 LeaveCriticalSection( &reader
->cs
);