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
28 #include "webservices.h"
30 #include "wine/debug.h"
31 #include "wine/list.h"
32 #include "webservices_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
36 ULONG
prop_size( const struct prop_desc
*desc
, ULONG count
)
38 ULONG i
, ret
= count
* sizeof(struct prop
);
39 for (i
= 0; i
< count
; i
++) ret
+= desc
[i
].size
;
43 void prop_init( const struct prop_desc
*desc
, ULONG count
, struct prop
*prop
, void *data
)
47 for (i
= 0; i
< count
; i
++)
50 prop
[i
].size
= desc
[i
].size
;
51 prop
[i
].readonly
= desc
[i
].readonly
;
52 prop
[i
].writeonly
= desc
[i
].writeonly
;
57 HRESULT
prop_set( const struct prop
*prop
, ULONG count
, ULONG id
, const void *value
, ULONG size
)
59 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].readonly
) return E_INVALIDARG
;
60 memcpy( prop
[id
].value
, value
, size
);
64 HRESULT
prop_get( const struct prop
*prop
, ULONG count
, ULONG id
, void *buf
, ULONG size
)
66 if (id
>= count
|| size
!= prop
[id
].size
|| prop
[id
].writeonly
) return E_INVALIDARG
;
67 memcpy( buf
, prop
[id
].value
, prop
[id
].size
);
71 struct node
*alloc_node( WS_XML_NODE_TYPE type
)
75 if (!(ret
= calloc( 1, sizeof(*ret
) ))) return NULL
;
76 ret
->hdr
.node
.nodeType
= type
;
77 list_init( &ret
->entry
);
78 list_init( &ret
->children
);
82 void free_attribute( WS_XML_ATTRIBUTE
*attr
)
85 free_xml_string( attr
->prefix
);
86 free_xml_string( attr
->localName
);
87 free_xml_string( attr
->ns
);
92 void free_node( struct node
*node
)
95 switch (node_type( node
))
97 case WS_XML_NODE_TYPE_ELEMENT
:
99 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
102 for (i
= 0; i
< elem
->attributeCount
; i
++) free_attribute( elem
->attributes
[i
] );
103 free( elem
->attributes
);
104 free_xml_string( elem
->prefix
);
105 free_xml_string( elem
->localName
);
106 free_xml_string( elem
->ns
);
109 case WS_XML_NODE_TYPE_TEXT
:
111 WS_XML_TEXT_NODE
*text
= (WS_XML_TEXT_NODE
*)node
;
115 case WS_XML_NODE_TYPE_COMMENT
:
117 WS_XML_COMMENT_NODE
*comment
= (WS_XML_COMMENT_NODE
*)node
;
118 free( comment
->value
.bytes
);
121 case WS_XML_NODE_TYPE_CDATA
:
122 case WS_XML_NODE_TYPE_END_CDATA
:
123 case WS_XML_NODE_TYPE_END_ELEMENT
:
124 case WS_XML_NODE_TYPE_EOF
:
125 case WS_XML_NODE_TYPE_BOF
:
129 ERR( "unhandled type %u\n", node_type( node
) );
135 void destroy_nodes( struct node
*node
)
140 while ((ptr
= list_head( &node
->children
)))
142 struct node
*child
= LIST_ENTRY( ptr
, struct node
, entry
);
143 list_remove( &child
->entry
);
144 destroy_nodes( child
);
149 static WS_XML_ATTRIBUTE
*dup_attribute( const WS_XML_ATTRIBUTE
*src
, WS_XML_WRITER_ENCODING_TYPE enc
)
151 WS_XML_ATTRIBUTE
*dst
;
154 if (!(dst
= calloc( 1, sizeof(*dst
) ))) return NULL
;
155 dst
->singleQuote
= src
->singleQuote
;
156 dst
->isXmlNs
= src
->isXmlNs
;
158 if (src
->prefix
&& !(dst
->prefix
= dup_xml_string( src
->prefix
, FALSE
))) goto error
;
159 if (src
->localName
&& !(dst
->localName
= dup_xml_string( src
->localName
, FALSE
))) goto error
;
160 if (src
->ns
&& !(dst
->ns
= dup_xml_string( src
->ns
, FALSE
))) goto error
;
166 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
167 if ((hr
= text_to_text( src
->value
, NULL
, NULL
, &dst
->value
)) != S_OK
) goto error
;
170 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
171 if ((hr
= text_to_utf8text( src
->value
, NULL
, NULL
, (WS_XML_UTF8_TEXT
**)&dst
->value
)) != S_OK
)
176 ERR( "unhandled encoding %u\n", enc
);
184 free_attribute( dst
);
188 static WS_XML_ATTRIBUTE
**dup_attributes( WS_XML_ATTRIBUTE
* const *src
, ULONG count
,
189 WS_XML_WRITER_ENCODING_TYPE enc
)
191 WS_XML_ATTRIBUTE
**dst
;
194 if (!(dst
= malloc( sizeof(*dst
) * count
))) return NULL
;
195 for (i
= 0; i
< count
; i
++)
197 if (!(dst
[i
] = dup_attribute( src
[i
], enc
)))
199 for (; i
> 0; i
--) free_attribute( dst
[i
- 1] );
207 static struct node
*dup_element_node( const WS_XML_ELEMENT_NODE
*src
, WS_XML_WRITER_ENCODING_TYPE enc
)
210 WS_XML_ELEMENT_NODE
*dst
;
211 ULONG count
= src
->attributeCount
;
212 WS_XML_ATTRIBUTE
**attrs
= src
->attributes
;
213 const WS_XML_STRING
*prefix
= (src
->prefix
&& src
->prefix
->length
) ? src
->prefix
: NULL
;
214 const WS_XML_STRING
*localname
= src
->localName
;
215 const WS_XML_STRING
*ns
= src
->ns
;
217 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
220 if (count
&& !(dst
->attributes
= dup_attributes( attrs
, count
, enc
))) goto error
;
221 dst
->attributeCount
= count
;
223 if (prefix
&& !(dst
->prefix
= dup_xml_string( prefix
, FALSE
))) goto error
;
224 if (localname
&& !(dst
->localName
= dup_xml_string( localname
, FALSE
))) goto error
;
225 if (ns
&& !(dst
->ns
= dup_xml_string( ns
, FALSE
))) goto error
;
233 static struct node
*dup_text_node( const WS_XML_TEXT_NODE
*src
, WS_XML_WRITER_ENCODING_TYPE enc
)
236 WS_XML_TEXT_NODE
*dst
;
239 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
240 dst
= (WS_XML_TEXT_NODE
*)node
;
241 if (!src
->text
) return node
;
245 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
246 hr
= text_to_text( src
->text
, NULL
, NULL
, &dst
->text
);
249 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
250 hr
= text_to_utf8text( src
->text
, NULL
, NULL
, (WS_XML_UTF8_TEXT
**)&dst
->text
);
254 ERR( "unhandled encoding %u\n", enc
);
268 static struct node
*dup_comment_node( const WS_XML_COMMENT_NODE
*src
)
271 WS_XML_COMMENT_NODE
*dst
;
273 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return NULL
;
274 dst
= (WS_XML_COMMENT_NODE
*)node
;
276 if (src
->value
.length
&& !(dst
->value
.bytes
= malloc( src
->value
.length
)))
281 memcpy( dst
->value
.bytes
, src
->value
.bytes
, src
->value
.length
);
282 dst
->value
.length
= src
->value
.length
;
286 static struct node
*dup_node( const struct node
*src
, WS_XML_WRITER_ENCODING_TYPE enc
)
288 switch (node_type( src
))
290 case WS_XML_NODE_TYPE_ELEMENT
:
291 return dup_element_node( &src
->hdr
, enc
);
293 case WS_XML_NODE_TYPE_TEXT
:
294 return dup_text_node( (const WS_XML_TEXT_NODE
*)src
, enc
);
296 case WS_XML_NODE_TYPE_COMMENT
:
297 return dup_comment_node( (const WS_XML_COMMENT_NODE
*)src
);
299 case WS_XML_NODE_TYPE_CDATA
:
300 case WS_XML_NODE_TYPE_END_CDATA
:
301 case WS_XML_NODE_TYPE_END_ELEMENT
:
302 case WS_XML_NODE_TYPE_EOF
:
303 case WS_XML_NODE_TYPE_BOF
:
304 return alloc_node( node_type( src
) );
307 ERR( "unhandled type %u\n", node_type( src
) );
313 static HRESULT
dup_tree( const struct node
*src
, WS_XML_WRITER_ENCODING_TYPE enc
, struct node
**dst
)
316 const struct node
*child
;
318 if (!*dst
&& !(*dst
= dup_node( src
, enc
))) return E_OUTOFMEMORY
;
321 LIST_FOR_EACH_ENTRY( child
, &src
->children
, struct node
, entry
)
323 HRESULT hr
= E_OUTOFMEMORY
;
324 struct node
*new_child
;
326 if (!(new_child
= dup_node( child
, enc
)) || (hr
= dup_tree( child
, enc
, &new_child
)) != S_OK
)
328 destroy_nodes( *dst
);
331 new_child
->parent
= parent
;
332 list_add_tail( &parent
->children
, &new_child
->entry
);
337 static const struct prop_desc reader_props
[] =
339 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
340 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_FRAGMENT */
341 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
342 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_READ_DECLARATION */
343 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_READER_PROPERTY_CHARSET */
344 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_ROW */
345 { sizeof(ULONGLONG
), TRUE
}, /* WS_XML_READER_PROPERTY_COLUMN */
346 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_UTF8_TRIM_SIZE */
347 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_BUFFER_SIZE */
348 { sizeof(BOOL
), TRUE
}, /* WS_XML_READER_PROPERTY_IN_ATTRIBUTE */
349 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_ROOT_MIME_PART_SIZE */
350 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_STREAM_MAX_MIME_HEADERS_SIZE */
351 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_MIME_PARTS */
352 { sizeof(BOOL
), FALSE
}, /* WS_XML_READER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
353 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_NAMESPACES */
358 READER_STATE_INITIAL
,
360 READER_STATE_STARTELEMENT
,
361 READER_STATE_STARTATTRIBUTE
,
362 READER_STATE_STARTCDATA
,
365 READER_STATE_ENDELEMENT
,
366 READER_STATE_ENDCDATA
,
367 READER_STATE_COMMENT
,
383 const unsigned char *read_bufptr
;
384 enum reader_state state
;
386 struct node
*current
;
389 struct prefix
*prefixes
;
391 ULONG nb_prefixes_allocated
;
392 WS_XML_READER_ENCODING_TYPE input_enc
;
393 WS_CHARSET input_charset
;
394 WS_XML_READER_INPUT_TYPE input_type
;
395 WS_READ_CALLBACK input_cb
;
396 void *input_cb_state
;
397 struct xmlbuf
*input_buf
;
398 unsigned char *input_conv
;
400 ULONG text_conv_offset
;
401 unsigned char *stream_buf
;
402 const WS_XML_DICTIONARY
*dict_static
;
403 WS_XML_DICTIONARY
*dict
;
405 struct prop prop
[ARRAY_SIZE( reader_props
)];
408 #define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D')
410 static struct reader
*alloc_reader(void)
412 static const ULONG count
= ARRAY_SIZE( reader_props
);
414 ULONG size
= sizeof(*ret
) + prop_size( reader_props
, count
);
416 if (!(ret
= calloc( 1, size
))) return NULL
;
417 if (!(ret
->prefixes
= calloc( 1, sizeof(*ret
->prefixes
) )))
422 ret
->nb_prefixes
= ret
->nb_prefixes_allocated
= 1;
424 ret
->magic
= READER_MAGIC
;
425 InitializeCriticalSection( &ret
->cs
);
426 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": reader.cs");
428 prop_init( reader_props
, count
, ret
->prop
, &ret
[1] );
429 ret
->prop_count
= count
;
433 static void clear_prefixes( struct prefix
*prefixes
, ULONG count
)
436 for (i
= 0; i
< count
; i
++)
438 free_xml_string( prefixes
[i
].str
);
439 prefixes
[i
].str
= NULL
;
440 free_xml_string( prefixes
[i
].ns
);
441 prefixes
[i
].ns
= NULL
;
445 static HRESULT
set_prefix( struct prefix
*prefix
, const WS_XML_STRING
*str
, const WS_XML_STRING
*ns
)
449 free_xml_string( prefix
->str
);
450 if (!(prefix
->str
= dup_xml_string( str
, FALSE
))) return E_OUTOFMEMORY
;
452 if (prefix
->ns
) free_xml_string( prefix
->ns
);
453 if (!(prefix
->ns
= dup_xml_string( ns
, FALSE
))) return E_OUTOFMEMORY
;
457 static HRESULT
bind_prefix( struct reader
*reader
, const WS_XML_STRING
*prefix
, const WS_XML_STRING
*ns
)
462 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
464 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
465 return set_prefix( &reader
->prefixes
[i
], NULL
, ns
);
467 if (i
>= reader
->nb_prefixes_allocated
)
469 ULONG new_size
= reader
->nb_prefixes_allocated
* 2;
470 struct prefix
*tmp
= realloc( reader
->prefixes
, new_size
* sizeof(*tmp
) );
471 if (!tmp
) return E_OUTOFMEMORY
;
472 memset( tmp
+ reader
->nb_prefixes_allocated
, 0, (new_size
- reader
->nb_prefixes_allocated
) * sizeof(*tmp
) );
473 reader
->prefixes
= tmp
;
474 reader
->nb_prefixes_allocated
= new_size
;
476 if ((hr
= set_prefix( &reader
->prefixes
[i
], prefix
, ns
)) != S_OK
) return hr
;
477 reader
->nb_prefixes
++;
481 static const WS_XML_STRING
*get_namespace( struct reader
*reader
, const WS_XML_STRING
*prefix
)
484 for (i
= 0; i
< reader
->nb_prefixes
; i
++)
486 if (WsXmlStringEquals( prefix
, reader
->prefixes
[i
].str
, NULL
) == S_OK
)
487 return reader
->prefixes
[i
].ns
;
492 static void read_insert_eof( struct reader
*reader
, struct node
*eof
)
494 if (!reader
->root
) reader
->root
= eof
;
497 eof
->parent
= reader
->root
;
498 list_add_tail( &reader
->root
->children
, &eof
->entry
);
500 reader
->current
= reader
->last
= eof
;
503 static void read_insert_bof( struct reader
*reader
, struct node
*bof
)
505 reader
->root
->parent
= bof
;
506 list_add_tail( &bof
->children
, &reader
->root
->entry
);
507 reader
->current
= reader
->last
= reader
->root
= bof
;
510 static void read_insert_node( struct reader
*reader
, struct node
*parent
, struct node
*node
)
512 node
->parent
= parent
;
513 list_add_before( list_tail( &parent
->children
), &node
->entry
);
514 reader
->current
= reader
->last
= node
;
517 static void free_reader( struct reader
*reader
)
519 destroy_nodes( reader
->root
);
520 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
521 free( reader
->prefixes
);
522 free( reader
->stream_buf
);
523 free( reader
->input_conv
);
525 reader
->cs
.DebugInfo
->Spare
[0] = 0;
526 DeleteCriticalSection( &reader
->cs
);
530 static HRESULT
init_reader( struct reader
*reader
)
532 static const WS_XML_STRING empty
= {0, NULL
};
536 reader
->state
= READER_STATE_INITIAL
;
537 destroy_nodes( reader
->root
);
538 reader
->root
= reader
->current
= NULL
;
539 reader
->current_attr
= 0;
540 clear_prefixes( reader
->prefixes
, reader
->nb_prefixes
);
541 reader
->nb_prefixes
= 1;
542 if ((hr
= bind_prefix( reader
, &empty
, &empty
)) != S_OK
) return hr
;
544 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
545 read_insert_eof( reader
, node
);
546 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
547 reader
->input_charset
= WS_CHARSET_UTF8
;
548 reader
->dict_static
= NULL
;
553 /**************************************************************************
554 * WsCreateReader [webservices.@]
556 HRESULT WINAPI
WsCreateReader( const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
557 WS_XML_READER
**handle
, WS_ERROR
*error
)
559 struct reader
*reader
;
560 ULONG i
, max_depth
= 32, max_attrs
= 128, max_ns
= 32;
561 BOOL read_decl
= TRUE
;
564 TRACE( "%p %lu %p %p\n", properties
, count
, handle
, error
);
565 if (error
) FIXME( "ignoring error parameter\n" );
567 if (!handle
) return E_INVALIDARG
;
568 if (!(reader
= alloc_reader())) return E_OUTOFMEMORY
;
570 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
571 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
572 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_READ_DECLARATION
, &read_decl
, sizeof(read_decl
) );
573 prop_set( reader
->prop
, reader
->prop_count
, WS_XML_READER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
575 for (i
= 0; i
< count
; i
++)
577 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
578 properties
[i
].valueSize
);
581 free_reader( reader
);
586 if ((hr
= init_reader( reader
)) != S_OK
)
588 free_reader( reader
);
592 TRACE( "created %p\n", reader
);
593 *handle
= (WS_XML_READER
*)reader
;
597 /**************************************************************************
598 * WsFreeReader [webservices.@]
600 void WINAPI
WsFreeReader( WS_XML_READER
*handle
)
602 struct reader
*reader
= (struct reader
*)handle
;
604 TRACE( "%p\n", handle
);
608 EnterCriticalSection( &reader
->cs
);
610 if (reader
->magic
!= READER_MAGIC
)
612 LeaveCriticalSection( &reader
->cs
);
618 LeaveCriticalSection( &reader
->cs
);
619 free_reader( reader
);
622 static HRESULT
read_more_data( struct reader
*reader
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
625 ULONG size
= 0, max_size
;
627 if (reader
->read_size
- reader
->read_pos
>= min_size
) return S_OK
;
628 if (reader
->input_type
!= WS_XML_READER_INPUT_TYPE_STREAM
) return WS_E_INVALID_FORMAT
;
629 if (min_size
> reader
->input_size
) return WS_E_QUOTA_EXCEEDED
;
631 if (reader
->read_pos
)
633 memmove( reader
->stream_buf
, reader
->stream_buf
+ reader
->read_pos
, reader
->read_size
- reader
->read_pos
);
634 reader
->read_size
-= reader
->read_pos
;
635 reader
->read_pos
= 0;
637 max_size
= reader
->input_size
- reader
->read_size
;
639 reader
->input_cb( reader
->input_cb_state
, reader
->stream_buf
+ reader
->read_size
, max_size
, &size
, ctx
, error
);
640 if (size
< min_size
) return WS_E_QUOTA_EXCEEDED
;
641 reader
->read_size
+= size
;
645 /**************************************************************************
646 * WsFillReader [webservices.@]
648 HRESULT WINAPI
WsFillReader( WS_XML_READER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
651 struct reader
*reader
= (struct reader
*)handle
;
654 TRACE( "%p %lu %p %p\n", handle
, min_size
, ctx
, error
);
655 if (error
) FIXME( "ignoring error parameter\n" );
656 if (ctx
) FIXME( "ignoring ctx parameter\n" );
658 if (!reader
) return E_INVALIDARG
;
660 EnterCriticalSection( &reader
->cs
);
662 if (reader
->magic
!= READER_MAGIC
)
664 LeaveCriticalSection( &reader
->cs
);
668 if (reader
->input_type
== WS_XML_READER_INPUT_TYPE_STREAM
)
670 hr
= read_more_data( reader
, min_size
, ctx
, error
);
674 reader
->read_size
= min( min_size
, reader
->input_size
);
675 reader
->read_pos
= 0;
679 LeaveCriticalSection( &reader
->cs
);
680 TRACE( "returning %#lx\n", hr
);
684 /**************************************************************************
685 * WsGetNamespaceFromPrefix [webservices.@]
687 HRESULT WINAPI
WsGetNamespaceFromPrefix( WS_XML_READER
*handle
, const WS_XML_STRING
*prefix
,
688 BOOL required
, const WS_XML_STRING
**ns
, WS_ERROR
*error
)
690 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
691 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
692 static const WS_XML_STRING empty_ns
= {0, NULL
};
693 static const WS_XML_STRING xml_ns
= {36, (BYTE
*)"http://www.w3.org/XML/1998/namespace"};
694 static const WS_XML_STRING xmlns_ns
= {29, (BYTE
*)"http://www.w3.org/2000/xmlns/"};
695 struct reader
*reader
= (struct reader
*)handle
;
699 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(prefix
), required
, ns
, error
);
700 if (error
) FIXME( "ignoring error parameter\n" );
702 if (!reader
|| !prefix
|| !ns
) return E_INVALIDARG
;
704 EnterCriticalSection( &reader
->cs
);
706 if (reader
->magic
!= READER_MAGIC
)
708 LeaveCriticalSection( &reader
->cs
);
712 if (reader
->state
!= READER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_OPERATION
;
713 else if (!prefix
->length
)
718 else if (WsXmlStringEquals( prefix
, &xml
, NULL
) == S_OK
)
723 else if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
730 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
733 for (i
= 0; i
< elem
->attributeCount
; i
++)
735 if (!elem
->attributes
[i
]->isXmlNs
) continue;
736 if (WsXmlStringEquals( prefix
, elem
->attributes
[i
]->prefix
, NULL
) == S_OK
)
738 *ns
= elem
->attributes
[i
]->ns
;
745 LeaveCriticalSection( &reader
->cs
);
747 if (hr
== S_OK
&& !found
)
749 if (required
) hr
= WS_E_INVALID_FORMAT
;
757 TRACE( "returning %#lx\n", hr
);
761 /**************************************************************************
762 * WsGetReaderNode [webservices.@]
764 HRESULT WINAPI
WsGetReaderNode( WS_XML_READER
*handle
, const WS_XML_NODE
**node
,
767 struct reader
*reader
= (struct reader
*)handle
;
770 TRACE( "%p %p %p\n", handle
, node
, error
);
771 if (error
) FIXME( "ignoring error parameter\n" );
773 if (!reader
|| !node
) return E_INVALIDARG
;
775 EnterCriticalSection( &reader
->cs
);
777 if (reader
->magic
!= READER_MAGIC
)
779 LeaveCriticalSection( &reader
->cs
);
783 *node
= &reader
->current
->hdr
.node
;
785 LeaveCriticalSection( &reader
->cs
);
786 TRACE( "returning %#lx\n", hr
);
790 static HRESULT
get_charset( struct reader
*reader
, void *buf
, ULONG size
)
792 if (!buf
|| size
!= sizeof(reader
->input_charset
)) return E_INVALIDARG
;
793 if (!reader
->input_charset
) return WS_E_INVALID_FORMAT
;
794 *(WS_CHARSET
*)buf
= reader
->input_charset
;
798 /**************************************************************************
799 * WsGetReaderProperty [webservices.@]
801 HRESULT WINAPI
WsGetReaderProperty( WS_XML_READER
*handle
, WS_XML_READER_PROPERTY_ID id
,
802 void *buf
, ULONG size
, WS_ERROR
*error
)
804 struct reader
*reader
= (struct reader
*)handle
;
807 TRACE( "%p %u %p %lu %p\n", handle
, id
, buf
, size
, error
);
808 if (error
) FIXME( "ignoring error parameter\n" );
810 if (!reader
) return E_INVALIDARG
;
812 EnterCriticalSection( &reader
->cs
);
814 if (reader
->magic
!= READER_MAGIC
)
816 LeaveCriticalSection( &reader
->cs
);
820 if (!reader
->input_type
) hr
= WS_E_INVALID_OPERATION
;
821 else if (id
== WS_XML_READER_PROPERTY_CHARSET
) hr
= get_charset( reader
, buf
, size
);
822 else hr
= prop_get( reader
->prop
, reader
->prop_count
, id
, buf
, size
);
824 LeaveCriticalSection( &reader
->cs
);
825 TRACE( "returning %#lx\n", hr
);
829 /**************************************************************************
830 * WsGetXmlAttribute [webservices.@]
832 HRESULT WINAPI
WsGetXmlAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*attr
,
833 WS_HEAP
*heap
, WCHAR
**str
, ULONG
*len
, WS_ERROR
*error
)
835 FIXME( "%p %s %p %p %p %p: stub\n", handle
, debugstr_xmlstr(attr
), heap
, str
, len
, error
);
839 WS_XML_UTF8_TEXT
*alloc_utf8_text( const BYTE
*data
, ULONG len
)
841 WS_XML_UTF8_TEXT
*ret
;
843 if (!(ret
= malloc( sizeof(*ret
) + len
))) return NULL
;
844 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
845 ret
->value
.length
= len
;
846 ret
->value
.bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
847 ret
->value
.dictionary
= NULL
;
849 if (data
) memcpy( ret
->value
.bytes
, data
, len
);
853 WS_XML_UTF16_TEXT
*alloc_utf16_text( const BYTE
*data
, ULONG len
)
855 WS_XML_UTF16_TEXT
*ret
;
857 if (!(ret
= malloc( sizeof(*ret
) + len
))) return NULL
;
858 ret
->text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
859 ret
->byteCount
= len
;
860 ret
->bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
861 if (data
) memcpy( ret
->bytes
, data
, len
);
865 WS_XML_BASE64_TEXT
*alloc_base64_text( const BYTE
*data
, ULONG len
)
867 WS_XML_BASE64_TEXT
*ret
;
869 if (!(ret
= malloc( sizeof(*ret
) + len
))) return NULL
;
870 ret
->text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
872 ret
->bytes
= len
? (BYTE
*)(ret
+ 1) : NULL
;
873 if (data
) memcpy( ret
->bytes
, data
, len
);
877 WS_XML_BOOL_TEXT
*alloc_bool_text( BOOL value
)
879 WS_XML_BOOL_TEXT
*ret
;
881 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
882 ret
->text
.textType
= WS_XML_TEXT_TYPE_BOOL
;
887 WS_XML_INT32_TEXT
*alloc_int32_text( INT32 value
)
889 WS_XML_INT32_TEXT
*ret
;
891 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
892 ret
->text
.textType
= WS_XML_TEXT_TYPE_INT32
;
897 WS_XML_INT64_TEXT
*alloc_int64_text( INT64 value
)
899 WS_XML_INT64_TEXT
*ret
;
901 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
902 ret
->text
.textType
= WS_XML_TEXT_TYPE_INT64
;
907 WS_XML_UINT64_TEXT
*alloc_uint64_text( UINT64 value
)
909 WS_XML_UINT64_TEXT
*ret
;
911 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
912 ret
->text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
917 static WS_XML_FLOAT_TEXT
*alloc_float_text( float value
)
919 WS_XML_FLOAT_TEXT
*ret
;
921 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
922 ret
->text
.textType
= WS_XML_TEXT_TYPE_FLOAT
;
927 WS_XML_DOUBLE_TEXT
*alloc_double_text( double value
)
929 WS_XML_DOUBLE_TEXT
*ret
;
931 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
932 ret
->text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
937 WS_XML_GUID_TEXT
*alloc_guid_text( const GUID
*value
)
939 WS_XML_GUID_TEXT
*ret
;
941 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
942 ret
->text
.textType
= WS_XML_TEXT_TYPE_GUID
;
947 WS_XML_UNIQUE_ID_TEXT
*alloc_unique_id_text( const GUID
*value
)
949 WS_XML_UNIQUE_ID_TEXT
*ret
;
951 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
952 ret
->text
.textType
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
957 WS_XML_DATETIME_TEXT
*alloc_datetime_text( const WS_DATETIME
*value
)
959 WS_XML_DATETIME_TEXT
*ret
;
961 if (!(ret
= malloc( sizeof(*ret
) ))) return NULL
;
962 ret
->text
.textType
= WS_XML_TEXT_TYPE_DATETIME
;
967 static inline BOOL
read_end_of_data( struct reader
*reader
)
969 return (read_more_data( reader
, 1, NULL
, NULL
) != S_OK
);
972 static inline const unsigned char *read_current_ptr( struct reader
*reader
)
974 return &reader
->read_bufptr
[reader
->read_pos
];
977 static inline void read_skip( struct reader
*reader
, unsigned int count
)
979 assert( reader
->read_pos
+ count
<= reader
->read_size
);
980 reader
->read_pos
+= count
;
983 static inline HRESULT
read_peek( struct reader
*reader
, unsigned char *bytes
, unsigned int len
)
986 if ((hr
= read_more_data( reader
, len
, NULL
, NULL
)) != S_OK
) return hr
;
987 memcpy( bytes
, read_current_ptr( reader
), len
);
991 static inline HRESULT
read_byte( struct reader
*reader
, unsigned char *byte
)
994 if ((hr
= read_more_data( reader
, 1, NULL
, NULL
)) != S_OK
) return hr
;
995 *byte
= *read_current_ptr( reader
);
996 read_skip( reader
, 1 );
1000 static inline HRESULT
read_bytes( struct reader
*reader
, unsigned char *bytes
, unsigned int len
)
1003 if ((hr
= read_more_data( reader
, len
, NULL
, NULL
)) != S_OK
) return hr
;
1004 memcpy( bytes
, read_current_ptr( reader
), len
);
1005 read_skip( reader
, len
);
1009 /* UTF-8 support based on libs/wine/utf8.c */
1011 /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
1012 static const char utf8_length
[128] =
1014 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
1015 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
1016 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
1017 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
1018 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
1019 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
1020 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
1021 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
1024 /* first byte mask depending on UTF-8 sequence length */
1025 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
1027 /* minimum Unicode value depending on UTF-8 sequence length */
1028 static const unsigned int utf8_minval
[4] = { 0x0, 0x80, 0x800, 0x10000 };
1030 static inline HRESULT
read_utf8_char( struct reader
*reader
, unsigned int *ret
, unsigned int *skip
)
1034 const unsigned char *end
;
1037 if ((hr
= read_more_data( reader
, 1, NULL
, NULL
)) != S_OK
) return hr
;
1038 ch
= *read_current_ptr( reader
);
1046 len
= utf8_length
[ch
- 0x80];
1047 if ((hr
= read_more_data( reader
, len
, NULL
, NULL
)) != S_OK
) return hr
;
1048 end
= read_current_ptr( reader
) + len
+ 1;
1049 *ret
= ch
& utf8_mask
[len
];
1054 if ((ch
= end
[-3] ^ 0x80) >= 0x40) break;
1055 *ret
= (*ret
<< 6) | ch
;
1057 if ((ch
= end
[-2] ^ 0x80) >= 0x40) break;
1058 *ret
= (*ret
<< 6) | ch
;
1060 if ((ch
= end
[-1] ^ 0x80) >= 0x40) break;
1061 *ret
= (*ret
<< 6) | ch
;
1062 if (*ret
< utf8_minval
[len
]) break;
1067 return WS_E_INVALID_FORMAT
;
1070 static inline BOOL
read_isnamechar( unsigned int ch
)
1072 /* FIXME: incomplete */
1073 return (ch
>= 'A' && ch
<= 'Z') ||
1074 (ch
>= 'a' && ch
<= 'z') ||
1075 (ch
>= '0' && ch
<= '9') ||
1076 ch
== '_' || ch
== '-' || ch
== '.' || ch
== ':';
1079 static inline BOOL
read_isspace( unsigned int ch
)
1081 return ch
== ' ' || ch
== '\t' || ch
== '\r' || ch
== '\n';
1084 static inline void read_skip_whitespace( struct reader
*reader
)
1088 if (read_more_data( reader
, 1, NULL
, NULL
) != S_OK
|| !read_isspace( *read_current_ptr( reader
) )) break;
1089 read_skip( reader
, 1 );
1093 static inline HRESULT
read_cmp( struct reader
*reader
, const char *str
, int len
)
1095 const unsigned char *ptr
;
1098 if (len
< 0) len
= strlen( str
);
1099 if ((hr
= read_more_data( reader
, len
, NULL
, NULL
)) != S_OK
) return hr
;
1101 ptr
= read_current_ptr( reader
);
1104 if (*str
!= *ptr
) return WS_E_INVALID_FORMAT
;
1110 static HRESULT
read_xmldecl( struct reader
*reader
)
1114 if ((hr
= read_more_data( reader
, 1, NULL
, NULL
)) != S_OK
) return hr
;
1115 if (*read_current_ptr( reader
) != '<' || (hr
= read_cmp( reader
, "<?", 2 )) != S_OK
)
1117 reader
->state
= READER_STATE_BOF
;
1120 if ((hr
= read_cmp( reader
, "<?xml ", 6 )) != S_OK
) return hr
;
1121 read_skip( reader
, 6 );
1123 /* FIXME: parse attributes */
1126 if (read_more_data( reader
, 1, NULL
, NULL
) != S_OK
|| *read_current_ptr( reader
) == '?' ) break;
1127 read_skip( reader
, 1 );
1130 if ((hr
= read_cmp( reader
, "?>", 2 )) != S_OK
) return hr
;
1131 read_skip( reader
, 2 );
1133 reader
->state
= READER_STATE_BOF
;
1137 HRESULT
append_attribute( WS_XML_ELEMENT_NODE
*elem
, WS_XML_ATTRIBUTE
*attr
)
1139 if (elem
->attributeCount
)
1141 WS_XML_ATTRIBUTE
**tmp
;
1142 if (!(tmp
= realloc( elem
->attributes
, (elem
->attributeCount
+ 1) * sizeof(attr
) ))) return E_OUTOFMEMORY
;
1143 elem
->attributes
= tmp
;
1145 else if (!(elem
->attributes
= malloc( sizeof(attr
) ))) return E_OUTOFMEMORY
;
1146 elem
->attributes
[elem
->attributeCount
++] = attr
;
1150 static inline void init_xml_string( BYTE
*bytes
, ULONG len
, WS_XML_STRING
*str
)
1154 str
->dictionary
= NULL
;
1158 static HRESULT
split_qname( const BYTE
*str
, ULONG len
, WS_XML_STRING
*prefix
, WS_XML_STRING
*localname
)
1160 BYTE
*prefix_bytes
= NULL
, *localname_bytes
= (BYTE
*)str
, *ptr
= (BYTE
*)str
;
1161 ULONG prefix_len
= 0, localname_len
= len
;
1167 if (ptr
== str
) return WS_E_INVALID_FORMAT
;
1168 prefix_bytes
= (BYTE
*)str
;
1169 prefix_len
= ptr
- str
;
1170 localname_bytes
= ptr
+ 1;
1171 localname_len
= len
;
1176 if (!localname_len
) return WS_E_INVALID_FORMAT
;
1178 init_xml_string( prefix_bytes
, prefix_len
, prefix
);
1179 init_xml_string( localname_bytes
, localname_len
, localname
);
1183 static HRESULT
parse_qname( const BYTE
*str
, ULONG len
, WS_XML_STRING
**prefix_ret
, WS_XML_STRING
**localname_ret
)
1185 WS_XML_STRING prefix
, localname
;
1188 if ((hr
= split_qname( str
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
1189 if (!(*prefix_ret
= alloc_xml_string( NULL
, prefix
.length
))) return E_OUTOFMEMORY
;
1190 if (!(*localname_ret
= dup_xml_string( &localname
, FALSE
)))
1192 free_xml_string( *prefix_ret
);
1193 return E_OUTOFMEMORY
;
1195 memcpy( (*prefix_ret
)->bytes
, prefix
.bytes
, prefix
.length
);
1196 if (prefix
.length
&& add_xml_string( *prefix_ret
) != S_OK
) WARN( "prefix not added to dictionary\n" );
1200 static int codepoint_to_utf8( int cp
, unsigned char *dst
)
1210 dst
[1] = 0x80 | (cp
& 0x3f);
1215 if ((cp
>= 0xd800 && cp
<= 0xdfff) || cp
== 0xfffe || cp
== 0xffff) return -1;
1218 dst
[2] = 0x80 | (cp
& 0x3f);
1220 dst
[1] = 0x80 | (cp
& 0x3f);
1225 if (cp
>= 0x110000) return -1;
1226 dst
[3] = 0x80 | (cp
& 0x3f);
1228 dst
[2] = 0x80 | (cp
& 0x3f);
1230 dst
[1] = 0x80 | (cp
& 0x3f);
1236 static HRESULT
decode_text( const unsigned char *str
, ULONG len
, unsigned char *ret
, ULONG
*ret_len
)
1238 const unsigned char *p
= str
;
1239 unsigned char *q
= ret
;
1247 if (!len
) return WS_E_INVALID_FORMAT
;
1249 if (len
>= 3 && !memcmp( p
, "lt;", 3 ))
1255 else if (len
>= 3 && !memcmp( p
, "gt;", 3 ))
1261 else if (len
>= 5 && !memcmp( p
, "quot;", 5 ))
1267 else if (len
>= 4 && !memcmp( p
, "amp;", 4 ))
1273 else if (len
>= 5 && !memcmp( p
, "apos;", 5 ))
1281 ULONG start
, nb_digits
, i
;
1282 int len_utf8
, cp
= 0;
1285 if (!len
) return WS_E_INVALID_FORMAT
;
1291 while (len
&& isxdigit( *p
)) { p
++; len
--; };
1292 if (!len
) return WS_E_INVALID_FORMAT
;
1294 p
-= nb_digits
= start
- len
;
1295 if (!nb_digits
|| nb_digits
> 6 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1296 for (i
= 0; i
< nb_digits
; i
++)
1299 if (*p
>= '0' && *p
<= '9') cp
+= *p
- '0';
1300 else if (*p
>= 'a' && *p
<= 'f') cp
+= *p
- 'a' + 10;
1301 else cp
+= *p
- 'A' + 10;
1305 else if (isdigit( *p
))
1307 while (len
&& *p
== '0') { p
++; len
--; };
1308 if (!len
) return WS_E_INVALID_FORMAT
;
1311 while (len
&& isdigit( *p
)) { p
++; len
--; };
1312 if (!len
) return WS_E_INVALID_FORMAT
;
1314 p
-= nb_digits
= start
- len
;
1315 if (!nb_digits
|| nb_digits
> 7 || p
[nb_digits
] != ';') return WS_E_INVALID_FORMAT
;
1316 for (i
= 0; i
< nb_digits
; i
++)
1323 else return WS_E_INVALID_FORMAT
;
1325 if ((len_utf8
= codepoint_to_utf8( cp
, q
)) < 0) return WS_E_INVALID_FORMAT
;
1326 *ret_len
+= len_utf8
;
1330 else return WS_E_INVALID_FORMAT
;
1342 static HRESULT
read_attribute_value_text( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1344 WS_XML_UTF8_TEXT
*utf8
;
1345 unsigned int len
, ch
, skip
, quote
;
1346 const unsigned char *start
;
1349 read_skip_whitespace( reader
);
1350 if ((hr
= read_cmp( reader
, "=", 1 )) != S_OK
) return hr
;
1351 read_skip( reader
, 1 );
1353 read_skip_whitespace( reader
);
1354 if ((hr
= read_cmp( reader
, "\"", 1 )) != S_OK
&& (hr
= read_cmp( reader
, "'", 1 )) != S_OK
) return hr
;
1355 if ((hr
= read_utf8_char( reader
, "e
, &skip
)) != S_OK
) return hr
;
1356 read_skip( reader
, 1 );
1359 start
= read_current_ptr( reader
);
1362 if ((hr
= read_utf8_char( reader
, &ch
, &skip
)) != S_OK
) return hr
;
1363 if (ch
== quote
) break;
1364 read_skip( reader
, skip
);
1367 read_skip( reader
, 1 );
1371 if (!(attr
->ns
= alloc_xml_string( start
, len
))) return E_OUTOFMEMORY
;
1372 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) return hr
;
1373 if (!(utf8
= alloc_utf8_text( NULL
, 0 ))) return E_OUTOFMEMORY
;
1377 if (!(utf8
= alloc_utf8_text( NULL
, len
))) return E_OUTOFMEMORY
;
1378 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
1385 attr
->value
= &utf8
->text
;
1386 attr
->singleQuote
= (quote
== '\'');
1390 static inline BOOL
is_text_type( unsigned char type
)
1392 return (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
);
1395 static HRESULT
read_int31( struct reader
*reader
, ULONG
*len
)
1400 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1402 if (!(byte
& 0x80)) return S_OK
;
1404 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1405 *len
+= (byte
& 0x7f) << 7;
1406 if (!(byte
& 0x80)) return S_OK
;
1408 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1409 *len
+= (byte
& 0x7f) << 14;
1410 if (!(byte
& 0x80)) return S_OK
;
1412 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1413 *len
+= (byte
& 0x7f) << 21;
1414 if (!(byte
& 0x80)) return S_OK
;
1416 if ((hr
= read_byte( reader
, &byte
)) != S_OK
) return hr
;
1417 *len
+= (byte
& 0x07) << 28;
1421 static HRESULT
read_string( struct reader
*reader
, WS_XML_STRING
**str
)
1425 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
1426 if (!(*str
= alloc_xml_string( NULL
, len
))) return E_OUTOFMEMORY
;
1427 if ((hr
= read_bytes( reader
, (*str
)->bytes
, len
)) == S_OK
)
1429 if (add_xml_string( *str
) != S_OK
) WARN( "string not added to dictionary\n" );
1432 free_xml_string( *str
);
1436 static HRESULT
read_dict_string( struct reader
*reader
, WS_XML_STRING
**str
)
1438 const WS_XML_DICTIONARY
*dict
;
1442 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1443 dict
= (id
& 1) ? reader
->dict
: reader
->dict_static
;
1444 if (!dict
|| (id
>>= 1) >= dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1445 if (!(*str
= alloc_xml_string( NULL
, 0 ))) return E_OUTOFMEMORY
;
1446 *(*str
) = dict
->strings
[id
];
1450 static HRESULT
read_datetime( struct reader
*reader
, WS_DATETIME
*ret
)
1455 if ((hr
= read_bytes( reader
, (unsigned char *)&val
, sizeof(val
) )) != S_OK
) return hr
;
1457 if ((val
& 0x03) == 1) ret
->format
= WS_DATETIME_FORMAT_UTC
;
1458 else if ((val
& 0x03) == 2) ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
1459 else ret
->format
= WS_DATETIME_FORMAT_NONE
;
1461 if ((ret
->ticks
= val
>> 2) > TICKS_MAX
) return WS_E_INVALID_FORMAT
;
1465 static HRESULT
lookup_string( struct reader
*reader
, ULONG id
, const WS_XML_STRING
**ret
)
1467 const WS_XML_DICTIONARY
*dict
= (id
& 1) ? reader
->dict
: reader
->dict_static
;
1468 if (!dict
|| (id
>>= 1) >= dict
->stringCount
) return WS_E_INVALID_FORMAT
;
1469 *ret
= &dict
->strings
[id
];
1473 static HRESULT
read_attribute_value_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
*attr
)
1475 WS_XML_UTF8_TEXT
*text_utf8
= NULL
;
1476 WS_XML_BASE64_TEXT
*text_base64
= NULL
;
1477 WS_XML_INT32_TEXT
*text_int32
;
1478 WS_XML_INT64_TEXT
*text_int64
;
1479 WS_XML_BOOL_TEXT
*text_bool
;
1480 const WS_XML_STRING
*str
;
1489 if ((hr
= read_peek( reader
, &type
, 1 )) != S_OK
) return hr
;
1490 if (!is_text_type( type
)) return WS_E_INVALID_FORMAT
;
1491 read_skip( reader
, 1 );
1495 case RECORD_ZERO_TEXT
:
1497 if (!(text_int32
= alloc_int32_text( 0 ))) return E_OUTOFMEMORY
;
1498 attr
->value
= &text_int32
->text
;
1501 case RECORD_ONE_TEXT
:
1503 if (!(text_int32
= alloc_int32_text( 1 ))) return E_OUTOFMEMORY
;
1504 attr
->value
= &text_int32
->text
;
1507 case RECORD_FALSE_TEXT
:
1509 if (!(text_bool
= alloc_bool_text( FALSE
))) return E_OUTOFMEMORY
;
1510 attr
->value
= &text_bool
->text
;
1513 case RECORD_TRUE_TEXT
:
1515 if (!(text_bool
= alloc_bool_text( TRUE
))) return E_OUTOFMEMORY
;
1516 attr
->value
= &text_bool
->text
;
1519 case RECORD_INT8_TEXT
:
1522 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
1523 if (!(text_int64
= alloc_int64_text( val_int8
))) return E_OUTOFMEMORY
;
1524 attr
->value
= &text_int64
->text
;
1527 case RECORD_INT16_TEXT
:
1530 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
1531 if (!(text_int64
= alloc_int64_text( val_int16
))) return E_OUTOFMEMORY
;
1532 attr
->value
= &text_int64
->text
;
1535 case RECORD_INT32_TEXT
:
1536 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1537 if (!(text_int64
= alloc_int64_text( val_int32
))) return E_OUTOFMEMORY
;
1538 attr
->value
= &text_int64
->text
;
1541 case RECORD_INT64_TEXT
:
1544 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
1545 if (!(text_int64
= alloc_int64_text( val_int64
))) return E_OUTOFMEMORY
;
1546 attr
->value
= &text_int64
->text
;
1549 case RECORD_FLOAT_TEXT
:
1551 WS_XML_FLOAT_TEXT
*text_float
;
1554 if ((hr
= read_bytes( reader
, (unsigned char *)&val_float
, sizeof(val_float
) )) != S_OK
) return hr
;
1555 if (!(text_float
= alloc_float_text( val_float
))) return E_OUTOFMEMORY
;
1556 attr
->value
= &text_float
->text
;
1559 case RECORD_DOUBLE_TEXT
:
1561 WS_XML_DOUBLE_TEXT
*text_double
;
1564 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
1565 if (!(text_double
= alloc_double_text( val_double
))) return E_OUTOFMEMORY
;
1566 attr
->value
= &text_double
->text
;
1569 case RECORD_DATETIME_TEXT
:
1571 WS_XML_DATETIME_TEXT
*text_datetime
;
1572 WS_DATETIME datetime
;
1574 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
1575 if (!(text_datetime
= alloc_datetime_text( &datetime
))) return E_OUTOFMEMORY
;
1576 attr
->value
= &text_datetime
->text
;
1579 case RECORD_CHARS8_TEXT
:
1580 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1584 case RECORD_CHARS16_TEXT
:
1585 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
1589 case RECORD_CHARS32_TEXT
:
1590 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1591 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1595 case RECORD_BYTES8_TEXT
:
1596 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
1597 if (!(text_base64
= alloc_base64_text( NULL
, val_uint8
))) return E_OUTOFMEMORY
;
1598 if ((hr
= read_bytes( reader
, text_base64
->bytes
, val_uint8
)) != S_OK
)
1600 free( text_base64
);
1605 case RECORD_BYTES16_TEXT
:
1606 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
1607 if (!(text_base64
= alloc_base64_text( NULL
, val_uint16
))) return E_OUTOFMEMORY
;
1608 if ((hr
= read_bytes( reader
, text_base64
->bytes
, val_uint16
)) != S_OK
)
1610 free( text_base64
);
1615 case RECORD_BYTES32_TEXT
:
1616 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
1617 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
1618 if (!(text_base64
= alloc_base64_text( NULL
, val_int32
))) return E_OUTOFMEMORY
;
1619 if ((hr
= read_bytes( reader
, text_base64
->bytes
, val_int32
)) != S_OK
)
1621 free( text_base64
);
1626 case RECORD_EMPTY_TEXT
:
1629 case RECORD_DICTIONARY_TEXT
:
1630 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
1631 if ((hr
= lookup_string( reader
, id
, &str
)) != S_OK
) return hr
;
1632 if (!(text_utf8
= alloc_utf8_text( str
->bytes
, str
->length
))) return E_OUTOFMEMORY
;
1635 case RECORD_UNIQUE_ID_TEXT
:
1637 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
;
1638 if ((hr
= read_bytes( reader
, (unsigned char *)&guid
, sizeof(guid
) )) != S_OK
) return hr
;
1639 if (!(text_unique_id
= alloc_unique_id_text( &guid
))) return E_OUTOFMEMORY
;
1640 attr
->value
= &text_unique_id
->text
;
1643 case RECORD_GUID_TEXT
:
1645 WS_XML_GUID_TEXT
*guid_text
;
1646 if ((hr
= read_bytes( reader
, (unsigned char *)&guid
, sizeof(guid
) )) != S_OK
) return hr
;
1647 if (!(guid_text
= alloc_guid_text( &guid
))) return E_OUTOFMEMORY
;
1648 attr
->value
= &guid_text
->text
;
1651 case RECORD_UINT64_TEXT
:
1653 WS_XML_UINT64_TEXT
*text_uint64
;
1656 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
1657 if (!(text_uint64
= alloc_uint64_text( val_uint64
))) return E_OUTOFMEMORY
;
1658 attr
->value
= &text_uint64
->text
;
1661 case RECORD_BOOL_TEXT
:
1663 WS_XML_BOOL_TEXT
*text_bool
;
1666 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
1667 if (!(text_bool
= alloc_bool_text( !!val_bool
))) return E_OUTOFMEMORY
;
1668 attr
->value
= &text_bool
->text
;
1672 ERR( "unhandled record type %02x\n", type
);
1673 return WS_E_NOT_SUPPORTED
;
1676 if (type
>= RECORD_BYTES8_TEXT
&& type
<= RECORD_BYTES32_TEXT
)
1678 attr
->value
= &text_base64
->text
;
1684 if (!(text_utf8
= alloc_utf8_text( NULL
, len
))) return E_OUTOFMEMORY
;
1685 if (!len
) text_utf8
->value
.bytes
= (BYTE
*)(text_utf8
+ 1); /* quirk */
1686 if ((hr
= read_bytes( reader
, text_utf8
->value
.bytes
, len
)) != S_OK
)
1693 attr
->value
= &text_utf8
->text
;
1697 static HRESULT
read_attribute_text( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1699 static const WS_XML_STRING xmlns
= {5, (BYTE
*)"xmlns"};
1700 WS_XML_ATTRIBUTE
*attr
;
1701 unsigned int len
= 0, ch
, skip
;
1702 const unsigned char *start
;
1703 WS_XML_STRING
*prefix
, *localname
;
1706 if (!(attr
= calloc( 1, sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1708 start
= read_current_ptr( reader
);
1711 if ((hr
= read_utf8_char( reader
, &ch
, &skip
)) != S_OK
) goto error
;
1712 if (!read_isnamechar( ch
)) break;
1713 read_skip( reader
, skip
);
1718 hr
= WS_E_INVALID_FORMAT
;
1722 if ((hr
= parse_qname( start
, len
, &prefix
, &localname
)) != S_OK
) goto error
;
1723 if (WsXmlStringEquals( prefix
, &xmlns
, NULL
) == S_OK
)
1725 free_xml_string( prefix
);
1727 if (!(attr
->prefix
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1729 free_xml_string( localname
);
1733 attr
->localName
= localname
;
1735 else if (!prefix
->length
&& WsXmlStringEquals( localname
, &xmlns
, NULL
) == S_OK
)
1738 attr
->prefix
= prefix
;
1739 attr
->localName
= localname
;
1743 attr
->prefix
= prefix
;
1744 attr
->localName
= localname
;
1747 if ((hr
= read_attribute_value_text( reader
, attr
)) != S_OK
) goto error
;
1753 free_attribute( attr
);
1757 static inline BOOL
is_attribute_type( unsigned char type
)
1759 return (type
>= RECORD_SHORT_ATTRIBUTE
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
);
1762 static WS_XML_STRING
*get_xmlns_localname( struct reader
*reader
, const WS_XML_STRING
*prefix
)
1764 if (!get_namespace( reader
, prefix
)) return alloc_xml_string( NULL
, 0 );
1765 return alloc_xml_string( prefix
->bytes
, prefix
->length
);
1768 static HRESULT
read_attribute_bin( struct reader
*reader
, WS_XML_ATTRIBUTE
**ret
)
1770 WS_XML_UTF8_TEXT
*utf8
;
1771 WS_XML_ATTRIBUTE
*attr
;
1772 unsigned char type
= 0;
1775 if ((hr
= read_peek( reader
, &type
, 1 )) != S_OK
) return hr
;
1776 if (!is_attribute_type( type
)) return WS_E_INVALID_FORMAT
;
1777 if (!(attr
= calloc( 1, sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1778 read_skip( reader
, 1 );
1780 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1782 unsigned char ch
= type
- RECORD_PREFIX_ATTRIBUTE_A
+ 'a';
1783 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1788 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1789 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1791 else if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1793 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ 'a';
1794 if (!(attr
->prefix
= alloc_xml_string( &ch
, 1 )))
1799 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1800 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1806 case RECORD_SHORT_ATTRIBUTE
:
1807 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1812 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1813 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1816 case RECORD_ATTRIBUTE
:
1817 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1818 if ((hr
= read_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1819 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1822 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1823 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1828 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1829 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1832 case RECORD_DICTIONARY_ATTRIBUTE
:
1833 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1834 if ((hr
= read_dict_string( reader
, &attr
->localName
)) != S_OK
) goto error
;
1835 if ((hr
= read_attribute_value_bin( reader
, attr
)) != S_OK
) goto error
;
1838 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1839 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1844 if (!(attr
->localName
= get_xmlns_localname( reader
, attr
->prefix
)))
1849 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1850 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1854 case RECORD_XMLNS_ATTRIBUTE
:
1855 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1856 if (!(attr
->localName
= get_xmlns_localname( reader
, attr
->prefix
)))
1861 if ((hr
= read_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1862 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1866 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1867 if (!(attr
->prefix
= alloc_xml_string( NULL
, 0 )))
1872 if (!(attr
->localName
= get_xmlns_localname( reader
, attr
->prefix
)))
1877 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1878 if (!(utf8
= alloc_utf8_text( NULL
, 0 )))
1883 attr
->value
= &utf8
->text
;
1884 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1888 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1889 if ((hr
= read_string( reader
, &attr
->prefix
)) != S_OK
) goto error
;
1890 if (!(attr
->localName
= get_xmlns_localname( reader
, attr
->prefix
)))
1895 if ((hr
= read_dict_string( reader
, &attr
->ns
)) != S_OK
) goto error
;
1896 if (!(utf8
= alloc_utf8_text( NULL
, 0 )))
1901 attr
->value
= &utf8
->text
;
1902 if ((hr
= bind_prefix( reader
, attr
->prefix
, attr
->ns
)) != S_OK
) goto error
;
1907 ERR( "unhandled record type %02x\n", type
);
1908 return WS_E_NOT_SUPPORTED
;
1916 free_attribute( attr
);
1920 static inline struct node
*find_parent( struct reader
*reader
)
1922 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
)
1924 if (is_valid_parent( reader
->current
->parent
->parent
)) return reader
->current
->parent
->parent
;
1927 if (is_valid_parent( reader
->current
)) return reader
->current
;
1928 if (is_valid_parent( reader
->current
->parent
)) return reader
->current
->parent
;
1932 static HRESULT
set_namespaces( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1934 static const WS_XML_STRING xml
= {3, (BYTE
*)"xml"};
1935 const WS_XML_STRING
*ns
;
1938 if (!(ns
= get_namespace( reader
, elem
->prefix
))) return WS_E_INVALID_FORMAT
;
1939 if (!(elem
->ns
= dup_xml_string( ns
, FALSE
))) return E_OUTOFMEMORY
;
1941 for (i
= 0; i
< elem
->attributeCount
; i
++)
1943 WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1944 if (attr
->isXmlNs
|| WsXmlStringEquals( attr
->prefix
, &xml
, NULL
) == S_OK
) continue;
1945 if (!(ns
= get_namespace( reader
, attr
->prefix
))) return WS_E_INVALID_FORMAT
;
1946 if (!(attr
->ns
= alloc_xml_string( NULL
, ns
->length
))) return E_OUTOFMEMORY
;
1947 if (attr
->ns
->length
) memcpy( attr
->ns
->bytes
, ns
->bytes
, ns
->length
);
1952 static WS_XML_ELEMENT_NODE
*alloc_element_pair(void)
1954 struct node
*node
, *end
;
1955 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return NULL
;
1956 if (!(end
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
)))
1961 list_add_tail( &node
->children
, &end
->entry
);
1966 static HRESULT
read_attributes_text( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
1968 WS_XML_ATTRIBUTE
*attr
;
1971 reader
->current_attr
= 0;
1974 read_skip_whitespace( reader
);
1975 if (read_cmp( reader
, ">", 1 ) == S_OK
|| read_cmp( reader
, "/>", 2 ) == S_OK
) break;
1976 if ((hr
= read_attribute_text( reader
, &attr
)) != S_OK
) return hr
;
1977 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1979 free_attribute( attr
);
1982 reader
->current_attr
++;
1987 static HRESULT
read_element_text( struct reader
*reader
)
1989 unsigned int len
= 0, ch
, skip
;
1990 const unsigned char *start
;
1991 unsigned char buf
[2];
1992 struct node
*node
= NULL
, *parent
;
1993 WS_XML_ELEMENT_NODE
*elem
;
1996 if (read_end_of_data( reader
))
1998 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
1999 reader
->last
= reader
->current
;
2000 reader
->state
= READER_STATE_EOF
;
2004 if ((hr
= read_peek( reader
, buf
, 2 )) != S_OK
) return hr
;
2005 if (buf
[0] != '<' || !read_isnamechar( buf
[1] )) return WS_E_INVALID_FORMAT
;
2006 read_skip( reader
, 1 );
2008 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
2009 node
= (struct node
*)elem
;
2011 start
= read_current_ptr( reader
);
2014 if ((hr
= read_utf8_char( reader
, &ch
, &skip
)) != S_OK
) goto error
;
2015 if (!read_isnamechar( ch
)) break;
2016 read_skip( reader
, skip
);
2021 hr
= WS_E_INVALID_FORMAT
;
2025 if (!(parent
= find_parent( reader
))) goto error
;
2026 if ((hr
= parse_qname( start
, len
, &elem
->prefix
, &elem
->localName
)) != S_OK
) goto error
;
2027 if ((hr
= read_attributes_text( reader
, elem
)) != S_OK
) goto error
;
2028 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
2030 read_insert_node( reader
, parent
, node
);
2031 reader
->state
= READER_STATE_STARTELEMENT
;
2035 destroy_nodes( node
);
2039 static inline BOOL
is_element_type( unsigned char type
)
2041 return (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
);
2044 static HRESULT
read_attributes_bin( struct reader
*reader
, WS_XML_ELEMENT_NODE
*elem
)
2046 WS_XML_ATTRIBUTE
*attr
;
2050 reader
->current_attr
= 0;
2053 if ((hr
= read_peek( reader
, &type
, 1 )) != S_OK
) return hr
;
2054 if (!is_attribute_type( type
)) break;
2055 if ((hr
= read_attribute_bin( reader
, &attr
)) != S_OK
) return hr
;
2056 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
2058 free_attribute( attr
);
2061 reader
->current_attr
++;
2066 static HRESULT
read_element_bin( struct reader
*reader
)
2068 struct node
*node
= NULL
, *parent
;
2069 WS_XML_ELEMENT_NODE
*elem
;
2073 if ((hr
= read_peek( reader
, &type
, 1 )) != S_OK
) return hr
;
2074 if (!is_element_type( type
)) return WS_E_INVALID_FORMAT
;
2075 read_skip( reader
, 1 );
2077 if (!(elem
= alloc_element_pair())) return E_OUTOFMEMORY
;
2078 node
= (struct node
*)elem
;
2080 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
2082 unsigned char ch
= type
- RECORD_PREFIX_ELEMENT_A
+ 'a';
2083 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
2088 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
2090 else if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
2092 unsigned char ch
= type
- RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ 'a';
2093 if (!(elem
->prefix
= alloc_xml_string( &ch
, 1 )))
2098 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
2104 case RECORD_SHORT_ELEMENT
:
2105 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
2110 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
2113 case RECORD_ELEMENT
:
2114 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
2115 if ((hr
= read_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
2118 case RECORD_SHORT_DICTIONARY_ELEMENT
:
2119 if (!(elem
->prefix
= alloc_xml_string( NULL
, 0 )))
2124 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
2127 case RECORD_DICTIONARY_ELEMENT
:
2128 if ((hr
= read_string( reader
, &elem
->prefix
)) != S_OK
) goto error
;
2129 if ((hr
= read_dict_string( reader
, &elem
->localName
)) != S_OK
) goto error
;
2133 ERR( "unhandled record type %02x\n", type
);
2134 return WS_E_NOT_SUPPORTED
;
2138 if (!(parent
= find_parent( reader
)))
2140 hr
= WS_E_INVALID_FORMAT
;
2144 if ((hr
= read_attributes_bin( reader
, elem
)) != S_OK
) goto error
;
2145 if ((hr
= set_namespaces( reader
, elem
)) != S_OK
) goto error
;
2147 read_insert_node( reader
, parent
, node
);
2148 reader
->state
= READER_STATE_STARTELEMENT
;
2152 destroy_nodes( node
);
2156 static HRESULT
read_text_text( struct reader
*reader
)
2158 unsigned int len
= 0, ch
, skip
;
2159 const unsigned char *start
;
2160 struct node
*node
, *parent
;
2161 WS_XML_TEXT_NODE
*text
;
2162 WS_XML_UTF8_TEXT
*utf8
;
2165 start
= read_current_ptr( reader
);
2168 if (read_end_of_data( reader
)) break;
2169 if ((hr
= read_utf8_char( reader
, &ch
, &skip
)) != S_OK
) return hr
;
2170 if (ch
== '<') break;
2171 read_skip( reader
, skip
);
2175 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2177 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2178 text
= (WS_XML_TEXT_NODE
*)node
;
2179 if (!(utf8
= alloc_utf8_text( NULL
, len
)))
2182 return E_OUTOFMEMORY
;
2184 if ((hr
= decode_text( start
, len
, utf8
->value
.bytes
, &utf8
->value
.length
)) != S_OK
)
2190 text
->text
= &utf8
->text
;
2192 read_insert_node( reader
, parent
, node
);
2193 reader
->state
= READER_STATE_TEXT
;
2194 reader
->text_conv_offset
= 0;
2198 static struct node
*alloc_utf8_text_node( const BYTE
*data
, ULONG len
, WS_XML_UTF8_TEXT
**ret
)
2201 WS_XML_UTF8_TEXT
*utf8
;
2202 WS_XML_TEXT_NODE
*text
;
2204 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2205 if (!(utf8
= alloc_utf8_text( data
, len
)))
2210 text
= (WS_XML_TEXT_NODE
*)node
;
2211 text
->text
= &utf8
->text
;
2212 if (ret
) *ret
= utf8
;
2216 static struct node
*alloc_base64_text_node( const BYTE
*data
, ULONG len
, WS_XML_BASE64_TEXT
**ret
)
2219 WS_XML_BASE64_TEXT
*base64
;
2220 WS_XML_TEXT_NODE
*text
;
2222 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2223 if (!(base64
= alloc_base64_text( data
, len
)))
2228 text
= (WS_XML_TEXT_NODE
*)node
;
2229 text
->text
= &base64
->text
;
2230 if (ret
) *ret
= base64
;
2234 static struct node
*alloc_bool_text_node( BOOL value
)
2237 WS_XML_BOOL_TEXT
*text_bool
;
2238 WS_XML_TEXT_NODE
*text
;
2240 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2241 if (!(text_bool
= alloc_bool_text( value
)))
2246 text
= (WS_XML_TEXT_NODE
*)node
;
2247 text
->text
= &text_bool
->text
;
2251 static struct node
*alloc_int32_text_node( INT32 value
)
2254 WS_XML_INT32_TEXT
*text_int32
;
2255 WS_XML_TEXT_NODE
*text
;
2257 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2258 if (!(text_int32
= alloc_int32_text( value
)))
2263 text
= (WS_XML_TEXT_NODE
*)node
;
2264 text
->text
= &text_int32
->text
;
2268 static struct node
*alloc_int64_text_node( INT64 value
)
2271 WS_XML_INT64_TEXT
*text_int64
;
2272 WS_XML_TEXT_NODE
*text
;
2274 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2275 if (!(text_int64
= alloc_int64_text( value
)))
2280 text
= (WS_XML_TEXT_NODE
*)node
;
2281 text
->text
= &text_int64
->text
;
2285 static struct node
*alloc_float_text_node( float value
)
2288 WS_XML_FLOAT_TEXT
*text_float
;
2289 WS_XML_TEXT_NODE
*text
;
2291 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2292 if (!(text_float
= alloc_float_text( value
)))
2297 text
= (WS_XML_TEXT_NODE
*)node
;
2298 text
->text
= &text_float
->text
;
2302 static struct node
*alloc_double_text_node( double value
)
2305 WS_XML_DOUBLE_TEXT
*text_double
;
2306 WS_XML_TEXT_NODE
*text
;
2308 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2309 if (!(text_double
= alloc_double_text( value
)))
2314 text
= (WS_XML_TEXT_NODE
*)node
;
2315 text
->text
= &text_double
->text
;
2319 static struct node
*alloc_datetime_text_node( const WS_DATETIME
*value
)
2322 WS_XML_DATETIME_TEXT
*text_datetime
;
2323 WS_XML_TEXT_NODE
*text
;
2325 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2326 if (!(text_datetime
= alloc_datetime_text( value
)))
2331 text
= (WS_XML_TEXT_NODE
*)node
;
2332 text
->text
= &text_datetime
->text
;
2336 static struct node
*alloc_unique_id_text_node( const GUID
*value
)
2339 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
;
2340 WS_XML_TEXT_NODE
*text
;
2342 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2343 if (!(text_unique_id
= alloc_unique_id_text( value
)))
2348 text
= (WS_XML_TEXT_NODE
*)node
;
2349 text
->text
= &text_unique_id
->text
;
2353 static struct node
*alloc_guid_text_node( const GUID
*value
)
2356 WS_XML_GUID_TEXT
*text_guid
;
2357 WS_XML_TEXT_NODE
*text
;
2359 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2360 if (!(text_guid
= alloc_guid_text( value
)))
2365 text
= (WS_XML_TEXT_NODE
*)node
;
2366 text
->text
= &text_guid
->text
;
2370 static struct node
*alloc_uint64_text_node( UINT64 value
)
2373 WS_XML_UINT64_TEXT
*text_uint64
;
2374 WS_XML_TEXT_NODE
*text
;
2376 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return NULL
;
2377 if (!(text_uint64
= alloc_uint64_text( value
)))
2382 text
= (WS_XML_TEXT_NODE
*)node
;
2383 text
->text
= &text_uint64
->text
;
2387 static HRESULT
append_text_bytes( struct reader
*reader
, WS_XML_TEXT_NODE
*node
, ULONG len
)
2389 WS_XML_BASE64_TEXT
*new, *old
= (WS_XML_BASE64_TEXT
*)node
->text
;
2392 if (!(new = alloc_base64_text( NULL
, old
->length
+ len
))) return E_OUTOFMEMORY
;
2393 memcpy( new->bytes
, old
->bytes
, old
->length
);
2394 if ((hr
= read_bytes( reader
, new->bytes
+ old
->length
, len
)) != S_OK
) return hr
;
2396 node
->text
= &new->text
;
2400 static HRESULT
read_text_bytes( struct reader
*reader
, unsigned char type
)
2402 struct node
*node
= NULL
, *parent
;
2403 WS_XML_BASE64_TEXT
*base64
;
2407 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2412 case RECORD_BYTES8_TEXT
:
2413 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT
:
2416 if ((hr
= read_byte( reader
, (unsigned char *)&len_uint8
)) != S_OK
) goto error
;
2420 case RECORD_BYTES16_TEXT
:
2421 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT
:
2424 if ((hr
= read_bytes( reader
, (unsigned char *)&len_uint16
, sizeof(len_uint16
) )) != S_OK
) goto error
;
2428 case RECORD_BYTES32_TEXT
:
2429 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT
:
2432 if ((hr
= read_bytes( reader
, (unsigned char *)&len_int32
, sizeof(len_int32
) )) != S_OK
) goto error
;
2435 hr
= WS_E_INVALID_FORMAT
;
2442 ERR( "unexpected type %u\n", type
);
2449 if (!(node
= alloc_base64_text_node( NULL
, len
, &base64
))) return E_OUTOFMEMORY
;
2450 if ((hr
= read_bytes( reader
, base64
->bytes
, len
)) != S_OK
) goto error
;
2452 else if ((hr
= append_text_bytes( reader
, (WS_XML_TEXT_NODE
*)node
, len
)) != S_OK
) goto error
;
2456 node
->flags
|= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
;
2459 if ((hr
= read_peek( reader
, &type
, 1 )) != S_OK
) goto error
;
2460 if (type
< RECORD_BYTES8_TEXT
|| type
> RECORD_BYTES32_TEXT_WITH_ENDELEMENT
) break;
2461 read_skip( reader
, 1 );
2464 read_insert_node( reader
, parent
, node
);
2465 reader
->state
= READER_STATE_TEXT
;
2466 reader
->text_conv_offset
= 0;
2474 static HRESULT
read_text_bin( struct reader
*reader
)
2476 struct node
*node
= NULL
, *parent
;
2478 WS_XML_UTF8_TEXT
*utf8
;
2486 if ((hr
= read_peek( reader
, &type
, 1 )) != S_OK
) return hr
;
2487 if (!is_text_type( type
) || !(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2488 read_skip( reader
, 1 );
2492 case RECORD_ZERO_TEXT
:
2493 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2494 if (!(node
= alloc_int32_text_node( 0 ))) return E_OUTOFMEMORY
;
2497 case RECORD_ONE_TEXT
:
2498 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2499 if (!(node
= alloc_int32_text_node( 1 ))) return E_OUTOFMEMORY
;
2502 case RECORD_FALSE_TEXT
:
2503 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2504 if (!(node
= alloc_bool_text_node( FALSE
))) return E_OUTOFMEMORY
;
2507 case RECORD_TRUE_TEXT
:
2508 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2509 if (!(node
= alloc_bool_text_node( TRUE
))) return E_OUTOFMEMORY
;
2512 case RECORD_INT8_TEXT
:
2513 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2516 if ((hr
= read_byte( reader
, (unsigned char *)&val_int8
)) != S_OK
) return hr
;
2517 if (!(node
= alloc_int32_text_node( val_int8
))) return E_OUTOFMEMORY
;
2520 case RECORD_INT16_TEXT
:
2521 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2524 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int16
, sizeof(val_int16
) )) != S_OK
) return hr
;
2525 if (!(node
= alloc_int32_text_node( val_int16
))) return E_OUTOFMEMORY
;
2528 case RECORD_INT32_TEXT
:
2529 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2530 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2531 if (!(node
= alloc_int32_text_node( val_int32
))) return E_OUTOFMEMORY
;
2534 case RECORD_INT64_TEXT
:
2535 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2538 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int64
, sizeof(val_int64
) )) != S_OK
) return hr
;
2539 if (!(node
= alloc_int64_text_node( val_int64
))) return E_OUTOFMEMORY
;
2542 case RECORD_FLOAT_TEXT
:
2543 case RECORD_FLOAT_TEXT_WITH_ENDELEMENT
:
2546 if ((hr
= read_bytes( reader
, (unsigned char *)&val_float
, sizeof(val_float
) )) != S_OK
) return hr
;
2547 if (!(node
= alloc_float_text_node( val_float
))) return E_OUTOFMEMORY
;
2550 case RECORD_DOUBLE_TEXT
:
2551 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2554 if ((hr
= read_bytes( reader
, (unsigned char *)&val_double
, sizeof(val_double
) )) != S_OK
) return hr
;
2555 if (!(node
= alloc_double_text_node( val_double
))) return E_OUTOFMEMORY
;
2558 case RECORD_DATETIME_TEXT
:
2559 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2561 WS_DATETIME datetime
;
2562 if ((hr
= read_datetime( reader
, &datetime
)) != S_OK
) return hr
;
2563 if (!(node
= alloc_datetime_text_node( &datetime
))) return E_OUTOFMEMORY
;
2566 case RECORD_CHARS8_TEXT
:
2567 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2568 if ((hr
= read_byte( reader
, (unsigned char *)&val_uint8
)) != S_OK
) return hr
;
2572 case RECORD_CHARS16_TEXT
:
2573 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2574 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint16
, sizeof(val_uint16
) )) != S_OK
) return hr
;
2578 case RECORD_CHARS32_TEXT
:
2579 case RECORD_CHARS32_TEXT_WITH_ENDELEMENT
:
2580 if ((hr
= read_bytes( reader
, (unsigned char *)&val_int32
, sizeof(val_int32
) )) != S_OK
) return hr
;
2581 if (val_int32
< 0) return WS_E_INVALID_FORMAT
;
2585 case RECORD_BYTES8_TEXT
:
2586 case RECORD_BYTES8_TEXT_WITH_ENDELEMENT
:
2587 case RECORD_BYTES16_TEXT
:
2588 case RECORD_BYTES16_TEXT_WITH_ENDELEMENT
:
2589 case RECORD_BYTES32_TEXT
:
2590 case RECORD_BYTES32_TEXT_WITH_ENDELEMENT
:
2591 return read_text_bytes( reader
, type
);
2593 case RECORD_EMPTY_TEXT
:
2594 case RECORD_EMPTY_TEXT_WITH_ENDELEMENT
:
2598 case RECORD_DICTIONARY_TEXT
:
2599 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2601 const WS_XML_STRING
*str
;
2602 if ((hr
= read_int31( reader
, &id
)) != S_OK
) return hr
;
2603 if ((hr
= lookup_string( reader
, id
, &str
)) != S_OK
) return hr
;
2604 if (!(node
= alloc_utf8_text_node( str
->bytes
, str
->length
, NULL
))) return E_OUTOFMEMORY
;
2607 case RECORD_UNIQUE_ID_TEXT
:
2608 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
:
2609 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2610 if (!(node
= alloc_unique_id_text_node( &uuid
))) return E_OUTOFMEMORY
;
2613 case RECORD_GUID_TEXT
:
2614 case RECORD_GUID_TEXT_WITH_ENDELEMENT
:
2615 if ((hr
= read_bytes( reader
, (unsigned char *)&uuid
, sizeof(uuid
) )) != S_OK
) return hr
;
2616 if (!(node
= alloc_guid_text_node( &uuid
))) return E_OUTOFMEMORY
;
2619 case RECORD_UINT64_TEXT
:
2620 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2623 if ((hr
= read_bytes( reader
, (unsigned char *)&val_uint64
, sizeof(val_uint64
) )) != S_OK
) return hr
;
2624 if (!(node
= alloc_uint64_text_node( val_uint64
))) return E_OUTOFMEMORY
;
2627 case RECORD_BOOL_TEXT
:
2628 case RECORD_BOOL_TEXT_WITH_ENDELEMENT
:
2631 if ((hr
= read_bytes( reader
, (unsigned char *)&val_bool
, sizeof(val_bool
) )) != S_OK
) return hr
;
2632 if (!(node
= alloc_bool_text_node( !!val_bool
))) return E_OUTOFMEMORY
;
2636 ERR( "unhandled record type %02x\n", type
);
2637 return WS_E_NOT_SUPPORTED
;
2642 if (!(node
= alloc_utf8_text_node( NULL
, len
, &utf8
))) return E_OUTOFMEMORY
;
2643 if (!len
) utf8
->value
.bytes
= (BYTE
*)(utf8
+ 1); /* quirk */
2644 if ((hr
= read_bytes( reader
, utf8
->value
.bytes
, len
)) != S_OK
)
2651 if (type
& 1) node
->flags
|= NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
;
2652 read_insert_node( reader
, parent
, node
);
2653 reader
->state
= READER_STATE_TEXT
;
2654 reader
->text_conv_offset
= 0;
2658 static HRESULT
read_node_text( struct reader
* );
2660 static HRESULT
read_startelement_text( struct reader
*reader
)
2664 if (read_cmp( reader
, "<?", 2 ) == S_OK
)
2666 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
2668 read_skip_whitespace( reader
);
2669 if (read_cmp( reader
, "<", 1 ) == S_OK
)
2671 if ((hr
= read_element_text( reader
)) != S_OK
) return hr
;
2673 if (read_cmp( reader
, "/>", 2 ) == S_OK
)
2675 read_skip( reader
, 2 );
2676 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->children
), struct node
, entry
);
2677 reader
->last
= reader
->current
;
2678 reader
->state
= READER_STATE_ENDELEMENT
;
2681 else if (read_cmp( reader
, ">", 1 ) == S_OK
)
2683 read_skip( reader
, 1 );
2684 return read_node_text( reader
);
2686 return WS_E_INVALID_FORMAT
;
2689 static HRESULT
read_node_bin( struct reader
* );
2691 static HRESULT
read_startelement_bin( struct reader
*reader
)
2693 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
2694 return read_node_bin( reader
);
2697 static HRESULT
read_startelement( struct reader
*reader
)
2699 switch (reader
->input_enc
)
2701 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_startelement_text( reader
);
2702 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_startelement_bin( reader
);
2704 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2705 return WS_E_NOT_SUPPORTED
;
2709 static HRESULT
read_to_startelement_text( struct reader
*reader
, BOOL
*found
)
2713 switch (reader
->state
)
2715 case READER_STATE_INITIAL
:
2716 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
2719 case READER_STATE_STARTELEMENT
:
2720 if (found
) *found
= TRUE
;
2727 read_skip_whitespace( reader
);
2728 if ((hr
= read_element_text( reader
)) == S_OK
&& found
)
2730 if (reader
->state
== READER_STATE_STARTELEMENT
)
2739 static HRESULT
read_to_startelement_bin( struct reader
*reader
, BOOL
*found
)
2743 if (reader
->state
== READER_STATE_STARTELEMENT
)
2745 if (found
) *found
= TRUE
;
2749 if ((hr
= read_element_bin( reader
)) == S_OK
&& found
)
2751 if (reader
->state
== READER_STATE_STARTELEMENT
)
2760 static HRESULT
read_to_startelement( struct reader
*reader
, BOOL
*found
)
2762 switch (reader
->input_enc
)
2764 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_to_startelement_text( reader
, found
);
2765 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_to_startelement_bin( reader
, found
);
2767 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2768 return WS_E_NOT_SUPPORTED
;
2772 static int cmp_name( const unsigned char *name1
, ULONG len1
, const unsigned char *name2
, ULONG len2
)
2775 if (len1
!= len2
) return 1;
2776 for (i
= 0; i
< len1
; i
++) { if (toupper( name1
[i
] ) != toupper( name2
[i
] )) return 1; }
2780 static struct node
*find_startelement( struct reader
*reader
, const WS_XML_STRING
*prefix
,
2781 const WS_XML_STRING
*localname
)
2783 struct node
*parent
;
2784 const WS_XML_STRING
*str
;
2786 for (parent
= reader
->current
; parent
; parent
= parent
->parent
)
2788 if (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2790 str
= parent
->hdr
.prefix
;
2791 if (cmp_name( str
->bytes
, str
->length
, prefix
->bytes
, prefix
->length
)) continue;
2792 str
= parent
->hdr
.localName
;
2793 if (cmp_name( str
->bytes
, str
->length
, localname
->bytes
, localname
->length
)) continue;
2800 static HRESULT
read_endelement_text( struct reader
*reader
)
2802 struct node
*parent
;
2803 unsigned int len
= 0, ch
, skip
;
2804 const unsigned char *start
;
2805 WS_XML_STRING prefix
, localname
;
2808 if ((hr
= read_cmp( reader
, "</", 2 )) != S_OK
) return hr
;
2809 read_skip( reader
, 2 );
2811 start
= read_current_ptr( reader
);
2814 if ((hr
= read_utf8_char( reader
, &ch
, &skip
)) != S_OK
) return hr
;
2817 read_skip( reader
, 1 );
2820 if (!read_isnamechar( ch
)) return WS_E_INVALID_FORMAT
;
2821 read_skip( reader
, skip
);
2825 if ((hr
= split_qname( start
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
2826 if (!(parent
= find_startelement( reader
, &prefix
, &localname
))) return WS_E_INVALID_FORMAT
;
2828 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2829 reader
->last
= reader
->current
;
2830 reader
->state
= READER_STATE_ENDELEMENT
;
2834 static HRESULT
read_endelement_bin( struct reader
*reader
)
2836 struct node
*parent
;
2840 if (!(reader
->current
->flags
& NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
))
2842 if ((hr
= read_peek( reader
, &type
, 1 )) != S_OK
) return hr
;
2843 if (type
!= RECORD_ENDELEMENT
) return WS_E_INVALID_FORMAT
;
2844 read_skip( reader
, 1 );
2846 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2848 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
2849 reader
->last
= reader
->current
;
2850 reader
->state
= READER_STATE_ENDELEMENT
;
2854 static HRESULT
read_endelement( struct reader
*reader
)
2856 if (reader
->state
== READER_STATE_EOF
) return WS_E_INVALID_FORMAT
;
2858 if (read_end_of_data( reader
))
2860 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
2861 reader
->last
= reader
->current
;
2862 reader
->state
= READER_STATE_EOF
;
2866 switch (reader
->input_enc
)
2868 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_endelement_text( reader
);
2869 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_endelement_bin( reader
);
2871 ERR( "unhandled encoding %u\n", reader
->input_enc
);
2872 return WS_E_NOT_SUPPORTED
;
2876 static HRESULT
read_comment_text( struct reader
*reader
)
2878 unsigned int len
= 0, ch
, skip
;
2879 const unsigned char *start
;
2880 struct node
*node
, *parent
;
2881 WS_XML_COMMENT_NODE
*comment
;
2884 if ((hr
= read_cmp( reader
, "<!--", 4 )) != S_OK
) return hr
;
2885 read_skip( reader
, 4 );
2887 start
= read_current_ptr( reader
);
2890 if (read_cmp( reader
, "-->", 3 ) == S_OK
)
2892 read_skip( reader
, 3 );
2895 if ((hr
= read_utf8_char( reader
, &ch
, &skip
)) != S_OK
) return hr
;
2896 read_skip( reader
, skip
);
2900 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2902 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2903 comment
= (WS_XML_COMMENT_NODE
*)node
;
2904 if (!(comment
->value
.bytes
= malloc( len
)))
2907 return E_OUTOFMEMORY
;
2909 memcpy( comment
->value
.bytes
, start
, len
);
2910 comment
->value
.length
= len
;
2912 read_insert_node( reader
, parent
, node
);
2913 reader
->state
= READER_STATE_COMMENT
;
2917 static HRESULT
read_comment_bin( struct reader
*reader
)
2919 struct node
*node
, *parent
;
2920 WS_XML_COMMENT_NODE
*comment
;
2925 if ((hr
= read_peek( reader
, &type
, 1 )) != S_OK
) return hr
;
2926 if (type
!= RECORD_COMMENT
) return WS_E_INVALID_FORMAT
;
2927 read_skip( reader
, 1 );
2928 if ((hr
= read_int31( reader
, &len
)) != S_OK
) return hr
;
2930 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2932 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2933 comment
= (WS_XML_COMMENT_NODE
*)node
;
2934 if (!(comment
->value
.bytes
= malloc( len
)))
2937 return E_OUTOFMEMORY
;
2939 if ((hr
= read_bytes( reader
, comment
->value
.bytes
, len
)) != S_OK
)
2942 return E_OUTOFMEMORY
;
2944 comment
->value
.length
= len
;
2946 read_insert_node( reader
, parent
, node
);
2947 reader
->state
= READER_STATE_COMMENT
;
2951 static HRESULT
read_startcdata( struct reader
*reader
)
2953 struct node
*node
, *endnode
, *parent
;
2956 if ((hr
= read_cmp( reader
, "<![CDATA[", 9 )) != S_OK
) return hr
;
2957 read_skip( reader
, 9 );
2959 if (!(parent
= find_parent( reader
))) return WS_E_INVALID_FORMAT
;
2961 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2962 if (!(endnode
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
)))
2965 return E_OUTOFMEMORY
;
2967 list_add_tail( &node
->children
, &endnode
->entry
);
2968 endnode
->parent
= node
;
2970 read_insert_node( reader
, parent
, node
);
2971 reader
->state
= READER_STATE_STARTCDATA
;
2975 static HRESULT
read_cdata( struct reader
*reader
)
2977 unsigned int len
= 0, ch
, skip
;
2978 const unsigned char *start
;
2980 WS_XML_TEXT_NODE
*text
;
2981 WS_XML_UTF8_TEXT
*utf8
;
2984 start
= read_current_ptr( reader
);
2987 if (read_cmp( reader
, "]]>", 3 ) == S_OK
) break;
2988 if ((hr
= read_utf8_char( reader
, &ch
, &skip
)) != S_OK
) return hr
;
2989 read_skip( reader
, skip
);
2993 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2994 text
= (WS_XML_TEXT_NODE
*)node
;
2995 if (!(utf8
= alloc_utf8_text( start
, len
)))
2998 return E_OUTOFMEMORY
;
3000 text
->text
= &utf8
->text
;
3002 read_insert_node( reader
, reader
->current
, node
);
3003 reader
->state
= READER_STATE_CDATA
;
3007 static HRESULT
read_endcdata( struct reader
*reader
)
3009 struct node
*parent
;
3012 if ((hr
= read_cmp( reader
, "]]>", 3 )) != S_OK
) return hr
;
3013 read_skip( reader
, 3 );
3015 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
) parent
= reader
->current
->parent
;
3016 else parent
= reader
->current
;
3018 reader
->current
= LIST_ENTRY( list_tail( &parent
->children
), struct node
, entry
);
3019 reader
->last
= reader
->current
;
3020 reader
->state
= READER_STATE_ENDCDATA
;
3024 static HRESULT
read_node_text( struct reader
*reader
)
3030 if (read_end_of_data( reader
))
3032 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
3033 reader
->last
= reader
->current
;
3034 reader
->state
= READER_STATE_EOF
;
3037 if (reader
->state
== READER_STATE_STARTCDATA
) return read_cdata( reader
);
3038 else if (reader
->state
== READER_STATE_CDATA
) return read_endcdata( reader
);
3039 else if (read_cmp( reader
, "<?", 2 ) == S_OK
)
3041 if ((hr
= read_xmldecl( reader
)) != S_OK
) return hr
;
3043 else if (read_cmp( reader
, "</", 2 ) == S_OK
) return read_endelement_text( reader
);
3044 else if (read_cmp( reader
, "<![CDATA[", 9 ) == S_OK
) return read_startcdata( reader
);
3045 else if (read_cmp( reader
, "<!--", 4 ) == S_OK
) return read_comment_text( reader
);
3046 else if (read_cmp( reader
, "<", 1 ) == S_OK
) return read_element_text( reader
);
3047 else if (read_cmp( reader
, "/>", 2 ) == S_OK
|| read_cmp( reader
, ">", 1 ) == S_OK
)
3049 return read_startelement_text( reader
);
3051 else return read_text_text( reader
);
3055 static HRESULT
read_node_bin( struct reader
*reader
)
3060 if (reader
->current
->flags
& NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT
)
3062 reader
->current
= LIST_ENTRY( list_tail( &reader
->current
->parent
->children
), struct node
, entry
);
3063 reader
->last
= reader
->current
;
3064 reader
->state
= READER_STATE_ENDELEMENT
;
3067 if (read_end_of_data( reader
))
3069 reader
->current
= LIST_ENTRY( list_tail( &reader
->root
->children
), struct node
, entry
);
3070 reader
->last
= reader
->current
;
3071 reader
->state
= READER_STATE_EOF
;
3075 if ((hr
= read_peek( reader
, &type
, 1 )) != S_OK
) return hr
;
3076 if (type
== RECORD_ENDELEMENT
)
3078 return read_endelement_bin( reader
);
3080 else if (type
== RECORD_COMMENT
)
3082 return read_comment_bin( reader
);
3084 else if (type
>= RECORD_SHORT_ELEMENT
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
3086 return read_element_bin( reader
);
3088 else if (type
>= RECORD_ZERO_TEXT
&& type
<= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT
)
3090 return read_text_bin( reader
);
3092 FIXME( "unhandled record type %02x\n", type
);
3093 return WS_E_NOT_SUPPORTED
;
3096 static HRESULT
read_node( struct reader
*reader
)
3098 switch (reader
->input_enc
)
3100 case WS_XML_READER_ENCODING_TYPE_TEXT
: return read_node_text( reader
);
3101 case WS_XML_READER_ENCODING_TYPE_BINARY
: return read_node_bin( reader
);
3103 ERR( "unhandled encoding %u\n", reader
->input_enc
);
3104 return WS_E_NOT_SUPPORTED
;
3108 HRESULT
copy_node( WS_XML_READER
*handle
, WS_XML_WRITER_ENCODING_TYPE enc
, struct node
**node
)
3110 struct reader
*reader
= (struct reader
*)handle
;
3111 const struct list
*ptr
;
3112 const struct node
*start
;
3115 EnterCriticalSection( &reader
->cs
);
3117 if (reader
->magic
!= READER_MAGIC
)
3119 LeaveCriticalSection( &reader
->cs
);
3120 return E_INVALIDARG
;
3123 if (reader
->current
!= reader
->root
) ptr
= &reader
->current
->entry
;
3124 else /* copy whole tree */
3126 if (!read_end_of_data( reader
))
3130 if ((hr
= read_node( reader
)) != S_OK
) goto done
;
3131 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) break;
3134 ptr
= list_head( &reader
->root
->children
);
3137 start
= LIST_ENTRY( ptr
, struct node
, entry
);
3138 if (node_type( start
) == WS_XML_NODE_TYPE_EOF
) hr
= WS_E_INVALID_OPERATION
;
3139 else hr
= dup_tree( start
, enc
, node
);
3142 LeaveCriticalSection( &reader
->cs
);
3146 /**************************************************************************
3147 * WsReadEndElement [webservices.@]
3149 HRESULT WINAPI
WsReadEndElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
3151 struct reader
*reader
= (struct reader
*)handle
;
3154 TRACE( "%p %p\n", handle
, error
);
3155 if (error
) FIXME( "ignoring error parameter\n" );
3157 if (!reader
) return E_INVALIDARG
;
3159 EnterCriticalSection( &reader
->cs
);
3161 if (reader
->magic
!= READER_MAGIC
)
3163 LeaveCriticalSection( &reader
->cs
);
3164 return E_INVALIDARG
;
3167 hr
= read_endelement( reader
);
3169 LeaveCriticalSection( &reader
->cs
);
3170 TRACE( "returning %#lx\n", hr
);
3174 /**************************************************************************
3175 * WsReadNode [webservices.@]
3177 HRESULT WINAPI
WsReadNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
3179 struct reader
*reader
= (struct reader
*)handle
;
3182 TRACE( "%p %p\n", handle
, error
);
3183 if (error
) FIXME( "ignoring error parameter\n" );
3185 if (!reader
) return E_INVALIDARG
;
3187 EnterCriticalSection( &reader
->cs
);
3189 if (reader
->magic
!= READER_MAGIC
)
3191 LeaveCriticalSection( &reader
->cs
);
3192 return E_INVALIDARG
;
3195 hr
= read_node( reader
);
3197 LeaveCriticalSection( &reader
->cs
);
3198 TRACE( "returning %#lx\n", hr
);
3202 static HRESULT
skip_node( struct reader
*reader
)
3204 const struct node
*parent
;
3207 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_EOF
) return WS_E_INVALID_OPERATION
;
3208 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_ELEMENT
) parent
= reader
->current
;
3213 if ((hr
= read_node( reader
)) != S_OK
|| !parent
) break;
3214 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_END_ELEMENT
) continue;
3215 if (reader
->current
->parent
== parent
) return read_node( reader
);
3221 /**************************************************************************
3222 * WsSkipNode [webservices.@]
3224 HRESULT WINAPI
WsSkipNode( WS_XML_READER
*handle
, WS_ERROR
*error
)
3226 struct reader
*reader
= (struct reader
*)handle
;
3229 TRACE( "%p %p\n", handle
, error
);
3230 if (error
) FIXME( "ignoring error parameter\n" );
3232 if (!reader
) return E_INVALIDARG
;
3234 EnterCriticalSection( &reader
->cs
);
3236 if (reader
->magic
!= READER_MAGIC
)
3238 LeaveCriticalSection( &reader
->cs
);
3239 return E_INVALIDARG
;
3242 hr
= skip_node( reader
);
3244 LeaveCriticalSection( &reader
->cs
);
3245 TRACE( "returning %#lx\n", hr
);
3249 /**************************************************************************
3250 * WsReadStartElement [webservices.@]
3252 HRESULT WINAPI
WsReadStartElement( WS_XML_READER
*handle
, WS_ERROR
*error
)
3254 struct reader
*reader
= (struct reader
*)handle
;
3257 TRACE( "%p %p\n", handle
, error
);
3258 if (error
) FIXME( "ignoring error parameter\n" );
3260 if (!reader
) return E_INVALIDARG
;
3262 EnterCriticalSection( &reader
->cs
);
3264 if (reader
->magic
!= READER_MAGIC
)
3266 LeaveCriticalSection( &reader
->cs
);
3267 return E_INVALIDARG
;
3270 hr
= read_startelement( reader
);
3272 LeaveCriticalSection( &reader
->cs
);
3273 TRACE( "returning %#lx\n", hr
);
3277 /**************************************************************************
3278 * WsReadToStartElement [webservices.@]
3280 HRESULT WINAPI
WsReadToStartElement( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
3281 const WS_XML_STRING
*ns
, BOOL
*found
, WS_ERROR
*error
)
3283 struct reader
*reader
= (struct reader
*)handle
;
3286 TRACE( "%p %s %s %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
), found
, error
);
3287 if (error
) FIXME( "ignoring error parameter\n" );
3289 if (!reader
) return E_INVALIDARG
;
3290 if (localname
|| ns
) FIXME( "name and/or namespace not verified\n" );
3292 EnterCriticalSection( &reader
->cs
);
3294 if (reader
->magic
!= READER_MAGIC
)
3296 LeaveCriticalSection( &reader
->cs
);
3297 return E_INVALIDARG
;
3300 hr
= read_to_startelement( reader
, found
);
3302 LeaveCriticalSection( &reader
->cs
);
3303 TRACE( "returning %#lx\n", hr
);
3307 BOOL
move_to_root_element( struct node
*root
, struct node
**current
)
3312 if (!(ptr
= list_head( &root
->children
))) return FALSE
;
3313 node
= LIST_ENTRY( ptr
, struct node
, entry
);
3314 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
)
3319 while ((ptr
= list_next( &root
->children
, &node
->entry
)))
3321 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
3322 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
3332 BOOL
move_to_next_element( struct node
**current
)
3335 struct node
*node
= *current
, *parent
= (*current
)->parent
;
3337 if (!parent
) return FALSE
;
3338 while ((ptr
= list_next( &parent
->children
, &node
->entry
)))
3340 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
3341 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
3351 BOOL
move_to_prev_element( struct node
**current
)
3354 struct node
*node
= *current
, *parent
= (*current
)->parent
;
3356 if (!parent
) return FALSE
;
3357 while ((ptr
= list_prev( &parent
->children
, &node
->entry
)))
3359 struct node
*prev
= LIST_ENTRY( ptr
, struct node
, entry
);
3360 if (node_type( prev
) == WS_XML_NODE_TYPE_ELEMENT
)
3370 BOOL
move_to_child_element( struct node
**current
)
3373 struct node
*child
, *node
= *current
;
3375 if (!(ptr
= list_head( &node
->children
))) return FALSE
;
3376 child
= LIST_ENTRY( ptr
, struct node
, entry
);
3377 if (node_type( child
) == WS_XML_NODE_TYPE_ELEMENT
)
3382 while ((ptr
= list_next( &node
->children
, &child
->entry
)))
3384 struct node
*next
= LIST_ENTRY( ptr
, struct node
, entry
);
3385 if (node_type( next
) == WS_XML_NODE_TYPE_ELEMENT
)
3395 BOOL
move_to_end_element( struct node
**current
)
3398 struct node
*node
= *current
;
3400 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
3402 if ((ptr
= list_tail( &node
->children
)))
3404 struct node
*tail
= LIST_ENTRY( ptr
, struct node
, entry
);
3405 if (node_type( tail
) == WS_XML_NODE_TYPE_END_ELEMENT
)
3414 BOOL
move_to_parent_element( struct node
**current
)
3416 struct node
*parent
= (*current
)->parent
;
3418 if (parent
&& (node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
||
3419 node_type( parent
) == WS_XML_NODE_TYPE_BOF
))
3427 BOOL
move_to_first_node( struct node
**current
)
3430 struct node
*node
= *current
;
3432 if ((ptr
= list_head( &node
->parent
->children
)))
3434 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3440 BOOL
move_to_next_node( struct node
**current
)
3443 struct node
*node
= *current
;
3445 if ((ptr
= list_next( &node
->parent
->children
, &node
->entry
)))
3447 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3453 BOOL
move_to_prev_node( struct node
**current
)
3456 struct node
*node
= *current
;
3458 if ((ptr
= list_prev( &node
->parent
->children
, &node
->entry
)))
3460 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3466 BOOL
move_to_bof( struct node
*root
, struct node
**current
)
3472 BOOL
move_to_eof( struct node
*root
, struct node
**current
)
3475 if ((ptr
= list_tail( &root
->children
)))
3477 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3483 BOOL
move_to_child_node( struct node
**current
)
3486 struct node
*node
= *current
;
3488 if ((ptr
= list_head( &node
->children
)))
3490 *current
= LIST_ENTRY( ptr
, struct node
, entry
);
3496 BOOL
move_to_parent_node( struct node
**current
)
3498 struct node
*parent
= (*current
)->parent
;
3499 if (!parent
) return FALSE
;
3504 static HRESULT
read_move_to( struct reader
*reader
, WS_MOVE_TO move
, BOOL
*found
)
3506 BOOL success
= FALSE
;
3509 if (!read_end_of_data( reader
))
3511 struct node
*saved_current
= reader
->current
;
3512 while (reader
->state
!= READER_STATE_EOF
&& (hr
= read_node( reader
)) == S_OK
) { /* nothing */ };
3513 if (hr
!= S_OK
) return hr
;
3514 reader
->current
= saved_current
;
3518 case WS_MOVE_TO_ROOT_ELEMENT
:
3519 success
= move_to_root_element( reader
->root
, &reader
->current
);
3522 case WS_MOVE_TO_NEXT_ELEMENT
:
3523 success
= move_to_next_element( &reader
->current
);
3526 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
3527 success
= move_to_prev_element( &reader
->current
);
3530 case WS_MOVE_TO_CHILD_ELEMENT
:
3531 success
= move_to_child_element( &reader
->current
);
3534 case WS_MOVE_TO_END_ELEMENT
:
3535 success
= move_to_end_element( &reader
->current
);
3538 case WS_MOVE_TO_PARENT_ELEMENT
:
3539 success
= move_to_parent_element( &reader
->current
);
3542 case WS_MOVE_TO_FIRST_NODE
:
3543 success
= move_to_first_node( &reader
->current
);
3546 case WS_MOVE_TO_NEXT_NODE
:
3547 success
= move_to_next_node( &reader
->current
);
3550 case WS_MOVE_TO_PREVIOUS_NODE
:
3551 success
= move_to_prev_node( &reader
->current
);
3554 case WS_MOVE_TO_CHILD_NODE
:
3555 success
= move_to_child_node( &reader
->current
);
3558 case WS_MOVE_TO_BOF
:
3559 success
= move_to_bof( reader
->root
, &reader
->current
);
3562 case WS_MOVE_TO_EOF
:
3563 success
= move_to_eof( reader
->root
, &reader
->current
);
3567 FIXME( "unhandled move %u\n", move
);
3576 return success
? S_OK
: WS_E_INVALID_FORMAT
;
3579 /**************************************************************************
3580 * WsMoveReader [webservices.@]
3582 HRESULT WINAPI
WsMoveReader( WS_XML_READER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
3584 struct reader
*reader
= (struct reader
*)handle
;
3587 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
3588 if (error
) FIXME( "ignoring error parameter\n" );
3590 if (!reader
) return E_INVALIDARG
;
3592 EnterCriticalSection( &reader
->cs
);
3594 if (reader
->magic
!= READER_MAGIC
)
3596 LeaveCriticalSection( &reader
->cs
);
3597 return E_INVALIDARG
;
3600 if (reader
->input_type
!= WS_XML_READER_INPUT_TYPE_BUFFER
) hr
= WS_E_INVALID_OPERATION
;
3601 else hr
= read_move_to( reader
, move
, found
);
3603 LeaveCriticalSection( &reader
->cs
);
3604 TRACE( "returning %#lx\n", hr
);
3608 /**************************************************************************
3609 * WsReadStartAttribute [webservices.@]
3611 HRESULT WINAPI
WsReadStartAttribute( WS_XML_READER
*handle
, ULONG index
, WS_ERROR
*error
)
3613 struct reader
*reader
= (struct reader
*)handle
;
3614 const WS_XML_ELEMENT_NODE
*elem
;
3617 TRACE( "%p %lu %p\n", handle
, index
, error
);
3618 if (error
) FIXME( "ignoring error parameter\n" );
3620 if (!reader
) return E_INVALIDARG
;
3622 EnterCriticalSection( &reader
->cs
);
3624 if (reader
->magic
!= READER_MAGIC
)
3626 LeaveCriticalSection( &reader
->cs
);
3627 return E_INVALIDARG
;
3630 elem
= &reader
->current
->hdr
;
3631 if (reader
->state
!= READER_STATE_STARTELEMENT
|| index
>= elem
->attributeCount
) hr
= WS_E_INVALID_FORMAT
;
3634 reader
->current_attr
= index
;
3635 reader
->state
= READER_STATE_STARTATTRIBUTE
;
3638 LeaveCriticalSection( &reader
->cs
);
3639 TRACE( "returning %#lx\n", hr
);
3643 /**************************************************************************
3644 * WsReadEndAttribute [webservices.@]
3646 HRESULT WINAPI
WsReadEndAttribute( WS_XML_READER
*handle
, WS_ERROR
*error
)
3648 struct reader
*reader
= (struct reader
*)handle
;
3651 TRACE( "%p %p\n", handle
, error
);
3652 if (error
) FIXME( "ignoring error parameter\n" );
3654 if (!reader
) return E_INVALIDARG
;
3656 EnterCriticalSection( &reader
->cs
);
3658 if (reader
->magic
!= READER_MAGIC
)
3660 LeaveCriticalSection( &reader
->cs
);
3661 return E_INVALIDARG
;
3664 if (reader
->state
!= READER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
3665 else reader
->state
= READER_STATE_STARTELEMENT
;
3667 LeaveCriticalSection( &reader
->cs
);
3668 TRACE( "returning %#lx\n", hr
);
3672 static HRESULT
str_to_bool( const unsigned char *str
, ULONG len
, BOOL
*ret
)
3674 if (len
== 4 && !memcmp( str
, "true", 4 )) *ret
= TRUE
;
3675 else if (len
== 1 && !memcmp( str
, "1", 1 )) *ret
= TRUE
;
3676 else if (len
== 5 && !memcmp( str
, "false", 5 )) *ret
= FALSE
;
3677 else if (len
== 1 && !memcmp( str
, "0", 1 )) *ret
= FALSE
;
3678 else return WS_E_INVALID_FORMAT
;
3682 static HRESULT
str_to_int64( const unsigned char *str
, ULONG len
, INT64 min
, INT64 max
, INT64
*ret
)
3684 BOOL negative
= FALSE
;
3685 const unsigned char *ptr
= str
;
3688 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3689 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3690 if (!len
) return WS_E_INVALID_FORMAT
;
3698 if (!len
) return WS_E_INVALID_FORMAT
;
3704 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3706 if (negative
) val
= -val
;
3708 if ((!negative
&& (*ret
> max
/ 10 || *ret
* 10 > max
- val
)) ||
3709 (negative
&& (*ret
< min
/ 10 || *ret
* 10 < min
- val
)))
3711 return WS_E_NUMERIC_OVERFLOW
;
3713 *ret
= *ret
* 10 + val
;
3720 static HRESULT
str_to_uint64( const unsigned char *str
, ULONG len
, UINT64 max
, UINT64
*ret
)
3722 const unsigned char *ptr
= str
;
3725 while (len
&& read_isspace( *ptr
)) { ptr
++; len
--; }
3726 while (len
&& read_isspace( ptr
[len
- 1] )) { len
--; }
3727 if (!len
) return WS_E_INVALID_FORMAT
;
3733 if (!isdigit( *ptr
)) return WS_E_INVALID_FORMAT
;
3736 if ((*ret
> max
/ 10 || *ret
* 10 > max
- val
)) return WS_E_NUMERIC_OVERFLOW
;
3737 *ret
= *ret
* 10 + val
;
3744 static HRESULT
str_to_double( const unsigned char *str
, ULONG len
, double *ret
)
3746 BOOL found_sign
= FALSE
, found_exponent
= FALSE
, found_digit
= FALSE
, found_decimal
= FALSE
;
3747 static const unsigned __int64 nan
= 0xfff8000000000000;
3748 static const unsigned __int64 inf
= 0x7ff0000000000000;
3749 static const unsigned __int64 inf_min
= 0xfff0000000000000;
3750 const char *p
= (const char *)str
;
3754 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3755 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3756 if (!len
) return WS_E_INVALID_FORMAT
;
3758 if (len
== 3 && !memcmp( p
, "NaN", 3 ))
3760 *(unsigned __int64
*)ret
= nan
;
3763 if (len
== 3 && !memcmp( p
, "INF", 3 ))
3765 *(unsigned __int64
*)ret
= inf
;
3768 if (len
== 4 && !memcmp( p
, "-INF", 4 ))
3770 *(unsigned __int64
*)ret
= inf_min
;
3774 for (i
= 0; i
< len
; i
++)
3776 if (p
[i
] >= '0' && p
[i
] <= '9')
3781 if (!found_sign
&& !found_digit
&& (p
[i
] == '+' || p
[i
] == '-'))
3786 if (!found_exponent
&& found_digit
&& (p
[i
] == 'e' || p
[i
] == 'E'))
3788 found_exponent
= found_decimal
= TRUE
;
3789 found_digit
= found_sign
= FALSE
;
3792 if (!found_decimal
&& p
[i
] == '.')
3794 found_decimal
= TRUE
;
3797 return WS_E_INVALID_FORMAT
;
3799 if (!found_digit
&& !found_exponent
)
3805 if (_snscanf_l( p
, len
, "%lf", c_locale
, &tmp
) != 1) return WS_E_INVALID_FORMAT
;
3810 static HRESULT
str_to_float( const unsigned char *str
, ULONG len
, float *ret
)
3812 static const unsigned int inf
= 0x7f800000;
3813 static const unsigned int inf_min
= 0xff800000;
3814 const unsigned char *p
= str
;
3818 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3819 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3820 if (!len
) return WS_E_INVALID_FORMAT
;
3822 if (len
== 3 && !memcmp( p
, "INF", 3 ))
3824 *(unsigned int *)ret
= inf
;
3827 if (len
== 4 && !memcmp( p
, "-INF", 4 ))
3829 *(unsigned int *)ret
= inf_min
;
3833 if ((hr
= str_to_double( p
, len
, &val
)) != S_OK
) return hr
;
3838 HRESULT
str_to_guid( const unsigned char *str
, ULONG len
, GUID
*ret
)
3840 static const unsigned char hex
[] =
3842 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */
3843 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */
3844 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */
3845 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */
3846 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */
3847 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */
3848 0,10,11,12,13,14,15 /* 0x60 */
3850 const unsigned char *p
= str
;
3853 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3854 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3855 if (len
!= 36) return WS_E_INVALID_FORMAT
;
3857 if (p
[8] != '-' || p
[13] != '-' || p
[18] != '-' || p
[23] != '-')
3858 return WS_E_INVALID_FORMAT
;
3860 for (i
= 0; i
< 36; i
++)
3862 if (i
== 8 || i
== 13 || i
== 18 || i
== 23) continue;
3863 if (p
[i
] > 'f' || (!hex
[p
[i
]] && p
[i
] != '0')) return WS_E_INVALID_FORMAT
;
3866 ret
->Data1
= hex
[p
[0]] << 28 | hex
[p
[1]] << 24 | hex
[p
[2]] << 20 | hex
[p
[3]] << 16 |
3867 hex
[p
[4]] << 12 | hex
[p
[5]] << 8 | hex
[p
[6]] << 4 | hex
[p
[7]];
3869 ret
->Data2
= hex
[p
[9]] << 12 | hex
[p
[10]] << 8 | hex
[p
[11]] << 4 | hex
[p
[12]];
3870 ret
->Data3
= hex
[p
[14]] << 12 | hex
[p
[15]] << 8 | hex
[p
[16]] << 4 | hex
[p
[17]];
3872 ret
->Data4
[0] = hex
[p
[19]] << 4 | hex
[p
[20]];
3873 ret
->Data4
[1] = hex
[p
[21]] << 4 | hex
[p
[22]];
3874 ret
->Data4
[2] = hex
[p
[24]] << 4 | hex
[p
[25]];
3875 ret
->Data4
[3] = hex
[p
[26]] << 4 | hex
[p
[27]];
3876 ret
->Data4
[4] = hex
[p
[28]] << 4 | hex
[p
[29]];
3877 ret
->Data4
[5] = hex
[p
[30]] << 4 | hex
[p
[31]];
3878 ret
->Data4
[6] = hex
[p
[32]] << 4 | hex
[p
[33]];
3879 ret
->Data4
[7] = hex
[p
[34]] << 4 | hex
[p
[35]];
3884 static HRESULT
str_to_string( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_STRING
*ret
)
3886 int len_utf16
= MultiByteToWideChar( CP_UTF8
, 0, (const char *)str
, len
, NULL
, 0 );
3887 if (!(ret
->chars
= ws_alloc( heap
, len_utf16
* sizeof(WCHAR
) ))) return WS_E_QUOTA_EXCEEDED
;
3888 MultiByteToWideChar( CP_UTF8
, 0, (const char *)str
, len
, ret
->chars
, len_utf16
);
3889 ret
->length
= len_utf16
;
3893 static HRESULT
str_to_unique_id( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_UNIQUE_ID
*ret
)
3895 if (len
== 45 && !memcmp( str
, "urn:uuid:", 9 ))
3897 ret
->uri
.length
= 0;
3898 ret
->uri
.chars
= NULL
;
3899 return str_to_guid( str
+ 9, len
- 9, &ret
->guid
);
3902 memset( &ret
->guid
, 0, sizeof(ret
->guid
) );
3903 return str_to_string( str
, len
, heap
, &ret
->uri
);
3906 static inline unsigned char decode_char( unsigned char c
)
3908 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
3909 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
3910 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
3911 if (c
== '+') return 62;
3912 if (c
== '/') return 63;
3916 static ULONG
decode_base64( const unsigned char *base64
, ULONG len
, unsigned char *buf
)
3919 unsigned char c0
, c1
, c2
, c3
;
3920 const unsigned char *p
= base64
;
3924 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3925 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3926 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3927 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3928 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3929 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3930 buf
[i
+ 2] = (c2
<< 6) | c3
;
3937 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3938 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3939 buf
[i
] = (c0
<< 2) | (c1
>> 4);
3942 else if (p
[3] == '=')
3944 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3945 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3946 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3947 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3948 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3953 if ((c0
= decode_char( p
[0] )) > 63) return 0;
3954 if ((c1
= decode_char( p
[1] )) > 63) return 0;
3955 if ((c2
= decode_char( p
[2] )) > 63) return 0;
3956 if ((c3
= decode_char( p
[3] )) > 63) return 0;
3957 buf
[i
+ 0] = (c0
<< 2) | (c1
>> 4);
3958 buf
[i
+ 1] = (c1
<< 4) | (c2
>> 2);
3959 buf
[i
+ 2] = (c2
<< 6) | c3
;
3965 static HRESULT
str_to_bytes( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_BYTES
*ret
)
3967 const unsigned char *p
= str
;
3969 while (len
&& read_isspace( *p
)) { p
++; len
--; }
3970 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
3972 if (len
% 4) return WS_E_INVALID_FORMAT
;
3973 if (!(ret
->bytes
= ws_alloc( heap
, len
* 3 / 4 ))) return WS_E_QUOTA_EXCEEDED
;
3974 ret
->length
= decode_base64( p
, len
, ret
->bytes
);
3978 static HRESULT
str_to_xml_string( const unsigned char *str
, ULONG len
, WS_HEAP
*heap
, WS_XML_STRING
*ret
)
3980 if (!(ret
->bytes
= ws_alloc( heap
, len
))) return WS_E_QUOTA_EXCEEDED
;
3981 memcpy( ret
->bytes
, str
, len
);
3983 ret
->dictionary
= NULL
;
3988 static HRESULT
copy_xml_string( WS_HEAP
*heap
, const WS_XML_STRING
*src
, WS_XML_STRING
*dst
)
3990 if (!(dst
->bytes
= ws_alloc( heap
, src
->length
))) return WS_E_QUOTA_EXCEEDED
;
3991 memcpy( dst
->bytes
, src
->bytes
, src
->length
);
3992 dst
->length
= src
->length
;
3996 static HRESULT
str_to_qname( struct reader
*reader
, const unsigned char *str
, ULONG len
, WS_HEAP
*heap
,
3997 WS_XML_STRING
*prefix_ret
, WS_XML_STRING
*localname_ret
, WS_XML_STRING
*ns_ret
)
3999 const unsigned char *p
= str
;
4000 WS_XML_STRING prefix
, localname
;
4001 const WS_XML_STRING
*ns
;
4004 while (len
&& read_isspace( *p
)) { p
++; len
--; }
4005 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
4007 if ((hr
= split_qname( p
, len
, &prefix
, &localname
)) != S_OK
) return hr
;
4008 if (!(ns
= get_namespace( reader
, &prefix
))) return WS_E_INVALID_FORMAT
;
4010 if (prefix_ret
&& (hr
= copy_xml_string( heap
, &prefix
, prefix_ret
)) != S_OK
) return hr
;
4011 if ((hr
= copy_xml_string( heap
, &localname
, localname_ret
)) != S_OK
)
4013 ws_free( heap
, prefix_ret
->bytes
, prefix_ret
->length
);
4016 if ((hr
= copy_xml_string( heap
, ns
, ns_ret
)) != S_OK
)
4018 ws_free( heap
, prefix_ret
->bytes
, prefix_ret
->length
);
4019 ws_free( heap
, localname_ret
->bytes
, localname_ret
->length
);
4025 static HRESULT
read_qualified_name( struct reader
*reader
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
4026 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
)
4028 const WS_XML_TEXT_NODE
*node
= (const WS_XML_TEXT_NODE
*)reader
->current
;
4029 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)node
->text
;
4030 return str_to_qname( reader
, utf8
->value
.bytes
, utf8
->value
.length
, heap
, prefix
, localname
, ns
);
4033 /**************************************************************************
4034 * WsReadQualifiedName [webservices.@]
4036 HRESULT WINAPI
WsReadQualifiedName( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_STRING
*prefix
,
4037 WS_XML_STRING
*localname
, WS_XML_STRING
*ns
,
4040 struct reader
*reader
= (struct reader
*)handle
;
4043 TRACE( "%p %p %p %p %p %p\n", handle
, heap
, prefix
, localname
, ns
, error
);
4044 if (error
) FIXME( "ignoring error parameter\n" );
4046 if (!reader
|| !heap
) return E_INVALIDARG
;
4048 EnterCriticalSection( &reader
->cs
);
4050 if (reader
->magic
!= READER_MAGIC
)
4052 LeaveCriticalSection( &reader
->cs
);
4053 return E_INVALIDARG
;
4056 if (!reader
->input_type
) hr
= WS_E_INVALID_OPERATION
;
4057 else if (!localname
) hr
= E_INVALIDARG
;
4058 else if (reader
->state
!= READER_STATE_TEXT
) hr
= WS_E_INVALID_FORMAT
;
4059 else hr
= read_qualified_name( reader
, heap
, prefix
, localname
, ns
);
4061 LeaveCriticalSection( &reader
->cs
);
4062 TRACE( "returning %#lx\n", hr
);
4066 static const int month_offsets
[2][12] =
4068 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
4069 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
4072 static inline int valid_day( int year
, int month
, int day
)
4074 return day
> 0 && day
<= month_days
[leap_year( year
)][month
- 1];
4077 static inline int leap_days_before( int year
)
4079 return (year
- 1) / 4 - (year
- 1) / 100 + (year
- 1) / 400;
4082 static HRESULT
str_to_datetime( const unsigned char *bytes
, ULONG len
, WS_DATETIME
*ret
)
4084 const unsigned char *p
= bytes
, *q
;
4085 int year
, month
, day
, hour
, min
, sec
, sec_frac
= 0, tz_hour
, tz_min
, tz_neg
;
4087 while (len
&& read_isspace( *p
)) { p
++; len
--; }
4088 while (len
&& read_isspace( p
[len
- 1] )) { len
--; }
4091 while (len
&& isdigit( *q
)) { q
++; len
--; };
4092 if (q
- p
!= 4 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
4093 year
= (p
[0] - '0') * 1000 + (p
[1] - '0') * 100 + (p
[2] - '0') * 10 + p
[3] - '0';
4094 if (year
< 1) return WS_E_INVALID_FORMAT
;
4097 while (len
&& isdigit( *q
)) { q
++; len
--; };
4098 if (q
- p
!= 2 || !len
|| *q
!= '-') return WS_E_INVALID_FORMAT
;
4099 month
= (p
[0] - '0') * 10 + p
[1] - '0';
4100 if (month
< 1 || month
> 12) return WS_E_INVALID_FORMAT
;
4103 while (len
&& isdigit( *q
)) { q
++; len
--; };
4104 if (q
- p
!= 2 || !len
|| *q
!= 'T') return WS_E_INVALID_FORMAT
;
4105 day
= (p
[0] - '0') * 10 + p
[1] - '0';
4106 if (!valid_day( year
, month
, day
)) return WS_E_INVALID_FORMAT
;
4109 while (len
&& isdigit( *q
)) { q
++; len
--; };
4110 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
4111 hour
= (p
[0] - '0') * 10 + p
[1] - '0';
4112 if (hour
> 24) return WS_E_INVALID_FORMAT
;
4115 while (len
&& isdigit( *q
)) { q
++; len
--; };
4116 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
4117 min
= (p
[0] - '0') * 10 + p
[1] - '0';
4118 if (min
> 59 || (min
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
4121 while (len
&& isdigit( *q
)) { q
++; len
--; };
4122 if (q
- p
!= 2 || !len
) return WS_E_INVALID_FORMAT
;
4123 sec
= (p
[0] - '0') * 10 + p
[1] - '0';
4124 if (sec
> 59 || (sec
> 0 && hour
== 24)) return WS_E_INVALID_FORMAT
;
4128 unsigned int i
, nb_digits
, mul
= TICKS_PER_SEC
/ 10;
4130 while (len
&& isdigit( *q
)) { q
++; len
--; };
4132 if (nb_digits
< 1 || nb_digits
> 7) return WS_E_INVALID_FORMAT
;
4133 for (i
= 0; i
< nb_digits
; i
++)
4135 sec_frac
+= (p
[i
] - '0') * mul
;
4141 if (--len
) return WS_E_INVALID_FORMAT
;
4142 tz_hour
= tz_min
= tz_neg
= 0;
4143 ret
->format
= WS_DATETIME_FORMAT_UTC
;
4145 else if (*q
== '+' || *q
== '-')
4147 tz_neg
= (*q
== '-') ? 1 : 0;
4150 while (len
&& isdigit( *q
)) { q
++; len
--; };
4151 if (q
- p
!= 2 || !len
|| *q
!= ':') return WS_E_INVALID_FORMAT
;
4152 tz_hour
= (p
[0] - '0') * 10 + p
[1] - '0';
4153 if (tz_hour
> 14) return WS_E_INVALID_FORMAT
;
4156 while (len
&& isdigit( *q
)) { q
++; len
--; };
4157 if (q
- p
!= 2 || len
) return WS_E_INVALID_FORMAT
;
4158 tz_min
= (p
[0] - '0') * 10 + p
[1] - '0';
4159 if (tz_min
> 59 || (tz_min
> 0 && tz_hour
== 14)) return WS_E_INVALID_FORMAT
;
4161 ret
->format
= WS_DATETIME_FORMAT_LOCAL
;
4163 else return WS_E_INVALID_FORMAT
;
4165 ret
->ticks
= ((year
- 1) * 365 + leap_days_before( year
)) * TICKS_PER_DAY
;
4166 ret
->ticks
+= month_offsets
[leap_year( year
)][month
- 1] * TICKS_PER_DAY
;
4167 ret
->ticks
+= (day
- 1) * TICKS_PER_DAY
;
4168 ret
->ticks
+= hour
* TICKS_PER_HOUR
;
4169 ret
->ticks
+= min
* TICKS_PER_MIN
;
4170 ret
->ticks
+= sec
* TICKS_PER_SEC
;
4171 ret
->ticks
+= sec_frac
;
4175 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
+ ret
->ticks
> TICKS_MAX
)
4176 return WS_E_INVALID_FORMAT
;
4177 ret
->ticks
+= tz_hour
* TICKS_PER_HOUR
;
4178 ret
->ticks
+= tz_min
* TICKS_PER_MIN
;
4182 if (tz_hour
* TICKS_PER_HOUR
+ tz_min
* TICKS_PER_MIN
> ret
->ticks
)
4183 return WS_E_INVALID_FORMAT
;
4184 ret
->ticks
-= tz_hour
* TICKS_PER_HOUR
;
4185 ret
->ticks
-= tz_min
* TICKS_PER_MIN
;
4191 /**************************************************************************
4192 * WsDateTimeToFileTime [webservices.@]
4194 HRESULT WINAPI
WsDateTimeToFileTime( const WS_DATETIME
*dt
, FILETIME
*ft
, WS_ERROR
*error
)
4196 unsigned __int64 ticks
;
4198 TRACE( "%p %p %p\n", dt
, ft
, error
);
4199 if (error
) FIXME( "ignoring error parameter\n" );
4201 if (!dt
|| !ft
) return E_INVALIDARG
;
4203 if (dt
->ticks
< TICKS_1601_01_01
) return WS_E_INVALID_FORMAT
;
4204 ticks
= dt
->ticks
- TICKS_1601_01_01
;
4205 ft
->dwHighDateTime
= ticks
>> 32;
4206 ft
->dwLowDateTime
= (DWORD
)ticks
;
4210 /**************************************************************************
4211 * WsFileTimeToDateTime [webservices.@]
4213 HRESULT WINAPI
WsFileTimeToDateTime( const FILETIME
*ft
, WS_DATETIME
*dt
, WS_ERROR
*error
)
4215 unsigned __int64 ticks
;
4217 TRACE( "%p %p %p\n", ft
, dt
, error
);
4218 if (error
) FIXME( "ignoring error parameter\n" );
4220 if (!dt
|| !ft
) return E_INVALIDARG
;
4222 ticks
= ((unsigned __int64
)ft
->dwHighDateTime
<< 32) | ft
->dwLowDateTime
;
4223 if (ticks
> MAX_UINT64
- TICKS_1601_01_01
) return WS_E_NUMERIC_OVERFLOW
;
4224 if (ticks
+ TICKS_1601_01_01
> TICKS_MAX
) return WS_E_INVALID_FORMAT
;
4225 dt
->ticks
= ticks
+ TICKS_1601_01_01
;
4226 dt
->format
= WS_DATETIME_FORMAT_UTC
;
4230 static BOOL
find_attribute( struct reader
*reader
, const WS_XML_STRING
*localname
,
4231 const WS_XML_STRING
*ns
, ULONG
*index
)
4234 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
4238 *index
= reader
->current_attr
;
4241 for (i
= 0; i
< elem
->attributeCount
; i
++)
4243 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
4244 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
4246 if (!cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
) &&
4247 !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
4256 /**************************************************************************
4257 * WsFindAttribute [webservices.@]
4259 HRESULT WINAPI
WsFindAttribute( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
,
4260 const WS_XML_STRING
*ns
, BOOL required
, ULONG
*index
,
4263 struct reader
*reader
= (struct reader
*)handle
;
4266 TRACE( "%p %s %s %d %p %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
4267 required
, index
, error
);
4268 if (error
) FIXME( "ignoring error parameter\n" );
4270 if (!reader
|| !localname
|| !ns
|| !index
) return E_INVALIDARG
;
4272 EnterCriticalSection( &reader
->cs
);
4274 if (reader
->magic
!= READER_MAGIC
)
4276 LeaveCriticalSection( &reader
->cs
);
4277 return E_INVALIDARG
;
4280 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) hr
= WS_E_INVALID_OPERATION
;
4281 else if (!find_attribute( reader
, localname
, ns
, index
))
4283 if (required
) hr
= WS_E_INVALID_FORMAT
;
4291 LeaveCriticalSection( &reader
->cs
);
4292 TRACE( "returning %#lx\n", hr
);
4296 static HRESULT
get_node_text( struct reader
*reader
, const WS_XML_TEXT
**ret
)
4298 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)&reader
->current
->hdr
.node
;
4303 static HRESULT
get_attribute_text( struct reader
*reader
, ULONG index
, const WS_XML_TEXT
**ret
)
4305 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
4306 *ret
= elem
->attributes
[index
]->value
;
4310 static BOOL
match_element( const struct node
*node
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
4312 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
4313 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) return FALSE
;
4314 return WsXmlStringEquals( localname
, elem
->localName
, NULL
) == S_OK
&&
4315 (!ns
|| WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
);
4318 static HRESULT
read_next_node( struct reader
*reader
)
4320 if (reader
->current
== reader
->last
) return read_node( reader
);
4321 if (move_to_child_node( &reader
->current
)) return S_OK
;
4322 if (move_to_next_node( &reader
->current
)) return S_OK
;
4323 if (!move_to_parent_node( &reader
->current
)) return WS_E_INVALID_FORMAT
;
4324 if (move_to_next_node( &reader
->current
)) return S_OK
;
4325 return WS_E_INVALID_FORMAT
;
4334 static void save_reader_position( const struct reader
*reader
, struct reader_pos
*pos
)
4336 pos
->node
= reader
->current
;
4337 pos
->attr
= reader
->current_attr
;
4340 static void restore_reader_position( struct reader
*reader
, const struct reader_pos
*pos
)
4342 reader
->current
= pos
->node
;
4343 reader
->current_attr
= pos
->attr
;
4346 static HRESULT
get_text( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
4347 const WS_XML_STRING
*ns
, const WS_XML_TEXT
**ret
, BOOL
*found
)
4351 case WS_ATTRIBUTE_TYPE_MAPPING
:
4354 WS_XML_ELEMENT_NODE
*elem
= &reader
->current
->hdr
;
4357 for (i
= 0; i
< elem
->attributeCount
; i
++)
4359 const WS_XML_STRING
*localname2
= elem
->attributes
[i
]->localName
;
4360 const WS_XML_STRING
*ns2
= elem
->attributes
[i
]->ns
;
4362 if (cmp_name( localname
->bytes
, localname
->length
, localname2
->bytes
, localname2
->length
)) continue;
4363 if (!ns
->length
|| !cmp_name( ns
->bytes
, ns
->length
, ns2
->bytes
, ns2
->length
))
4369 if (!*found
) return S_OK
;
4370 return get_attribute_text( reader
, i
, ret
);
4372 case WS_ELEMENT_TYPE_MAPPING
:
4373 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
4374 case WS_ANY_ELEMENT_TYPE_MAPPING
:
4379 struct reader_pos pos
;
4382 if (!match_element( reader
->current
, localname
, ns
))
4387 save_reader_position( reader
, &pos
);
4388 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
4389 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
4391 restore_reader_position( reader
, &pos
);
4396 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
)
4401 return get_node_text( reader
, ret
);
4404 FIXME( "mapping %u not supported\n", mapping
);
4409 static HRESULT
text_to_bool( const WS_XML_TEXT
*text
, BOOL
*val
)
4413 switch (text
->textType
)
4415 case WS_XML_TEXT_TYPE_UTF8
:
4417 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
4418 hr
= str_to_bool( text_utf8
->value
.bytes
, text_utf8
->value
.length
, val
);
4421 case WS_XML_TEXT_TYPE_BOOL
:
4423 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
4424 *val
= text_bool
->value
;
4429 FIXME( "unhandled text type %u\n", text
->textType
);
4436 static HRESULT
read_type_bool( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4437 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4438 const WS_BOOL_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4439 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
4441 const WS_XML_TEXT
*text
;
4447 FIXME( "description not supported\n" );
4450 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
4451 if (*found
&& (hr
= text_to_bool( text
, &val
)) != S_OK
) return hr
;
4455 case WS_READ_REQUIRED_VALUE
:
4456 if (!*found
) return WS_E_INVALID_FORMAT
;
4459 case WS_READ_NILLABLE_VALUE
:
4460 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4464 case WS_READ_REQUIRED_POINTER
:
4465 if (!*found
) return WS_E_INVALID_FORMAT
;
4468 case WS_READ_OPTIONAL_POINTER
:
4469 case WS_READ_NILLABLE_POINTER
:
4471 BOOL
*heap_val
= NULL
;
4472 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4475 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4478 *(BOOL
**)ret
= heap_val
;
4482 FIXME( "read option %u not supported\n", option
);
4489 static HRESULT
text_to_int8( const WS_XML_TEXT
*text
, INT64
*val
)
4493 switch (text
->textType
)
4495 case WS_XML_TEXT_TYPE_UTF8
:
4497 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
4498 hr
= str_to_int64( text_utf8
->value
.bytes
, text_utf8
->value
.length
, MIN_INT8
, MAX_INT8
, val
);
4501 case WS_XML_TEXT_TYPE_INT32
:
4503 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
4504 if (text_int32
->value
< MIN_INT8
|| text_int32
->value
> MAX_INT8
) return WS_E_NUMERIC_OVERFLOW
;
4505 *val
= text_int32
->value
;
4510 FIXME( "unhandled text type %u\n", text
->textType
);
4517 static HRESULT
read_type_int8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4518 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4519 const WS_INT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4520 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
4522 const WS_XML_TEXT
*text
;
4528 FIXME( "description not supported\n" );
4531 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
4532 if (*found
&& (hr
= text_to_int8( text
, &val
)) != S_OK
) return hr
;
4536 case WS_READ_REQUIRED_VALUE
:
4537 if (!*found
) return WS_E_INVALID_FORMAT
;
4540 case WS_READ_NILLABLE_VALUE
:
4541 if (size
!= sizeof(INT8
)) return E_INVALIDARG
;
4545 case WS_READ_REQUIRED_POINTER
:
4546 if (!*found
) return WS_E_INVALID_FORMAT
;
4549 case WS_READ_OPTIONAL_POINTER
:
4550 case WS_READ_NILLABLE_POINTER
:
4552 INT8
*heap_val
= NULL
;
4553 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4556 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4559 *(INT8
**)ret
= heap_val
;
4563 FIXME( "read option %u not supported\n", option
);
4570 static HRESULT
text_to_int16( const WS_XML_TEXT
*text
, INT64
*val
)
4574 switch (text
->textType
)
4576 case WS_XML_TEXT_TYPE_UTF8
:
4578 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
4579 hr
= str_to_int64( text_utf8
->value
.bytes
, text_utf8
->value
.length
, MIN_INT16
, MAX_INT16
, val
);
4582 case WS_XML_TEXT_TYPE_INT32
:
4584 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
4585 if (text_int32
->value
< MIN_INT16
|| text_int32
->value
> MAX_INT16
) return WS_E_NUMERIC_OVERFLOW
;
4586 *val
= text_int32
->value
;
4591 FIXME( "unhandled text type %u\n", text
->textType
);
4598 static HRESULT
read_type_int16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4599 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4600 const WS_INT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4601 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
4603 const WS_XML_TEXT
*text
;
4609 FIXME( "description not supported\n" );
4612 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
4613 if (*found
&& (hr
= text_to_int16( text
, &val
)) != S_OK
) return hr
;
4617 case WS_READ_REQUIRED_VALUE
:
4618 if (!*found
) return WS_E_INVALID_FORMAT
;
4621 case WS_READ_NILLABLE_VALUE
:
4622 if (size
!= sizeof(INT16
)) return E_INVALIDARG
;
4623 *(INT16
*)ret
= val
;
4626 case WS_READ_REQUIRED_POINTER
:
4627 if (!*found
) return WS_E_INVALID_FORMAT
;
4630 case WS_READ_OPTIONAL_POINTER
:
4631 case WS_READ_NILLABLE_POINTER
:
4633 INT16
*heap_val
= NULL
;
4634 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4637 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4640 *(INT16
**)ret
= heap_val
;
4644 FIXME( "read option %u not supported\n", option
);
4651 static HRESULT
text_to_int32( const WS_XML_TEXT
*text
, INT64
*val
)
4655 switch (text
->textType
)
4657 case WS_XML_TEXT_TYPE_UTF8
:
4659 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
4660 hr
= str_to_int64( text_utf8
->value
.bytes
, text_utf8
->value
.length
, MIN_INT32
, MAX_INT32
, val
);
4663 case WS_XML_TEXT_TYPE_INT32
:
4665 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
4666 *val
= text_int32
->value
;
4671 FIXME( "unhandled text type %u\n", text
->textType
);
4678 static HRESULT
read_type_int32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4679 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4680 const WS_INT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4681 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
4683 const WS_XML_TEXT
*text
;
4689 FIXME( "description not supported\n" );
4692 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
4693 if (*found
&& (hr
= text_to_int32( text
, &val
)) != S_OK
) return hr
;
4697 case WS_READ_REQUIRED_VALUE
:
4698 if (!*found
) return WS_E_INVALID_FORMAT
;
4701 case WS_READ_NILLABLE_VALUE
:
4702 if (size
!= sizeof(INT32
)) return E_INVALIDARG
;
4703 *(INT32
*)ret
= val
;
4706 case WS_READ_REQUIRED_POINTER
:
4707 if (!*found
) return WS_E_INVALID_FORMAT
;
4710 case WS_READ_OPTIONAL_POINTER
:
4711 case WS_READ_NILLABLE_POINTER
:
4713 INT32
*heap_val
= NULL
;
4714 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4717 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4720 *(INT32
**)ret
= heap_val
;
4724 FIXME( "read option %u not supported\n", option
);
4731 static HRESULT
text_to_int64( const WS_XML_TEXT
*text
, INT64
*val
)
4735 switch (text
->textType
)
4737 case WS_XML_TEXT_TYPE_UTF8
:
4739 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
4740 hr
= str_to_int64( text_utf8
->value
.bytes
, text_utf8
->value
.length
, MIN_INT64
, MAX_INT64
, val
);
4743 case WS_XML_TEXT_TYPE_INT64
:
4745 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
4746 *val
= text_int64
->value
;
4751 FIXME( "unhandled text type %u\n", text
->textType
);
4758 static HRESULT
read_type_int64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4759 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4760 const WS_INT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4761 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
4763 const WS_XML_TEXT
*text
;
4769 FIXME( "description not supported\n" );
4772 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
4773 if (*found
&& (hr
= text_to_int64( text
, &val
)) != S_OK
) return hr
;
4777 case WS_READ_REQUIRED_VALUE
:
4778 if (!*found
) return WS_E_INVALID_FORMAT
;
4781 case WS_READ_NILLABLE_VALUE
:
4782 if (size
!= sizeof(val
)) return E_INVALIDARG
;
4783 *(INT64
*)ret
= val
;
4786 case WS_READ_REQUIRED_POINTER
:
4787 if (!*found
) return WS_E_INVALID_FORMAT
;
4790 case WS_READ_OPTIONAL_POINTER
:
4791 case WS_READ_NILLABLE_POINTER
:
4793 INT64
*heap_val
= NULL
;
4794 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4797 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4800 *(INT64
**)ret
= heap_val
;
4804 FIXME( "read option %u not supported\n", option
);
4811 static HRESULT
text_to_uint8( const WS_XML_TEXT
*text
, UINT64
*val
)
4815 switch (text
->textType
)
4817 case WS_XML_TEXT_TYPE_UTF8
:
4819 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
4820 hr
= str_to_uint64( text_utf8
->value
.bytes
, text_utf8
->value
.length
, MAX_UINT8
, val
);
4823 case WS_XML_TEXT_TYPE_UINT64
:
4825 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
4826 if (text_uint64
->value
> MAX_UINT8
) return WS_E_NUMERIC_OVERFLOW
;
4827 *val
= text_uint64
->value
;
4832 FIXME( "unhandled text type %u\n", text
->textType
);
4839 static HRESULT
read_type_uint8( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4840 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4841 const WS_UINT8_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4842 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
4844 const WS_XML_TEXT
*text
;
4850 FIXME( "description not supported\n" );
4853 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
4854 if (*found
&& (hr
= text_to_uint8( text
, &val
)) != S_OK
) return hr
;
4858 case WS_READ_REQUIRED_VALUE
:
4859 if (!*found
) return WS_E_INVALID_FORMAT
;
4862 case WS_READ_NILLABLE_VALUE
:
4863 if (size
!= sizeof(UINT8
)) return E_INVALIDARG
;
4864 *(UINT8
*)ret
= val
;
4867 case WS_READ_REQUIRED_POINTER
:
4868 if (!*found
) return WS_E_INVALID_FORMAT
;
4871 case WS_READ_OPTIONAL_POINTER
:
4872 case WS_READ_NILLABLE_POINTER
:
4874 UINT8
*heap_val
= NULL
;
4875 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4878 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4881 *(UINT8
**)ret
= heap_val
;
4885 FIXME( "read option %u not supported\n", option
);
4892 static HRESULT
text_to_uint16( const WS_XML_TEXT
*text
, UINT64
*val
)
4896 switch (text
->textType
)
4898 case WS_XML_TEXT_TYPE_UTF8
:
4900 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
4901 hr
= str_to_uint64( text_utf8
->value
.bytes
, text_utf8
->value
.length
, MAX_UINT16
, val
);
4904 case WS_XML_TEXT_TYPE_INT32
:
4906 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
4907 if (text_int32
->value
< 0 || text_int32
->value
> MAX_UINT16
) return WS_E_NUMERIC_OVERFLOW
;
4908 *val
= text_int32
->value
;
4912 case WS_XML_TEXT_TYPE_UINT64
:
4914 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
4915 if (text_uint64
->value
> MAX_UINT16
) return WS_E_NUMERIC_OVERFLOW
;
4916 *val
= text_uint64
->value
;
4921 FIXME( "unhandled text type %u\n", text
->textType
);
4928 static HRESULT
read_type_uint16( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
4929 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4930 const WS_UINT16_DESCRIPTION
*desc
, WS_READ_OPTION option
,
4931 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
4933 const WS_XML_TEXT
*text
;
4939 FIXME( "description not supported\n" );
4942 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
4943 if (*found
&& (hr
= text_to_uint16( text
, &val
)) != S_OK
) return hr
;
4947 case WS_READ_REQUIRED_VALUE
:
4948 if (!*found
) return WS_E_INVALID_FORMAT
;
4951 case WS_READ_NILLABLE_VALUE
:
4952 if (size
!= sizeof(UINT16
)) return E_INVALIDARG
;
4953 *(UINT16
*)ret
= val
;
4956 case WS_READ_REQUIRED_POINTER
:
4957 if (!*found
) return WS_E_INVALID_FORMAT
;
4960 case WS_READ_OPTIONAL_POINTER
:
4961 case WS_READ_NILLABLE_POINTER
:
4963 UINT16
*heap_val
= NULL
;
4964 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
4967 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
4970 *(UINT16
**)ret
= heap_val
;
4974 FIXME( "read option %u not supported\n", option
);
4981 static HRESULT
text_to_uint32( const WS_XML_TEXT
*text
, UINT64
*val
)
4985 switch (text
->textType
)
4987 case WS_XML_TEXT_TYPE_UTF8
:
4989 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
4990 hr
= str_to_uint64( text_utf8
->value
.bytes
, text_utf8
->value
.length
, MAX_UINT32
, val
);
4993 case WS_XML_TEXT_TYPE_INT32
:
4995 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
4996 if (text_int32
->value
< 0) return WS_E_NUMERIC_OVERFLOW
;
4997 *val
= text_int32
->value
;
5001 case WS_XML_TEXT_TYPE_INT64
:
5003 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
5004 if (text_int64
->value
< 0 || text_int64
->value
> MAX_UINT32
) return WS_E_NUMERIC_OVERFLOW
;
5005 *val
= text_int64
->value
;
5009 case WS_XML_TEXT_TYPE_UINT64
:
5011 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
5012 if (text_uint64
->value
> MAX_UINT32
) return WS_E_NUMERIC_OVERFLOW
;
5013 *val
= text_uint64
->value
;
5018 FIXME( "unhandled text type %u\n", text
->textType
);
5025 static HRESULT
read_type_uint32( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5026 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5027 const WS_UINT32_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5028 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5030 const WS_XML_TEXT
*text
;
5036 FIXME( "description not supported\n" );
5039 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5040 if (*found
&& (hr
= text_to_uint32( text
, &val
)) != S_OK
) return hr
;
5044 case WS_READ_REQUIRED_VALUE
:
5045 if (!*found
) return WS_E_INVALID_FORMAT
;
5048 case WS_READ_NILLABLE_VALUE
:
5049 if (size
!= sizeof(UINT32
)) return E_INVALIDARG
;
5050 *(UINT32
*)ret
= val
;
5053 case WS_READ_REQUIRED_POINTER
:
5054 if (!*found
) return WS_E_INVALID_FORMAT
;
5057 case WS_READ_OPTIONAL_POINTER
:
5058 case WS_READ_NILLABLE_POINTER
:
5060 UINT32
*heap_val
= NULL
;
5061 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5064 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5067 *(UINT32
**)ret
= heap_val
;
5071 FIXME( "read option %u not supported\n", option
);
5078 static HRESULT
text_to_uint64( const WS_XML_TEXT
*text
, UINT64
*val
)
5082 switch (text
->textType
)
5084 case WS_XML_TEXT_TYPE_UTF8
:
5086 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5087 hr
= str_to_uint64( text_utf8
->value
.bytes
, text_utf8
->value
.length
, MAX_UINT64
, val
);
5090 case WS_XML_TEXT_TYPE_INT32
:
5092 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
5093 if (text_int32
->value
< 0) return WS_E_NUMERIC_OVERFLOW
;
5094 *val
= text_int32
->value
;
5098 case WS_XML_TEXT_TYPE_INT64
:
5100 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
5101 if (text_int64
->value
< 0) return WS_E_NUMERIC_OVERFLOW
;
5102 *val
= text_int64
->value
;
5106 case WS_XML_TEXT_TYPE_UINT64
:
5108 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
5109 *val
= text_uint64
->value
;
5114 FIXME( "unhandled text type %u\n", text
->textType
);
5121 static HRESULT
read_type_uint64( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5122 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5123 const WS_UINT64_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5124 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5126 const WS_XML_TEXT
*text
;
5132 FIXME( "description not supported\n" );
5135 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5136 if (*found
&& (hr
= text_to_uint64( text
, &val
)) != S_OK
) return hr
;
5140 case WS_READ_REQUIRED_VALUE
:
5141 if (!*found
) return WS_E_INVALID_FORMAT
;
5144 case WS_READ_NILLABLE_VALUE
:
5145 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5146 *(UINT64
*)ret
= val
;
5149 case WS_READ_REQUIRED_POINTER
:
5150 if (!*found
) return WS_E_INVALID_FORMAT
;
5153 case WS_READ_OPTIONAL_POINTER
:
5154 case WS_READ_NILLABLE_POINTER
:
5156 UINT64
*heap_val
= NULL
;
5157 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5160 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5163 *(UINT64
**)ret
= heap_val
;
5167 FIXME( "read option %u not supported\n", option
);
5174 static HRESULT
text_to_float( const WS_XML_TEXT
*text
, float *val
)
5178 switch (text
->textType
)
5180 case WS_XML_TEXT_TYPE_UTF8
:
5182 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5183 hr
= str_to_float( text_utf8
->value
.bytes
, text_utf8
->value
.length
, val
);
5186 case WS_XML_TEXT_TYPE_FLOAT
:
5188 const WS_XML_FLOAT_TEXT
*text_float
= (const WS_XML_FLOAT_TEXT
*)text
;
5189 *val
= text_float
->value
;
5194 FIXME( "unhandled text type %u\n", text
->textType
);
5201 static HRESULT
read_type_float( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5202 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5203 const WS_FLOAT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5204 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5206 const WS_XML_TEXT
*text
;
5210 if (desc
) FIXME( "ignoring description\n" );
5212 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5213 if (*found
&& (hr
= text_to_float( text
, &val
)) != S_OK
) return hr
;
5217 case WS_READ_REQUIRED_VALUE
:
5218 if (!*found
) return WS_E_INVALID_FORMAT
;
5221 case WS_READ_NILLABLE_VALUE
:
5222 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5223 *(float *)ret
= val
;
5226 case WS_READ_REQUIRED_POINTER
:
5227 if (!*found
) return WS_E_INVALID_FORMAT
;
5230 case WS_READ_OPTIONAL_POINTER
:
5231 case WS_READ_NILLABLE_POINTER
:
5233 float *heap_val
= NULL
;
5234 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5237 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5240 *(float **)ret
= heap_val
;
5244 FIXME( "read option %u not supported\n", option
);
5251 static HRESULT
text_to_double( const WS_XML_TEXT
*text
, double *val
)
5255 switch (text
->textType
)
5257 case WS_XML_TEXT_TYPE_UTF8
:
5259 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5260 hr
= str_to_double( text_utf8
->value
.bytes
, text_utf8
->value
.length
, val
);
5263 case WS_XML_TEXT_TYPE_DOUBLE
:
5265 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
5266 *val
= text_double
->value
;
5271 FIXME( "unhandled text type %u\n", text
->textType
);
5278 static HRESULT
read_type_double( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5279 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5280 const WS_DOUBLE_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5281 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5283 const WS_XML_TEXT
*text
;
5287 if (desc
) FIXME( "ignoring description\n" );
5289 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5290 if (*found
&& (hr
= text_to_double( text
, &val
)) != S_OK
) return hr
;
5294 case WS_READ_REQUIRED_VALUE
:
5295 if (!*found
) return WS_E_INVALID_FORMAT
;
5298 case WS_READ_NILLABLE_VALUE
:
5299 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5300 *(double *)ret
= val
;
5303 case WS_READ_REQUIRED_POINTER
:
5304 if (!*found
) return WS_E_INVALID_FORMAT
;
5307 case WS_READ_OPTIONAL_POINTER
:
5308 case WS_READ_NILLABLE_POINTER
:
5310 double *heap_val
= NULL
;
5311 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5314 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5317 *(double **)ret
= heap_val
;
5321 FIXME( "read option %u not supported\n", option
);
5328 static HRESULT
text_to_wsz( const WS_XML_TEXT
*text
, WS_HEAP
*heap
, WCHAR
**ret
)
5330 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5333 assert( text
->textType
== WS_XML_TEXT_TYPE_UTF8
);
5334 len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
5335 if (!(*ret
= ws_alloc( heap
, (len
+ 1) * sizeof(WCHAR
) ))) return E_OUTOFMEMORY
;
5336 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, *ret
, len
);
5341 static HRESULT
read_type_wsz( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5342 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5343 const WS_WSZ_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5344 WS_HEAP
*heap
, WCHAR
**ret
, ULONG size
, BOOL
*found
)
5346 const WS_XML_TEXT
*text
;
5352 FIXME( "description not supported\n" );
5355 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5356 if (*found
&& (hr
= text_to_wsz( text
, heap
, &str
)) != S_OK
) return hr
;
5360 case WS_READ_REQUIRED_POINTER
:
5361 if (!str
&& !(str
= ws_alloc_zero( heap
, sizeof(*str
) ))) return WS_E_QUOTA_EXCEEDED
;
5364 case WS_READ_OPTIONAL_POINTER
:
5365 case WS_READ_NILLABLE_POINTER
:
5366 if (size
!= sizeof(str
)) return E_INVALIDARG
;
5371 FIXME( "read option %u not supported\n", option
);
5378 static HRESULT
get_enum_value( const WS_XML_TEXT
*text
, const WS_ENUM_DESCRIPTION
*desc
, int *ret
)
5380 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5383 assert( text
->textType
== WS_XML_TEXT_TYPE_UTF8
);
5384 for (i
= 0; i
< desc
->valueCount
; i
++)
5386 if (WsXmlStringEquals( &utf8
->value
, desc
->values
[i
].name
, NULL
) == S_OK
)
5388 *ret
= desc
->values
[i
].value
;
5392 return WS_E_INVALID_FORMAT
;
5395 static HRESULT
read_type_enum( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5396 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5397 const WS_ENUM_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5398 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5400 const WS_XML_TEXT
*text
;
5404 if (!desc
) return E_INVALIDARG
;
5406 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5407 if (*found
&& (hr
= get_enum_value( text
, desc
, &val
)) != S_OK
) return hr
;
5411 case WS_READ_REQUIRED_VALUE
:
5412 if (!*found
) return WS_E_INVALID_FORMAT
;
5415 case WS_READ_NILLABLE_VALUE
:
5416 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5420 case WS_READ_REQUIRED_POINTER
:
5421 if (!*found
) return WS_E_INVALID_FORMAT
;
5424 case WS_READ_OPTIONAL_POINTER
:
5425 case WS_READ_NILLABLE_POINTER
:
5427 int *heap_val
= NULL
;
5428 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5431 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5434 *(int **)ret
= heap_val
;
5438 FIXME( "read option %u not supported\n", option
);
5445 static HRESULT
text_to_datetime( const WS_XML_TEXT
*text
, WS_DATETIME
*val
)
5449 switch (text
->textType
)
5451 case WS_XML_TEXT_TYPE_UTF8
:
5453 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5454 hr
= str_to_datetime( text_utf8
->value
.bytes
, text_utf8
->value
.length
, val
);
5457 case WS_XML_TEXT_TYPE_DATETIME
:
5459 const WS_XML_DATETIME_TEXT
*text_datetime
= (const WS_XML_DATETIME_TEXT
*)text
;
5460 *val
= text_datetime
->value
;
5465 FIXME( "unhandled text type %u\n", text
->textType
);
5472 static HRESULT
read_type_datetime( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5473 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5474 const WS_DATETIME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5475 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5477 const WS_XML_TEXT
*text
;
5479 WS_DATETIME val
= {0, WS_DATETIME_FORMAT_UTC
};
5481 if (desc
) FIXME( "ignoring description\n" );
5483 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5484 if (*found
&& (hr
= text_to_datetime( text
, &val
)) != S_OK
) return hr
;
5488 case WS_READ_REQUIRED_VALUE
:
5489 if (!*found
) return WS_E_INVALID_FORMAT
;
5492 case WS_READ_NILLABLE_VALUE
:
5493 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5494 *(WS_DATETIME
*)ret
= val
;
5497 case WS_READ_REQUIRED_POINTER
:
5498 if (!*found
) return WS_E_INVALID_FORMAT
;
5501 case WS_READ_OPTIONAL_POINTER
:
5502 case WS_READ_NILLABLE_POINTER
:
5504 WS_DATETIME
*heap_val
= NULL
;
5505 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5508 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5511 *(WS_DATETIME
**)ret
= heap_val
;
5515 FIXME( "read option %u not supported\n", option
);
5522 static HRESULT
text_to_guid( const WS_XML_TEXT
*text
, GUID
*val
)
5526 switch (text
->textType
)
5528 case WS_XML_TEXT_TYPE_UTF8
:
5530 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5531 hr
= str_to_guid( text_utf8
->value
.bytes
, text_utf8
->value
.length
, val
);
5534 case WS_XML_TEXT_TYPE_GUID
:
5536 const WS_XML_GUID_TEXT
*text_guid
= (const WS_XML_GUID_TEXT
*)text
;
5537 *val
= text_guid
->value
;
5542 FIXME( "unhandled text type %u\n", text
->textType
);
5549 static HRESULT
read_type_guid( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5550 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5551 const WS_GUID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5552 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5554 const WS_XML_TEXT
*text
;
5558 if (desc
) FIXME( "ignoring description\n" );
5560 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5561 if (*found
&& (hr
= text_to_guid( text
, &val
)) != S_OK
) return hr
;
5565 case WS_READ_REQUIRED_VALUE
:
5566 if (!*found
) return WS_E_INVALID_FORMAT
;
5569 case WS_READ_NILLABLE_VALUE
:
5570 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5574 case WS_READ_REQUIRED_POINTER
:
5575 if (!*found
) return WS_E_INVALID_FORMAT
;
5578 case WS_READ_OPTIONAL_POINTER
:
5579 case WS_READ_NILLABLE_POINTER
:
5581 GUID
*heap_val
= NULL
;
5582 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5585 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5588 *(GUID
**)ret
= heap_val
;
5592 FIXME( "read option %u not supported\n", option
);
5599 static HRESULT
text_to_unique_id( const WS_XML_TEXT
*text
, WS_HEAP
*heap
, WS_UNIQUE_ID
*val
)
5603 switch (text
->textType
)
5605 case WS_XML_TEXT_TYPE_UTF8
:
5607 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5608 hr
= str_to_unique_id( text_utf8
->value
.bytes
, text_utf8
->value
.length
, heap
, val
);
5611 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
5613 const WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
5614 val
->guid
= text_unique_id
->value
;
5615 val
->uri
.length
= 0;
5616 val
->uri
.chars
= NULL
;
5621 FIXME( "unhandled text type %u\n", text
->textType
);
5628 static HRESULT
read_type_unique_id( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5629 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5630 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5631 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5633 const WS_XML_TEXT
*text
;
5634 WS_UNIQUE_ID val
= {{0}};
5637 if (desc
) FIXME( "ignoring description\n" );
5639 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5640 if (*found
&& (hr
= text_to_unique_id( text
, heap
, &val
)) != S_OK
) return hr
;
5644 case WS_READ_REQUIRED_VALUE
:
5645 if (!*found
) return WS_E_INVALID_FORMAT
;
5648 case WS_READ_NILLABLE_VALUE
:
5649 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5650 *(WS_UNIQUE_ID
*)ret
= val
;
5653 case WS_READ_REQUIRED_POINTER
:
5654 if (!*found
) return WS_E_INVALID_FORMAT
;
5657 case WS_READ_OPTIONAL_POINTER
:
5658 case WS_READ_NILLABLE_POINTER
:
5660 WS_UNIQUE_ID
*heap_val
= NULL
;
5661 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5664 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5667 *(WS_UNIQUE_ID
**)ret
= heap_val
;
5671 FIXME( "read option %u not supported\n", option
);
5678 static HRESULT
text_to_string( const WS_XML_TEXT
*text
, WS_HEAP
*heap
, WS_STRING
*val
)
5682 switch (text
->textType
)
5684 case WS_XML_TEXT_TYPE_UTF8
:
5686 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5687 hr
= str_to_string( text_utf8
->value
.bytes
, text_utf8
->value
.length
, heap
, val
);
5690 case WS_XML_TEXT_TYPE_UTF16
:
5692 const WS_XML_UTF16_TEXT
*text_utf16
= (const WS_XML_UTF16_TEXT
*)text
;
5693 if (!(val
->chars
= ws_alloc( heap
, text_utf16
->byteCount
))) return WS_E_QUOTA_EXCEEDED
;
5694 memcpy( val
->chars
, text_utf16
->bytes
, text_utf16
->byteCount
);
5695 val
->length
= text_utf16
->byteCount
/ sizeof(WCHAR
);
5700 FIXME( "unhandled text type %u\n", text
->textType
);
5707 static HRESULT
read_type_string( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5708 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5709 const WS_STRING_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5710 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5712 const WS_XML_TEXT
*text
;
5713 WS_STRING val
= {0};
5716 if (desc
) FIXME( "ignoring description\n" );
5718 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5719 if (*found
&& (hr
= text_to_string( text
, heap
, &val
)) != S_OK
) return hr
;
5723 case WS_READ_REQUIRED_VALUE
:
5724 case WS_READ_NILLABLE_VALUE
:
5725 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5726 *(WS_STRING
*)ret
= val
;
5729 case WS_READ_REQUIRED_POINTER
:
5731 WS_STRING
*heap_val
;
5732 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5733 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5735 *(WS_STRING
**)ret
= heap_val
;
5738 case WS_READ_OPTIONAL_POINTER
:
5739 case WS_READ_NILLABLE_POINTER
:
5741 WS_STRING
*heap_val
= NULL
;
5742 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5745 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5748 *(WS_STRING
**)ret
= heap_val
;
5752 FIXME( "read option %u not supported\n", option
);
5759 static HRESULT
text_to_bytes( const WS_XML_TEXT
*text
, WS_HEAP
*heap
, WS_BYTES
*val
)
5763 switch (text
->textType
)
5765 case WS_XML_TEXT_TYPE_UTF8
:
5767 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5768 hr
= str_to_bytes( text_utf8
->value
.bytes
, text_utf8
->value
.length
, heap
, val
);
5771 case WS_XML_TEXT_TYPE_BASE64
:
5773 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
5774 if (!(val
->bytes
= ws_alloc( heap
, text_base64
->length
))) return WS_E_QUOTA_EXCEEDED
;
5775 memcpy( val
->bytes
, text_base64
->bytes
, text_base64
->length
);
5776 val
->length
= text_base64
->length
;
5781 FIXME( "unhandled text type %u\n", text
->textType
);
5788 static HRESULT
read_type_bytes( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5789 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5790 const WS_BYTES_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5791 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5793 const WS_XML_TEXT
*text
;
5797 if (desc
) FIXME( "ignoring description\n" );
5799 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5800 if (*found
&& (hr
= text_to_bytes( text
, heap
, &val
)) != S_OK
) return hr
;
5804 case WS_READ_REQUIRED_VALUE
:
5805 case WS_READ_NILLABLE_VALUE
:
5806 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5807 *(WS_BYTES
*)ret
= val
;
5810 case WS_READ_REQUIRED_POINTER
:
5813 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5814 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5816 *(WS_BYTES
**)ret
= heap_val
;
5819 case WS_READ_OPTIONAL_POINTER
:
5820 case WS_READ_NILLABLE_POINTER
:
5822 WS_BYTES
*heap_val
= NULL
;
5823 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5826 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5829 *(WS_BYTES
**)ret
= heap_val
;
5833 FIXME( "read option %u not supported\n", option
);
5840 static HRESULT
text_to_xml_string( const WS_XML_TEXT
*text
, WS_HEAP
*heap
, WS_XML_STRING
*val
)
5842 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5843 assert( text
->textType
== WS_XML_TEXT_TYPE_UTF8
);
5844 return str_to_xml_string( utf8
->value
.bytes
, utf8
->value
.length
, heap
, val
);
5847 static HRESULT
read_type_xml_string( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5848 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5849 const WS_XML_STRING_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5850 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5852 const WS_XML_TEXT
*text
;
5853 WS_XML_STRING val
= {0};
5856 if (desc
) FIXME( "ignoring description\n" );
5858 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5859 if (*found
&& (hr
= text_to_xml_string( text
, heap
, &val
)) != S_OK
) return hr
;
5863 case WS_READ_REQUIRED_VALUE
:
5864 case WS_READ_NILLABLE_VALUE
:
5865 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5866 *(WS_XML_STRING
*)ret
= val
;
5869 case WS_READ_REQUIRED_POINTER
:
5871 WS_XML_STRING
*heap_val
;
5872 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5873 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5875 *(WS_XML_STRING
**)ret
= heap_val
;
5878 case WS_READ_OPTIONAL_POINTER
:
5879 case WS_READ_NILLABLE_POINTER
:
5881 WS_XML_STRING
*heap_val
= NULL
;
5882 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5885 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5888 *(WS_XML_STRING
**)ret
= heap_val
;
5892 FIXME( "read option %u not supported\n", option
);
5899 static HRESULT
text_to_qname( struct reader
*reader
, const WS_XML_TEXT
*text
, WS_HEAP
*heap
, WS_XML_QNAME
*val
)
5903 switch (text
->textType
)
5905 case WS_XML_TEXT_TYPE_UTF8
:
5907 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
5908 hr
= str_to_qname( reader
, text_utf8
->value
.bytes
, text_utf8
->value
.length
, heap
, NULL
,
5909 &val
->localName
, &val
->ns
);
5912 case WS_XML_TEXT_TYPE_QNAME
:
5914 const WS_XML_QNAME_TEXT
*text_qname
= (const WS_XML_QNAME_TEXT
*)text
;
5915 if ((hr
= copy_xml_string( heap
, text_qname
->localName
, &val
->localName
)) != S_OK
) return hr
;
5916 if ((hr
= copy_xml_string( heap
, text_qname
->ns
, &val
->ns
)) != S_OK
)
5918 ws_free( heap
, val
->localName
.bytes
, val
->localName
.length
);
5924 FIXME( "unhandled text type %u\n", text
->textType
);
5931 static HRESULT
read_type_qname( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5932 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5933 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5934 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5936 const WS_XML_TEXT
*text
;
5937 WS_XML_QNAME val
= {{0}};
5940 if (desc
) FIXME( "ignoring description\n" );
5942 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return WS_E_INVALID_FORMAT
;
5943 if ((hr
= read_startelement( reader
)) != S_OK
) return hr
;
5944 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_TEXT
) return WS_E_INVALID_FORMAT
;
5946 if ((hr
= get_text( reader
, mapping
, localname
, ns
, &text
, found
)) != S_OK
) return hr
;
5947 if (*found
&& (hr
= text_to_qname( reader
, text
, heap
, &val
)) != S_OK
) return hr
;
5951 case WS_READ_REQUIRED_VALUE
:
5952 if (!*found
) return WS_E_INVALID_FORMAT
;
5955 case WS_READ_NILLABLE_VALUE
:
5956 if (size
!= sizeof(val
)) return E_INVALIDARG
;
5957 *(WS_XML_QNAME
*)ret
= val
;
5960 case WS_READ_REQUIRED_POINTER
:
5961 if (!*found
) return WS_E_INVALID_FORMAT
;
5964 case WS_READ_OPTIONAL_POINTER
:
5965 case WS_READ_NILLABLE_POINTER
:
5967 WS_XML_QNAME
*heap_val
= NULL
;
5968 if (size
!= sizeof(heap_val
)) return E_INVALIDARG
;
5971 if (!(heap_val
= ws_alloc( heap
, sizeof(*heap_val
) ))) return WS_E_QUOTA_EXCEEDED
;
5974 *(WS_XML_QNAME
**)ret
= heap_val
;
5978 FIXME( "read option %u not supported\n", option
);
5985 static HRESULT
read_type_description( struct reader
*reader
, WS_TYPE_MAPPING mapping
,
5986 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
5987 const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
5988 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
5992 case WS_READ_REQUIRED_POINTER
:
5993 case WS_READ_OPTIONAL_POINTER
:
5995 if (size
!= sizeof(desc
)) return E_INVALIDARG
;
5996 *(const WS_STRUCT_DESCRIPTION
**)ret
= desc
;
6001 FIXME( "read option %u not supported\n", option
);
6008 static BOOL
is_empty_text_node( const struct node
*node
)
6010 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
6012 if (node_type( node
) != WS_XML_NODE_TYPE_TEXT
) return FALSE
;
6013 switch (text
->text
->textType
)
6015 case WS_XML_TEXT_TYPE_UTF8
:
6018 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
6019 for (i
= 0; i
< utf8
->value
.length
; i
++) if (!read_isspace( utf8
->value
.bytes
[i
] )) return FALSE
;
6022 case WS_XML_TEXT_TYPE_BASE64
:
6024 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
->text
;
6025 return !base64
->length
;
6027 case WS_XML_TEXT_TYPE_BOOL
:
6028 case WS_XML_TEXT_TYPE_INT32
:
6029 case WS_XML_TEXT_TYPE_INT64
:
6030 case WS_XML_TEXT_TYPE_UINT64
:
6031 case WS_XML_TEXT_TYPE_FLOAT
:
6032 case WS_XML_TEXT_TYPE_DOUBLE
:
6033 case WS_XML_TEXT_TYPE_DECIMAL
:
6034 case WS_XML_TEXT_TYPE_GUID
:
6035 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
6036 case WS_XML_TEXT_TYPE_DATETIME
:
6040 ERR( "unhandled text type %u\n", text
->text
->textType
);
6045 /* skips comment and empty text nodes */
6046 static HRESULT
read_type_next_node( struct reader
*reader
)
6051 WS_XML_NODE_TYPE type
;
6053 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
6054 type
= node_type( reader
->current
);
6055 if (type
== WS_XML_NODE_TYPE_COMMENT
||
6056 (type
== WS_XML_NODE_TYPE_TEXT
&& is_empty_text_node( reader
->current
))) continue;
6061 static HRESULT
read_type_next_element_node( struct reader
*reader
, const WS_XML_STRING
*localname
,
6062 const WS_XML_STRING
*ns
)
6064 struct reader_pos pos
;
6067 if (!localname
) return S_OK
; /* assume reader is already correctly positioned */
6068 if (reader
->current
== reader
->last
)
6071 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
6072 if (!found
) return WS_E_INVALID_FORMAT
;
6074 if (match_element( reader
->current
, localname
, ns
)) return S_OK
;
6076 save_reader_position( reader
, &pos
);
6077 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
6078 if (match_element( reader
->current
, localname
, ns
)) return S_OK
;
6079 restore_reader_position( reader
, &pos
);
6081 return WS_E_INVALID_FORMAT
;
6084 ULONG
get_type_size( WS_TYPE type
, const void *desc
)
6090 return sizeof(INT8
);
6093 case WS_UINT16_TYPE
:
6094 return sizeof(INT16
);
6098 case WS_UINT32_TYPE
:
6100 return sizeof(INT32
);
6103 case WS_UINT64_TYPE
:
6104 return sizeof(INT64
);
6107 return sizeof(float);
6109 case WS_DOUBLE_TYPE
:
6110 return sizeof(double);
6112 case WS_DATETIME_TYPE
:
6113 return sizeof(WS_DATETIME
);
6116 return sizeof(GUID
);
6118 case WS_UNIQUE_ID_TYPE
:
6119 return sizeof(WS_UNIQUE_ID
);
6121 case WS_STRING_TYPE
:
6122 return sizeof(WS_STRING
);
6125 return sizeof(WCHAR
*);
6128 return sizeof(WS_BYTES
);
6130 case WS_XML_STRING_TYPE
:
6131 return sizeof(WS_XML_STRING
);
6133 case WS_XML_QNAME_TYPE
:
6134 return sizeof(WS_XML_QNAME
);
6136 case WS_DESCRIPTION_TYPE
:
6137 return sizeof(WS_STRUCT_DESCRIPTION
*);
6139 case WS_STRUCT_TYPE
:
6141 const WS_STRUCT_DESCRIPTION
*desc_struct
= desc
;
6142 return desc_struct
->size
;
6146 const WS_UNION_DESCRIPTION
*desc_union
= desc
;
6147 return desc_union
->size
;
6149 case WS_ANY_ATTRIBUTES_TYPE
:
6153 ERR( "unhandled type %u\n", type
);
6158 static WS_READ_OPTION
get_field_read_option( WS_TYPE type
, ULONG options
)
6160 if (options
& WS_FIELD_POINTER
)
6162 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
6163 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
6164 return WS_READ_REQUIRED_POINTER
;
6175 case WS_UINT16_TYPE
:
6176 case WS_UINT32_TYPE
:
6177 case WS_UINT64_TYPE
:
6179 case WS_DOUBLE_TYPE
:
6180 case WS_DATETIME_TYPE
:
6182 case WS_UNIQUE_ID_TYPE
:
6183 case WS_STRING_TYPE
:
6185 case WS_XML_STRING_TYPE
:
6186 case WS_XML_QNAME_TYPE
:
6187 case WS_XML_BUFFER_TYPE
:
6188 case WS_STRUCT_TYPE
:
6191 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_READ_NILLABLE_VALUE
;
6192 return WS_READ_REQUIRED_VALUE
;
6195 case WS_DESCRIPTION_TYPE
:
6196 if (options
& WS_FIELD_NILLABLE
) return WS_READ_NILLABLE_POINTER
;
6197 if (options
& WS_FIELD_OPTIONAL
) return WS_READ_OPTIONAL_POINTER
;
6198 return WS_READ_REQUIRED_POINTER
;
6201 FIXME( "unhandled type %u\n", type
);
6206 static HRESULT
read_type_field( struct reader
*, const WS_STRUCT_DESCRIPTION
*, const WS_FIELD_DESCRIPTION
*,
6207 WS_HEAP
*, char *, ULONG
);
6209 static HRESULT
read_type_union( struct reader
*reader
, const WS_UNION_DESCRIPTION
*desc
, WS_HEAP
*heap
, void *ret
,
6210 ULONG size
, BOOL
*found
)
6212 struct reader_pos pos
;
6216 if (size
!= desc
->size
) return E_INVALIDARG
;
6218 save_reader_position( reader
, &pos
);
6219 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
6221 for (i
= 0; i
< desc
->fieldCount
; i
++)
6223 if ((*found
= match_element( reader
->current
, desc
->fields
[i
]->field
.localName
, desc
->fields
[i
]->field
.ns
)))
6229 *(int *)((char *)ret
+ desc
->enumOffset
) = desc
->noneEnumValue
;
6230 restore_reader_position( reader
, &pos
);
6234 ULONG offset
= desc
->fields
[i
]->field
.offset
;
6235 if ((hr
= read_type_field( reader
, NULL
, &desc
->fields
[i
]->field
, heap
, ret
, offset
)) != S_OK
) return hr
;
6236 *(int *)((char *)ret
+ desc
->enumOffset
) = desc
->fields
[i
]->value
;
6242 static HRESULT
read_type( struct reader
*, WS_TYPE_MAPPING
, WS_TYPE
, const WS_XML_STRING
*,
6243 const WS_XML_STRING
*, const void *, WS_READ_OPTION
, WS_HEAP
*,
6244 void *, ULONG
, BOOL
* );
6246 static HRESULT
read_type_array( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
,
6247 void **ret
, ULONG
*count
)
6250 ULONG item_size
, nb_items
= 0, nb_allocated
= 1, offset
= 0;
6251 WS_READ_OPTION option
;
6255 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
6257 /* wrapper element */
6258 if (desc
->localName
&& ((hr
= read_type_next_element_node( reader
, desc
->localName
, desc
->ns
)) != S_OK
))
6261 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
6262 item_size
= get_type_size( desc
->type
, desc
->typeDescription
);
6264 item_size
= sizeof(void *);
6266 if (!(buf
= ws_alloc_zero( heap
, item_size
))) return WS_E_QUOTA_EXCEEDED
;
6269 if (nb_items
>= nb_allocated
)
6271 SIZE_T old_size
= nb_allocated
* item_size
, new_size
= old_size
* 2;
6272 if (!(buf
= ws_realloc_zero( heap
, buf
, old_size
, new_size
))) return WS_E_QUOTA_EXCEEDED
;
6276 if (desc
->type
== WS_UNION_TYPE
)
6278 hr
= read_type_union( reader
, desc
->typeDescription
, heap
, buf
+ offset
, item_size
, &found
);
6281 ws_free( heap
, buf
, nb_allocated
* item_size
);
6288 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->itemLocalName
, desc
->itemNs
,
6289 desc
->typeDescription
, option
, heap
, buf
+ offset
, item_size
, &found
);
6290 if (hr
== WS_E_INVALID_FORMAT
) break;
6293 ws_free( heap
, buf
, nb_allocated
* item_size
);
6298 offset
+= item_size
;
6302 if (desc
->localName
&& ((hr
= read_type_next_node( reader
)) != S_OK
)) return hr
;
6304 if (desc
->itemRange
&& (nb_items
< desc
->itemRange
->minItemCount
|| nb_items
> desc
->itemRange
->maxItemCount
))
6306 TRACE( "number of items %lu out of range (%lu-%lu)\n", nb_items
, desc
->itemRange
->minItemCount
,
6307 desc
->itemRange
->maxItemCount
);
6308 ws_free( heap
, buf
, nb_allocated
* item_size
);
6309 return WS_E_INVALID_FORMAT
;
6318 static HRESULT
read_type_text( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
,
6319 WS_READ_OPTION option
, WS_HEAP
*heap
, void *ret
, ULONG size
)
6321 struct reader_pos pos
;
6325 if (reader
->current
== reader
->last
)
6327 if ((hr
= read_to_startelement( reader
, &found
)) != S_OK
) return hr
;
6328 if (!found
) return WS_E_INVALID_FORMAT
;
6331 save_reader_position( reader
, &pos
);
6332 if ((hr
= read_next_node( reader
)) != S_OK
) return hr
;
6333 hr
= read_type( reader
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, NULL
, NULL
,
6334 desc
->typeDescription
, option
, heap
, ret
, size
, &found
);
6335 if (hr
== S_OK
&& !found
) restore_reader_position( reader
, &pos
);
6339 static HRESULT
read_type_field( struct reader
*reader
, const WS_STRUCT_DESCRIPTION
*desc_struct
,
6340 const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
, char *buf
, ULONG offset
)
6343 WS_READ_OPTION option
;
6348 if (!desc
) return E_INVALIDARG
;
6349 if (desc
->options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
6351 FIXME( "options %#lx not supported\n", desc
->options
);
6354 if (!(option
= get_field_read_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
6356 if (option
== WS_READ_REQUIRED_VALUE
|| option
== WS_READ_NILLABLE_VALUE
)
6357 size
= get_type_size( desc
->type
, desc
->typeDescription
);
6359 size
= sizeof(void *);
6362 switch (desc
->mapping
)
6364 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING
:
6365 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
6366 desc_struct
, option
, heap
, ptr
, size
, &found
);
6369 case WS_ATTRIBUTE_FIELD_MAPPING
:
6370 hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
6371 desc
->typeDescription
, option
, heap
, ptr
, size
, &found
);
6374 case WS_ELEMENT_FIELD_MAPPING
:
6375 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->localName
, desc
->ns
,
6376 desc
->typeDescription
, option
, heap
, ptr
, size
, &found
);
6379 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
6381 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
||
6382 (desc
->options
& (WS_FIELD_POINTER
|WS_FIELD_NILLABLE
))) return E_INVALIDARG
;
6383 hr
= read_type_union( reader
, desc
->typeDescription
, heap
, ptr
, size
, &found
);
6386 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
6387 case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING
:
6390 hr
= read_type_array( reader
, desc
, heap
, (void **)ptr
, &count
);
6391 if (hr
== S_OK
) *(ULONG
*)(buf
+ desc
->countOffset
) = count
;
6394 case WS_TEXT_FIELD_MAPPING
:
6395 hr
= read_type_text( reader
, desc
, option
, heap
, ptr
, size
);
6399 FIXME( "unhandled field mapping %u\n", desc
->mapping
);
6403 if (hr
== WS_E_INVALID_FORMAT
)
6407 case WS_READ_REQUIRED_VALUE
:
6408 case WS_READ_REQUIRED_POINTER
:
6409 return WS_E_INVALID_FORMAT
;
6411 case WS_READ_NILLABLE_VALUE
:
6412 if (desc
->defaultValue
) memcpy( ptr
, desc
->defaultValue
->value
, desc
->defaultValue
->valueSize
);
6415 case WS_READ_OPTIONAL_POINTER
:
6416 case WS_READ_NILLABLE_POINTER
:
6417 *(void **)ptr
= NULL
;
6421 ERR( "unhandled option %u\n", option
);
6429 static HRESULT
read_type_struct( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
6430 const WS_XML_STRING
*ns
, const WS_STRUCT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
6431 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
6437 if (!desc
) return E_INVALIDARG
;
6438 if (desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
6440 FIXME( "struct options %#lx not supported\n",
6441 desc
->structOptions
& ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
);
6446 case WS_READ_REQUIRED_POINTER
:
6447 case WS_READ_OPTIONAL_POINTER
:
6448 case WS_READ_NILLABLE_POINTER
:
6449 if (size
!= sizeof(void *)) return E_INVALIDARG
;
6450 if (!(buf
= ws_alloc_zero( heap
, desc
->size
))) return WS_E_QUOTA_EXCEEDED
;
6453 case WS_READ_REQUIRED_VALUE
:
6454 case WS_READ_NILLABLE_VALUE
:
6455 if (size
!= desc
->size
) return E_INVALIDARG
;
6460 FIXME( "unhandled read option %u\n", option
);
6464 for (i
= 0; i
< desc
->fieldCount
; i
++)
6466 offset
= desc
->fields
[i
]->offset
;
6467 if ((hr
= read_type_field( reader
, desc
, desc
->fields
[i
], heap
, buf
, offset
)) != S_OK
) break;
6472 case WS_READ_REQUIRED_POINTER
:
6475 ws_free( heap
, buf
, desc
->size
);
6478 *(char **)ret
= buf
;
6481 case WS_READ_OPTIONAL_POINTER
:
6482 case WS_READ_NILLABLE_POINTER
:
6483 if (is_nil_value( buf
, desc
->size
))
6485 ws_free( heap
, buf
, desc
->size
);
6488 *(char **)ret
= buf
;
6491 case WS_READ_REQUIRED_VALUE
:
6492 case WS_READ_NILLABLE_VALUE
:
6493 if (hr
!= S_OK
) return hr
;
6497 ERR( "unhandled read option %u\n", option
);
6501 if (desc
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
6503 struct node
*parent
= find_parent( reader
);
6504 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
6511 static HRESULT
read_type_fault( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
6512 const WS_XML_STRING
*ns
, const WS_FAULT_DESCRIPTION
*desc
, WS_READ_OPTION option
,
6513 WS_HEAP
*heap
, void *ret
, ULONG size
, BOOL
*found
)
6515 static const WS_XML_STRING faultcode
= {9, (BYTE
*)"faultcode"}, faultstring
= {11, (BYTE
*)"faultstring"};
6516 static const WS_XML_STRING faultactor
= {10, (BYTE
*)"faultactor"}, detail
= {6, (BYTE
*)"detail"};
6518 const struct node
*root
= reader
->current
;
6522 if (mapping
!= WS_ELEMENT_TYPE_MAPPING
|| !desc
|| !ret
)
6523 return E_INVALIDARG
;
6524 if (desc
->envelopeVersion
< WS_ENVELOPE_VERSION_SOAP_1_1
|| desc
->envelopeVersion
>= WS_ENVELOPE_VERSION_NONE
)
6525 return E_INVALIDARG
;
6526 else if (desc
->envelopeVersion
!= WS_ENVELOPE_VERSION_SOAP_1_1
)
6528 FIXME( "unhandled envelopeVersion %u\n", desc
->envelopeVersion
);
6534 case WS_READ_REQUIRED_VALUE
:
6535 if (size
!= sizeof(*fault
))
6536 return E_INVALIDARG
;
6538 memset( fault
, 0, sizeof(*fault
) );
6541 case WS_READ_REQUIRED_POINTER
:
6542 case WS_READ_OPTIONAL_POINTER
:
6543 case WS_READ_NILLABLE_POINTER
:
6544 if (size
!= sizeof(void *))
6545 return E_INVALIDARG
;
6546 if (!(fault
= ws_alloc_zero( heap
, sizeof(*fault
) )))
6547 return WS_E_QUOTA_EXCEEDED
;
6550 case WS_READ_NILLABLE_VALUE
:
6551 return E_INVALIDARG
;
6554 FIXME( "unhandled read option %u\n", option
);
6558 if ((hr
= read_type_next_node( reader
)) != S_OK
) goto done
;
6561 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
&& reader
->current
->parent
== root
)
6564 if (match_element( reader
->current
, &faultcode
, ns
))
6568 hr
= WS_E_INVALID_FORMAT
;
6571 if (!(fault
->code
= ws_alloc_zero( heap
, sizeof(*fault
->code
) )))
6573 hr
= WS_E_QUOTA_EXCEEDED
;
6576 if ((hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, WS_XML_QNAME_TYPE
, NULL
, NULL
,
6577 NULL
, WS_READ_REQUIRED_VALUE
, heap
, &fault
->code
->value
,
6578 sizeof(fault
->code
->value
), found
)) != S_OK
)
6582 else if (match_element( reader
->current
, &faultstring
, ns
))
6586 hr
= WS_E_INVALID_FORMAT
;
6589 if (!(fault
->reasons
= ws_alloc_zero( heap
, sizeof(*fault
->reasons
) )))
6591 hr
= WS_E_QUOTA_EXCEEDED
;
6594 fault
->reasonCount
= 1;
6595 /* FIXME: parse optional xml:lang attribute */
6596 if ((hr
= read_next_node( reader
)) != S_OK
||
6597 (hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, WS_STRING_TYPE
, NULL
, NULL
,
6598 NULL
, WS_READ_REQUIRED_VALUE
, heap
, &fault
->reasons
->text
,
6599 sizeof(fault
->reasons
->text
), found
)) != S_OK
)
6602 else if (match_element( reader
->current
, &faultactor
, ns
))
6604 if (fault
->actor
.length
> 0)
6606 hr
= WS_E_INVALID_FORMAT
;
6609 if ((hr
= read_next_node( reader
)) != S_OK
||
6610 (hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, WS_STRING_TYPE
, NULL
, NULL
,
6611 NULL
, WS_READ_REQUIRED_VALUE
, heap
, &fault
->actor
,
6612 sizeof(fault
->actor
), found
)) != S_OK
)
6615 else if (match_element( reader
->current
, &detail
, ns
))
6619 hr
= WS_E_INVALID_FORMAT
;
6622 if ((hr
= WsReadXmlBuffer( (WS_XML_READER
*)reader
, heap
, &fault
->detail
, NULL
)) != S_OK
)
6625 else if ((hr
= read_type_next_node( reader
)) != S_OK
)
6630 if ((!fault
->code
|| !fault
->reasons
) && hr
== S_OK
)
6631 hr
= WS_E_INVALID_FORMAT
;
6635 free_fault_fields( heap
, fault
);
6639 case WS_READ_REQUIRED_VALUE
:
6640 case WS_READ_REQUIRED_POINTER
:
6641 memset( fault
, 0, sizeof(*fault
) );
6644 case WS_READ_OPTIONAL_POINTER
:
6645 case WS_READ_NILLABLE_POINTER
:
6646 if (hr
== WS_E_INVALID_FORMAT
&& is_nil_value( (const char *)fault
, sizeof(*fault
) ))
6648 ws_free( heap
, fault
, sizeof(*fault
) );
6653 memset( fault
, 0, sizeof(*fault
) );
6657 ERR( "unhandled option %u\n", option
);
6662 if (option
!= WS_READ_REQUIRED_VALUE
)
6663 *(WS_FAULT
**)ret
= fault
;
6669 static HRESULT
start_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
, const WS_XML_STRING
*localname
,
6670 const WS_XML_STRING
*ns
)
6674 case WS_ELEMENT_TYPE_MAPPING
:
6675 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
6676 return read_type_next_element_node( reader
, localname
, ns
);
6678 case WS_ANY_ELEMENT_TYPE_MAPPING
:
6679 case WS_ATTRIBUTE_TYPE_MAPPING
:
6683 FIXME( "unhandled mapping %u\n", mapping
);
6688 static HRESULT
read_type_endelement_node( struct reader
*reader
)
6690 const struct node
*parent
= find_parent( reader
);
6695 if ((hr
= read_type_next_node( reader
)) != S_OK
) return hr
;
6696 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_END_ELEMENT
&& reader
->current
->parent
== parent
)
6700 if (read_end_of_data( reader
) || !(parent
->flags
& NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
)) break;
6703 return WS_E_INVALID_FORMAT
;
6706 static HRESULT
end_mapping( struct reader
*reader
, WS_TYPE_MAPPING mapping
)
6710 case WS_ELEMENT_TYPE_MAPPING
:
6711 return read_type_endelement_node( reader
);
6713 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
6714 return read_type_next_node( reader
);
6716 case WS_ATTRIBUTE_TYPE_MAPPING
:
6722 static BOOL
is_true_text( const WS_XML_TEXT
*text
)
6724 switch (text
->textType
)
6726 case WS_XML_TEXT_TYPE_UTF8
:
6728 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
6729 if (text_utf8
->value
.length
== 4 && !memcmp( text_utf8
->value
.bytes
, "true", 4 )) return TRUE
;
6732 case WS_XML_TEXT_TYPE_BOOL
:
6734 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
6735 return text_bool
->value
;
6738 ERR( "unhandled text type %u\n", text
->textType
);
6743 static HRESULT
is_nil_element( const WS_XML_ELEMENT_NODE
*elem
)
6745 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
6746 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
6749 for (i
= 0; i
< elem
->attributeCount
; i
++)
6751 if (elem
->attributes
[i
]->isXmlNs
) continue;
6752 if (WsXmlStringEquals( elem
->attributes
[i
]->localName
, &localname
, NULL
) == S_OK
&&
6753 WsXmlStringEquals( elem
->attributes
[i
]->ns
, &ns
, NULL
) == S_OK
&&
6754 is_true_text( elem
->attributes
[i
]->value
)) return TRUE
;
6759 static HRESULT
read_type( struct reader
*reader
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
6760 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
, const void *desc
,
6761 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
, BOOL
*found
)
6765 if ((hr
= start_mapping( reader
, mapping
, localname
, ns
)) != S_OK
) return hr
;
6767 if (mapping
== WS_ELEMENT_TYPE_MAPPING
&& is_nil_element( &reader
->current
->hdr
))
6769 if (option
!= WS_READ_NILLABLE_POINTER
&& option
!= WS_READ_NILLABLE_VALUE
) return WS_E_INVALID_FORMAT
;
6771 return end_mapping( reader
, mapping
);
6777 hr
= read_type_bool( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6781 hr
= read_type_int8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6785 hr
= read_type_int16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6789 hr
= read_type_int32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6793 hr
= read_type_int64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6797 hr
= read_type_uint8( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6800 case WS_UINT16_TYPE
:
6801 hr
= read_type_uint16( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6804 case WS_UINT32_TYPE
:
6805 hr
= read_type_uint32( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6808 case WS_UINT64_TYPE
:
6809 hr
= read_type_uint64( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6813 hr
= read_type_float( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6816 case WS_DOUBLE_TYPE
:
6817 hr
= read_type_double( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6820 case WS_DATETIME_TYPE
:
6821 hr
= read_type_datetime( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6825 hr
= read_type_guid( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6828 case WS_UNIQUE_ID_TYPE
:
6829 hr
= read_type_unique_id( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6832 case WS_STRING_TYPE
:
6833 hr
= read_type_string( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6837 hr
= read_type_wsz( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6841 hr
= read_type_bytes( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6844 case WS_XML_STRING_TYPE
:
6845 hr
= read_type_xml_string( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6848 case WS_XML_QNAME_TYPE
:
6849 hr
= read_type_qname( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6852 case WS_DESCRIPTION_TYPE
:
6853 hr
= read_type_description( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6856 case WS_STRUCT_TYPE
:
6857 hr
= read_type_struct( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6861 hr
= read_type_fault( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6865 hr
= read_type_enum( reader
, mapping
, localname
, ns
, desc
, option
, heap
, value
, size
, found
);
6869 FIXME( "type %u not supported\n", type
);
6873 if (hr
!= S_OK
) return hr
;
6874 return end_mapping( reader
, mapping
);
6877 /**************************************************************************
6878 * WsReadType [webservices.@]
6880 HRESULT WINAPI
WsReadType( WS_XML_READER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
6881 const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
6882 ULONG size
, WS_ERROR
*error
)
6884 struct reader
*reader
= (struct reader
*)handle
;
6888 TRACE( "%p %u %u %p %#x %p %p %lu %p\n", handle
, mapping
, type
, desc
, option
, heap
, value
,
6890 if (error
) FIXME( "ignoring error parameter\n" );
6892 if (!reader
|| !value
) return E_INVALIDARG
;
6894 EnterCriticalSection( &reader
->cs
);
6896 if (reader
->magic
!= READER_MAGIC
)
6898 LeaveCriticalSection( &reader
->cs
);
6899 return E_INVALIDARG
;
6902 if ((hr
= read_type( reader
, mapping
, type
, NULL
, NULL
, desc
, option
, heap
, value
, size
, &found
)) == S_OK
)
6906 case WS_ELEMENT_TYPE_MAPPING
:
6907 hr
= read_node( reader
);
6913 if (hr
== S_OK
&& !read_end_of_data( reader
)) hr
= WS_E_INVALID_FORMAT
;
6916 LeaveCriticalSection( &reader
->cs
);
6917 TRACE( "returning %#lx\n", hr
);
6921 HRESULT
read_header( WS_XML_READER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
6922 WS_TYPE type
, const void *desc
, WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
,
6925 struct reader
*reader
= (struct reader
*)handle
;
6929 EnterCriticalSection( &reader
->cs
);
6931 if (reader
->magic
!= READER_MAGIC
)
6933 LeaveCriticalSection( &reader
->cs
);
6934 return E_INVALIDARG
;
6937 hr
= read_type( reader
, WS_ELEMENT_CONTENT_TYPE_MAPPING
, type
, localname
, ns
, desc
, option
, heap
,
6938 value
, size
, &found
);
6940 LeaveCriticalSection( &reader
->cs
);
6944 /**************************************************************************
6945 * WsReadElement [webservices.@]
6947 HRESULT WINAPI
WsReadElement( WS_XML_READER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
6948 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
6951 struct reader
*reader
= (struct reader
*)handle
;
6955 TRACE( "%p %p %#x %p %p %lu %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
6956 if (error
) FIXME( "ignoring error parameter\n" );
6958 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
6960 EnterCriticalSection( &reader
->cs
);
6962 if (reader
->magic
!= READER_MAGIC
)
6964 LeaveCriticalSection( &reader
->cs
);
6965 return E_INVALIDARG
;
6968 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->elementLocalName
,
6969 desc
->elementNs
, desc
->typeDescription
, option
, heap
, value
, size
, &found
);
6971 LeaveCriticalSection( &reader
->cs
);
6972 TRACE( "returning %#lx\n", hr
);
6976 /**************************************************************************
6977 * WsReadValue [webservices.@]
6979 HRESULT WINAPI
WsReadValue( WS_XML_READER
*handle
, WS_VALUE_TYPE value_type
, void *value
, ULONG size
,
6982 struct reader
*reader
= (struct reader
*)handle
;
6983 WS_TYPE type
= map_value_type( value_type
);
6987 TRACE( "%p %u %p %lu %p\n", handle
, type
, value
, size
, error
);
6988 if (error
) FIXME( "ignoring error parameter\n" );
6990 if (!reader
|| !value
|| type
== ~0u) return E_INVALIDARG
;
6992 EnterCriticalSection( &reader
->cs
);
6994 if (reader
->magic
!= READER_MAGIC
)
6996 LeaveCriticalSection( &reader
->cs
);
6997 return E_INVALIDARG
;
7000 hr
= read_type( reader
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, NULL
, NULL
, WS_READ_REQUIRED_VALUE
,
7001 NULL
, value
, size
, &found
);
7003 LeaveCriticalSection( &reader
->cs
);
7004 TRACE( "returning %#lx\n", hr
);
7008 /**************************************************************************
7009 * WsReadAttribute [webservices.@]
7011 HRESULT WINAPI
WsReadAttribute( WS_XML_READER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
7012 WS_READ_OPTION option
, WS_HEAP
*heap
, void *value
, ULONG size
,
7015 struct reader
*reader
= (struct reader
*)handle
;
7019 TRACE( "%p %p %#x %p %p %lu %p\n", handle
, desc
, option
, heap
, value
, size
, error
);
7020 if (error
) FIXME( "ignoring error parameter\n" );
7022 if (!reader
|| !desc
|| !value
) return E_INVALIDARG
;
7024 EnterCriticalSection( &reader
->cs
);
7026 if (reader
->magic
!= READER_MAGIC
)
7028 LeaveCriticalSection( &reader
->cs
);
7029 return E_INVALIDARG
;
7032 if (!reader
->input_type
) hr
= WS_E_INVALID_OPERATION
;
7033 else hr
= read_type( reader
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->attributeLocalName
,
7034 desc
->attributeNs
, desc
->typeDescription
, option
, heap
, value
, size
, &found
);
7036 LeaveCriticalSection( &reader
->cs
);
7037 TRACE( "returning %#lx\n", hr
);
7041 static inline BOOL
is_utf8( const unsigned char *data
, ULONG size
, ULONG
*offset
)
7043 static const char bom
[] = {0xef,0xbb,0xbf};
7044 return (size
>= sizeof(bom
) && !memcmp( data
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
7045 (size
> 2 && !(*offset
= 0));
7048 static inline BOOL
is_utf16le( const unsigned char *data
, ULONG size
, ULONG
*offset
)
7050 static const char bom
[] = {0xff,0xfe};
7051 return (size
>= sizeof(bom
) && !memcmp( data
, bom
, sizeof(bom
) ) && (*offset
= sizeof(bom
))) ||
7052 (size
>= 4 && data
[0] == '<' && !data
[1] && !(*offset
= 0));
7055 static WS_CHARSET
detect_charset( const unsigned char *data
, ULONG size
, ULONG
*offset
)
7059 /* FIXME: parse xml declaration */
7061 if (is_utf16le( data
, size
, offset
)) ret
= WS_CHARSET_UTF16LE
;
7062 else if (is_utf8( data
, size
, offset
)) ret
= WS_CHARSET_UTF8
;
7065 FIXME( "charset not recognized\n" );
7069 TRACE( "detected charset %u\n", ret
);
7073 static HRESULT
utf16le_to_utf8( const unsigned char *data
, ULONG size
, unsigned char **buf
, ULONG
*buflen
)
7075 if (size
% sizeof(WCHAR
)) return E_INVALIDARG
;
7076 *buflen
= WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)data
, size
/ sizeof(WCHAR
), NULL
, 0, NULL
, NULL
);
7077 if (!(*buf
= malloc( *buflen
))) return E_OUTOFMEMORY
;
7078 WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)data
, size
/ sizeof(WCHAR
), (char *)*buf
, *buflen
, NULL
, NULL
);
7082 static HRESULT
set_input_buffer( struct reader
*reader
, const unsigned char *data
, ULONG size
)
7084 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
7085 reader
->input_buf
= NULL
;
7087 if (reader
->input_enc
== WS_XML_READER_ENCODING_TYPE_TEXT
&& reader
->input_charset
== WS_CHARSET_UTF16LE
)
7093 if ((hr
= utf16le_to_utf8( data
, size
, &buf
, &buflen
)) != S_OK
) return hr
;
7094 free( reader
->input_conv
);
7095 reader
->read_bufptr
= reader
->input_conv
= buf
;
7096 reader
->read_size
= reader
->input_size
= buflen
;
7100 reader
->read_bufptr
= data
;
7101 reader
->read_size
= reader
->input_size
= size
;
7104 reader
->read_pos
= 0;
7105 reader
->text_conv_offset
= 0;
7109 static void set_input_stream( struct reader
*reader
, WS_READ_CALLBACK callback
, void *state
)
7111 reader
->input_type
= WS_XML_READER_INPUT_TYPE_STREAM
;
7112 reader
->input_cb
= callback
;
7113 reader
->input_cb_state
= state
;
7114 reader
->input_buf
= NULL
;
7115 reader
->input_size
= STREAM_BUFSIZE
;
7117 if (reader
->read_pos
>= reader
->read_size
) reader
->read_size
= 0;
7120 memmove( reader
->stream_buf
, reader
->stream_buf
+ reader
->read_pos
, reader
->read_size
- reader
->read_pos
);
7121 reader
->read_size
-= reader
->read_pos
;
7123 reader
->read_pos
= 0;
7124 reader
->read_bufptr
= reader
->stream_buf
;
7125 reader
->text_conv_offset
= 0;
7128 /**************************************************************************
7129 * WsSetInput [webservices.@]
7131 HRESULT WINAPI
WsSetInput( WS_XML_READER
*handle
, const WS_XML_READER_ENCODING
*encoding
,
7132 const WS_XML_READER_INPUT
*input
, const WS_XML_READER_PROPERTY
*properties
,
7133 ULONG count
, WS_ERROR
*error
)
7135 struct reader
*reader
= (struct reader
*)handle
;
7137 ULONG i
, offset
= 0;
7140 TRACE( "%p %p %p %p %lu %p\n", handle
, encoding
, input
, properties
, count
, error
);
7141 if (error
) FIXME( "ignoring error parameter\n" );
7143 if (!reader
) return E_INVALIDARG
;
7145 EnterCriticalSection( &reader
->cs
);
7147 if (reader
->magic
!= READER_MAGIC
)
7149 LeaveCriticalSection( &reader
->cs
);
7150 return E_INVALIDARG
;
7153 for (i
= 0; i
< count
; i
++)
7155 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
7156 properties
[i
].valueSize
);
7157 if (hr
!= S_OK
) goto done
;
7160 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
7162 switch (encoding
->encodingType
)
7164 case WS_XML_READER_ENCODING_TYPE_TEXT
:
7166 if (input
->inputType
== WS_XML_READER_INPUT_TYPE_BUFFER
)
7168 const WS_XML_READER_TEXT_ENCODING
*text
= (const WS_XML_READER_TEXT_ENCODING
*)encoding
;
7169 const WS_XML_READER_BUFFER_INPUT
*buf
= (const WS_XML_READER_BUFFER_INPUT
*)input
;
7170 if (text
->charSet
!= WS_CHARSET_AUTO
) reader
->input_charset
= text
->charSet
;
7171 else reader
->input_charset
= detect_charset( buf
->encodedData
, buf
->encodedDataSize
, &offset
);
7174 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_TEXT
;
7177 case WS_XML_READER_ENCODING_TYPE_BINARY
:
7179 const WS_XML_READER_BINARY_ENCODING
*bin
= (const WS_XML_READER_BINARY_ENCODING
*)encoding
;
7180 reader
->input_enc
= WS_XML_READER_ENCODING_TYPE_BINARY
;
7181 reader
->input_charset
= 0;
7182 reader
->dict_static
= bin
->staticDictionary
? bin
->staticDictionary
: &dict_builtin_static
.dict
;
7183 reader
->dict
= bin
->dynamicDictionary
? bin
->dynamicDictionary
: &dict_builtin
.dict
;
7187 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
7192 switch (input
->inputType
)
7194 case WS_XML_READER_INPUT_TYPE_BUFFER
:
7196 const WS_XML_READER_BUFFER_INPUT
*buf
= (const WS_XML_READER_BUFFER_INPUT
*)input
;
7197 hr
= set_input_buffer( reader
, (const unsigned char *)buf
->encodedData
+ offset
, buf
->encodedDataSize
- offset
);
7198 if (hr
!= S_OK
) goto done
;
7201 case WS_XML_READER_INPUT_TYPE_STREAM
:
7203 const WS_XML_READER_STREAM_INPUT
*stream
= (const WS_XML_READER_STREAM_INPUT
*)input
;
7204 if (!reader
->stream_buf
&& !(reader
->stream_buf
= malloc( STREAM_BUFSIZE
)))
7209 set_input_stream( reader
, stream
->readCallback
, stream
->readCallbackState
);
7213 FIXME( "input type %u not supported\n", input
->inputType
);
7218 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
7219 else read_insert_bof( reader
, node
);
7222 LeaveCriticalSection( &reader
->cs
);
7223 TRACE( "returning %#lx\n", hr
);
7227 static HRESULT
set_input_xml_buffer( struct reader
*reader
, struct xmlbuf
*xmlbuf
)
7229 reader
->input_type
= WS_XML_READER_INPUT_TYPE_BUFFER
;
7230 reader
->input_buf
= xmlbuf
;
7231 reader
->input_enc
= xmlbuf
->encoding
;
7232 reader
->input_charset
= xmlbuf
->charset
;
7233 reader
->dict_static
= xmlbuf
->dict_static
;
7234 reader
->dict
= xmlbuf
->dict
;
7236 if (reader
->input_enc
== WS_XML_READER_ENCODING_TYPE_TEXT
&& reader
->input_charset
== WS_CHARSET_UTF16LE
)
7242 if ((hr
= utf16le_to_utf8( xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
, &buf
, &buflen
)) != S_OK
) return hr
;
7243 free( reader
->input_conv
);
7244 reader
->read_bufptr
= reader
->input_conv
= buf
;
7245 reader
->read_size
= reader
->input_size
= buflen
;
7249 reader
->read_bufptr
= xmlbuf
->bytes
.bytes
;
7250 reader
->read_size
= reader
->input_size
= xmlbuf
->bytes
.length
;
7253 reader
->read_pos
= 0;
7254 reader
->text_conv_offset
= 0;
7258 /**************************************************************************
7259 * WsSetInputToBuffer [webservices.@]
7261 HRESULT WINAPI
WsSetInputToBuffer( WS_XML_READER
*handle
, WS_XML_BUFFER
*buffer
,
7262 const WS_XML_READER_PROPERTY
*properties
, ULONG count
,
7265 struct reader
*reader
= (struct reader
*)handle
;
7266 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
7271 TRACE( "%p %p %p %lu %p\n", handle
, buffer
, properties
, count
, error
);
7272 if (error
) FIXME( "ignoring error parameter\n" );
7274 if (!reader
|| !xmlbuf
) return E_INVALIDARG
;
7276 EnterCriticalSection( &reader
->cs
);
7278 if (reader
->magic
!= READER_MAGIC
)
7280 LeaveCriticalSection( &reader
->cs
);
7281 return E_INVALIDARG
;
7284 for (i
= 0; i
< count
; i
++)
7286 hr
= prop_set( reader
->prop
, reader
->prop_count
, properties
[i
].id
, properties
[i
].value
,
7287 properties
[i
].valueSize
);
7288 if (hr
!= S_OK
) goto done
;
7291 if ((hr
= init_reader( reader
)) != S_OK
) goto done
;
7292 if ((hr
= set_input_xml_buffer( reader
, xmlbuf
)) != S_OK
) goto done
;
7294 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
7295 else read_insert_bof( reader
, node
);
7298 LeaveCriticalSection( &reader
->cs
);
7299 TRACE( "returning %#lx\n", hr
);
7303 /**************************************************************************
7304 * WsGetReaderPosition [webservices.@]
7306 HRESULT WINAPI
WsGetReaderPosition( WS_XML_READER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
7308 struct reader
*reader
= (struct reader
*)handle
;
7311 TRACE( "%p %p %p\n", handle
, pos
, error
);
7312 if (error
) FIXME( "ignoring error parameter\n" );
7314 if (!reader
|| !pos
) return E_INVALIDARG
;
7316 EnterCriticalSection( &reader
->cs
);
7318 if (reader
->magic
!= READER_MAGIC
)
7320 LeaveCriticalSection( &reader
->cs
);
7321 return E_INVALIDARG
;
7324 if (!reader
->input_buf
) hr
= WS_E_INVALID_OPERATION
;
7327 pos
->buffer
= (WS_XML_BUFFER
*)reader
->input_buf
;
7328 pos
->node
= reader
->current
;
7331 LeaveCriticalSection( &reader
->cs
);
7332 TRACE( "returning %#lx\n", hr
);
7336 /**************************************************************************
7337 * WsSetReaderPosition [webservices.@]
7339 HRESULT WINAPI
WsSetReaderPosition( WS_XML_READER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
7341 struct reader
*reader
= (struct reader
*)handle
;
7344 TRACE( "%p %p %p\n", handle
, pos
, error
);
7345 if (error
) FIXME( "ignoring error parameter\n" );
7347 if (!reader
|| !pos
) return E_INVALIDARG
;
7349 EnterCriticalSection( &reader
->cs
);
7351 if (reader
->magic
!= READER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= reader
->input_buf
)
7353 LeaveCriticalSection( &reader
->cs
);
7354 return E_INVALIDARG
;
7357 if (!reader
->input_buf
) hr
= WS_E_INVALID_OPERATION
;
7358 else reader
->current
= pos
->node
;
7360 LeaveCriticalSection( &reader
->cs
);
7361 TRACE( "returning %#lx\n", hr
);
7365 static HRESULT
utf8_to_base64( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_BASE64_TEXT
*base64
)
7367 if (utf8
->value
.length
% 4) return WS_E_INVALID_FORMAT
;
7368 if (!(base64
->bytes
= malloc( utf8
->value
.length
* 3 / 4 ))) return E_OUTOFMEMORY
;
7369 base64
->length
= decode_base64( utf8
->value
.bytes
, utf8
->value
.length
, base64
->bytes
);
7373 /**************************************************************************
7374 * WsReadBytes [webservices.@]
7376 HRESULT WINAPI
WsReadBytes( WS_XML_READER
*handle
, void *bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
7378 struct reader
*reader
= (struct reader
*)handle
;
7381 TRACE( "%p %p %lu %p %p\n", handle
, bytes
, max_count
, count
, error
);
7382 if (error
) FIXME( "ignoring error parameter\n" );
7384 if (!reader
) return E_INVALIDARG
;
7386 EnterCriticalSection( &reader
->cs
);
7388 if (reader
->magic
!= READER_MAGIC
)
7390 LeaveCriticalSection( &reader
->cs
);
7391 return E_INVALIDARG
;
7394 if (!reader
->input_type
)
7396 hr
= WS_E_INVALID_OPERATION
;
7406 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
7408 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
7409 WS_XML_BASE64_TEXT base64
;
7411 if ((hr
= utf8_to_base64( (const WS_XML_UTF8_TEXT
*)text
->text
, &base64
)) != S_OK
) goto done
;
7412 if (reader
->text_conv_offset
== base64
.length
)
7414 free( base64
.bytes
);
7415 hr
= read_node( reader
);
7418 *count
= min( base64
.length
- reader
->text_conv_offset
, max_count
);
7419 memcpy( bytes
, base64
.bytes
+ reader
->text_conv_offset
, *count
);
7420 reader
->text_conv_offset
+= *count
;
7421 free( base64
.bytes
);
7425 LeaveCriticalSection( &reader
->cs
);
7426 TRACE( "returning %#lx\n", hr
);
7430 static HRESULT
utf8_to_utf16( const WS_XML_UTF8_TEXT
*utf8
, WS_XML_UTF16_TEXT
*utf16
)
7432 int len
= MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, NULL
, 0 );
7433 if (!(utf16
->bytes
= malloc( len
* sizeof(WCHAR
) ))) return E_OUTOFMEMORY
;
7434 MultiByteToWideChar( CP_UTF8
, 0, (char *)utf8
->value
.bytes
, utf8
->value
.length
, (WCHAR
*)utf16
->bytes
, len
);
7435 utf16
->byteCount
= len
* sizeof(WCHAR
);
7439 /**************************************************************************
7440 * WsReadChars [webservices.@]
7442 HRESULT WINAPI
WsReadChars( WS_XML_READER
*handle
, WCHAR
*chars
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
7444 struct reader
*reader
= (struct reader
*)handle
;
7447 TRACE( "%p %p %lu %p %p\n", handle
, chars
, max_count
, count
, error
);
7448 if (error
) FIXME( "ignoring error parameter\n" );
7450 if (!reader
) return E_INVALIDARG
;
7452 EnterCriticalSection( &reader
->cs
);
7454 if (reader
->magic
!= READER_MAGIC
)
7456 LeaveCriticalSection( &reader
->cs
);
7457 return E_INVALIDARG
;
7460 if (!reader
->input_type
)
7462 hr
= WS_E_INVALID_OPERATION
;
7472 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& chars
)
7474 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
7475 WS_XML_UTF16_TEXT utf16
;
7478 if ((hr
= utf8_to_utf16( (const WS_XML_UTF8_TEXT
*)text
->text
, &utf16
)) != S_OK
) goto done
;
7479 if (reader
->text_conv_offset
== utf16
.byteCount
/ sizeof(WCHAR
))
7481 free( utf16
.bytes
);
7482 hr
= read_node( reader
);
7485 *count
= min( utf16
.byteCount
/ sizeof(WCHAR
) - reader
->text_conv_offset
, max_count
);
7486 memcpy( chars
, utf16
.bytes
+ reader
->text_conv_offset
* sizeof(WCHAR
), *count
* sizeof(WCHAR
) );
7487 reader
->text_conv_offset
+= *count
;
7488 free( utf16
.bytes
);
7492 LeaveCriticalSection( &reader
->cs
);
7493 TRACE( "returning %#lx\n", hr
);
7497 /**************************************************************************
7498 * WsReadCharsUtf8 [webservices.@]
7500 HRESULT WINAPI
WsReadCharsUtf8( WS_XML_READER
*handle
, BYTE
*bytes
, ULONG max_count
, ULONG
*count
, WS_ERROR
*error
)
7502 struct reader
*reader
= (struct reader
*)handle
;
7505 TRACE( "%p %p %lu %p %p\n", handle
, bytes
, max_count
, count
, error
);
7506 if (error
) FIXME( "ignoring error parameter\n" );
7508 if (!reader
) return E_INVALIDARG
;
7510 EnterCriticalSection( &reader
->cs
);
7512 if (reader
->magic
!= READER_MAGIC
)
7514 LeaveCriticalSection( &reader
->cs
);
7515 return E_INVALIDARG
;
7518 if (!reader
->input_type
)
7520 hr
= WS_E_INVALID_OPERATION
;
7530 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_TEXT
&& bytes
)
7532 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)reader
->current
;
7533 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
7535 if (reader
->text_conv_offset
== utf8
->value
.length
)
7537 hr
= read_node( reader
);
7540 *count
= min( utf8
->value
.length
- reader
->text_conv_offset
, max_count
);
7541 memcpy( bytes
, utf8
->value
.bytes
+ reader
->text_conv_offset
, *count
);
7542 reader
->text_conv_offset
+= *count
;
7546 LeaveCriticalSection( &reader
->cs
);
7547 TRACE( "returning %#lx\n", hr
);
7551 static HRESULT
move_to_element( struct reader
*reader
)
7554 if (node_type( reader
->current
) == WS_XML_NODE_TYPE_BOF
&&
7555 (hr
= read_move_to( reader
, WS_MOVE_TO_CHILD_NODE
, NULL
)) != S_OK
) return hr
;
7556 if (node_type( reader
->current
) != WS_XML_NODE_TYPE_ELEMENT
) return E_FAIL
;
7560 static HRESULT
copy_tree( struct reader
*reader
, WS_XML_WRITER
*writer
)
7562 const struct node
*node
, *parent
;
7566 if ((hr
= move_to_element( reader
)) != S_OK
) return hr
;
7567 parent
= reader
->current
;
7570 node
= reader
->current
;
7571 if ((hr
= WsWriteNode( writer
, (const WS_XML_NODE
*)node
, NULL
)) != S_OK
) break;
7572 if (node_type( node
) == WS_XML_NODE_TYPE_END_ELEMENT
&& node
->parent
== parent
) done
= TRUE
;
7573 if ((hr
= read_next_node( reader
)) != S_OK
|| done
) break;
7578 /**************************************************************************
7579 * WsReadXmlBuffer [webservices.@]
7581 HRESULT WINAPI
WsReadXmlBuffer( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_BUFFER
**ret
, WS_ERROR
*error
)
7583 struct reader
*reader
= (struct reader
*)handle
;
7584 WS_XML_WRITER
*writer
= NULL
;
7585 WS_XML_BUFFER
*buffer
= NULL
;
7588 TRACE( "%p %p %p %p\n", handle
, heap
, ret
, error
);
7589 if (error
) FIXME( "ignoring error parameter\n" );
7591 if (!reader
|| !heap
) return E_INVALIDARG
;
7592 if (!ret
) return E_FAIL
;
7594 EnterCriticalSection( &reader
->cs
);
7596 if (reader
->magic
!= READER_MAGIC
)
7598 LeaveCriticalSection( &reader
->cs
);
7599 return E_INVALIDARG
;
7602 if (!reader
->input_type
) hr
= WS_E_INVALID_OPERATION
;
7605 if ((hr
= WsCreateWriter( NULL
, 0, &writer
, NULL
)) != S_OK
) goto done
;
7606 if ((hr
= WsCreateXmlBuffer( heap
, NULL
, 0, &buffer
, NULL
)) != S_OK
) goto done
;
7607 if ((hr
= WsSetOutputToBuffer( writer
, buffer
, NULL
, 0, NULL
)) != S_OK
) goto done
;
7608 if ((hr
= copy_tree( reader
, writer
)) == S_OK
) *ret
= buffer
;
7612 if (hr
!= S_OK
) free_xmlbuf( (struct xmlbuf
*)buffer
);
7613 WsFreeWriter( writer
);
7614 LeaveCriticalSection( &reader
->cs
);
7615 TRACE( "returning %#lx\n", hr
);
7619 HRESULT
create_header_buffer( WS_XML_READER
*handle
, WS_HEAP
*heap
, WS_XML_BUFFER
**ret
)
7621 struct reader
*reader
= (struct reader
*)handle
;
7622 HRESULT hr
= WS_E_QUOTA_EXCEEDED
;
7623 struct xmlbuf
*xmlbuf
;
7625 EnterCriticalSection( &reader
->cs
);
7627 if (reader
->magic
!= READER_MAGIC
)
7629 LeaveCriticalSection( &reader
->cs
);
7630 return E_INVALIDARG
;
7633 if ((xmlbuf
= alloc_xmlbuf( heap
, reader
->read_pos
, reader
->input_enc
, reader
->input_charset
,
7634 reader
->dict_static
, reader
->dict
)))
7636 memcpy( xmlbuf
->bytes
.bytes
, reader
->read_bufptr
, reader
->read_pos
);
7637 xmlbuf
->bytes
.length
= reader
->read_pos
;
7638 *ret
= (WS_XML_BUFFER
*)xmlbuf
;
7642 LeaveCriticalSection( &reader
->cs
);
7646 HRESULT
get_param_desc( const WS_STRUCT_DESCRIPTION
*desc
, USHORT index
, const WS_FIELD_DESCRIPTION
**ret
)
7648 if (index
>= desc
->fieldCount
) return E_INVALIDARG
;
7649 *ret
= desc
->fields
[index
];
7653 static ULONG
get_field_size( const WS_FIELD_DESCRIPTION
*desc
)
7655 if (desc
->options
& WS_FIELD_POINTER
) return sizeof(void *);
7656 return get_type_size( desc
->type
, desc
->typeDescription
);
7659 static HRESULT
read_param( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
, void *ret
)
7661 if (!ret
&& !(ret
= ws_alloc_zero( heap
, get_field_size(desc
) ))) return WS_E_QUOTA_EXCEEDED
;
7662 return read_type_field( reader
, NULL
, desc
, heap
, ret
, 0 );
7665 static HRESULT
read_param_array( struct reader
*reader
, const WS_FIELD_DESCRIPTION
*desc
, WS_HEAP
*heap
,
7666 void **ret
, ULONG
*count
)
7668 if (!ret
&& !(ret
= ws_alloc_zero( heap
, sizeof(void **) ))) return WS_E_QUOTA_EXCEEDED
;
7669 return read_type_array( reader
, desc
, heap
, ret
, count
);
7672 static void set_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, ULONG len
,
7676 for (i
= 0; i
< count
; i
++)
7678 if (params
[i
].outputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
7680 if ((ptr
= *(ULONG
**)args
[i
])) *ptr
= len
;
7685 HRESULT
read_output_params( WS_XML_READER
*handle
, WS_HEAP
*heap
, const WS_ELEMENT_DESCRIPTION
*desc
,
7686 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
7688 struct reader
*reader
= (struct reader
*)handle
;
7689 const WS_STRUCT_DESCRIPTION
*desc_struct
;
7690 const WS_FIELD_DESCRIPTION
*desc_field
;
7694 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
7696 EnterCriticalSection( &reader
->cs
);
7698 if (reader
->magic
!= READER_MAGIC
)
7700 LeaveCriticalSection( &reader
->cs
);
7701 return E_INVALIDARG
;
7704 if ((hr
= start_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
)
7707 for (i
= 0; i
< count
; i
++)
7709 if (params
[i
].outputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
7710 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
7712 FIXME( "messages type not supported\n" );
7716 if ((hr
= get_param_desc( desc_struct
, params
[i
].outputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
7717 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
7719 void *ptr
= *(void **)args
[i
];
7720 if ((hr
= read_param( reader
, desc_field
, heap
, ptr
)) != S_OK
) goto done
;
7722 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
7724 void **ptr
= *(void ***)args
[i
];
7725 if ((hr
= read_param_array( reader
, desc_field
, heap
, ptr
, &len
)) != S_OK
) goto done
;
7726 set_array_len( params
, count
, params
[i
].outputMessageIndex
, len
, args
);
7730 if (desc_struct
->structOptions
& WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
7732 struct node
*parent
= find_parent( reader
);
7733 parent
->flags
|= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
7736 hr
= end_mapping( reader
, WS_ELEMENT_TYPE_MAPPING
);
7739 LeaveCriticalSection( &reader
->cs
);