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_XML_READER_INPUT_TYPE input_type
;
369 struct xmlbuf
*input_buf
;
370 const unsigned char *input_data
;
372 ULONG text_conv_offset
;
373 const WS_XML_DICTIONARY
*dict_static
;
374 WS_XML_DICTIONARY
*dict
;
376 struct prop prop
[sizeof(reader_props
)/sizeof(reader_props
[0])];
379 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
381 static struct reader
*alloc_reader(void)
383 static const ULONG count
= sizeof(reader_props
)/sizeof(reader_props
[0]);
385 ULONG size
= sizeof(*ret
) + prop_size( reader_props
, count
);
387 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
388 if (!(ret
->prefixes
= heap_alloc_zero( sizeof(*ret
->prefixes
) )))
393 ret
->nb_prefixes
= ret
->nb_prefixes_allocated
= 1;
395 ret
->magic
= READER_MAGIC
;
396 InitializeCriticalSection( &ret
->cs
);
397 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": reader.cs");
399 prop_init( reader_props
, count
, ret
->prop
, &ret
[1] );
400 ret
->prop_count
= count
;
404 static void clear_prefixes( struct prefix
*prefixes
, ULONG count
)
407 for (i
= 0; i
< count
; i
++)
409 free_xml_string( prefixes
[i
].str
);
410 prefixes
[i
].str
= NULL
;
411 free_xml_string( prefixes
[i
].ns
);
412 prefixes
[i
].ns
= NULL
;
416 static HRESULT
set_prefix( struct prefix
*prefix
, const WS_XML_STRING
*str
, const WS_XML_STRING
*ns
)
420 free_xml_string( prefix
->str
);
421 if (!(prefix
->str
= dup_xml_string( str
))) return E_OUTOFMEMORY
;
423 if (prefix
->ns
) free_xml_string( prefix
->ns
);
424 if (!(prefix
->ns
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
428 static HRESULT
bind_prefix( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
*ns
)
433 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
435 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
436 return set_prefix( &reader
->prefixes
[i
], NULL
, ns
);
438 if (i
>= reader
->nb_prefixes_allocated
)
440 ULONG new_size
= reader
->nb_prefixes_allocated
* sizeof(*reader
->prefixes
) * 2;
441 struct prefix
*tmp
= heap_realloc_zero( reader
->prefixes
, new_size
);
442 if (!tmp
) return E_OUTOFMEMORY
;
443 reader
->prefixes
= tmp
;
444 reader
->nb_prefixes_allocated
*= 2;
446 if ((hr
= set_prefix( &reader
->prefixes
[i
], prefix
, ns
)) != S_OK
) return hr
;
447 reader
->nb_prefixes
++;
451 static const WS_XML_STRING
*get_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
)
454 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
456 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
457 return reader
->prefixes
[i
].ns
;
462 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
464 if (!reader
->root
) reader
->root
= eof
;
467 eof
->parent
= reader
->root
;
468 list_add_tail( &reader
->root
->children
, &eof
->entry
);
470 reader
->current
= reader
->last
= eof
;
473 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
475 reader
->root
->parent
= bof
;
476 list_add_tail( &bof
->children
, &reader
->root
->entry
);
477 reader
->current
= reader
->last
= reader
->root
= bof
;
480 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
482 node
->parent
= parent
;
483 list_add_before( list_tail( &parent
->children
), &node
->entry
);
484 reader
->current
= reader
->last
= node
;
487 static void free_reader( struct reader
*reader
)
489 destroy_nodes( reader
->root
);
490 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
491 heap_free( reader
->prefixes
);
492 reader
->cs
.DebugInfo
->Spare
[0] = 0;
493 DeleteCriticalSection( &reader
->cs
);
497 static HRESULT
init_reader( struct reader
*reader
)
499 static const WS_XML_STRING empty
= {0, NULL
};
503 reader
->state
= READER_STATE_INITIAL
;
504 destroy_nodes( reader
->root
);
505 reader
->root
= reader
->current
= NULL
;
506 reader
->current_attr
= 0;
507 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
508 reader
->nb_prefixes
= 1;
509 if ((hr
= bind_prefix( reader
, &empty
, &empty
)) != S_OK
) return hr
;
511 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
512 read_insert_eof( reader
, node
);
513 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
514 reader
->dict_static
= NULL
;
519 /**************************************************************************
520 * WsCreateReader [webservices.@]
522 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
523 WS_XML_READER
**handle
, WS_ERROR
*error
)
525 struct reader
*reader
;
526 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
527 WS_CHARSET charset
= WS_CHARSET_UTF8
;
528 BOOL read_decl
= TRUE
;
531 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
532 if (error
) FIXME( "ignoring error parameter\n" );
534 if (!handle
) return E_INVALIDARG
;
535 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
537 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
538 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
539 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
540 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
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 /**************************************************************************
723 * WsGetReaderProperty [webservices.@]
725 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
726 void *buf
, ULONG size
, WS_ERROR
*error
)
728 struct reader
*reader
= (struct reader
*)handle
;
731 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
732 if (error
) FIXME( "ignoring error parameter\n" );
734 if (!reader
) return E_INVALIDARG
;
736 EnterCriticalSection( &reader
->cs
);
738 if (reader
->magic
!= READER_MAGIC
)
740 LeaveCriticalSection( &reader
->cs
);
744 if (!reader
->input_type
)
746 LeaveCriticalSection( &reader
->cs
);
747 return WS_E_INVALID_OPERATION
;
750 if (id
== WS_XML_READER_PROPERTY_CHARSET
)
753 if ((hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, &charset
, size
)) != S_OK
) goto done
;
756 hr
= WS_E_INVALID_FORMAT
;
759 *(WS_CHARSET
*)buf
= charset
;
762 else hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, buf
, size
);
765 LeaveCriticalSection( &reader
->cs
);
769 /**************************************************************************
770 * WsGetXmlAttribute [webservices.@]
772 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
773 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
775 FIXME( "%p %s %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
779 WS_XML_UTF8_TEXT
*alloc_utf8_text( const unsigned char *data
, ULONG len
)
781 WS_XML_UTF8_TEXT
*ret
;
783 if (!(ret
= heap_alloc( sizeof(*ret
) + len
))) return NULL
;
784 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
785 ret
->value
.length
= len
;
786 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
787 ret
->value
.dictionary
= NULL
;
789 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
793 static inline BOOL
read_end_of_data( struct reader
*reader
)
795 return reader
->read_pos
>= reader
->read_size
;
798 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
800 return &reader
->read_bufptr
[reader
->read_pos
];
803 static inline HRESULT
read_peek( struct reader
*reader
, unsigned char *byte
)
805 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
806 *byte
= reader
->read_bufptr
[reader
->read_pos
];
810 static inline HRESULT
read_byte( struct reader
*reader
, unsigned char *byte
)
812 if (reader
->read_pos
>= reader
->read_size
) return WS_E_INVALID_FORMAT
;
813 *byte
= reader
->read_bufptr
[reader
->read_pos
++];
817 static inline HRESULT
read_bytes( struct reader
*reader
, unsigned char *bytes
, unsigned int len
)
819 if (reader
->read_pos
+ len
> reader
->read_size
) return WS_E_INVALID_FORMAT
;
820 memcpy( bytes
, reader
->read_bufptr
+ reader
->read_pos
, len
);
821 reader
->read_pos
+= len
;
825 /* UTF-8 support based on libs/wine/utf8.c */
827 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
828 static const char utf8_length
[128] =
830 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
831 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
832 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
833 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
834 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
835 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
836 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
837 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
840 /* first byte mask depending on UTF-8 sequence length */
841 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
843 /* minimum Unicode value depending on UTF-8 sequence length */
844 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
846 static inline unsigned int read_utf8_char( struct reader
*reader
, unsigned int *skip
)
848 unsigned int len
, res
;
849 unsigned char ch
= reader
->read_bufptr
[reader
->read_pos
];
850 const unsigned char *end
;
852 if (reader
->read_pos
>= reader
->read_size
) return 0;
859 len
= utf8_length
[ch
- 0x80];
860 if (reader
->read_pos
+ len
>= reader
->read_size
) return 0;
861 end
= reader
->read_bufptr
+ reader
->read_pos
+ len
+ 1;
862 res
= ch
& utf8_mask
[len
];
867 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
868 res
= (res
<< 6) | ch
;
870 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
871 res
= (res
<< 6) | ch
;
873 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
874 res
= (res
<< 6) | ch
;
875 if (res
< utf8_minval
[len
]) break;
883 static inline void read_skip( struct reader
*reader
, unsigned int count
)
885 if (reader
->read_pos
+ count
> reader
->read_size
) return;
886 reader
->read_pos
+= count
;
889 static inline void read_rewind( struct reader
*reader
, unsigned int count
)
891 reader
->read_pos
-= count
;
894 static inline BOOL
read_isnamechar( unsigned int ch
)
896 /* FIXME: incomplete */
897 return (ch
>= 'A' && ch
<= 'Z') ||
898 (ch
>= 'a' && ch
<= 'z') ||
899 (ch
>= '0' && ch
<= '9') ||
900 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
903 static inline BOOL
read_isspace( unsigned int ch
)
905 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
908 static inline void read_skip_whitespace( struct reader
*reader
)
910 while (reader
->read_pos
< reader
->read_size
&& read_isspace( reader
->read_bufptr
[reader
->read_pos
] ))
914 static inline int read_cmp( struct reader
*reader
, const char *str
, int len
)
916 const unsigned char *ptr
= read_current_ptr( reader
);
918 if (len
< 0) len
= strlen( str
);
919 if (reader
->read_pos
+ len
> reader
->read_size
) return -1;
922 if (*str
!= *ptr
) return *ptr
- *str
;
928 static HRESULT
read_xmldecl( struct reader
*reader
)
930 if (!reader
->read_size
) return WS_E_INVALID_FORMAT
;
932 if (read_cmp( reader
, "<", 1 ) || read_cmp( reader
, "<?", 2 ))
934 reader
->state
= READER_STATE_BOF
;
937 if (read_cmp( reader
, "<?xml ", 6 )) return WS_E_INVALID_FORMAT
;
938 read_skip( reader
, 6 );
940 /* FIXME: parse attributes */
941 while (reader
->read_pos
< reader
->read_size
&& reader
->read_bufptr
[reader
->read_pos
] != '?')
944 if (read_cmp( reader
, "?>", 2 )) return WS_E_INVALID_FORMAT
;
945 read_skip( reader
, 2 );
947 reader
->state
= READER_STATE_BOF
;
951 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
953 if (elem
->attributeCount
)
955 WS_XML_ATTRIBUTE
**tmp
;
956 if (!(tmp
= heap_realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) )))
957 return E_OUTOFMEMORY
;
958 elem
->attributes
= tmp
;
960 else if (!(elem
->attributes
= heap_alloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
961 elem
->attributes
[elem
->attributeCount
++] = attr
;
965 static HRESULT
split_name( const unsigned char *str
, ULONG len
, const unsigned char **prefix
,
966 ULONG
*prefix_len
, const unsigned char **localname
, ULONG
*localname_len
)
968 const unsigned char *ptr
= str
;
974 *localname_len
= len
;
980 if (ptr
== str
) return WS_E_INVALID_FORMAT
;
982 *prefix_len
= ptr
- str
;
983 *localname
= ptr
+ 1;
984 *localname_len
= len
;
992 static HRESULT
parse_name( const unsigned char *str
, ULONG len
, WS_XML_STRING
**prefix
, WS_XML_STRING
**localname
)
994 const unsigned char *localname_ptr
, *prefix_ptr
;
995 ULONG localname_len
, prefix_len
;
998 if ((hr
= split_name( str
, len
, &prefix_ptr
, &prefix_len
, &localname_ptr
, &localname_len
)) != S_OK
) return hr
;
999 if (!(*prefix
= alloc_xml_string( prefix_ptr
, prefix_len
))) return E_OUTOFMEMORY
;
1000 if (!(*localname
= alloc_xml_string( localname_ptr
, localname_len
)))
1002 free_xml_string( *prefix
);
1004 return E_OUTOFMEMORY
;
1009 static int codepoint_to_utf8( int cp
, unsigned char *dst
)
1019 dst
[1] = 0x80 | (cp
& 0x3f);
1024 if ((cp
>= 0xd800 && cp
<= 0xdfff) || cp
== 0xfffe || cp
== 0xffff) return -1;
1027 dst
[2] = 0x80 | (cp
& 0x3f);
1029 dst
[1] = 0x80 | (cp
& 0x3f);
1034 if (cp
>= 0x110000) return -1;
1035 dst
[3] = 0x80 | (cp
& 0x3f);
1037 dst
[2] = 0x80 | (cp
& 0x3f);
1039 dst
[1] = 0x80 | (cp
& 0x3f);
1045 static HRESULT
decode_text( const unsigned char *str
, ULONG len
, unsigned char *ret
, ULONG
*ret_len
)
1047 const unsigned char *p
= str
;
1048 unsigned char *q
= ret
;
1056 if (!len
) return WS_E_INVALID_FORMAT
;
1058 if (len
>= 3 && !memcmp( p
, "lt;", 3 ))
1064 else if (len
>= 3 && !memcmp( p
, "gt;", 3 ))
1070 else if (len
>= 5 && !memcmp( p
, "quot;", 5 ))
1076 else if (len
>= 4 && !memcmp( p
, "amp;", 4 ))
1082 else if (len
>= 5 && !memcmp( p
, "apos;", 5 ))
1090 ULONG start
, nb_digits
, i
;
1091 int len_utf8
, cp
= 0;
1094 if (!len
) return WS_E_INVALID_FORMAT
;
1100 while (len
&& isxdigit( *p
)) { p
++; len
--; };
1101 if (!len
) return WS_E_INVALID_FORMAT
;
1103 p
-= nb_digits
= start
- len
;
1104 if (!nb_digits
|| nb_digits
> 6 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1105 for (i
= 0; i
< nb_digits
; i
++)
1108 if (*p
>= '0' && *p
<= '9') cp
+= *p
- '0';
1109 else if (*p
>= 'a' && *p
<= 'f') cp
+= *p
- 'a' + 10;
1110 else cp
+= *p
- 'A' + 10;
1114 else if (isdigit( *p
))
1116 while (len
&& *p
== '0') { p
++; len
--; };
1117 if (!len
) return WS_E_INVALID_FORMAT
;
1120 while (len
&& isdigit( *p
)) { p
++; len
--; };
1121 if (!len
) return WS_E_INVALID_FORMAT
;
1123 p
-= nb_digits
= start
- len
;
1124 if (!nb_digits
|| nb_digits
> 7 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1125 for (i
= 0; i
< nb_digits
; i
++)
1132 else return WS_E_INVALID_FORMAT
;
1134 if ((len_utf8
= codepoint_to_utf8( cp
, q
)) < 0) return WS_E_INVALID_FORMAT
;
1135 *ret_len
+= len_utf8
;
1139 else return WS_E_INVALID_FORMAT
;
1151 static HRESULT
read_attribute_value_text( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1153 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1154 unsigned int len
, ch
, skip
, quote
;
1155 const unsigned char *start
;
1156 HRESULT hr
= E_OUTOFMEMORY
;
1158 read_skip_whitespace( reader
);
1159 if (read_cmp( reader
, "=", 1 )) return WS_E_INVALID_FORMAT
;
1160 read_skip( reader
, 1 );
1162 read_skip_whitespace( reader
);
1163 if (read_cmp( reader
, "\"", 1 ) && read_cmp( reader
, "'", 1 )) return WS_E_INVALID_FORMAT
;
1164 quote
= read_utf8_char( reader
, &skip
);
1165 read_skip( reader
, 1 );
1168 start
= read_current_ptr( reader
);
1171 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1172 if (ch
== quote
) break;
1173 read_skip( reader
, skip
);
1176 read_skip( reader
, 1 );
1180 if (!(attr
->ns
= alloc_xml_string( start
, len
))) goto error
;
1181 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1182 if (!(utf8
= alloc_utf8_text( NULL
, 0 )))
1190 if (!(utf8
= alloc_utf8_text( NULL
, len
))) goto error
;
1191 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
) goto error
;
1194 attr
->value
= &utf8
->text
;
1195 attr
->singleQuote
= (quote
== '\'');
1203 static inline BOOL
is_text_type( unsigned char type
)
1205 return (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
);
1208 static HRESULT
read_int31( struct reader
*reader
, ULONG
*len
)
1213 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1215 if (!(byte
& 0x80)) return S_OK
;
1217 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1218 *len
+= (byte
& 0x7f) << 7;
1219 if (!(byte
& 0x80)) return S_OK
;
1221 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1222 *len
+= (byte
& 0x7f) << 14;
1223 if (!(byte
& 0x80)) return S_OK
;
1225 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1226 *len
+= (byte
& 0x7f) << 21;
1227 if (!(byte
& 0x80)) return S_OK
;
1229 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1230 *len
+= (byte
& 0x07) << 28;
1234 static HRESULT
read_string( struct reader
*reader
, WS_XML_STRING
**str
)
1238 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
1239 if (!(*str
= alloc_xml_string( NULL
, len
))) return E_OUTOFMEMORY
;
1240 if ((hr
= read_bytes( reader
, (*str
)->bytes
, len
)) == S_OK
)
1242 if (add_xml_string( *str
) != S_OK
) WARN( "string not added to dictionary\n" );
1245 free_xml_string( *str
);
1249 static HRESULT
read_dict_string( struct reader
*reader
, WS_XML_STRING
**str
)
1251 const WS_XML_DICTIONARY
*dict
;
1255 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1256 dict
= (id
& 1) ? reader
->dict
: reader
->dict_static
;
1257 if (!dict
|| (id
>>= 1) >= dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1258 if (!(*str
= alloc_xml_string( NULL
, 0 ))) return E_OUTOFMEMORY
;
1259 *(*str
) = dict
->strings
[id
];
1263 static HRESULT
read_datetime( struct reader
*reader
, WS_DATETIME
*ret
)
1268 if ((hr
= read_bytes( reader
, (unsigned char *)&val
, sizeof(val
) )) != S_OK
) return hr
;
1270 if ((val
& 0x03) == 1) ret
->format
= WS_DATETIME_FORMAT_UTC
;
1271 else if ((val
& 0x03) == 2) ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
1272 else ret
->format
= WS_DATETIME_FORMAT_NONE
;
1274 if ((ret
->ticks
= val
>> 2) > TICKS_MAX
) return WS_E_INVALID_FORMAT
;
1278 static HRESULT
read_encode_base64( struct reader
*reader
, ULONG len
, unsigned char *buf
, ULONG
*ret_len
)
1280 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1287 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1288 buf
[i
++] = base64
[(byte
& 0xfc) >> 2];
1289 x
= (byte
& 3) << 4;
1292 buf
[i
++] = base64
[x
];
1297 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1298 buf
[i
++] = base64
[x
| ((byte
& 0xf0) >> 4)];
1299 x
= (byte
& 0x0f) << 2;
1302 buf
[i
++] = base64
[x
];
1306 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1307 buf
[i
++] = base64
[x
| ((byte
& 0xc0) >> 6)];
1308 buf
[i
++] = base64
[byte
& 0x3f];
1315 static HRESULT
read_attribute_value_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1317 static const unsigned char zero
[] = {'0'}, one
[] = {'1'};
1318 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1319 WS_XML_UTF8_TEXT
*utf8
= NULL
;
1320 unsigned char type
, buf
[46];
1330 WS_DATETIME datetime
;
1335 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1336 if (!is_text_type( type
)) return WS_E_INVALID_FORMAT
;
1340 case RECORD_ZERO_TEXT
:
1341 if (!(utf8
= alloc_utf8_text( zero
, sizeof(zero
) ))) return E_OUTOFMEMORY
;
1344 case RECORD_ONE_TEXT
:
1345 if (!(utf8
= alloc_utf8_text( one
, sizeof(one
) ))) return E_OUTOFMEMORY
;
1348 case RECORD_FALSE_TEXT
:
1349 if (!(utf8
= alloc_utf8_text( false, sizeof(false) ))) return E_OUTOFMEMORY
;
1352 case RECORD_TRUE_TEXT
:
1353 if (!(utf8
= alloc_utf8_text( true, sizeof(true) ))) return E_OUTOFMEMORY
;
1356 case RECORD_INT8_TEXT
:
1357 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
1358 len
= format_int8( &val_int8
, buf
);
1359 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1362 case RECORD_INT16_TEXT
:
1363 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
1364 len
= format_int16( &val_int16
, buf
);
1365 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1368 case RECORD_INT32_TEXT
:
1369 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1370 len
= format_int32( &val_int32
, buf
);
1371 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1374 case RECORD_INT64_TEXT
:
1375 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
1376 len
= format_int64( &val_int64
, buf
);
1377 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1380 case RECORD_DOUBLE_TEXT
:
1381 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
1382 len
= format_double( &val_double
, buf
);
1383 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1386 case RECORD_DATETIME_TEXT
:
1387 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
1388 len
= format_datetime( &datetime
, buf
);
1389 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1392 case RECORD_CHARS8_TEXT
:
1393 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1397 case RECORD_CHARS16_TEXT
:
1398 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
1402 case RECORD_CHARS32_TEXT
:
1403 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1404 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1408 case RECORD_BYTES8_TEXT
:
1409 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1410 if (!(utf8
= alloc_utf8_text( NULL
, ((4 * val_uint8
/ 3) + 3) & ~3 ))) return E_OUTOFMEMORY
;
1411 if ((hr
= read_encode_base64( reader
, val_uint8
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1418 case RECORD_BYTES16_TEXT
:
1419 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint16
)) != S_OK
) return hr
;
1420 if (!(utf8
= alloc_utf8_text( NULL
, ((4 * val_uint16
/ 3) + 3) & ~3 ))) return E_OUTOFMEMORY
;
1421 if ((hr
= read_encode_base64( reader
, val_uint16
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1428 case RECORD_BYTES32_TEXT
:
1429 if ((hr
= read_byte( reader
, (unsigned char *)&val_int32
)) != S_OK
) return hr
;
1430 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1431 if (!(utf8
= alloc_utf8_text( NULL
, ((4 * val_int32
/ 3) + 3) & ~3 ))) return E_OUTOFMEMORY
;
1432 if ((hr
= read_encode_base64( reader
, val_int32
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1439 case RECORD_EMPTY_TEXT
:
1443 case RECORD_DICTIONARY_TEXT
:
1444 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1445 if (!reader
->dict
|| (id
>>= 1) >= reader
->dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1446 if (!(utf8
= alloc_utf8_text( reader
->dict
->strings
[id
].bytes
, reader
->dict
->strings
[id
].length
)))
1447 return E_OUTOFMEMORY
;
1450 case RECORD_UNIQUEID_TEXT
:
1451 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
1452 len
= format_urn( &uuid
, buf
);
1453 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1456 case RECORD_UUID_TEXT
:
1457 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
1458 len
= format_guid( &uuid
, buf
);
1459 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1462 case RECORD_UINT64_TEXT
:
1463 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
1464 len
= format_uint64( &val_uint64
, buf
);
1465 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1468 case RECORD_BOOL_TEXT
:
1469 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
1470 len
= format_bool( &val_bool
, buf
);
1471 if (!(utf8
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1475 ERR( "unhandled record type %02x\n", type
);
1476 return WS_E_NOT_SUPPORTED
;
1481 if (!(utf8
= alloc_utf8_text( NULL
, len
))) return E_OUTOFMEMORY
;
1482 if (!len
) utf8
->value
.bytes
= (BYTE
*)(utf8
+ 1); /* quirk */
1483 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
1490 attr
->value
= &utf8
->text
;
1494 static HRESULT
read_attribute_text( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1496 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1497 WS_XML_ATTRIBUTE
*attr
;
1498 unsigned int len
= 0, ch
, skip
;
1499 const unsigned char *start
;
1500 WS_XML_STRING
*prefix
, *localname
;
1501 HRESULT hr
= WS_E_INVALID_FORMAT
;
1503 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1505 start
= read_current_ptr( reader
);
1508 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1509 if (!read_isnamechar( ch
)) break;
1510 read_skip( reader
, skip
);
1513 if (!len
) goto error
;
1515 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1516 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1518 free_xml_string( prefix
);
1520 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1522 free_xml_string( localname
);
1526 attr
->localName
= localname
;
1528 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1531 attr
->prefix
= prefix
;
1532 attr
->localName
= localname
;
1536 attr
->prefix
= prefix
;
1537 attr
->localName
= localname
;
1540 if ((hr
= read_attribute_value_text( reader
, attr
)) != S_OK
) goto error
;
1546 free_attribute( attr
);
1550 static inline BOOL
is_attribute_type( unsigned char type
)
1552 return (type
>= RECORD_SHORT_ATTRIBUTE
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
);
1555 static HRESULT
read_attribute_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1557 WS_XML_ATTRIBUTE
*attr
;
1558 unsigned char type
= 0;
1561 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1562 if (!is_attribute_type( type
)) return WS_E_INVALID_FORMAT
;
1563 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1565 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1567 unsigned char ch
= type
- RECORD_PREFIX_ATTRIBUTE_A
+ 'a';
1568 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1573 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1574 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1576 else if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1578 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ 'a';
1579 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1584 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1585 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1591 case RECORD_SHORT_ATTRIBUTE
:
1592 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1597 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1598 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1601 case RECORD_ATTRIBUTE
:
1602 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1603 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1604 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1607 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1608 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1613 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1614 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1617 case RECORD_DICTIONARY_ATTRIBUTE
:
1618 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1619 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1620 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1623 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1624 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1629 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1630 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1634 case RECORD_XMLNS_ATTRIBUTE
:
1635 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1636 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1637 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1641 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1642 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1647 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1648 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1652 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1653 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1654 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1655 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1660 ERR( "unhandled record type %02x\n", type
);
1661 return WS_E_NOT_SUPPORTED
;
1669 free_attribute( attr
);
1673 static inline struct node
*find_parent( struct reader
*reader
)
1675 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1677 if (is_valid_parent( reader
->current
->parent
->parent
)) return reader
->current
->parent
->parent
;
1680 if (is_valid_parent( reader
->current
)) return reader
->current
;
1681 if (is_valid_parent( reader
->current
->parent
)) return reader
->current
->parent
;
1685 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1687 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1688 const WS_XML_STRING
*ns
;
1691 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1692 if (!(elem
->ns
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
1694 for (i
= 0; i
< elem
->attributeCount
; i
++)
1696 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1697 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1698 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1699 if (!(attr
->ns
= alloc_xml_string( NULL
, ns
->length
))) return E_OUTOFMEMORY
;
1700 if (attr
->ns
->length
) memcpy( attr
->ns
->bytes
, ns
->bytes
, ns
->length
);
1705 static WS_XML_ELEMENT_NODE
*alloc_element_pair(void)
1707 struct node
*node
, *end
;
1708 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
1709 if (!(end
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
)))
1714 list_add_tail( &node
->children
, &end
->entry
);
1719 static HRESULT
read_attributes_text( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1721 WS_XML_ATTRIBUTE
*attr
;
1724 reader
->current_attr
= 0;
1727 read_skip_whitespace( reader
);
1728 if (!read_cmp( reader
, ">", 1 ) || !read_cmp( reader
, "/>", 2 )) break;
1729 if ((hr
= read_attribute_text( reader
, &attr
)) != S_OK
) return hr
;
1730 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1732 free_attribute( attr
);
1735 reader
->current_attr
++;
1740 static HRESULT
read_element_text( struct reader
*reader
)
1742 unsigned int len
= 0, ch
, skip
;
1743 const unsigned char *start
;
1744 struct node
*node
= NULL
, *parent
;
1745 WS_XML_ELEMENT_NODE
*elem
;
1746 HRESULT hr
= WS_E_INVALID_FORMAT
;
1748 if (read_end_of_data( reader
))
1750 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1751 reader
->last
= reader
->current
;
1752 reader
->state
= READER_STATE_EOF
;
1756 if (read_cmp( reader
, "<", 1 )) return WS_E_INVALID_FORMAT
;
1757 read_skip( reader
, 1 );
1758 if (!read_isnamechar( read_utf8_char( reader
, &skip
)))
1760 read_rewind( reader
, 1 );
1761 return WS_E_INVALID_FORMAT
;
1764 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1765 node
= (struct node
*)elem
;
1767 start
= read_current_ptr( reader
);
1770 if (!(ch
= read_utf8_char( reader
, &skip
))) goto error
;
1771 if (!read_isnamechar( ch
)) break;
1772 read_skip( reader
, skip
);
1775 if (!len
) goto error
;
1777 if (!(parent
= find_parent( reader
))) goto error
;
1778 if ((hr
= parse_name( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
1780 if ((hr
= read_attributes_text( reader
, elem
)) != S_OK
) goto error
;
1781 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1783 read_insert_node( reader
, parent
, node
);
1784 reader
->state
= READER_STATE_STARTELEMENT
;
1788 destroy_nodes( node
);
1792 static inline BOOL
is_element_type( unsigned char type
)
1794 return (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
);
1797 static HRESULT
read_attributes_bin( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1799 WS_XML_ATTRIBUTE
*attr
;
1803 reader
->current_attr
= 0;
1806 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
1807 if (!is_attribute_type( type
)) break;
1808 if ((hr
= read_attribute_bin( reader
, &attr
)) != S_OK
) return hr
;
1809 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1811 free_attribute( attr
);
1814 reader
->current_attr
++;
1819 static HRESULT
read_element_bin( struct reader
*reader
)
1821 struct node
*node
= NULL
, *parent
;
1822 WS_XML_ELEMENT_NODE
*elem
;
1826 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1827 if (!is_element_type( type
)) return WS_E_INVALID_FORMAT
;
1829 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
1830 node
= (struct node
*)elem
;
1832 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1834 unsigned char ch
= type
- RECORD_PREFIX_ELEMENT_A
+ 'a';
1835 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1840 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1842 else if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1844 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ 'a';
1845 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
1850 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1856 case RECORD_SHORT_ELEMENT
:
1857 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1862 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1865 case RECORD_ELEMENT
:
1866 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1867 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1870 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1871 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
1876 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1879 case RECORD_DICTIONARY_ELEMENT
:
1880 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
1881 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
1885 ERR( "unhandled record type %02x\n", type
);
1886 return WS_E_NOT_SUPPORTED
;
1890 if (!(parent
= find_parent( reader
)))
1892 hr
= WS_E_INVALID_FORMAT
;
1896 if ((hr
= read_attributes_bin( reader
, elem
)) != S_OK
) goto error
;
1897 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
1899 read_insert_node( reader
, parent
, node
);
1900 reader
->state
= READER_STATE_STARTELEMENT
;
1904 destroy_nodes( node
);
1908 static HRESULT
read_text_text( struct reader
*reader
)
1910 unsigned int len
= 0, ch
, skip
;
1911 const unsigned char *start
;
1912 struct node
*node
, *parent
;
1913 WS_XML_TEXT_NODE
*text
;
1914 WS_XML_UTF8_TEXT
*utf8
;
1917 start
= read_current_ptr( reader
);
1920 if (read_end_of_data( reader
)) break;
1921 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
1922 if (ch
== '<') break;
1923 read_skip( reader
, skip
);
1927 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1929 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1930 text
= (WS_XML_TEXT_NODE
*)node
;
1931 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
1934 return E_OUTOFMEMORY
;
1936 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1942 text
->text
= &utf8
->text
;
1944 read_insert_node( reader
, parent
, node
);
1945 reader
->state
= READER_STATE_TEXT
;
1946 reader
->text_conv_offset
= 0;
1950 static struct node
*alloc_text_node( const unsigned char *data
, ULONG len
, WS_XML_UTF8_TEXT
**ret
)
1953 WS_XML_UTF8_TEXT
*utf8
;
1954 WS_XML_TEXT_NODE
*text
;
1956 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
1957 if (!(utf8
= alloc_utf8_text( data
, len
)))
1962 text
= (WS_XML_TEXT_NODE
*)node
;
1963 text
->text
= &utf8
->text
;
1964 if (ret
) *ret
= utf8
;
1968 static HRESULT
read_text_bin( struct reader
*reader
)
1970 static const unsigned char zero
[] = {'0'}, one
[] = {'1'};
1971 static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
1972 unsigned char type
, buf
[46];
1973 struct node
*node
= NULL
, *parent
;
1974 WS_XML_UTF8_TEXT
*utf8
;
1984 WS_DATETIME datetime
;
1989 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
1990 if (!is_text_type( type
) || !(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
1994 case RECORD_ZERO_TEXT
:
1995 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
1996 if (!(node
= alloc_text_node( zero
, sizeof(zero
), NULL
))) return E_OUTOFMEMORY
;
1999 case RECORD_ONE_TEXT
:
2000 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2001 if (!(node
= alloc_text_node( one
, sizeof(one
), NULL
))) return E_OUTOFMEMORY
;
2004 case RECORD_FALSE_TEXT
:
2005 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2006 if (!(node
= alloc_text_node( false, sizeof(false), NULL
))) return E_OUTOFMEMORY
;
2009 case RECORD_TRUE_TEXT
:
2010 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2011 if (!(node
= alloc_text_node( true, sizeof(true), NULL
))) return E_OUTOFMEMORY
;
2014 case RECORD_INT8_TEXT
:
2015 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2016 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
2017 len
= format_int8( &val_int8
, buf
);
2018 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2021 case RECORD_INT16_TEXT
:
2022 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2023 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
2024 len
= format_int16( &val_int16
, buf
);
2025 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2028 case RECORD_INT32_TEXT
:
2029 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2030 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2031 len
= format_int32( &val_int32
, buf
);
2032 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2035 case RECORD_INT64_TEXT
:
2036 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2037 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
2038 len
= format_int64( &val_int64
, buf
);
2039 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2042 case RECORD_DOUBLE_TEXT
:
2043 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2044 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
2045 len
= format_double( &val_double
, buf
);
2046 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2049 case RECORD_DATETIME_TEXT
:
2050 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2051 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
2052 len
= format_datetime( &datetime
, buf
);
2053 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2056 case RECORD_CHARS8_TEXT
:
2057 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2058 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
2062 case RECORD_CHARS16_TEXT
:
2063 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2064 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
2068 case RECORD_CHARS32_TEXT
:
2069 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT
:
2070 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2071 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
2075 case RECORD_BYTES8_TEXT
:
2076 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT
:
2077 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
2078 if (!(node
= alloc_text_node( NULL
, ((4 * val_uint8
/ 3) + 3) & ~3, &utf8
))) return E_OUTOFMEMORY
;
2079 if ((hr
= read_encode_base64( reader
, val_uint8
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
2086 case RECORD_BYTES16_TEXT
:
2087 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT
:
2088 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint16
)) != S_OK
) return hr
;
2089 if (!(node
= alloc_text_node( NULL
, ((4 * val_uint16
/ 3) + 3) & ~3, &utf8
))) return E_OUTOFMEMORY
;
2090 if ((hr
= read_encode_base64( reader
, val_uint16
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
2097 case RECORD_BYTES32_TEXT
:
2098 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT
:
2099 if ((hr
= read_byte( reader
, (unsigned char *)&val_int32
)) != S_OK
) return hr
;
2100 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
2101 if (!(node
= alloc_text_node( NULL
, ((4 * val_int32
/ 3) + 3) & ~3, &utf8
))) return E_OUTOFMEMORY
;
2102 if ((hr
= read_encode_base64( reader
, val_int32
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
2109 case RECORD_EMPTY_TEXT
:
2110 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT
:
2114 case RECORD_DICTIONARY_TEXT
:
2115 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2116 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
2117 if (!reader
->dict
|| (id
>>= 1) >= reader
->dict
->stringCount
) return WS_E_INVALID_FORMAT
;
2118 if (!(node
= alloc_text_node( reader
->dict
->strings
[id
].bytes
, reader
->dict
->strings
[id
].length
, NULL
)))
2119 return E_OUTOFMEMORY
;
2122 case RECORD_UNIQUEID_TEXT
:
2123 case RECORD_UNIQUEID_TEXT_WITH_ENDELEMENT
:
2124 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2125 len
= format_urn( &uuid
, buf
);
2126 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2129 case RECORD_UUID_TEXT
:
2130 case RECORD_UUID_TEXT_WITH_ENDELEMENT
:
2131 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2132 len
= format_guid( &uuid
, buf
);
2133 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2136 case RECORD_UINT64_TEXT
:
2137 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2138 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
2139 len
= format_uint64( &val_uint64
, buf
);
2140 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2143 case RECORD_BOOL_TEXT
:
2144 case RECORD_BOOL_TEXT_WITH_ENDELEMENT
:
2145 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
2146 len
= format_bool( &val_bool
, buf
);
2147 if (!(node
= alloc_text_node( buf
, len
, NULL
))) return E_OUTOFMEMORY
;
2151 ERR( "unhandled record type %02x\n", type
);
2152 return WS_E_NOT_SUPPORTED
;
2157 if (!(node
= alloc_text_node( NULL
, len
, &utf8
))) return E_OUTOFMEMORY
;
2158 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
2165 read_insert_node( reader
, parent
, node
);
2166 reader
->state
= READER_STATE_TEXT
;
2167 reader
->text_conv_offset
= 0;
2171 static HRESULT
read_node_text( struct reader
* );
2173 static HRESULT
read_startelement_text( struct reader
*reader
)
2175 read_skip_whitespace( reader
);
2176 if (!read_cmp( reader
, "/>", 2 ))
2178 read_skip( reader
, 2 );
2179 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->children
), struct node
, entry
);
2180 reader
->last
= reader
->current
;
2181 reader
->state
= READER_STATE_ENDELEMENT
;
2184 else if (!read_cmp( reader
, ">", 1 ))
2186 read_skip( reader
, 1 );
2187 return read_node_text( reader
);
2189 return WS_E_INVALID_FORMAT
;
2192 static HRESULT
read_node_bin( struct reader
* );
2194 static HRESULT
read_startelement_bin( struct reader
*reader
)
2196 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
2197 return read_node_bin( reader
);
2200 static HRESULT
read_startelement( struct reader
*reader
)
2202 switch (reader
->input_enc
)
2204 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_startelement_text( reader
);
2205 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_startelement_bin( reader
);
2207 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2208 return WS_E_NOT_SUPPORTED
;
2212 static HRESULT
read_to_startelement_text( struct reader
*reader
, BOOL
*found
)
2216 switch (reader
->state
)
2218 case READER_STATE_INITIAL
:
2219 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
2222 case READER_STATE_STARTELEMENT
:
2223 if (found
) *found
= TRUE
;
2230 read_skip_whitespace( reader
);
2231 if ((hr
= read_element_text( reader
)) == S_OK
&& found
)
2233 if (reader
->state
== READER_STATE_STARTELEMENT
)
2242 static HRESULT
read_to_startelement_bin( struct reader
*reader
, BOOL
*found
)
2246 if (reader
->state
== READER_STATE_STARTELEMENT
)
2248 if (found
) *found
= TRUE
;
2252 if ((hr
= read_element_bin( reader
)) == S_OK
&& found
)
2254 if (reader
->state
== READER_STATE_STARTELEMENT
)
2263 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
2265 switch (reader
->input_enc
)
2267 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_to_startelement_text( reader
, found
);
2268 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_to_startelement_bin( reader
, found
);
2270 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2271 return WS_E_NOT_SUPPORTED
;
2275 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
2278 if (len1
!= len2
) return 1;
2279 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
2283 static struct node
*find_startelement( struct reader
*reader
, const WS_XML_STRING
*prefix
,
2284 const WS_XML_STRING
*localname
)
2286 struct node
*parent
;
2287 const WS_XML_STRING
*str
;
2289 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
2291 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2293 str
= parent
->hdr
.prefix
;
2294 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
2295 str
= parent
->hdr
.localName
;
2296 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
2303 static HRESULT
read_endelement_text( struct reader
*reader
)
2305 struct node
*parent
;
2306 unsigned int len
= 0, ch
, skip
;
2307 const unsigned char *start
;
2308 WS_XML_STRING
*prefix
, *localname
;
2311 if (read_cmp( reader
, "</", 2 )) return WS_E_INVALID_FORMAT
;
2312 read_skip( reader
, 2 );
2314 start
= read_current_ptr( reader
);
2317 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2320 read_skip( reader
, 1 );
2323 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
2324 read_skip( reader
, skip
);
2328 if ((hr
= parse_name( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
2329 parent
= find_startelement( reader
, prefix
, localname
);
2330 free_xml_string( prefix
);
2331 free_xml_string( localname
);
2332 if (!parent
) return WS_E_INVALID_FORMAT
;
2334 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2335 reader
->last
= reader
->current
;
2336 reader
->state
= READER_STATE_ENDELEMENT
;
2340 static HRESULT
read_endelement_bin( struct reader
*reader
)
2342 struct node
*parent
;
2346 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2347 if (type
!= RECORD_ENDELEMENT
) return WS_E_INVALID_FORMAT
;
2349 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2351 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2352 reader
->last
= reader
->current
;
2353 reader
->state
= READER_STATE_ENDELEMENT
;
2357 static HRESULT
read_endelement( struct reader
*reader
)
2359 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
2361 if (read_end_of_data( reader
))
2363 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2364 reader
->last
= reader
->current
;
2365 reader
->state
= READER_STATE_EOF
;
2369 switch (reader
->input_enc
)
2371 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_endelement_text( reader
);
2372 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_endelement_bin( reader
);
2374 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2375 return WS_E_NOT_SUPPORTED
;
2379 static HRESULT
read_comment_text( struct reader
*reader
)
2381 unsigned int len
= 0, ch
, skip
;
2382 const unsigned char *start
;
2383 struct node
*node
, *parent
;
2384 WS_XML_COMMENT_NODE
*comment
;
2386 if (read_cmp( reader
, "<!--", 4 )) return WS_E_INVALID_FORMAT
;
2387 read_skip( reader
, 4 );
2389 start
= read_current_ptr( reader
);
2392 if (!read_cmp( reader
, "-->", 3 ))
2394 read_skip( reader
, 3 );
2397 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2398 read_skip( reader
, skip
);
2402 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2404 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2405 comment
= (WS_XML_COMMENT_NODE
*)node
;
2406 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2409 return E_OUTOFMEMORY
;
2411 memcpy( comment
->value
.bytes
, start
, len
);
2412 comment
->value
.length
= len
;
2414 read_insert_node( reader
, parent
, node
);
2415 reader
->state
= READER_STATE_COMMENT
;
2419 static HRESULT
read_comment_bin( struct reader
*reader
)
2421 struct node
*node
, *parent
;
2422 WS_XML_COMMENT_NODE
*comment
;
2427 if ((hr
= read_byte( reader
, &type
)) != S_OK
) return hr
;
2428 if (type
!= RECORD_COMMENT
) return WS_E_INVALID_FORMAT
;
2429 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
2431 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2433 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2434 comment
= (WS_XML_COMMENT_NODE
*)node
;
2435 if (!(comment
->value
.bytes
= heap_alloc( len
)))
2438 return E_OUTOFMEMORY
;
2440 if ((hr
= read_bytes( reader
, comment
->value
.bytes
, len
)) != S_OK
)
2443 return E_OUTOFMEMORY
;
2445 comment
->value
.length
= len
;
2447 read_insert_node( reader
, parent
, node
);
2448 reader
->state
= READER_STATE_COMMENT
;
2452 static HRESULT
read_startcdata( struct reader
*reader
)
2454 struct node
*node
, *endnode
, *parent
;
2456 if (read_cmp( reader
, "<![CDATA[", 9 )) return WS_E_INVALID_FORMAT
;
2457 read_skip( reader
, 9 );
2459 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2461 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2462 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
)))
2465 return E_OUTOFMEMORY
;
2467 list_add_tail( &node
->children
, &endnode
->entry
);
2468 endnode
->parent
= node
;
2470 read_insert_node( reader
, parent
, node
);
2471 reader
->state
= READER_STATE_STARTCDATA
;
2475 static HRESULT
read_cdata( struct reader
*reader
)
2477 unsigned int len
= 0, ch
, skip
;
2478 const unsigned char *start
;
2480 WS_XML_TEXT_NODE
*text
;
2481 WS_XML_UTF8_TEXT
*utf8
;
2483 start
= read_current_ptr( reader
);
2486 if (!read_cmp( reader
, "]]>", 3 )) break;
2487 if (!(ch
= read_utf8_char( reader
, &skip
))) return WS_E_INVALID_FORMAT
;
2488 read_skip( reader
, skip
);
2492 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2493 text
= (WS_XML_TEXT_NODE
*)node
;
2494 if (!(utf8
= alloc_utf8_text( start
, len
)))
2497 return E_OUTOFMEMORY
;
2499 text
->text
= &utf8
->text
;
2501 read_insert_node( reader
, reader
->current
, node
);
2502 reader
->state
= READER_STATE_CDATA
;
2506 static HRESULT
read_endcdata( struct reader
*reader
)
2508 struct node
*parent
;
2510 if (read_cmp( reader
, "]]>", 3 )) return WS_E_INVALID_FORMAT
;
2511 read_skip( reader
, 3 );
2513 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
) parent
= reader
->current
->parent
;
2514 else parent
= reader
->current
;
2516 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2517 reader
->last
= reader
->current
;
2518 reader
->state
= READER_STATE_ENDCDATA
;
2522 static HRESULT
read_node_text( struct reader
*reader
)
2528 if (read_end_of_data( reader
))
2530 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2531 reader
->last
= reader
->current
;
2532 reader
->state
= READER_STATE_EOF
;
2535 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
2536 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
2537 else if (!read_cmp( reader
, "<?", 2 ))
2539 hr
= read_xmldecl( reader
);
2540 if (FAILED( hr
)) return hr
;
2542 else if (!read_cmp( reader
, "</", 2 )) return read_endelement_text( reader
);
2543 else if (!read_cmp( reader
, "<![CDATA[", 9 )) return read_startcdata( reader
);
2544 else if (!read_cmp( reader
, "<!--", 4 )) return read_comment_text( reader
);
2545 else if (!read_cmp( reader
, "<", 1 )) return read_element_text( reader
);
2546 else if (!read_cmp( reader
, "/>", 2 ) || !read_cmp( reader
, ">", 1 )) return read_startelement_text( reader
);
2547 else return read_text_text( reader
);
2551 static HRESULT
read_node_bin( struct reader
*reader
)
2556 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
)
2558 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->parent
->children
), struct node
, entry
);
2559 reader
->last
= reader
->current
;
2560 reader
->state
= READER_STATE_ENDELEMENT
;
2563 if (read_end_of_data( reader
))
2565 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2566 reader
->last
= reader
->current
;
2567 reader
->state
= READER_STATE_EOF
;
2571 if ((hr
= read_peek( reader
, &type
)) != S_OK
) return hr
;
2572 if (type
== RECORD_ENDELEMENT
)
2574 return read_endelement_bin( reader
);
2576 else if (type
== RECORD_COMMENT
)
2578 return read_comment_bin( reader
);
2580 else if (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
2582 return read_element_bin( reader
);
2584 else if (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
)
2586 return read_text_bin( reader
);
2588 FIXME( "unhandled record type %02x\n", type
);
2589 return WS_E_NOT_SUPPORTED
;
2592 static HRESULT
read_node( struct reader
*reader
)
2594 switch (reader
->input_enc
)
2596 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_node_text( reader
);
2597 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_node_bin( reader
);
2599 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2600 return WS_E_NOT_SUPPORTED
;
2604 HRESULT
copy_node( WS_XML_READER
*handle
, struct node
**node
)
2606 struct reader
*reader
= (struct reader
*)handle
;
2607 const struct list
*ptr
;
2608 const struct node
*start
;
2611 EnterCriticalSection( &reader
->cs
);
2613 if (reader
->magic
!= READER_MAGIC
)
2615 LeaveCriticalSection( &reader
->cs
);
2616 return E_INVALIDARG
;
2619 if (reader
->current
!= reader
->root
) ptr
= &reader
->current
->entry
;
2620 else /* copy whole tree */
2622 if (!read_end_of_data( reader
))
2626 if ((hr
= read_node( reader
)) != S_OK
) goto done
;
2627 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) break;
2630 ptr
= list_head( &reader
->root
->children
);
2633 start
= LIST_ENTRY( ptr
, struct node
, entry
);
2634 if (node_type( start
) == WS_XML_NODE_TYPE_EOF
) hr
= WS_E_INVALID_OPERATION
;
2635 else hr
= dup_tree( node
, start
);
2638 LeaveCriticalSection( &reader
->cs
);
2642 /**************************************************************************
2643 * WsReadEndElement [webservices.@]
2645 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2647 struct reader
*reader
= (struct reader
*)handle
;
2650 TRACE( "%p %p\n", handle
, error
);
2651 if (error
) FIXME( "ignoring error parameter\n" );
2653 if (!reader
) return E_INVALIDARG
;
2655 EnterCriticalSection( &reader
->cs
);
2657 if (reader
->magic
!= READER_MAGIC
)
2659 LeaveCriticalSection( &reader
->cs
);
2660 return E_INVALIDARG
;
2663 hr
= read_endelement( reader
);
2665 LeaveCriticalSection( &reader
->cs
);
2669 /**************************************************************************
2670 * WsReadNode [webservices.@]
2672 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2674 struct reader
*reader
= (struct reader
*)handle
;
2677 TRACE( "%p %p\n", handle
, error
);
2678 if (error
) FIXME( "ignoring error parameter\n" );
2680 if (!reader
) return E_INVALIDARG
;
2682 EnterCriticalSection( &reader
->cs
);
2684 if (reader
->magic
!= READER_MAGIC
)
2686 LeaveCriticalSection( &reader
->cs
);
2687 return E_INVALIDARG
;
2690 hr
= read_node( reader
);
2692 LeaveCriticalSection( &reader
->cs
);
2696 static HRESULT
skip_node( struct reader
*reader
)
2698 const struct node
*parent
;
2701 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) return WS_E_INVALID_OPERATION
;
2702 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_ELEMENT
) parent
= reader
->current
;
2707 if ((hr
= read_node( reader
) != S_OK
) || !parent
) break;
2708 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_END_ELEMENT
) continue;
2709 if (reader
->current
->parent
== parent
) return read_node( reader
);
2715 /**************************************************************************
2716 * WsSkipNode [webservices.@]
2718 HRESULT WINAPI
WsSkipNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
2720 struct reader
*reader
= (struct reader
*)handle
;
2723 TRACE( "%p %p\n", handle
, error
);
2724 if (error
) FIXME( "ignoring error parameter\n" );
2726 if (!reader
) return E_INVALIDARG
;
2728 EnterCriticalSection( &reader
->cs
);
2730 if (reader
->magic
!= READER_MAGIC
)
2732 LeaveCriticalSection( &reader
->cs
);
2733 return E_INVALIDARG
;
2736 hr
= skip_node( reader
);
2738 LeaveCriticalSection( &reader
->cs
);
2742 /**************************************************************************
2743 * WsReadStartElement [webservices.@]
2745 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
2747 struct reader
*reader
= (struct reader
*)handle
;
2750 TRACE( "%p %p\n", handle
, error
);
2751 if (error
) FIXME( "ignoring error parameter\n" );
2753 if (!reader
) return E_INVALIDARG
;
2755 EnterCriticalSection( &reader
->cs
);
2757 if (reader
->magic
!= READER_MAGIC
)
2759 LeaveCriticalSection( &reader
->cs
);
2760 return E_INVALIDARG
;
2763 hr
= read_startelement( reader
);
2765 LeaveCriticalSection( &reader
->cs
);
2769 /**************************************************************************
2770 * WsReadToStartElement [webservices.@]
2772 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
2773 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
2775 struct reader
*reader
= (struct reader
*)handle
;
2778 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
2779 if (error
) FIXME( "ignoring error parameter\n" );
2781 if (!reader
) return E_INVALIDARG
;
2782 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
2784 EnterCriticalSection( &reader
->cs
);
2786 if (reader
->magic
!= READER_MAGIC
)
2788 LeaveCriticalSection( &reader
->cs
);
2789 return E_INVALIDARG
;
2792 hr
= read_to_startelement( reader
, found
);
2794 LeaveCriticalSection( &reader
->cs
);
2798 BOOL
move_to_root_element( struct node
*root
, struct node
**current
)
2803 if (!(ptr
= list_head( &root
->children
))) return FALSE
;
2804 node
= LIST_ENTRY( ptr
, struct node
, entry
);
2805 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
2810 while ((ptr
= list_next( &root
->children
, &node
->entry
)))
2812 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2813 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2823 BOOL
move_to_next_element( struct node
**current
)
2826 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2828 if (!parent
) return FALSE
;
2829 while ((ptr
= list_next( &parent
->children
, &node
->entry
)))
2831 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2832 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2842 BOOL
move_to_prev_element( struct node
**current
)
2845 struct node
*node
= *current
, *parent
= (*current
)->parent
;
2847 if (!parent
) return FALSE
;
2848 while ((ptr
= list_prev( &parent
->children
, &node
->entry
)))
2850 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
2851 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
2861 BOOL
move_to_child_element( struct node
**current
)
2864 struct node
*child
, *node
= *current
;
2866 if (!(ptr
= list_head( &node
->children
))) return FALSE
;
2867 child
= LIST_ENTRY( ptr
, struct node
, entry
);
2868 if (node_type( child
) == WS_XML_NODE_TYPE_ELEMENT
)
2873 while ((ptr
= list_next( &node
->children
, &child
->entry
)))
2875 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
2876 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
2886 BOOL
move_to_end_element( struct node
**current
)
2889 struct node
*node
= *current
;
2891 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
2893 if ((ptr
= list_tail( &node
->children
)))
2895 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
2896 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
2905 BOOL
move_to_parent_element( struct node
**current
)
2907 struct node
*parent
= (*current
)->parent
;
2909 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
2910 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
2918 BOOL
move_to_first_node( struct node
**current
)
2921 struct node
*node
= *current
;
2923 if ((ptr
= list_head( &node
->parent
->children
)))
2925 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2931 BOOL
move_to_next_node( struct node
**current
)
2934 struct node
*node
= *current
;
2936 if ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
2938 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2944 BOOL
move_to_prev_node( struct node
**current
)
2947 struct node
*node
= *current
;
2949 if ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
2951 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2957 BOOL
move_to_bof( struct node
*root
, struct node
**current
)
2963 BOOL
move_to_eof( struct node
*root
, struct node
**current
)
2966 if ((ptr
= list_tail( &root
->children
)))
2968 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2974 BOOL
move_to_child_node( struct node
**current
)
2977 struct node
*node
= *current
;
2979 if ((ptr
= list_head( &node
->children
)))
2981 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
2987 BOOL
move_to_parent_node( struct node
**current
)
2989 struct node
*parent
= (*current
)->parent
;
2990 if (!parent
) return FALSE
;
2995 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
2997 BOOL success
= FALSE
;
3000 if (!read_end_of_data( reader
))
3002 struct node
*saved_current
= reader
->current
;
3003 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
3004 if (hr
!= S_OK
) return hr
;
3005 reader
->current
= saved_current
;
3009 case WS_MOVE_TO_ROOT_ELEMENT
:
3010 success
= move_to_root_element( reader
->root
, &reader
->current
);
3013 case WS_MOVE_TO_NEXT_ELEMENT
:
3014 success
= move_to_next_element( &reader
->current
);
3017 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
3018 success
= move_to_prev_element( &reader
->current
);
3021 case WS_MOVE_TO_CHILD_ELEMENT
:
3022 success
= move_to_child_element( &reader
->current
);
3025 case WS_MOVE_TO_END_ELEMENT
:
3026 success
= move_to_end_element( &reader
->current
);
3029 case WS_MOVE_TO_PARENT_ELEMENT
:
3030 success
= move_to_parent_element( &reader
->current
);
3033 case WS_MOVE_TO_FIRST_NODE
:
3034 success
= move_to_first_node( &reader
->current
);
3037 case WS_MOVE_TO_NEXT_NODE
:
3038 success
= move_to_next_node( &reader
->current
);
3041 case WS_MOVE_TO_PREVIOUS_NODE
:
3042 success
= move_to_prev_node( &reader
->current
);
3045 case WS_MOVE_TO_CHILD_NODE
:
3046 success
= move_to_child_node( &reader
->current
);
3049 case WS_MOVE_TO_BOF
:
3050 success
= move_to_bof( reader
->root
, &reader
->current
);
3053 case WS_MOVE_TO_EOF
:
3054 success
= move_to_eof( reader
->root
, &reader
->current
);
3058 FIXME( "unhandled move %u\n", move
);
3067 return success
? S_OK
: WS_E_INVALID_FORMAT
;
3070 /**************************************************************************
3071 * WsMoveReader [webservices.@]
3073 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
3075 struct reader
*reader
= (struct reader
*)handle
;
3078 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
3079 if (error
) FIXME( "ignoring error parameter\n" );
3081 if (!reader
) return E_INVALIDARG
;
3083 EnterCriticalSection( &reader
->cs
);
3085 if (reader
->magic
!= READER_MAGIC
)
3087 LeaveCriticalSection( &reader
->cs
);
3088 return E_INVALIDARG
;
3091 if (!reader
->input_type
)
3093 LeaveCriticalSection( &reader
->cs
);
3094 return WS_E_INVALID_OPERATION
;
3097 hr
= read_move_to( reader
, move
, found
);
3099 LeaveCriticalSection( &reader
->cs
);
3103 /**************************************************************************
3104 * WsReadStartAttribute [webservices.@]
3106 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
3108 struct reader
*reader
= (struct reader
*)handle
;
3109 const WS_XML_ELEMENT_NODE
*elem
;
3111 TRACE( "%p %u %p\n", handle
, index
, error
);
3112 if (error
) FIXME( "ignoring error parameter\n" );
3114 if (!reader
) return E_INVALIDARG
;
3116 EnterCriticalSection( &reader
->cs
);
3118 if (reader
->magic
!= READER_MAGIC
)
3120 LeaveCriticalSection( &reader
->cs
);
3121 return E_INVALIDARG
;
3124 elem
= &reader
->current
->hdr
;
3125 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
)
3127 LeaveCriticalSection( &reader
->cs
);
3128 return WS_E_INVALID_FORMAT
;
3131 reader
->current_attr
= index
;
3132 reader
->state
= READER_STATE_STARTATTRIBUTE
;
3134 LeaveCriticalSection( &reader
->cs
);
3138 /**************************************************************************
3139 * WsReadEndAttribute [webservices.@]
3141 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
3143 struct reader
*reader
= (struct reader
*)handle
;
3145 TRACE( "%p %p\n", handle
, error
);
3146 if (error
) FIXME( "ignoring error parameter\n" );
3148 if (!reader
) return E_INVALIDARG
;
3150 EnterCriticalSection( &reader
->cs
);
3152 if (reader
->magic
!= READER_MAGIC
)
3154 LeaveCriticalSection( &reader
->cs
);
3155 return E_INVALIDARG
;
3158 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
)
3160 LeaveCriticalSection( &reader
->cs
);
3161 return WS_E_INVALID_FORMAT
;
3164 reader
->state
= READER_STATE_STARTELEMENT
;
3166 LeaveCriticalSection( &reader
->cs
);
3170 static HRESULT
find_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
**ns
)
3172 const struct node
*node
;
3173 for (node
= reader
->current
->parent
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3175 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3177 for (i
= 0; i
< elem
->attributeCount
; i
++)
3179 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3180 if (WsXmlStringEquals( elem
->attributes
[i
]->prefix
, prefix
, NULL
) != S_OK
) continue;
3181 *ns
= elem
->attributes
[i
]->ns
;
3185 return WS_E_INVALID_FORMAT
;
3188 static HRESULT
read_qualified_name( struct reader
*reader
, WS_HEAP
*heap
, WS_XML_STRING
*prefix_ret
,
3189 WS_XML_STRING
*localname_ret
, WS_XML_STRING
*ns_ret
)
3191 const WS_XML_TEXT_NODE
*node
= (const WS_XML_TEXT_NODE
*)reader
->current
;
3192 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)node
->text
;
3193 unsigned char *prefix_bytes
, *localname_bytes
, *ns_bytes
;
3194 const unsigned char *ptr
= utf8
->value
.bytes
;
3195 WS_XML_STRING prefix
, localname
, empty
= {0, NULL
};
3196 const WS_XML_STRING
*ns
= &empty
;
3197 ULONG len
= utf8
->value
.length
;
3200 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3201 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3202 if (!len
) return WS_E_INVALID_FORMAT
;
3204 if ((hr
= split_name( ptr
, len
, (const unsigned char **)&prefix
.bytes
, &prefix
.length
,
3205 (const unsigned char **)&localname
.bytes
, &localname
.length
)) != S_OK
) return hr
;
3207 if (!localname
.length
) return WS_E_INVALID_FORMAT
;
3208 if (prefix
.length
&& (hr
= find_namespace( reader
, &prefix
, &ns
)) != S_OK
) return hr
;
3210 if (!(prefix_bytes
= ws_alloc( heap
, prefix
.length
))) return WS_E_QUOTA_EXCEEDED
;
3211 memcpy( prefix_bytes
, prefix
.bytes
, prefix
.length
);
3213 if (!(localname_bytes
= ws_alloc( heap
, localname
.length
)))
3215 ws_free( heap
, prefix_bytes
, prefix
.length
);
3216 return WS_E_QUOTA_EXCEEDED
;
3218 memcpy( localname_bytes
, localname
.bytes
, localname
.length
);
3220 if (!(ns_bytes
= ws_alloc( heap
, ns
->length
)))
3222 ws_free( heap
, prefix_bytes
, prefix
.length
);
3223 ws_free( heap
, localname_bytes
, localname
.length
);
3224 return WS_E_QUOTA_EXCEEDED
;
3226 memcpy( ns_bytes
, ns
->bytes
, ns
->length
);
3228 prefix_ret
->bytes
= prefix_bytes
;
3229 prefix_ret
->length
= prefix
.length
;
3231 localname_ret
->bytes
= localname_bytes
;
3232 localname_ret
->length
= localname
.length
;
3234 ns_ret
->bytes
= ns_bytes
;
3235 ns_ret
->length
= ns
->length
;
3240 /**************************************************************************
3241 * WsReadQualifiedName [webservices.@]
3243 HRESULT WINAPI
WsReadQualifiedName( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
3244 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
,
3247 struct reader
*reader
= (struct reader
*)handle
;
3250 TRACE( "%p %p %p %p %p %p\n", handle
, heap
, prefix
, localname
, ns
, error
);
3251 if (error
) FIXME( "ignoring error parameter\n" );
3253 if (!reader
|| !heap
) return E_INVALIDARG
;
3255 EnterCriticalSection( &reader
->cs
);
3257 if (reader
->magic
!= READER_MAGIC
)
3259 LeaveCriticalSection( &reader
->cs
);
3260 return E_INVALIDARG
;
3263 if (!reader
->input_type
)
3265 LeaveCriticalSection( &reader
->cs
);
3266 return WS_E_INVALID_OPERATION
;
3271 LeaveCriticalSection( &reader
->cs
);
3272 return E_INVALIDARG
;
3275 if (reader
->state
!= READER_STATE_TEXT
)
3277 LeaveCriticalSection( &reader
->cs
);
3278 return WS_E_INVALID_FORMAT
;
3281 hr
= read_qualified_name( reader
, heap
, prefix
, localname
, ns
);
3283 LeaveCriticalSection( &reader
->cs
);
3287 static WCHAR
*xmltext_to_widechar( WS_HEAP
*heap
, const WS_XML_TEXT
*text
)
3291 switch (text
->textType
)
3293 case WS_XML_TEXT_TYPE_UTF8
:
3295 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
3296 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
3297 if (!(ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return NULL
;
3298 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, ret
, len
);
3303 FIXME( "unhandled type %u\n", text
->textType
);
3310 #define MAX_INT8 0x7f
3311 #define MIN_INT8 (-MAX_INT8 - 1)
3312 #define MAX_INT16 0x7fff
3313 #define MIN_INT16 (-MAX_INT16 - 1)
3314 #define MAX_INT32 0x7fffffff
3315 #define MIN_INT32 (-MAX_INT32 - 1)
3316 #define MAX_INT64 (((INT64)0x7fffffff << 32) | 0xffffffff)
3317 #define MIN_INT64 (-MAX_INT64 - 1)
3318 #define MAX_UINT8 0xff
3319 #define MAX_UINT16 0xffff
3320 #define MAX_UINT32 0xffffffff
3321 #define MAX_UINT64 (((UINT64)0xffffffff << 32) | 0xffffffff)
3323 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
3325 BOOL negative
= FALSE
;
3326 const unsigned char *ptr
= str
;
3329 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3330 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3331 if (!len
) return WS_E_INVALID_FORMAT
;
3339 if (!len
) return WS_E_INVALID_FORMAT
;
3345 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3347 if (negative
) val
= -val
;
3349 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
3350 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
3352 return WS_E_NUMERIC_OVERFLOW
;
3354 *ret
= *ret
* 10 + val
;
3361 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
3363 const unsigned char *ptr
= str
;
3366 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3367 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3368 if (!len
) return WS_E_INVALID_FORMAT
;
3374 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3377 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
3378 *ret
= *ret
* 10 + val
;
3385 BOOL
set_fpword( unsigned short new, unsigned short *old
)
3387 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3388 unsigned short fpword
;
3390 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
3393 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3396 FIXME( "not implemented\n" );
3401 void restore_fpword( unsigned short fpword
)
3403 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3404 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
3406 FIXME( "not implemented\n" );
3410 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
3412 static const unsigned __int64 nan
= 0xfff8000000000000;
3413 static const unsigned __int64 inf
= 0x7ff0000000000000;
3414 static const unsigned __int64 inf_min
= 0xfff0000000000000;
3415 HRESULT hr
= WS_E_INVALID_FORMAT
;
3416 const unsigned char *p
= str
, *q
;
3417 int sign
= 1, exp_sign
= 1, exp
= 0, exp_tmp
= 0, neg_exp
, i
, nb_digits
, have_digits
;
3418 unsigned __int64 val
= 0, tmp
;
3419 long double exp_val
= 1.0, exp_mul
= 10.0;
3420 unsigned short fpword
;
3422 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3423 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3424 if (!len
) return WS_E_INVALID_FORMAT
;
3426 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
3428 *(unsigned __int64
*)ret
= nan
;
3431 else if (len
== 3 && !memcmp( p
, "INF", 3 ))
3433 *(unsigned __int64
*)ret
= inf
;
3436 else if (len
== 4 && !memcmp( p
, "-INF", 4 ))
3438 *(unsigned __int64
*)ret
= inf_min
;
3448 else if (*p
== '+') { p
++; len
--; };
3449 if (!len
) return S_OK
;
3451 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
3454 while (len
&& isdigit( *q
)) { q
++; len
--; }
3455 have_digits
= nb_digits
= q
- p
;
3456 for (i
= 0; i
< nb_digits
; i
++)
3458 tmp
= val
* 10 + p
[i
] - '0';
3459 if (val
> MAX_UINT64
/ 10 || tmp
< val
)
3461 for (; i
< nb_digits
; i
++) exp
++;
3472 while (len
&& isdigit( *q
)) { q
++; len
--; };
3473 have_digits
|= nb_digits
= q
- p
;
3474 for (i
= 0; i
< nb_digits
; i
++)
3476 tmp
= val
* 10 + p
[i
] - '0';
3477 if (val
> MAX_UINT64
/ 10 || tmp
< val
) break;
3482 if (len
> 1 && tolower(*q
) == 'e')
3484 if (!have_digits
) goto done
;
3491 else if (*p
== '+') { p
++; len
--; };
3494 while (len
&& isdigit( *q
)) { q
++; len
--; };
3496 if (!nb_digits
|| len
) goto done
;
3497 for (i
= 0; i
< nb_digits
; i
++)
3499 if (exp_tmp
> MAX_INT32
/ 10 || (exp_tmp
= exp_tmp
* 10 + p
[i
] - '0') < 0)
3500 exp_tmp
= MAX_INT32
;
3502 exp_tmp
*= exp_sign
;
3504 if (exp
< 0 && exp_tmp
< 0 && exp
+ exp_tmp
>= 0) exp
= MIN_INT32
;
3505 else if (exp
> 0 && exp_tmp
> 0 && exp
+ exp_tmp
< 0) exp
= MAX_INT32
;
3506 else exp
+= exp_tmp
;
3509 if (!have_digits
|| len
) goto done
;
3511 if ((neg_exp
= exp
< 0)) exp
= -exp
;
3512 for (; exp
; exp
>>= 1)
3514 if (exp
& 1) exp_val
*= exp_mul
;
3518 *ret
= sign
* (neg_exp
? val
/ exp_val
: val
* exp_val
);
3522 restore_fpword( fpword
);
3526 static HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
3528 static const unsigned char hex
[] =
3530 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3531 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3532 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3533 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3534 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3535 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3536 0,10,11,12,13,14,15 /* 0x60 */
3538 const unsigned char *p
= str
;
3541 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3542 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3543 if (len
!= 36) return WS_E_INVALID_FORMAT
;
3545 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
3546 return WS_E_INVALID_FORMAT
;
3548 for (i
= 0; i
< 36; i
++)
3550 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
3551 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
3554 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
3555 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
3557 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
3558 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
3560 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
3561 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
3562 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
3563 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
3564 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
3565 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
3566 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
3567 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
3572 static inline unsigned char decode_char( unsigned char c
)
3574 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
3575 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
3576 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
3577 if (c
== '+') return 62;
3578 if (c
== '/') return 63;
3582 static ULONG
decode_base64( const unsigned char *base64
, ULONG len
, unsigned char *buf
)
3585 unsigned char c0
, c1
, c2
, c3
;
3586 const unsigned char *p
= base64
;
3590 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3591 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3592 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3593 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3594 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3595 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3596 buf
[i
+ 2] = (c2
<< 6) | c3
;
3603 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3604 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3605 buf
[i
] = (c0
<< 2) | (c1
>> 4);
3608 else if (p
[3] == '=')
3610 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3611 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3612 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3613 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3614 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3619 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3620 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3621 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3622 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3623 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3624 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3625 buf
[i
+ 2] = (c2
<< 6) | c3
;
3631 static HRESULT
str_to_bytes( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_BYTES
*ret
)
3633 const unsigned char *p
= str
;
3635 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3636 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3638 if (len
% 4) return WS_E_INVALID_FORMAT
;
3639 if (!(ret
->bytes
= ws_alloc( heap
, len
* 3 / 4 ))) return WS_E_QUOTA_EXCEEDED
;
3640 ret
->length
= decode_base64( p
, len
, ret
->bytes
);
3644 static const int month_offsets
[2][12] =
3646 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
3647 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
3650 static inline int valid_day( int year
, int month
, int day
)
3652 return day
> 0 && day
<= month_days
[leap_year( year
)][month
- 1];
3655 static inline int leap_days_before( int year
)
3657 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
3660 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
3662 const unsigned char *p
= bytes
, *q
;
3663 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
3665 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3666 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3669 while (len
&& isdigit( *q
)) { q
++; len
--; };
3670 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3671 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
3672 if (year
< 1) return WS_E_INVALID_FORMAT
;
3675 while (len
&& isdigit( *q
)) { q
++; len
--; };
3676 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
3677 month
= (p
[0] - '0') * 10 + p
[1] - '0';
3678 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
3681 while (len
&& isdigit( *q
)) { q
++; len
--; };
3682 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
3683 day
= (p
[0] - '0') * 10 + p
[1] - '0';
3684 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
3687 while (len
&& isdigit( *q
)) { q
++; len
--; };
3688 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3689 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3690 if (hour
> 24) return WS_E_INVALID_FORMAT
;
3693 while (len
&& isdigit( *q
)) { q
++; len
--; };
3694 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3695 min
= (p
[0] - '0') * 10 + p
[1] - '0';
3696 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3699 while (len
&& isdigit( *q
)) { q
++; len
--; };
3700 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
3701 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
3702 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
3706 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
3708 while (len
&& isdigit( *q
)) { q
++; len
--; };
3710 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
3711 for (i
= 0; i
< nb_digits
; i
++)
3713 sec_frac
+= (p
[i
] - '0') * mul
;
3719 if (--len
) return WS_E_INVALID_FORMAT
;
3720 tz_hour
= tz_min
= tz_neg
= 0;
3721 ret
->format
= WS_DATETIME_FORMAT_UTC
;
3723 else if (*q
== '+' || *q
== '-')
3725 tz_neg
= (*q
== '-') ? 1 : 0;
3728 while (len
&& isdigit( *q
)) { q
++; len
--; };
3729 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
3730 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
3731 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
3734 while (len
&& isdigit( *q
)) { q
++; len
--; };
3735 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
3736 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
3737 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
3739 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
3741 else return WS_E_INVALID_FORMAT
;
3743 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
3744 ret
->ticks
+= month_offsets
[leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
3745 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
3746 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
3747 ret
->ticks
+= min
* TICKS_PER_MIN
;
3748 ret
->ticks
+= sec
* TICKS_PER_SEC
;
3749 ret
->ticks
+= sec_frac
;
3753 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
3754 return WS_E_INVALID_FORMAT
;
3755 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
3756 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
3760 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
3761 return WS_E_INVALID_FORMAT
;
3762 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
3763 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
3769 /**************************************************************************
3770 * WsDateTimeToFileTime [webservices.@]
3772 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
3774 unsigned __int64 ticks
;
3776 TRACE( "%p %p %p\n", dt
, ft
, error
);
3777 if (error
) FIXME( "ignoring error parameter\n" );
3779 if (!dt
|| !ft
) return E_INVALIDARG
;
3781 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
3782 ticks
= dt
->ticks
- TICKS_1601_01_01
;
3783 ft
->dwHighDateTime
= ticks
>> 32;
3784 ft
->dwLowDateTime
= (DWORD
)ticks
;
3788 /**************************************************************************
3789 * WsFileTimeToDateTime [webservices.@]
3791 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
3793 unsigned __int64 ticks
;
3795 TRACE( "%p %p %p\n", ft
, dt
, error
);
3796 if (error
) FIXME( "ignoring error parameter\n" );
3798 if (!dt
|| !ft
) return E_INVALIDARG
;
3800 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
3801 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
3802 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
3803 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
3804 dt
->format
= WS_DATETIME_FORMAT_UTC
;
3808 static HRESULT
read_get_node_text( struct reader
*reader
, WS_XML_UTF8_TEXT
**ret
)
3810 WS_XML_TEXT_NODE
*text
;
3812 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
3813 return WS_E_INVALID_FORMAT
;
3815 text
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
3816 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3818 FIXME( "text type %u not supported\n", text
->text
->textType
);
3821 *ret
= (WS_XML_UTF8_TEXT
*)text
->text
;
3825 static HRESULT
read_get_attribute_text( struct reader
*reader
, ULONG index
, WS_XML_UTF8_TEXT
**ret
)
3827 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3828 WS_XML_ATTRIBUTE
*attr
;
3830 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
3831 return WS_E_INVALID_FORMAT
;
3833 attr
= elem
->attributes
[index
];
3834 if (attr
->value
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
3836 FIXME( "text type %u not supported\n", attr
->value
->textType
);
3839 *ret
= (WS_XML_UTF8_TEXT
*)attr
->value
;
3843 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
3844 const WS_XML_STRING
*ns
, ULONG
*index
)
3847 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3851 *index
= reader
->current_attr
;
3854 for (i
= 0; i
< elem
->attributeCount
; i
++)
3856 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
3857 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
3859 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
3860 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
3869 /**************************************************************************
3870 * WsFindAttribute [webservices.@]
3872 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
3873 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
3876 struct reader
*reader
= (struct reader
*)handle
;
3879 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3880 required
, index
, error
);
3881 if (error
) FIXME( "ignoring error parameter\n" );
3883 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
3885 EnterCriticalSection( &reader
->cs
);
3887 if (reader
->magic
!= READER_MAGIC
)
3889 LeaveCriticalSection( &reader
->cs
);
3890 return E_INVALIDARG
;
3893 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
)
3895 LeaveCriticalSection( &reader
->cs
);
3896 return WS_E_INVALID_OPERATION
;
3899 if (!find_attribute( reader
, localname
, ns
, index
))
3901 if (required
) hr
= WS_E_INVALID_FORMAT
;
3909 LeaveCriticalSection( &reader
->cs
);
3913 static HRESULT
read_get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3914 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3915 WS_XML_UTF8_TEXT
**ret
, BOOL
*found
)
3919 case WS_ATTRIBUTE_TYPE_MAPPING
:
3922 if (!(*found
= find_attribute( reader
, localname
, ns
, &index
))) return S_OK
;
3923 return read_get_attribute_text( reader
, index
, ret
);
3925 case WS_ELEMENT_TYPE_MAPPING
:
3926 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3927 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3933 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
3935 if (WsXmlStringEquals( localname
, elem
->localName
, NULL
) != S_OK
||
3936 WsXmlStringEquals( ns
, elem
->ns
, NULL
) != S_OK
)
3941 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
3943 return read_get_node_text( reader
, ret
);
3946 FIXME( "mapping %u not supported\n", mapping
);
3951 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
3952 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3953 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
3954 WS_HEAP
*heap
, void *ret
, ULONG size
)
3956 WS_XML_UTF8_TEXT
*utf8
;
3958 BOOL found
, val
= FALSE
;
3962 FIXME( "description not supported\n" );
3965 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
3968 ULONG len
= utf8
->value
.length
;
3969 if (len
== 4 && !memcmp( utf8
->value
.bytes
, "true", 4 )) val
= TRUE
;
3970 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "1", 1 )) val
= TRUE
;
3971 else if (len
== 5 && !memcmp( utf8
->value
.bytes
, "false", 5 )) val
= FALSE
;
3972 else if (len
== 1 && !memcmp( utf8
->value
.bytes
, "0", 1 )) val
= FALSE
;
3973 else return WS_E_INVALID_FORMAT
;
3978 case WS_READ_REQUIRED_VALUE
:
3979 if (!found
) return WS_E_INVALID_FORMAT
;
3982 case WS_READ_NILLABLE_VALUE
:
3983 if (size
!= sizeof(BOOL
)) return E_INVALIDARG
;
3987 case WS_READ_REQUIRED_POINTER
:
3988 if (!found
) return WS_E_INVALID_FORMAT
;
3991 case WS_READ_OPTIONAL_POINTER
:
3992 case WS_READ_NILLABLE_POINTER
:
3994 BOOL
*heap_val
= NULL
;
3995 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
3998 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4001 *(BOOL
**)ret
= heap_val
;
4005 FIXME( "read option %u not supported\n", option
);
4012 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4013 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4014 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4015 WS_HEAP
*heap
, void *ret
, ULONG size
)
4017 WS_XML_UTF8_TEXT
*utf8
;
4024 FIXME( "description not supported\n" );
4027 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4028 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT8
, MAX_INT8
, &val
)) != S_OK
)
4033 case WS_READ_REQUIRED_VALUE
:
4034 if (!found
) return WS_E_INVALID_FORMAT
;
4037 case WS_READ_NILLABLE_VALUE
:
4038 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
4042 case WS_READ_REQUIRED_POINTER
:
4043 if (!found
) return WS_E_INVALID_FORMAT
;
4046 case WS_READ_OPTIONAL_POINTER
:
4047 case WS_READ_NILLABLE_POINTER
:
4049 INT8
*heap_val
= NULL
;
4050 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4053 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4056 *(INT8
**)ret
= heap_val
;
4060 FIXME( "read option %u not supported\n", option
);
4067 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4068 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4069 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4070 WS_HEAP
*heap
, void *ret
, ULONG size
)
4072 WS_XML_UTF8_TEXT
*utf8
;
4079 FIXME( "description not supported\n" );
4082 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4083 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT16
, MAX_INT16
, &val
)) != S_OK
)
4088 case WS_READ_REQUIRED_VALUE
:
4089 if (!found
) return WS_E_INVALID_FORMAT
;
4092 case WS_READ_NILLABLE_VALUE
:
4093 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
4094 *(INT16
*)ret
= val
;
4097 case WS_READ_REQUIRED_POINTER
:
4098 if (!found
) return WS_E_INVALID_FORMAT
;
4101 case WS_READ_OPTIONAL_POINTER
:
4102 case WS_READ_NILLABLE_POINTER
:
4104 INT16
*heap_val
= NULL
;
4105 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4108 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4111 *(INT16
**)ret
= heap_val
;
4115 FIXME( "read option %u not supported\n", option
);
4122 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4123 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4124 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4125 WS_HEAP
*heap
, void *ret
, ULONG size
)
4127 WS_XML_UTF8_TEXT
*utf8
;
4134 FIXME( "description not supported\n" );
4137 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4138 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT32
, MAX_INT32
, &val
)) != S_OK
)
4143 case WS_READ_REQUIRED_VALUE
:
4144 if (!found
) return WS_E_INVALID_FORMAT
;
4147 case WS_READ_NILLABLE_VALUE
:
4148 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
4149 *(INT32
*)ret
= val
;
4152 case WS_READ_REQUIRED_POINTER
:
4153 if (!found
) return WS_E_INVALID_FORMAT
;
4156 case WS_READ_OPTIONAL_POINTER
:
4157 case WS_READ_NILLABLE_POINTER
:
4159 INT32
*heap_val
= NULL
;
4160 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4163 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4166 *(INT32
**)ret
= heap_val
;
4170 FIXME( "read option %u not supported\n", option
);
4177 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4178 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4179 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4180 WS_HEAP
*heap
, void *ret
, ULONG size
)
4182 WS_XML_UTF8_TEXT
*utf8
;
4189 FIXME( "description not supported\n" );
4192 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4193 if (found
&& (hr
= str_to_int64( utf8
->value
.bytes
, utf8
->value
.length
, MIN_INT64
, MAX_INT64
, &val
)) != S_OK
)
4198 case WS_READ_REQUIRED_VALUE
:
4199 if (!found
) return WS_E_INVALID_FORMAT
;
4202 case WS_READ_NILLABLE_VALUE
:
4203 if (size
!= sizeof(INT64
)) return E_INVALIDARG
;
4204 *(INT64
*)ret
= val
;
4207 case WS_READ_REQUIRED_POINTER
:
4208 if (!found
) return WS_E_INVALID_FORMAT
;
4211 case WS_READ_OPTIONAL_POINTER
:
4212 case WS_READ_NILLABLE_POINTER
:
4214 INT64
*heap_val
= NULL
;
4215 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4218 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4221 *(INT64
**)ret
= heap_val
;
4225 FIXME( "read option %u not supported\n", option
);
4232 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4233 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4234 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4235 WS_HEAP
*heap
, void *ret
, ULONG size
)
4237 WS_XML_UTF8_TEXT
*utf8
;
4244 FIXME( "description not supported\n" );
4247 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4248 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT8
, &val
)) != S_OK
)
4253 case WS_READ_REQUIRED_VALUE
:
4254 if (!found
) return WS_E_INVALID_FORMAT
;
4257 case WS_READ_NILLABLE_VALUE
:
4258 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
4259 *(UINT8
*)ret
= val
;
4262 case WS_READ_REQUIRED_POINTER
:
4263 if (!found
) return WS_E_INVALID_FORMAT
;
4266 case WS_READ_OPTIONAL_POINTER
:
4267 case WS_READ_NILLABLE_POINTER
:
4269 UINT8
*heap_val
= NULL
;
4270 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4273 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4276 *(UINT8
**)ret
= heap_val
;
4280 FIXME( "read option %u not supported\n", option
);
4287 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4288 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4289 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4290 WS_HEAP
*heap
, void *ret
, ULONG size
)
4292 WS_XML_UTF8_TEXT
*utf8
;
4299 FIXME( "description not supported\n" );
4302 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4303 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT16
, &val
)) != S_OK
)
4308 case WS_READ_REQUIRED_VALUE
:
4309 if (!found
) return WS_E_INVALID_FORMAT
;
4312 case WS_READ_NILLABLE_VALUE
:
4313 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
4314 *(UINT16
*)ret
= val
;
4317 case WS_READ_REQUIRED_POINTER
:
4318 if (!found
) return WS_E_INVALID_FORMAT
;
4321 case WS_READ_OPTIONAL_POINTER
:
4322 case WS_READ_NILLABLE_POINTER
:
4324 UINT16
*heap_val
= NULL
;
4325 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4328 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4331 *(UINT16
**)ret
= heap_val
;
4335 FIXME( "read option %u not supported\n", option
);
4342 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4343 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4344 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4345 WS_HEAP
*heap
, void *ret
, ULONG size
)
4347 WS_XML_UTF8_TEXT
*utf8
;
4354 FIXME( "description not supported\n" );
4357 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4358 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT32
, &val
)) != S_OK
)
4363 case WS_READ_REQUIRED_VALUE
:
4364 if (!found
) return WS_E_INVALID_FORMAT
;
4367 case WS_READ_NILLABLE_VALUE
:
4368 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
4369 *(UINT32
*)ret
= val
;
4372 case WS_READ_REQUIRED_POINTER
:
4373 if (!found
) return WS_E_INVALID_FORMAT
;
4376 case WS_READ_OPTIONAL_POINTER
:
4377 case WS_READ_NILLABLE_POINTER
:
4379 UINT32
*heap_val
= NULL
;
4380 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4383 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4386 *(UINT32
**)ret
= heap_val
;
4390 FIXME( "read option %u not supported\n", option
);
4397 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4398 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4399 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4400 WS_HEAP
*heap
, void *ret
, ULONG size
)
4402 WS_XML_UTF8_TEXT
*utf8
;
4409 FIXME( "description not supported\n" );
4412 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4413 if (found
&& (hr
= str_to_uint64( utf8
->value
.bytes
, utf8
->value
.length
, MAX_UINT64
, &val
)) != S_OK
)
4418 case WS_READ_REQUIRED_VALUE
:
4419 if (!found
) return WS_E_INVALID_FORMAT
;
4422 case WS_READ_NILLABLE_VALUE
:
4423 if (size
!= sizeof(UINT64
)) return E_INVALIDARG
;
4424 *(UINT64
*)ret
= val
;
4427 case WS_READ_REQUIRED_POINTER
:
4428 if (!found
) return WS_E_INVALID_FORMAT
;
4431 case WS_READ_OPTIONAL_POINTER
:
4432 case WS_READ_NILLABLE_POINTER
:
4434 UINT64
*heap_val
= NULL
;
4435 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4438 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4441 *(UINT64
**)ret
= heap_val
;
4445 FIXME( "read option %u not supported\n", option
);
4452 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4453 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4454 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4455 WS_HEAP
*heap
, void *ret
, ULONG size
)
4457 WS_XML_UTF8_TEXT
*utf8
;
4462 if (desc
) FIXME( "ignoring description\n" );
4464 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4465 if (found
&& (hr
= str_to_double( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4469 case WS_READ_REQUIRED_VALUE
:
4470 if (!found
) return WS_E_INVALID_FORMAT
;
4473 case WS_READ_NILLABLE_VALUE
:
4474 if (size
!= sizeof(double)) return E_INVALIDARG
;
4475 *(double *)ret
= val
;
4478 case WS_READ_REQUIRED_POINTER
:
4479 if (!found
) return WS_E_INVALID_FORMAT
;
4482 case WS_READ_OPTIONAL_POINTER
:
4483 case WS_READ_NILLABLE_POINTER
:
4485 double *heap_val
= NULL
;
4486 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4489 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4492 *(double **)ret
= heap_val
;
4496 FIXME( "read option %u not supported\n", option
);
4503 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4504 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4505 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4506 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
)
4508 WS_XML_UTF8_TEXT
*utf8
;
4515 FIXME( "description not supported\n" );
4518 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4519 if (found
&& !(str
= xmltext_to_widechar( heap
, &utf8
->text
))) return WS_E_QUOTA_EXCEEDED
;
4523 case WS_READ_REQUIRED_POINTER
:
4524 if (!found
) return WS_E_INVALID_FORMAT
;
4527 case WS_READ_OPTIONAL_POINTER
:
4528 case WS_READ_NILLABLE_POINTER
:
4529 if (size
!= sizeof(str
)) return E_INVALIDARG
;
4534 FIXME( "read option %u not supported\n", option
);
4541 static HRESULT
get_enum_value( const WS_XML_UTF8_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
4544 for (i
= 0; i
< desc
->valueCount
; i
++)
4546 if (WsXmlStringEquals( &text
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
4548 *ret
= desc
->values
[i
].value
;
4552 return WS_E_INVALID_FORMAT
;
4555 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4556 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4557 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4558 WS_HEAP
*heap
, void *ret
, ULONG size
)
4560 WS_XML_UTF8_TEXT
*utf8
;
4565 if (!desc
) return E_INVALIDARG
;
4567 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4568 if (found
&& (hr
= get_enum_value( utf8
, desc
, &val
)) != S_OK
) return hr
;
4572 case WS_READ_REQUIRED_VALUE
:
4573 if (!found
) return WS_E_INVALID_FORMAT
;
4576 case WS_READ_NILLABLE_VALUE
:
4577 if (size
!= sizeof(int)) return E_INVALIDARG
;
4581 case WS_READ_REQUIRED_POINTER
:
4582 if (!found
) return WS_E_INVALID_FORMAT
;
4585 case WS_READ_OPTIONAL_POINTER
:
4586 case WS_READ_NILLABLE_POINTER
:
4588 int *heap_val
= NULL
;
4589 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4592 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4595 *(int **)ret
= heap_val
;
4599 FIXME( "read option %u not supported\n", option
);
4606 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4607 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4608 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4609 WS_HEAP
*heap
, void *ret
, ULONG size
)
4611 WS_XML_UTF8_TEXT
*utf8
;
4613 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
4616 if (desc
) FIXME( "ignoring description\n" );
4618 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4619 if (found
&& (hr
= str_to_datetime( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4623 case WS_READ_REQUIRED_VALUE
:
4624 if (!found
) return WS_E_INVALID_FORMAT
;
4627 case WS_READ_NILLABLE_VALUE
:
4628 if (size
!= sizeof(WS_DATETIME
)) return E_INVALIDARG
;
4629 *(WS_DATETIME
*)ret
= val
;
4632 case WS_READ_REQUIRED_POINTER
:
4633 if (!found
) return WS_E_INVALID_FORMAT
;
4636 case WS_READ_OPTIONAL_POINTER
:
4637 case WS_READ_NILLABLE_POINTER
:
4639 WS_DATETIME
*heap_val
= NULL
;
4640 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4643 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4646 *(WS_DATETIME
**)ret
= heap_val
;
4650 FIXME( "read option %u not supported\n", option
);
4657 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4658 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4659 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4660 WS_HEAP
*heap
, void *ret
, ULONG size
)
4662 WS_XML_UTF8_TEXT
*utf8
;
4667 if (desc
) FIXME( "ignoring description\n" );
4669 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4670 if (found
&& (hr
= str_to_guid( utf8
->value
.bytes
, utf8
->value
.length
, &val
)) != S_OK
) return hr
;
4674 case WS_READ_REQUIRED_VALUE
:
4675 if (!found
) return WS_E_INVALID_FORMAT
;
4678 case WS_READ_NILLABLE_VALUE
:
4679 if (size
!= sizeof(GUID
)) return E_INVALIDARG
;
4683 case WS_READ_REQUIRED_POINTER
:
4684 if (!found
) return WS_E_INVALID_FORMAT
;
4687 case WS_READ_OPTIONAL_POINTER
:
4688 case WS_READ_NILLABLE_POINTER
:
4690 GUID
*heap_val
= NULL
;
4691 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4694 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4697 *(GUID
**)ret
= heap_val
;
4701 FIXME( "read option %u not supported\n", option
);
4708 static HRESULT
read_type_bytes( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4709 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4710 const WS_BYTES_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4711 WS_HEAP
*heap
, void *ret
, ULONG size
)
4713 WS_XML_UTF8_TEXT
*utf8
;
4718 if (desc
) FIXME( "ignoring description\n" );
4720 if ((hr
= read_get_text( reader
, mapping
, localname
, ns
, &utf8
, &found
)) != S_OK
) return hr
;
4721 if (found
&& (hr
= str_to_bytes( utf8
->value
.bytes
, utf8
->value
.length
, heap
, &val
)) != S_OK
)
4726 case WS_READ_REQUIRED_VALUE
:
4727 if (!found
) return WS_E_INVALID_FORMAT
;
4730 case WS_READ_NILLABLE_VALUE
:
4731 if (size
!= sizeof(WS_BYTES
)) return E_INVALIDARG
;
4732 *(WS_BYTES
*)ret
= val
;
4735 case WS_READ_REQUIRED_POINTER
:
4736 if (!found
) return WS_E_INVALID_FORMAT
;
4739 case WS_READ_OPTIONAL_POINTER
:
4740 case WS_READ_NILLABLE_POINTER
:
4742 WS_BYTES
*heap_val
= NULL
;
4743 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4746 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4749 *(WS_BYTES
**)ret
= heap_val
;
4753 FIXME( "read option %u not supported\n", option
);
4760 static BOOL
is_empty_text_node( const struct node
*node
)
4762 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4763 const WS_XML_UTF8_TEXT
*utf8
;
4766 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
4767 if (text
->text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
4769 ERR( "unhandled text type %u\n", text
->text
->textType
);
4772 utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
4773 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
4777 static HRESULT
read_next_node( struct reader
*reader
)
4779 if (reader
->current
== reader
->last
) return read_node( reader
);
4780 if (move_to_child_node( &reader
->current
)) return S_OK
;
4781 if (move_to_next_node( &reader
->current
)) return S_OK
;
4782 if (!move_to_parent_node( &reader
->current
)) return WS_E_INVALID_FORMAT
;
4783 if (move_to_next_node( &reader
->current
)) return S_OK
;
4784 return WS_E_INVALID_FORMAT
;
4787 /* skips comment and empty text nodes */
4788 static HRESULT
read_type_next_node( struct reader
*reader
)
4793 WS_XML_NODE_TYPE type
;
4795 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
4796 type
= node_type( reader
->current
);
4797 if (type
== WS_XML_NODE_TYPE_COMMENT
||
4798 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
4803 static BOOL
match_current_element( struct reader
*reader
, const WS_XML_STRING
*localname
,
4804 const WS_XML_STRING
*ns
)
4806 const WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
4807 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
4808 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
4809 WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
;
4812 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
4813 const WS_XML_STRING
*ns
)
4819 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
4820 if (reader
->current
== reader
->last
)
4823 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
4824 if (!found
) return WS_E_INVALID_FORMAT
;
4826 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
4828 node
= reader
->current
;
4829 attr
= reader
->current_attr
;
4831 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
4832 if (match_current_element( reader
, localname
, ns
)) return S_OK
;
4834 reader
->current
= node
;
4835 reader
->current_attr
= attr
;
4837 return WS_E_INVALID_FORMAT
;
4840 ULONG
get_type_size( WS_TYPE type
, const WS_STRUCT_DESCRIPTION
*desc
)
4846 return sizeof(INT8
);
4849 case WS_UINT16_TYPE
:
4850 return sizeof(INT16
);
4854 case WS_UINT32_TYPE
:
4856 return sizeof(INT32
);
4859 case WS_UINT64_TYPE
:
4860 return sizeof(INT64
);
4862 case WS_DOUBLE_TYPE
:
4863 return sizeof(double);
4865 case WS_DATETIME_TYPE
:
4866 return sizeof(WS_DATETIME
);
4869 return sizeof(GUID
);
4871 case WS_STRING_TYPE
:
4872 return sizeof(WS_STRING
);
4875 return sizeof(WCHAR
*);
4878 return sizeof(WS_BYTES
);
4880 case WS_XML_STRING_TYPE
:
4881 return sizeof(WS_XML_STRING
);
4883 case WS_STRUCT_TYPE
:
4886 case WS_DESCRIPTION_TYPE
:
4887 return sizeof(WS_STRUCT_DESCRIPTION
*);
4890 ERR( "unhandled type %u\n", type
);
4895 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
, ULONG options
)
4897 if (options
& WS_FIELD_POINTER
)
4899 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
4900 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
4901 return WS_READ_REQUIRED_POINTER
;
4912 case WS_UINT16_TYPE
:
4913 case WS_UINT32_TYPE
:
4914 case WS_UINT64_TYPE
:
4915 case WS_DOUBLE_TYPE
:
4916 case WS_DATETIME_TYPE
:
4918 case WS_STRING_TYPE
:
4920 case WS_XML_STRING_TYPE
:
4921 case WS_STRUCT_TYPE
:
4923 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_READ_NILLABLE_VALUE
;
4924 return WS_READ_REQUIRED_VALUE
;
4927 case WS_DESCRIPTION_TYPE
:
4928 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
4929 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
4930 return WS_READ_REQUIRED_POINTER
;
4933 FIXME( "unhandled type %u\n", type
);
4938 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
4939 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
4942 static HRESULT
read_type_repeating_element( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
4943 WS_HEAP
*heap
, void **ret
, ULONG
*count
)
4946 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
4947 WS_READ_OPTION option
;
4950 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
4952 /* wrapper element */
4953 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
4956 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
4957 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
4959 item_size
= sizeof(void *);
4961 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
4964 if (nb_items
>= nb_allocated
)
4966 SIZE_T old_size
= nb_allocated
* item_size
, new_size
= old_size
* 2;
4967 if (!(buf
= ws_realloc_zero( heap
, buf
, old_size
, new_size
)))
4968 return WS_E_QUOTA_EXCEEDED
;
4971 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
4972 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
);
4973 if (hr
== WS_E_INVALID_FORMAT
) break;
4976 ws_free( heap
, buf
, nb_allocated
* item_size
);
4979 offset
+= item_size
;
4983 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
4985 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
4987 TRACE( "number of items %u out of range (%u-%u)\n", nb_items
, desc
->itemRange
->minItemCount
,
4988 desc
->itemRange
->maxItemCount
);
4989 ws_free( heap
, buf
, nb_allocated
* item_size
);
4990 return WS_E_INVALID_FORMAT
;
4999 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5000 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
5003 if (reader
->current
== reader
->last
)
5006 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return S_OK
;
5007 if (!found
) return WS_E_INVALID_FORMAT
;
5009 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
5010 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
5012 return read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
5013 desc
->typeDescription
, option
, heap
, ret
, size
);
5016 static HRESULT
read_type_struct_field( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
5017 WS_HEAP
*heap
, char *buf
, ULONG offset
)
5020 WS_READ_OPTION option
;
5024 if (!desc
) return E_INVALIDARG
;
5025 if (desc
->options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
5027 FIXME( "options %08x not supported\n", desc
->options
);
5030 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
5032 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
5033 size
= get_type_size( desc
->type
, desc
->typeDescription
);
5035 size
= sizeof(void *);
5038 switch (desc
->mapping
)
5040 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING
:
5041 FIXME( "WS_TYPE_ATTRIBUTE_FIELD_MAPPING not supported\n" );
5044 case WS_ATTRIBUTE_FIELD_MAPPING
:
5045 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
5046 desc
->typeDescription
, option
, heap
, ptr
, size
);
5049 case WS_ELEMENT_FIELD_MAPPING
:
5050 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
5051 desc
->typeDescription
, option
, heap
, ptr
, size
);
5054 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
5057 hr
= read_type_repeating_element( reader
, desc
, heap
, (void **)ptr
, &count
);
5058 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
5061 case WS_TEXT_FIELD_MAPPING
:
5062 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
5066 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
5070 if (hr
== WS_E_INVALID_FORMAT
)
5074 case WS_READ_REQUIRED_VALUE
:
5075 case WS_READ_REQUIRED_POINTER
:
5076 return WS_E_INVALID_FORMAT
;
5078 case WS_READ_NILLABLE_VALUE
:
5079 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
5082 case WS_READ_OPTIONAL_POINTER
:
5083 case WS_READ_NILLABLE_POINTER
:
5084 *(void **)ptr
= NULL
;
5088 ERR( "unhandled option %u\n", option
);
5096 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5097 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5098 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5099 WS_HEAP
*heap
, void *ret
, ULONG size
)
5105 if (!desc
) return E_INVALIDARG
;
5106 if (desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5108 FIXME( "struct options %08x not supported\n",
5109 desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
);
5114 case WS_READ_REQUIRED_POINTER
:
5115 case WS_READ_OPTIONAL_POINTER
:
5116 case WS_READ_NILLABLE_POINTER
:
5117 if (size
!= sizeof(void *)) return E_INVALIDARG
;
5118 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
5121 case WS_READ_REQUIRED_VALUE
:
5122 case WS_READ_NILLABLE_VALUE
:
5123 if (size
!= desc
->size
) return E_INVALIDARG
;
5128 FIXME( "unhandled read option %u\n", option
);
5132 for (i
= 0; i
< desc
->fieldCount
; i
++)
5134 offset
= desc
->fields
[i
]->offset
;
5135 if ((hr
= read_type_struct_field( reader
, desc
->fields
[i
], heap
, buf
, offset
)) != S_OK
)
5141 case WS_READ_REQUIRED_POINTER
:
5144 ws_free( heap
, buf
, desc
->size
);
5147 *(char **)ret
= buf
;
5150 case WS_READ_OPTIONAL_POINTER
:
5151 case WS_READ_NILLABLE_POINTER
:
5152 if (is_nil_value( buf
, desc
->size
))
5154 ws_free( heap
, buf
, desc
->size
);
5157 *(char **)ret
= buf
;
5160 case WS_READ_REQUIRED_VALUE
:
5161 case WS_READ_NILLABLE_VALUE
:
5162 if (hr
!= S_OK
) return hr
;
5166 ERR( "unhandled read option %u\n", option
);
5170 if (desc
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
5172 struct node
*parent
= find_parent( reader
);
5173 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
5178 static HRESULT
start_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
5179 const WS_XML_STRING
*ns
)
5183 case WS_ELEMENT_TYPE_MAPPING
:
5184 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5185 return read_type_next_element_node( reader
, localname
, ns
);
5187 case WS_ANY_ELEMENT_TYPE_MAPPING
:
5188 case WS_ATTRIBUTE_TYPE_MAPPING
:
5192 FIXME( "unhandled mapping %u\n", mapping
);
5197 static HRESULT
read_type_endelement_node( struct reader
*reader
)
5199 const struct node
*parent
= find_parent( reader
);
5204 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
5205 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
&& reader
->current
->parent
== parent
)
5209 if (read_end_of_data( reader
) || !(parent
->flags
& NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
)) break;
5212 return WS_E_INVALID_FORMAT
;
5215 static HRESULT
end_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
)
5219 case WS_ELEMENT_TYPE_MAPPING
:
5220 return read_type_endelement_node( reader
);
5222 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
5223 return read_type_next_node( reader
);
5225 case WS_ATTRIBUTE_TYPE_MAPPING
:
5231 static HRESULT
is_nil_element( const WS_XML_ELEMENT_NODE
*elem
)
5233 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
5234 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
5237 for (i
= 0; i
< elem
->attributeCount
; i
++)
5239 const WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[i
]->value
;
5241 if (elem
->attributes
[i
]->isXmlNs
) continue;
5242 if (WsXmlStringEquals( elem
->attributes
[i
]->localName
, &localname
, NULL
) == S_OK
&&
5243 WsXmlStringEquals( elem
->attributes
[i
]->ns
, &ns
, NULL
) == S_OK
&&
5244 text
->value
.length
== 4 && !memcmp( text
->value
.bytes
, "true", 4 )) return TRUE
;
5249 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5250 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
, const void *desc
,
5251 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
)
5255 if ((hr
= start_mapping( reader
, mapping
, localname
, ns
)) != S_OK
) return hr
;
5257 if (mapping
== WS_ELEMENT_TYPE_MAPPING
&& is_nil_element( &reader
->current
->hdr
))
5259 if (option
!= WS_READ_NILLABLE_POINTER
&& option
!= WS_READ_NILLABLE_VALUE
) return WS_E_INVALID_FORMAT
;
5260 return end_mapping( reader
, mapping
);
5266 if ((hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5271 if ((hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5276 if ((hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5281 if ((hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5286 if ((hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5291 if ((hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5295 case WS_UINT16_TYPE
:
5296 if ((hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5300 case WS_UINT32_TYPE
:
5301 if ((hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5305 case WS_UINT64_TYPE
:
5306 if ((hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5310 case WS_DOUBLE_TYPE
:
5311 if ((hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5315 case WS_DATETIME_TYPE
:
5316 if ((hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5321 if ((hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5326 if ((hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5331 if ((hr
= read_type_bytes( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5335 case WS_STRUCT_TYPE
:
5336 if ((hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5341 if ((hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
)) != S_OK
)
5346 FIXME( "type %u not supported\n", type
);
5350 return end_mapping( reader
, mapping
);
5353 /**************************************************************************
5354 * WsReadType [webservices.@]
5356 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
5357 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
5358 ULONG size
, WS_ERROR
*error
)
5360 struct reader
*reader
= (struct reader
*)handle
;
5363 TRACE( "%p %u %u %p %u %p %p %u %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
5365 if (error
) FIXME( "ignoring error parameter\n" );
5367 if (!reader
|| !value
) return E_INVALIDARG
;
5369 EnterCriticalSection( &reader
->cs
);
5371 if (reader
->magic
!= READER_MAGIC
)
5373 LeaveCriticalSection( &reader
->cs
);
5374 return E_INVALIDARG
;
5377 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
)) != S_OK
)
5379 LeaveCriticalSection( &reader
->cs
);
5385 case WS_ELEMENT_TYPE_MAPPING
:
5386 hr
= read_node( reader
);
5393 if (hr
== S_OK
&& !read_end_of_data( reader
)) hr
= WS_E_INVALID_FORMAT
;
5395 LeaveCriticalSection( &reader
->cs
);
5399 HRESULT
read_header( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5400 WS_TYPE type
, const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
5403 struct reader
*reader
= (struct reader
*)handle
;
5406 EnterCriticalSection( &reader
->cs
);
5408 if (reader
->magic
!= READER_MAGIC
)
5410 LeaveCriticalSection( &reader
->cs
);
5411 return E_INVALIDARG
;
5414 hr
= read_type( reader
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, type
, localname
, ns
, desc
, option
, heap
,
5417 LeaveCriticalSection( &reader
->cs
);
5421 /**************************************************************************
5422 * WsReadElement [webservices.@]
5424 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
5425 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5428 struct reader
*reader
= (struct reader
*)handle
;
5431 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5432 if (error
) FIXME( "ignoring error parameter\n" );
5434 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5436 EnterCriticalSection( &reader
->cs
);
5438 if (reader
->magic
!= READER_MAGIC
)
5440 LeaveCriticalSection( &reader
->cs
);
5441 return E_INVALIDARG
;
5444 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
5445 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5447 LeaveCriticalSection( &reader
->cs
);
5451 /**************************************************************************
5452 * WsReadValue [webservices.@]
5454 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
5457 struct reader
*reader
= (struct reader
*)handle
;
5458 WS_TYPE type
= map_value_type( value_type
);
5461 TRACE( "%p %u %p %u %p\n", handle
, type
, value
, size
, error
);
5462 if (error
) FIXME( "ignoring error parameter\n" );
5464 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
5466 EnterCriticalSection( &reader
->cs
);
5468 if (reader
->magic
!= READER_MAGIC
)
5470 LeaveCriticalSection( &reader
->cs
);
5471 return E_INVALIDARG
;
5474 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
5475 NULL
, value
, size
);
5477 LeaveCriticalSection( &reader
->cs
);
5481 /**************************************************************************
5482 * WsReadAttribute [webservices.@]
5484 HRESULT WINAPI
WsReadAttribute( WS_XML_READER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
5485 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
5488 struct reader
*reader
= (struct reader
*)handle
;
5491 TRACE( "%p %p %u %p %p %u %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
5492 if (error
) FIXME( "ignoring error parameter\n" );
5494 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
5496 EnterCriticalSection( &reader
->cs
);
5498 if (reader
->magic
!= READER_MAGIC
)
5500 LeaveCriticalSection( &reader
->cs
);
5501 return E_INVALIDARG
;
5504 if (!reader
->input_type
)
5506 LeaveCriticalSection( &reader
->cs
);
5507 return WS_E_INVALID_OPERATION
;
5510 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->attributeLocalName
,
5511 desc
->attributeNs
, desc
->typeDescription
, option
, heap
, value
, size
);
5513 LeaveCriticalSection( &reader
->cs
);
5517 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5519 static const char bom
[] = {0xef,0xbb,0xbf};
5520 const unsigned char *p
= data
;
5522 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
5523 (size
> 2 && !(*offset
= 0));
5526 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5528 static const char bom
[] = {0xff,0xfe};
5529 const unsigned char *p
= data
;
5531 return (size
>= sizeof(bom
) && !memcmp( p
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
5532 (size
>= 4 && p
[0] == '<' && !p
[1] && !(*offset
= 0));
5535 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
5539 /* FIXME: parse xml declaration */
5541 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
5542 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
5545 FIXME( "charset not recognized\n" );
5549 TRACE( "detected charset %u\n", ret
);
5553 static void set_input_buffer( struct reader
*reader
, struct xmlbuf
*buf
, const unsigned char *data
, ULONG size
)
5555 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
5556 reader
->input_buf
= buf
;
5557 reader
->input_data
= data
;
5558 reader
->input_size
= size
;
5560 reader
->read_size
= reader
->input_size
;
5561 reader
->read_pos
= 0;
5562 reader
->read_bufptr
= reader
->input_data
;
5564 reader
->text_conv_offset
= 0;
5567 /**************************************************************************
5568 * WsSetInput [webservices.@]
5570 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
5571 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
5572 ULONG count
, WS_ERROR
*error
)
5574 struct reader
*reader
= (struct reader
*)handle
;
5576 ULONG i
, offset
= 0;
5579 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, input
, properties
, count
, error
);
5580 if (error
) FIXME( "ignoring error parameter\n" );
5582 if (!reader
) return E_INVALIDARG
;
5584 EnterCriticalSection( &reader
->cs
);
5586 if (reader
->magic
!= READER_MAGIC
)
5588 LeaveCriticalSection( &reader
->cs
);
5589 return E_INVALIDARG
;
5592 for (i
= 0; i
< count
; i
++)
5594 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
5595 properties
[i
].valueSize
);
5596 if (hr
!= S_OK
) goto done
;
5599 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
5601 switch (encoding
->encodingType
)
5603 case WS_XML_READER_ENCODING_TYPE_TEXT
:
5605 WS_XML_READER_TEXT_ENCODING
*text
= (WS_XML_READER_TEXT_ENCODING
*)encoding
;
5606 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
5607 WS_CHARSET charset
= text
->charSet
;
5609 if (input
->inputType
!= WS_XML_READER_INPUT_TYPE_BUFFER
)
5611 FIXME( "charset detection on input type %u not supported\n", input
->inputType
);
5616 if (charset
== WS_CHARSET_AUTO
)
5617 charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
5619 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
,
5620 &charset
, sizeof(charset
) );
5621 if (hr
!= S_OK
) goto done
;
5623 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
5626 case WS_XML_READER_ENCODING_TYPE_BINARY
:
5628 WS_XML_READER_BINARY_ENCODING
*bin
= (WS_XML_READER_BINARY_ENCODING
*)encoding
;
5629 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_BINARY
;
5630 reader
->dict_static
= bin
->staticDictionary
? bin
->staticDictionary
: &dict_builtin_static
;
5631 reader
->dict
= bin
->dynamicDictionary
? bin
->dynamicDictionary
: &dict_builtin
;
5635 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
5640 switch (input
->inputType
)
5642 case WS_XML_READER_INPUT_TYPE_BUFFER
:
5644 WS_XML_READER_BUFFER_INPUT
*buf
= (WS_XML_READER_BUFFER_INPUT
*)input
;
5645 set_input_buffer( reader
, NULL
, (const unsigned char *)buf
->encodedData
+ offset
,
5646 buf
->encodedDataSize
- offset
);
5650 FIXME( "input type %u not supported\n", input
->inputType
);
5655 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
5656 else read_insert_bof( reader
, node
);
5659 LeaveCriticalSection( &reader
->cs
);
5663 /**************************************************************************
5664 * WsSetInputToBuffer [webservices.@]
5666 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
5667 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
5670 struct reader
*reader
= (struct reader
*)handle
;
5671 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
5674 ULONG i
, offset
= 0;
5677 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
5678 if (error
) FIXME( "ignoring error parameter\n" );
5680 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
5682 EnterCriticalSection( &reader
->cs
);
5684 if (reader
->magic
!= READER_MAGIC
)
5686 LeaveCriticalSection( &reader
->cs
);
5687 return E_INVALIDARG
;
5690 for (i
= 0; i
< count
; i
++)
5692 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
5693 properties
[i
].valueSize
);
5694 if (hr
!= S_OK
) goto done
;
5697 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
5699 charset
= detect_charset( xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
, &offset
);
5700 hr
= prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_CHARSET
, &charset
,
5702 if (hr
!= S_OK
) goto done
;
5704 set_input_buffer( reader
, xmlbuf
, xmlbuf
->bytes
.bytes
+ offset
, xmlbuf
->bytes
.length
- offset
);
5705 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
5706 else read_insert_bof( reader
, node
);
5709 LeaveCriticalSection( &reader
->cs
);
5713 /**************************************************************************
5714 * WsGetReaderPosition [webservices.@]
5716 HRESULT WINAPI
WsGetReaderPosition( WS_XML_READER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
5718 struct reader
*reader
= (struct reader
*)handle
;
5720 TRACE( "%p %p %p\n", handle
, pos
, error
);
5721 if (error
) FIXME( "ignoring error parameter\n" );
5723 if (!reader
|| !pos
) return E_INVALIDARG
;
5725 EnterCriticalSection( &reader
->cs
);
5727 if (reader
->magic
!= READER_MAGIC
)
5729 LeaveCriticalSection( &reader
->cs
);
5730 return E_INVALIDARG
;
5733 if (!reader
->input_buf
)
5735 LeaveCriticalSection( &reader
->cs
);
5736 return WS_E_INVALID_OPERATION
;
5739 pos
->buffer
= (WS_XML_BUFFER
*)reader
->input_buf
;
5740 pos
->node
= reader
->current
;
5742 LeaveCriticalSection( &reader
->cs
);
5746 /**************************************************************************
5747 * WsSetReaderPosition [webservices.@]
5749 HRESULT WINAPI
WsSetReaderPosition( WS_XML_READER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
5751 struct reader
*reader
= (struct reader
*)handle
;
5753 TRACE( "%p %p %p\n", handle
, pos
, error
);
5754 if (error
) FIXME( "ignoring error parameter\n" );
5756 if (!reader
|| !pos
) return E_INVALIDARG
;
5758 EnterCriticalSection( &reader
->cs
);
5760 if (reader
->magic
!= READER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= reader
->input_buf
)
5762 LeaveCriticalSection( &reader
->cs
);
5763 return E_INVALIDARG
;
5766 if (!reader
->input_buf
)
5768 LeaveCriticalSection( &reader
->cs
);
5769 return WS_E_INVALID_OPERATION
;
5772 reader
->current
= pos
->node
;
5774 LeaveCriticalSection( &reader
->cs
);
5778 static HRESULT
utf8_to_base64( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_BASE64_TEXT
*base64
)
5780 if (utf8
->value
.length
% 4) return WS_E_INVALID_FORMAT
;
5781 if (!(base64
->bytes
= heap_alloc( utf8
->value
.length
* 3 / 4 ))) return E_OUTOFMEMORY
;
5782 base64
->length
= decode_base64( utf8
->value
.bytes
, utf8
->value
.length
, base64
->bytes
);
5786 /**************************************************************************
5787 * WsReadBytes [webservices.@]
5789 HRESULT WINAPI
WsReadBytes( WS_XML_READER
*handle
, void *bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
5791 struct reader
*reader
= (struct reader
*)handle
;
5794 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
5795 if (error
) FIXME( "ignoring error parameter\n" );
5797 if (!reader
) return E_INVALIDARG
;
5799 EnterCriticalSection( &reader
->cs
);
5801 if (reader
->magic
!= READER_MAGIC
)
5803 LeaveCriticalSection( &reader
->cs
);
5804 return E_INVALIDARG
;
5807 if (!reader
->input_type
)
5809 LeaveCriticalSection( &reader
->cs
);
5810 return WS_E_INVALID_OPERATION
;
5815 LeaveCriticalSection( &reader
->cs
);
5816 return E_INVALIDARG
;
5820 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
5822 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
5823 WS_XML_BASE64_TEXT base64
;
5825 if ((hr
= utf8_to_base64( (const WS_XML_UTF8_TEXT
*)text
->text
, &base64
)) != S_OK
)
5827 LeaveCriticalSection( &reader
->cs
);
5830 if (reader
->text_conv_offset
== base64
.length
)
5832 heap_free( base64
.bytes
);
5833 hr
= read_node( reader
);
5834 LeaveCriticalSection( &reader
->cs
);
5837 *count
= min( base64
.length
- reader
->text_conv_offset
, max_count
);
5838 memcpy( bytes
, base64
.bytes
+ reader
->text_conv_offset
, *count
);
5839 reader
->text_conv_offset
+= *count
;
5840 heap_free( base64
.bytes
);
5843 LeaveCriticalSection( &reader
->cs
);
5847 static HRESULT
utf8_to_utf16( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_UTF16_TEXT
*utf16
)
5849 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
5850 if (!(utf16
->bytes
= heap_alloc( len
* sizeof(WCHAR
) ))) return E_OUTOFMEMORY
;
5851 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, (WCHAR
*)utf16
->bytes
, len
);
5852 utf16
->byteCount
= len
* sizeof(WCHAR
);
5856 /**************************************************************************
5857 * WsReadChars [webservices.@]
5859 HRESULT WINAPI
WsReadChars( WS_XML_READER
*handle
, WCHAR
*chars
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
5861 struct reader
*reader
= (struct reader
*)handle
;
5863 TRACE( "%p %p %u %p %p\n", handle
, chars
, max_count
, count
, error
);
5864 if (error
) FIXME( "ignoring error parameter\n" );
5866 if (!reader
) return E_INVALIDARG
;
5868 EnterCriticalSection( &reader
->cs
);
5870 if (reader
->magic
!= READER_MAGIC
)
5872 LeaveCriticalSection( &reader
->cs
);
5873 return E_INVALIDARG
;
5876 if (!reader
->input_type
)
5878 LeaveCriticalSection( &reader
->cs
);
5879 return WS_E_INVALID_OPERATION
;
5884 LeaveCriticalSection( &reader
->cs
);
5885 return E_INVALIDARG
;
5889 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& chars
)
5891 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
5892 WS_XML_UTF16_TEXT utf16
;
5895 if ((hr
= utf8_to_utf16( (const WS_XML_UTF8_TEXT
*)text
->text
, &utf16
)) != S_OK
)
5897 LeaveCriticalSection( &reader
->cs
);
5900 if (reader
->text_conv_offset
== utf16
.byteCount
/ sizeof(WCHAR
))
5902 heap_free( utf16
.bytes
);
5903 hr
= read_node( reader
);
5904 LeaveCriticalSection( &reader
->cs
);
5907 *count
= min( utf16
.byteCount
/ sizeof(WCHAR
) - reader
->text_conv_offset
, max_count
);
5908 memcpy( chars
, utf16
.bytes
+ reader
->text_conv_offset
* sizeof(WCHAR
), *count
* sizeof(WCHAR
) );
5909 reader
->text_conv_offset
+= *count
;
5910 heap_free( utf16
.bytes
);
5913 LeaveCriticalSection( &reader
->cs
);
5917 /**************************************************************************
5918 * WsReadCharsUtf8 [webservices.@]
5920 HRESULT WINAPI
WsReadCharsUtf8( WS_XML_READER
*handle
, BYTE
*bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
5922 struct reader
*reader
= (struct reader
*)handle
;
5925 TRACE( "%p %p %u %p %p\n", handle
, bytes
, max_count
, count
, error
);
5926 if (error
) FIXME( "ignoring error parameter\n" );
5928 if (!reader
) return E_INVALIDARG
;
5930 EnterCriticalSection( &reader
->cs
);
5932 if (reader
->magic
!= READER_MAGIC
)
5934 LeaveCriticalSection( &reader
->cs
);
5935 return E_INVALIDARG
;
5938 if (!reader
->input_type
)
5940 LeaveCriticalSection( &reader
->cs
);
5941 return WS_E_INVALID_OPERATION
;
5946 LeaveCriticalSection( &reader
->cs
);
5947 return E_INVALIDARG
;
5951 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
5953 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
5954 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
5956 if (reader
->text_conv_offset
== utf8
->value
.length
)
5958 hr
= read_node( reader
);
5959 LeaveCriticalSection( &reader
->cs
);
5962 *count
= min( utf8
->value
.length
- reader
->text_conv_offset
, max_count
);
5963 memcpy( bytes
, utf8
->value
.bytes
+ reader
->text_conv_offset
, *count
);
5964 reader
->text_conv_offset
+= *count
;
5967 LeaveCriticalSection( &reader
->cs
);
5971 static HRESULT
move_to_element( struct reader
*reader
)
5974 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_BOF
&&
5975 (hr
= read_move_to( reader
, WS_MOVE_TO_CHILD_NODE
, NULL
)) != S_OK
) return hr
;
5976 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return E_FAIL
;
5980 static HRESULT
copy_tree( struct reader
*reader
, WS_XML_WRITER
*writer
)
5982 const struct node
*node
, *parent
;
5986 if ((hr
= move_to_element( reader
)) != S_OK
) return hr
;
5987 parent
= reader
->current
;
5990 node
= reader
->current
;
5991 if ((hr
= WsWriteNode( writer
, (const WS_XML_NODE
*)node
, NULL
)) != S_OK
) break;
5992 if (node_type( node
) == WS_XML_NODE_TYPE_END_ELEMENT
&& node
->parent
== parent
) done
= TRUE
;
5993 if ((hr
= read_next_node( reader
)) != S_OK
|| done
) break;
5998 /**************************************************************************
5999 * WsReadXmlBuffer [webservices.@]
6001 HRESULT WINAPI
WsReadXmlBuffer( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_BUFFER
**ret
, WS_ERROR
*error
)
6003 struct reader
*reader
= (struct reader
*)handle
;
6004 WS_XML_WRITER
*writer
= NULL
;
6005 WS_XML_BUFFER
*buffer
;
6008 TRACE( "%p %p %p %p\n", handle
, heap
, ret
, error
);
6009 if (error
) FIXME( "ignoring error parameter\n" );
6011 if (!reader
|| !heap
) return E_INVALIDARG
;
6012 if (!ret
) return E_FAIL
;
6014 EnterCriticalSection( &reader
->cs
);
6016 if (reader
->magic
!= READER_MAGIC
)
6018 LeaveCriticalSection( &reader
->cs
);
6019 return E_INVALIDARG
;
6022 if (!reader
->input_type
)
6024 LeaveCriticalSection( &reader
->cs
);
6025 return WS_E_INVALID_OPERATION
;
6028 if ((hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
)) != S_OK
) goto done
;
6029 if ((hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
)) != S_OK
) goto done
;
6030 if ((hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
)) != S_OK
) goto done
;
6031 if ((hr
= copy_tree( reader
, writer
)) == S_OK
) *ret
= buffer
;
6034 if (hr
!= S_OK
) free_xmlbuf( (struct xmlbuf
*)buffer
);
6035 WsFreeWriter( writer
);
6036 LeaveCriticalSection( &reader
->cs
);
6040 HRESULT
get_param_desc( const WS_STRUCT_DESCRIPTION
*desc
, USHORT index
, const WS_FIELD_DESCRIPTION
**ret
)
6042 if (index
>= desc
->fieldCount
) return E_INVALIDARG
;
6043 *ret
= desc
->fields
[index
];
6047 static ULONG
get_field_size( const WS_FIELD_DESCRIPTION
*desc
)
6049 WS_READ_OPTION option
;
6052 switch ((option
= get_field_read_option( desc
->type
, desc
->options
)))
6054 case WS_READ_REQUIRED_POINTER
:
6055 case WS_READ_OPTIONAL_POINTER
:
6056 case WS_READ_NILLABLE_POINTER
:
6057 size
= sizeof(void *);
6060 case WS_READ_REQUIRED_VALUE
:
6061 case WS_READ_NILLABLE_VALUE
:
6062 size
= get_type_size( desc
->type
, desc
->typeDescription
);
6066 WARN( "unhandled option %u\n", option
);
6073 static HRESULT
read_param( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
, void *ret
)
6075 if (!ret
&& !(ret
= ws_alloc_zero( heap
, get_field_size(desc
) ))) return WS_E_QUOTA_EXCEEDED
;
6076 return read_type_struct_field( reader
, desc
, heap
, ret
, 0 );
6079 static HRESULT
read_param_array( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
,
6080 void **ret
, ULONG
*count
)
6082 if (!ret
&& !(ret
= ws_alloc_zero( heap
, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED
;
6083 return read_type_repeating_element( reader
, desc
, heap
, ret
, count
);
6086 static void set_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, ULONG len
,
6090 for (i
= 0; i
< count
; i
++)
6092 if (params
[i
].outputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
6094 if ((ptr
= *(ULONG
**)args
[i
])) *ptr
= len
;
6099 HRESULT
read_output_params( WS_XML_READER
*handle
, WS_HEAP
*heap
, const WS_ELEMENT_DESCRIPTION
*desc
,
6100 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
6102 struct reader
*reader
= (struct reader
*)handle
;
6103 const WS_STRUCT_DESCRIPTION
*desc_struct
;
6104 const WS_FIELD_DESCRIPTION
*desc_field
;
6108 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
6110 EnterCriticalSection( &reader
->cs
);
6112 if (reader
->magic
!= READER_MAGIC
)
6114 LeaveCriticalSection( &reader
->cs
);
6115 return E_INVALIDARG
;
6118 if ((hr
= start_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
)
6121 for (i
= 0; i
< count
; i
++)
6123 if (params
[i
].outputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
6124 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
6126 FIXME( "messages type not supported\n" );
6130 if ((hr
= get_param_desc( desc_struct
, params
[i
].outputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
6131 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
6133 void *ptr
= *(void **)args
[i
];
6134 if ((hr
= read_param( reader
, desc_field
, heap
, ptr
)) != S_OK
) goto done
;
6136 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
6138 void **ptr
= *(void ***)args
[i
];
6139 if ((hr
= read_param_array( reader
, desc_field
, heap
, ptr
, &len
)) != S_OK
) goto done
;
6140 set_array_len( params
, count
, params
[i
].outputMessageIndex
, len
, args
);
6144 if (desc_struct
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
6146 struct node
*parent
= find_parent( reader
);
6147 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
6150 hr
= end_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
);
6153 LeaveCriticalSection( &reader
->cs
);