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
27 #include "webservices.h"
29 #include "wine/debug.h"
30 #include "wine/list.h"
31 #include "wine/unicode.h"
32 #include "webservices_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
36 static const struct prop_desc writer_props
[] =
38 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
39 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
40 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
41 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
42 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INDENT */
43 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
44 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_WRITER_PROPERTY_CHARSET */
45 { sizeof(WS_BUFFERS
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFERS */
46 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
47 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BYTES */
48 { sizeof(BOOL
), TRUE
}, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
49 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
50 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
51 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
52 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
53 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
54 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
55 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
56 { sizeof(BOOL
), FALSE
} /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
62 WRITER_STATE_STARTELEMENT
,
63 WRITER_STATE_STARTATTRIBUTE
,
64 WRITER_STATE_STARTCDATA
,
65 WRITER_STATE_ENDSTARTELEMENT
,
68 WRITER_STATE_ENDELEMENT
,
75 unsigned char *write_bufptr
;
76 enum writer_state state
;
79 WS_XML_STRING
*current_ns
;
80 WS_XML_WRITER_OUTPUT_TYPE output_type
;
81 struct xmlbuf
*output_buf
;
84 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
87 static struct writer
*alloc_writer(void)
89 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
91 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
93 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
94 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
95 ret
->prop_count
= count
;
99 static void free_writer( struct writer
*writer
)
102 destroy_nodes( writer
->root
);
103 heap_free( writer
->current_ns
);
104 WsFreeHeap( writer
->output_heap
);
108 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
110 if (!writer
->root
) writer
->root
= eof
;
113 eof
->parent
= writer
->root
;
114 list_add_tail( &writer
->root
->children
, &eof
->entry
);
116 writer
->current
= eof
;
119 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
121 writer
->root
->parent
= bof
;
122 list_add_tail( &bof
->children
, &writer
->root
->entry
);
123 writer
->current
= writer
->root
= bof
;
126 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
128 node
->parent
= parent
;
129 list_add_before( list_tail( &parent
->children
), &node
->entry
);
130 writer
->current
= node
;
133 static struct node
*find_parent( struct writer
*writer
)
135 if (is_valid_parent( writer
->current
)) return writer
->current
;
136 if (is_valid_parent( writer
->current
->parent
)) return writer
->current
->parent
;
140 static HRESULT
write_init_state( struct writer
*writer
)
144 heap_free( writer
->current_ns
);
145 writer
->current_ns
= NULL
;
146 destroy_nodes( writer
->root
);
149 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
150 write_insert_eof( writer
, node
);
151 writer
->state
= WRITER_STATE_INITIAL
;
155 /**************************************************************************
156 * WsCreateWriter [webservices.@]
158 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
159 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
161 struct writer
*writer
;
162 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
163 WS_CHARSET charset
= WS_CHARSET_UTF8
;
166 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
167 if (error
) FIXME( "ignoring error parameter\n" );
169 if (!handle
) return E_INVALIDARG
;
170 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
172 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
173 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
174 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
175 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
176 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
177 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
178 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
180 for (i
= 0; i
< count
; i
++)
182 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
183 properties
[i
].valueSize
);
186 free_writer( writer
);
191 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
192 &max_size
, sizeof(max_size
) );
195 free_writer( writer
);
199 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
202 free_writer( writer
);
206 hr
= write_init_state( writer
);
209 free_writer( writer
);
213 *handle
= (WS_XML_WRITER
*)writer
;
217 /**************************************************************************
218 * WsFreeWriter [webservices.@]
220 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
222 struct writer
*writer
= (struct writer
*)handle
;
224 TRACE( "%p\n", handle
);
225 free_writer( writer
);
228 #define XML_BUFFER_INITIAL_ALLOCATED_SIZE 256
229 static struct xmlbuf
*alloc_xmlbuf( WS_HEAP
*heap
)
233 if (!(ret
= ws_alloc( heap
, sizeof(*ret
) ))) return NULL
;
234 if (!(ret
->ptr
= ws_alloc( heap
, XML_BUFFER_INITIAL_ALLOCATED_SIZE
)))
236 ws_free( heap
, ret
);
240 ret
->size_allocated
= XML_BUFFER_INITIAL_ALLOCATED_SIZE
;
245 static void free_xmlbuf( struct xmlbuf
*xmlbuf
)
248 ws_free( xmlbuf
->heap
, xmlbuf
->ptr
);
249 ws_free( xmlbuf
->heap
, xmlbuf
);
252 /**************************************************************************
253 * WsCreateXmlBuffer [webservices.@]
255 HRESULT WINAPI
WsCreateXmlBuffer( WS_HEAP
*heap
, const WS_XML_BUFFER_PROPERTY
*properties
,
256 ULONG count
, WS_XML_BUFFER
**handle
, WS_ERROR
*error
)
258 struct xmlbuf
*xmlbuf
;
260 if (!heap
|| !handle
) return E_INVALIDARG
;
261 if (count
) FIXME( "properties not implemented\n" );
263 if (!(xmlbuf
= alloc_xmlbuf( heap
))) return E_OUTOFMEMORY
;
265 *handle
= (WS_XML_BUFFER
*)xmlbuf
;
269 /**************************************************************************
270 * WsGetWriterProperty [webservices.@]
272 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
273 void *buf
, ULONG size
, WS_ERROR
*error
)
275 struct writer
*writer
= (struct writer
*)handle
;
277 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
278 if (error
) FIXME( "ignoring error parameter\n" );
280 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
284 case WS_XML_WRITER_PROPERTY_BYTES
:
286 WS_BYTES
*bytes
= buf
;
287 if (size
!= sizeof(*bytes
)) return E_INVALIDARG
;
288 bytes
->bytes
= writer
->output_buf
->ptr
;
289 bytes
->length
= writer
->output_buf
->size
;
293 return prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
297 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
299 /* free current buffer if it's ours */
300 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
302 free_xmlbuf( writer
->output_buf
);
304 writer
->output_buf
= xmlbuf
;
305 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
306 writer
->write_bufptr
= xmlbuf
->ptr
;
307 writer
->write_pos
= 0;
310 /**************************************************************************
311 * WsSetOutput [webservices.@]
313 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
314 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
315 ULONG count
, WS_ERROR
*error
)
317 struct writer
*writer
= (struct writer
*)handle
;
322 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
323 if (error
) FIXME( "ignoring error parameter\n" );
325 if (!writer
) return E_INVALIDARG
;
327 for (i
= 0; i
< count
; i
++)
329 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
330 properties
[i
].valueSize
);
331 if (hr
!= S_OK
) return hr
;
334 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
336 switch (encoding
->encodingType
)
338 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
340 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
341 if (text
->charSet
!= WS_CHARSET_UTF8
)
343 FIXME( "charset %u not supported\n", text
->charSet
);
349 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
352 switch (output
->outputType
)
354 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
356 struct xmlbuf
*xmlbuf
;
358 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
))) return E_OUTOFMEMORY
;
359 set_output_buffer( writer
, xmlbuf
);
363 FIXME( "output type %u not supported\n", output
->outputType
);
367 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
368 write_insert_bof( writer
, node
);
372 /**************************************************************************
373 * WsSetOutputToBuffer [webservices.@]
375 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
376 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
379 struct writer
*writer
= (struct writer
*)handle
;
380 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
385 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
386 if (error
) FIXME( "ignoring error parameter\n" );
388 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
390 for (i
= 0; i
< count
; i
++)
392 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
393 properties
[i
].valueSize
);
394 if (hr
!= S_OK
) return hr
;
397 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
398 set_output_buffer( writer
, xmlbuf
);
400 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
401 write_insert_bof( writer
, node
);
405 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
407 struct xmlbuf
*buf
= writer
->output_buf
;
411 if (buf
->size_allocated
>= writer
->write_pos
+ size
)
413 buf
->size
= writer
->write_pos
+ size
;
416 new_size
= max( buf
->size_allocated
* 2, writer
->write_pos
+ size
);
417 if (!(tmp
= ws_realloc( buf
->heap
, buf
->ptr
, new_size
))) return E_OUTOFMEMORY
;
418 writer
->write_bufptr
= buf
->ptr
= tmp
;
419 buf
->size_allocated
= new_size
;
420 buf
->size
= writer
->write_pos
+ size
;
424 static inline void write_char( struct writer
*writer
, unsigned char ch
)
426 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
429 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
431 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
432 writer
->write_pos
+= len
;
441 static const struct escape escape_lt
= { '<', "<", 4 };
442 static const struct escape escape_gt
= { '>', ">", 4 };
443 static const struct escape escape_amp
= { '&', "&", 5 };
444 static const struct escape escape_apos
= { '\'', "'", 6 };
445 static const struct escape escape_quot
= { '"', """, 6 };
447 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
448 const struct escape
**escapes
, ULONG nb_escapes
)
454 for (i
= 0; i
< len
; i
++)
458 for (j
= 0; j
< nb_escapes
; j
++)
460 if (bytes
[i
] == escapes
[j
]->ch
)
462 ptr
= (const BYTE
*)escapes
[j
]->entity
;
463 size
= escapes
[j
]->len
;
467 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
468 write_bytes( writer
, ptr
, size
);
474 static HRESULT
write_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
476 WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)attr
->value
;
477 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
478 const WS_XML_STRING
*prefix
;
482 if (attr
->prefix
) prefix
= attr
->prefix
;
483 else prefix
= writer
->current
->hdr
.prefix
;
485 /* ' prefix:attr="value"' */
487 size
= attr
->localName
->length
+ 4 /* ' =""' */;
488 if (prefix
) size
+= prefix
->length
+ 1 /* ':' */;
489 if (text
) size
+= text
->value
.length
;
490 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
492 write_char( writer
, ' ' );
495 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
496 write_char( writer
, ':' );
498 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
499 write_char( writer
, '=' );
500 write_char( writer
, quote
);
503 const struct escape
*escapes
[3];
504 escapes
[0] = attr
->singleQuote
? &escape_apos
: &escape_quot
;
505 escapes
[1] = &escape_lt
;
506 escapes
[2] = &escape_amp
;
507 hr
= write_bytes_escape( writer
, text
->value
.bytes
, text
->value
.length
, escapes
, 3 );
509 write_char( writer
, quote
);
514 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
516 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
519 /**************************************************************************
520 * WsGetPrefixFromNamespace [webservices.@]
522 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
523 BOOL required
, const WS_XML_STRING
**prefix
,
526 struct writer
*writer
= (struct writer
*)handle
;
527 WS_XML_ELEMENT_NODE
*elem
;
530 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
531 if (error
) FIXME( "ignoring error parameter\n" );
533 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
535 elem
= &writer
->current
->hdr
;
536 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
538 *prefix
= elem
->prefix
;
543 if (required
) return WS_E_INVALID_FORMAT
;
550 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
553 if (!(str
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
554 heap_free( writer
->current_ns
);
555 writer
->current_ns
= str
;
559 static HRESULT
write_namespace_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
561 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
565 /* ' xmlns:prefix="namespace"' */
567 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
568 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
569 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
571 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
574 write_char( writer
, ':' );
575 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
577 write_char( writer
, '=' );
578 write_char( writer
, quote
);
579 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
580 write_char( writer
, quote
);
585 static HRESULT
write_add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
586 const WS_XML_STRING
*ns
, BOOL single
)
588 WS_XML_ATTRIBUTE
*attr
;
589 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
592 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
594 attr
->singleQuote
= !!single
;
596 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
598 free_attribute( attr
);
599 return E_OUTOFMEMORY
;
601 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
603 free_attribute( attr
);
604 return E_OUTOFMEMORY
;
606 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
608 free_attribute( attr
);
614 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
616 if (!str1
&& !str2
) return TRUE
;
617 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
620 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
621 const WS_XML_STRING
*ns
)
624 const struct node
*node
;
626 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
628 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
631 for (i
= 0; i
< elem
->attributeCount
; i
++)
633 if (!elem
->attributes
[i
]->isXmlNs
) continue;
634 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
635 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
641 static HRESULT
write_set_element_namespace( struct writer
*writer
)
643 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
646 if (!elem
->ns
->length
|| namespace_in_scope( elem
, elem
->prefix
, elem
->ns
)) return S_OK
;
648 if ((hr
= write_add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
)
651 return set_current_namespace( writer
, elem
->ns
);
654 /**************************************************************************
655 * WsWriteEndAttribute [webservices.@]
657 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
659 struct writer
*writer
= (struct writer
*)handle
;
661 TRACE( "%p %p\n", handle
, error
);
662 if (error
) FIXME( "ignoring error parameter\n" );
664 if (!writer
) return E_INVALIDARG
;
666 writer
->state
= WRITER_STATE_STARTELEMENT
;
670 static HRESULT
write_startelement( struct writer
*writer
)
672 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
676 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
678 size
= elem
->localName
->length
+ 1 /* '<' */;
679 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
680 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
682 write_char( writer
, '<' );
685 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
686 write_char( writer
, ':' );
688 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
689 for (i
= 0; i
< elem
->attributeCount
; i
++)
691 if (elem
->attributes
[i
]->isXmlNs
) continue;
692 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
694 for (i
= 0; i
< elem
->attributeCount
; i
++)
696 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
697 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
699 for (i
= 0; i
< elem
->attributeCount
; i
++)
701 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
702 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
707 static struct node
*write_find_startelement( struct writer
*writer
)
710 for (node
= writer
->current
; node
; node
= node
->parent
)
712 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
717 static inline BOOL
is_empty_element( const struct node
*node
)
719 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
720 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
723 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
730 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
732 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
733 write_char( writer
, '/' );
734 write_char( writer
, '>' );
738 /* '</prefix:localname>' */
740 size
= elem
->localName
->length
+ 3 /* '</>' */;
741 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
742 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
744 write_char( writer
, '<' );
745 write_char( writer
, '/' );
748 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
749 write_char( writer
, ':' );
751 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
752 write_char( writer
, '>' );
756 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
758 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
759 elem
->isEmpty
= is_empty_element( node
);
760 return write_endelement( writer
, elem
);
763 static HRESULT
write_endelement_node( struct writer
*writer
)
768 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
769 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
771 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
772 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
774 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
775 writer
->current
= node
->parent
;
776 writer
->state
= WRITER_STATE_ENDELEMENT
;
780 /**************************************************************************
781 * WsWriteEndElement [webservices.@]
783 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
785 struct writer
*writer
= (struct writer
*)handle
;
787 TRACE( "%p %p\n", handle
, error
);
788 if (error
) FIXME( "ignoring error parameter\n" );
790 if (!writer
) return E_INVALIDARG
;
791 return write_endelement_node( writer
);
794 static HRESULT
write_endstartelement( struct writer
*writer
)
797 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
798 write_char( writer
, '>' );
802 /**************************************************************************
803 * WsWriteEndStartElement [webservices.@]
805 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
807 struct writer
*writer
= (struct writer
*)handle
;
810 TRACE( "%p %p\n", handle
, error
);
811 if (error
) FIXME( "ignoring error parameter\n" );
813 if (!writer
) return E_INVALIDARG
;
814 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
816 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
817 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
818 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
820 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
824 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
825 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
828 WS_XML_ATTRIBUTE
*attr
;
829 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
832 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
834 if (!prefix
) prefix
= elem
->prefix
;
836 attr
->singleQuote
= !!single
;
837 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
839 free_attribute( attr
);
840 return E_OUTOFMEMORY
;
842 if (!(attr
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
844 free_attribute( attr
);
845 return E_OUTOFMEMORY
;
847 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
849 free_attribute( attr
);
850 return E_OUTOFMEMORY
;
852 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
854 free_attribute( attr
);
860 /**************************************************************************
861 * WsWriteStartAttribute [webservices.@]
863 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
864 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
865 BOOL single
, WS_ERROR
*error
)
867 struct writer
*writer
= (struct writer
*)handle
;
870 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
871 debugstr_xmlstr(ns
), single
, error
);
872 if (error
) FIXME( "ignoring error parameter\n" );
874 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
876 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
878 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) != S_OK
) return hr
;
879 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
883 /* flush current start element if necessary */
884 static HRESULT
write_flush( struct writer
*writer
)
886 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
889 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
890 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
891 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
892 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
897 static HRESULT
write_add_cdata_node( struct writer
*writer
)
899 struct node
*node
, *parent
;
900 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
901 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
902 write_insert_node( writer
, parent
, node
);
906 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
909 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
910 node
->parent
= writer
->current
;
911 list_add_tail( &node
->parent
->children
, &node
->entry
);
915 static HRESULT
write_cdata( struct writer
*writer
)
918 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
919 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
923 static HRESULT
write_cdata_node( struct writer
*writer
)
926 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
927 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
928 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
929 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
930 writer
->state
= WRITER_STATE_STARTCDATA
;
934 /**************************************************************************
935 * WsWriteStartCData [webservices.@]
937 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
939 struct writer
*writer
= (struct writer
*)handle
;
941 TRACE( "%p %p\n", handle
, error
);
942 if (error
) FIXME( "ignoring error parameter\n" );
944 if (!writer
) return E_INVALIDARG
;
945 return write_cdata_node( writer
);
948 static HRESULT
write_endcdata( struct writer
*writer
)
951 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
952 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
956 static HRESULT
write_endcdata_node( struct writer
*writer
)
959 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
960 writer
->current
= writer
->current
->parent
;
961 writer
->state
= WRITER_STATE_ENDCDATA
;
965 /**************************************************************************
966 * WsWriteEndCData [webservices.@]
968 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
970 struct writer
*writer
= (struct writer
*)handle
;
972 TRACE( "%p %p\n", handle
, error
);
973 if (error
) FIXME( "ignoring error parameter\n" );
975 if (!writer
) return E_INVALIDARG
;
976 if (writer
->state
!= WRITER_STATE_TEXT
) return WS_E_INVALID_OPERATION
;
978 return write_endcdata_node( writer
);
981 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
982 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
984 struct node
*node
, *parent
;
985 WS_XML_ELEMENT_NODE
*elem
;
987 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
989 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
992 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
995 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
998 if (prefix
&& !(elem
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
1001 return E_OUTOFMEMORY
;
1003 if (!(elem
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1006 return E_OUTOFMEMORY
;
1008 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
1011 return E_OUTOFMEMORY
;
1013 write_insert_node( writer
, parent
, node
);
1017 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
1020 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1021 node
->parent
= parent
;
1022 list_add_tail( &parent
->children
, &node
->entry
);
1026 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1027 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1030 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1031 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
1032 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
1033 writer
->state
= WRITER_STATE_STARTELEMENT
;
1037 /**************************************************************************
1038 * WsWriteStartElement [webservices.@]
1040 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1041 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1044 struct writer
*writer
= (struct writer
*)handle
;
1046 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1047 debugstr_xmlstr(ns
), error
);
1048 if (error
) FIXME( "ignoring error parameter\n" );
1050 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1051 return write_element_node( writer
, prefix
, localname
, ns
);
1054 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
1056 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1059 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1060 return sizeof(bool_true
);
1062 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1063 return sizeof(bool_false
);
1066 static ULONG
format_int8( const INT8
*ptr
, unsigned char *buf
)
1068 return wsprintfA( (char *)buf
, "%d", *ptr
);
1071 static ULONG
format_int16( const INT16
*ptr
, unsigned char *buf
)
1073 return wsprintfA( (char *)buf
, "%d", *ptr
);
1076 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1078 return wsprintfA( (char *)buf
, "%d", *ptr
);
1081 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1083 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1086 static ULONG
format_uint8( const UINT8
*ptr
, unsigned char *buf
)
1088 return wsprintfA( (char *)buf
, "%u", *ptr
);
1091 static ULONG
format_uint16( const UINT16
*ptr
, unsigned char *buf
)
1093 return wsprintfA( (char *)buf
, "%u", *ptr
);
1096 static ULONG
format_uint32( const UINT32
*ptr
, unsigned char *buf
)
1098 return wsprintfA( (char *)buf
, "%u", *ptr
);
1101 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1103 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1106 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
1109 static const long double precision
= 0.0000000000000001;
1110 unsigned char *p
= buf
;
1111 long double val
= *ptr
;
1112 int neg
, mag
, mag2
, use_exp
;
1116 memcpy( buf
, "NaN", 3 );
1123 memcpy( buf
, "-INF", 4 );
1126 memcpy( buf
, "INF", 3 );
1135 if ((neg
= val
< 0))
1141 mag
= log10l( val
);
1142 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1145 if (mag
< 0) mag
-= 1;
1146 val
= val
/ powl( 10.0, mag
);
1150 else if (mag
< 1) mag
= 0;
1152 while (val
> precision
|| mag
>= 0)
1154 long double weight
= powl( 10.0, mag
);
1155 if (weight
> 0 && !isinf( weight
))
1157 int digit
= floorl( val
/ weight
);
1158 val
-= digit
* weight
;
1159 *(p
++) = '0' + digit
;
1161 if (!mag
&& val
> precision
) *(p
++) = '.';
1169 if (mag2
> 0) *(p
++) = '+';
1178 *(p
++) = '0' + mag2
% 10;
1182 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1192 FIXME( "powl not found at build time\n" );
1197 static inline int year_size( int year
)
1199 return leap_year( year
) ? 366 : 365;
1203 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
1205 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
1206 int day
, hour
, min
, sec
, sec_frac
, month
= 1, year
= 1, tz_hour
;
1207 unsigned __int64 ticks
, day_ticks
;
1210 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
1211 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
1213 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1214 tz_hour
= TZ_OFFSET
;
1221 day
= ticks
/ TICKS_PER_DAY
;
1222 day_ticks
= ticks
% TICKS_PER_DAY
;
1223 hour
= day_ticks
/ TICKS_PER_HOUR
;
1224 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1225 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1226 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1228 while (day
>= year_size( year
))
1230 day
-= year_size( year
);
1233 while (day
>= month_days
[leap_year( year
)][month
])
1235 day
-= month_days
[leap_year( year
)][month
];
1240 len
= sprintf( (char *)buf
, fmt
, year
, month
, day
, hour
, min
, sec
);
1243 static const char fmt_frac
[] = ".%07u";
1244 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
1245 while (buf
[len
- 1] == '0') len
--;
1247 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
1251 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
1253 static const char fmt_tz
[] = "%c%02u:00";
1254 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
1260 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1262 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1263 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1264 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1265 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1268 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
1270 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1271 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1272 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1273 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1276 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
1278 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1283 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
1284 x
= (bin
[0] & 3) << 4;
1287 buf
[i
++] = base64
[x
];
1292 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
1293 x
= (bin
[1] & 0x0f) << 2;
1296 buf
[i
++] = base64
[x
];
1300 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
1301 buf
[i
++] = base64
[bin
[2] & 0x3f];
1308 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, WS_XML_UTF8_TEXT
**ret
)
1310 switch (text
->textType
)
1312 case WS_XML_TEXT_TYPE_UTF8
:
1314 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1315 if (!(*ret
= alloc_utf8_text( src
->value
.bytes
, src
->value
.length
))) return E_OUTOFMEMORY
;
1318 case WS_XML_TEXT_TYPE_UTF16
:
1320 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1321 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1322 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1324 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1325 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1326 if (!(*ret
= alloc_utf8_text( NULL
, len_utf8
))) return E_OUTOFMEMORY
;
1327 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
, (*ret
)->value
.length
, NULL
, NULL
);
1330 case WS_XML_TEXT_TYPE_BASE64
:
1332 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
1333 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
1334 if (!(*ret
= alloc_utf8_text( NULL
, len
))) return E_OUTOFMEMORY
;
1335 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
);
1338 case WS_XML_TEXT_TYPE_BOOL
:
1340 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1341 if (!(*ret
= alloc_utf8_text( NULL
, 5 ))) return E_OUTOFMEMORY
;
1342 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
);
1345 case WS_XML_TEXT_TYPE_INT32
:
1347 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1348 unsigned char buf
[12]; /* "-2147483648" */
1349 ULONG len
= format_int32( &int32_text
->value
, buf
);
1350 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1353 case WS_XML_TEXT_TYPE_INT64
:
1355 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1356 unsigned char buf
[21]; /* "-9223372036854775808" */
1357 ULONG len
= format_int64( &int64_text
->value
, buf
);
1358 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1361 case WS_XML_TEXT_TYPE_UINT64
:
1363 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1364 unsigned char buf
[21]; /* "18446744073709551615" */
1365 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1366 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1369 case WS_XML_TEXT_TYPE_DOUBLE
:
1371 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1372 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
1373 unsigned short fpword
;
1376 if (!set_fp_rounding( &fpword
)) return E_NOTIMPL
;
1377 len
= format_double( &double_text
->value
, buf
);
1378 restore_fp_rounding( fpword
);
1379 if (!len
) return E_NOTIMPL
;
1380 if (!(*ret
= alloc_utf8_text( buf
, len
))) return E_OUTOFMEMORY
;
1383 case WS_XML_TEXT_TYPE_GUID
:
1385 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1386 if (!(*ret
= alloc_utf8_text( NULL
, 37 ))) return E_OUTOFMEMORY
;
1387 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
);
1390 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1392 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1393 if (!(*ret
= alloc_utf8_text( NULL
, 46 ))) return E_OUTOFMEMORY
;
1394 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
);
1397 case WS_XML_TEXT_TYPE_DATETIME
:
1399 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
1400 if (!(*ret
= alloc_utf8_text( NULL
, 34 ))) return E_OUTOFMEMORY
;
1401 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
);
1405 FIXME( "unhandled text type %u\n", text
->textType
);
1410 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
1412 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1413 WS_XML_UTF8_TEXT
*utf8
;
1416 if ((hr
= text_to_utf8text( value
, &utf8
)) != S_OK
) return hr
;
1417 elem
->attributes
[elem
->attributeCount
- 1]->value
= &utf8
->text
;
1421 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
1424 WS_XML_TEXT_NODE
*text
;
1425 WS_XML_UTF8_TEXT
*utf8
;
1428 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
1429 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
1430 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
1432 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1433 if ((hr
= text_to_utf8text( value
, &utf8
)) != S_OK
)
1438 text
= (WS_XML_TEXT_NODE
*)node
;
1439 text
->text
= &utf8
->text
;
1441 write_insert_node( writer
, writer
->current
, node
);
1445 static HRESULT
write_text( struct writer
*writer
)
1447 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)writer
->current
;
1448 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
1451 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
1452 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1454 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
1455 return write_bytes_escape( writer
, utf8
->value
.bytes
, utf8
->value
.length
, escapes
, 3 );
1457 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
1459 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
)) != S_OK
) return hr
;
1460 write_bytes( writer
, utf8
->value
.bytes
, utf8
->value
.length
);
1464 return WS_E_INVALID_FORMAT
;
1467 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
1470 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1471 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
1472 if ((hr
= write_text( writer
)) != S_OK
) return hr
;
1473 writer
->state
= WRITER_STATE_TEXT
;
1477 /**************************************************************************
1478 * WsWriteText [webservices.@]
1480 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
1482 struct writer
*writer
= (struct writer
*)handle
;
1484 TRACE( "%p %p %p\n", handle
, text
, error
);
1486 if (!writer
|| !text
) return E_INVALIDARG
;
1488 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) return write_set_attribute_value( writer
, text
);
1489 return write_text_node( writer
, text
);
1492 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
1496 case WS_ELEMENT_TYPE_MAPPING
:
1497 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1498 return write_text_node( writer
, text
);
1500 case WS_ATTRIBUTE_TYPE_MAPPING
:
1501 return write_set_attribute_value( writer
, text
);
1503 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1504 switch (writer
->state
)
1506 case WRITER_STATE_STARTATTRIBUTE
:
1507 return write_set_attribute_value( writer
, text
);
1509 case WRITER_STATE_STARTELEMENT
:
1510 return write_text_node( writer
, text
);
1513 FIXME( "writer state %u not handled\n", writer
->state
);
1518 FIXME( "mapping %u not implemented\n", mapping
);
1523 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
1525 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
1526 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
1527 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
1528 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
1531 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
1532 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
1533 return write_add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
1536 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
1541 case WS_WRITE_REQUIRED_VALUE
:
1542 case WS_WRITE_NILLABLE_VALUE
:
1543 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
1547 case WS_WRITE_REQUIRED_POINTER
:
1548 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
1551 case WS_WRITE_NILLABLE_POINTER
:
1552 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
1553 *ptr
= *(const void **)value
;
1557 return E_INVALIDARG
;
1561 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1562 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1563 const BOOL
*value
, ULONG size
)
1565 WS_XML_UTF8_TEXT utf8
;
1566 unsigned char buf
[6]; /* "false" */
1572 FIXME( "description not supported\n" );
1576 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1577 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
1578 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1580 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1581 utf8
.value
.bytes
= buf
;
1582 utf8
.value
.length
= format_bool( ptr
, buf
);
1583 return write_type_text( writer
, mapping
, &utf8
.text
);
1586 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1587 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1588 const BOOL
*value
, ULONG size
)
1590 WS_XML_UTF8_TEXT utf8
;
1591 unsigned char buf
[5]; /* "-128" */
1597 FIXME( "description not supported\n" );
1601 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1602 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
1603 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1605 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1606 utf8
.value
.bytes
= buf
;
1607 utf8
.value
.length
= format_int8( ptr
, buf
);
1608 return write_type_text( writer
, mapping
, &utf8
.text
);
1611 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1612 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1613 const BOOL
*value
, ULONG size
)
1615 WS_XML_UTF8_TEXT utf8
;
1616 unsigned char buf
[7]; /* "-32768" */
1622 FIXME( "description not supported\n" );
1626 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1627 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
1628 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1630 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1631 utf8
.value
.bytes
= buf
;
1632 utf8
.value
.length
= format_int16( ptr
, buf
);
1633 return write_type_text( writer
, mapping
, &utf8
.text
);
1636 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1637 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1638 const void *value
, ULONG size
)
1640 WS_XML_UTF8_TEXT utf8
;
1641 unsigned char buf
[12]; /* "-2147483648" */
1647 FIXME( "description not supported\n" );
1651 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1652 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
1653 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1655 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1656 utf8
.value
.bytes
= buf
;
1657 utf8
.value
.length
= format_int32( ptr
, buf
);
1658 return write_type_text( writer
, mapping
, &utf8
.text
);
1661 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1662 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1663 const void *value
, ULONG size
)
1665 WS_XML_UTF8_TEXT utf8
;
1666 unsigned char buf
[21]; /* "-9223372036854775808" */
1672 FIXME( "description not supported\n" );
1676 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1677 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
1678 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1680 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1681 utf8
.value
.bytes
= buf
;
1682 utf8
.value
.length
= format_int64( ptr
, buf
);
1683 return write_type_text( writer
, mapping
, &utf8
.text
);
1686 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1687 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1688 const void *value
, ULONG size
)
1690 WS_XML_UTF8_TEXT utf8
;
1691 unsigned char buf
[4]; /* "255" */
1697 FIXME( "description not supported\n" );
1701 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1702 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
1703 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1705 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1706 utf8
.value
.bytes
= buf
;
1707 utf8
.value
.length
= format_uint8( ptr
, buf
);
1708 return write_type_text( writer
, mapping
, &utf8
.text
);
1711 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1712 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1713 const void *value
, ULONG size
)
1715 WS_XML_UTF8_TEXT utf8
;
1716 unsigned char buf
[6]; /* "65535" */
1722 FIXME( "description not supported\n" );
1726 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1727 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
1728 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1730 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1731 utf8
.value
.bytes
= buf
;
1732 utf8
.value
.length
= format_uint16( ptr
, buf
);
1733 return write_type_text( writer
, mapping
, &utf8
.text
);
1736 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1737 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1738 const void *value
, ULONG size
)
1740 WS_XML_UTF8_TEXT utf8
;
1741 unsigned char buf
[11]; /* "4294967295" */
1747 FIXME( "description not supported\n" );
1751 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1752 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
1753 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1755 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1756 utf8
.value
.bytes
= buf
;
1757 utf8
.value
.length
= format_uint32( ptr
, buf
);
1758 return write_type_text( writer
, mapping
, &utf8
.text
);
1761 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1762 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1763 const void *value
, ULONG size
)
1765 WS_XML_UTF8_TEXT utf8
;
1766 unsigned char buf
[21]; /* "18446744073709551615" */
1772 FIXME( "description not supported\n" );
1776 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1777 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
1778 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1780 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1781 utf8
.value
.bytes
= buf
;
1782 utf8
.value
.length
= format_uint64( ptr
, buf
);
1783 return write_type_text( writer
, mapping
, &utf8
.text
);
1786 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1787 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1788 const void *value
, ULONG size
)
1790 WS_XML_UTF8_TEXT utf8
;
1791 unsigned char buf
[34]; /* "0000-00-00T00:00:00.0000000-00:00" */
1792 const WS_DATETIME
*ptr
;
1797 FIXME( "description not supported\n" );
1801 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1802 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
1803 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1804 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
1806 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1807 utf8
.value
.bytes
= buf
;
1808 utf8
.value
.length
= format_datetime( ptr
, buf
);
1809 return write_type_text( writer
, mapping
, &utf8
.text
);
1812 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1813 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1814 const void *value
, ULONG size
)
1816 WS_XML_UTF8_TEXT utf8
;
1817 unsigned char buf
[37]; /* "00000000-0000-0000-0000-000000000000" */
1823 FIXME( "description not supported\n" );
1827 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1828 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
1829 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1831 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1832 utf8
.value
.bytes
= buf
;
1833 utf8
.value
.length
= format_guid( ptr
, buf
);
1834 return write_type_text( writer
, mapping
, &utf8
.text
);
1837 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1838 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1839 const void *value
, ULONG size
)
1841 WS_XML_UTF16_TEXT utf16
;
1842 const WS_STRING
*ptr
;
1847 FIXME( "description not supported\n" );
1851 if (!option
) return E_INVALIDARG
;
1852 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
1853 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1854 if (!ptr
->length
) return S_OK
;
1856 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
1857 utf16
.bytes
= (BYTE
*)ptr
->chars
;
1858 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
1859 return write_type_text( writer
, mapping
, &utf16
.text
);
1862 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1863 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1864 const void *value
, ULONG size
)
1866 WS_XML_UTF16_TEXT utf16
;
1873 FIXME( "description not supported\n" );
1877 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1878 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
1879 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1880 if (!(len
= strlenW( ptr
))) return S_OK
;
1882 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
1883 utf16
.bytes
= (BYTE
*)ptr
;
1884 utf16
.byteCount
= len
* sizeof(WCHAR
);
1885 return write_type_text( writer
, mapping
, &utf16
.text
);
1888 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1889 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1890 const void *value
, ULONG size
)
1892 WS_XML_BASE64_TEXT base64
;
1893 const WS_BYTES
*ptr
;
1898 FIXME( "description not supported\n" );
1902 if (!option
) return E_INVALIDARG
;
1903 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
1904 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
1905 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
1906 if (!ptr
->length
) return S_OK
;
1908 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
1909 base64
.bytes
= ptr
->bytes
;
1910 base64
.length
= ptr
->length
;
1911 return write_type_text( writer
, mapping
, &base64
.text
);
1914 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1915 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1916 const void *value
, ULONG size
)
1918 WS_XML_UTF8_TEXT utf8
;
1919 const WS_XML_STRING
*ptr
;
1924 FIXME( "description not supported\n" );
1928 if (!option
) return E_INVALIDARG
;
1929 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
1930 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1931 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
1932 if (!ptr
->length
) return S_OK
;
1934 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1935 utf8
.value
.bytes
= ptr
->bytes
;
1936 utf8
.value
.length
= ptr
->length
;
1937 return write_type_text( writer
, mapping
, &utf8
.text
);
1940 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
1942 if (options
& WS_FIELD_POINTER
)
1944 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
1945 return WS_WRITE_REQUIRED_POINTER
;
1956 case WS_UINT16_TYPE
:
1957 case WS_UINT32_TYPE
:
1958 case WS_UINT64_TYPE
:
1959 case WS_DOUBLE_TYPE
:
1960 case WS_DATETIME_TYPE
:
1962 case WS_STRING_TYPE
:
1964 case WS_XML_STRING_TYPE
:
1965 case WS_STRUCT_TYPE
:
1967 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
1968 return WS_WRITE_REQUIRED_VALUE
;
1971 case WS_DESCRIPTION_TYPE
:
1972 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
1973 return WS_WRITE_REQUIRED_POINTER
;
1976 FIXME( "unhandled type %u\n", type
);
1981 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
1982 const void *, ULONG
);
1984 static HRESULT
write_type_repeating_element( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
1985 const char *buf
, ULONG count
)
1988 ULONG i
, size
, offset
= 0;
1989 WS_WRITE_OPTION option
;
1991 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
1993 /* wrapper element */
1994 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
1997 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
1998 size
= get_type_size( desc
->type
, desc
->typeDescription
);
2000 size
= sizeof(const void *);
2002 for (i
= 0; i
< count
; i
++)
2004 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
2005 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
2006 buf
+ offset
, size
)) != S_OK
) return hr
;
2007 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2011 if (desc
->localName
) hr
= write_endelement_node( writer
);
2015 static HRESULT
write_type_struct_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
2016 const char *buf
, ULONG offset
)
2019 WS_TYPE_MAPPING mapping
;
2020 WS_WRITE_OPTION option
;
2021 ULONG count
, size
, field_options
= desc
->options
;
2022 const char *ptr
= buf
+ offset
;
2024 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
2026 FIXME( "options 0x%x not supported\n", desc
->options
);
2030 /* zero-terminated strings are always pointers */
2031 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
2033 if (field_options
& WS_FIELD_POINTER
)
2034 size
= sizeof(const void *);
2036 size
= get_type_size( desc
->type
, desc
->typeDescription
);
2038 if (is_nil_value( ptr
, size
))
2040 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
2041 if (field_options
& WS_FIELD_NILLABLE
)
2043 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
2044 else option
= WS_WRITE_NILLABLE_VALUE
;
2046 else return E_INVALIDARG
;
2050 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
2051 else option
= WS_WRITE_REQUIRED_VALUE
;
2054 switch (desc
->mapping
)
2056 case WS_ATTRIBUTE_FIELD_MAPPING
:
2057 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
2058 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
2060 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2062 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2065 case WS_ELEMENT_FIELD_MAPPING
:
2066 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
2067 mapping
= WS_ELEMENT_TYPE_MAPPING
;
2070 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
2071 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
2072 return write_type_repeating_element( writer
, desc
, *(const char **)ptr
, count
);
2074 case WS_TEXT_FIELD_MAPPING
:
2075 switch (writer
->state
)
2077 case WRITER_STATE_STARTELEMENT
:
2078 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
2081 case WRITER_STATE_STARTATTRIBUTE
:
2082 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2086 FIXME( "unhandled writer state %u\n", writer
->state
);
2092 FIXME( "field mapping %u not supported\n", desc
->mapping
);
2096 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
2101 case WS_ATTRIBUTE_TYPE_MAPPING
:
2102 writer
->state
= WRITER_STATE_STARTELEMENT
;
2105 case WS_ELEMENT_TYPE_MAPPING
:
2106 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2115 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2116 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2117 const void *value
, ULONG size
)
2123 if (!desc
) return E_INVALIDARG
;
2124 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
2126 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
2128 for (i
= 0; i
< desc
->fieldCount
; i
++)
2130 offset
= desc
->fields
[i
]->offset
;
2131 if ((hr
= write_type_struct_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
)
2139 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
2140 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
2146 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
2149 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
2152 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
2155 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
2158 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
2161 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
2163 case WS_UINT16_TYPE
:
2164 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
2166 case WS_UINT32_TYPE
:
2167 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
2169 case WS_UINT64_TYPE
:
2170 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
2172 case WS_DATETIME_TYPE
:
2173 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
2176 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
2178 case WS_STRING_TYPE
:
2179 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
2182 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
2185 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
2187 case WS_XML_STRING_TYPE
:
2188 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
2190 case WS_STRUCT_TYPE
:
2191 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
2194 FIXME( "type %u not supported\n", type
);
2199 /**************************************************************************
2200 * WsWriteAttribute [webservices.@]
2202 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
2203 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
2206 struct writer
*writer
= (struct writer
*)handle
;
2209 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
2210 if (error
) FIXME( "ignoring error parameter\n" );
2212 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
2213 return E_INVALIDARG
;
2215 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
2217 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
,
2218 FALSE
)) != S_OK
) return hr
;
2219 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2221 return write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
2222 option
, value
, size
);
2225 /**************************************************************************
2226 * WsWriteElement [webservices.@]
2228 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
2229 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
2232 struct writer
*writer
= (struct writer
*)handle
;
2235 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
2236 if (error
) FIXME( "ignoring error parameter\n" );
2238 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
2239 return E_INVALIDARG
;
2241 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) return hr
;
2243 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
2244 option
, value
, size
)) != S_OK
) return hr
;
2246 return write_endelement_node( writer
);
2249 /**************************************************************************
2250 * WsWriteType [webservices.@]
2252 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
2253 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
2254 ULONG size
, WS_ERROR
*error
)
2256 struct writer
*writer
= (struct writer
*)handle
;
2259 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
2261 if (error
) FIXME( "ignoring error parameter\n" );
2263 if (!writer
|| !value
) return E_INVALIDARG
;
2267 case WS_ATTRIBUTE_TYPE_MAPPING
:
2268 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) return WS_E_INVALID_FORMAT
;
2269 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
2272 case WS_ELEMENT_TYPE_MAPPING
:
2273 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2274 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_FORMAT
;
2275 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
2278 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2279 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
2283 FIXME( "mapping %u not implemented\n", mapping
);
2290 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
2294 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
2295 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
2296 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
2297 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
2298 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
2299 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
2300 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
2301 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
2302 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
2303 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
2304 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
2305 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
2306 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
2307 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
2308 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
2310 FIXME( "unhandled type %u\n", type
);
2315 /**************************************************************************
2316 * WsWriteValue [webservices.@]
2318 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
2319 ULONG size
, WS_ERROR
*error
)
2321 struct writer
*writer
= (struct writer
*)handle
;
2322 WS_TYPE_MAPPING mapping
;
2325 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
2326 if (error
) FIXME( "ignoring error parameter\n" );
2328 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
2330 switch (writer
->state
)
2332 case WRITER_STATE_STARTATTRIBUTE
:
2333 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2336 case WRITER_STATE_STARTELEMENT
:
2337 mapping
= WS_ELEMENT_TYPE_MAPPING
;
2341 return WS_E_INVALID_FORMAT
;
2344 return write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
2347 /**************************************************************************
2348 * WsWriteArray [webservices.@]
2350 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2351 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
2352 ULONG count
, WS_ERROR
*error
)
2354 struct writer
*writer
= (struct writer
*)handle
;
2359 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
2360 value_type
, array
, size
, offset
, count
, error
);
2361 if (error
) FIXME( "ignoring error parameter\n" );
2363 if (!writer
) return E_INVALIDARG
;
2364 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2365 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
2367 type_size
= get_type_size( type
, NULL
);
2368 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
)) return E_INVALIDARG
;
2370 for (i
= offset
; i
< count
; i
++)
2372 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
2373 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) return hr
;
2374 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
2375 &ptr
, sizeof(ptr
) )) != S_OK
) return hr
;
2376 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2382 /**************************************************************************
2383 * WsWriteXmlBuffer [webservices.@]
2385 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
2387 struct writer
*writer
= (struct writer
*)handle
;
2388 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
2391 TRACE( "%p %p %p\n", handle
, buffer
, error
);
2392 if (error
) FIXME( "ignoring error parameter\n" );
2394 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
2396 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2397 if ((hr
= write_grow_buffer( writer
, xmlbuf
->size
)) != S_OK
) return hr
;
2398 write_bytes( writer
, xmlbuf
->ptr
, xmlbuf
->size
);
2402 /**************************************************************************
2403 * WsWriteXmlBufferToBytes [webservices.@]
2405 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
2406 const WS_XML_WRITER_ENCODING
*encoding
,
2407 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
2408 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
2410 struct writer
*writer
= (struct writer
*)handle
;
2411 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
2416 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
2417 bytes
, size
, error
);
2418 if (error
) FIXME( "ignoring error parameter\n" );
2420 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
2422 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
2424 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
2428 for (i
= 0; i
< count
; i
++)
2430 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
2431 properties
[i
].valueSize
);
2432 if (hr
!= S_OK
) return hr
;
2435 if (!(buf
= ws_alloc( heap
, xmlbuf
->size
))) return WS_E_QUOTA_EXCEEDED
;
2436 memcpy( buf
, xmlbuf
->ptr
, xmlbuf
->size
);
2438 *size
= xmlbuf
->size
;
2442 /**************************************************************************
2443 * WsWriteXmlnsAttribute [webservices.@]
2445 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2446 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
2448 struct writer
*writer
= (struct writer
*)handle
;
2450 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
2452 if (error
) FIXME( "ignoring error parameter\n" );
2454 if (!writer
|| !ns
) return E_INVALIDARG
;
2455 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
2457 if (namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
)) return S_OK
;
2458 return write_add_namespace_attribute( writer
, prefix
, ns
, single
);
2461 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
2463 BOOL success
= FALSE
;
2464 struct node
*node
= writer
->current
;
2468 case WS_MOVE_TO_ROOT_ELEMENT
:
2469 success
= move_to_root_element( writer
->root
, &node
);
2472 case WS_MOVE_TO_NEXT_ELEMENT
:
2473 success
= move_to_next_element( &node
);
2476 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
2477 success
= move_to_prev_element( &node
);
2480 case WS_MOVE_TO_CHILD_ELEMENT
:
2481 success
= move_to_child_element( &node
);
2484 case WS_MOVE_TO_END_ELEMENT
:
2485 success
= move_to_end_element( &node
);
2488 case WS_MOVE_TO_PARENT_ELEMENT
:
2489 success
= move_to_parent_element( &node
);
2492 case WS_MOVE_TO_FIRST_NODE
:
2493 success
= move_to_first_node( &node
);
2496 case WS_MOVE_TO_NEXT_NODE
:
2497 success
= move_to_next_node( &node
);
2500 case WS_MOVE_TO_PREVIOUS_NODE
:
2501 success
= move_to_prev_node( &node
);
2504 case WS_MOVE_TO_CHILD_NODE
:
2505 success
= move_to_child_node( &node
);
2508 case WS_MOVE_TO_BOF
:
2509 success
= move_to_bof( writer
->root
, &node
);
2512 case WS_MOVE_TO_EOF
:
2513 success
= move_to_eof( writer
->root
, &node
);
2517 FIXME( "unhandled move %u\n", move
);
2521 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
2522 writer
->current
= node
;
2529 return success
? S_OK
: WS_E_INVALID_FORMAT
;
2532 /**************************************************************************
2533 * WsMoveWriter [webservices.@]
2535 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
2537 struct writer
*writer
= (struct writer
*)handle
;
2539 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
2540 if (error
) FIXME( "ignoring error parameter\n" );
2542 if (!writer
) return E_INVALIDARG
;
2543 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2545 return write_move_to( writer
, move
, found
);
2548 /**************************************************************************
2549 * WsGetWriterPosition [webservices.@]
2551 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
2553 struct writer
*writer
= (struct writer
*)handle
;
2555 TRACE( "%p %p %p\n", handle
, pos
, error
);
2556 if (error
) FIXME( "ignoring error parameter\n" );
2558 if (!writer
|| !pos
) return E_INVALIDARG
;
2559 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2561 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
2562 pos
->node
= writer
->current
;
2566 /**************************************************************************
2567 * WsSetWriterPosition [webservices.@]
2569 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
2571 struct writer
*writer
= (struct writer
*)handle
;
2573 TRACE( "%p %p %p\n", handle
, pos
, error
);
2574 if (error
) FIXME( "ignoring error parameter\n" );
2576 if (!writer
|| !pos
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
) return E_INVALIDARG
;
2577 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2579 writer
->current
= pos
->node
;
2583 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
2585 struct node
*node
, *parent
;
2586 WS_XML_COMMENT_NODE
*comment
;
2588 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2589 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
2590 comment
= (WS_XML_COMMENT_NODE
*)node
;
2592 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
2595 return E_OUTOFMEMORY
;
2597 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
2598 comment
->value
.length
= value
->length
;
2600 write_insert_node( writer
, parent
, node
);
2604 static HRESULT
write_comment( struct writer
*writer
)
2606 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
2609 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
2610 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
2611 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
2612 write_bytes( writer
, (const BYTE
*)"-->", 3 );
2616 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
2619 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2620 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
2621 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
2622 writer
->state
= WRITER_STATE_COMMENT
;
2626 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
2631 for (i
= 0; i
< count
; i
++)
2633 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
2634 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
2635 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
2640 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
2644 switch (node
->nodeType
)
2646 case WS_XML_NODE_TYPE_ELEMENT
:
2648 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
2649 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
2650 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
2652 case WS_XML_NODE_TYPE_TEXT
:
2654 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
2655 return write_text_node( writer
, text
->text
);
2657 case WS_XML_NODE_TYPE_END_ELEMENT
:
2658 return write_endelement_node( writer
);
2660 case WS_XML_NODE_TYPE_COMMENT
:
2662 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
2663 return write_comment_node( writer
, &comment
->value
);
2665 case WS_XML_NODE_TYPE_CDATA
:
2666 return write_cdata_node( writer
);
2668 case WS_XML_NODE_TYPE_END_CDATA
:
2669 return write_endcdata_node( writer
);
2671 case WS_XML_NODE_TYPE_EOF
:
2672 case WS_XML_NODE_TYPE_BOF
:
2676 WARN( "unknown node type %u\n", node
->nodeType
);
2677 return E_INVALIDARG
;
2681 /**************************************************************************
2682 * WsWriteNode [webservices.@]
2684 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
2686 struct writer
*writer
= (struct writer
*)handle
;
2688 TRACE( "%p %p %p\n", handle
, node
, error
);
2689 if (error
) FIXME( "ignoring error parameter\n" );
2691 if (!writer
|| !node
) return E_INVALIDARG
;
2692 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
2694 return write_node( writer
, node
);
2697 static HRESULT
write_tree_node( struct writer
*writer
)
2701 switch (node_type( writer
->current
))
2703 case WS_XML_NODE_TYPE_ELEMENT
:
2704 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2706 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
2707 writer
->state
= WRITER_STATE_STARTELEMENT
;
2710 case WS_XML_NODE_TYPE_TEXT
:
2711 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2713 if ((hr
= write_text( writer
)) != S_OK
) return hr
;
2714 writer
->state
= WRITER_STATE_TEXT
;
2717 case WS_XML_NODE_TYPE_END_ELEMENT
:
2718 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
2719 writer
->state
= WRITER_STATE_ENDELEMENT
;
2722 case WS_XML_NODE_TYPE_COMMENT
:
2723 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2725 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
2726 writer
->state
= WRITER_STATE_COMMENT
;
2729 case WS_XML_NODE_TYPE_CDATA
:
2730 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
2732 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
2733 writer
->state
= WRITER_STATE_STARTCDATA
;
2736 case WS_XML_NODE_TYPE_END_CDATA
:
2737 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
2738 writer
->state
= WRITER_STATE_ENDCDATA
;
2741 case WS_XML_NODE_TYPE_EOF
:
2742 case WS_XML_NODE_TYPE_BOF
:
2746 ERR( "unknown node type %u\n", node_type(writer
->current
) );
2747 return E_INVALIDARG
;
2751 static HRESULT
write_tree( struct writer
*writer
)
2755 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2758 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
2759 if (move_to_child_node( &writer
->current
))
2761 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2764 if (move_to_next_node( &writer
->current
))
2766 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2769 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
2771 ERR( "invalid tree\n" );
2772 return WS_E_INVALID_FORMAT
;
2774 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
2779 static void write_rewind( struct writer
*writer
)
2781 writer
->write_pos
= 0;
2782 writer
->current
= writer
->root
;
2783 writer
->state
= WRITER_STATE_INITIAL
;
2786 /**************************************************************************
2787 * WsCopyNode [webservices.@]
2789 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
2791 struct writer
*writer
= (struct writer
*)handle
;
2792 struct node
*parent
, *current
= writer
->current
, *node
= NULL
;
2795 TRACE( "%p %p %p\n", handle
, reader
, error
);
2796 if (error
) FIXME( "ignoring error parameter\n" );
2798 if (!writer
) return E_INVALIDARG
;
2799 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2801 if ((hr
= copy_node( reader
, &node
)) != S_OK
) return hr
;
2802 write_insert_node( writer
, parent
, node
);
2804 write_rewind( writer
);
2805 if ((hr
= write_tree( writer
)) != S_OK
) return hr
;
2807 writer
->current
= current
;
2811 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
2813 return write_type_struct_field( writer
, desc
, value
, 0 );
2816 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
2819 for (i
= 0; i
< count
; i
++)
2821 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
2823 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
2829 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
2832 return write_type_repeating_element( writer
, desc
, value
, len
);
2835 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
2836 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
2838 struct writer
*writer
= (struct writer
*)handle
;
2839 const WS_STRUCT_DESCRIPTION
*desc_struct
;
2840 const WS_FIELD_DESCRIPTION
*desc_field
;
2844 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
2846 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) return hr
;
2848 for (i
= 0; i
< count
; i
++)
2850 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
2851 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
2853 FIXME( "messages type not supported\n" );
2856 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) return hr
;
2857 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
2859 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) return hr
;
2861 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
2863 const void *ptr
= *(const void **)args
[i
];
2864 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
2865 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) return hr
;
2869 return write_endelement_node( writer
);