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 BYTE
*data
, ULONG len
)
777 WS_XML_UTF8_TEXT
*ret
;
779 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
780 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
781 ret
->value
.length
= len
;
782 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
783 ret
->value
.dictionary
= NULL
;
785 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
789 static WS_XML_BASE64_TEXT
*alloc_base64_text( const BYTE
*data
, ULONG len
)
791 WS_XML_BASE64_TEXT
*ret
;
793 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
794 ret
->text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
796 ret
->bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
797 if (data
) memcpy( ret
->bytes
, data
, len
);
801 static inline BOOL
read_end_of_data( struct reader
*reader
)
803 return reader
->read_pos
>= reader
->read_size
;
806 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
808 return &reader
->read_bufptr
[reader
->read_pos
];
811 static inline HRESULT
read_peek( struct reader
*reader
, unsigned char *byte
)
813 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
814 *byte
= reader
->read_bufptr
[reader
->read_pos
];
818 static inline HRESULT
read_byte( struct reader
*reader
, unsigned char *byte
)
820 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
821 *byte
= reader
->read_bufptr
[reader
->read_pos
++];
825 static inline HRESULT
read_bytes( struct reader
*reader
, unsigned char *bytes
, unsigned int len
)
827 if (reader
->read_pos
+ len
> reader
->read_size
) return WS_E_INVALID_FORMAT
;
828 memcpy( bytes
, reader
->read_bufptr
+ reader
->read_pos
, len
);
829 reader
->read_pos
+= len
;
833 /* UTF-8 support based on libs/wine/utf8.c */
835 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
836 static const char utf8_length
[128] =
838 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
839 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
840 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
841 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
842 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
843 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
844 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
845 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
848 /* first byte mask depending on UTF-8 sequence length */
849 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
851 /* minimum Unicode value depending on UTF-8 sequence length */
852 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
854 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
856 unsigned int len
, res
;
857 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
858 const unsigned char *end
;
860 if (reader
->read_pos
>= reader
->read_size
) return 0;
867 len
= utf8_length
[ch
- 0x80];
868 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
869 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
+ 1;
870 res
= ch
& utf8_mask
[len
];
875 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
876 res
= (res
<< 6) | ch
;
878 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
879 res
= (res
<< 6) | ch
;
881 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
882 res
= (res
<< 6) | ch
;
883 if (res
< utf8_minval
[len
]) break;
891 static inline void read_skip( struct reader
*reader
, unsigned int count
)
893 if (reader
->read_pos
+ count
> reader
->read_size
) return;
894 reader
->read_pos
+= count
;
897 static inline void read_rewind( struct reader
*reader
, unsigned int count
)
899 reader
->read_pos
-= count
;
902 static inline BOOL
read_isnamechar( unsigned int ch
)
904 /* FIXME: incomplete */
905 return (ch
>= 'A' && ch
<= 'Z') ||
906 (ch
>= 'a' && ch
<= 'z') ||
907 (ch
>= '0' && ch
<= '9') ||
908 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
911 static inline BOOL
read_isspace( unsigned int ch
)
913 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
916 static inline void read_skip_whitespace( struct reader
*reader
)
918 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
922 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
924 const unsigned char *ptr
= read_current_ptr( reader
);
926 if (len
< 0) len
= strlen( str
);
927 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
930 if (*str
!= *ptr
) return *ptr
- *str
;
936 static HRESULT
read_xmldecl( struct reader
*reader
)
938 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
940 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
942 reader
->state
= READER_STATE_BOF
;
945 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
946 read_skip( reader
, 6 );
948 /* FIXME: parse attributes */
949 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
952 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
953 read_skip( reader
, 2 );
955 reader
->state
= READER_STATE_BOF
;
959 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
961 if (elem
->attributeCount
)
963 WS_XML_ATTRIBUTE
**tmp
;
964 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
965 return E_OUTOFMEMORY
;
966 elem
->attributes
= tmp
;
968 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
969 elem
->attributes
[elem
->attributeCount
++] = attr
;
973 static inline void init_xml_string( BYTE
*bytes
, ULONG len
, WS_XML_STRING
*str
)
977 str
->dictionary
= NULL
;
981 static HRESULT
split_qname( const BYTE
*str
, ULONG len
, WS_XML_STRING
*prefix
, WS_XML_STRING
*localname
)
983 BYTE
*prefix_bytes
= NULL
, *localname_bytes
= (BYTE
*)str
, *ptr
= (BYTE
*)str
;
984 ULONG prefix_len
= 0, localname_len
= len
;
990 if (ptr
== str
) return WS_E_INVALID_FORMAT
;
991 prefix_bytes
= (BYTE
*)str
;
992 prefix_len
= ptr
- str
;
993 localname_bytes
= ptr
+ 1;
999 if (!localname_len
) return WS_E_INVALID_FORMAT
;
1001 init_xml_string( prefix_bytes
, prefix_len
, prefix
);
1002 init_xml_string( localname_bytes
, localname_len
, localname
);
1006 static HRESULT
parse_qname( const BYTE
*str
, ULONG len
, WS_XML_STRING
**prefix_ret
, WS_XML_STRING
**localname_ret
)
1008 WS_XML_STRING prefix
, localname
;
1011 if ((hr
= split_qname( str
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
1012 if (!(*prefix_ret
= alloc_xml_string( NULL
, prefix
.length
))) return E_OUTOFMEMORY
;
1013 if (!(*localname_ret
= dup_xml_string( &localname
)))
1015 free_xml_string( *prefix_ret
);
1016 return E_OUTOFMEMORY
;
1018 memcpy( (*prefix_ret
)->bytes
, prefix
.bytes
, prefix
.length
);
1019 if (prefix
.length
&& add_xml_string( *prefix_ret
) != S_OK
) WARN( "prefix not added to dictionary\n" );
1023 static int codepoint_to_utf8( int cp
, unsigned char *dst
)
1033 dst
[1] = 0x80 | (cp
& 0x3f);
1038 if ((cp
>= 0xd800 && cp
<= 0xdfff) || cp
== 0xfffe || cp
== 0xffff) return -1;
1041 dst
[2] = 0x80 | (cp
& 0x3f);
1043 dst
[1] = 0x80 | (cp
& 0x3f);
1048 if (cp
>= 0x110000) return -1;
1049 dst
[3] = 0x80 | (cp
& 0x3f);
1051 dst
[2] = 0x80 | (cp
& 0x3f);
1053 dst
[1] = 0x80 | (cp
& 0x3f);
1059 static HRESULT
decode_text( const unsigned char *str
, ULONG len
, unsigned char *ret
, ULONG
*ret_len
)
1061 const unsigned char *p
= str
;
1062 unsigned char *q
= ret
;
1070 if (!len
) return WS_E_INVALID_FORMAT
;
1072 if (len
>= 3 && !memcmp( p
, "lt;", 3 ))
1078 else if (len
>= 3 && !memcmp( p
, "gt;", 3 ))
1084 else if (len
>= 5 && !memcmp( p
, "quot;", 5 ))
1090 else if (len
>= 4 && !memcmp( p
, "amp;", 4 ))
1096 else if (len
>= 5 && !memcmp( p
, "apos;", 5 ))
1104 ULONG start
, nb_digits
, i
;
1105 int len_utf8
, cp
= 0;
1108 if (!len
) return WS_E_INVALID_FORMAT
;
1114 while (len
&& isxdigit( *p
)) { p
++; len
--; };
1115 if (!len
) return WS_E_INVALID_FORMAT
;
1117 p
-= nb_digits
= start
- len
;
1118 if (!nb_digits
|| nb_digits
> 6 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1119 for (i
= 0; i
< nb_digits
; i
++)
1122 if (*p
>= '0' && *p
<= '9') cp
+= *p
- '0';
1123 else if (*p
>= 'a' && *p
<= 'f') cp
+= *p
- 'a' + 10;
1124 else cp
+= *p
- 'A' + 10;
1128 else if (isdigit( *p
))
1130 while (len
&& *p
== '0') { p
++; len
--; };
1131 if (!len
) return WS_E_INVALID_FORMAT
;
1134 while (len
&& isdigit( *p
)) { p
++; len
--; };
1135 if (!len
) return WS_E_INVALID_FORMAT
;
1137 p
-= nb_digits
= start
- len
;
1138 if (!nb_digits
|| nb_digits
> 7 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1139 for (i
= 0; i
< nb_digits
; i
++)
1146 else return WS_E_INVALID_FORMAT
;
1148 if ((len_utf8
= codepoint_to_utf8( cp
, q
)) < 0) return WS_E_INVALID_FORMAT
;
1149 *ret_len
+= len_utf8
;
1153 else return WS_E_INVALID_FORMAT
;
1165 static HRESULT
read_attribute_value_text( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1167 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1168 unsigned int len
, ch
, skip
, quote
;
1169 const unsigned char *start
;
1170 HRESULT hr
= E_OUTOFMEMORY
;
1172 read_skip_whitespace( reader
);
1173 if (read_cmp( reader
, "=", 1 )) return WS_E_INVALID_FORMAT
;
1174 read_skip( reader
, 1 );
1176 read_skip_whitespace( reader
);
1177 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) return WS_E_INVALID_FORMAT
;
1178 quote
= read_utf8_char( reader
, &skip
);
1179 read_skip( reader
, 1 );
1182 start
= read_current_ptr( reader
);
1185 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1186 if (ch
== quote
) break;
1187 read_skip( reader
, skip
);
1190 read_skip( reader
, 1 );
1194 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1195 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1196 if (!(utf8
= alloc_utf8_text( NULL
, 0 )))
1204 if (!(utf8
= alloc_utf8_text( NULL
, len
))) goto error
;
1205 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
) goto error
;
1208 attr
->value
= &utf8
->text
;
1209 attr
->singleQuote
= (quote
== '\'');
1217 static inline BOOL
is_text_type( unsigned char type
)
1219 return (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
);
1222 static HRESULT
read_int31( struct reader
*reader
, ULONG
*len
)
1227 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1229 if (!(byte
& 0x80)) return S_OK
;
1231 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1232 *len
+= (byte
& 0x7f) << 7;
1233 if (!(byte
& 0x80)) return S_OK
;
1235 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1236 *len
+= (byte
& 0x7f) << 14;
1237 if (!(byte
& 0x80)) return S_OK
;
1239 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1240 *len
+= (byte
& 0x7f) << 21;
1241 if (!(byte
& 0x80)) return S_OK
;
1243 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1244 *len
+= (byte
& 0x07) << 28;
1248 static HRESULT
read_string( struct reader
*reader
, WS_XML_STRING
**str
)
1252 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
1253 if (!(*str
= alloc_xml_string( NULL
, len
))) return E_OUTOFMEMORY
;
1254 if ((hr
= read_bytes( reader
, (*str
)->bytes
, len
)) == S_OK
)
1256 if (add_xml_string( *str
) != S_OK
) WARN( "string not added to dictionary\n" );
1259 free_xml_string( *str
);
1263 static HRESULT
read_dict_string( struct reader
*reader
, WS_XML_STRING
**str
)
1265 const WS_XML_DICTIONARY
*dict
;
1269 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1270 dict
= (id
& 1) ? reader
->dict
: reader
->dict_static
;
1271 if (!dict
|| (id
>>= 1) >= dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1272 if (!(*str
= alloc_xml_string( NULL
, 0 ))) return E_OUTOFMEMORY
;
1273 *(*str
) = dict
->strings
[id
];
1277 static HRESULT
read_datetime( struct reader
*reader
, WS_DATETIME
*ret
)
1282 if ((hr
= read_bytes( reader
, (unsigned char *)&val
, sizeof(val
) )) != S_OK
) return hr
;
1284 if ((val
& 0x03) == 1) ret
->format
= WS_DATETIME_FORMAT_UTC
;
1285 else if ((val
& 0x03) == 2) ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
1286 else ret
->format
= WS_DATETIME_FORMAT_NONE
;
1288 if ((ret
->ticks
= val
>> 2) > TICKS_MAX
) return WS_E_INVALID_FORMAT
;
1292 static HRESULT
lookup_string( struct reader
*reader
, ULONG id
, const WS_XML_STRING
**ret
)
1294 const WS_XML_DICTIONARY
*dict
= (id
& 1) ? reader
->dict
: reader
->dict_static
;
1295 if (!dict
|| (id
>>= 1) >= dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1296 *ret
= &dict
->strings
[id
];
1300 static HRESULT
read_attribute_value_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1302 static const unsigned char zero
[] = {'0'}, one
[] = {'1'};
1303 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1304 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1305 WS_XML_BASE64_TEXT
*base64
;
1306 const WS_XML_STRING
*str
;
1307 unsigned char type
, buf
[46];
1317 WS_DATETIME datetime
;
1322 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1323 if (!is_text_type( type
)) return WS_E_INVALID_FORMAT
;
1327 case RECORD_ZERO_TEXT
:
1328 if (!(utf8
= alloc_utf8_text( zero
, sizeof(zero
) ))) return E_OUTOFMEMORY
;
1331 case RECORD_ONE_TEXT
:
1332 if (!(utf8
= alloc_utf8_text( one
, sizeof(one
) ))) return E_OUTOFMEMORY
;
1335 case RECORD_FALSE_TEXT
:
1336 if (!(utf8
= alloc_utf8_text( false, sizeof(false) ))) return E_OUTOFMEMORY
;
1339 case RECORD_TRUE_TEXT
:
1340 if (!(utf8
= alloc_utf8_text( true, sizeof(true) ))) return E_OUTOFMEMORY
;
1343 case RECORD_INT8_TEXT
:
1344 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
1345 len
= format_int8( &val_int8
, buf
);
1346 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1349 case RECORD_INT16_TEXT
:
1350 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
1351 len
= format_int16( &val_int16
, buf
);
1352 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1355 case RECORD_INT32_TEXT
:
1356 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1357 len
= format_int32( &val_int32
, buf
);
1358 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1361 case RECORD_INT64_TEXT
:
1362 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
1363 len
= format_int64( &val_int64
, buf
);
1364 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1367 case RECORD_DOUBLE_TEXT
:
1368 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
1369 len
= format_double( &val_double
, buf
);
1370 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1373 case RECORD_DATETIME_TEXT
:
1374 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
1375 len
= format_datetime( &datetime
, buf
);
1376 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1379 case RECORD_CHARS8_TEXT
:
1380 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1384 case RECORD_CHARS16_TEXT
:
1385 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
1389 case RECORD_CHARS32_TEXT
:
1390 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1391 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1395 case RECORD_BYTES8_TEXT
:
1396 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1397 if (!(base64
= alloc_base64_text( NULL
, val_uint8
))) return E_OUTOFMEMORY
;
1398 if ((hr
= read_bytes( reader
, base64
->bytes
, val_uint8
)) != S_OK
)
1400 heap_free( base64
);
1405 case RECORD_BYTES16_TEXT
:
1406 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
1407 if (!(base64
= alloc_base64_text( NULL
, val_uint16
))) return E_OUTOFMEMORY
;
1408 if ((hr
= read_bytes( reader
, base64
->bytes
, val_uint16
)) != S_OK
)
1410 heap_free( base64
);
1415 case RECORD_BYTES32_TEXT
:
1416 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1417 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1418 if (!(base64
= alloc_base64_text( NULL
, val_int32
))) return E_OUTOFMEMORY
;
1419 if ((hr
= read_bytes( reader
, base64
->bytes
, val_int32
)) != S_OK
)
1421 heap_free( base64
);
1426 case RECORD_EMPTY_TEXT
:
1430 case RECORD_DICTIONARY_TEXT
:
1431 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1432 if ((hr
= lookup_string( reader
, id
, &str
)) != S_OK
) return hr
;
1433 if (!(utf8
= alloc_utf8_text( str
->bytes
, str
->length
))) return E_OUTOFMEMORY
;
1436 case RECORD_UNIQUEID_TEXT
:
1437 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
1438 len
= format_urn( &uuid
, buf
);
1439 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1442 case RECORD_UUID_TEXT
:
1443 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
1444 len
= format_guid( &uuid
, buf
);
1445 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1448 case RECORD_UINT64_TEXT
:
1449 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
1450 len
= format_uint64( &val_uint64
, buf
);
1451 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1454 case RECORD_BOOL_TEXT
:
1455 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
1456 len
= format_bool( &val_bool
, buf
);
1457 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1461 ERR( "unhandled record type %02x\n", type
);
1462 return WS_E_NOT_SUPPORTED
;
1465 if (type
>= RECORD_BYTES8_TEXT
&& type
<= RECORD_BYTES32_TEXT
)
1467 attr
->value
= &base64
->text
;
1473 if (!(utf8
= alloc_utf8_text( NULL
, len
))) return E_OUTOFMEMORY
;
1474 if (!len
) utf8
->value
.bytes
= (BYTE
*)(utf8
+ 1); /* quirk */
1475 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
1482 attr
->value
= &utf8
->text
;
1486 static HRESULT
read_attribute_text( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1488 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1489 WS_XML_ATTRIBUTE
*attr
;
1490 unsigned int len
= 0, ch
, skip
;
1491 const unsigned char *start
;
1492 WS_XML_STRING
*prefix
, *localname
;
1493 HRESULT hr
= WS_E_INVALID_FORMAT
;
1495 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1497 start
= read_current_ptr( reader
);
1500 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1501 if (!read_isnamechar( ch
)) break;
1502 read_skip( reader
, skip
);
1505 if (!len
) goto error
;
1507 if ((hr
= parse_qname( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1508 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1510 free_xml_string( prefix
);
1512 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1514 free_xml_string( localname
);
1518 attr
->localName
= localname
;
1520 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1523 attr
->prefix
= prefix
;
1524 attr
->localName
= localname
;
1528 attr
->prefix
= prefix
;
1529 attr
->localName
= localname
;
1532 if ((hr
= read_attribute_value_text( reader
, attr
)) != S_OK
) goto error
;
1538 free_attribute( attr
);
1542 static inline BOOL
is_attribute_type( unsigned char type
)
1544 return (type
>= RECORD_SHORT_ATTRIBUTE
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
);
1547 static HRESULT
read_attribute_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1549 WS_XML_ATTRIBUTE
*attr
;
1550 unsigned char type
= 0;
1553 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1554 if (!is_attribute_type( type
)) return WS_E_INVALID_FORMAT
;
1555 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1557 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1559 unsigned char ch
= type
- RECORD_PREFIX_ATTRIBUTE_A
+ 'a';
1560 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1565 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1566 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1568 else if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1570 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ 'a';
1571 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1576 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1577 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1583 case RECORD_SHORT_ATTRIBUTE
:
1584 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1589 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1590 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1593 case RECORD_ATTRIBUTE
:
1594 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1595 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1596 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1599 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1600 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1605 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1606 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1609 case RECORD_DICTIONARY_ATTRIBUTE
:
1610 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1611 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1612 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1615 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1616 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1621 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1622 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1626 case RECORD_XMLNS_ATTRIBUTE
:
1627 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1628 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1629 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1633 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1634 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1639 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1640 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1644 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1645 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1646 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1647 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1652 ERR( "unhandled record type %02x\n", type
);
1653 return WS_E_NOT_SUPPORTED
;
1661 free_attribute( attr
);
1665 static inline struct node
*find_parent( struct reader
*reader
)
1667 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1669 if (is_valid_parent( reader
->current
->parent
->parent
)) return reader
->current
->parent
->parent
;
1672 if (is_valid_parent( reader
->current
)) return reader
->current
;
1673 if (is_valid_parent( reader
->current
->parent
)) return reader
->current
->parent
;
1677 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1679 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1680 const WS_XML_STRING
*ns
;
1683 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1684 if (!(elem
->ns
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
1686 for (i
= 0; i
< elem
->attributeCount
; i
++)
1688 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1689 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1690 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1691 if (!(attr
->ns
= alloc_xml_string( NULL
, ns
->length
))) return E_OUTOFMEMORY
;
1692 if (attr
->ns
->length
) memcpy( attr
->ns
->bytes
, ns
->bytes
, ns
->length
);
1697 static WS_XML_ELEMENT_NODE
*alloc_element_pair(void)
1699 struct node
*node
, *end
;
1700 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
1701 if (!(end
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
)))
1706 list_add_tail( &node
->children
, &end
->entry
);
1711 static HRESULT
read_attributes_text( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1713 WS_XML_ATTRIBUTE
*attr
;
1716 reader
->current_attr
= 0;
1719 read_skip_whitespace( reader
);
1720 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1721 if ((hr
= read_attribute_text( reader
, &attr
)) != S_OK
) return hr
;
1722 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1724 free_attribute( attr
);
1727 reader
->current_attr
++;
1732 static HRESULT
read_element_text( struct reader
*reader
)
1734 unsigned int len
= 0, ch
, skip
;
1735 const unsigned char *start
;
1736 struct node
*node
= NULL
, *parent
;
1737 WS_XML_ELEMENT_NODE
*elem
;
1738 HRESULT hr
= WS_E_INVALID_FORMAT
;
1740 if (read_end_of_data( reader
))
1742 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1743 reader
->last
= reader
->current
;
1744 reader
->state
= READER_STATE_EOF
;
1748 if (read_cmp( reader
, "<", 1 )) return WS_E_INVALID_FORMAT
;
1749 read_skip( reader
, 1 );
1750 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1752 read_rewind( reader
, 1 );
1753 return WS_E_INVALID_FORMAT
;
1756 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1757 node
= (struct node
*)elem
;
1759 start
= read_current_ptr( reader
);
1762 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1763 if (!read_isnamechar( ch
)) break;
1764 read_skip( reader
, skip
);
1767 if (!len
) goto error
;
1769 if (!(parent
= find_parent( reader
))) goto error
;
1770 if ((hr
= parse_qname( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1771 if ((hr
= read_attributes_text( reader
, elem
)) != S_OK
) goto error
;
1772 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1774 read_insert_node( reader
, parent
, node
);
1775 reader
->state
= READER_STATE_STARTELEMENT
;
1779 destroy_nodes( node
);
1783 static inline BOOL
is_element_type( unsigned char type
)
1785 return (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
);
1788 static HRESULT
read_attributes_bin( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1790 WS_XML_ATTRIBUTE
*attr
;
1794 reader
->current_attr
= 0;
1797 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
1798 if (!is_attribute_type( type
)) break;
1799 if ((hr
= read_attribute_bin( reader
, &attr
)) != S_OK
) return hr
;
1800 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1802 free_attribute( attr
);
1805 reader
->current_attr
++;
1810 static HRESULT
read_element_bin( struct reader
*reader
)
1812 struct node
*node
= NULL
, *parent
;
1813 WS_XML_ELEMENT_NODE
*elem
;
1817 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1818 if (!is_element_type( type
)) return WS_E_INVALID_FORMAT
;
1820 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1821 node
= (struct node
*)elem
;
1823 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1825 unsigned char ch
= type
- RECORD_PREFIX_ELEMENT_A
+ 'a';
1826 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1831 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1833 else if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1835 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ 'a';
1836 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1841 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1847 case RECORD_SHORT_ELEMENT
:
1848 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1853 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1856 case RECORD_ELEMENT
:
1857 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1858 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1861 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1862 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1867 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1870 case RECORD_DICTIONARY_ELEMENT
:
1871 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1872 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1876 ERR( "unhandled record type %02x\n", type
);
1877 return WS_E_NOT_SUPPORTED
;
1881 if (!(parent
= find_parent( reader
)))
1883 hr
= WS_E_INVALID_FORMAT
;
1887 if ((hr
= read_attributes_bin( reader
, elem
)) != S_OK
) goto error
;
1888 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1890 read_insert_node( reader
, parent
, node
);
1891 reader
->state
= READER_STATE_STARTELEMENT
;
1895 destroy_nodes( node
);
1899 static HRESULT
read_text_text( struct reader
*reader
)
1901 unsigned int len
= 0, ch
, skip
;
1902 const unsigned char *start
;
1903 struct node
*node
, *parent
;
1904 WS_XML_TEXT_NODE
*text
;
1905 WS_XML_UTF8_TEXT
*utf8
;
1908 start
= read_current_ptr( reader
);
1911 if (read_end_of_data( reader
)) break;
1912 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1913 if (ch
== '<') break;
1914 read_skip( reader
, skip
);
1918 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1920 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1921 text
= (WS_XML_TEXT_NODE
*)node
;
1922 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
1925 return E_OUTOFMEMORY
;
1927 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1933 text
->text
= &utf8
->text
;
1935 read_insert_node( reader
, parent
, node
);
1936 reader
->state
= READER_STATE_TEXT
;
1937 reader
->text_conv_offset
= 0;
1941 static struct node
*alloc_utf8_text_node( const BYTE
*data
, ULONG len
, WS_XML_UTF8_TEXT
**ret
)
1944 WS_XML_UTF8_TEXT
*utf8
;
1945 WS_XML_TEXT_NODE
*text
;
1947 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
1948 if (!(utf8
= alloc_utf8_text( data
, len
)))
1953 text
= (WS_XML_TEXT_NODE
*)node
;
1954 text
->text
= &utf8
->text
;
1955 if (ret
) *ret
= utf8
;
1959 static struct node
*alloc_base64_text_node( const BYTE
*data
, ULONG len
, WS_XML_BASE64_TEXT
**ret
)
1962 WS_XML_BASE64_TEXT
*base64
;
1963 WS_XML_TEXT_NODE
*text
;
1965 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
1966 if (!(base64
= alloc_base64_text( data
, len
)))
1971 text
= (WS_XML_TEXT_NODE
*)node
;
1972 text
->text
= &base64
->text
;
1973 if (ret
) *ret
= base64
;
1977 static HRESULT
read_text_bin( struct reader
*reader
)
1979 static const unsigned char zero
[] = {'0'}, one
[] = {'1'};
1980 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1981 unsigned char type
, buf
[46];
1982 struct node
*node
= NULL
, *parent
;
1983 WS_XML_UTF8_TEXT
*utf8
;
1984 WS_XML_BASE64_TEXT
*base64
;
1985 const WS_XML_STRING
*str
;
1995 WS_DATETIME datetime
;
2000 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2001 if (!is_text_type( type
) || !(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2005 case RECORD_ZERO_TEXT
:
2006 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2007 if (!(node
= alloc_utf8_text_node( zero
, sizeof(zero
), NULL
))) return E_OUTOFMEMORY
;
2010 case RECORD_ONE_TEXT
:
2011 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2012 if (!(node
= alloc_utf8_text_node( one
, sizeof(one
), NULL
))) return E_OUTOFMEMORY
;
2015 case RECORD_FALSE_TEXT
:
2016 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2017 if (!(node
= alloc_utf8_text_node( false, sizeof(false), NULL
))) return E_OUTOFMEMORY
;
2020 case RECORD_TRUE_TEXT
:
2021 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2022 if (!(node
= alloc_utf8_text_node( true, sizeof(true), NULL
))) return E_OUTOFMEMORY
;
2025 case RECORD_INT8_TEXT
:
2026 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2027 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
2028 len
= format_int8( &val_int8
, buf
);
2029 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2032 case RECORD_INT16_TEXT
:
2033 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2034 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
2035 len
= format_int16( &val_int16
, buf
);
2036 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2039 case RECORD_INT32_TEXT
:
2040 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2041 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2042 len
= format_int32( &val_int32
, buf
);
2043 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2046 case RECORD_INT64_TEXT
:
2047 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2048 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
2049 len
= format_int64( &val_int64
, buf
);
2050 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2053 case RECORD_DOUBLE_TEXT
:
2054 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2055 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
2056 len
= format_double( &val_double
, buf
);
2057 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2060 case RECORD_DATETIME_TEXT
:
2061 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2062 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
2063 len
= format_datetime( &datetime
, buf
);
2064 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2067 case RECORD_CHARS8_TEXT
:
2068 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2069 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
2073 case RECORD_CHARS16_TEXT
:
2074 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2075 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
2079 case RECORD_CHARS32_TEXT
:
2080 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT
:
2081 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2082 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
2086 case RECORD_BYTES8_TEXT
:
2087 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT
:
2088 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
2089 if (!(node
= alloc_base64_text_node( NULL
, val_uint8
, &base64
))) return E_OUTOFMEMORY
;
2090 if ((hr
= read_bytes( reader
, base64
->bytes
, val_uint8
)) != S_OK
)
2097 case RECORD_BYTES16_TEXT
:
2098 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT
:
2099 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
2100 if (!(node
= alloc_base64_text_node( NULL
, val_uint16
, &base64
))) return E_OUTOFMEMORY
;
2101 if ((hr
= read_bytes( reader
, base64
->bytes
, val_uint16
)) != S_OK
)
2108 case RECORD_BYTES32_TEXT
:
2109 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT
:
2110 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2111 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
2112 if (!(node
= alloc_base64_text_node( NULL
, val_int32
, &base64
))) return E_OUTOFMEMORY
;
2113 if ((hr
= read_bytes( reader
, base64
->bytes
, val_int32
)) != S_OK
)
2120 case RECORD_EMPTY_TEXT
:
2121 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT
:
2125 case RECORD_DICTIONARY_TEXT
:
2126 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2127 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
2128 if ((hr
= lookup_string( reader
, id
, &str
)) != S_OK
) return hr
;
2129 if (!(node
= alloc_utf8_text_node( str
->bytes
, str
->length
, NULL
))) return E_OUTOFMEMORY
;
2132 case RECORD_UNIQUEID_TEXT
:
2133 case RECORD_UNIQUEID_TEXT_WITH_ENDELEMENT
:
2134 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2135 len
= format_urn( &uuid
, buf
);
2136 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2139 case RECORD_UUID_TEXT
:
2140 case RECORD_UUID_TEXT_WITH_ENDELEMENT
:
2141 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2142 len
= format_guid( &uuid
, buf
);
2143 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2146 case RECORD_UINT64_TEXT
:
2147 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2148 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
2149 len
= format_uint64( &val_uint64
, buf
);
2150 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2153 case RECORD_BOOL_TEXT
:
2154 case RECORD_BOOL_TEXT_WITH_ENDELEMENT
:
2155 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
2156 len
= format_bool( &val_bool
, buf
);
2157 if (!(node
= alloc_utf8_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2161 ERR( "unhandled record type %02x\n", type
);
2162 return WS_E_NOT_SUPPORTED
;
2167 if (!(node
= alloc_utf8_text_node( NULL
, len
, &utf8
))) return E_OUTOFMEMORY
;
2168 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
2175 if (type
& 1) node
->flags
|= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
;
2176 read_insert_node( reader
, parent
, node
);
2177 reader
->state
= READER_STATE_TEXT
;
2178 reader
->text_conv_offset
= 0;
2182 static HRESULT
read_node_text( struct reader
* );
2184 static HRESULT
read_startelement_text( struct reader
*reader
)
2186 read_skip_whitespace( reader
);
2187 if (!read_cmp( reader
, "/>", 2 ))
2189 read_skip( reader
, 2 );
2190 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->children
), struct node
, entry
);
2191 reader
->last
= reader
->current
;
2192 reader
->state
= READER_STATE_ENDELEMENT
;
2195 else if (!read_cmp( reader
, ">", 1 ))
2197 read_skip( reader
, 1 );
2198 return read_node_text( reader
);
2200 return WS_E_INVALID_FORMAT
;
2203 static HRESULT
read_node_bin( struct reader
* );
2205 static HRESULT
read_startelement_bin( struct reader
*reader
)
2207 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
2208 return read_node_bin( reader
);
2211 static HRESULT
read_startelement( struct reader
*reader
)
2213 switch (reader
->input_enc
)
2215 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_startelement_text( reader
);
2216 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_startelement_bin( reader
);
2218 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2219 return WS_E_NOT_SUPPORTED
;
2223 static HRESULT
read_to_startelement_text( struct reader
*reader
, BOOL
*found
)
2227 switch (reader
->state
)
2229 case READER_STATE_INITIAL
:
2230 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
2233 case READER_STATE_STARTELEMENT
:
2234 if (found
) *found
= TRUE
;
2241 read_skip_whitespace( reader
);
2242 if ((hr
= read_element_text( reader
)) == S_OK
&& found
)
2244 if (reader
->state
== READER_STATE_STARTELEMENT
)
2253 static HRESULT
read_to_startelement_bin( struct reader
*reader
, BOOL
*found
)
2257 if (reader
->state
== READER_STATE_STARTELEMENT
)
2259 if (found
) *found
= TRUE
;
2263 if ((hr
= read_element_bin( reader
)) == S_OK
&& found
)
2265 if (reader
->state
== READER_STATE_STARTELEMENT
)
2274 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
2276 switch (reader
->input_enc
)
2278 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_to_startelement_text( reader
, found
);
2279 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_to_startelement_bin( reader
, found
);
2281 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2282 return WS_E_NOT_SUPPORTED
;
2286 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
2289 if (len1
!= len2
) return 1;
2290 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
2294 static struct node
*find_startelement( struct reader
*reader
, const WS_XML_STRING
*prefix
,
2295 const WS_XML_STRING
*localname
)
2297 struct node
*parent
;
2298 const WS_XML_STRING
*str
;
2300 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
2302 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2304 str
= parent
->hdr
.prefix
;
2305 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
2306 str
= parent
->hdr
.localName
;
2307 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
2314 static HRESULT
read_endelement_text( struct reader
*reader
)
2316 struct node
*parent
;
2317 unsigned int len
= 0, ch
, skip
;
2318 const unsigned char *start
;
2319 WS_XML_STRING prefix
, localname
;
2322 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
2323 read_skip( reader
, 2 );
2325 start
= read_current_ptr( reader
);
2328 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2331 read_skip( reader
, 1 );
2334 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
2335 read_skip( reader
, skip
);
2339 if ((hr
= split_qname( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
2340 if (!(parent
= find_startelement( reader
, &prefix
, &localname
))) return WS_E_INVALID_FORMAT
;
2342 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2343 reader
->last
= reader
->current
;
2344 reader
->state
= READER_STATE_ENDELEMENT
;
2348 static HRESULT
read_endelement_bin( struct reader
*reader
)
2350 struct node
*parent
;
2354 if (!(reader
->current
->flags
& NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
))
2356 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2357 if (type
!= RECORD_ENDELEMENT
) return WS_E_INVALID_FORMAT
;
2359 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2361 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2362 reader
->last
= reader
->current
;
2363 reader
->state
= READER_STATE_ENDELEMENT
;
2367 static HRESULT
read_endelement( struct reader
*reader
)
2369 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
2371 if (read_end_of_data( reader
))
2373 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2374 reader
->last
= reader
->current
;
2375 reader
->state
= READER_STATE_EOF
;
2379 switch (reader
->input_enc
)
2381 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_endelement_text( reader
);
2382 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_endelement_bin( reader
);
2384 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2385 return WS_E_NOT_SUPPORTED
;
2389 static HRESULT
read_comment_text( struct reader
*reader
)
2391 unsigned int len
= 0, ch
, skip
;
2392 const unsigned char *start
;
2393 struct node
*node
, *parent
;
2394 WS_XML_COMMENT_NODE
*comment
;
2396 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
2397 read_skip( reader
, 4 );
2399 start
= read_current_ptr( reader
);
2402 if (!read_cmp( reader
, "-->", 3 ))
2404 read_skip( reader
, 3 );
2407 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2408 read_skip( reader
, skip
);
2412 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2414 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2415 comment
= (WS_XML_COMMENT_NODE
*)node
;
2416 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2419 return E_OUTOFMEMORY
;
2421 memcpy( comment
->value
.bytes
, start
, len
);
2422 comment
->value
.length
= len
;
2424 read_insert_node( reader
, parent
, node
);
2425 reader
->state
= READER_STATE_COMMENT
;
2429 static HRESULT
read_comment_bin( struct reader
*reader
)
2431 struct node
*node
, *parent
;
2432 WS_XML_COMMENT_NODE
*comment
;
2437 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2438 if (type
!= RECORD_COMMENT
) return WS_E_INVALID_FORMAT
;
2439 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
2441 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2443 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2444 comment
= (WS_XML_COMMENT_NODE
*)node
;
2445 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2448 return E_OUTOFMEMORY
;
2450 if ((hr
= read_bytes( reader
, comment
->value
.bytes
, len
)) != S_OK
)
2453 return E_OUTOFMEMORY
;
2455 comment
->value
.length
= len
;
2457 read_insert_node( reader
, parent
, node
);
2458 reader
->state
= READER_STATE_COMMENT
;
2462 static HRESULT
read_startcdata( struct reader
*reader
)
2464 struct node
*node
, *endnode
, *parent
;
2466 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
2467 read_skip( reader
, 9 );
2469 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2471 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2472 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
)))
2475 return E_OUTOFMEMORY
;
2477 list_add_tail( &node
->children
, &endnode
->entry
);
2478 endnode
->parent
= node
;
2480 read_insert_node( reader
, parent
, node
);
2481 reader
->state
= READER_STATE_STARTCDATA
;
2485 static HRESULT
read_cdata( struct reader
*reader
)
2487 unsigned int len
= 0, ch
, skip
;
2488 const unsigned char *start
;
2490 WS_XML_TEXT_NODE
*text
;
2491 WS_XML_UTF8_TEXT
*utf8
;
2493 start
= read_current_ptr( reader
);
2496 if (!read_cmp( reader
, "]]>", 3 )) break;
2497 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2498 read_skip( reader
, skip
);
2502 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2503 text
= (WS_XML_TEXT_NODE
*)node
;
2504 if (!(utf8
= alloc_utf8_text( start
, len
)))
2507 return E_OUTOFMEMORY
;
2509 text
->text
= &utf8
->text
;
2511 read_insert_node( reader
, reader
->current
, node
);
2512 reader
->state
= READER_STATE_CDATA
;
2516 static HRESULT
read_endcdata( struct reader
*reader
)
2518 struct node
*parent
;
2520 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
2521 read_skip( reader
, 3 );
2523 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
) parent
= reader
->current
->parent
;
2524 else parent
= reader
->current
;
2526 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2527 reader
->last
= reader
->current
;
2528 reader
->state
= READER_STATE_ENDCDATA
;
2532 static HRESULT
read_node_text( struct reader
*reader
)
2538 if (read_end_of_data( reader
))
2540 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2541 reader
->last
= reader
->current
;
2542 reader
->state
= READER_STATE_EOF
;
2545 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
2546 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
2547 else if (!read_cmp( reader
, "<?", 2 ))
2549 hr
= read_xmldecl( reader
);
2550 if (FAILED( hr
)) return hr
;
2552 else if (!read_cmp( reader
, "</", 2 )) return read_endelement_text( reader
);
2553 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
2554 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment_text( reader
);
2555 else if (!read_cmp( reader
, "<", 1 )) return read_element_text( reader
);
2556 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement_text( reader
);
2557 else return read_text_text( reader
);
2561 static HRESULT
read_node_bin( struct reader
*reader
)
2566 if (reader
->current
->flags
& NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
)
2568 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->parent
->children
), struct node
, entry
);
2569 reader
->last
= reader
->current
;
2570 reader
->state
= READER_STATE_ENDELEMENT
;
2573 if (read_end_of_data( reader
))
2575 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2576 reader
->last
= reader
->current
;
2577 reader
->state
= READER_STATE_EOF
;
2581 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
2582 if (type
== RECORD_ENDELEMENT
)
2584 return read_endelement_bin( reader
);
2586 else if (type
== RECORD_COMMENT
)
2588 return read_comment_bin( reader
);
2590 else if (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
2592 return read_element_bin( reader
);
2594 else if (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
)
2596 return read_text_bin( reader
);
2598 FIXME( "unhandled record type %02x\n", type
);
2599 return WS_E_NOT_SUPPORTED
;
2602 static HRESULT
read_node( struct reader
*reader
)
2604 switch (reader
->input_enc
)
2606 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_node_text( reader
);
2607 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_node_bin( reader
);
2609 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2610 return WS_E_NOT_SUPPORTED
;
2614 HRESULT
copy_node( WS_XML_READER
*handle
, struct node
**node
)
2616 struct reader
*reader
= (struct reader
*)handle
;
2617 const struct list
*ptr
;
2618 const struct node
*start
;
2621 EnterCriticalSection( &reader
->cs
);
2623 if (reader
->magic
!= READER_MAGIC
)
2625 LeaveCriticalSection( &reader
->cs
);
2626 return E_INVALIDARG
;
2629 if (reader
->current
!= reader
->root
) ptr
= &reader
->current
->entry
;
2630 else /* copy whole tree */
2632 if (!read_end_of_data( reader
))
2636 if ((hr
= read_node( reader
)) != S_OK
) goto done
;
2637 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) break;
2640 ptr
= list_head( &reader
->root
->children
);
2643 start
= LIST_ENTRY( ptr
, struct node
, entry
);
2644 if (node_type( start
) == WS_XML_NODE_TYPE_EOF
) hr
= WS_E_INVALID_OPERATION
;
2645 else hr
= dup_tree( node
, start
);
2648 LeaveCriticalSection( &reader
->cs
);
2652 /**************************************************************************
2653 * WsReadEndElement [webservices.@]
2655 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2657 struct reader
*reader
= (struct reader
*)handle
;
2660 TRACE( "%p %p\n", handle
, error
);
2661 if (error
) FIXME( "ignoring error parameter\n" );
2663 if (!reader
) return E_INVALIDARG
;
2665 EnterCriticalSection( &reader
->cs
);
2667 if (reader
->magic
!= READER_MAGIC
)
2669 LeaveCriticalSection( &reader
->cs
);
2670 return E_INVALIDARG
;
2673 hr
= read_endelement( reader
);
2675 LeaveCriticalSection( &reader
->cs
);
2679 /**************************************************************************
2680 * WsReadNode [webservices.@]
2682 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2684 struct reader
*reader
= (struct reader
*)handle
;
2687 TRACE( "%p %p\n", handle
, error
);
2688 if (error
) FIXME( "ignoring error parameter\n" );
2690 if (!reader
) return E_INVALIDARG
;
2692 EnterCriticalSection( &reader
->cs
);
2694 if (reader
->magic
!= READER_MAGIC
)
2696 LeaveCriticalSection( &reader
->cs
);
2697 return E_INVALIDARG
;
2700 hr
= read_node( reader
);
2702 LeaveCriticalSection( &reader
->cs
);
2706 static HRESULT
skip_node( struct reader
*reader
)
2708 const struct node
*parent
;
2711 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) return WS_E_INVALID_OPERATION
;
2712 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_ELEMENT
) parent
= reader
->current
;
2717 if ((hr
= read_node( reader
) != S_OK
) || !parent
) break;
2718 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_END_ELEMENT
) continue;
2719 if (reader
->current
->parent
== parent
) return read_node( reader
);
2725 /**************************************************************************
2726 * WsSkipNode [webservices.@]
2728 HRESULT WINAPI
WsSkipNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2730 struct reader
*reader
= (struct reader
*)handle
;
2733 TRACE( "%p %p\n", handle
, error
);
2734 if (error
) FIXME( "ignoring error parameter\n" );
2736 if (!reader
) return E_INVALIDARG
;
2738 EnterCriticalSection( &reader
->cs
);
2740 if (reader
->magic
!= READER_MAGIC
)
2742 LeaveCriticalSection( &reader
->cs
);
2743 return E_INVALIDARG
;
2746 hr
= skip_node( reader
);
2748 LeaveCriticalSection( &reader
->cs
);
2752 /**************************************************************************
2753 * WsReadStartElement [webservices.@]
2755 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2757 struct reader
*reader
= (struct reader
*)handle
;
2760 TRACE( "%p %p\n", handle
, error
);
2761 if (error
) FIXME( "ignoring error parameter\n" );
2763 if (!reader
) return E_INVALIDARG
;
2765 EnterCriticalSection( &reader
->cs
);
2767 if (reader
->magic
!= READER_MAGIC
)
2769 LeaveCriticalSection( &reader
->cs
);
2770 return E_INVALIDARG
;
2773 hr
= read_startelement( reader
);
2775 LeaveCriticalSection( &reader
->cs
);
2779 /**************************************************************************
2780 * WsReadToStartElement [webservices.@]
2782 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2783 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
2785 struct reader
*reader
= (struct reader
*)handle
;
2788 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
2789 if (error
) FIXME( "ignoring error parameter\n" );
2791 if (!reader
) return E_INVALIDARG
;
2792 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
2794 EnterCriticalSection( &reader
->cs
);
2796 if (reader
->magic
!= READER_MAGIC
)
2798 LeaveCriticalSection( &reader
->cs
);
2799 return E_INVALIDARG
;
2802 hr
= read_to_startelement( reader
, found
);
2804 LeaveCriticalSection( &reader
->cs
);
2808 BOOL
move_to_root_element( struct node
*root
, struct node
**current
)
2813 if (!(ptr
= list_head( &root
->children
))) return FALSE
;
2814 node
= LIST_ENTRY( ptr
, struct node
, entry
);
2815 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
2820 while ((ptr
= list_next( &root
->children
, &node
->entry
)))
2822 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2823 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2833 BOOL
move_to_next_element( struct node
**current
)
2836 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2838 if (!parent
) return FALSE
;
2839 while ((ptr
= list_next( &parent
->children
, &node
->entry
)))
2841 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2842 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2852 BOOL
move_to_prev_element( struct node
**current
)
2855 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2857 if (!parent
) return FALSE
;
2858 while ((ptr
= list_prev( &parent
->children
, &node
->entry
)))
2860 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
2861 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
2871 BOOL
move_to_child_element( struct node
**current
)
2874 struct node
*child
, *node
= *current
;
2876 if (!(ptr
= list_head( &node
->children
))) return FALSE
;
2877 child
= LIST_ENTRY( ptr
, struct node
, entry
);
2878 if (node_type( child
) == WS_XML_NODE_TYPE_ELEMENT
)
2883 while ((ptr
= list_next( &node
->children
, &child
->entry
)))
2885 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2886 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2896 BOOL
move_to_end_element( struct node
**current
)
2899 struct node
*node
= *current
;
2901 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
2903 if ((ptr
= list_tail( &node
->children
)))
2905 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
2906 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
2915 BOOL
move_to_parent_element( struct node
**current
)
2917 struct node
*parent
= (*current
)->parent
;
2919 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
2920 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
2928 BOOL
move_to_first_node( struct node
**current
)
2931 struct node
*node
= *current
;
2933 if ((ptr
= list_head( &node
->parent
->children
)))
2935 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2941 BOOL
move_to_next_node( struct node
**current
)
2944 struct node
*node
= *current
;
2946 if ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
2948 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2954 BOOL
move_to_prev_node( struct node
**current
)
2957 struct node
*node
= *current
;
2959 if ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
2961 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2967 BOOL
move_to_bof( struct node
*root
, struct node
**current
)
2973 BOOL
move_to_eof( struct node
*root
, struct node
**current
)
2976 if ((ptr
= list_tail( &root
->children
)))
2978 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2984 BOOL
move_to_child_node( struct node
**current
)
2987 struct node
*node
= *current
;
2989 if ((ptr
= list_head( &node
->children
)))
2991 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2997 BOOL
move_to_parent_node( struct node
**current
)
2999 struct node
*parent
= (*current
)->parent
;
3000 if (!parent
) return FALSE
;
3005 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
3007 BOOL success
= FALSE
;
3010 if (!read_end_of_data( reader
))
3012 struct node
*saved_current
= reader
->current
;
3013 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
3014 if (hr
!= S_OK
) return hr
;
3015 reader
->current
= saved_current
;
3019 case WS_MOVE_TO_ROOT_ELEMENT
:
3020 success
= move_to_root_element( reader
->root
, &reader
->current
);
3023 case WS_MOVE_TO_NEXT_ELEMENT
:
3024 success
= move_to_next_element( &reader
->current
);
3027 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
3028 success
= move_to_prev_element( &reader
->current
);
3031 case WS_MOVE_TO_CHILD_ELEMENT
:
3032 success
= move_to_child_element( &reader
->current
);
3035 case WS_MOVE_TO_END_ELEMENT
:
3036 success
= move_to_end_element( &reader
->current
);
3039 case WS_MOVE_TO_PARENT_ELEMENT
:
3040 success
= move_to_parent_element( &reader
->current
);
3043 case WS_MOVE_TO_FIRST_NODE
:
3044 success
= move_to_first_node( &reader
->current
);
3047 case WS_MOVE_TO_NEXT_NODE
:
3048 success
= move_to_next_node( &reader
->current
);
3051 case WS_MOVE_TO_PREVIOUS_NODE
:
3052 success
= move_to_prev_node( &reader
->current
);
3055 case WS_MOVE_TO_CHILD_NODE
:
3056 success
= move_to_child_node( &reader
->current
);
3059 case WS_MOVE_TO_BOF
:
3060 success
= move_to_bof( reader
->root
, &reader
->current
);
3063 case WS_MOVE_TO_EOF
:
3064 success
= move_to_eof( reader
->root
, &reader
->current
);
3068 FIXME( "unhandled move %u\n", move
);
3077 return success
? S_OK
: WS_E_INVALID_FORMAT
;
3080 /**************************************************************************
3081 * WsMoveReader [webservices.@]
3083 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
3085 struct reader
*reader
= (struct reader
*)handle
;
3088 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
3089 if (error
) FIXME( "ignoring error parameter\n" );
3091 if (!reader
) return E_INVALIDARG
;
3093 EnterCriticalSection( &reader
->cs
);
3095 if (reader
->magic
!= READER_MAGIC
)
3097 LeaveCriticalSection( &reader
->cs
);
3098 return E_INVALIDARG
;
3101 if (!reader
->input_type
)
3103 LeaveCriticalSection( &reader
->cs
);
3104 return WS_E_INVALID_OPERATION
;
3107 hr
= read_move_to( reader
, move
, found
);
3109 LeaveCriticalSection( &reader
->cs
);
3113 /**************************************************************************
3114 * WsReadStartAttribute [webservices.@]
3116 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
3118 struct reader
*reader
= (struct reader
*)handle
;
3119 const WS_XML_ELEMENT_NODE
*elem
;
3121 TRACE( "%p %u %p\n", handle
, index
, error
);
3122 if (error
) FIXME( "ignoring error parameter\n" );
3124 if (!reader
) return E_INVALIDARG
;
3126 EnterCriticalSection( &reader
->cs
);
3128 if (reader
->magic
!= READER_MAGIC
)
3130 LeaveCriticalSection( &reader
->cs
);
3131 return E_INVALIDARG
;
3134 elem
= &reader
->current
->hdr
;
3135 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
3137 LeaveCriticalSection( &reader
->cs
);
3138 return WS_E_INVALID_FORMAT
;
3141 reader
->current_attr
= index
;
3142 reader
->state
= READER_STATE_STARTATTRIBUTE
;
3144 LeaveCriticalSection( &reader
->cs
);
3148 /**************************************************************************
3149 * WsReadEndAttribute [webservices.@]
3151 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
3153 struct reader
*reader
= (struct reader
*)handle
;
3155 TRACE( "%p %p\n", handle
, error
);
3156 if (error
) FIXME( "ignoring error parameter\n" );
3158 if (!reader
) return E_INVALIDARG
;
3160 EnterCriticalSection( &reader
->cs
);
3162 if (reader
->magic
!= READER_MAGIC
)
3164 LeaveCriticalSection( &reader
->cs
);
3165 return E_INVALIDARG
;
3168 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
3170 LeaveCriticalSection( &reader
->cs
);
3171 return WS_E_INVALID_FORMAT
;
3174 reader
->state
= READER_STATE_STARTELEMENT
;
3176 LeaveCriticalSection( &reader
->cs
);
3180 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
3184 switch (text
->textType
)
3186 case WS_XML_TEXT_TYPE_UTF8
:
3188 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
3189 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
3190 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
3191 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
3196 FIXME( "unhandled type %u\n", text
->textType
);
3203 #define MAX_INT8 0x7f
3204 #define MIN_INT8 (-MAX_INT8 - 1)
3205 #define MAX_INT16 0x7fff
3206 #define MIN_INT16 (-MAX_INT16 - 1)
3207 #define MAX_INT32 0x7fffffff
3208 #define MIN_INT32 (-MAX_INT32 - 1)
3209 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
3210 #define MIN_INT64 (-MAX_INT64 - 1)
3211 #define MAX_UINT8 0xff
3212 #define MAX_UINT16 0xffff
3213 #define MAX_UINT32 0xffffffff
3214 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
3216 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
3218 BOOL negative
= FALSE
;
3219 const unsigned char *ptr
= str
;
3222 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3223 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3224 if (!len
) return WS_E_INVALID_FORMAT
;
3232 if (!len
) return WS_E_INVALID_FORMAT
;
3238 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3240 if (negative
) val
= -val
;
3242 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
3243 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
3245 return WS_E_NUMERIC_OVERFLOW
;
3247 *ret
= *ret
* 10 + val
;
3254 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
3256 const unsigned char *ptr
= str
;
3259 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3260 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3261 if (!len
) return WS_E_INVALID_FORMAT
;
3267 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3270 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
3271 *ret
= *ret
* 10 + val
;
3278 BOOL
set_fpword( unsigned short new, unsigned short *old
)
3280 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3281 unsigned short fpword
;
3283 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
3286 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3289 FIXME( "not implemented\n" );
3294 void restore_fpword( unsigned short fpword
)
3296 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3297 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3299 FIXME( "not implemented\n" );
3303 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
3305 static const unsigned __int64 nan
= 0xfff8000000000000;
3306 static const unsigned __int64 inf
= 0x7ff0000000000000;
3307 static const unsigned __int64 inf_min
= 0xfff0000000000000;
3308 HRESULT hr
= WS_E_INVALID_FORMAT
;
3309 const unsigned char *p
= str
, *q
;
3310 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
3311 unsigned __int64 val
= 0, tmp
;
3312 long double exp_val
= 1.0, exp_mul
= 10.0;
3313 unsigned short fpword
;
3315 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3316 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3317 if (!len
) return WS_E_INVALID_FORMAT
;
3319 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
3321 *(unsigned __int64
*)ret
= nan
;
3324 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
3326 *(unsigned __int64
*)ret
= inf
;
3329 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
3331 *(unsigned __int64
*)ret
= inf_min
;
3341 else if (*p
== '+') { p
++; len
--; };
3342 if (!len
) return S_OK
;
3344 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
3347 while (len
&& isdigit( *q
)) { q
++; len
--; }
3348 have_digits
= nb_digits
= q
- p
;
3349 for (i
= 0; i
< nb_digits
; i
++)
3351 tmp
= val
* 10 + p
[i
] - '0';
3352 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
3354 for (; i
< nb_digits
; i
++) exp
++;
3365 while (len
&& isdigit( *q
)) { q
++; len
--; };
3366 have_digits
|= nb_digits
= q
- p
;
3367 for (i
= 0; i
< nb_digits
; i
++)
3369 tmp
= val
* 10 + p
[i
] - '0';
3370 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
3375 if (len
> 1 && tolower(*q
) == 'e')
3377 if (!have_digits
) goto done
;
3384 else if (*p
== '+') { p
++; len
--; };
3387 while (len
&& isdigit( *q
)) { q
++; len
--; };
3389 if (!nb_digits
|| len
) goto done
;
3390 for (i
= 0; i
< nb_digits
; i
++)
3392 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
3393 exp_tmp
= MAX_INT32
;
3395 exp_tmp
*= exp_sign
;
3397 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
3398 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
3399 else exp
+= exp_tmp
;
3402 if (!have_digits
|| len
) goto done
;
3404 if ((neg_exp
= exp
< 0)) exp
= -exp
;
3405 for (; exp
; exp
>>= 1)
3407 if (exp
& 1) exp_val
*= exp_mul
;
3411 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
3415 restore_fpword( fpword
);
3419 static HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
3421 static const unsigned char hex
[] =
3423 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3424 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3425 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3426 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3427 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3428 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3429 0,10,11,12,13,14,15 /* 0x60 */
3431 const unsigned char *p
= str
;
3434 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3435 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3436 if (len
!= 36) return WS_E_INVALID_FORMAT
;
3438 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
3439 return WS_E_INVALID_FORMAT
;
3441 for (i
= 0; i
< 36; i
++)
3443 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
3444 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
3447 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
3448 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
3450 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
3451 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
3453 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
3454 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
3455 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
3456 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
3457 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
3458 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
3459 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
3460 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
3465 static HRESULT
str_to_string( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_STRING
*ret
)
3467 int len_utf16
= MultiByteToWideChar( CP_UTF8
, 0, (const char *)str
, len
, NULL
, 0 );
3468 if (!(ret
->chars
= ws_alloc( heap
, len_utf16
* sizeof(WCHAR
) ))) return WS_E_QUOTA_EXCEEDED
;
3469 MultiByteToWideChar( CP_UTF8
, 0, (const char *)str
, len
, ret
->chars
, len_utf16
);
3470 ret
->length
= len_utf16
;
3474 static HRESULT
str_to_unique_id( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_UNIQUE_ID
*ret
)
3476 if (len
== 45 && !memcmp( str
, "urn:uuid:", 9 ))
3478 ret
->uri
.length
= 0;
3479 ret
->uri
.chars
= NULL
;
3480 return str_to_guid( str
+ 9, len
- 9, &ret
->guid
);
3483 memset( &ret
->guid
, 0, sizeof(ret
->guid
) );
3484 return str_to_string( str
, len
, heap
, &ret
->uri
);
3487 static inline unsigned char decode_char( unsigned char c
)
3489 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
3490 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
3491 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
3492 if (c
== '+') return 62;
3493 if (c
== '/') return 63;
3497 static ULONG
decode_base64( const unsigned char *base64
, ULONG len
, unsigned char *buf
)
3500 unsigned char c0
, c1
, c2
, c3
;
3501 const unsigned char *p
= base64
;
3505 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3506 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3507 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3508 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3509 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3510 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3511 buf
[i
+ 2] = (c2
<< 6) | c3
;
3518 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3519 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3520 buf
[i
] = (c0
<< 2) | (c1
>> 4);
3523 else if (p
[3] == '=')
3525 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3526 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3527 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3528 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3529 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3534 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3535 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3536 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3537 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3538 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3539 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3540 buf
[i
+ 2] = (c2
<< 6) | c3
;
3546 static HRESULT
str_to_bytes( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_BYTES
*ret
)
3548 const unsigned char *p
= str
;
3550 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3551 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3553 if (len
% 4) return WS_E_INVALID_FORMAT
;
3554 if (!(ret
->bytes
= ws_alloc( heap
, len
* 3 / 4 ))) return WS_E_QUOTA_EXCEEDED
;
3555 ret
->length
= decode_base64( p
, len
, ret
->bytes
);
3559 static HRESULT
str_to_xml_string( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_XML_STRING
*ret
)
3561 if (!(ret
->bytes
= ws_alloc( heap
, len
))) return WS_E_QUOTA_EXCEEDED
;
3562 memcpy( ret
->bytes
, str
, len
);
3564 ret
->dictionary
= NULL
;
3569 static HRESULT
copy_xml_string( WS_HEAP
*heap
, const WS_XML_STRING
*src
, WS_XML_STRING
*dst
)
3571 if (!(dst
->bytes
= ws_alloc( heap
, src
->length
))) return WS_E_QUOTA_EXCEEDED
;
3572 memcpy( dst
->bytes
, src
->bytes
, src
->length
);
3573 dst
->length
= src
->length
;
3577 static HRESULT
str_to_qname( struct reader
*reader
, const unsigned char *str
, ULONG len
, WS_HEAP
*heap
,
3578 WS_XML_STRING
*prefix_ret
, WS_XML_STRING
*localname_ret
, WS_XML_STRING
*ns_ret
)
3580 const unsigned char *p
= str
;
3581 WS_XML_STRING prefix
, localname
;
3582 const WS_XML_STRING
*ns
;
3585 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3586 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3588 if ((hr
= split_qname( p
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
3589 if (!(ns
= get_namespace( reader
, &prefix
))) return WS_E_INVALID_FORMAT
;
3591 if (prefix_ret
&& (hr
= copy_xml_string( heap
, &prefix
, prefix_ret
)) != S_OK
) return hr
;
3592 if ((hr
= copy_xml_string( heap
, &localname
, localname_ret
)) != S_OK
)
3594 ws_free( heap
, prefix_ret
->bytes
, prefix_ret
->length
);
3597 if ((hr
= copy_xml_string( heap
, ns
, ns_ret
)) != S_OK
)
3599 ws_free( heap
, prefix_ret
->bytes
, prefix_ret
->length
);
3600 ws_free( heap
, localname_ret
->bytes
, localname_ret
->length
);
3606 static HRESULT
read_qualified_name( struct reader
*reader
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
3607 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
)
3609 const WS_XML_TEXT_NODE
*node
= (const WS_XML_TEXT_NODE
*)reader
->current
;
3610 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)node
->text
;
3611 return str_to_qname( reader
, utf8
->value
.bytes
, utf8
->value
.length
, heap
, prefix
, localname
, ns
);
3614 /**************************************************************************
3615 * WsReadQualifiedName [webservices.@]
3617 HRESULT WINAPI
WsReadQualifiedName( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
3618 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
,
3621 struct reader
*reader
= (struct reader
*)handle
;
3624 TRACE( "%p %p %p %p %p %p\n", handle
, heap
, prefix
, localname
, ns
, error
);
3625 if (error
) FIXME( "ignoring error parameter\n" );
3627 if (!reader
|| !heap
) return E_INVALIDARG
;
3629 EnterCriticalSection( &reader
->cs
);
3631 if (reader
->magic
!= READER_MAGIC
)
3633 LeaveCriticalSection( &reader
->cs
);
3634 return E_INVALIDARG
;
3637 if (!reader
->input_type
)
3639 LeaveCriticalSection( &reader
->cs
);
3640 return WS_E_INVALID_OPERATION
;
3645 LeaveCriticalSection( &reader
->cs
);
3646 return E_INVALIDARG
;
3649 if (reader
->state
!= READER_STATE_TEXT
)
3651 LeaveCriticalSection( &reader
->cs
);
3652 return WS_E_INVALID_FORMAT
;
3655 hr
= read_qualified_name( reader
, heap
, prefix
, localname
, ns
);
3657 LeaveCriticalSection( &reader
->cs
);
3661 static const int month_offsets
[2][12] =
3663 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
3664 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
3667 static inline int valid_day( int year
, int month
, int day
)
3669 return day
> 0 && day
<= month_days
[leap_year( year
)][month
- 1];
3672 static inline int leap_days_before( int year
)
3674 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
3677 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
3679 const unsigned char *p
= bytes
, *q
;
3680 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
3682 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3683 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3686 while (len
&& isdigit( *q
)) { q
++; len
--; };
3687 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3688 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
3689 if (year
< 1) return WS_E_INVALID_FORMAT
;
3692 while (len
&& isdigit( *q
)) { q
++; len
--; };
3693 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3694 month
= (p
[0] - '0') * 10 + p
[1] - '0';
3695 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
3698 while (len
&& isdigit( *q
)) { q
++; len
--; };
3699 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
3700 day
= (p
[0] - '0') * 10 + p
[1] - '0';
3701 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
3704 while (len
&& isdigit( *q
)) { q
++; len
--; };
3705 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3706 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3707 if (hour
> 24) return WS_E_INVALID_FORMAT
;
3710 while (len
&& isdigit( *q
)) { q
++; len
--; };
3711 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3712 min
= (p
[0] - '0') * 10 + p
[1] - '0';
3713 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3716 while (len
&& isdigit( *q
)) { q
++; len
--; };
3717 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
3718 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
3719 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3723 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
3725 while (len
&& isdigit( *q
)) { q
++; len
--; };
3727 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
3728 for (i
= 0; i
< nb_digits
; i
++)
3730 sec_frac
+= (p
[i
] - '0') * mul
;
3736 if (--len
) return WS_E_INVALID_FORMAT
;
3737 tz_hour
= tz_min
= tz_neg
= 0;
3738 ret
->format
= WS_DATETIME_FORMAT_UTC
;
3740 else if (*q
== '+' || *q
== '-')
3742 tz_neg
= (*q
== '-') ? 1 : 0;
3745 while (len
&& isdigit( *q
)) { q
++; len
--; };
3746 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3747 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3748 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
3751 while (len
&& isdigit( *q
)) { q
++; len
--; };
3752 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
3753 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
3754 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
3756 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
3758 else return WS_E_INVALID_FORMAT
;
3760 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
3761 ret
->ticks
+= month_offsets
[leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
3762 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
3763 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
3764 ret
->ticks
+= min
* TICKS_PER_MIN
;
3765 ret
->ticks
+= sec
* TICKS_PER_SEC
;
3766 ret
->ticks
+= sec_frac
;
3770 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
3771 return WS_E_INVALID_FORMAT
;
3772 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
3773 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
3777 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
3778 return WS_E_INVALID_FORMAT
;
3779 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
3780 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
3786 /**************************************************************************
3787 * WsDateTimeToFileTime [webservices.@]
3789 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
3791 unsigned __int64 ticks
;
3793 TRACE( "%p %p %p\n", dt
, ft
, error
);
3794 if (error
) FIXME( "ignoring error parameter\n" );
3796 if (!dt
|| !ft
) return E_INVALIDARG
;
3798 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
3799 ticks
= dt
->ticks
- TICKS_1601_01_01
;
3800 ft
->dwHighDateTime
= ticks
>> 32;
3801 ft
->dwLowDateTime
= (DWORD
)ticks
;
3805 /**************************************************************************
3806 * WsFileTimeToDateTime [webservices.@]
3808 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
3810 unsigned __int64 ticks
;
3812 TRACE( "%p %p %p\n", ft
, dt
, error
);
3813 if (error
) FIXME( "ignoring error parameter\n" );
3815 if (!dt
|| !ft
) return E_INVALIDARG
;
3817 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
3818 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
3819 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
3820 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
3821 dt
->format
= WS_DATETIME_FORMAT_UTC
;
3825 static HRESULT
read_get_node_text( struct reader
*reader
, WS_XML_UTF8_TEXT
**ret
)
3827 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
3828 if (node
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3830 FIXME( "text type %u not supported\n", node
->text
->textType
);
3833 *ret
= (WS_XML_UTF8_TEXT
*)node
->text
;
3837 static HRESULT
read_get_attribute_text( struct reader
*reader
, ULONG index
, WS_XML_UTF8_TEXT
**ret
)
3839 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3840 WS_XML_ATTRIBUTE
*attr
;
3842 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
3843 return WS_E_INVALID_FORMAT
;
3845 attr
= elem
->attributes
[index
];
3846 if (attr
->value
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3848 FIXME( "text type %u not supported\n", attr
->value
->textType
);
3851 *ret
= (WS_XML_UTF8_TEXT
*)attr
->value
;
3855 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
3856 const WS_XML_STRING
*ns
, ULONG
*index
)
3859 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3863 *index
= reader
->current_attr
;
3866 for (i
= 0; i
< elem
->attributeCount
; i
++)
3868 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
3869 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
3871 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
3872 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
3881 /**************************************************************************
3882 * WsFindAttribute [webservices.@]
3884 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
3885 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
3888 struct reader
*reader
= (struct reader
*)handle
;
3891 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3892 required
, index
, error
);
3893 if (error
) FIXME( "ignoring error parameter\n" );
3895 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
3897 EnterCriticalSection( &reader
->cs
);
3899 if (reader
->magic
!= READER_MAGIC
)
3901 LeaveCriticalSection( &reader
->cs
);
3902 return E_INVALIDARG
;
3905 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
3907 LeaveCriticalSection( &reader
->cs
);
3908 return WS_E_INVALID_OPERATION
;
3911 if (!find_attribute( reader
, localname
, ns
, index
))
3913 if (required
) hr
= WS_E_INVALID_FORMAT
;
3921 LeaveCriticalSection( &reader
->cs
);
3925 static BOOL
match_element( const struct node
*node
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
3927 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
3928 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
3929 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
3930 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
3933 static HRESULT
read_next_node( struct reader
*reader
)
3935 if (reader
->current
== reader
->last
) return read_node( reader
);
3936 if (move_to_child_node( &reader
->current
)) return S_OK
;
3937 if (move_to_next_node( &reader
->current
)) return S_OK
;
3938 if (!move_to_parent_node( &reader
->current
)) return WS_E_INVALID_FORMAT
;
3939 if (move_to_next_node( &reader
->current
)) return S_OK
;
3940 return WS_E_INVALID_FORMAT
;
3943 static HRESULT
read_get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3944 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3945 WS_XML_UTF8_TEXT
**ret
, BOOL
*found
)
3949 case WS_ATTRIBUTE_TYPE_MAPPING
:
3952 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
3953 return read_get_attribute_text( reader
, index
, ret
);
3955 case WS_ELEMENT_TYPE_MAPPING
:
3956 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3957 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3963 if (!match_element( reader
->current
, localname
, ns
))
3968 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
3969 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
3971 if (!move_to_parent_element( &reader
->current
)) return WS_E_INVALID_FORMAT
;
3976 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
3981 return read_get_node_text( reader
, ret
);
3984 FIXME( "mapping %u not supported\n", mapping
);
3989 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3990 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3991 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3992 WS_HEAP
*heap
, void *ret
, ULONG size
)
3994 WS_XML_UTF8_TEXT
*utf8
;
3996 BOOL found
, val
= FALSE
;
4000 FIXME( "description not supported\n" );
4003 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4006 ULONG len
= utf8
->value
.length
;
4007 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
4008 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
4009 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
4010 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
4011 else return WS_E_INVALID_FORMAT
;
4016 case WS_READ_REQUIRED_VALUE
:
4017 if (!found
) return WS_E_INVALID_FORMAT
;
4020 case WS_READ_NILLABLE_VALUE
:
4021 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4025 case WS_READ_REQUIRED_POINTER
:
4026 if (!found
) return WS_E_INVALID_FORMAT
;
4029 case WS_READ_OPTIONAL_POINTER
:
4030 case WS_READ_NILLABLE_POINTER
:
4032 BOOL
*heap_val
= NULL
;
4033 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4036 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4039 *(BOOL
**)ret
= heap_val
;
4043 FIXME( "read option %u not supported\n", option
);
4050 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4051 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4052 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4053 WS_HEAP
*heap
, void *ret
, ULONG size
)
4055 WS_XML_UTF8_TEXT
*utf8
;
4062 FIXME( "description not supported\n" );
4065 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4066 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
4071 case WS_READ_REQUIRED_VALUE
:
4072 if (!found
) return WS_E_INVALID_FORMAT
;
4075 case WS_READ_NILLABLE_VALUE
:
4076 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
4080 case WS_READ_REQUIRED_POINTER
:
4081 if (!found
) return WS_E_INVALID_FORMAT
;
4084 case WS_READ_OPTIONAL_POINTER
:
4085 case WS_READ_NILLABLE_POINTER
:
4087 INT8
*heap_val
= NULL
;
4088 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4091 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4094 *(INT8
**)ret
= heap_val
;
4098 FIXME( "read option %u not supported\n", option
);
4105 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4106 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4107 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4108 WS_HEAP
*heap
, void *ret
, ULONG size
)
4110 WS_XML_UTF8_TEXT
*utf8
;
4117 FIXME( "description not supported\n" );
4120 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4121 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
4126 case WS_READ_REQUIRED_VALUE
:
4127 if (!found
) return WS_E_INVALID_FORMAT
;
4130 case WS_READ_NILLABLE_VALUE
:
4131 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
4132 *(INT16
*)ret
= val
;
4135 case WS_READ_REQUIRED_POINTER
:
4136 if (!found
) return WS_E_INVALID_FORMAT
;
4139 case WS_READ_OPTIONAL_POINTER
:
4140 case WS_READ_NILLABLE_POINTER
:
4142 INT16
*heap_val
= NULL
;
4143 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4146 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4149 *(INT16
**)ret
= heap_val
;
4153 FIXME( "read option %u not supported\n", option
);
4160 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4161 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4162 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4163 WS_HEAP
*heap
, void *ret
, ULONG size
)
4165 WS_XML_UTF8_TEXT
*utf8
;
4172 FIXME( "description not supported\n" );
4175 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4176 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
4181 case WS_READ_REQUIRED_VALUE
:
4182 if (!found
) return WS_E_INVALID_FORMAT
;
4185 case WS_READ_NILLABLE_VALUE
:
4186 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
4187 *(INT32
*)ret
= val
;
4190 case WS_READ_REQUIRED_POINTER
:
4191 if (!found
) return WS_E_INVALID_FORMAT
;
4194 case WS_READ_OPTIONAL_POINTER
:
4195 case WS_READ_NILLABLE_POINTER
:
4197 INT32
*heap_val
= NULL
;
4198 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4201 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4204 *(INT32
**)ret
= heap_val
;
4208 FIXME( "read option %u not supported\n", option
);
4215 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4216 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4217 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4218 WS_HEAP
*heap
, void *ret
, ULONG size
)
4220 WS_XML_UTF8_TEXT
*utf8
;
4227 FIXME( "description not supported\n" );
4230 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4231 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
4236 case WS_READ_REQUIRED_VALUE
:
4237 if (!found
) return WS_E_INVALID_FORMAT
;
4240 case WS_READ_NILLABLE_VALUE
:
4241 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4242 *(INT64
*)ret
= val
;
4245 case WS_READ_REQUIRED_POINTER
:
4246 if (!found
) return WS_E_INVALID_FORMAT
;
4249 case WS_READ_OPTIONAL_POINTER
:
4250 case WS_READ_NILLABLE_POINTER
:
4252 INT64
*heap_val
= NULL
;
4253 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4256 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4259 *(INT64
**)ret
= heap_val
;
4263 FIXME( "read option %u not supported\n", option
);
4270 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4271 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4272 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4273 WS_HEAP
*heap
, void *ret
, ULONG size
)
4275 WS_XML_UTF8_TEXT
*utf8
;
4282 FIXME( "description not supported\n" );
4285 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4286 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
4291 case WS_READ_REQUIRED_VALUE
:
4292 if (!found
) return WS_E_INVALID_FORMAT
;
4295 case WS_READ_NILLABLE_VALUE
:
4296 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
4297 *(UINT8
*)ret
= val
;
4300 case WS_READ_REQUIRED_POINTER
:
4301 if (!found
) return WS_E_INVALID_FORMAT
;
4304 case WS_READ_OPTIONAL_POINTER
:
4305 case WS_READ_NILLABLE_POINTER
:
4307 UINT8
*heap_val
= NULL
;
4308 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4311 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4314 *(UINT8
**)ret
= heap_val
;
4318 FIXME( "read option %u not supported\n", option
);
4325 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4326 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4327 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4328 WS_HEAP
*heap
, void *ret
, ULONG size
)
4330 WS_XML_UTF8_TEXT
*utf8
;
4337 FIXME( "description not supported\n" );
4340 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4341 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
4346 case WS_READ_REQUIRED_VALUE
:
4347 if (!found
) return WS_E_INVALID_FORMAT
;
4350 case WS_READ_NILLABLE_VALUE
:
4351 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
4352 *(UINT16
*)ret
= val
;
4355 case WS_READ_REQUIRED_POINTER
:
4356 if (!found
) return WS_E_INVALID_FORMAT
;
4359 case WS_READ_OPTIONAL_POINTER
:
4360 case WS_READ_NILLABLE_POINTER
:
4362 UINT16
*heap_val
= NULL
;
4363 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4366 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4369 *(UINT16
**)ret
= heap_val
;
4373 FIXME( "read option %u not supported\n", option
);
4380 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4381 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4382 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4383 WS_HEAP
*heap
, void *ret
, ULONG size
)
4385 WS_XML_UTF8_TEXT
*utf8
;
4392 FIXME( "description not supported\n" );
4395 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4396 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
4401 case WS_READ_REQUIRED_VALUE
:
4402 if (!found
) return WS_E_INVALID_FORMAT
;
4405 case WS_READ_NILLABLE_VALUE
:
4406 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
4407 *(UINT32
*)ret
= val
;
4410 case WS_READ_REQUIRED_POINTER
:
4411 if (!found
) return WS_E_INVALID_FORMAT
;
4414 case WS_READ_OPTIONAL_POINTER
:
4415 case WS_READ_NILLABLE_POINTER
:
4417 UINT32
*heap_val
= NULL
;
4418 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4421 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4424 *(UINT32
**)ret
= heap_val
;
4428 FIXME( "read option %u not supported\n", option
);
4435 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4436 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4437 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4438 WS_HEAP
*heap
, void *ret
, ULONG size
)
4440 WS_XML_UTF8_TEXT
*utf8
;
4447 FIXME( "description not supported\n" );
4450 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4451 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
)) != S_OK
)
4456 case WS_READ_REQUIRED_VALUE
:
4457 if (!found
) return WS_E_INVALID_FORMAT
;
4460 case WS_READ_NILLABLE_VALUE
:
4461 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4462 *(UINT64
*)ret
= val
;
4465 case WS_READ_REQUIRED_POINTER
:
4466 if (!found
) return WS_E_INVALID_FORMAT
;
4469 case WS_READ_OPTIONAL_POINTER
:
4470 case WS_READ_NILLABLE_POINTER
:
4472 UINT64
*heap_val
= NULL
;
4473 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4476 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4479 *(UINT64
**)ret
= heap_val
;
4483 FIXME( "read option %u not supported\n", option
);
4490 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4491 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4492 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4493 WS_HEAP
*heap
, void *ret
, ULONG size
)
4495 WS_XML_UTF8_TEXT
*utf8
;
4500 if (desc
) FIXME( "ignoring description\n" );
4502 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4503 if (found
&& (hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4507 case WS_READ_REQUIRED_VALUE
:
4508 if (!found
) return WS_E_INVALID_FORMAT
;
4511 case WS_READ_NILLABLE_VALUE
:
4512 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4513 *(double *)ret
= val
;
4516 case WS_READ_REQUIRED_POINTER
:
4517 if (!found
) return WS_E_INVALID_FORMAT
;
4520 case WS_READ_OPTIONAL_POINTER
:
4521 case WS_READ_NILLABLE_POINTER
:
4523 double *heap_val
= NULL
;
4524 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4527 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4530 *(double **)ret
= heap_val
;
4534 FIXME( "read option %u not supported\n", option
);
4541 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4542 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4543 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4544 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
4546 WS_XML_UTF8_TEXT
*utf8
;
4553 FIXME( "description not supported\n" );
4556 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4557 if (found
&& !(str
= xmltext_to_widechar( heap
, &utf8
->text
))) return WS_E_QUOTA_EXCEEDED
;
4561 case WS_READ_REQUIRED_POINTER
:
4562 if (!found
&& !(str
= ws_alloc_zero( heap
, 1 ))) return WS_E_QUOTA_EXCEEDED
;
4565 case WS_READ_OPTIONAL_POINTER
:
4566 case WS_READ_NILLABLE_POINTER
:
4567 if (size
!= sizeof(str
)) return E_INVALIDARG
;
4572 FIXME( "read option %u not supported\n", option
);
4579 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
4582 for (i
= 0; i
< desc
->valueCount
; i
++)
4584 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
4586 *ret
= desc
->values
[i
].value
;
4590 return WS_E_INVALID_FORMAT
;
4593 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4594 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4595 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4596 WS_HEAP
*heap
, void *ret
, ULONG size
)
4598 WS_XML_UTF8_TEXT
*utf8
;
4603 if (!desc
) return E_INVALIDARG
;
4605 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4606 if (found
&& (hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
4610 case WS_READ_REQUIRED_VALUE
:
4611 if (!found
) return WS_E_INVALID_FORMAT
;
4614 case WS_READ_NILLABLE_VALUE
:
4615 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4619 case WS_READ_REQUIRED_POINTER
:
4620 if (!found
) return WS_E_INVALID_FORMAT
;
4623 case WS_READ_OPTIONAL_POINTER
:
4624 case WS_READ_NILLABLE_POINTER
:
4626 int *heap_val
= NULL
;
4627 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4630 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4633 *(int **)ret
= heap_val
;
4637 FIXME( "read option %u not supported\n", option
);
4644 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4645 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4646 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4647 WS_HEAP
*heap
, void *ret
, ULONG size
)
4649 WS_XML_UTF8_TEXT
*utf8
;
4651 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
4654 if (desc
) FIXME( "ignoring description\n" );
4656 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4657 if (found
&& (hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4661 case WS_READ_REQUIRED_VALUE
:
4662 if (!found
) return WS_E_INVALID_FORMAT
;
4665 case WS_READ_NILLABLE_VALUE
:
4666 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4667 *(WS_DATETIME
*)ret
= val
;
4670 case WS_READ_REQUIRED_POINTER
:
4671 if (!found
) return WS_E_INVALID_FORMAT
;
4674 case WS_READ_OPTIONAL_POINTER
:
4675 case WS_READ_NILLABLE_POINTER
:
4677 WS_DATETIME
*heap_val
= NULL
;
4678 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4681 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4684 *(WS_DATETIME
**)ret
= heap_val
;
4688 FIXME( "read option %u not supported\n", option
);
4695 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4696 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4697 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4698 WS_HEAP
*heap
, void *ret
, ULONG size
)
4700 WS_XML_UTF8_TEXT
*utf8
;
4705 if (desc
) FIXME( "ignoring description\n" );
4707 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4708 if (found
&& (hr
= str_to_guid( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4712 case WS_READ_REQUIRED_VALUE
:
4713 if (!found
) return WS_E_INVALID_FORMAT
;
4716 case WS_READ_NILLABLE_VALUE
:
4717 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4721 case WS_READ_REQUIRED_POINTER
:
4722 if (!found
) return WS_E_INVALID_FORMAT
;
4725 case WS_READ_OPTIONAL_POINTER
:
4726 case WS_READ_NILLABLE_POINTER
:
4728 GUID
*heap_val
= NULL
;
4729 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4732 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4735 *(GUID
**)ret
= heap_val
;
4739 FIXME( "read option %u not supported\n", option
);
4746 static HRESULT
read_type_unique_id( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4747 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4748 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4749 WS_HEAP
*heap
, void *ret
, ULONG size
)
4751 WS_XML_UTF8_TEXT
*utf8
;
4752 WS_UNIQUE_ID val
= {{0}};
4756 if (desc
) FIXME( "ignoring description\n" );
4758 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4759 if (found
&& (hr
= str_to_unique_id( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
) return hr
;
4763 case WS_READ_REQUIRED_VALUE
:
4764 if (!found
) return WS_E_INVALID_FORMAT
;
4767 case WS_READ_NILLABLE_VALUE
:
4768 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4769 *(WS_UNIQUE_ID
*)ret
= val
;
4772 case WS_READ_REQUIRED_POINTER
:
4773 if (!found
) return WS_E_INVALID_FORMAT
;
4776 case WS_READ_OPTIONAL_POINTER
:
4777 case WS_READ_NILLABLE_POINTER
:
4779 WS_UNIQUE_ID
*heap_val
= NULL
;
4780 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4783 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4786 *(WS_UNIQUE_ID
**)ret
= heap_val
;
4790 FIXME( "read option %u not supported\n", option
);
4797 static HRESULT
read_type_string( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4798 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4799 const WS_STRING_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4800 WS_HEAP
*heap
, void *ret
, ULONG size
)
4802 WS_XML_UTF8_TEXT
*utf8
;
4803 WS_STRING val
= {0};
4807 if (desc
) FIXME( "ignoring description\n" );
4809 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4810 if (found
&& (hr
= str_to_string( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4815 case WS_READ_REQUIRED_VALUE
:
4816 case WS_READ_NILLABLE_VALUE
:
4817 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4818 *(WS_STRING
*)ret
= val
;
4821 case WS_READ_REQUIRED_POINTER
:
4823 WS_STRING
*heap_val
;
4824 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4825 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4827 *(WS_STRING
**)ret
= heap_val
;
4830 case WS_READ_OPTIONAL_POINTER
:
4831 case WS_READ_NILLABLE_POINTER
:
4833 WS_STRING
*heap_val
= NULL
;
4834 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4837 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4840 *(WS_STRING
**)ret
= heap_val
;
4844 FIXME( "read option %u not supported\n", option
);
4851 static HRESULT
read_type_bytes( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4852 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4853 const WS_BYTES_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4854 WS_HEAP
*heap
, void *ret
, ULONG size
)
4856 WS_XML_UTF8_TEXT
*utf8
;
4861 if (desc
) FIXME( "ignoring description\n" );
4863 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4864 if (found
&& (hr
= str_to_bytes( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4869 case WS_READ_REQUIRED_VALUE
:
4870 case WS_READ_NILLABLE_VALUE
:
4871 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4872 *(WS_BYTES
*)ret
= val
;
4875 case WS_READ_REQUIRED_POINTER
:
4878 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4879 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4881 *(WS_BYTES
**)ret
= heap_val
;
4884 case WS_READ_OPTIONAL_POINTER
:
4885 case WS_READ_NILLABLE_POINTER
:
4887 WS_BYTES
*heap_val
= NULL
;
4888 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4891 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4894 *(WS_BYTES
**)ret
= heap_val
;
4898 FIXME( "read option %u not supported\n", option
);
4905 static HRESULT
read_type_xml_string( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4906 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4907 const WS_XML_STRING_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4908 WS_HEAP
*heap
, void *ret
, ULONG size
)
4910 WS_XML_UTF8_TEXT
*utf8
;
4911 WS_XML_STRING val
= {0};
4915 if (desc
) FIXME( "ignoring description\n" );
4917 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4918 if (found
&& (hr
= str_to_xml_string( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4923 case WS_READ_REQUIRED_VALUE
:
4924 case WS_READ_NILLABLE_VALUE
:
4925 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4926 *(WS_XML_STRING
*)ret
= val
;
4929 case WS_READ_REQUIRED_POINTER
:
4931 WS_XML_STRING
*heap_val
;
4932 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4933 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4935 *(WS_XML_STRING
**)ret
= heap_val
;
4938 case WS_READ_OPTIONAL_POINTER
:
4939 case WS_READ_NILLABLE_POINTER
:
4941 WS_XML_STRING
*heap_val
= NULL
;
4942 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4945 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4948 *(WS_XML_STRING
**)ret
= heap_val
;
4952 FIXME( "read option %u not supported\n", option
);
4959 static HRESULT
read_type_qname( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4960 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4961 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4962 WS_HEAP
*heap
, void *ret
, ULONG size
)
4964 WS_XML_UTF8_TEXT
*utf8
;
4965 WS_XML_QNAME val
= {{0}};
4969 if (desc
) FIXME( "ignoring description\n" );
4971 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
4972 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
4973 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
4975 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4976 if (found
&& (hr
= str_to_qname( reader
, utf8
->value
.bytes
, utf8
->value
.length
, heap
,
4977 NULL
, &val
.localName
, &val
.ns
)) != S_OK
) return hr
;
4981 case WS_READ_REQUIRED_VALUE
:
4982 if (!found
) return WS_E_INVALID_FORMAT
;
4985 case WS_READ_NILLABLE_VALUE
:
4986 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4987 *(WS_XML_QNAME
*)ret
= val
;
4990 case WS_READ_REQUIRED_POINTER
:
4991 if (!found
) return WS_E_INVALID_FORMAT
;
4994 case WS_READ_OPTIONAL_POINTER
:
4995 case WS_READ_NILLABLE_POINTER
:
4997 WS_XML_QNAME
*heap_val
= NULL
;
4998 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5001 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5004 *(WS_XML_QNAME
**)ret
= heap_val
;
5008 FIXME( "read option %u not supported\n", option
);
5015 static BOOL
is_empty_text_node( const struct node
*node
)
5017 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
5018 const WS_XML_UTF8_TEXT
*utf8
;
5021 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
5022 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
5024 ERR( "unhandled text type %u\n", text
->text
->textType
);
5027 utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
5028 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
5032 /* skips comment and empty text nodes */
5033 static HRESULT
read_type_next_node( struct reader
*reader
)
5038 WS_XML_NODE_TYPE type
;
5040 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
5041 type
= node_type( reader
->current
);
5042 if (type
== WS_XML_NODE_TYPE_COMMENT
||
5043 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
5048 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
5049 const WS_XML_STRING
*ns
)
5055 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
5056 if (reader
->current
== reader
->last
)
5059 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
5060 if (!found
) return WS_E_INVALID_FORMAT
;
5062 if (match_element( reader
->current
, localname
, ns
)) return S_OK
;
5064 node
= reader
->current
;
5065 attr
= reader
->current_attr
;
5067 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
5068 if (match_element( reader
->current
, localname
, ns
)) return S_OK
;
5070 reader
->current
= node
;
5071 reader
->current_attr
= attr
;
5073 return WS_E_INVALID_FORMAT
;
5076 ULONG
get_type_size( WS_TYPE type
, const void *desc
)
5082 return sizeof(INT8
);
5085 case WS_UINT16_TYPE
:
5086 return sizeof(INT16
);
5090 case WS_UINT32_TYPE
:
5092 return sizeof(INT32
);
5095 case WS_UINT64_TYPE
:
5096 return sizeof(INT64
);
5098 case WS_DOUBLE_TYPE
:
5099 return sizeof(double);
5101 case WS_DATETIME_TYPE
:
5102 return sizeof(WS_DATETIME
);
5105 return sizeof(GUID
);
5107 case WS_STRING_TYPE
:
5108 return sizeof(WS_STRING
);
5111 return sizeof(WCHAR
*);
5114 return sizeof(WS_BYTES
);
5116 case WS_XML_STRING_TYPE
:
5117 return sizeof(WS_XML_STRING
);
5119 case WS_XML_QNAME_TYPE
:
5120 return sizeof(WS_XML_QNAME
);
5122 case WS_DESCRIPTION_TYPE
:
5123 return sizeof(WS_STRUCT_DESCRIPTION
*);
5125 case WS_STRUCT_TYPE
:
5127 const WS_STRUCT_DESCRIPTION
*desc_struct
= desc
;
5128 return desc_struct
->size
;
5132 const WS_UNION_DESCRIPTION
*desc_union
= desc
;
5133 return desc_union
->size
;
5136 ERR( "unhandled type %u\n", type
);
5141 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
, ULONG options
)
5143 if (options
& WS_FIELD_POINTER
)
5145 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
5146 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
5147 return WS_READ_REQUIRED_POINTER
;
5158 case WS_UINT16_TYPE
:
5159 case WS_UINT32_TYPE
:
5160 case WS_UINT64_TYPE
:
5161 case WS_DOUBLE_TYPE
:
5162 case WS_DATETIME_TYPE
:
5164 case WS_UNIQUE_ID_TYPE
:
5165 case WS_STRING_TYPE
:
5167 case WS_XML_STRING_TYPE
:
5168 case WS_XML_QNAME_TYPE
:
5169 case WS_STRUCT_TYPE
:
5171 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_READ_NILLABLE_VALUE
;
5172 return WS_READ_REQUIRED_VALUE
;
5175 case WS_DESCRIPTION_TYPE
:
5176 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
5177 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
5178 return WS_READ_REQUIRED_POINTER
;
5181 FIXME( "unhandled type %u\n", type
);
5186 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
5187 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
5190 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5191 WS_HEAP
*heap
, void **ret
, ULONG
*count
)
5194 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
5195 WS_READ_OPTION option
;
5198 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
5200 /* wrapper element */
5201 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
5204 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
5205 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
5207 item_size
= sizeof(void *);
5209 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
5212 if (nb_items
>= nb_allocated
)
5214 SIZE_T old_size
= nb_allocated
* item_size
, new_size
= old_size
* 2;
5215 if (!(buf
= ws_realloc_zero( heap
, buf
, old_size
, new_size
)))
5216 return WS_E_QUOTA_EXCEEDED
;
5219 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
5220 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
5221 if (hr
== WS_E_INVALID_FORMAT
) break;
5224 ws_free( heap
, buf
, nb_allocated
* item_size
);
5227 offset
+= item_size
;
5231 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
5233 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
5235 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
5236 desc
->itemRange
->maxItemCount
);
5237 ws_free( heap
, buf
, nb_allocated
* item_size
);
5238 return WS_E_INVALID_FORMAT
;
5247 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5248 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
5251 if (reader
->current
== reader
->last
)
5254 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
5255 if (!found
) return WS_E_INVALID_FORMAT
;
5257 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
5258 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
5260 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
5261 desc
->typeDescription
, option
, heap
, ret
, size
);
5264 static HRESULT
read_type_struct_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5265 WS_HEAP
*heap
, char *buf
, ULONG offset
)
5268 WS_READ_OPTION option
;
5272 if (!desc
) return E_INVALIDARG
;
5273 if (desc
->options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
5275 FIXME( "options %08x not supported\n", desc
->options
);
5278 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
5280 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
5281 size
= get_type_size( desc
->type
, desc
->typeDescription
);
5283 size
= sizeof(void *);
5286 switch (desc
->mapping
)
5288 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING
:
5289 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
5292 case WS_ATTRIBUTE_FIELD_MAPPING
:
5293 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
5294 desc
->typeDescription
, option
, heap
, ptr
, size
);
5297 case WS_ELEMENT_FIELD_MAPPING
:
5298 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
5299 desc
->typeDescription
, option
, heap
, ptr
, size
);
5302 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
5305 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, &count
);
5306 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
5309 case WS_TEXT_FIELD_MAPPING
:
5310 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
5314 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
5318 if (hr
== WS_E_INVALID_FORMAT
)
5322 case WS_READ_REQUIRED_VALUE
:
5323 case WS_READ_REQUIRED_POINTER
:
5324 return WS_E_INVALID_FORMAT
;
5326 case WS_READ_NILLABLE_VALUE
:
5327 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
5330 case WS_READ_OPTIONAL_POINTER
:
5331 case WS_READ_NILLABLE_POINTER
:
5332 *(void **)ptr
= NULL
;
5336 ERR( "unhandled option %u\n", option
);
5344 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5345 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5346 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5347 WS_HEAP
*heap
, void *ret
, ULONG size
)
5353 if (!desc
) return E_INVALIDARG
;
5354 if (desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5356 FIXME( "struct options %08x not supported\n",
5357 desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
);
5362 case WS_READ_REQUIRED_POINTER
:
5363 case WS_READ_OPTIONAL_POINTER
:
5364 case WS_READ_NILLABLE_POINTER
:
5365 if (size
!= sizeof(void *)) return E_INVALIDARG
;
5366 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
5369 case WS_READ_REQUIRED_VALUE
:
5370 case WS_READ_NILLABLE_VALUE
:
5371 if (size
!= desc
->size
) return E_INVALIDARG
;
5376 FIXME( "unhandled read option %u\n", option
);
5380 for (i
= 0; i
< desc
->fieldCount
; i
++)
5382 offset
= desc
->fields
[i
]->offset
;
5383 if ((hr
= read_type_struct_field( reader
, desc
->fields
[i
], heap
, buf
, offset
)) != S_OK
)
5389 case WS_READ_REQUIRED_POINTER
:
5392 ws_free( heap
, buf
, desc
->size
);
5395 *(char **)ret
= buf
;
5398 case WS_READ_OPTIONAL_POINTER
:
5399 case WS_READ_NILLABLE_POINTER
:
5400 if (is_nil_value( buf
, desc
->size
))
5402 ws_free( heap
, buf
, desc
->size
);
5405 *(char **)ret
= buf
;
5408 case WS_READ_REQUIRED_VALUE
:
5409 case WS_READ_NILLABLE_VALUE
:
5410 if (hr
!= S_OK
) return hr
;
5414 ERR( "unhandled read option %u\n", option
);
5418 if (desc
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5420 struct node
*parent
= find_parent( reader
);
5421 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
5426 static HRESULT
start_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
5427 const WS_XML_STRING
*ns
)
5431 case WS_ELEMENT_TYPE_MAPPING
:
5432 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5433 return read_type_next_element_node( reader
, localname
, ns
);
5435 case WS_ANY_ELEMENT_TYPE_MAPPING
:
5436 case WS_ATTRIBUTE_TYPE_MAPPING
:
5440 FIXME( "unhandled mapping %u\n", mapping
);
5445 static HRESULT
read_type_endelement_node( struct reader
*reader
)
5447 const struct node
*parent
= find_parent( reader
);
5452 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
5453 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
&& reader
->current
->parent
== parent
)
5457 if (read_end_of_data( reader
) || !(parent
->flags
& NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
)) break;
5460 return WS_E_INVALID_FORMAT
;
5463 static HRESULT
end_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
)
5467 case WS_ELEMENT_TYPE_MAPPING
:
5468 return read_type_endelement_node( reader
);
5470 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5471 return read_type_next_node( reader
);
5473 case WS_ATTRIBUTE_TYPE_MAPPING
:
5479 static HRESULT
is_nil_element( const WS_XML_ELEMENT_NODE
*elem
)
5481 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
5482 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
5485 for (i
= 0; i
< elem
->attributeCount
; i
++)
5487 const WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[i
]->value
;
5489 if (elem
->attributes
[i
]->isXmlNs
) continue;
5490 if (WsXmlStringEquals( elem
->attributes
[i
]->localName
, &localname
, NULL
) == S_OK
&&
5491 WsXmlStringEquals( elem
->attributes
[i
]->ns
, &ns
, NULL
) == S_OK
&&
5492 text
->value
.length
== 4 && !memcmp( text
->value
.bytes
, "true", 4 )) return TRUE
;
5497 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5498 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
, const void *desc
,
5499 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
)
5503 if ((hr
= start_mapping( reader
, mapping
, localname
, ns
)) != S_OK
) return hr
;
5505 if (mapping
== WS_ELEMENT_TYPE_MAPPING
&& is_nil_element( &reader
->current
->hdr
))
5507 if (option
!= WS_READ_NILLABLE_POINTER
&& option
!= WS_READ_NILLABLE_VALUE
) return WS_E_INVALID_FORMAT
;
5508 return end_mapping( reader
, mapping
);
5514 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5519 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5524 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5529 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5534 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5539 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5543 case WS_UINT16_TYPE
:
5544 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5548 case WS_UINT32_TYPE
:
5549 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5553 case WS_UINT64_TYPE
:
5554 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5558 case WS_DOUBLE_TYPE
:
5559 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5563 case WS_DATETIME_TYPE
:
5564 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5569 if ((hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5573 case WS_UNIQUE_ID_TYPE
:
5574 if ((hr
= read_type_unique_id( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5578 case WS_STRING_TYPE
:
5579 if ((hr
= read_type_string( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5584 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5589 if ((hr
= read_type_bytes( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5593 case WS_XML_STRING_TYPE
:
5594 if ((hr
= read_type_xml_string( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5598 case WS_XML_QNAME_TYPE
:
5599 if ((hr
= read_type_qname( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5603 case WS_STRUCT_TYPE
:
5604 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5609 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5614 FIXME( "type %u not supported\n", type
);
5618 return end_mapping( reader
, mapping
);
5621 /**************************************************************************
5622 * WsReadType [webservices.@]
5624 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5625 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
5626 ULONG size
, WS_ERROR
*error
)
5628 struct reader
*reader
= (struct reader
*)handle
;
5631 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
5633 if (error
) FIXME( "ignoring error parameter\n" );
5635 if (!reader
|| !value
) return E_INVALIDARG
;
5637 EnterCriticalSection( &reader
->cs
);
5639 if (reader
->magic
!= READER_MAGIC
)
5641 LeaveCriticalSection( &reader
->cs
);
5642 return E_INVALIDARG
;
5645 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
5647 LeaveCriticalSection( &reader
->cs
);
5653 case WS_ELEMENT_TYPE_MAPPING
:
5654 hr
= read_node( reader
);
5661 if (hr
== S_OK
&& !read_end_of_data( reader
)) hr
= WS_E_INVALID_FORMAT
;
5663 LeaveCriticalSection( &reader
->cs
);
5667 HRESULT
read_header( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5668 WS_TYPE type
, const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
5671 struct reader
*reader
= (struct reader
*)handle
;
5674 EnterCriticalSection( &reader
->cs
);
5676 if (reader
->magic
!= READER_MAGIC
)
5678 LeaveCriticalSection( &reader
->cs
);
5679 return E_INVALIDARG
;
5682 hr
= read_type( reader
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, type
, localname
, ns
, desc
, option
, heap
,
5685 LeaveCriticalSection( &reader
->cs
);
5689 /**************************************************************************
5690 * WsReadElement [webservices.@]
5692 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
5693 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5696 struct reader
*reader
= (struct reader
*)handle
;
5699 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5700 if (error
) FIXME( "ignoring error parameter\n" );
5702 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5704 EnterCriticalSection( &reader
->cs
);
5706 if (reader
->magic
!= READER_MAGIC
)
5708 LeaveCriticalSection( &reader
->cs
);
5709 return E_INVALIDARG
;
5712 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
5713 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5715 LeaveCriticalSection( &reader
->cs
);
5719 /**************************************************************************
5720 * WsReadValue [webservices.@]
5722 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
5725 struct reader
*reader
= (struct reader
*)handle
;
5726 WS_TYPE type
= map_value_type( value_type
);
5729 TRACE( "%p %u %p %u %p\n", handle
, type
, value
, size
, error
);
5730 if (error
) FIXME( "ignoring error parameter\n" );
5732 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
5734 EnterCriticalSection( &reader
->cs
);
5736 if (reader
->magic
!= READER_MAGIC
)
5738 LeaveCriticalSection( &reader
->cs
);
5739 return E_INVALIDARG
;
5742 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
5743 NULL
, value
, size
);
5745 LeaveCriticalSection( &reader
->cs
);
5749 /**************************************************************************
5750 * WsReadAttribute [webservices.@]
5752 HRESULT WINAPI
WsReadAttribute( WS_XML_READER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
5753 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5756 struct reader
*reader
= (struct reader
*)handle
;
5759 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5760 if (error
) FIXME( "ignoring error parameter\n" );
5762 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5764 EnterCriticalSection( &reader
->cs
);
5766 if (reader
->magic
!= READER_MAGIC
)
5768 LeaveCriticalSection( &reader
->cs
);
5769 return E_INVALIDARG
;
5772 if (!reader
->input_type
)
5774 LeaveCriticalSection( &reader
->cs
);
5775 return WS_E_INVALID_OPERATION
;
5778 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->attributeLocalName
,
5779 desc
->attributeNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5781 LeaveCriticalSection( &reader
->cs
);
5785 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5787 static const char bom
[] = {0xef,0xbb,0xbf};
5788 const unsigned char *p
= data
;
5790 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
5791 (size
> 2 && !(*offset
= 0));
5794 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5796 static const char bom
[] = {0xff,0xfe};
5797 const unsigned char *p
= data
;
5799 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
5800 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
5803 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5807 /* FIXME: parse xml declaration */
5809 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
5810 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
5813 FIXME( "charset not recognized\n" );
5817 TRACE( "detected charset %u\n", ret
);
5821 static void set_input_buffer( struct reader
*reader
, struct xmlbuf
*buf
, const unsigned char *data
, ULONG size
)
5823 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
5824 reader
->input_buf
= buf
;
5825 reader
->input_data
= data
;
5826 reader
->input_size
= size
;
5828 reader
->read_size
= reader
->input_size
;
5829 reader
->read_pos
= 0;
5830 reader
->read_bufptr
= reader
->input_data
;
5832 reader
->text_conv_offset
= 0;
5835 /**************************************************************************
5836 * WsSetInput [webservices.@]
5838 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
5839 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
5840 ULONG count
, WS_ERROR
*error
)
5842 struct reader
*reader
= (struct reader
*)handle
;
5844 ULONG i
, offset
= 0;
5847 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
5848 if (error
) FIXME( "ignoring error parameter\n" );
5850 if (!reader
) return E_INVALIDARG
;
5852 EnterCriticalSection( &reader
->cs
);
5854 if (reader
->magic
!= READER_MAGIC
)
5856 LeaveCriticalSection( &reader
->cs
);
5857 return E_INVALIDARG
;
5860 for (i
= 0; i
< count
; i
++)
5862 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
5863 properties
[i
].valueSize
);
5864 if (hr
!= S_OK
) goto done
;
5867 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
5869 switch (encoding
->encodingType
)
5871 case WS_XML_READER_ENCODING_TYPE_TEXT
:
5873 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
5874 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
5876 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
5878 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
5883 if (text
->charSet
!= WS_CHARSET_AUTO
) reader
->input_charset
= text
->charSet
;
5884 else reader
->input_charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
5886 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
5889 case WS_XML_READER_ENCODING_TYPE_BINARY
:
5891 WS_XML_READER_BINARY_ENCODING
*bin
= (WS_XML_READER_BINARY_ENCODING
*)encoding
;
5892 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_BINARY
;
5893 reader
->input_charset
= 0;
5894 reader
->dict_static
= bin
->staticDictionary
? bin
->staticDictionary
: &dict_builtin_static
.dict
;
5895 reader
->dict
= bin
->dynamicDictionary
? bin
->dynamicDictionary
: &dict_builtin
.dict
;
5899 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
5904 switch (input
->inputType
)
5906 case WS_XML_READER_INPUT_TYPE_BUFFER
:
5908 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
5909 set_input_buffer( reader
, NULL
, (const unsigned char *)buf
->encodedData
+ offset
,
5910 buf
->encodedDataSize
- offset
);
5914 FIXME( "input type %u not supported\n", input
->inputType
);
5919 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
5920 else read_insert_bof( reader
, node
);
5923 LeaveCriticalSection( &reader
->cs
);
5927 /**************************************************************************
5928 * WsSetInputToBuffer [webservices.@]
5930 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
5931 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
5934 struct reader
*reader
= (struct reader
*)handle
;
5935 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
5940 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
5941 if (error
) FIXME( "ignoring error parameter\n" );
5943 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
5945 EnterCriticalSection( &reader
->cs
);
5947 if (reader
->magic
!= READER_MAGIC
)
5949 LeaveCriticalSection( &reader
->cs
);
5950 return E_INVALIDARG
;
5953 for (i
= 0; i
< count
; i
++)
5955 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
5956 properties
[i
].valueSize
);
5957 if (hr
!= S_OK
) goto done
;
5960 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
5962 reader
->input_enc
= xmlbuf
->encoding
;
5963 reader
->input_charset
= xmlbuf
->charset
;
5964 set_input_buffer( reader
, xmlbuf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
5966 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
5967 else read_insert_bof( reader
, node
);
5970 LeaveCriticalSection( &reader
->cs
);
5974 /**************************************************************************
5975 * WsGetReaderPosition [webservices.@]
5977 HRESULT WINAPI
WsGetReaderPosition( WS_XML_READER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
5979 struct reader
*reader
= (struct reader
*)handle
;
5981 TRACE( "%p %p %p\n", handle
, pos
, error
);
5982 if (error
) FIXME( "ignoring error parameter\n" );
5984 if (!reader
|| !pos
) return E_INVALIDARG
;
5986 EnterCriticalSection( &reader
->cs
);
5988 if (reader
->magic
!= READER_MAGIC
)
5990 LeaveCriticalSection( &reader
->cs
);
5991 return E_INVALIDARG
;
5994 if (!reader
->input_buf
)
5996 LeaveCriticalSection( &reader
->cs
);
5997 return WS_E_INVALID_OPERATION
;
6000 pos
->buffer
= (WS_XML_BUFFER
*)reader
->input_buf
;
6001 pos
->node
= reader
->current
;
6003 LeaveCriticalSection( &reader
->cs
);
6007 /**************************************************************************
6008 * WsSetReaderPosition [webservices.@]
6010 HRESULT WINAPI
WsSetReaderPosition( WS_XML_READER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
6012 struct reader
*reader
= (struct reader
*)handle
;
6014 TRACE( "%p %p %p\n", handle
, pos
, error
);
6015 if (error
) FIXME( "ignoring error parameter\n" );
6017 if (!reader
|| !pos
) return E_INVALIDARG
;
6019 EnterCriticalSection( &reader
->cs
);
6021 if (reader
->magic
!= READER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= reader
->input_buf
)
6023 LeaveCriticalSection( &reader
->cs
);
6024 return E_INVALIDARG
;
6027 if (!reader
->input_buf
)
6029 LeaveCriticalSection( &reader
->cs
);
6030 return WS_E_INVALID_OPERATION
;
6033 reader
->current
= pos
->node
;
6035 LeaveCriticalSection( &reader
->cs
);
6039 static HRESULT
utf8_to_base64( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_BASE64_TEXT
*base64
)
6041 if (utf8
->value
.length
% 4) return WS_E_INVALID_FORMAT
;
6042 if (!(base64
->bytes
= heap_alloc( utf8
->value
.length
* 3 / 4 ))) return E_OUTOFMEMORY
;
6043 base64
->length
= decode_base64( utf8
->value
.bytes
, utf8
->value
.length
, base64
->bytes
);
6047 /**************************************************************************
6048 * WsReadBytes [webservices.@]
6050 HRESULT WINAPI
WsReadBytes( WS_XML_READER
*handle
, void *bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
6052 struct reader
*reader
= (struct reader
*)handle
;
6055 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
6056 if (error
) FIXME( "ignoring error parameter\n" );
6058 if (!reader
) return E_INVALIDARG
;
6060 EnterCriticalSection( &reader
->cs
);
6062 if (reader
->magic
!= READER_MAGIC
)
6064 LeaveCriticalSection( &reader
->cs
);
6065 return E_INVALIDARG
;
6068 if (!reader
->input_type
)
6070 LeaveCriticalSection( &reader
->cs
);
6071 return WS_E_INVALID_OPERATION
;
6076 LeaveCriticalSection( &reader
->cs
);
6077 return E_INVALIDARG
;
6081 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
6083 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
6084 WS_XML_BASE64_TEXT base64
;
6086 if ((hr
= utf8_to_base64( (const WS_XML_UTF8_TEXT
*)text
->text
, &base64
)) != S_OK
)
6088 LeaveCriticalSection( &reader
->cs
);
6091 if (reader
->text_conv_offset
== base64
.length
)
6093 heap_free( base64
.bytes
);
6094 hr
= read_node( reader
);
6095 LeaveCriticalSection( &reader
->cs
);
6098 *count
= min( base64
.length
- reader
->text_conv_offset
, max_count
);
6099 memcpy( bytes
, base64
.bytes
+ reader
->text_conv_offset
, *count
);
6100 reader
->text_conv_offset
+= *count
;
6101 heap_free( base64
.bytes
);
6104 LeaveCriticalSection( &reader
->cs
);
6108 static HRESULT
utf8_to_utf16( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_UTF16_TEXT
*utf16
)
6110 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
6111 if (!(utf16
->bytes
= heap_alloc( len
* sizeof(WCHAR
) ))) return E_OUTOFMEMORY
;
6112 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, (WCHAR
*)utf16
->bytes
, len
);
6113 utf16
->byteCount
= len
* sizeof(WCHAR
);
6117 /**************************************************************************
6118 * WsReadChars [webservices.@]
6120 HRESULT WINAPI
WsReadChars( WS_XML_READER
*handle
, WCHAR
*chars
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
6122 struct reader
*reader
= (struct reader
*)handle
;
6124 TRACE( "%p %p %u %p %p\n", handle
, chars
, max_count
, count
, error
);
6125 if (error
) FIXME( "ignoring error parameter\n" );
6127 if (!reader
) return E_INVALIDARG
;
6129 EnterCriticalSection( &reader
->cs
);
6131 if (reader
->magic
!= READER_MAGIC
)
6133 LeaveCriticalSection( &reader
->cs
);
6134 return E_INVALIDARG
;
6137 if (!reader
->input_type
)
6139 LeaveCriticalSection( &reader
->cs
);
6140 return WS_E_INVALID_OPERATION
;
6145 LeaveCriticalSection( &reader
->cs
);
6146 return E_INVALIDARG
;
6150 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& chars
)
6152 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
6153 WS_XML_UTF16_TEXT utf16
;
6156 if ((hr
= utf8_to_utf16( (const WS_XML_UTF8_TEXT
*)text
->text
, &utf16
)) != S_OK
)
6158 LeaveCriticalSection( &reader
->cs
);
6161 if (reader
->text_conv_offset
== utf16
.byteCount
/ sizeof(WCHAR
))
6163 heap_free( utf16
.bytes
);
6164 hr
= read_node( reader
);
6165 LeaveCriticalSection( &reader
->cs
);
6168 *count
= min( utf16
.byteCount
/ sizeof(WCHAR
) - reader
->text_conv_offset
, max_count
);
6169 memcpy( chars
, utf16
.bytes
+ reader
->text_conv_offset
* sizeof(WCHAR
), *count
* sizeof(WCHAR
) );
6170 reader
->text_conv_offset
+= *count
;
6171 heap_free( utf16
.bytes
);
6174 LeaveCriticalSection( &reader
->cs
);
6178 /**************************************************************************
6179 * WsReadCharsUtf8 [webservices.@]
6181 HRESULT WINAPI
WsReadCharsUtf8( WS_XML_READER
*handle
, BYTE
*bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
6183 struct reader
*reader
= (struct reader
*)handle
;
6186 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
6187 if (error
) FIXME( "ignoring error parameter\n" );
6189 if (!reader
) return E_INVALIDARG
;
6191 EnterCriticalSection( &reader
->cs
);
6193 if (reader
->magic
!= READER_MAGIC
)
6195 LeaveCriticalSection( &reader
->cs
);
6196 return E_INVALIDARG
;
6199 if (!reader
->input_type
)
6201 LeaveCriticalSection( &reader
->cs
);
6202 return WS_E_INVALID_OPERATION
;
6207 LeaveCriticalSection( &reader
->cs
);
6208 return E_INVALIDARG
;
6212 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
6214 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
6215 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
6217 if (reader
->text_conv_offset
== utf8
->value
.length
)
6219 hr
= read_node( reader
);
6220 LeaveCriticalSection( &reader
->cs
);
6223 *count
= min( utf8
->value
.length
- reader
->text_conv_offset
, max_count
);
6224 memcpy( bytes
, utf8
->value
.bytes
+ reader
->text_conv_offset
, *count
);
6225 reader
->text_conv_offset
+= *count
;
6228 LeaveCriticalSection( &reader
->cs
);
6232 static HRESULT
move_to_element( struct reader
*reader
)
6235 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_BOF
&&
6236 (hr
= read_move_to( reader
, WS_MOVE_TO_CHILD_NODE
, NULL
)) != S_OK
) return hr
;
6237 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return E_FAIL
;
6241 static HRESULT
copy_tree( struct reader
*reader
, WS_XML_WRITER
*writer
)
6243 const struct node
*node
, *parent
;
6247 if ((hr
= move_to_element( reader
)) != S_OK
) return hr
;
6248 parent
= reader
->current
;
6251 node
= reader
->current
;
6252 if ((hr
= WsWriteNode( writer
, (const WS_XML_NODE
*)node
, NULL
)) != S_OK
) break;
6253 if (node_type( node
) == WS_XML_NODE_TYPE_END_ELEMENT
&& node
->parent
== parent
) done
= TRUE
;
6254 if ((hr
= read_next_node( reader
)) != S_OK
|| done
) break;
6259 /**************************************************************************
6260 * WsReadXmlBuffer [webservices.@]
6262 HRESULT WINAPI
WsReadXmlBuffer( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_BUFFER
**ret
, WS_ERROR
*error
)
6264 struct reader
*reader
= (struct reader
*)handle
;
6265 WS_XML_WRITER
*writer
= NULL
;
6266 WS_XML_BUFFER
*buffer
;
6269 TRACE( "%p %p %p %p\n", handle
, heap
, ret
, error
);
6270 if (error
) FIXME( "ignoring error parameter\n" );
6272 if (!reader
|| !heap
) return E_INVALIDARG
;
6273 if (!ret
) return E_FAIL
;
6275 EnterCriticalSection( &reader
->cs
);
6277 if (reader
->magic
!= READER_MAGIC
)
6279 LeaveCriticalSection( &reader
->cs
);
6280 return E_INVALIDARG
;
6283 if (!reader
->input_type
)
6285 LeaveCriticalSection( &reader
->cs
);
6286 return WS_E_INVALID_OPERATION
;
6289 if ((hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
)) != S_OK
) goto done
;
6290 if ((hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
)) != S_OK
) goto done
;
6291 if ((hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
)) != S_OK
) goto done
;
6292 if ((hr
= copy_tree( reader
, writer
)) == S_OK
) *ret
= buffer
;
6295 if (hr
!= S_OK
) free_xmlbuf( (struct xmlbuf
*)buffer
);
6296 WsFreeWriter( writer
);
6297 LeaveCriticalSection( &reader
->cs
);
6301 HRESULT
get_param_desc( const WS_STRUCT_DESCRIPTION
*desc
, USHORT index
, const WS_FIELD_DESCRIPTION
**ret
)
6303 if (index
>= desc
->fieldCount
) return E_INVALIDARG
;
6304 *ret
= desc
->fields
[index
];
6308 static ULONG
get_field_size( const WS_FIELD_DESCRIPTION
*desc
)
6310 WS_READ_OPTION option
;
6313 switch ((option
= get_field_read_option( desc
->type
, desc
->options
)))
6315 case WS_READ_REQUIRED_POINTER
:
6316 case WS_READ_OPTIONAL_POINTER
:
6317 case WS_READ_NILLABLE_POINTER
:
6318 size
= sizeof(void *);
6321 case WS_READ_REQUIRED_VALUE
:
6322 case WS_READ_NILLABLE_VALUE
:
6323 size
= get_type_size( desc
->type
, desc
->typeDescription
);
6327 WARN( "unhandled option %u\n", option
);
6334 static HRESULT
read_param( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
, void *ret
)
6336 if (!ret
&& !(ret
= ws_alloc_zero( heap
, get_field_size(desc
) ))) return WS_E_QUOTA_EXCEEDED
;
6337 return read_type_struct_field( reader
, desc
, heap
, ret
, 0 );
6340 static HRESULT
read_param_array( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
,
6341 void **ret
, ULONG
*count
)
6343 if (!ret
&& !(ret
= ws_alloc_zero( heap
, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED
;
6344 return read_type_repeating_element( reader
, desc
, heap
, ret
, count
);
6347 static void set_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, ULONG len
,
6351 for (i
= 0; i
< count
; i
++)
6353 if (params
[i
].outputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
6355 if ((ptr
= *(ULONG
**)args
[i
])) *ptr
= len
;
6360 HRESULT
read_output_params( WS_XML_READER
*handle
, WS_HEAP
*heap
, const WS_ELEMENT_DESCRIPTION
*desc
,
6361 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
6363 struct reader
*reader
= (struct reader
*)handle
;
6364 const WS_STRUCT_DESCRIPTION
*desc_struct
;
6365 const WS_FIELD_DESCRIPTION
*desc_field
;
6369 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
6371 EnterCriticalSection( &reader
->cs
);
6373 if (reader
->magic
!= READER_MAGIC
)
6375 LeaveCriticalSection( &reader
->cs
);
6376 return E_INVALIDARG
;
6379 if ((hr
= start_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
)
6382 for (i
= 0; i
< count
; i
++)
6384 if (params
[i
].outputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
6385 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
6387 FIXME( "messages type not supported\n" );
6391 if ((hr
= get_param_desc( desc_struct
, params
[i
].outputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
6392 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
6394 void *ptr
= *(void **)args
[i
];
6395 if ((hr
= read_param( reader
, desc_field
, heap
, ptr
)) != S_OK
) goto done
;
6397 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
6399 void **ptr
= *(void ***)args
[i
];
6400 if ((hr
= read_param_array( reader
, desc_field
, heap
, ptr
, &len
)) != S_OK
) goto done
;
6401 set_array_len( params
, count
, params
[i
].outputMessageIndex
, len
, args
);
6405 if (desc_struct
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
6407 struct node
*parent
= find_parent( reader
);
6408 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
6411 hr
= end_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
);
6414 LeaveCriticalSection( &reader
->cs
);