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 ULONG
prop_size( const struct prop_desc
*desc
, ULONG count
)
34 ULONG i
, ret
= count
* sizeof(struct prop
);
35 for (i
= 0; i
< count
; i
++) ret
+= desc
[i
].size
;
39 void prop_init( const struct prop_desc
*desc
, ULONG count
, struct prop
*prop
, void *data
)
43 for (i
= 0; i
< count
; i
++)
46 prop
[i
].size
= desc
[i
].size
;
47 prop
[i
].readonly
= desc
[i
].readonly
;
48 prop
[i
].writeonly
= desc
[i
].writeonly
;
53 HRESULT
prop_set( const struct prop
*prop
, ULONG count
, ULONG id
, const void *value
, ULONG size
)
55 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].readonly
) return E_INVALIDARG
;
56 memcpy( prop
[id
].value
, value
, size
);
60 HRESULT
prop_get( const struct prop
*prop
, ULONG count
, ULONG id
, void *buf
, ULONG size
)
62 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].writeonly
) return E_INVALIDARG
;
63 memcpy( buf
, prop
[id
].value
, prop
[id
].size
);
67 struct node
*alloc_node( WS_XML_NODE_TYPE type
)
71 if (!(ret
= heap_alloc_zero( sizeof(*ret
) ))) return NULL
;
72 ret
->hdr
.node
.nodeType
= type
;
73 list_init( &ret
->entry
);
74 list_init( &ret
->children
);
78 void free_attribute( WS_XML_ATTRIBUTE
*attr
)
81 free_xml_string( attr
->prefix
);
82 free_xml_string( attr
->localName
);
83 free_xml_string( attr
->ns
);
84 heap_free( attr
->value
);
88 void free_node( struct node
*node
)
91 switch (node_type( node
))
93 case WS_XML_NODE_TYPE_ELEMENT
:
95 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
98 for (i
= 0; i
< elem
->attributeCount
; i
++) free_attribute( elem
->attributes
[i
] );
99 heap_free( elem
->attributes
);
100 free_xml_string( elem
->prefix
);
101 free_xml_string( elem
->localName
);
102 free_xml_string( elem
->ns
);
105 case WS_XML_NODE_TYPE_TEXT
:
107 WS_XML_TEXT_NODE
*text
= (WS_XML_TEXT_NODE
*)node
;
108 heap_free( text
->text
);
111 case WS_XML_NODE_TYPE_COMMENT
:
113 WS_XML_COMMENT_NODE
*comment
= (WS_XML_COMMENT_NODE
*)node
;
114 heap_free( comment
->value
.bytes
);
117 case WS_XML_NODE_TYPE_CDATA
:
118 case WS_XML_NODE_TYPE_END_CDATA
:
119 case WS_XML_NODE_TYPE_END_ELEMENT
:
120 case WS_XML_NODE_TYPE_EOF
:
121 case WS_XML_NODE_TYPE_BOF
:
125 ERR( "unhandled type %u\n", node_type( node
) );
131 void destroy_nodes( struct node
*node
)
136 while ((ptr
= list_head( &node
->children
)))
138 struct node
*child
= LIST_ENTRY( ptr
, struct node
, entry
);
139 list_remove( &child
->entry
);
140 destroy_nodes( child
);
145 static WS_XML_ATTRIBUTE
*dup_attribute( const WS_XML_ATTRIBUTE
*src
)
147 WS_XML_ATTRIBUTE
*dst
;
148 const WS_XML_STRING
*prefix
= src
->prefix
;
149 const WS_XML_STRING
*localname
= src
->localName
;
150 const WS_XML_STRING
*ns
= src
->localName
;
151 const WS_XML_TEXT
*text
= src
->value
;
153 if (!(dst
= heap_alloc( sizeof(*dst
) ))) return NULL
;
154 dst
->singleQuote
= src
->singleQuote
;
155 dst
->isXmlNs
= src
->isXmlNs
;
157 if (!prefix
) dst
->prefix
= NULL
;
158 else if (!(dst
->prefix
= dup_xml_string( prefix
))) goto error
;
159 if (!(dst
->localName
= dup_xml_string( localname
))) goto error
;
160 if (!(dst
->ns
= dup_xml_string( ns
))) goto error
;
164 WS_XML_UTF8_TEXT
*utf8
;
165 const WS_XML_UTF8_TEXT
*utf8_src
= (const WS_XML_UTF8_TEXT
*)text
;
166 if (!(utf8
= alloc_utf8_text( utf8_src
->value
.bytes
, utf8_src
->value
.length
))) goto error
;
167 dst
->value
= &utf8
->text
;
173 free_attribute( dst
);
177 static WS_XML_ATTRIBUTE
**dup_attributes( WS_XML_ATTRIBUTE
* const *src
, ULONG count
)
179 WS_XML_ATTRIBUTE
**dst
;
182 if (!(dst
= heap_alloc( sizeof(*dst
) * count
))) return NULL
;
183 for (i
= 0; i
< count
; i
++)
185 if (!(dst
[i
] = dup_attribute( src
[i
] )))
187 for (; i
> 0; i
--) free_attribute( dst
[i
- 1] );
195 static struct node
*dup_element_node( const WS_XML_ELEMENT_NODE
*src
)
198 WS_XML_ELEMENT_NODE
*dst
;
199 ULONG count
= src
->attributeCount
;
200 WS_XML_ATTRIBUTE
**attrs
= src
->attributes
;
201 const WS_XML_STRING
*prefix
= (src
->prefix
&& src
->prefix
->length
) ? src
->prefix
: NULL
;
202 const WS_XML_STRING
*localname
= src
->localName
;
203 const WS_XML_STRING
*ns
= src
->ns
;
205 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
208 if (count
&& !(dst
->attributes
= dup_attributes( attrs
, count
))) goto error
;
209 dst
->attributeCount
= count
;
211 if (prefix
&& !(dst
->prefix
= dup_xml_string( prefix
))) goto error
;
212 if (localname
&& !(dst
->localName
= dup_xml_string( localname
))) goto error
;
213 if (ns
&& !(dst
->ns
= dup_xml_string( ns
))) goto error
;
221 static struct node
*dup_text_node( const WS_XML_TEXT_NODE
*src
)
224 WS_XML_TEXT_NODE
*dst
;
226 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
227 dst
= (WS_XML_TEXT_NODE
*)node
;
231 WS_XML_UTF8_TEXT
*utf8
;
232 const WS_XML_UTF8_TEXT
*utf8_src
= (const WS_XML_UTF8_TEXT
*)src
->text
;
233 if (!(utf8
= alloc_utf8_text( utf8_src
->value
.bytes
, utf8_src
->value
.length
)))
238 dst
->text
= &utf8
->text
;
243 static struct node
*dup_comment_node( const WS_XML_COMMENT_NODE
*src
)
246 WS_XML_COMMENT_NODE
*dst
;
248 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return NULL
;
249 dst
= (WS_XML_COMMENT_NODE
*)node
;
251 if (src
->value
.length
&& !(dst
->value
.bytes
= heap_alloc( src
->value
.length
)))
256 memcpy( dst
->value
.bytes
, src
->value
.bytes
, src
->value
.length
);
257 dst
->value
.length
= src
->value
.length
;
261 static struct node
*dup_node( const struct node
*src
)
263 switch (node_type( src
))
265 case WS_XML_NODE_TYPE_ELEMENT
:
266 return dup_element_node( &src
->hdr
);
268 case WS_XML_NODE_TYPE_TEXT
:
269 return dup_text_node( (const WS_XML_TEXT_NODE
*)src
);
271 case WS_XML_NODE_TYPE_COMMENT
:
272 return dup_comment_node( (const WS_XML_COMMENT_NODE
*)src
);
274 case WS_XML_NODE_TYPE_CDATA
:
275 case WS_XML_NODE_TYPE_END_CDATA
:
276 case WS_XML_NODE_TYPE_END_ELEMENT
:
277 case WS_XML_NODE_TYPE_EOF
:
278 case WS_XML_NODE_TYPE_BOF
:
279 return alloc_node( node_type( src
) );
282 ERR( "unhandled type %u\n", node_type( src
) );
288 static HRESULT
dup_tree( struct node
**dst
, const struct node
*src
)
291 const struct node
*child
;
293 if (!*dst
&& !(*dst
= dup_node( src
))) return E_OUTOFMEMORY
;
296 LIST_FOR_EACH_ENTRY( child
, &src
->children
, struct node
, entry
)
298 HRESULT hr
= E_OUTOFMEMORY
;
299 struct node
*new_child
;
301 if (!(new_child
= dup_node( child
)) || (hr
= dup_tree( &new_child
, child
)) != S_OK
)
303 destroy_nodes( *dst
);
306 new_child
->parent
= parent
;
307 list_add_tail( &parent
->children
, &new_child
->entry
);
312 static const struct prop_desc reader_props
[] =
314 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
315 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
316 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
317 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
318 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
319 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
320 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
321 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
322 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
323 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
324 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
325 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
326 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
327 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
328 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
333 READER_STATE_INITIAL
,
335 READER_STATE_STARTELEMENT
,
336 READER_STATE_STARTATTRIBUTE
,
337 READER_STATE_STARTCDATA
,
340 READER_STATE_ENDELEMENT
,
341 READER_STATE_ENDCDATA
,
342 READER_STATE_COMMENT
,
358 const unsigned char *read_bufptr
;
359 enum reader_state state
;
361 struct node
*current
;
364 struct prefix
*prefixes
;
366 ULONG nb_prefixes_allocated
;
367 WS_XML_READER_ENCODING_TYPE input_enc
;
368 WS_CHARSET input_charset
;
369 WS_XML_READER_INPUT_TYPE input_type
;
370 struct xmlbuf
*input_buf
;
371 const unsigned char *input_data
;
373 ULONG text_conv_offset
;
374 const WS_XML_DICTIONARY
*dict_static
;
375 WS_XML_DICTIONARY
*dict
;
377 struct prop prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
380 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
382 static struct reader
*alloc_reader(void)
384 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
386 ULONG size
= sizeof(*ret
) + prop_size( reader_props
, count
);
388 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
389 if (!(ret
->prefixes
= heap_alloc_zero( sizeof(*ret
->prefixes
) )))
394 ret
->nb_prefixes
= ret
->nb_prefixes_allocated
= 1;
396 ret
->magic
= READER_MAGIC
;
397 InitializeCriticalSection( &ret
->cs
);
398 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": reader.cs");
400 prop_init( reader_props
, count
, ret
->prop
, &ret
[1] );
401 ret
->prop_count
= count
;
405 static void clear_prefixes( struct prefix
*prefixes
, ULONG count
)
408 for (i
= 0; i
< count
; i
++)
410 free_xml_string( prefixes
[i
].str
);
411 prefixes
[i
].str
= NULL
;
412 free_xml_string( prefixes
[i
].ns
);
413 prefixes
[i
].ns
= NULL
;
417 static HRESULT
set_prefix( struct prefix
*prefix
, const WS_XML_STRING
*str
, const WS_XML_STRING
*ns
)
421 free_xml_string( prefix
->str
);
422 if (!(prefix
->str
= dup_xml_string( str
))) return E_OUTOFMEMORY
;
424 if (prefix
->ns
) free_xml_string( prefix
->ns
);
425 if (!(prefix
->ns
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
429 static HRESULT
bind_prefix( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
*ns
)
434 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
436 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
437 return set_prefix( &reader
->prefixes
[i
], NULL
, ns
);
439 if (i
>= reader
->nb_prefixes_allocated
)
441 ULONG new_size
= reader
->nb_prefixes_allocated
* sizeof(*reader
->prefixes
) * 2;
442 struct prefix
*tmp
= heap_realloc_zero( reader
->prefixes
, new_size
);
443 if (!tmp
) return E_OUTOFMEMORY
;
444 reader
->prefixes
= tmp
;
445 reader
->nb_prefixes_allocated
*= 2;
447 if ((hr
= set_prefix( &reader
->prefixes
[i
], prefix
, ns
)) != S_OK
) return hr
;
448 reader
->nb_prefixes
++;
452 static const WS_XML_STRING
*get_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
)
455 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
457 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
458 return reader
->prefixes
[i
].ns
;
463 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
465 if (!reader
->root
) reader
->root
= eof
;
468 eof
->parent
= reader
->root
;
469 list_add_tail( &reader
->root
->children
, &eof
->entry
);
471 reader
->current
= reader
->last
= eof
;
474 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
476 reader
->root
->parent
= bof
;
477 list_add_tail( &bof
->children
, &reader
->root
->entry
);
478 reader
->current
= reader
->last
= reader
->root
= bof
;
481 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
483 node
->parent
= parent
;
484 list_add_before( list_tail( &parent
->children
), &node
->entry
);
485 reader
->current
= reader
->last
= node
;
488 static void free_reader( struct reader
*reader
)
490 destroy_nodes( reader
->root
);
491 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
492 heap_free( reader
->prefixes
);
493 reader
->cs
.DebugInfo
->Spare
[0] = 0;
494 DeleteCriticalSection( &reader
->cs
);
498 static HRESULT
init_reader( struct reader
*reader
)
500 static const WS_XML_STRING empty
= {0, NULL
};
504 reader
->state
= READER_STATE_INITIAL
;
505 destroy_nodes( reader
->root
);
506 reader
->root
= reader
->current
= NULL
;
507 reader
->current_attr
= 0;
508 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
509 reader
->nb_prefixes
= 1;
510 if ((hr
= bind_prefix( reader
, &empty
, &empty
)) != S_OK
) return hr
;
512 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
513 read_insert_eof( reader
, node
);
514 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
515 reader
->input_charset
= WS_CHARSET_UTF8
;
516 reader
->dict_static
= NULL
;
521 /**************************************************************************
522 * WsCreateReader [webservices.@]
524 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
525 WS_XML_READER
**handle
, WS_ERROR
*error
)
527 struct reader
*reader
;
528 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
529 BOOL read_decl
= TRUE
;
532 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
533 if (error
) FIXME( "ignoring error parameter\n" );
535 if (!handle
) return E_INVALIDARG
;
536 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
538 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
539 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
540 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
541 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
543 for (i
= 0; i
< count
; i
++)
545 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
546 properties
[i
].valueSize
);
549 free_reader( reader
);
554 if ((hr
= init_reader( reader
)) != S_OK
)
556 free_reader( reader
);
560 *handle
= (WS_XML_READER
*)reader
;
564 /**************************************************************************
565 * WsFreeReader [webservices.@]
567 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
569 struct reader
*reader
= (struct reader
*)handle
;
571 TRACE( "%p\n", handle
);
575 EnterCriticalSection( &reader
->cs
);
577 if (reader
->magic
!= READER_MAGIC
)
579 LeaveCriticalSection( &reader
->cs
);
585 LeaveCriticalSection( &reader
->cs
);
586 free_reader( reader
);
589 /**************************************************************************
590 * WsFillReader [webservices.@]
592 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
595 struct reader
*reader
= (struct reader
*)handle
;
597 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
598 if (error
) FIXME( "ignoring error parameter\n" );
600 if (!reader
) return E_INVALIDARG
;
602 EnterCriticalSection( &reader
->cs
);
604 if (reader
->magic
!= READER_MAGIC
)
606 LeaveCriticalSection( &reader
->cs
);
610 /* FIXME: add support for stream input */
611 reader
->read_size
= min( min_size
, reader
->input_size
);
612 reader
->read_pos
= 0;
614 LeaveCriticalSection( &reader
->cs
);
618 /**************************************************************************
619 * WsGetNamespaceFromPrefix [webservices.@]
621 HRESULT WINAPI
WsGetNamespaceFromPrefix( WS_XML_READER
*handle
, const WS_XML_STRING
*prefix
,
622 BOOL required
, const WS_XML_STRING
**ns
, WS_ERROR
*error
)
624 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
625 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
626 static const WS_XML_STRING empty_ns
= {0, NULL
};
627 static const WS_XML_STRING xml_ns
= {36, (BYTE
*)"http://www.w3.org/XML/1998/namespace"};
628 static const WS_XML_STRING xmlns_ns
= {29, (BYTE
*)"http://www.w3.org/2000/xmlns/"};
629 struct reader
*reader
= (struct reader
*)handle
;
632 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(prefix
), required
, ns
, error
);
633 if (error
) FIXME( "ignoring error parameter\n" );
635 if (!reader
|| !prefix
|| !ns
) return E_INVALIDARG
;
637 EnterCriticalSection( &reader
->cs
);
639 if (reader
->magic
!= READER_MAGIC
)
641 LeaveCriticalSection( &reader
->cs
);
645 if (reader
->state
!= READER_STATE_STARTELEMENT
)
647 LeaveCriticalSection( &reader
->cs
);
648 return WS_E_INVALID_OPERATION
;
656 else if (WsXmlStringEquals( prefix
, &xml
, NULL
) == S_OK
)
661 else if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
668 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
671 for (i
= 0; i
< elem
->attributeCount
; i
++)
673 if (!elem
->attributes
[i
]->isXmlNs
) continue;
674 if (WsXmlStringEquals( prefix
, elem
->attributes
[i
]->prefix
, NULL
) == S_OK
)
676 *ns
= elem
->attributes
[i
]->ns
;
683 LeaveCriticalSection( &reader
->cs
);
687 if (required
) return WS_E_INVALID_FORMAT
;
695 /**************************************************************************
696 * WsGetReaderNode [webservices.@]
698 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
701 struct reader
*reader
= (struct reader
*)handle
;
703 TRACE( "%p %p %p\n", handle
, node
, error
);
704 if (error
) FIXME( "ignoring error parameter\n" );
706 if (!reader
|| !node
) return E_INVALIDARG
;
708 EnterCriticalSection( &reader
->cs
);
710 if (reader
->magic
!= READER_MAGIC
)
712 LeaveCriticalSection( &reader
->cs
);
716 *node
= &reader
->current
->hdr
.node
;
718 LeaveCriticalSection( &reader
->cs
);
722 static HRESULT
get_charset( struct reader
*reader
, void *buf
, ULONG size
)
724 if (!buf
|| size
!= sizeof(reader
->input_charset
)) return E_INVALIDARG
;
725 if (!reader
->input_charset
) return WS_E_INVALID_FORMAT
;
726 *(WS_CHARSET
*)buf
= reader
->input_charset
;
730 /**************************************************************************
731 * WsGetReaderProperty [webservices.@]
733 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
734 void *buf
, ULONG size
, WS_ERROR
*error
)
736 struct reader
*reader
= (struct reader
*)handle
;
739 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
740 if (error
) FIXME( "ignoring error parameter\n" );
742 if (!reader
) return E_INVALIDARG
;
744 EnterCriticalSection( &reader
->cs
);
746 if (reader
->magic
!= READER_MAGIC
)
748 LeaveCriticalSection( &reader
->cs
);
752 if (!reader
->input_type
)
754 LeaveCriticalSection( &reader
->cs
);
755 return WS_E_INVALID_OPERATION
;
758 if (id
== WS_XML_READER_PROPERTY_CHARSET
) hr
= get_charset( reader
, buf
, size
);
759 else hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, buf
, size
);
761 LeaveCriticalSection( &reader
->cs
);
765 /**************************************************************************
766 * WsGetXmlAttribute [webservices.@]
768 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
769 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
771 FIXME( "%p %s %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
775 WS_XML_UTF8_TEXT
*alloc_utf8_text( const unsigned char *data
, ULONG len
)
777 WS_XML_UTF8_TEXT
*ret
;
779 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
780 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
781 ret
->value
.length
= len
;
782 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
783 ret
->value
.dictionary
= NULL
;
785 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
789 static inline BOOL
read_end_of_data( struct reader
*reader
)
791 return reader
->read_pos
>= reader
->read_size
;
794 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
796 return &reader
->read_bufptr
[reader
->read_pos
];
799 static inline HRESULT
read_peek( struct reader
*reader
, unsigned char *byte
)
801 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
802 *byte
= reader
->read_bufptr
[reader
->read_pos
];
806 static inline HRESULT
read_byte( struct reader
*reader
, unsigned char *byte
)
808 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
809 *byte
= reader
->read_bufptr
[reader
->read_pos
++];
813 static inline HRESULT
read_bytes( struct reader
*reader
, unsigned char *bytes
, unsigned int len
)
815 if (reader
->read_pos
+ len
> reader
->read_size
) return WS_E_INVALID_FORMAT
;
816 memcpy( bytes
, reader
->read_bufptr
+ reader
->read_pos
, len
);
817 reader
->read_pos
+= len
;
821 /* UTF-8 support based on libs/wine/utf8.c */
823 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
824 static const char utf8_length
[128] =
826 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
827 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
828 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
829 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
830 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
831 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
832 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
833 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
836 /* first byte mask depending on UTF-8 sequence length */
837 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
839 /* minimum Unicode value depending on UTF-8 sequence length */
840 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
842 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
844 unsigned int len
, res
;
845 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
846 const unsigned char *end
;
848 if (reader
->read_pos
>= reader
->read_size
) return 0;
855 len
= utf8_length
[ch
- 0x80];
856 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
857 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
+ 1;
858 res
= ch
& utf8_mask
[len
];
863 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
864 res
= (res
<< 6) | ch
;
866 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
867 res
= (res
<< 6) | ch
;
869 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
870 res
= (res
<< 6) | ch
;
871 if (res
< utf8_minval
[len
]) break;
879 static inline void read_skip( struct reader
*reader
, unsigned int count
)
881 if (reader
->read_pos
+ count
> reader
->read_size
) return;
882 reader
->read_pos
+= count
;
885 static inline void read_rewind( struct reader
*reader
, unsigned int count
)
887 reader
->read_pos
-= count
;
890 static inline BOOL
read_isnamechar( unsigned int ch
)
892 /* FIXME: incomplete */
893 return (ch
>= 'A' && ch
<= 'Z') ||
894 (ch
>= 'a' && ch
<= 'z') ||
895 (ch
>= '0' && ch
<= '9') ||
896 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
899 static inline BOOL
read_isspace( unsigned int ch
)
901 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
904 static inline void read_skip_whitespace( struct reader
*reader
)
906 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
910 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
912 const unsigned char *ptr
= read_current_ptr( reader
);
914 if (len
< 0) len
= strlen( str
);
915 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
918 if (*str
!= *ptr
) return *ptr
- *str
;
924 static HRESULT
read_xmldecl( struct reader
*reader
)
926 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
928 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
930 reader
->state
= READER_STATE_BOF
;
933 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
934 read_skip( reader
, 6 );
936 /* FIXME: parse attributes */
937 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
940 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
941 read_skip( reader
, 2 );
943 reader
->state
= READER_STATE_BOF
;
947 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
949 if (elem
->attributeCount
)
951 WS_XML_ATTRIBUTE
**tmp
;
952 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
953 return E_OUTOFMEMORY
;
954 elem
->attributes
= tmp
;
956 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
957 elem
->attributes
[elem
->attributeCount
++] = attr
;
961 static inline void init_xml_string( BYTE
*bytes
, ULONG len
, WS_XML_STRING
*str
)
965 str
->dictionary
= NULL
;
969 static HRESULT
split_qname( const BYTE
*str
, ULONG len
, WS_XML_STRING
*prefix
, WS_XML_STRING
*localname
)
971 BYTE
*prefix_bytes
= NULL
, *localname_bytes
= (BYTE
*)str
, *ptr
= (BYTE
*)str
;
972 ULONG prefix_len
= 0, localname_len
= len
;
978 if (ptr
== str
) return WS_E_INVALID_FORMAT
;
979 prefix_bytes
= (BYTE
*)str
;
980 prefix_len
= ptr
- str
;
981 localname_bytes
= ptr
+ 1;
987 if (!localname_len
) return WS_E_INVALID_FORMAT
;
989 init_xml_string( prefix_bytes
, prefix_len
, prefix
);
990 init_xml_string( localname_bytes
, localname_len
, localname
);
994 static HRESULT
parse_qname( const BYTE
*str
, ULONG len
, WS_XML_STRING
**prefix_ret
, WS_XML_STRING
**localname_ret
)
996 WS_XML_STRING prefix
, localname
;
999 if ((hr
= split_qname( str
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
1000 if (!(*prefix_ret
= alloc_xml_string( NULL
, prefix
.length
))) return E_OUTOFMEMORY
;
1001 if (!(*localname_ret
= dup_xml_string( &localname
)))
1003 free_xml_string( *prefix_ret
);
1004 return E_OUTOFMEMORY
;
1006 memcpy( (*prefix_ret
)->bytes
, prefix
.bytes
, prefix
.length
);
1007 if (prefix
.length
&& add_xml_string( *prefix_ret
) != S_OK
) WARN( "prefix not added to dictionary\n" );
1011 static int codepoint_to_utf8( int cp
, unsigned char *dst
)
1021 dst
[1] = 0x80 | (cp
& 0x3f);
1026 if ((cp
>= 0xd800 && cp
<= 0xdfff) || cp
== 0xfffe || cp
== 0xffff) return -1;
1029 dst
[2] = 0x80 | (cp
& 0x3f);
1031 dst
[1] = 0x80 | (cp
& 0x3f);
1036 if (cp
>= 0x110000) return -1;
1037 dst
[3] = 0x80 | (cp
& 0x3f);
1039 dst
[2] = 0x80 | (cp
& 0x3f);
1041 dst
[1] = 0x80 | (cp
& 0x3f);
1047 static HRESULT
decode_text( const unsigned char *str
, ULONG len
, unsigned char *ret
, ULONG
*ret_len
)
1049 const unsigned char *p
= str
;
1050 unsigned char *q
= ret
;
1058 if (!len
) return WS_E_INVALID_FORMAT
;
1060 if (len
>= 3 && !memcmp( p
, "lt;", 3 ))
1066 else if (len
>= 3 && !memcmp( p
, "gt;", 3 ))
1072 else if (len
>= 5 && !memcmp( p
, "quot;", 5 ))
1078 else if (len
>= 4 && !memcmp( p
, "amp;", 4 ))
1084 else if (len
>= 5 && !memcmp( p
, "apos;", 5 ))
1092 ULONG start
, nb_digits
, i
;
1093 int len_utf8
, cp
= 0;
1096 if (!len
) return WS_E_INVALID_FORMAT
;
1102 while (len
&& isxdigit( *p
)) { p
++; len
--; };
1103 if (!len
) return WS_E_INVALID_FORMAT
;
1105 p
-= nb_digits
= start
- len
;
1106 if (!nb_digits
|| nb_digits
> 6 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1107 for (i
= 0; i
< nb_digits
; i
++)
1110 if (*p
>= '0' && *p
<= '9') cp
+= *p
- '0';
1111 else if (*p
>= 'a' && *p
<= 'f') cp
+= *p
- 'a' + 10;
1112 else cp
+= *p
- 'A' + 10;
1116 else if (isdigit( *p
))
1118 while (len
&& *p
== '0') { p
++; len
--; };
1119 if (!len
) return WS_E_INVALID_FORMAT
;
1122 while (len
&& isdigit( *p
)) { p
++; len
--; };
1123 if (!len
) return WS_E_INVALID_FORMAT
;
1125 p
-= nb_digits
= start
- len
;
1126 if (!nb_digits
|| nb_digits
> 7 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1127 for (i
= 0; i
< nb_digits
; i
++)
1134 else return WS_E_INVALID_FORMAT
;
1136 if ((len_utf8
= codepoint_to_utf8( cp
, q
)) < 0) return WS_E_INVALID_FORMAT
;
1137 *ret_len
+= len_utf8
;
1141 else return WS_E_INVALID_FORMAT
;
1153 static HRESULT
read_attribute_value_text( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1155 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1156 unsigned int len
, ch
, skip
, quote
;
1157 const unsigned char *start
;
1158 HRESULT hr
= E_OUTOFMEMORY
;
1160 read_skip_whitespace( reader
);
1161 if (read_cmp( reader
, "=", 1 )) return WS_E_INVALID_FORMAT
;
1162 read_skip( reader
, 1 );
1164 read_skip_whitespace( reader
);
1165 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) return WS_E_INVALID_FORMAT
;
1166 quote
= read_utf8_char( reader
, &skip
);
1167 read_skip( reader
, 1 );
1170 start
= read_current_ptr( reader
);
1173 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1174 if (ch
== quote
) break;
1175 read_skip( reader
, skip
);
1178 read_skip( reader
, 1 );
1182 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1183 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1184 if (!(utf8
= alloc_utf8_text( NULL
, 0 )))
1192 if (!(utf8
= alloc_utf8_text( NULL
, len
))) goto error
;
1193 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
) goto error
;
1196 attr
->value
= &utf8
->text
;
1197 attr
->singleQuote
= (quote
== '\'');
1205 static inline BOOL
is_text_type( unsigned char type
)
1207 return (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
);
1210 static HRESULT
read_int31( struct reader
*reader
, ULONG
*len
)
1215 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1217 if (!(byte
& 0x80)) return S_OK
;
1219 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1220 *len
+= (byte
& 0x7f) << 7;
1221 if (!(byte
& 0x80)) return S_OK
;
1223 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1224 *len
+= (byte
& 0x7f) << 14;
1225 if (!(byte
& 0x80)) return S_OK
;
1227 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1228 *len
+= (byte
& 0x7f) << 21;
1229 if (!(byte
& 0x80)) return S_OK
;
1231 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1232 *len
+= (byte
& 0x07) << 28;
1236 static HRESULT
read_string( struct reader
*reader
, WS_XML_STRING
**str
)
1240 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
1241 if (!(*str
= alloc_xml_string( NULL
, len
))) return E_OUTOFMEMORY
;
1242 if ((hr
= read_bytes( reader
, (*str
)->bytes
, len
)) == S_OK
)
1244 if (add_xml_string( *str
) != S_OK
) WARN( "string not added to dictionary\n" );
1247 free_xml_string( *str
);
1251 static HRESULT
read_dict_string( struct reader
*reader
, WS_XML_STRING
**str
)
1253 const WS_XML_DICTIONARY
*dict
;
1257 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1258 dict
= (id
& 1) ? reader
->dict
: reader
->dict_static
;
1259 if (!dict
|| (id
>>= 1) >= dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1260 if (!(*str
= alloc_xml_string( NULL
, 0 ))) return E_OUTOFMEMORY
;
1261 *(*str
) = dict
->strings
[id
];
1265 static HRESULT
read_datetime( struct reader
*reader
, WS_DATETIME
*ret
)
1270 if ((hr
= read_bytes( reader
, (unsigned char *)&val
, sizeof(val
) )) != S_OK
) return hr
;
1272 if ((val
& 0x03) == 1) ret
->format
= WS_DATETIME_FORMAT_UTC
;
1273 else if ((val
& 0x03) == 2) ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
1274 else ret
->format
= WS_DATETIME_FORMAT_NONE
;
1276 if ((ret
->ticks
= val
>> 2) > TICKS_MAX
) return WS_E_INVALID_FORMAT
;
1280 static HRESULT
read_encode_base64( struct reader
*reader
, ULONG len
, unsigned char *buf
, ULONG
*ret_len
)
1282 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1289 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1290 buf
[i
++] = base64
[(byte
& 0xfc) >> 2];
1291 x
= (byte
& 3) << 4;
1294 buf
[i
++] = base64
[x
];
1299 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1300 buf
[i
++] = base64
[x
| ((byte
& 0xf0) >> 4)];
1301 x
= (byte
& 0x0f) << 2;
1304 buf
[i
++] = base64
[x
];
1308 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1309 buf
[i
++] = base64
[x
| ((byte
& 0xc0) >> 6)];
1310 buf
[i
++] = base64
[byte
& 0x3f];
1317 static HRESULT
read_attribute_value_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1319 static const unsigned char zero
[] = {'0'}, one
[] = {'1'};
1320 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1321 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1322 unsigned char type
, buf
[46];
1332 WS_DATETIME datetime
;
1337 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1338 if (!is_text_type( type
)) return WS_E_INVALID_FORMAT
;
1342 case RECORD_ZERO_TEXT
:
1343 if (!(utf8
= alloc_utf8_text( zero
, sizeof(zero
) ))) return E_OUTOFMEMORY
;
1346 case RECORD_ONE_TEXT
:
1347 if (!(utf8
= alloc_utf8_text( one
, sizeof(one
) ))) return E_OUTOFMEMORY
;
1350 case RECORD_FALSE_TEXT
:
1351 if (!(utf8
= alloc_utf8_text( false, sizeof(false) ))) return E_OUTOFMEMORY
;
1354 case RECORD_TRUE_TEXT
:
1355 if (!(utf8
= alloc_utf8_text( true, sizeof(true) ))) return E_OUTOFMEMORY
;
1358 case RECORD_INT8_TEXT
:
1359 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
1360 len
= format_int8( &val_int8
, buf
);
1361 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1364 case RECORD_INT16_TEXT
:
1365 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
1366 len
= format_int16( &val_int16
, buf
);
1367 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1370 case RECORD_INT32_TEXT
:
1371 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1372 len
= format_int32( &val_int32
, buf
);
1373 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1376 case RECORD_INT64_TEXT
:
1377 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
1378 len
= format_int64( &val_int64
, buf
);
1379 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1382 case RECORD_DOUBLE_TEXT
:
1383 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
1384 len
= format_double( &val_double
, buf
);
1385 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1388 case RECORD_DATETIME_TEXT
:
1389 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
1390 len
= format_datetime( &datetime
, buf
);
1391 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1394 case RECORD_CHARS8_TEXT
:
1395 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1399 case RECORD_CHARS16_TEXT
:
1400 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
1404 case RECORD_CHARS32_TEXT
:
1405 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1406 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1410 case RECORD_BYTES8_TEXT
:
1411 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1412 if (!(utf8
= alloc_utf8_text( NULL
, ((4 * val_uint8
/ 3) + 3) & ~3 ))) return E_OUTOFMEMORY
;
1413 if ((hr
= read_encode_base64( reader
, val_uint8
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1420 case RECORD_BYTES16_TEXT
:
1421 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint16
)) != S_OK
) return hr
;
1422 if (!(utf8
= alloc_utf8_text( NULL
, ((4 * val_uint16
/ 3) + 3) & ~3 ))) return E_OUTOFMEMORY
;
1423 if ((hr
= read_encode_base64( reader
, val_uint16
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1430 case RECORD_BYTES32_TEXT
:
1431 if ((hr
= read_byte( reader
, (unsigned char *)&val_int32
)) != S_OK
) return hr
;
1432 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1433 if (!(utf8
= alloc_utf8_text( NULL
, ((4 * val_int32
/ 3) + 3) & ~3 ))) return E_OUTOFMEMORY
;
1434 if ((hr
= read_encode_base64( reader
, val_int32
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1441 case RECORD_EMPTY_TEXT
:
1445 case RECORD_DICTIONARY_TEXT
:
1446 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1447 if (!reader
->dict
|| (id
>>= 1) >= reader
->dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1448 if (!(utf8
= alloc_utf8_text( reader
->dict
->strings
[id
].bytes
, reader
->dict
->strings
[id
].length
)))
1449 return E_OUTOFMEMORY
;
1452 case RECORD_UNIQUEID_TEXT
:
1453 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
1454 len
= format_urn( &uuid
, buf
);
1455 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1458 case RECORD_UUID_TEXT
:
1459 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
1460 len
= format_guid( &uuid
, buf
);
1461 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1464 case RECORD_UINT64_TEXT
:
1465 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
1466 len
= format_uint64( &val_uint64
, buf
);
1467 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1470 case RECORD_BOOL_TEXT
:
1471 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
1472 len
= format_bool( &val_bool
, buf
);
1473 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1477 ERR( "unhandled record type %02x\n", type
);
1478 return WS_E_NOT_SUPPORTED
;
1483 if (!(utf8
= alloc_utf8_text( NULL
, len
))) return E_OUTOFMEMORY
;
1484 if (!len
) utf8
->value
.bytes
= (BYTE
*)(utf8
+ 1); /* quirk */
1485 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
1492 attr
->value
= &utf8
->text
;
1496 static HRESULT
read_attribute_text( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1498 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1499 WS_XML_ATTRIBUTE
*attr
;
1500 unsigned int len
= 0, ch
, skip
;
1501 const unsigned char *start
;
1502 WS_XML_STRING
*prefix
, *localname
;
1503 HRESULT hr
= WS_E_INVALID_FORMAT
;
1505 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1507 start
= read_current_ptr( reader
);
1510 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1511 if (!read_isnamechar( ch
)) break;
1512 read_skip( reader
, skip
);
1515 if (!len
) goto error
;
1517 if ((hr
= parse_qname( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1518 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1520 free_xml_string( prefix
);
1522 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1524 free_xml_string( localname
);
1528 attr
->localName
= localname
;
1530 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1533 attr
->prefix
= prefix
;
1534 attr
->localName
= localname
;
1538 attr
->prefix
= prefix
;
1539 attr
->localName
= localname
;
1542 if ((hr
= read_attribute_value_text( reader
, attr
)) != S_OK
) goto error
;
1548 free_attribute( attr
);
1552 static inline BOOL
is_attribute_type( unsigned char type
)
1554 return (type
>= RECORD_SHORT_ATTRIBUTE
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
);
1557 static HRESULT
read_attribute_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1559 WS_XML_ATTRIBUTE
*attr
;
1560 unsigned char type
= 0;
1563 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1564 if (!is_attribute_type( type
)) return WS_E_INVALID_FORMAT
;
1565 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1567 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1569 unsigned char ch
= type
- RECORD_PREFIX_ATTRIBUTE_A
+ 'a';
1570 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1575 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1576 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1578 else if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1580 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ 'a';
1581 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1586 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1587 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1593 case RECORD_SHORT_ATTRIBUTE
:
1594 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1599 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1600 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1603 case RECORD_ATTRIBUTE
:
1604 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1605 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1606 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1609 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1610 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1615 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1616 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1619 case RECORD_DICTIONARY_ATTRIBUTE
:
1620 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1621 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1622 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1625 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1626 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1631 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1632 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1636 case RECORD_XMLNS_ATTRIBUTE
:
1637 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1638 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1639 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1643 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1644 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1649 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1650 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1654 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1655 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1656 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1657 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1662 ERR( "unhandled record type %02x\n", type
);
1663 return WS_E_NOT_SUPPORTED
;
1671 free_attribute( attr
);
1675 static inline struct node
*find_parent( struct reader
*reader
)
1677 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1679 if (is_valid_parent( reader
->current
->parent
->parent
)) return reader
->current
->parent
->parent
;
1682 if (is_valid_parent( reader
->current
)) return reader
->current
;
1683 if (is_valid_parent( reader
->current
->parent
)) return reader
->current
->parent
;
1687 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1689 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1690 const WS_XML_STRING
*ns
;
1693 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1694 if (!(elem
->ns
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
1696 for (i
= 0; i
< elem
->attributeCount
; i
++)
1698 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1699 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1700 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1701 if (!(attr
->ns
= alloc_xml_string( NULL
, ns
->length
))) return E_OUTOFMEMORY
;
1702 if (attr
->ns
->length
) memcpy( attr
->ns
->bytes
, ns
->bytes
, ns
->length
);
1707 static WS_XML_ELEMENT_NODE
*alloc_element_pair(void)
1709 struct node
*node
, *end
;
1710 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
1711 if (!(end
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
)))
1716 list_add_tail( &node
->children
, &end
->entry
);
1721 static HRESULT
read_attributes_text( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1723 WS_XML_ATTRIBUTE
*attr
;
1726 reader
->current_attr
= 0;
1729 read_skip_whitespace( reader
);
1730 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1731 if ((hr
= read_attribute_text( reader
, &attr
)) != S_OK
) return hr
;
1732 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1734 free_attribute( attr
);
1737 reader
->current_attr
++;
1742 static HRESULT
read_element_text( struct reader
*reader
)
1744 unsigned int len
= 0, ch
, skip
;
1745 const unsigned char *start
;
1746 struct node
*node
= NULL
, *parent
;
1747 WS_XML_ELEMENT_NODE
*elem
;
1748 HRESULT hr
= WS_E_INVALID_FORMAT
;
1750 if (read_end_of_data( reader
))
1752 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1753 reader
->last
= reader
->current
;
1754 reader
->state
= READER_STATE_EOF
;
1758 if (read_cmp( reader
, "<", 1 )) return WS_E_INVALID_FORMAT
;
1759 read_skip( reader
, 1 );
1760 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1762 read_rewind( reader
, 1 );
1763 return WS_E_INVALID_FORMAT
;
1766 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1767 node
= (struct node
*)elem
;
1769 start
= read_current_ptr( reader
);
1772 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1773 if (!read_isnamechar( ch
)) break;
1774 read_skip( reader
, skip
);
1777 if (!len
) goto error
;
1779 if (!(parent
= find_parent( reader
))) goto error
;
1780 if ((hr
= parse_qname( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1781 if ((hr
= read_attributes_text( reader
, elem
)) != S_OK
) goto error
;
1782 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1784 read_insert_node( reader
, parent
, node
);
1785 reader
->state
= READER_STATE_STARTELEMENT
;
1789 destroy_nodes( node
);
1793 static inline BOOL
is_element_type( unsigned char type
)
1795 return (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
);
1798 static HRESULT
read_attributes_bin( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1800 WS_XML_ATTRIBUTE
*attr
;
1804 reader
->current_attr
= 0;
1807 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
1808 if (!is_attribute_type( type
)) break;
1809 if ((hr
= read_attribute_bin( reader
, &attr
)) != S_OK
) return hr
;
1810 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1812 free_attribute( attr
);
1815 reader
->current_attr
++;
1820 static HRESULT
read_element_bin( struct reader
*reader
)
1822 struct node
*node
= NULL
, *parent
;
1823 WS_XML_ELEMENT_NODE
*elem
;
1827 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1828 if (!is_element_type( type
)) return WS_E_INVALID_FORMAT
;
1830 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1831 node
= (struct node
*)elem
;
1833 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1835 unsigned char ch
= type
- RECORD_PREFIX_ELEMENT_A
+ 'a';
1836 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1841 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1843 else if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1845 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ 'a';
1846 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1851 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1857 case RECORD_SHORT_ELEMENT
:
1858 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1863 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1866 case RECORD_ELEMENT
:
1867 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1868 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1871 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1872 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1877 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1880 case RECORD_DICTIONARY_ELEMENT
:
1881 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1882 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1886 ERR( "unhandled record type %02x\n", type
);
1887 return WS_E_NOT_SUPPORTED
;
1891 if (!(parent
= find_parent( reader
)))
1893 hr
= WS_E_INVALID_FORMAT
;
1897 if ((hr
= read_attributes_bin( reader
, elem
)) != S_OK
) goto error
;
1898 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1900 read_insert_node( reader
, parent
, node
);
1901 reader
->state
= READER_STATE_STARTELEMENT
;
1905 destroy_nodes( node
);
1909 static HRESULT
read_text_text( struct reader
*reader
)
1911 unsigned int len
= 0, ch
, skip
;
1912 const unsigned char *start
;
1913 struct node
*node
, *parent
;
1914 WS_XML_TEXT_NODE
*text
;
1915 WS_XML_UTF8_TEXT
*utf8
;
1918 start
= read_current_ptr( reader
);
1921 if (read_end_of_data( reader
)) break;
1922 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1923 if (ch
== '<') break;
1924 read_skip( reader
, skip
);
1928 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1930 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1931 text
= (WS_XML_TEXT_NODE
*)node
;
1932 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
1935 return E_OUTOFMEMORY
;
1937 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1943 text
->text
= &utf8
->text
;
1945 read_insert_node( reader
, parent
, node
);
1946 reader
->state
= READER_STATE_TEXT
;
1947 reader
->text_conv_offset
= 0;
1951 static struct node
*alloc_text_node( const unsigned char *data
, ULONG len
, WS_XML_UTF8_TEXT
**ret
)
1954 WS_XML_UTF8_TEXT
*utf8
;
1955 WS_XML_TEXT_NODE
*text
;
1957 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
1958 if (!(utf8
= alloc_utf8_text( data
, len
)))
1963 text
= (WS_XML_TEXT_NODE
*)node
;
1964 text
->text
= &utf8
->text
;
1965 if (ret
) *ret
= utf8
;
1969 static HRESULT
read_text_bin( struct reader
*reader
)
1971 static const unsigned char zero
[] = {'0'}, one
[] = {'1'};
1972 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1973 unsigned char type
, buf
[46];
1974 struct node
*node
= NULL
, *parent
;
1975 WS_XML_UTF8_TEXT
*utf8
;
1985 WS_DATETIME datetime
;
1990 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1991 if (!is_text_type( type
) || !(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1995 case RECORD_ZERO_TEXT
:
1996 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
1997 if (!(node
= alloc_text_node( zero
, sizeof(zero
), NULL
))) return E_OUTOFMEMORY
;
2000 case RECORD_ONE_TEXT
:
2001 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2002 if (!(node
= alloc_text_node( one
, sizeof(one
), NULL
))) return E_OUTOFMEMORY
;
2005 case RECORD_FALSE_TEXT
:
2006 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2007 if (!(node
= alloc_text_node( false, sizeof(false), NULL
))) return E_OUTOFMEMORY
;
2010 case RECORD_TRUE_TEXT
:
2011 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2012 if (!(node
= alloc_text_node( true, sizeof(true), NULL
))) return E_OUTOFMEMORY
;
2015 case RECORD_INT8_TEXT
:
2016 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2017 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
2018 len
= format_int8( &val_int8
, buf
);
2019 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2022 case RECORD_INT16_TEXT
:
2023 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2024 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
2025 len
= format_int16( &val_int16
, buf
);
2026 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2029 case RECORD_INT32_TEXT
:
2030 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2031 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2032 len
= format_int32( &val_int32
, buf
);
2033 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2036 case RECORD_INT64_TEXT
:
2037 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2038 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
2039 len
= format_int64( &val_int64
, buf
);
2040 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2043 case RECORD_DOUBLE_TEXT
:
2044 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2045 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
2046 len
= format_double( &val_double
, buf
);
2047 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2050 case RECORD_DATETIME_TEXT
:
2051 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2052 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
2053 len
= format_datetime( &datetime
, buf
);
2054 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2057 case RECORD_CHARS8_TEXT
:
2058 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2059 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
2063 case RECORD_CHARS16_TEXT
:
2064 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2065 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
2069 case RECORD_CHARS32_TEXT
:
2070 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT
:
2071 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2072 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
2076 case RECORD_BYTES8_TEXT
:
2077 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT
:
2078 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
2079 if (!(node
= alloc_text_node( NULL
, ((4 * val_uint8
/ 3) + 3) & ~3, &utf8
))) return E_OUTOFMEMORY
;
2080 if ((hr
= read_encode_base64( reader
, val_uint8
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
2087 case RECORD_BYTES16_TEXT
:
2088 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT
:
2089 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint16
)) != S_OK
) return hr
;
2090 if (!(node
= alloc_text_node( NULL
, ((4 * val_uint16
/ 3) + 3) & ~3, &utf8
))) return E_OUTOFMEMORY
;
2091 if ((hr
= read_encode_base64( reader
, val_uint16
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
2098 case RECORD_BYTES32_TEXT
:
2099 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT
:
2100 if ((hr
= read_byte( reader
, (unsigned char *)&val_int32
)) != S_OK
) return hr
;
2101 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
2102 if (!(node
= alloc_text_node( NULL
, ((4 * val_int32
/ 3) + 3) & ~3, &utf8
))) return E_OUTOFMEMORY
;
2103 if ((hr
= read_encode_base64( reader
, val_int32
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
2110 case RECORD_EMPTY_TEXT
:
2111 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT
:
2115 case RECORD_DICTIONARY_TEXT
:
2116 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2117 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
2118 if (!reader
->dict
|| (id
>>= 1) >= reader
->dict
->stringCount
) return WS_E_INVALID_FORMAT
;
2119 if (!(node
= alloc_text_node( reader
->dict
->strings
[id
].bytes
, reader
->dict
->strings
[id
].length
, NULL
)))
2120 return E_OUTOFMEMORY
;
2123 case RECORD_UNIQUEID_TEXT
:
2124 case RECORD_UNIQUEID_TEXT_WITH_ENDELEMENT
:
2125 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2126 len
= format_urn( &uuid
, buf
);
2127 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2130 case RECORD_UUID_TEXT
:
2131 case RECORD_UUID_TEXT_WITH_ENDELEMENT
:
2132 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2133 len
= format_guid( &uuid
, buf
);
2134 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2137 case RECORD_UINT64_TEXT
:
2138 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2139 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
2140 len
= format_uint64( &val_uint64
, buf
);
2141 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2144 case RECORD_BOOL_TEXT
:
2145 case RECORD_BOOL_TEXT_WITH_ENDELEMENT
:
2146 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
2147 len
= format_bool( &val_bool
, buf
);
2148 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2152 ERR( "unhandled record type %02x\n", type
);
2153 return WS_E_NOT_SUPPORTED
;
2158 if (!(node
= alloc_text_node( NULL
, len
, &utf8
))) return E_OUTOFMEMORY
;
2159 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
2166 read_insert_node( reader
, parent
, node
);
2167 reader
->state
= READER_STATE_TEXT
;
2168 reader
->text_conv_offset
= 0;
2172 static HRESULT
read_node_text( struct reader
* );
2174 static HRESULT
read_startelement_text( struct reader
*reader
)
2176 read_skip_whitespace( reader
);
2177 if (!read_cmp( reader
, "/>", 2 ))
2179 read_skip( reader
, 2 );
2180 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->children
), struct node
, entry
);
2181 reader
->last
= reader
->current
;
2182 reader
->state
= READER_STATE_ENDELEMENT
;
2185 else if (!read_cmp( reader
, ">", 1 ))
2187 read_skip( reader
, 1 );
2188 return read_node_text( reader
);
2190 return WS_E_INVALID_FORMAT
;
2193 static HRESULT
read_node_bin( struct reader
* );
2195 static HRESULT
read_startelement_bin( struct reader
*reader
)
2197 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
2198 return read_node_bin( reader
);
2201 static HRESULT
read_startelement( struct reader
*reader
)
2203 switch (reader
->input_enc
)
2205 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_startelement_text( reader
);
2206 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_startelement_bin( reader
);
2208 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2209 return WS_E_NOT_SUPPORTED
;
2213 static HRESULT
read_to_startelement_text( struct reader
*reader
, BOOL
*found
)
2217 switch (reader
->state
)
2219 case READER_STATE_INITIAL
:
2220 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
2223 case READER_STATE_STARTELEMENT
:
2224 if (found
) *found
= TRUE
;
2231 read_skip_whitespace( reader
);
2232 if ((hr
= read_element_text( reader
)) == S_OK
&& found
)
2234 if (reader
->state
== READER_STATE_STARTELEMENT
)
2243 static HRESULT
read_to_startelement_bin( struct reader
*reader
, BOOL
*found
)
2247 if (reader
->state
== READER_STATE_STARTELEMENT
)
2249 if (found
) *found
= TRUE
;
2253 if ((hr
= read_element_bin( reader
)) == S_OK
&& found
)
2255 if (reader
->state
== READER_STATE_STARTELEMENT
)
2264 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
2266 switch (reader
->input_enc
)
2268 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_to_startelement_text( reader
, found
);
2269 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_to_startelement_bin( reader
, found
);
2271 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2272 return WS_E_NOT_SUPPORTED
;
2276 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
2279 if (len1
!= len2
) return 1;
2280 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
2284 static struct node
*find_startelement( struct reader
*reader
, const WS_XML_STRING
*prefix
,
2285 const WS_XML_STRING
*localname
)
2287 struct node
*parent
;
2288 const WS_XML_STRING
*str
;
2290 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
2292 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2294 str
= parent
->hdr
.prefix
;
2295 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
2296 str
= parent
->hdr
.localName
;
2297 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
2304 static HRESULT
read_endelement_text( struct reader
*reader
)
2306 struct node
*parent
;
2307 unsigned int len
= 0, ch
, skip
;
2308 const unsigned char *start
;
2309 WS_XML_STRING prefix
, localname
;
2312 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
2313 read_skip( reader
, 2 );
2315 start
= read_current_ptr( reader
);
2318 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2321 read_skip( reader
, 1 );
2324 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
2325 read_skip( reader
, skip
);
2329 if ((hr
= split_qname( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
2330 if (!(parent
= find_startelement( reader
, &prefix
, &localname
))) return WS_E_INVALID_FORMAT
;
2332 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2333 reader
->last
= reader
->current
;
2334 reader
->state
= READER_STATE_ENDELEMENT
;
2338 static HRESULT
read_endelement_bin( struct reader
*reader
)
2340 struct node
*parent
;
2344 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2345 if (type
!= RECORD_ENDELEMENT
) return WS_E_INVALID_FORMAT
;
2347 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2349 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2350 reader
->last
= reader
->current
;
2351 reader
->state
= READER_STATE_ENDELEMENT
;
2355 static HRESULT
read_endelement( struct reader
*reader
)
2357 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
2359 if (read_end_of_data( reader
))
2361 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2362 reader
->last
= reader
->current
;
2363 reader
->state
= READER_STATE_EOF
;
2367 switch (reader
->input_enc
)
2369 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_endelement_text( reader
);
2370 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_endelement_bin( reader
);
2372 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2373 return WS_E_NOT_SUPPORTED
;
2377 static HRESULT
read_comment_text( struct reader
*reader
)
2379 unsigned int len
= 0, ch
, skip
;
2380 const unsigned char *start
;
2381 struct node
*node
, *parent
;
2382 WS_XML_COMMENT_NODE
*comment
;
2384 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
2385 read_skip( reader
, 4 );
2387 start
= read_current_ptr( reader
);
2390 if (!read_cmp( reader
, "-->", 3 ))
2392 read_skip( reader
, 3 );
2395 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2396 read_skip( reader
, skip
);
2400 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2402 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2403 comment
= (WS_XML_COMMENT_NODE
*)node
;
2404 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2407 return E_OUTOFMEMORY
;
2409 memcpy( comment
->value
.bytes
, start
, len
);
2410 comment
->value
.length
= len
;
2412 read_insert_node( reader
, parent
, node
);
2413 reader
->state
= READER_STATE_COMMENT
;
2417 static HRESULT
read_comment_bin( struct reader
*reader
)
2419 struct node
*node
, *parent
;
2420 WS_XML_COMMENT_NODE
*comment
;
2425 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2426 if (type
!= RECORD_COMMENT
) return WS_E_INVALID_FORMAT
;
2427 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
2429 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2431 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2432 comment
= (WS_XML_COMMENT_NODE
*)node
;
2433 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2436 return E_OUTOFMEMORY
;
2438 if ((hr
= read_bytes( reader
, comment
->value
.bytes
, len
)) != S_OK
)
2441 return E_OUTOFMEMORY
;
2443 comment
->value
.length
= len
;
2445 read_insert_node( reader
, parent
, node
);
2446 reader
->state
= READER_STATE_COMMENT
;
2450 static HRESULT
read_startcdata( struct reader
*reader
)
2452 struct node
*node
, *endnode
, *parent
;
2454 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
2455 read_skip( reader
, 9 );
2457 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2459 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2460 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
)))
2463 return E_OUTOFMEMORY
;
2465 list_add_tail( &node
->children
, &endnode
->entry
);
2466 endnode
->parent
= node
;
2468 read_insert_node( reader
, parent
, node
);
2469 reader
->state
= READER_STATE_STARTCDATA
;
2473 static HRESULT
read_cdata( struct reader
*reader
)
2475 unsigned int len
= 0, ch
, skip
;
2476 const unsigned char *start
;
2478 WS_XML_TEXT_NODE
*text
;
2479 WS_XML_UTF8_TEXT
*utf8
;
2481 start
= read_current_ptr( reader
);
2484 if (!read_cmp( reader
, "]]>", 3 )) break;
2485 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2486 read_skip( reader
, skip
);
2490 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2491 text
= (WS_XML_TEXT_NODE
*)node
;
2492 if (!(utf8
= alloc_utf8_text( start
, len
)))
2495 return E_OUTOFMEMORY
;
2497 text
->text
= &utf8
->text
;
2499 read_insert_node( reader
, reader
->current
, node
);
2500 reader
->state
= READER_STATE_CDATA
;
2504 static HRESULT
read_endcdata( struct reader
*reader
)
2506 struct node
*parent
;
2508 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
2509 read_skip( reader
, 3 );
2511 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
) parent
= reader
->current
->parent
;
2512 else parent
= reader
->current
;
2514 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2515 reader
->last
= reader
->current
;
2516 reader
->state
= READER_STATE_ENDCDATA
;
2520 static HRESULT
read_node_text( struct reader
*reader
)
2526 if (read_end_of_data( reader
))
2528 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2529 reader
->last
= reader
->current
;
2530 reader
->state
= READER_STATE_EOF
;
2533 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
2534 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
2535 else if (!read_cmp( reader
, "<?", 2 ))
2537 hr
= read_xmldecl( reader
);
2538 if (FAILED( hr
)) return hr
;
2540 else if (!read_cmp( reader
, "</", 2 )) return read_endelement_text( reader
);
2541 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
2542 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment_text( reader
);
2543 else if (!read_cmp( reader
, "<", 1 )) return read_element_text( reader
);
2544 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement_text( reader
);
2545 else return read_text_text( reader
);
2549 static HRESULT
read_node_bin( struct reader
*reader
)
2554 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
)
2556 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->parent
->children
), struct node
, entry
);
2557 reader
->last
= reader
->current
;
2558 reader
->state
= READER_STATE_ENDELEMENT
;
2561 if (read_end_of_data( reader
))
2563 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2564 reader
->last
= reader
->current
;
2565 reader
->state
= READER_STATE_EOF
;
2569 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
2570 if (type
== RECORD_ENDELEMENT
)
2572 return read_endelement_bin( reader
);
2574 else if (type
== RECORD_COMMENT
)
2576 return read_comment_bin( reader
);
2578 else if (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
2580 return read_element_bin( reader
);
2582 else if (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
)
2584 return read_text_bin( reader
);
2586 FIXME( "unhandled record type %02x\n", type
);
2587 return WS_E_NOT_SUPPORTED
;
2590 static HRESULT
read_node( struct reader
*reader
)
2592 switch (reader
->input_enc
)
2594 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_node_text( reader
);
2595 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_node_bin( reader
);
2597 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2598 return WS_E_NOT_SUPPORTED
;
2602 HRESULT
copy_node( WS_XML_READER
*handle
, struct node
**node
)
2604 struct reader
*reader
= (struct reader
*)handle
;
2605 const struct list
*ptr
;
2606 const struct node
*start
;
2609 EnterCriticalSection( &reader
->cs
);
2611 if (reader
->magic
!= READER_MAGIC
)
2613 LeaveCriticalSection( &reader
->cs
);
2614 return E_INVALIDARG
;
2617 if (reader
->current
!= reader
->root
) ptr
= &reader
->current
->entry
;
2618 else /* copy whole tree */
2620 if (!read_end_of_data( reader
))
2624 if ((hr
= read_node( reader
)) != S_OK
) goto done
;
2625 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) break;
2628 ptr
= list_head( &reader
->root
->children
);
2631 start
= LIST_ENTRY( ptr
, struct node
, entry
);
2632 if (node_type( start
) == WS_XML_NODE_TYPE_EOF
) hr
= WS_E_INVALID_OPERATION
;
2633 else hr
= dup_tree( node
, start
);
2636 LeaveCriticalSection( &reader
->cs
);
2640 /**************************************************************************
2641 * WsReadEndElement [webservices.@]
2643 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2645 struct reader
*reader
= (struct reader
*)handle
;
2648 TRACE( "%p %p\n", handle
, error
);
2649 if (error
) FIXME( "ignoring error parameter\n" );
2651 if (!reader
) return E_INVALIDARG
;
2653 EnterCriticalSection( &reader
->cs
);
2655 if (reader
->magic
!= READER_MAGIC
)
2657 LeaveCriticalSection( &reader
->cs
);
2658 return E_INVALIDARG
;
2661 hr
= read_endelement( reader
);
2663 LeaveCriticalSection( &reader
->cs
);
2667 /**************************************************************************
2668 * WsReadNode [webservices.@]
2670 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2672 struct reader
*reader
= (struct reader
*)handle
;
2675 TRACE( "%p %p\n", handle
, error
);
2676 if (error
) FIXME( "ignoring error parameter\n" );
2678 if (!reader
) return E_INVALIDARG
;
2680 EnterCriticalSection( &reader
->cs
);
2682 if (reader
->magic
!= READER_MAGIC
)
2684 LeaveCriticalSection( &reader
->cs
);
2685 return E_INVALIDARG
;
2688 hr
= read_node( reader
);
2690 LeaveCriticalSection( &reader
->cs
);
2694 static HRESULT
skip_node( struct reader
*reader
)
2696 const struct node
*parent
;
2699 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) return WS_E_INVALID_OPERATION
;
2700 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_ELEMENT
) parent
= reader
->current
;
2705 if ((hr
= read_node( reader
) != S_OK
) || !parent
) break;
2706 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_END_ELEMENT
) continue;
2707 if (reader
->current
->parent
== parent
) return read_node( reader
);
2713 /**************************************************************************
2714 * WsSkipNode [webservices.@]
2716 HRESULT WINAPI
WsSkipNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2718 struct reader
*reader
= (struct reader
*)handle
;
2721 TRACE( "%p %p\n", handle
, error
);
2722 if (error
) FIXME( "ignoring error parameter\n" );
2724 if (!reader
) return E_INVALIDARG
;
2726 EnterCriticalSection( &reader
->cs
);
2728 if (reader
->magic
!= READER_MAGIC
)
2730 LeaveCriticalSection( &reader
->cs
);
2731 return E_INVALIDARG
;
2734 hr
= skip_node( reader
);
2736 LeaveCriticalSection( &reader
->cs
);
2740 /**************************************************************************
2741 * WsReadStartElement [webservices.@]
2743 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2745 struct reader
*reader
= (struct reader
*)handle
;
2748 TRACE( "%p %p\n", handle
, error
);
2749 if (error
) FIXME( "ignoring error parameter\n" );
2751 if (!reader
) return E_INVALIDARG
;
2753 EnterCriticalSection( &reader
->cs
);
2755 if (reader
->magic
!= READER_MAGIC
)
2757 LeaveCriticalSection( &reader
->cs
);
2758 return E_INVALIDARG
;
2761 hr
= read_startelement( reader
);
2763 LeaveCriticalSection( &reader
->cs
);
2767 /**************************************************************************
2768 * WsReadToStartElement [webservices.@]
2770 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2771 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
2773 struct reader
*reader
= (struct reader
*)handle
;
2776 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
2777 if (error
) FIXME( "ignoring error parameter\n" );
2779 if (!reader
) return E_INVALIDARG
;
2780 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
2782 EnterCriticalSection( &reader
->cs
);
2784 if (reader
->magic
!= READER_MAGIC
)
2786 LeaveCriticalSection( &reader
->cs
);
2787 return E_INVALIDARG
;
2790 hr
= read_to_startelement( reader
, found
);
2792 LeaveCriticalSection( &reader
->cs
);
2796 BOOL
move_to_root_element( struct node
*root
, struct node
**current
)
2801 if (!(ptr
= list_head( &root
->children
))) return FALSE
;
2802 node
= LIST_ENTRY( ptr
, struct node
, entry
);
2803 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
2808 while ((ptr
= list_next( &root
->children
, &node
->entry
)))
2810 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2811 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2821 BOOL
move_to_next_element( struct node
**current
)
2824 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2826 if (!parent
) return FALSE
;
2827 while ((ptr
= list_next( &parent
->children
, &node
->entry
)))
2829 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2830 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2840 BOOL
move_to_prev_element( struct node
**current
)
2843 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2845 if (!parent
) return FALSE
;
2846 while ((ptr
= list_prev( &parent
->children
, &node
->entry
)))
2848 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
2849 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
2859 BOOL
move_to_child_element( struct node
**current
)
2862 struct node
*child
, *node
= *current
;
2864 if (!(ptr
= list_head( &node
->children
))) return FALSE
;
2865 child
= LIST_ENTRY( ptr
, struct node
, entry
);
2866 if (node_type( child
) == WS_XML_NODE_TYPE_ELEMENT
)
2871 while ((ptr
= list_next( &node
->children
, &child
->entry
)))
2873 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2874 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2884 BOOL
move_to_end_element( struct node
**current
)
2887 struct node
*node
= *current
;
2889 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
2891 if ((ptr
= list_tail( &node
->children
)))
2893 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
2894 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
2903 BOOL
move_to_parent_element( struct node
**current
)
2905 struct node
*parent
= (*current
)->parent
;
2907 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
2908 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
2916 BOOL
move_to_first_node( struct node
**current
)
2919 struct node
*node
= *current
;
2921 if ((ptr
= list_head( &node
->parent
->children
)))
2923 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2929 BOOL
move_to_next_node( struct node
**current
)
2932 struct node
*node
= *current
;
2934 if ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
2936 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2942 BOOL
move_to_prev_node( struct node
**current
)
2945 struct node
*node
= *current
;
2947 if ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
2949 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2955 BOOL
move_to_bof( struct node
*root
, struct node
**current
)
2961 BOOL
move_to_eof( struct node
*root
, struct node
**current
)
2964 if ((ptr
= list_tail( &root
->children
)))
2966 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2972 BOOL
move_to_child_node( struct node
**current
)
2975 struct node
*node
= *current
;
2977 if ((ptr
= list_head( &node
->children
)))
2979 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2985 BOOL
move_to_parent_node( struct node
**current
)
2987 struct node
*parent
= (*current
)->parent
;
2988 if (!parent
) return FALSE
;
2993 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
2995 BOOL success
= FALSE
;
2998 if (!read_end_of_data( reader
))
3000 struct node
*saved_current
= reader
->current
;
3001 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
3002 if (hr
!= S_OK
) return hr
;
3003 reader
->current
= saved_current
;
3007 case WS_MOVE_TO_ROOT_ELEMENT
:
3008 success
= move_to_root_element( reader
->root
, &reader
->current
);
3011 case WS_MOVE_TO_NEXT_ELEMENT
:
3012 success
= move_to_next_element( &reader
->current
);
3015 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
3016 success
= move_to_prev_element( &reader
->current
);
3019 case WS_MOVE_TO_CHILD_ELEMENT
:
3020 success
= move_to_child_element( &reader
->current
);
3023 case WS_MOVE_TO_END_ELEMENT
:
3024 success
= move_to_end_element( &reader
->current
);
3027 case WS_MOVE_TO_PARENT_ELEMENT
:
3028 success
= move_to_parent_element( &reader
->current
);
3031 case WS_MOVE_TO_FIRST_NODE
:
3032 success
= move_to_first_node( &reader
->current
);
3035 case WS_MOVE_TO_NEXT_NODE
:
3036 success
= move_to_next_node( &reader
->current
);
3039 case WS_MOVE_TO_PREVIOUS_NODE
:
3040 success
= move_to_prev_node( &reader
->current
);
3043 case WS_MOVE_TO_CHILD_NODE
:
3044 success
= move_to_child_node( &reader
->current
);
3047 case WS_MOVE_TO_BOF
:
3048 success
= move_to_bof( reader
->root
, &reader
->current
);
3051 case WS_MOVE_TO_EOF
:
3052 success
= move_to_eof( reader
->root
, &reader
->current
);
3056 FIXME( "unhandled move %u\n", move
);
3065 return success
? S_OK
: WS_E_INVALID_FORMAT
;
3068 /**************************************************************************
3069 * WsMoveReader [webservices.@]
3071 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
3073 struct reader
*reader
= (struct reader
*)handle
;
3076 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
3077 if (error
) FIXME( "ignoring error parameter\n" );
3079 if (!reader
) return E_INVALIDARG
;
3081 EnterCriticalSection( &reader
->cs
);
3083 if (reader
->magic
!= READER_MAGIC
)
3085 LeaveCriticalSection( &reader
->cs
);
3086 return E_INVALIDARG
;
3089 if (!reader
->input_type
)
3091 LeaveCriticalSection( &reader
->cs
);
3092 return WS_E_INVALID_OPERATION
;
3095 hr
= read_move_to( reader
, move
, found
);
3097 LeaveCriticalSection( &reader
->cs
);
3101 /**************************************************************************
3102 * WsReadStartAttribute [webservices.@]
3104 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
3106 struct reader
*reader
= (struct reader
*)handle
;
3107 const WS_XML_ELEMENT_NODE
*elem
;
3109 TRACE( "%p %u %p\n", handle
, index
, error
);
3110 if (error
) FIXME( "ignoring error parameter\n" );
3112 if (!reader
) return E_INVALIDARG
;
3114 EnterCriticalSection( &reader
->cs
);
3116 if (reader
->magic
!= READER_MAGIC
)
3118 LeaveCriticalSection( &reader
->cs
);
3119 return E_INVALIDARG
;
3122 elem
= &reader
->current
->hdr
;
3123 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
3125 LeaveCriticalSection( &reader
->cs
);
3126 return WS_E_INVALID_FORMAT
;
3129 reader
->current_attr
= index
;
3130 reader
->state
= READER_STATE_STARTATTRIBUTE
;
3132 LeaveCriticalSection( &reader
->cs
);
3136 /**************************************************************************
3137 * WsReadEndAttribute [webservices.@]
3139 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
3141 struct reader
*reader
= (struct reader
*)handle
;
3143 TRACE( "%p %p\n", handle
, error
);
3144 if (error
) FIXME( "ignoring error parameter\n" );
3146 if (!reader
) return E_INVALIDARG
;
3148 EnterCriticalSection( &reader
->cs
);
3150 if (reader
->magic
!= READER_MAGIC
)
3152 LeaveCriticalSection( &reader
->cs
);
3153 return E_INVALIDARG
;
3156 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
3158 LeaveCriticalSection( &reader
->cs
);
3159 return WS_E_INVALID_FORMAT
;
3162 reader
->state
= READER_STATE_STARTELEMENT
;
3164 LeaveCriticalSection( &reader
->cs
);
3168 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
3172 switch (text
->textType
)
3174 case WS_XML_TEXT_TYPE_UTF8
:
3176 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
3177 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
3178 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
3179 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
3184 FIXME( "unhandled type %u\n", text
->textType
);
3191 #define MAX_INT8 0x7f
3192 #define MIN_INT8 (-MAX_INT8 - 1)
3193 #define MAX_INT16 0x7fff
3194 #define MIN_INT16 (-MAX_INT16 - 1)
3195 #define MAX_INT32 0x7fffffff
3196 #define MIN_INT32 (-MAX_INT32 - 1)
3197 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
3198 #define MIN_INT64 (-MAX_INT64 - 1)
3199 #define MAX_UINT8 0xff
3200 #define MAX_UINT16 0xffff
3201 #define MAX_UINT32 0xffffffff
3202 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
3204 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
3206 BOOL negative
= FALSE
;
3207 const unsigned char *ptr
= str
;
3210 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3211 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3212 if (!len
) return WS_E_INVALID_FORMAT
;
3220 if (!len
) return WS_E_INVALID_FORMAT
;
3226 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3228 if (negative
) val
= -val
;
3230 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
3231 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
3233 return WS_E_NUMERIC_OVERFLOW
;
3235 *ret
= *ret
* 10 + val
;
3242 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
3244 const unsigned char *ptr
= str
;
3247 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3248 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3249 if (!len
) return WS_E_INVALID_FORMAT
;
3255 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3258 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
3259 *ret
= *ret
* 10 + val
;
3266 BOOL
set_fpword( unsigned short new, unsigned short *old
)
3268 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3269 unsigned short fpword
;
3271 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
3274 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3277 FIXME( "not implemented\n" );
3282 void restore_fpword( unsigned short fpword
)
3284 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3285 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3287 FIXME( "not implemented\n" );
3291 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
3293 static const unsigned __int64 nan
= 0xfff8000000000000;
3294 static const unsigned __int64 inf
= 0x7ff0000000000000;
3295 static const unsigned __int64 inf_min
= 0xfff0000000000000;
3296 HRESULT hr
= WS_E_INVALID_FORMAT
;
3297 const unsigned char *p
= str
, *q
;
3298 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
3299 unsigned __int64 val
= 0, tmp
;
3300 long double exp_val
= 1.0, exp_mul
= 10.0;
3301 unsigned short fpword
;
3303 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3304 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3305 if (!len
) return WS_E_INVALID_FORMAT
;
3307 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
3309 *(unsigned __int64
*)ret
= nan
;
3312 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
3314 *(unsigned __int64
*)ret
= inf
;
3317 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
3319 *(unsigned __int64
*)ret
= inf_min
;
3329 else if (*p
== '+') { p
++; len
--; };
3330 if (!len
) return S_OK
;
3332 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
3335 while (len
&& isdigit( *q
)) { q
++; len
--; }
3336 have_digits
= nb_digits
= q
- p
;
3337 for (i
= 0; i
< nb_digits
; i
++)
3339 tmp
= val
* 10 + p
[i
] - '0';
3340 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
3342 for (; i
< nb_digits
; i
++) exp
++;
3353 while (len
&& isdigit( *q
)) { q
++; len
--; };
3354 have_digits
|= nb_digits
= q
- p
;
3355 for (i
= 0; i
< nb_digits
; i
++)
3357 tmp
= val
* 10 + p
[i
] - '0';
3358 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
3363 if (len
> 1 && tolower(*q
) == 'e')
3365 if (!have_digits
) goto done
;
3372 else if (*p
== '+') { p
++; len
--; };
3375 while (len
&& isdigit( *q
)) { q
++; len
--; };
3377 if (!nb_digits
|| len
) goto done
;
3378 for (i
= 0; i
< nb_digits
; i
++)
3380 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
3381 exp_tmp
= MAX_INT32
;
3383 exp_tmp
*= exp_sign
;
3385 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
3386 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
3387 else exp
+= exp_tmp
;
3390 if (!have_digits
|| len
) goto done
;
3392 if ((neg_exp
= exp
< 0)) exp
= -exp
;
3393 for (; exp
; exp
>>= 1)
3395 if (exp
& 1) exp_val
*= exp_mul
;
3399 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
3403 restore_fpword( fpword
);
3407 static HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
3409 static const unsigned char hex
[] =
3411 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3412 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3413 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3414 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3415 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3416 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3417 0,10,11,12,13,14,15 /* 0x60 */
3419 const unsigned char *p
= str
;
3422 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3423 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3424 if (len
!= 36) return WS_E_INVALID_FORMAT
;
3426 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
3427 return WS_E_INVALID_FORMAT
;
3429 for (i
= 0; i
< 36; i
++)
3431 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
3432 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
3435 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
3436 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
3438 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
3439 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
3441 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
3442 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
3443 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
3444 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
3445 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
3446 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
3447 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
3448 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
3453 static HRESULT
str_to_string( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_STRING
*ret
)
3455 const unsigned char *p
= str
;
3458 len_utf16
= MultiByteToWideChar( CP_UTF8
, 0, (const char *)p
, len
, NULL
, 0 );
3459 if (!(ret
->chars
= ws_alloc( heap
, len_utf16
* sizeof(WCHAR
) ))) return WS_E_QUOTA_EXCEEDED
;
3460 MultiByteToWideChar( CP_UTF8
, 0, (const char *)p
, len
, ret
->chars
, len_utf16
);
3461 ret
->length
= len_utf16
;
3466 static HRESULT
str_to_unique_id( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_UNIQUE_ID
*ret
)
3468 if (len
== 45 && !memcmp( str
, "urn:uuid:", 9 ))
3470 ret
->uri
.length
= 0;
3471 ret
->uri
.chars
= NULL
;
3472 return str_to_guid( str
+ 9, len
- 9, &ret
->guid
);
3475 memset( &ret
->guid
, 0, sizeof(ret
->guid
) );
3476 return str_to_string( str
, len
, heap
, &ret
->uri
);
3479 static inline unsigned char decode_char( unsigned char c
)
3481 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
3482 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
3483 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
3484 if (c
== '+') return 62;
3485 if (c
== '/') return 63;
3489 static ULONG
decode_base64( const unsigned char *base64
, ULONG len
, unsigned char *buf
)
3492 unsigned char c0
, c1
, c2
, c3
;
3493 const unsigned char *p
= base64
;
3497 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3498 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3499 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3500 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3501 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3502 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3503 buf
[i
+ 2] = (c2
<< 6) | c3
;
3510 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3511 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3512 buf
[i
] = (c0
<< 2) | (c1
>> 4);
3515 else if (p
[3] == '=')
3517 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3518 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3519 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3520 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3521 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3526 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3527 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3528 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3529 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3530 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3531 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3532 buf
[i
+ 2] = (c2
<< 6) | c3
;
3538 static HRESULT
str_to_bytes( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_BYTES
*ret
)
3540 const unsigned char *p
= str
;
3542 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3543 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3545 if (len
% 4) return WS_E_INVALID_FORMAT
;
3546 if (!(ret
->bytes
= ws_alloc( heap
, len
* 3 / 4 ))) return WS_E_QUOTA_EXCEEDED
;
3547 ret
->length
= decode_base64( p
, len
, ret
->bytes
);
3551 static HRESULT
str_to_xml_string( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_XML_STRING
*ret
)
3553 const unsigned char *p
= str
;
3555 if (!(ret
->bytes
= ws_alloc( heap
, len
))) return WS_E_QUOTA_EXCEEDED
;
3556 memcpy( ret
->bytes
, p
, len
);
3558 ret
->dictionary
= NULL
;
3563 static HRESULT
copy_xml_string( WS_HEAP
*heap
, const WS_XML_STRING
*src
, WS_XML_STRING
*dst
)
3565 if (!(dst
->bytes
= ws_alloc( heap
, src
->length
))) return WS_E_QUOTA_EXCEEDED
;
3566 memcpy( dst
->bytes
, src
->bytes
, src
->length
);
3567 dst
->length
= src
->length
;
3571 static HRESULT
str_to_qname( struct reader
*reader
, const unsigned char *str
, ULONG len
, WS_HEAP
*heap
,
3572 WS_XML_STRING
*prefix_ret
, WS_XML_STRING
*localname_ret
, WS_XML_STRING
*ns_ret
)
3574 const unsigned char *p
= str
;
3575 WS_XML_STRING prefix
, localname
;
3576 const WS_XML_STRING
*ns
;
3579 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3580 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3582 if ((hr
= split_qname( p
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
3583 if (!(ns
= get_namespace( reader
, &prefix
))) return WS_E_INVALID_FORMAT
;
3585 if (prefix_ret
&& (hr
= copy_xml_string( heap
, &prefix
, prefix_ret
)) != S_OK
) return hr
;
3586 if ((hr
= copy_xml_string( heap
, &localname
, localname_ret
)) != S_OK
)
3588 ws_free( heap
, prefix_ret
->bytes
, prefix_ret
->length
);
3591 if ((hr
= copy_xml_string( heap
, ns
, ns_ret
)) != S_OK
)
3593 ws_free( heap
, prefix_ret
->bytes
, prefix_ret
->length
);
3594 ws_free( heap
, localname_ret
->bytes
, localname_ret
->length
);
3600 static HRESULT
read_qualified_name( struct reader
*reader
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
3601 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
)
3603 const WS_XML_TEXT_NODE
*node
= (const WS_XML_TEXT_NODE
*)reader
->current
;
3604 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)node
->text
;
3605 return str_to_qname( reader
, utf8
->value
.bytes
, utf8
->value
.length
, heap
, prefix
, localname
, ns
);
3608 /**************************************************************************
3609 * WsReadQualifiedName [webservices.@]
3611 HRESULT WINAPI
WsReadQualifiedName( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
3612 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
,
3615 struct reader
*reader
= (struct reader
*)handle
;
3618 TRACE( "%p %p %p %p %p %p\n", handle
, heap
, prefix
, localname
, ns
, error
);
3619 if (error
) FIXME( "ignoring error parameter\n" );
3621 if (!reader
|| !heap
) return E_INVALIDARG
;
3623 EnterCriticalSection( &reader
->cs
);
3625 if (reader
->magic
!= READER_MAGIC
)
3627 LeaveCriticalSection( &reader
->cs
);
3628 return E_INVALIDARG
;
3631 if (!reader
->input_type
)
3633 LeaveCriticalSection( &reader
->cs
);
3634 return WS_E_INVALID_OPERATION
;
3639 LeaveCriticalSection( &reader
->cs
);
3640 return E_INVALIDARG
;
3643 if (reader
->state
!= READER_STATE_TEXT
)
3645 LeaveCriticalSection( &reader
->cs
);
3646 return WS_E_INVALID_FORMAT
;
3649 hr
= read_qualified_name( reader
, heap
, prefix
, localname
, ns
);
3651 LeaveCriticalSection( &reader
->cs
);
3655 static const int month_offsets
[2][12] =
3657 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
3658 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
3661 static inline int valid_day( int year
, int month
, int day
)
3663 return day
> 0 && day
<= month_days
[leap_year( year
)][month
- 1];
3666 static inline int leap_days_before( int year
)
3668 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
3671 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
3673 const unsigned char *p
= bytes
, *q
;
3674 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
3676 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3677 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3680 while (len
&& isdigit( *q
)) { q
++; len
--; };
3681 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3682 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
3683 if (year
< 1) return WS_E_INVALID_FORMAT
;
3686 while (len
&& isdigit( *q
)) { q
++; len
--; };
3687 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3688 month
= (p
[0] - '0') * 10 + p
[1] - '0';
3689 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
3692 while (len
&& isdigit( *q
)) { q
++; len
--; };
3693 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
3694 day
= (p
[0] - '0') * 10 + p
[1] - '0';
3695 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
3698 while (len
&& isdigit( *q
)) { q
++; len
--; };
3699 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3700 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3701 if (hour
> 24) return WS_E_INVALID_FORMAT
;
3704 while (len
&& isdigit( *q
)) { q
++; len
--; };
3705 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3706 min
= (p
[0] - '0') * 10 + p
[1] - '0';
3707 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3710 while (len
&& isdigit( *q
)) { q
++; len
--; };
3711 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
3712 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
3713 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3717 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
3719 while (len
&& isdigit( *q
)) { q
++; len
--; };
3721 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
3722 for (i
= 0; i
< nb_digits
; i
++)
3724 sec_frac
+= (p
[i
] - '0') * mul
;
3730 if (--len
) return WS_E_INVALID_FORMAT
;
3731 tz_hour
= tz_min
= tz_neg
= 0;
3732 ret
->format
= WS_DATETIME_FORMAT_UTC
;
3734 else if (*q
== '+' || *q
== '-')
3736 tz_neg
= (*q
== '-') ? 1 : 0;
3739 while (len
&& isdigit( *q
)) { q
++; len
--; };
3740 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3741 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3742 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
3745 while (len
&& isdigit( *q
)) { q
++; len
--; };
3746 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
3747 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
3748 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
3750 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
3752 else return WS_E_INVALID_FORMAT
;
3754 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
3755 ret
->ticks
+= month_offsets
[leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
3756 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
3757 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
3758 ret
->ticks
+= min
* TICKS_PER_MIN
;
3759 ret
->ticks
+= sec
* TICKS_PER_SEC
;
3760 ret
->ticks
+= sec_frac
;
3764 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
3765 return WS_E_INVALID_FORMAT
;
3766 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
3767 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
3771 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
3772 return WS_E_INVALID_FORMAT
;
3773 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
3774 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
3780 /**************************************************************************
3781 * WsDateTimeToFileTime [webservices.@]
3783 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
3785 unsigned __int64 ticks
;
3787 TRACE( "%p %p %p\n", dt
, ft
, error
);
3788 if (error
) FIXME( "ignoring error parameter\n" );
3790 if (!dt
|| !ft
) return E_INVALIDARG
;
3792 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
3793 ticks
= dt
->ticks
- TICKS_1601_01_01
;
3794 ft
->dwHighDateTime
= ticks
>> 32;
3795 ft
->dwLowDateTime
= (DWORD
)ticks
;
3799 /**************************************************************************
3800 * WsFileTimeToDateTime [webservices.@]
3802 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
3804 unsigned __int64 ticks
;
3806 TRACE( "%p %p %p\n", ft
, dt
, error
);
3807 if (error
) FIXME( "ignoring error parameter\n" );
3809 if (!dt
|| !ft
) return E_INVALIDARG
;
3811 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
3812 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
3813 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
3814 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
3815 dt
->format
= WS_DATETIME_FORMAT_UTC
;
3819 static HRESULT
read_get_node_text( struct reader
*reader
, WS_XML_UTF8_TEXT
**ret
)
3821 WS_XML_TEXT_NODE
*text
;
3823 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
3824 return WS_E_INVALID_FORMAT
;
3826 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
3827 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3829 FIXME( "text type %u not supported\n", text
->text
->textType
);
3832 *ret
= (WS_XML_UTF8_TEXT
*)text
->text
;
3836 static HRESULT
read_get_attribute_text( struct reader
*reader
, ULONG index
, WS_XML_UTF8_TEXT
**ret
)
3838 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3839 WS_XML_ATTRIBUTE
*attr
;
3841 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
3842 return WS_E_INVALID_FORMAT
;
3844 attr
= elem
->attributes
[index
];
3845 if (attr
->value
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3847 FIXME( "text type %u not supported\n", attr
->value
->textType
);
3850 *ret
= (WS_XML_UTF8_TEXT
*)attr
->value
;
3854 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
3855 const WS_XML_STRING
*ns
, ULONG
*index
)
3858 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3862 *index
= reader
->current_attr
;
3865 for (i
= 0; i
< elem
->attributeCount
; i
++)
3867 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
3868 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
3870 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
3871 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
3880 /**************************************************************************
3881 * WsFindAttribute [webservices.@]
3883 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
3884 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
3887 struct reader
*reader
= (struct reader
*)handle
;
3890 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3891 required
, index
, error
);
3892 if (error
) FIXME( "ignoring error parameter\n" );
3894 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
3896 EnterCriticalSection( &reader
->cs
);
3898 if (reader
->magic
!= READER_MAGIC
)
3900 LeaveCriticalSection( &reader
->cs
);
3901 return E_INVALIDARG
;
3904 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
3906 LeaveCriticalSection( &reader
->cs
);
3907 return WS_E_INVALID_OPERATION
;
3910 if (!find_attribute( reader
, localname
, ns
, index
))
3912 if (required
) hr
= WS_E_INVALID_FORMAT
;
3920 LeaveCriticalSection( &reader
->cs
);
3924 static HRESULT
read_get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3925 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3926 WS_XML_UTF8_TEXT
**ret
, BOOL
*found
)
3930 case WS_ATTRIBUTE_TYPE_MAPPING
:
3933 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
3934 return read_get_attribute_text( reader
, index
, ret
);
3936 case WS_ELEMENT_TYPE_MAPPING
:
3937 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3938 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3944 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3946 if (WsXmlStringEquals( localname
, elem
->localName
, NULL
) != S_OK
||
3947 WsXmlStringEquals( ns
, elem
->ns
, NULL
) != S_OK
)
3952 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
3954 return read_get_node_text( reader
, ret
);
3957 FIXME( "mapping %u not supported\n", mapping
);
3962 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3963 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3964 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3965 WS_HEAP
*heap
, void *ret
, ULONG size
)
3967 WS_XML_UTF8_TEXT
*utf8
;
3969 BOOL found
, val
= FALSE
;
3973 FIXME( "description not supported\n" );
3976 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3979 ULONG len
= utf8
->value
.length
;
3980 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
3981 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
3982 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
3983 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
3984 else return WS_E_INVALID_FORMAT
;
3989 case WS_READ_REQUIRED_VALUE
:
3990 if (!found
) return WS_E_INVALID_FORMAT
;
3993 case WS_READ_NILLABLE_VALUE
:
3994 if (size
!= sizeof(val
)) return E_INVALIDARG
;
3998 case WS_READ_REQUIRED_POINTER
:
3999 if (!found
) return WS_E_INVALID_FORMAT
;
4002 case WS_READ_OPTIONAL_POINTER
:
4003 case WS_READ_NILLABLE_POINTER
:
4005 BOOL
*heap_val
= NULL
;
4006 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4009 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4012 *(BOOL
**)ret
= heap_val
;
4016 FIXME( "read option %u not supported\n", option
);
4023 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4024 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4025 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4026 WS_HEAP
*heap
, void *ret
, ULONG size
)
4028 WS_XML_UTF8_TEXT
*utf8
;
4035 FIXME( "description not supported\n" );
4038 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4039 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
4044 case WS_READ_REQUIRED_VALUE
:
4045 if (!found
) return WS_E_INVALID_FORMAT
;
4048 case WS_READ_NILLABLE_VALUE
:
4049 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
4053 case WS_READ_REQUIRED_POINTER
:
4054 if (!found
) return WS_E_INVALID_FORMAT
;
4057 case WS_READ_OPTIONAL_POINTER
:
4058 case WS_READ_NILLABLE_POINTER
:
4060 INT8
*heap_val
= NULL
;
4061 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4064 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4067 *(INT8
**)ret
= heap_val
;
4071 FIXME( "read option %u not supported\n", option
);
4078 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4079 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4080 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4081 WS_HEAP
*heap
, void *ret
, ULONG size
)
4083 WS_XML_UTF8_TEXT
*utf8
;
4090 FIXME( "description not supported\n" );
4093 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4094 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
4099 case WS_READ_REQUIRED_VALUE
:
4100 if (!found
) return WS_E_INVALID_FORMAT
;
4103 case WS_READ_NILLABLE_VALUE
:
4104 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
4105 *(INT16
*)ret
= val
;
4108 case WS_READ_REQUIRED_POINTER
:
4109 if (!found
) return WS_E_INVALID_FORMAT
;
4112 case WS_READ_OPTIONAL_POINTER
:
4113 case WS_READ_NILLABLE_POINTER
:
4115 INT16
*heap_val
= NULL
;
4116 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4119 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4122 *(INT16
**)ret
= heap_val
;
4126 FIXME( "read option %u not supported\n", option
);
4133 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4134 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4135 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4136 WS_HEAP
*heap
, void *ret
, ULONG size
)
4138 WS_XML_UTF8_TEXT
*utf8
;
4145 FIXME( "description not supported\n" );
4148 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4149 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
4154 case WS_READ_REQUIRED_VALUE
:
4155 if (!found
) return WS_E_INVALID_FORMAT
;
4158 case WS_READ_NILLABLE_VALUE
:
4159 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
4160 *(INT32
*)ret
= val
;
4163 case WS_READ_REQUIRED_POINTER
:
4164 if (!found
) return WS_E_INVALID_FORMAT
;
4167 case WS_READ_OPTIONAL_POINTER
:
4168 case WS_READ_NILLABLE_POINTER
:
4170 INT32
*heap_val
= NULL
;
4171 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4174 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4177 *(INT32
**)ret
= heap_val
;
4181 FIXME( "read option %u not supported\n", option
);
4188 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4189 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4190 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4191 WS_HEAP
*heap
, void *ret
, ULONG size
)
4193 WS_XML_UTF8_TEXT
*utf8
;
4200 FIXME( "description not supported\n" );
4203 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4204 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
4209 case WS_READ_REQUIRED_VALUE
:
4210 if (!found
) return WS_E_INVALID_FORMAT
;
4213 case WS_READ_NILLABLE_VALUE
:
4214 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4215 *(INT64
*)ret
= val
;
4218 case WS_READ_REQUIRED_POINTER
:
4219 if (!found
) return WS_E_INVALID_FORMAT
;
4222 case WS_READ_OPTIONAL_POINTER
:
4223 case WS_READ_NILLABLE_POINTER
:
4225 INT64
*heap_val
= NULL
;
4226 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4229 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4232 *(INT64
**)ret
= heap_val
;
4236 FIXME( "read option %u not supported\n", option
);
4243 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4244 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4245 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4246 WS_HEAP
*heap
, void *ret
, ULONG size
)
4248 WS_XML_UTF8_TEXT
*utf8
;
4255 FIXME( "description not supported\n" );
4258 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4259 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
4264 case WS_READ_REQUIRED_VALUE
:
4265 if (!found
) return WS_E_INVALID_FORMAT
;
4268 case WS_READ_NILLABLE_VALUE
:
4269 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
4270 *(UINT8
*)ret
= val
;
4273 case WS_READ_REQUIRED_POINTER
:
4274 if (!found
) return WS_E_INVALID_FORMAT
;
4277 case WS_READ_OPTIONAL_POINTER
:
4278 case WS_READ_NILLABLE_POINTER
:
4280 UINT8
*heap_val
= NULL
;
4281 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4284 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4287 *(UINT8
**)ret
= heap_val
;
4291 FIXME( "read option %u not supported\n", option
);
4298 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4299 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4300 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4301 WS_HEAP
*heap
, void *ret
, ULONG size
)
4303 WS_XML_UTF8_TEXT
*utf8
;
4310 FIXME( "description not supported\n" );
4313 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4314 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
4319 case WS_READ_REQUIRED_VALUE
:
4320 if (!found
) return WS_E_INVALID_FORMAT
;
4323 case WS_READ_NILLABLE_VALUE
:
4324 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
4325 *(UINT16
*)ret
= val
;
4328 case WS_READ_REQUIRED_POINTER
:
4329 if (!found
) return WS_E_INVALID_FORMAT
;
4332 case WS_READ_OPTIONAL_POINTER
:
4333 case WS_READ_NILLABLE_POINTER
:
4335 UINT16
*heap_val
= NULL
;
4336 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4339 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4342 *(UINT16
**)ret
= heap_val
;
4346 FIXME( "read option %u not supported\n", option
);
4353 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4354 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4355 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4356 WS_HEAP
*heap
, void *ret
, ULONG size
)
4358 WS_XML_UTF8_TEXT
*utf8
;
4365 FIXME( "description not supported\n" );
4368 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4369 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
4374 case WS_READ_REQUIRED_VALUE
:
4375 if (!found
) return WS_E_INVALID_FORMAT
;
4378 case WS_READ_NILLABLE_VALUE
:
4379 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
4380 *(UINT32
*)ret
= val
;
4383 case WS_READ_REQUIRED_POINTER
:
4384 if (!found
) return WS_E_INVALID_FORMAT
;
4387 case WS_READ_OPTIONAL_POINTER
:
4388 case WS_READ_NILLABLE_POINTER
:
4390 UINT32
*heap_val
= NULL
;
4391 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4394 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4397 *(UINT32
**)ret
= heap_val
;
4401 FIXME( "read option %u not supported\n", option
);
4408 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4409 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4410 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4411 WS_HEAP
*heap
, void *ret
, ULONG size
)
4413 WS_XML_UTF8_TEXT
*utf8
;
4420 FIXME( "description not supported\n" );
4423 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4424 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
)) != S_OK
)
4429 case WS_READ_REQUIRED_VALUE
:
4430 if (!found
) return WS_E_INVALID_FORMAT
;
4433 case WS_READ_NILLABLE_VALUE
:
4434 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4435 *(UINT64
*)ret
= val
;
4438 case WS_READ_REQUIRED_POINTER
:
4439 if (!found
) return WS_E_INVALID_FORMAT
;
4442 case WS_READ_OPTIONAL_POINTER
:
4443 case WS_READ_NILLABLE_POINTER
:
4445 UINT64
*heap_val
= NULL
;
4446 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4449 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4452 *(UINT64
**)ret
= heap_val
;
4456 FIXME( "read option %u not supported\n", option
);
4463 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4464 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4465 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4466 WS_HEAP
*heap
, void *ret
, ULONG size
)
4468 WS_XML_UTF8_TEXT
*utf8
;
4473 if (desc
) FIXME( "ignoring description\n" );
4475 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4476 if (found
&& (hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4480 case WS_READ_REQUIRED_VALUE
:
4481 if (!found
) return WS_E_INVALID_FORMAT
;
4484 case WS_READ_NILLABLE_VALUE
:
4485 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4486 *(double *)ret
= val
;
4489 case WS_READ_REQUIRED_POINTER
:
4490 if (!found
) return WS_E_INVALID_FORMAT
;
4493 case WS_READ_OPTIONAL_POINTER
:
4494 case WS_READ_NILLABLE_POINTER
:
4496 double *heap_val
= NULL
;
4497 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4500 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4503 *(double **)ret
= heap_val
;
4507 FIXME( "read option %u not supported\n", option
);
4514 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4515 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4516 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4517 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
4519 WS_XML_UTF8_TEXT
*utf8
;
4526 FIXME( "description not supported\n" );
4529 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4530 if (found
&& !(str
= xmltext_to_widechar( heap
, &utf8
->text
))) return WS_E_QUOTA_EXCEEDED
;
4534 case WS_READ_REQUIRED_POINTER
:
4535 if (!found
) return WS_E_INVALID_FORMAT
;
4538 case WS_READ_OPTIONAL_POINTER
:
4539 case WS_READ_NILLABLE_POINTER
:
4540 if (size
!= sizeof(str
)) return E_INVALIDARG
;
4545 FIXME( "read option %u not supported\n", option
);
4552 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
4555 for (i
= 0; i
< desc
->valueCount
; i
++)
4557 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
4559 *ret
= desc
->values
[i
].value
;
4563 return WS_E_INVALID_FORMAT
;
4566 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4567 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4568 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4569 WS_HEAP
*heap
, void *ret
, ULONG size
)
4571 WS_XML_UTF8_TEXT
*utf8
;
4576 if (!desc
) return E_INVALIDARG
;
4578 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4579 if (found
&& (hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
4583 case WS_READ_REQUIRED_VALUE
:
4584 if (!found
) return WS_E_INVALID_FORMAT
;
4587 case WS_READ_NILLABLE_VALUE
:
4588 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4592 case WS_READ_REQUIRED_POINTER
:
4593 if (!found
) return WS_E_INVALID_FORMAT
;
4596 case WS_READ_OPTIONAL_POINTER
:
4597 case WS_READ_NILLABLE_POINTER
:
4599 int *heap_val
= NULL
;
4600 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4603 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4606 *(int **)ret
= heap_val
;
4610 FIXME( "read option %u not supported\n", option
);
4617 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4618 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4619 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4620 WS_HEAP
*heap
, void *ret
, ULONG size
)
4622 WS_XML_UTF8_TEXT
*utf8
;
4624 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
4627 if (desc
) FIXME( "ignoring description\n" );
4629 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4630 if (found
&& (hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4634 case WS_READ_REQUIRED_VALUE
:
4635 if (!found
) return WS_E_INVALID_FORMAT
;
4638 case WS_READ_NILLABLE_VALUE
:
4639 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4640 *(WS_DATETIME
*)ret
= val
;
4643 case WS_READ_REQUIRED_POINTER
:
4644 if (!found
) return WS_E_INVALID_FORMAT
;
4647 case WS_READ_OPTIONAL_POINTER
:
4648 case WS_READ_NILLABLE_POINTER
:
4650 WS_DATETIME
*heap_val
= NULL
;
4651 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4654 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4657 *(WS_DATETIME
**)ret
= heap_val
;
4661 FIXME( "read option %u not supported\n", option
);
4668 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4669 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4670 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4671 WS_HEAP
*heap
, void *ret
, ULONG size
)
4673 WS_XML_UTF8_TEXT
*utf8
;
4678 if (desc
) FIXME( "ignoring description\n" );
4680 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4681 if (found
&& (hr
= str_to_guid( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4685 case WS_READ_REQUIRED_VALUE
:
4686 if (!found
) return WS_E_INVALID_FORMAT
;
4689 case WS_READ_NILLABLE_VALUE
:
4690 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4694 case WS_READ_REQUIRED_POINTER
:
4695 if (!found
) return WS_E_INVALID_FORMAT
;
4698 case WS_READ_OPTIONAL_POINTER
:
4699 case WS_READ_NILLABLE_POINTER
:
4701 GUID
*heap_val
= NULL
;
4702 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4705 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4708 *(GUID
**)ret
= heap_val
;
4712 FIXME( "read option %u not supported\n", option
);
4719 static HRESULT
read_type_unique_id( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4720 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4721 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4722 WS_HEAP
*heap
, void *ret
, ULONG size
)
4724 WS_XML_UTF8_TEXT
*utf8
;
4725 WS_UNIQUE_ID val
= {{0}};
4729 if (desc
) FIXME( "ignoring description\n" );
4731 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4732 if (found
&& (hr
= str_to_unique_id( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
) return hr
;
4736 case WS_READ_REQUIRED_VALUE
:
4737 if (!found
) return WS_E_INVALID_FORMAT
;
4740 case WS_READ_NILLABLE_VALUE
:
4741 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4742 *(WS_UNIQUE_ID
*)ret
= val
;
4745 case WS_READ_REQUIRED_POINTER
:
4746 if (!found
) return WS_E_INVALID_FORMAT
;
4749 case WS_READ_OPTIONAL_POINTER
:
4750 case WS_READ_NILLABLE_POINTER
:
4752 WS_UNIQUE_ID
*heap_val
= NULL
;
4753 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4756 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4759 *(WS_UNIQUE_ID
**)ret
= heap_val
;
4763 FIXME( "read option %u not supported\n", option
);
4770 static HRESULT
read_type_string( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4771 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4772 const WS_STRING_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4773 WS_HEAP
*heap
, void *ret
, ULONG size
)
4775 WS_XML_UTF8_TEXT
*utf8
;
4776 WS_STRING val
= {0};
4780 if (desc
) FIXME( "ignoring description\n" );
4782 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4783 if (found
&& (hr
= str_to_string( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4788 case WS_READ_REQUIRED_VALUE
:
4789 if (!found
) return WS_E_INVALID_FORMAT
;
4792 case WS_READ_NILLABLE_VALUE
:
4793 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4794 *(WS_STRING
*)ret
= val
;
4797 case WS_READ_REQUIRED_POINTER
:
4798 if (!found
) return WS_E_INVALID_FORMAT
;
4801 case WS_READ_OPTIONAL_POINTER
:
4802 case WS_READ_NILLABLE_POINTER
:
4804 WS_STRING
*heap_val
= NULL
;
4805 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4808 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4811 *(WS_STRING
**)ret
= heap_val
;
4815 FIXME( "read option %u not supported\n", option
);
4822 static HRESULT
read_type_bytes( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4823 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4824 const WS_BYTES_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4825 WS_HEAP
*heap
, void *ret
, ULONG size
)
4827 WS_XML_UTF8_TEXT
*utf8
;
4832 if (desc
) FIXME( "ignoring description\n" );
4834 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4835 if (found
&& (hr
= str_to_bytes( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4840 case WS_READ_REQUIRED_VALUE
:
4841 if (!found
) return WS_E_INVALID_FORMAT
;
4844 case WS_READ_NILLABLE_VALUE
:
4845 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4846 *(WS_BYTES
*)ret
= val
;
4849 case WS_READ_REQUIRED_POINTER
:
4850 if (!found
) return WS_E_INVALID_FORMAT
;
4853 case WS_READ_OPTIONAL_POINTER
:
4854 case WS_READ_NILLABLE_POINTER
:
4856 WS_BYTES
*heap_val
= NULL
;
4857 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4860 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4863 *(WS_BYTES
**)ret
= heap_val
;
4867 FIXME( "read option %u not supported\n", option
);
4874 static HRESULT
read_type_xml_string( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4875 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4876 const WS_XML_STRING_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4877 WS_HEAP
*heap
, void *ret
, ULONG size
)
4879 WS_XML_UTF8_TEXT
*utf8
;
4880 WS_XML_STRING val
= {0};
4884 if (desc
) FIXME( "ignoring description\n" );
4886 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4887 if (found
&& (hr
= str_to_xml_string( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4892 case WS_READ_REQUIRED_VALUE
:
4893 if (!found
) return WS_E_INVALID_FORMAT
;
4896 case WS_READ_NILLABLE_VALUE
:
4897 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4898 *(WS_XML_STRING
*)ret
= val
;
4901 case WS_READ_REQUIRED_POINTER
:
4902 if (!found
) return WS_E_INVALID_FORMAT
;
4905 case WS_READ_OPTIONAL_POINTER
:
4906 case WS_READ_NILLABLE_POINTER
:
4908 WS_XML_STRING
*heap_val
= NULL
;
4909 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4912 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4915 *(WS_XML_STRING
**)ret
= heap_val
;
4919 FIXME( "read option %u not supported\n", option
);
4926 static HRESULT
read_type_qname( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4927 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4928 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4929 WS_HEAP
*heap
, void *ret
, ULONG size
)
4931 WS_XML_UTF8_TEXT
*utf8
;
4932 WS_XML_QNAME val
= {{0}};
4936 if (desc
) FIXME( "ignoring description\n" );
4938 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
4939 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
4940 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
4942 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4943 if (found
&& (hr
= str_to_qname( reader
, utf8
->value
.bytes
, utf8
->value
.length
, heap
,
4944 NULL
, &val
.localName
, &val
.ns
)) != S_OK
) return hr
;
4948 case WS_READ_REQUIRED_VALUE
:
4949 if (!found
) return WS_E_INVALID_FORMAT
;
4952 case WS_READ_NILLABLE_VALUE
:
4953 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4954 *(WS_XML_QNAME
*)ret
= val
;
4957 case WS_READ_REQUIRED_POINTER
:
4958 if (!found
) return WS_E_INVALID_FORMAT
;
4961 case WS_READ_OPTIONAL_POINTER
:
4962 case WS_READ_NILLABLE_POINTER
:
4964 WS_XML_QNAME
*heap_val
= NULL
;
4965 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4968 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4971 *(WS_XML_QNAME
**)ret
= heap_val
;
4975 FIXME( "read option %u not supported\n", option
);
4982 static BOOL
is_empty_text_node( const struct node
*node
)
4984 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4985 const WS_XML_UTF8_TEXT
*utf8
;
4988 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
4989 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
4991 ERR( "unhandled text type %u\n", text
->text
->textType
);
4994 utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
4995 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
4999 static HRESULT
read_next_node( struct reader
*reader
)
5001 if (reader
->current
== reader
->last
) return read_node( reader
);
5002 if (move_to_child_node( &reader
->current
)) return S_OK
;
5003 if (move_to_next_node( &reader
->current
)) return S_OK
;
5004 if (!move_to_parent_node( &reader
->current
)) return WS_E_INVALID_FORMAT
;
5005 if (move_to_next_node( &reader
->current
)) return S_OK
;
5006 return WS_E_INVALID_FORMAT
;
5009 /* skips comment and empty text nodes */
5010 static HRESULT
read_type_next_node( struct reader
*reader
)
5015 WS_XML_NODE_TYPE type
;
5017 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
5018 type
= node_type( reader
->current
);
5019 if (type
== WS_XML_NODE_TYPE_COMMENT
||
5020 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
5025 static BOOL
match_current_element( struct reader
*reader
, const WS_XML_STRING
*localname
,
5026 const WS_XML_STRING
*ns
)
5028 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
5029 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
5030 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
5031 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
5034 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
5035 const WS_XML_STRING
*ns
)
5041 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
5042 if (reader
->current
== reader
->last
)
5045 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
5046 if (!found
) return WS_E_INVALID_FORMAT
;
5048 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
5050 node
= reader
->current
;
5051 attr
= reader
->current_attr
;
5053 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
5054 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
5056 reader
->current
= node
;
5057 reader
->current_attr
= attr
;
5059 return WS_E_INVALID_FORMAT
;
5062 ULONG
get_type_size( WS_TYPE type
, const WS_STRUCT_DESCRIPTION
*desc
)
5068 return sizeof(INT8
);
5071 case WS_UINT16_TYPE
:
5072 return sizeof(INT16
);
5076 case WS_UINT32_TYPE
:
5078 return sizeof(INT32
);
5081 case WS_UINT64_TYPE
:
5082 return sizeof(INT64
);
5084 case WS_DOUBLE_TYPE
:
5085 return sizeof(double);
5087 case WS_DATETIME_TYPE
:
5088 return sizeof(WS_DATETIME
);
5091 return sizeof(GUID
);
5093 case WS_STRING_TYPE
:
5094 return sizeof(WS_STRING
);
5097 return sizeof(WCHAR
*);
5100 return sizeof(WS_BYTES
);
5102 case WS_XML_STRING_TYPE
:
5103 return sizeof(WS_XML_STRING
);
5105 case WS_XML_QNAME_TYPE
:
5106 return sizeof(WS_XML_QNAME
);
5108 case WS_STRUCT_TYPE
:
5111 case WS_DESCRIPTION_TYPE
:
5112 return sizeof(WS_STRUCT_DESCRIPTION
*);
5115 ERR( "unhandled type %u\n", type
);
5120 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
, ULONG options
)
5122 if (options
& WS_FIELD_POINTER
)
5124 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
5125 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
5126 return WS_READ_REQUIRED_POINTER
;
5137 case WS_UINT16_TYPE
:
5138 case WS_UINT32_TYPE
:
5139 case WS_UINT64_TYPE
:
5140 case WS_DOUBLE_TYPE
:
5141 case WS_DATETIME_TYPE
:
5143 case WS_UNIQUE_ID_TYPE
:
5144 case WS_STRING_TYPE
:
5146 case WS_XML_STRING_TYPE
:
5147 case WS_XML_QNAME_TYPE
:
5148 case WS_STRUCT_TYPE
:
5150 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_READ_NILLABLE_VALUE
;
5151 return WS_READ_REQUIRED_VALUE
;
5154 case WS_DESCRIPTION_TYPE
:
5155 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
5156 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
5157 return WS_READ_REQUIRED_POINTER
;
5160 FIXME( "unhandled type %u\n", type
);
5165 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
5166 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
5169 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5170 WS_HEAP
*heap
, void **ret
, ULONG
*count
)
5173 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
5174 WS_READ_OPTION option
;
5177 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
5179 /* wrapper element */
5180 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
5183 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
5184 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
5186 item_size
= sizeof(void *);
5188 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
5191 if (nb_items
>= nb_allocated
)
5193 SIZE_T old_size
= nb_allocated
* item_size
, new_size
= old_size
* 2;
5194 if (!(buf
= ws_realloc_zero( heap
, buf
, old_size
, new_size
)))
5195 return WS_E_QUOTA_EXCEEDED
;
5198 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
5199 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
5200 if (hr
== WS_E_INVALID_FORMAT
) break;
5203 ws_free( heap
, buf
, nb_allocated
* item_size
);
5206 offset
+= item_size
;
5210 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
5212 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
5214 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
5215 desc
->itemRange
->maxItemCount
);
5216 ws_free( heap
, buf
, nb_allocated
* item_size
);
5217 return WS_E_INVALID_FORMAT
;
5226 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5227 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
5230 if (reader
->current
== reader
->last
)
5233 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
5234 if (!found
) return WS_E_INVALID_FORMAT
;
5236 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
5237 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
5239 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
5240 desc
->typeDescription
, option
, heap
, ret
, size
);
5243 static HRESULT
read_type_struct_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5244 WS_HEAP
*heap
, char *buf
, ULONG offset
)
5247 WS_READ_OPTION option
;
5251 if (!desc
) return E_INVALIDARG
;
5252 if (desc
->options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
5254 FIXME( "options %08x not supported\n", desc
->options
);
5257 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
5259 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
5260 size
= get_type_size( desc
->type
, desc
->typeDescription
);
5262 size
= sizeof(void *);
5265 switch (desc
->mapping
)
5267 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING
:
5268 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
5271 case WS_ATTRIBUTE_FIELD_MAPPING
:
5272 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
5273 desc
->typeDescription
, option
, heap
, ptr
, size
);
5276 case WS_ELEMENT_FIELD_MAPPING
:
5277 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
5278 desc
->typeDescription
, option
, heap
, ptr
, size
);
5281 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
5284 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, &count
);
5285 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
5288 case WS_TEXT_FIELD_MAPPING
:
5289 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
5293 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
5297 if (hr
== WS_E_INVALID_FORMAT
)
5301 case WS_READ_REQUIRED_VALUE
:
5302 case WS_READ_REQUIRED_POINTER
:
5303 return WS_E_INVALID_FORMAT
;
5305 case WS_READ_NILLABLE_VALUE
:
5306 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
5309 case WS_READ_OPTIONAL_POINTER
:
5310 case WS_READ_NILLABLE_POINTER
:
5311 *(void **)ptr
= NULL
;
5315 ERR( "unhandled option %u\n", option
);
5323 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5324 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5325 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5326 WS_HEAP
*heap
, void *ret
, ULONG size
)
5332 if (!desc
) return E_INVALIDARG
;
5333 if (desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5335 FIXME( "struct options %08x not supported\n",
5336 desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
);
5341 case WS_READ_REQUIRED_POINTER
:
5342 case WS_READ_OPTIONAL_POINTER
:
5343 case WS_READ_NILLABLE_POINTER
:
5344 if (size
!= sizeof(void *)) return E_INVALIDARG
;
5345 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
5348 case WS_READ_REQUIRED_VALUE
:
5349 case WS_READ_NILLABLE_VALUE
:
5350 if (size
!= desc
->size
) return E_INVALIDARG
;
5355 FIXME( "unhandled read option %u\n", option
);
5359 for (i
= 0; i
< desc
->fieldCount
; i
++)
5361 offset
= desc
->fields
[i
]->offset
;
5362 if ((hr
= read_type_struct_field( reader
, desc
->fields
[i
], heap
, buf
, offset
)) != S_OK
)
5368 case WS_READ_REQUIRED_POINTER
:
5371 ws_free( heap
, buf
, desc
->size
);
5374 *(char **)ret
= buf
;
5377 case WS_READ_OPTIONAL_POINTER
:
5378 case WS_READ_NILLABLE_POINTER
:
5379 if (is_nil_value( buf
, desc
->size
))
5381 ws_free( heap
, buf
, desc
->size
);
5384 *(char **)ret
= buf
;
5387 case WS_READ_REQUIRED_VALUE
:
5388 case WS_READ_NILLABLE_VALUE
:
5389 if (hr
!= S_OK
) return hr
;
5393 ERR( "unhandled read option %u\n", option
);
5397 if (desc
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5399 struct node
*parent
= find_parent( reader
);
5400 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
5405 static HRESULT
start_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
5406 const WS_XML_STRING
*ns
)
5410 case WS_ELEMENT_TYPE_MAPPING
:
5411 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5412 return read_type_next_element_node( reader
, localname
, ns
);
5414 case WS_ANY_ELEMENT_TYPE_MAPPING
:
5415 case WS_ATTRIBUTE_TYPE_MAPPING
:
5419 FIXME( "unhandled mapping %u\n", mapping
);
5424 static HRESULT
read_type_endelement_node( struct reader
*reader
)
5426 const struct node
*parent
= find_parent( reader
);
5431 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
5432 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
&& reader
->current
->parent
== parent
)
5436 if (read_end_of_data( reader
) || !(parent
->flags
& NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
)) break;
5439 return WS_E_INVALID_FORMAT
;
5442 static HRESULT
end_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
)
5446 case WS_ELEMENT_TYPE_MAPPING
:
5447 return read_type_endelement_node( reader
);
5449 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5450 return read_type_next_node( reader
);
5452 case WS_ATTRIBUTE_TYPE_MAPPING
:
5458 static HRESULT
is_nil_element( const WS_XML_ELEMENT_NODE
*elem
)
5460 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
5461 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
5464 for (i
= 0; i
< elem
->attributeCount
; i
++)
5466 const WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[i
]->value
;
5468 if (elem
->attributes
[i
]->isXmlNs
) continue;
5469 if (WsXmlStringEquals( elem
->attributes
[i
]->localName
, &localname
, NULL
) == S_OK
&&
5470 WsXmlStringEquals( elem
->attributes
[i
]->ns
, &ns
, NULL
) == S_OK
&&
5471 text
->value
.length
== 4 && !memcmp( text
->value
.bytes
, "true", 4 )) return TRUE
;
5476 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5477 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
, const void *desc
,
5478 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
)
5482 if ((hr
= start_mapping( reader
, mapping
, localname
, ns
)) != S_OK
) return hr
;
5484 if (mapping
== WS_ELEMENT_TYPE_MAPPING
&& is_nil_element( &reader
->current
->hdr
))
5486 if (option
!= WS_READ_NILLABLE_POINTER
&& option
!= WS_READ_NILLABLE_VALUE
) return WS_E_INVALID_FORMAT
;
5487 return end_mapping( reader
, mapping
);
5493 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5498 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5503 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5508 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5513 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5518 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5522 case WS_UINT16_TYPE
:
5523 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5527 case WS_UINT32_TYPE
:
5528 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5532 case WS_UINT64_TYPE
:
5533 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5537 case WS_DOUBLE_TYPE
:
5538 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5542 case WS_DATETIME_TYPE
:
5543 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5548 if ((hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5552 case WS_UNIQUE_ID_TYPE
:
5553 if ((hr
= read_type_unique_id( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5557 case WS_STRING_TYPE
:
5558 if ((hr
= read_type_string( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5563 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5568 if ((hr
= read_type_bytes( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5572 case WS_XML_STRING_TYPE
:
5573 if ((hr
= read_type_xml_string( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5577 case WS_XML_QNAME_TYPE
:
5578 if ((hr
= read_type_qname( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5582 case WS_STRUCT_TYPE
:
5583 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5588 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5593 FIXME( "type %u not supported\n", type
);
5597 return end_mapping( reader
, mapping
);
5600 /**************************************************************************
5601 * WsReadType [webservices.@]
5603 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5604 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
5605 ULONG size
, WS_ERROR
*error
)
5607 struct reader
*reader
= (struct reader
*)handle
;
5610 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
5612 if (error
) FIXME( "ignoring error parameter\n" );
5614 if (!reader
|| !value
) return E_INVALIDARG
;
5616 EnterCriticalSection( &reader
->cs
);
5618 if (reader
->magic
!= READER_MAGIC
)
5620 LeaveCriticalSection( &reader
->cs
);
5621 return E_INVALIDARG
;
5624 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
5626 LeaveCriticalSection( &reader
->cs
);
5632 case WS_ELEMENT_TYPE_MAPPING
:
5633 hr
= read_node( reader
);
5640 if (hr
== S_OK
&& !read_end_of_data( reader
)) hr
= WS_E_INVALID_FORMAT
;
5642 LeaveCriticalSection( &reader
->cs
);
5646 HRESULT
read_header( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5647 WS_TYPE type
, const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
5650 struct reader
*reader
= (struct reader
*)handle
;
5653 EnterCriticalSection( &reader
->cs
);
5655 if (reader
->magic
!= READER_MAGIC
)
5657 LeaveCriticalSection( &reader
->cs
);
5658 return E_INVALIDARG
;
5661 hr
= read_type( reader
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, type
, localname
, ns
, desc
, option
, heap
,
5664 LeaveCriticalSection( &reader
->cs
);
5668 /**************************************************************************
5669 * WsReadElement [webservices.@]
5671 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
5672 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5675 struct reader
*reader
= (struct reader
*)handle
;
5678 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5679 if (error
) FIXME( "ignoring error parameter\n" );
5681 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5683 EnterCriticalSection( &reader
->cs
);
5685 if (reader
->magic
!= READER_MAGIC
)
5687 LeaveCriticalSection( &reader
->cs
);
5688 return E_INVALIDARG
;
5691 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
5692 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5694 LeaveCriticalSection( &reader
->cs
);
5698 /**************************************************************************
5699 * WsReadValue [webservices.@]
5701 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
5704 struct reader
*reader
= (struct reader
*)handle
;
5705 WS_TYPE type
= map_value_type( value_type
);
5708 TRACE( "%p %u %p %u %p\n", handle
, type
, value
, size
, error
);
5709 if (error
) FIXME( "ignoring error parameter\n" );
5711 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
5713 EnterCriticalSection( &reader
->cs
);
5715 if (reader
->magic
!= READER_MAGIC
)
5717 LeaveCriticalSection( &reader
->cs
);
5718 return E_INVALIDARG
;
5721 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
5722 NULL
, value
, size
);
5724 LeaveCriticalSection( &reader
->cs
);
5728 /**************************************************************************
5729 * WsReadAttribute [webservices.@]
5731 HRESULT WINAPI
WsReadAttribute( WS_XML_READER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
5732 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5735 struct reader
*reader
= (struct reader
*)handle
;
5738 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5739 if (error
) FIXME( "ignoring error parameter\n" );
5741 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5743 EnterCriticalSection( &reader
->cs
);
5745 if (reader
->magic
!= READER_MAGIC
)
5747 LeaveCriticalSection( &reader
->cs
);
5748 return E_INVALIDARG
;
5751 if (!reader
->input_type
)
5753 LeaveCriticalSection( &reader
->cs
);
5754 return WS_E_INVALID_OPERATION
;
5757 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->attributeLocalName
,
5758 desc
->attributeNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5760 LeaveCriticalSection( &reader
->cs
);
5764 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5766 static const char bom
[] = {0xef,0xbb,0xbf};
5767 const unsigned char *p
= data
;
5769 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
5770 (size
> 2 && !(*offset
= 0));
5773 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5775 static const char bom
[] = {0xff,0xfe};
5776 const unsigned char *p
= data
;
5778 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
5779 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
5782 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5786 /* FIXME: parse xml declaration */
5788 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
5789 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
5792 FIXME( "charset not recognized\n" );
5796 TRACE( "detected charset %u\n", ret
);
5800 static void set_input_buffer( struct reader
*reader
, struct xmlbuf
*buf
, const unsigned char *data
, ULONG size
)
5802 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
5803 reader
->input_buf
= buf
;
5804 reader
->input_data
= data
;
5805 reader
->input_size
= size
;
5807 reader
->read_size
= reader
->input_size
;
5808 reader
->read_pos
= 0;
5809 reader
->read_bufptr
= reader
->input_data
;
5811 reader
->text_conv_offset
= 0;
5814 /**************************************************************************
5815 * WsSetInput [webservices.@]
5817 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
5818 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
5819 ULONG count
, WS_ERROR
*error
)
5821 struct reader
*reader
= (struct reader
*)handle
;
5823 ULONG i
, offset
= 0;
5826 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
5827 if (error
) FIXME( "ignoring error parameter\n" );
5829 if (!reader
) return E_INVALIDARG
;
5831 EnterCriticalSection( &reader
->cs
);
5833 if (reader
->magic
!= READER_MAGIC
)
5835 LeaveCriticalSection( &reader
->cs
);
5836 return E_INVALIDARG
;
5839 for (i
= 0; i
< count
; i
++)
5841 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
5842 properties
[i
].valueSize
);
5843 if (hr
!= S_OK
) goto done
;
5846 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
5848 switch (encoding
->encodingType
)
5850 case WS_XML_READER_ENCODING_TYPE_TEXT
:
5852 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
5853 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
5855 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
5857 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
5862 if (text
->charSet
!= WS_CHARSET_AUTO
) reader
->input_charset
= text
->charSet
;
5863 else reader
->input_charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
5865 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
5868 case WS_XML_READER_ENCODING_TYPE_BINARY
:
5870 WS_XML_READER_BINARY_ENCODING
*bin
= (WS_XML_READER_BINARY_ENCODING
*)encoding
;
5871 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_BINARY
;
5872 reader
->input_charset
= 0;
5873 reader
->dict_static
= bin
->staticDictionary
? bin
->staticDictionary
: &dict_builtin_static
.dict
;
5874 reader
->dict
= bin
->dynamicDictionary
? bin
->dynamicDictionary
: &dict_builtin
.dict
;
5878 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
5883 switch (input
->inputType
)
5885 case WS_XML_READER_INPUT_TYPE_BUFFER
:
5887 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
5888 set_input_buffer( reader
, NULL
, (const unsigned char *)buf
->encodedData
+ offset
,
5889 buf
->encodedDataSize
- offset
);
5893 FIXME( "input type %u not supported\n", input
->inputType
);
5898 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
5899 else read_insert_bof( reader
, node
);
5902 LeaveCriticalSection( &reader
->cs
);
5906 /**************************************************************************
5907 * WsSetInputToBuffer [webservices.@]
5909 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
5910 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
5913 struct reader
*reader
= (struct reader
*)handle
;
5914 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
5919 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
5920 if (error
) FIXME( "ignoring error parameter\n" );
5922 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
5924 EnterCriticalSection( &reader
->cs
);
5926 if (reader
->magic
!= READER_MAGIC
)
5928 LeaveCriticalSection( &reader
->cs
);
5929 return E_INVALIDARG
;
5932 for (i
= 0; i
< count
; i
++)
5934 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
5935 properties
[i
].valueSize
);
5936 if (hr
!= S_OK
) goto done
;
5939 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
5941 reader
->input_enc
= xmlbuf
->encoding
;
5942 reader
->input_charset
= xmlbuf
->charset
;
5943 set_input_buffer( reader
, xmlbuf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
5945 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
5946 else read_insert_bof( reader
, node
);
5949 LeaveCriticalSection( &reader
->cs
);
5953 /**************************************************************************
5954 * WsGetReaderPosition [webservices.@]
5956 HRESULT WINAPI
WsGetReaderPosition( WS_XML_READER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
5958 struct reader
*reader
= (struct reader
*)handle
;
5960 TRACE( "%p %p %p\n", handle
, pos
, error
);
5961 if (error
) FIXME( "ignoring error parameter\n" );
5963 if (!reader
|| !pos
) return E_INVALIDARG
;
5965 EnterCriticalSection( &reader
->cs
);
5967 if (reader
->magic
!= READER_MAGIC
)
5969 LeaveCriticalSection( &reader
->cs
);
5970 return E_INVALIDARG
;
5973 if (!reader
->input_buf
)
5975 LeaveCriticalSection( &reader
->cs
);
5976 return WS_E_INVALID_OPERATION
;
5979 pos
->buffer
= (WS_XML_BUFFER
*)reader
->input_buf
;
5980 pos
->node
= reader
->current
;
5982 LeaveCriticalSection( &reader
->cs
);
5986 /**************************************************************************
5987 * WsSetReaderPosition [webservices.@]
5989 HRESULT WINAPI
WsSetReaderPosition( WS_XML_READER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
5991 struct reader
*reader
= (struct reader
*)handle
;
5993 TRACE( "%p %p %p\n", handle
, pos
, error
);
5994 if (error
) FIXME( "ignoring error parameter\n" );
5996 if (!reader
|| !pos
) return E_INVALIDARG
;
5998 EnterCriticalSection( &reader
->cs
);
6000 if (reader
->magic
!= READER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= reader
->input_buf
)
6002 LeaveCriticalSection( &reader
->cs
);
6003 return E_INVALIDARG
;
6006 if (!reader
->input_buf
)
6008 LeaveCriticalSection( &reader
->cs
);
6009 return WS_E_INVALID_OPERATION
;
6012 reader
->current
= pos
->node
;
6014 LeaveCriticalSection( &reader
->cs
);
6018 static HRESULT
utf8_to_base64( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_BASE64_TEXT
*base64
)
6020 if (utf8
->value
.length
% 4) return WS_E_INVALID_FORMAT
;
6021 if (!(base64
->bytes
= heap_alloc( utf8
->value
.length
* 3 / 4 ))) return E_OUTOFMEMORY
;
6022 base64
->length
= decode_base64( utf8
->value
.bytes
, utf8
->value
.length
, base64
->bytes
);
6026 /**************************************************************************
6027 * WsReadBytes [webservices.@]
6029 HRESULT WINAPI
WsReadBytes( WS_XML_READER
*handle
, void *bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
6031 struct reader
*reader
= (struct reader
*)handle
;
6034 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
6035 if (error
) FIXME( "ignoring error parameter\n" );
6037 if (!reader
) return E_INVALIDARG
;
6039 EnterCriticalSection( &reader
->cs
);
6041 if (reader
->magic
!= READER_MAGIC
)
6043 LeaveCriticalSection( &reader
->cs
);
6044 return E_INVALIDARG
;
6047 if (!reader
->input_type
)
6049 LeaveCriticalSection( &reader
->cs
);
6050 return WS_E_INVALID_OPERATION
;
6055 LeaveCriticalSection( &reader
->cs
);
6056 return E_INVALIDARG
;
6060 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
6062 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
6063 WS_XML_BASE64_TEXT base64
;
6065 if ((hr
= utf8_to_base64( (const WS_XML_UTF8_TEXT
*)text
->text
, &base64
)) != S_OK
)
6067 LeaveCriticalSection( &reader
->cs
);
6070 if (reader
->text_conv_offset
== base64
.length
)
6072 heap_free( base64
.bytes
);
6073 hr
= read_node( reader
);
6074 LeaveCriticalSection( &reader
->cs
);
6077 *count
= min( base64
.length
- reader
->text_conv_offset
, max_count
);
6078 memcpy( bytes
, base64
.bytes
+ reader
->text_conv_offset
, *count
);
6079 reader
->text_conv_offset
+= *count
;
6080 heap_free( base64
.bytes
);
6083 LeaveCriticalSection( &reader
->cs
);
6087 static HRESULT
utf8_to_utf16( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_UTF16_TEXT
*utf16
)
6089 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
6090 if (!(utf16
->bytes
= heap_alloc( len
* sizeof(WCHAR
) ))) return E_OUTOFMEMORY
;
6091 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, (WCHAR
*)utf16
->bytes
, len
);
6092 utf16
->byteCount
= len
* sizeof(WCHAR
);
6096 /**************************************************************************
6097 * WsReadChars [webservices.@]
6099 HRESULT WINAPI
WsReadChars( WS_XML_READER
*handle
, WCHAR
*chars
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
6101 struct reader
*reader
= (struct reader
*)handle
;
6103 TRACE( "%p %p %u %p %p\n", handle
, chars
, max_count
, count
, error
);
6104 if (error
) FIXME( "ignoring error parameter\n" );
6106 if (!reader
) return E_INVALIDARG
;
6108 EnterCriticalSection( &reader
->cs
);
6110 if (reader
->magic
!= READER_MAGIC
)
6112 LeaveCriticalSection( &reader
->cs
);
6113 return E_INVALIDARG
;
6116 if (!reader
->input_type
)
6118 LeaveCriticalSection( &reader
->cs
);
6119 return WS_E_INVALID_OPERATION
;
6124 LeaveCriticalSection( &reader
->cs
);
6125 return E_INVALIDARG
;
6129 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& chars
)
6131 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
6132 WS_XML_UTF16_TEXT utf16
;
6135 if ((hr
= utf8_to_utf16( (const WS_XML_UTF8_TEXT
*)text
->text
, &utf16
)) != S_OK
)
6137 LeaveCriticalSection( &reader
->cs
);
6140 if (reader
->text_conv_offset
== utf16
.byteCount
/ sizeof(WCHAR
))
6142 heap_free( utf16
.bytes
);
6143 hr
= read_node( reader
);
6144 LeaveCriticalSection( &reader
->cs
);
6147 *count
= min( utf16
.byteCount
/ sizeof(WCHAR
) - reader
->text_conv_offset
, max_count
);
6148 memcpy( chars
, utf16
.bytes
+ reader
->text_conv_offset
* sizeof(WCHAR
), *count
* sizeof(WCHAR
) );
6149 reader
->text_conv_offset
+= *count
;
6150 heap_free( utf16
.bytes
);
6153 LeaveCriticalSection( &reader
->cs
);
6157 /**************************************************************************
6158 * WsReadCharsUtf8 [webservices.@]
6160 HRESULT WINAPI
WsReadCharsUtf8( WS_XML_READER
*handle
, BYTE
*bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
6162 struct reader
*reader
= (struct reader
*)handle
;
6165 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
6166 if (error
) FIXME( "ignoring error parameter\n" );
6168 if (!reader
) return E_INVALIDARG
;
6170 EnterCriticalSection( &reader
->cs
);
6172 if (reader
->magic
!= READER_MAGIC
)
6174 LeaveCriticalSection( &reader
->cs
);
6175 return E_INVALIDARG
;
6178 if (!reader
->input_type
)
6180 LeaveCriticalSection( &reader
->cs
);
6181 return WS_E_INVALID_OPERATION
;
6186 LeaveCriticalSection( &reader
->cs
);
6187 return E_INVALIDARG
;
6191 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
6193 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
6194 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
6196 if (reader
->text_conv_offset
== utf8
->value
.length
)
6198 hr
= read_node( reader
);
6199 LeaveCriticalSection( &reader
->cs
);
6202 *count
= min( utf8
->value
.length
- reader
->text_conv_offset
, max_count
);
6203 memcpy( bytes
, utf8
->value
.bytes
+ reader
->text_conv_offset
, *count
);
6204 reader
->text_conv_offset
+= *count
;
6207 LeaveCriticalSection( &reader
->cs
);
6211 static HRESULT
move_to_element( struct reader
*reader
)
6214 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_BOF
&&
6215 (hr
= read_move_to( reader
, WS_MOVE_TO_CHILD_NODE
, NULL
)) != S_OK
) return hr
;
6216 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return E_FAIL
;
6220 static HRESULT
copy_tree( struct reader
*reader
, WS_XML_WRITER
*writer
)
6222 const struct node
*node
, *parent
;
6226 if ((hr
= move_to_element( reader
)) != S_OK
) return hr
;
6227 parent
= reader
->current
;
6230 node
= reader
->current
;
6231 if ((hr
= WsWriteNode( writer
, (const WS_XML_NODE
*)node
, NULL
)) != S_OK
) break;
6232 if (node_type( node
) == WS_XML_NODE_TYPE_END_ELEMENT
&& node
->parent
== parent
) done
= TRUE
;
6233 if ((hr
= read_next_node( reader
)) != S_OK
|| done
) break;
6238 /**************************************************************************
6239 * WsReadXmlBuffer [webservices.@]
6241 HRESULT WINAPI
WsReadXmlBuffer( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_BUFFER
**ret
, WS_ERROR
*error
)
6243 struct reader
*reader
= (struct reader
*)handle
;
6244 WS_XML_WRITER
*writer
= NULL
;
6245 WS_XML_BUFFER
*buffer
;
6248 TRACE( "%p %p %p %p\n", handle
, heap
, ret
, error
);
6249 if (error
) FIXME( "ignoring error parameter\n" );
6251 if (!reader
|| !heap
) return E_INVALIDARG
;
6252 if (!ret
) return E_FAIL
;
6254 EnterCriticalSection( &reader
->cs
);
6256 if (reader
->magic
!= READER_MAGIC
)
6258 LeaveCriticalSection( &reader
->cs
);
6259 return E_INVALIDARG
;
6262 if (!reader
->input_type
)
6264 LeaveCriticalSection( &reader
->cs
);
6265 return WS_E_INVALID_OPERATION
;
6268 if ((hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
)) != S_OK
) goto done
;
6269 if ((hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
)) != S_OK
) goto done
;
6270 if ((hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
)) != S_OK
) goto done
;
6271 if ((hr
= copy_tree( reader
, writer
)) == S_OK
) *ret
= buffer
;
6274 if (hr
!= S_OK
) free_xmlbuf( (struct xmlbuf
*)buffer
);
6275 WsFreeWriter( writer
);
6276 LeaveCriticalSection( &reader
->cs
);
6280 HRESULT
get_param_desc( const WS_STRUCT_DESCRIPTION
*desc
, USHORT index
, const WS_FIELD_DESCRIPTION
**ret
)
6282 if (index
>= desc
->fieldCount
) return E_INVALIDARG
;
6283 *ret
= desc
->fields
[index
];
6287 static ULONG
get_field_size( const WS_FIELD_DESCRIPTION
*desc
)
6289 WS_READ_OPTION option
;
6292 switch ((option
= get_field_read_option( desc
->type
, desc
->options
)))
6294 case WS_READ_REQUIRED_POINTER
:
6295 case WS_READ_OPTIONAL_POINTER
:
6296 case WS_READ_NILLABLE_POINTER
:
6297 size
= sizeof(void *);
6300 case WS_READ_REQUIRED_VALUE
:
6301 case WS_READ_NILLABLE_VALUE
:
6302 size
= get_type_size( desc
->type
, desc
->typeDescription
);
6306 WARN( "unhandled option %u\n", option
);
6313 static HRESULT
read_param( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
, void *ret
)
6315 if (!ret
&& !(ret
= ws_alloc_zero( heap
, get_field_size(desc
) ))) return WS_E_QUOTA_EXCEEDED
;
6316 return read_type_struct_field( reader
, desc
, heap
, ret
, 0 );
6319 static HRESULT
read_param_array( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
,
6320 void **ret
, ULONG
*count
)
6322 if (!ret
&& !(ret
= ws_alloc_zero( heap
, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED
;
6323 return read_type_repeating_element( reader
, desc
, heap
, ret
, count
);
6326 static void set_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, ULONG len
,
6330 for (i
= 0; i
< count
; i
++)
6332 if (params
[i
].outputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
6334 if ((ptr
= *(ULONG
**)args
[i
])) *ptr
= len
;
6339 HRESULT
read_output_params( WS_XML_READER
*handle
, WS_HEAP
*heap
, const WS_ELEMENT_DESCRIPTION
*desc
,
6340 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
6342 struct reader
*reader
= (struct reader
*)handle
;
6343 const WS_STRUCT_DESCRIPTION
*desc_struct
;
6344 const WS_FIELD_DESCRIPTION
*desc_field
;
6348 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
6350 EnterCriticalSection( &reader
->cs
);
6352 if (reader
->magic
!= READER_MAGIC
)
6354 LeaveCriticalSection( &reader
->cs
);
6355 return E_INVALIDARG
;
6358 if ((hr
= start_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
)
6361 for (i
= 0; i
< count
; i
++)
6363 if (params
[i
].outputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
6364 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
6366 FIXME( "messages type not supported\n" );
6370 if ((hr
= get_param_desc( desc_struct
, params
[i
].outputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
6371 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
6373 void *ptr
= *(void **)args
[i
];
6374 if ((hr
= read_param( reader
, desc_field
, heap
, ptr
)) != S_OK
) goto done
;
6376 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
6378 void **ptr
= *(void ***)args
[i
];
6379 if ((hr
= read_param_array( reader
, desc_field
, heap
, ptr
, &len
)) != S_OK
) goto done
;
6380 set_array_len( params
, count
, params
[i
].outputMessageIndex
, len
, args
);
6384 if (desc_struct
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
6386 struct node
*parent
= find_parent( reader
);
6387 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
6390 hr
= end_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
);
6393 LeaveCriticalSection( &reader
->cs
);