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
,
77 unsigned char *write_bufptr
;
78 enum writer_state state
;
81 WS_XML_STRING
*current_ns
;
82 WS_XML_WRITER_ENCODING_TYPE output_enc
;
83 WS_CHARSET output_charset
;
84 WS_XML_WRITER_OUTPUT_TYPE output_type
;
85 struct xmlbuf
*output_buf
;
87 WS_XML_DICTIONARY
*dict
;
88 WS_DYNAMIC_STRING_CALLBACK dict_cb
;
91 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
94 #define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T')
96 static struct writer
*alloc_writer(void)
98 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
100 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
102 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
104 ret
->magic
= WRITER_MAGIC
;
105 InitializeCriticalSection( &ret
->cs
);
106 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": writer.cs");
108 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
109 ret
->prop_count
= count
;
113 static void free_writer( struct writer
*writer
)
115 destroy_nodes( writer
->root
);
116 free_xml_string( writer
->current_ns
);
117 WsFreeHeap( writer
->output_heap
);
119 writer
->cs
.DebugInfo
->Spare
[0] = 0;
120 DeleteCriticalSection( &writer
->cs
);
124 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
126 if (!writer
->root
) writer
->root
= eof
;
129 eof
->parent
= writer
->root
;
130 list_add_tail( &writer
->root
->children
, &eof
->entry
);
132 writer
->current
= eof
;
135 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
137 writer
->root
->parent
= bof
;
138 list_add_tail( &bof
->children
, &writer
->root
->entry
);
139 writer
->current
= writer
->root
= bof
;
142 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
144 node
->parent
= parent
;
145 list_add_before( list_tail( &parent
->children
), &node
->entry
);
146 writer
->current
= node
;
149 static struct node
*find_parent( struct writer
*writer
)
151 if (is_valid_parent( writer
->current
)) return writer
->current
;
152 if (is_valid_parent( writer
->current
->parent
)) return writer
->current
->parent
;
156 static HRESULT
init_writer( struct writer
*writer
)
160 writer
->write_pos
= 0;
161 writer
->write_bufptr
= NULL
;
162 destroy_nodes( writer
->root
);
163 writer
->root
= writer
->current
= NULL
;
164 free_xml_string( writer
->current_ns
);
165 writer
->current_ns
= NULL
;
167 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
168 write_insert_eof( writer
, node
);
169 writer
->state
= WRITER_STATE_INITIAL
;
170 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
171 writer
->output_charset
= WS_CHARSET_UTF8
;
173 writer
->dict_cb
= NULL
;
174 writer
->dict_cb_state
= NULL
;
178 /**************************************************************************
179 * WsCreateWriter [webservices.@]
181 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
182 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
184 struct writer
*writer
;
185 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
186 WS_CHARSET charset
= WS_CHARSET_UTF8
;
189 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
190 if (error
) FIXME( "ignoring error parameter\n" );
192 if (!handle
) return E_INVALIDARG
;
193 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
195 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
196 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
197 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
198 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
199 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
200 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
201 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
203 for (i
= 0; i
< count
; i
++)
205 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
206 properties
[i
].valueSize
);
209 free_writer( writer
);
214 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
215 &max_size
, sizeof(max_size
) );
218 free_writer( writer
);
222 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
225 free_writer( writer
);
229 hr
= init_writer( writer
);
232 free_writer( writer
);
236 *handle
= (WS_XML_WRITER
*)writer
;
240 /**************************************************************************
241 * WsFreeWriter [webservices.@]
243 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
245 struct writer
*writer
= (struct writer
*)handle
;
247 TRACE( "%p\n", handle
);
251 EnterCriticalSection( &writer
->cs
);
253 if (writer
->magic
!= WRITER_MAGIC
)
255 LeaveCriticalSection( &writer
->cs
);
261 LeaveCriticalSection( &writer
->cs
);
262 free_writer( writer
);
265 /**************************************************************************
266 * WsGetWriterProperty [webservices.@]
268 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
269 void *buf
, ULONG size
, WS_ERROR
*error
)
271 struct writer
*writer
= (struct writer
*)handle
;
274 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
275 if (error
) FIXME( "ignoring error parameter\n" );
277 if (!writer
) return E_INVALIDARG
;
279 EnterCriticalSection( &writer
->cs
);
281 if (writer
->magic
!= WRITER_MAGIC
)
283 LeaveCriticalSection( &writer
->cs
);
287 if (!writer
->output_type
)
289 LeaveCriticalSection( &writer
->cs
);
290 return WS_E_INVALID_OPERATION
;
295 case WS_XML_WRITER_PROPERTY_BYTES
:
297 WS_BYTES
*bytes
= buf
;
298 if (size
!= sizeof(*bytes
)) hr
= E_INVALIDARG
;
301 bytes
->bytes
= writer
->output_buf
->bytes
.bytes
;
302 bytes
->length
= writer
->output_buf
->bytes
.length
;
306 case WS_XML_WRITER_PROPERTY_BUFFERS
:
307 if (writer
->output_buf
->bytes
.length
)
309 WS_BUFFERS
*buffers
= buf
;
310 if (size
!= sizeof(*buffers
)) hr
= E_INVALIDARG
;
313 buffers
->bufferCount
= 1;
314 buffers
->buffers
= &writer
->output_buf
->bytes
;
320 hr
= prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
323 LeaveCriticalSection( &writer
->cs
);
327 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
329 /* free current buffer if it's ours */
330 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
332 free_xmlbuf( writer
->output_buf
);
334 writer
->output_buf
= xmlbuf
;
335 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
336 writer
->write_bufptr
= xmlbuf
->bytes
.bytes
;
337 writer
->write_pos
= 0;
340 /**************************************************************************
341 * WsSetOutput [webservices.@]
343 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
344 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
345 ULONG count
, WS_ERROR
*error
)
347 struct writer
*writer
= (struct writer
*)handle
;
352 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
353 if (error
) FIXME( "ignoring error parameter\n" );
355 if (!writer
) return E_INVALIDARG
;
357 EnterCriticalSection( &writer
->cs
);
359 if (writer
->magic
!= WRITER_MAGIC
)
361 LeaveCriticalSection( &writer
->cs
);
365 for (i
= 0; i
< count
; i
++)
367 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
368 properties
[i
].valueSize
);
369 if (hr
!= S_OK
) goto done
;
372 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
374 switch (encoding
->encodingType
)
376 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
378 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
379 if (text
->charSet
!= WS_CHARSET_UTF8
)
381 FIXME( "charset %u not supported\n", text
->charSet
);
385 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
386 writer
->output_charset
= WS_CHARSET_UTF8
;
389 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
391 WS_XML_WRITER_BINARY_ENCODING
*bin
= (WS_XML_WRITER_BINARY_ENCODING
*)encoding
;
392 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_BINARY
;
393 writer
->output_charset
= 0;
394 writer
->dict
= bin
->staticDictionary
;
395 writer
->dict_cb
= bin
->dynamicStringCallback
;
396 writer
->dict_cb_state
= bin
->dynamicStringCallbackState
;
400 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
405 switch (output
->outputType
)
407 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
409 struct xmlbuf
*xmlbuf
;
410 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
, writer
->output_enc
, writer
->output_charset
)))
412 hr
= WS_E_QUOTA_EXCEEDED
;
415 set_output_buffer( writer
, xmlbuf
);
419 FIXME( "output type %u not supported\n", output
->outputType
);
424 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
425 else write_insert_bof( writer
, node
);
428 LeaveCriticalSection( &writer
->cs
);
432 /**************************************************************************
433 * WsSetOutputToBuffer [webservices.@]
435 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
436 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
439 struct writer
*writer
= (struct writer
*)handle
;
440 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
445 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
446 if (error
) FIXME( "ignoring error parameter\n" );
448 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
450 EnterCriticalSection( &writer
->cs
);
452 if (writer
->magic
!= WRITER_MAGIC
)
454 LeaveCriticalSection( &writer
->cs
);
458 for (i
= 0; i
< count
; i
++)
460 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
461 properties
[i
].valueSize
);
462 if (hr
!= S_OK
) goto done
;
465 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
466 writer
->output_enc
= xmlbuf
->encoding
;
467 writer
->output_charset
= xmlbuf
->charset
;
468 set_output_buffer( writer
, xmlbuf
);
470 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
471 else write_insert_bof( writer
, node
);
474 LeaveCriticalSection( &writer
->cs
);
478 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
480 struct xmlbuf
*buf
= writer
->output_buf
;
484 if (buf
->size
>= writer
->write_pos
+ size
)
486 buf
->bytes
.length
= writer
->write_pos
+ size
;
489 new_size
= max( buf
->size
* 2, writer
->write_pos
+ size
);
490 if (!(tmp
= ws_realloc( buf
->heap
, buf
->bytes
.bytes
, buf
->size
, new_size
))) return WS_E_QUOTA_EXCEEDED
;
491 writer
->write_bufptr
= buf
->bytes
.bytes
= tmp
;
492 buf
->size
= new_size
;
493 buf
->bytes
.length
= writer
->write_pos
+ size
;
497 static inline void write_char( struct writer
*writer
, unsigned char ch
)
499 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
502 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
504 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
505 writer
->write_pos
+= len
;
514 static const struct escape escape_lt
= { '<', "<", 4 };
515 static const struct escape escape_gt
= { '>', ">", 4 };
516 static const struct escape escape_amp
= { '&', "&", 5 };
517 static const struct escape escape_apos
= { '\'', "'", 6 };
518 static const struct escape escape_quot
= { '"', """, 6 };
520 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
521 const struct escape
**escapes
, ULONG nb_escapes
)
527 for (i
= 0; i
< len
; i
++)
531 for (j
= 0; j
< nb_escapes
; j
++)
533 if (bytes
[i
] == escapes
[j
]->ch
)
535 ptr
= (const BYTE
*)escapes
[j
]->entity
;
536 size
= escapes
[j
]->len
;
540 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
541 write_bytes( writer
, ptr
, size
);
547 static HRESULT
write_attribute_value_text( struct writer
*writer
, const WS_XML_TEXT
*text
, BOOL single
)
549 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
;
550 const struct escape
*escapes
[3];
552 escapes
[0] = single
? &escape_apos
: &escape_quot
;
553 escapes
[1] = &escape_lt
;
554 escapes
[2] = &escape_amp
;
555 return write_bytes_escape( writer
, utf8
->value
.bytes
, utf8
->value
.length
, escapes
, 3 );
558 static HRESULT
write_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
560 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
561 const WS_XML_STRING
*prefix
= NULL
;
565 if (attr
->prefix
) prefix
= attr
->prefix
;
567 /* ' prefix:attr="value"' */
569 size
= attr
->localName
->length
+ 4 /* ' =""' */;
570 if (prefix
&& prefix
->length
) size
+= prefix
->length
+ 1 /* ':' */;
571 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
573 write_char( writer
, ' ' );
574 if (prefix
&& prefix
->length
)
576 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
577 write_char( writer
, ':' );
579 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
580 write_char( writer
, '=' );
581 write_char( writer
, quote
);
582 if (attr
->value
) hr
= write_attribute_value_text( writer
, attr
->value
, attr
->singleQuote
);
583 write_char( writer
, quote
);
588 static HRESULT
write_int31( struct writer
*writer
, ULONG len
)
592 if (len
> 0x7fffffff) return E_INVALIDARG
;
594 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
597 write_char( writer
, len
);
600 write_char( writer
, (len
& 0x7f) | 0x80 );
602 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
603 if ((len
>>= 7) < 0x80)
605 write_char( writer
, len
);
608 write_char( writer
, (len
& 0x7f) | 0x80 );
610 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
611 if ((len
>>= 7) < 0x80)
613 write_char( writer
, len
);
616 write_char( writer
, (len
& 0x7f) | 0x80 );
618 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
619 if ((len
>>= 7) < 0x80)
621 write_char( writer
, len
);
624 write_char( writer
, (len
& 0x7f) | 0x80 );
626 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
627 if ((len
>>= 7) < 0x08)
629 write_char( writer
, len
);
632 return WS_E_INVALID_FORMAT
;
635 static HRESULT
write_string( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
638 if ((hr
= write_int31( writer
, len
)) != S_OK
) return hr
;
639 if ((hr
= write_grow_buffer( writer
, len
)) != S_OK
) return hr
;
640 write_bytes( writer
, bytes
, len
);
644 static HRESULT
write_dict_string( struct writer
*writer
, ULONG id
)
647 if (id
> 0x7fffffff) return E_INVALIDARG
;
648 if ((hr
= write_int31( writer
, id
)) != S_OK
) return hr
;
652 static enum record_type
get_text_record_type( const WS_XML_TEXT
*text
, BOOL attr
)
654 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
655 if (!utf8
|| utf8
->value
.length
<= 0xff) return attr
? RECORD_CHARS8_TEXT
: RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
659 static HRESULT
write_attribute_value_bin( struct writer
*writer
, const WS_XML_TEXT
*text
)
661 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
;
662 enum record_type type
= get_text_record_type( text
, TRUE
);
665 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
666 write_char( writer
, type
);
670 case RECORD_CHARS8_TEXT
:
671 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
672 if (!utf8
|| !utf8
->value
.length
) write_char( writer
, 0 );
675 write_char( writer
, utf8
->value
.length
);
676 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
)) != S_OK
) return hr
;
677 write_bytes( writer
, utf8
->value
.bytes
, utf8
->value
.length
);
682 ERR( "unhandled record type %02x\n", type
);
683 return WS_E_NOT_SUPPORTED
;
687 static BOOL
lookup_string_id( struct writer
*writer
, const WS_XML_STRING
*str
, ULONG
*id
)
689 if (writer
->dict
&& str
->dictionary
== writer
->dict
)
697 writer
->dict_cb( writer
->dict_cb_state
, str
, &found
, id
, NULL
);
698 if (found
) *id
= (*id
<< 1) | 1;
704 static enum record_type
get_attr_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
706 if (!attr
->prefix
|| !attr
->prefix
->length
)
708 if (use_dict
) return RECORD_SHORT_DICTIONARY_ATTRIBUTE
;
709 return RECORD_SHORT_ATTRIBUTE
;
711 if (attr
->prefix
->length
== 1 && attr
->prefix
->bytes
[0] >= 'a' && attr
->prefix
->bytes
[0] <= 'z')
713 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
714 return RECORD_PREFIX_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
716 if (use_dict
) return RECORD_DICTIONARY_ATTRIBUTE
;
717 return RECORD_ATTRIBUTE
;
720 static HRESULT
write_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
723 enum record_type type
= get_attr_record_type( attr
, lookup_string_id(writer
, attr
->localName
, &id
) );
726 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
727 write_char( writer
, type
);
729 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
731 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
732 return write_attribute_value_bin( writer
, attr
->value
);
734 if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
736 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
737 return write_attribute_value_bin( writer
, attr
->value
);
742 case RECORD_SHORT_ATTRIBUTE
:
743 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
746 case RECORD_ATTRIBUTE
:
747 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
748 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
751 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
752 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
755 case RECORD_DICTIONARY_ATTRIBUTE
:
756 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
757 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
761 ERR( "unhandled record type %02x\n", type
);
762 return WS_E_NOT_SUPPORTED
;
765 return write_attribute_value_bin( writer
, attr
->value
);
768 static HRESULT
write_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
770 switch (writer
->output_enc
)
772 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_attribute_text( writer
, attr
);
773 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_attribute_bin( writer
, attr
);
775 ERR( "unhandled encoding %u\n", writer
->output_enc
);
776 return WS_E_NOT_SUPPORTED
;
780 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
782 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
785 /**************************************************************************
786 * WsGetPrefixFromNamespace [webservices.@]
788 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
789 BOOL required
, const WS_XML_STRING
**prefix
,
792 struct writer
*writer
= (struct writer
*)handle
;
793 WS_XML_ELEMENT_NODE
*elem
;
797 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
798 if (error
) FIXME( "ignoring error parameter\n" );
800 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
802 EnterCriticalSection( &writer
->cs
);
804 if (writer
->magic
!= WRITER_MAGIC
)
806 LeaveCriticalSection( &writer
->cs
);
810 elem
= &writer
->current
->hdr
;
811 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
813 *prefix
= elem
->prefix
;
819 if (required
) hr
= WS_E_INVALID_FORMAT
;
827 LeaveCriticalSection( &writer
->cs
);
831 static HRESULT
write_namespace_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
833 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
837 /* ' xmlns:prefix="namespace"' */
839 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
840 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
841 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
843 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
846 write_char( writer
, ':' );
847 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
849 write_char( writer
, '=' );
850 write_char( writer
, quote
);
851 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
852 write_char( writer
, quote
);
857 static enum record_type
get_xmlns_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
859 if (!attr
->prefix
|| !attr
->prefix
->length
)
861 if (use_dict
) return RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
;
862 return RECORD_SHORT_XMLNS_ATTRIBUTE
;
864 if (use_dict
) return RECORD_DICTIONARY_XMLNS_ATTRIBUTE
;
865 return RECORD_XMLNS_ATTRIBUTE
;
868 static HRESULT
write_namespace_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
871 enum record_type type
= get_xmlns_record_type( attr
, lookup_string_id(writer
, attr
->ns
, &id
) );
874 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
875 write_char( writer
, type
);
879 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
882 case RECORD_XMLNS_ATTRIBUTE
:
883 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
886 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
887 return write_dict_string( writer
, id
);
889 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
890 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
891 return write_dict_string( writer
, id
);
894 ERR( "unhandled record type %02x\n", type
);
895 return WS_E_NOT_SUPPORTED
;
898 return write_string( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
901 static HRESULT
write_namespace_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
903 switch (writer
->output_enc
)
905 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_namespace_attribute_text( writer
, attr
);
906 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_namespace_attribute_bin( writer
, attr
);
908 ERR( "unhandled encoding %u\n", writer
->output_enc
);
909 return WS_E_NOT_SUPPORTED
;
913 static HRESULT
add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
914 const WS_XML_STRING
*ns
, BOOL single
)
916 WS_XML_ATTRIBUTE
*attr
;
917 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
920 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
922 attr
->singleQuote
= !!single
;
924 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
)))
926 free_attribute( attr
);
927 return E_OUTOFMEMORY
;
929 if (!(attr
->ns
= dup_xml_string( ns
)))
931 free_attribute( attr
);
932 return E_OUTOFMEMORY
;
934 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
936 free_attribute( attr
);
942 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
944 if (!str1
&& !str2
) return TRUE
;
945 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
948 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
949 const WS_XML_STRING
*ns
)
952 const struct node
*node
;
954 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
956 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
959 for (i
= 0; i
< elem
->attributeCount
; i
++)
961 if (!elem
->attributes
[i
]->isXmlNs
) continue;
962 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
963 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
969 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
972 if (!(str
= dup_xml_string( ns
))) return E_OUTOFMEMORY
;
973 free_xml_string( writer
->current_ns
);
974 writer
->current_ns
= str
;
978 static HRESULT
set_namespaces( struct writer
*writer
)
980 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
984 if (elem
->ns
->length
&& !namespace_in_scope( elem
, elem
->prefix
, elem
->ns
))
986 if ((hr
= add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
) return hr
;
987 if ((hr
= set_current_namespace( writer
, elem
->ns
)) != S_OK
) return hr
;
990 for (i
= 0; i
< elem
->attributeCount
; i
++)
992 const WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
993 if (!attr
->ns
->length
|| namespace_in_scope( elem
, attr
->prefix
, attr
->ns
)) continue;
994 if ((hr
= add_namespace_attribute( writer
, attr
->prefix
, attr
->ns
, FALSE
)) != S_OK
) return hr
;
1000 /**************************************************************************
1001 * WsWriteEndAttribute [webservices.@]
1003 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1005 struct writer
*writer
= (struct writer
*)handle
;
1007 TRACE( "%p %p\n", handle
, error
);
1008 if (error
) FIXME( "ignoring error parameter\n" );
1010 if (!writer
) return E_INVALIDARG
;
1012 EnterCriticalSection( &writer
->cs
);
1014 if (writer
->magic
!= WRITER_MAGIC
)
1016 LeaveCriticalSection( &writer
->cs
);
1017 return E_INVALIDARG
;
1020 writer
->state
= WRITER_STATE_STARTELEMENT
;
1022 LeaveCriticalSection( &writer
->cs
);
1026 static HRESULT
write_attributes( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1030 for (i
= 0; i
< elem
->attributeCount
; i
++)
1032 if (elem
->attributes
[i
]->isXmlNs
) continue;
1033 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1035 for (i
= 0; i
< elem
->attributeCount
; i
++)
1037 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
1038 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1040 for (i
= 0; i
< elem
->attributeCount
; i
++)
1042 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
1043 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1048 static HRESULT
write_startelement_text( struct writer
*writer
)
1050 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1054 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
1056 size
= elem
->localName
->length
+ 1 /* '<' */;
1057 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1058 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1060 write_char( writer
, '<' );
1061 if (elem
->prefix
&& elem
->prefix
->length
)
1063 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1064 write_char( writer
, ':' );
1066 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1067 return write_attributes( writer
, elem
);
1070 static enum record_type
get_elem_record_type( const WS_XML_ELEMENT_NODE
*elem
, BOOL use_dict
)
1072 if (!elem
->prefix
|| !elem
->prefix
->length
)
1074 if (use_dict
) return RECORD_SHORT_DICTIONARY_ELEMENT
;
1075 return RECORD_SHORT_ELEMENT
;
1077 if (elem
->prefix
->length
== 1 && elem
->prefix
->bytes
[0] >= 'a' && elem
->prefix
->bytes
[0] <= 'z')
1079 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1080 return RECORD_PREFIX_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1082 if (use_dict
) return RECORD_DICTIONARY_ELEMENT
;
1083 return RECORD_ELEMENT
;
1086 static HRESULT
write_startelement_bin( struct writer
*writer
)
1088 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1090 enum record_type type
= get_elem_record_type( elem
, lookup_string_id(writer
, elem
->localName
, &id
) );
1093 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1094 write_char( writer
, type
);
1096 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1098 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1099 return write_attributes( writer
, elem
);
1101 if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1103 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1104 return write_attributes( writer
, elem
);
1109 case RECORD_SHORT_ELEMENT
:
1110 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1113 case RECORD_ELEMENT
:
1114 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1115 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1118 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1119 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1122 case RECORD_DICTIONARY_ELEMENT
:
1123 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1124 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1128 ERR( "unhandled record type %02x\n", type
);
1129 return WS_E_NOT_SUPPORTED
;
1132 return write_attributes( writer
, elem
);
1135 static HRESULT
write_startelement( struct writer
*writer
)
1137 switch (writer
->output_enc
)
1139 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_startelement_text( writer
);
1140 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_startelement_bin( writer
);
1142 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1143 return WS_E_NOT_SUPPORTED
;
1147 static struct node
*write_find_startelement( struct writer
*writer
)
1150 for (node
= writer
->current
; node
; node
= node
->parent
)
1152 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
1157 static inline BOOL
is_empty_element( const struct node
*node
)
1159 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
1160 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
1163 static HRESULT
write_endelement_text( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1170 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
1172 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1173 write_char( writer
, '/' );
1174 write_char( writer
, '>' );
1178 /* '</prefix:localname>' */
1180 size
= elem
->localName
->length
+ 3 /* '</>' */;
1181 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1182 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1184 write_char( writer
, '<' );
1185 write_char( writer
, '/' );
1186 if (elem
->prefix
&& elem
->prefix
->length
)
1188 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1189 write_char( writer
, ':' );
1191 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1192 write_char( writer
, '>' );
1196 static HRESULT
write_endelement_bin( struct writer
*writer
)
1199 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_TEXT
) return S_OK
;
1200 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1201 write_char( writer
, RECORD_ENDELEMENT
);
1205 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1207 switch (writer
->output_enc
)
1209 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endelement_text( writer
, elem
);
1210 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_endelement_bin( writer
);
1212 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1213 return WS_E_NOT_SUPPORTED
;
1217 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
1219 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
1220 elem
->isEmpty
= is_empty_element( node
);
1221 return write_endelement( writer
, elem
);
1224 static HRESULT
write_endelement_node( struct writer
*writer
)
1229 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
1230 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1232 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1233 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1235 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
1236 writer
->current
= node
->parent
;
1237 writer
->state
= WRITER_STATE_ENDELEMENT
;
1241 /**************************************************************************
1242 * WsWriteEndElement [webservices.@]
1244 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1246 struct writer
*writer
= (struct writer
*)handle
;
1249 TRACE( "%p %p\n", handle
, error
);
1250 if (error
) FIXME( "ignoring error parameter\n" );
1252 if (!writer
) return E_INVALIDARG
;
1254 EnterCriticalSection( &writer
->cs
);
1256 if (writer
->magic
!= WRITER_MAGIC
)
1258 LeaveCriticalSection( &writer
->cs
);
1259 return E_INVALIDARG
;
1262 hr
= write_endelement_node( writer
);
1264 LeaveCriticalSection( &writer
->cs
);
1268 static HRESULT
write_endstartelement_text( struct writer
*writer
)
1271 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1272 write_char( writer
, '>' );
1276 static HRESULT
write_endstartelement( struct writer
*writer
)
1278 switch (writer
->output_enc
)
1280 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endstartelement_text( writer
);
1281 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return S_OK
;
1283 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1284 return WS_E_NOT_SUPPORTED
;
1288 /**************************************************************************
1289 * WsWriteEndStartElement [webservices.@]
1291 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1293 struct writer
*writer
= (struct writer
*)handle
;
1296 TRACE( "%p %p\n", handle
, error
);
1297 if (error
) FIXME( "ignoring error parameter\n" );
1299 if (!writer
) return E_INVALIDARG
;
1301 EnterCriticalSection( &writer
->cs
);
1303 if (writer
->magic
!= WRITER_MAGIC
)
1305 LeaveCriticalSection( &writer
->cs
);
1306 return E_INVALIDARG
;
1309 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1311 LeaveCriticalSection( &writer
->cs
);
1312 return WS_E_INVALID_OPERATION
;
1315 if ((hr
= set_namespaces( writer
)) != S_OK
) goto done
;
1316 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
1317 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
1318 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1321 LeaveCriticalSection( &writer
->cs
);
1325 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1326 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1329 WS_XML_ATTRIBUTE
*attr
;
1330 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1333 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1335 if (!prefix
&& ns
->length
) prefix
= elem
->prefix
;
1337 attr
->singleQuote
= !!single
;
1338 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
)))
1340 free_attribute( attr
);
1341 return E_OUTOFMEMORY
;
1343 if (!(attr
->localName
= dup_xml_string( localname
)))
1345 free_attribute( attr
);
1346 return E_OUTOFMEMORY
;
1348 if (!(attr
->ns
= dup_xml_string( ns
)))
1350 free_attribute( attr
);
1351 return E_OUTOFMEMORY
;
1353 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1355 free_attribute( attr
);
1361 /**************************************************************************
1362 * WsWriteStartAttribute [webservices.@]
1364 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1365 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1366 BOOL single
, WS_ERROR
*error
)
1368 struct writer
*writer
= (struct writer
*)handle
;
1371 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1372 debugstr_xmlstr(ns
), single
, error
);
1373 if (error
) FIXME( "ignoring error parameter\n" );
1375 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1377 EnterCriticalSection( &writer
->cs
);
1379 if (writer
->magic
!= WRITER_MAGIC
)
1381 LeaveCriticalSection( &writer
->cs
);
1382 return E_INVALIDARG
;
1385 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1387 LeaveCriticalSection( &writer
->cs
);
1388 return WS_E_INVALID_OPERATION
;
1391 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
1392 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1394 LeaveCriticalSection( &writer
->cs
);
1398 /* flush current start element if necessary */
1399 static HRESULT
write_flush( struct writer
*writer
)
1401 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1404 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1405 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1406 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
1407 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1412 static HRESULT
write_add_cdata_node( struct writer
*writer
)
1414 struct node
*node
, *parent
;
1415 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1416 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1417 write_insert_node( writer
, parent
, node
);
1421 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
1424 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
1425 node
->parent
= writer
->current
;
1426 list_add_tail( &node
->parent
->children
, &node
->entry
);
1430 static HRESULT
write_cdata( struct writer
*writer
)
1433 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
1434 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
1438 static HRESULT
write_cdata_node( struct writer
*writer
)
1441 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1442 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
1443 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
1444 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
1445 writer
->state
= WRITER_STATE_STARTCDATA
;
1449 /**************************************************************************
1450 * WsWriteStartCData [webservices.@]
1452 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1454 struct writer
*writer
= (struct writer
*)handle
;
1457 TRACE( "%p %p\n", handle
, error
);
1458 if (error
) FIXME( "ignoring error parameter\n" );
1460 if (!writer
) return E_INVALIDARG
;
1462 EnterCriticalSection( &writer
->cs
);
1464 if (writer
->magic
!= WRITER_MAGIC
)
1466 LeaveCriticalSection( &writer
->cs
);
1467 return E_INVALIDARG
;
1470 hr
= write_cdata_node( writer
);
1472 LeaveCriticalSection( &writer
->cs
);
1476 static HRESULT
write_endcdata( struct writer
*writer
)
1479 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
1480 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
1484 static HRESULT
write_endcdata_node( struct writer
*writer
)
1487 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
1488 writer
->current
= writer
->current
->parent
;
1489 writer
->state
= WRITER_STATE_ENDCDATA
;
1493 /**************************************************************************
1494 * WsWriteEndCData [webservices.@]
1496 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1498 struct writer
*writer
= (struct writer
*)handle
;
1501 TRACE( "%p %p\n", handle
, error
);
1502 if (error
) FIXME( "ignoring error parameter\n" );
1504 if (!writer
) return E_INVALIDARG
;
1506 EnterCriticalSection( &writer
->cs
);
1508 if (writer
->magic
!= WRITER_MAGIC
)
1510 LeaveCriticalSection( &writer
->cs
);
1511 return E_INVALIDARG
;
1514 if (writer
->state
!= WRITER_STATE_TEXT
)
1516 LeaveCriticalSection( &writer
->cs
);
1517 return WS_E_INVALID_OPERATION
;
1520 hr
= write_endcdata_node( writer
);
1522 LeaveCriticalSection( &writer
->cs
);
1526 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1527 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1529 struct node
*node
, *parent
;
1530 WS_XML_ELEMENT_NODE
*elem
;
1532 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1534 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1536 elem
= &parent
->hdr
;
1537 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
1540 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
1543 if (prefix
&& !(elem
->prefix
= dup_xml_string( prefix
)))
1546 return E_OUTOFMEMORY
;
1548 if (!(elem
->localName
= dup_xml_string( localname
)))
1551 return E_OUTOFMEMORY
;
1553 if (!(elem
->ns
= dup_xml_string( ns
)))
1556 return E_OUTOFMEMORY
;
1558 write_insert_node( writer
, parent
, node
);
1562 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
1565 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1566 node
->parent
= parent
;
1567 list_add_tail( &parent
->children
, &node
->entry
);
1571 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1572 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1575 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1576 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
1577 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
1578 writer
->state
= WRITER_STATE_STARTELEMENT
;
1582 /**************************************************************************
1583 * WsWriteStartElement [webservices.@]
1585 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1586 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1589 struct writer
*writer
= (struct writer
*)handle
;
1592 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1593 debugstr_xmlstr(ns
), error
);
1594 if (error
) FIXME( "ignoring error parameter\n" );
1596 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1598 EnterCriticalSection( &writer
->cs
);
1600 if (writer
->magic
!= WRITER_MAGIC
)
1602 LeaveCriticalSection( &writer
->cs
);
1603 return E_INVALIDARG
;
1606 hr
= write_element_node( writer
, prefix
, localname
, ns
);
1608 LeaveCriticalSection( &writer
->cs
);
1612 ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
1614 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1617 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1618 return sizeof(bool_true
);
1620 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1621 return sizeof(bool_false
);
1624 ULONG
format_int8( const INT8
*ptr
, unsigned char *buf
)
1626 return wsprintfA( (char *)buf
, "%d", *ptr
);
1629 ULONG
format_int16( const INT16
*ptr
, unsigned char *buf
)
1631 return wsprintfA( (char *)buf
, "%d", *ptr
);
1634 ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1636 return wsprintfA( (char *)buf
, "%d", *ptr
);
1639 ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1641 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1644 static ULONG
format_uint8( const UINT8
*ptr
, unsigned char *buf
)
1646 return wsprintfA( (char *)buf
, "%u", *ptr
);
1649 static ULONG
format_uint16( const UINT16
*ptr
, unsigned char *buf
)
1651 return wsprintfA( (char *)buf
, "%u", *ptr
);
1654 static ULONG
format_uint32( const UINT32
*ptr
, unsigned char *buf
)
1656 return wsprintfA( (char *)buf
, "%u", *ptr
);
1659 ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1661 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1664 ULONG
format_double( const double *ptr
, unsigned char *buf
)
1667 static const long double precision
= 0.0000000000000001;
1668 unsigned char *p
= buf
;
1669 long double val
= *ptr
;
1670 int neg
, mag
, mag2
, use_exp
;
1674 memcpy( buf
, "NaN", 3 );
1681 memcpy( buf
, "-INF", 4 );
1684 memcpy( buf
, "INF", 3 );
1693 if ((neg
= val
< 0))
1699 mag
= log10l( val
);
1700 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1703 if (mag
< 0) mag
-= 1;
1704 val
= val
/ powl( 10.0, mag
);
1708 else if (mag
< 1) mag
= 0;
1710 while (val
> precision
|| mag
>= 0)
1712 long double weight
= powl( 10.0, mag
);
1713 if (weight
> 0 && !isinf( weight
))
1715 int digit
= floorl( val
/ weight
);
1716 val
-= digit
* weight
;
1717 *(p
++) = '0' + digit
;
1719 if (!mag
&& val
> precision
) *(p
++) = '.';
1727 if (mag2
> 0) *(p
++) = '+';
1736 *(p
++) = '0' + mag2
% 10;
1740 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1750 FIXME( "powl not found at build time\n" );
1755 static inline int year_size( int year
)
1757 return leap_year( year
) ? 366 : 365;
1761 ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
1763 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
1764 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
1765 unsigned __int64 ticks
, day_ticks
;
1768 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
1769 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
1771 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1772 tz_hour
= TZ_OFFSET
;
1779 day
= ticks
/ TICKS_PER_DAY
;
1780 day_ticks
= ticks
% TICKS_PER_DAY
;
1781 hour
= day_ticks
/ TICKS_PER_HOUR
;
1782 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1783 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1784 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1786 while (day
>= year_size( year
))
1788 day
-= year_size( year
);
1791 while (day
>= month_days
[leap_year( year
)][month
])
1793 day
-= month_days
[leap_year( year
)][month
];
1797 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
1800 static const char fmt_frac
[] = ".%07u";
1801 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
1802 while (buf
[len
- 1] == '0') len
--;
1804 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
1808 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
1810 static const char fmt_tz
[] = "%c%02u:00";
1811 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
1817 ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1819 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1820 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1821 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1822 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1825 ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
1827 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1828 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1829 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1830 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1833 static ULONG
format_qname( const WS_XML_STRING
*prefix
, const WS_XML_STRING
*localname
, unsigned char *buf
)
1836 if (prefix
&& prefix
->length
)
1838 memcpy( buf
, prefix
->bytes
, prefix
->length
);
1839 len
+= prefix
->length
;
1842 memcpy( buf
+ len
, localname
->bytes
, localname
->length
);
1843 return len
+ localname
->length
;
1846 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
1848 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1853 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
1854 x
= (bin
[0] & 3) << 4;
1857 buf
[i
++] = base64
[x
];
1862 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
1863 x
= (bin
[1] & 0x0f) << 2;
1866 buf
[i
++] = base64
[x
];
1870 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
1871 buf
[i
++] = base64
[bin
[2] & 0x3f];
1878 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, WS_XML_UTF8_TEXT
**ret
)
1880 ULONG len_old
= old
? old
->value
.length
: 0;
1882 switch (text
->textType
)
1884 case WS_XML_TEXT_TYPE_UTF8
:
1886 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1888 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
1889 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1890 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
1893 case WS_XML_TEXT_TYPE_UTF16
:
1895 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1896 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1897 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1899 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1900 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1901 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
1902 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1903 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
1906 case WS_XML_TEXT_TYPE_BASE64
:
1908 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
1909 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
1911 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1912 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1913 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1916 case WS_XML_TEXT_TYPE_BOOL
:
1918 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1920 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
1921 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1922 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1925 case WS_XML_TEXT_TYPE_INT32
:
1927 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1928 unsigned char buf
[12]; /* "-2147483648" */
1929 ULONG len
= format_int32( &int32_text
->value
, buf
);
1931 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1932 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1933 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1936 case WS_XML_TEXT_TYPE_INT64
:
1938 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1939 unsigned char buf
[21]; /* "-9223372036854775808" */
1940 ULONG len
= format_int64( &int64_text
->value
, buf
);
1942 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1943 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1944 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1947 case WS_XML_TEXT_TYPE_UINT64
:
1949 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1950 unsigned char buf
[21]; /* "18446744073709551615" */
1951 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1953 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1954 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1955 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1958 case WS_XML_TEXT_TYPE_DOUBLE
:
1960 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1961 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
1962 unsigned short fpword
;
1965 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
1966 len
= format_double( &double_text
->value
, buf
);
1967 restore_fpword( fpword
);
1968 if (!len
) return E_NOTIMPL
;
1970 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1971 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1972 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1975 case WS_XML_TEXT_TYPE_GUID
:
1977 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1979 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
1980 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1981 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1984 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1986 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1988 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
1989 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1990 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1993 case WS_XML_TEXT_TYPE_DATETIME
:
1995 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
1997 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
1998 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1999 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2002 case WS_XML_TEXT_TYPE_QNAME
:
2004 const WS_XML_QNAME_TEXT
*qn
= (const WS_XML_QNAME_TEXT
*)text
;
2005 ULONG len
= qn
->localName
->length
;
2007 if (qn
->prefix
&& qn
->prefix
->length
) len
+= qn
->prefix
->length
+ 1;
2008 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2009 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2010 (*ret
)->value
.length
= format_qname( qn
->prefix
, qn
->localName
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2014 FIXME( "unhandled text type %u\n", text
->textType
);
2019 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
2021 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2022 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
2025 switch (value
->textType
)
2027 case WS_XML_TEXT_TYPE_UTF8
:
2028 case WS_XML_TEXT_TYPE_UTF16
:
2029 case WS_XML_TEXT_TYPE_BASE64
:
2032 case WS_XML_TEXT_TYPE_BOOL
:
2033 case WS_XML_TEXT_TYPE_INT32
:
2034 case WS_XML_TEXT_TYPE_INT64
:
2035 case WS_XML_TEXT_TYPE_UINT64
:
2036 case WS_XML_TEXT_TYPE_DOUBLE
:
2037 case WS_XML_TEXT_TYPE_GUID
:
2038 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2039 case WS_XML_TEXT_TYPE_DATETIME
:
2040 if (old
) return WS_E_INVALID_OPERATION
;
2044 FIXME( "unhandled text type %u\n", value
->textType
);
2048 if ((hr
= text_to_utf8text( value
, old
, &new )) != S_OK
) return hr
;
2051 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
2056 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
2059 WS_XML_TEXT_NODE
*text
;
2060 WS_XML_UTF8_TEXT
*utf8
;
2063 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
2064 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
2065 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
2067 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2068 if ((hr
= text_to_utf8text( value
, NULL
, &utf8
)) != S_OK
)
2073 text
= (WS_XML_TEXT_NODE
*)node
;
2074 text
->text
= &utf8
->text
;
2076 write_insert_node( writer
, writer
->current
, node
);
2080 static HRESULT
write_text_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2082 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2085 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2087 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
2088 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
2090 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
2092 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
2093 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
2097 return WS_E_INVALID_FORMAT
;
2100 static HRESULT
write_text_bin( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2102 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2103 enum record_type type
= get_text_record_type( text
, FALSE
);
2108 FIXME( "no support for appending text in binary mode\n" );
2109 return WS_E_NOT_SUPPORTED
;
2114 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2115 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
2116 write_char( writer
, type
);
2117 if (!utf8
|| !utf8
->value
.length
) write_char( writer
, 0 );
2120 write_char( writer
, utf8
->value
.length
);
2121 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
)) != S_OK
) return hr
;
2122 write_bytes( writer
, utf8
->value
.bytes
, utf8
->value
.length
);
2127 FIXME( "unhandled record type %02x\n", type
);
2128 return WS_E_NOT_SUPPORTED
;
2132 static HRESULT
write_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2134 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
2136 switch (writer
->output_enc
)
2138 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_text_text( writer
, text
, offset
);
2139 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_text_bin( writer
, text
, offset
);
2141 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2142 return WS_E_NOT_SUPPORTED
;
2146 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
2148 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2152 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2153 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
2156 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
2157 node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2161 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
2163 offset
= old
->value
.length
;
2164 if ((hr
= text_to_utf8text( text
, old
, &new )) != S_OK
) return hr
;
2166 node
->text
= &new->text
;
2169 if ((hr
= write_text( writer
, node
->text
, offset
)) != S_OK
) return hr
;
2171 writer
->state
= WRITER_STATE_TEXT
;
2175 /**************************************************************************
2176 * WsWriteText [webservices.@]
2178 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
2180 struct writer
*writer
= (struct writer
*)handle
;
2183 TRACE( "%p %p %p\n", handle
, text
, error
);
2184 if (error
) FIXME( "ignoring error parameter\n" );
2186 if (!writer
|| !text
) return E_INVALIDARG
;
2188 EnterCriticalSection( &writer
->cs
);
2190 if (writer
->magic
!= WRITER_MAGIC
)
2192 LeaveCriticalSection( &writer
->cs
);
2193 return E_INVALIDARG
;
2196 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
2197 else hr
= write_text_node( writer
, text
);
2199 LeaveCriticalSection( &writer
->cs
);
2203 /**************************************************************************
2204 * WsWriteBytes [webservices.@]
2206 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
2208 struct writer
*writer
= (struct writer
*)handle
;
2209 WS_XML_BASE64_TEXT base64
;
2212 TRACE( "%p %p %u %p\n", handle
, bytes
, count
, error
);
2213 if (error
) FIXME( "ignoring error parameter\n" );
2215 if (!writer
) return E_INVALIDARG
;
2217 EnterCriticalSection( &writer
->cs
);
2219 if (writer
->magic
!= WRITER_MAGIC
)
2221 LeaveCriticalSection( &writer
->cs
);
2222 return E_INVALIDARG
;
2225 if (!writer
->output_type
)
2227 LeaveCriticalSection( &writer
->cs
);
2228 return WS_E_INVALID_OPERATION
;
2231 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2232 base64
.bytes
= (BYTE
*)bytes
;
2233 base64
.length
= count
;
2235 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
2236 else hr
= write_text_node( writer
, &base64
.text
);
2238 LeaveCriticalSection( &writer
->cs
);
2242 /**************************************************************************
2243 * WsWriteChars [webservices.@]
2245 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
2247 struct writer
*writer
= (struct writer
*)handle
;
2248 WS_XML_UTF16_TEXT utf16
;
2251 TRACE( "%p %s %u %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
2252 if (error
) FIXME( "ignoring error parameter\n" );
2254 if (!writer
) return E_INVALIDARG
;
2256 EnterCriticalSection( &writer
->cs
);
2258 if (writer
->magic
!= WRITER_MAGIC
)
2260 LeaveCriticalSection( &writer
->cs
);
2261 return E_INVALIDARG
;
2264 if (!writer
->output_type
)
2266 LeaveCriticalSection( &writer
->cs
);
2267 return WS_E_INVALID_OPERATION
;
2270 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2271 utf16
.bytes
= (BYTE
*)chars
;
2272 utf16
.byteCount
= count
* sizeof(WCHAR
);
2274 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
2275 else hr
= write_text_node( writer
, &utf16
.text
);
2277 LeaveCriticalSection( &writer
->cs
);
2281 /**************************************************************************
2282 * WsWriteCharsUtf8 [webservices.@]
2284 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
2286 struct writer
*writer
= (struct writer
*)handle
;
2287 WS_XML_UTF8_TEXT utf8
;
2290 TRACE( "%p %s %u %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
2291 if (error
) FIXME( "ignoring error parameter\n" );
2293 if (!writer
) return E_INVALIDARG
;
2295 EnterCriticalSection( &writer
->cs
);
2297 if (writer
->magic
!= WRITER_MAGIC
)
2299 LeaveCriticalSection( &writer
->cs
);
2300 return E_INVALIDARG
;
2303 if (!writer
->output_type
)
2305 LeaveCriticalSection( &writer
->cs
);
2306 return WS_E_INVALID_OPERATION
;
2309 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2310 utf8
.value
.bytes
= (BYTE
*)bytes
;
2311 utf8
.value
.length
= count
;
2313 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
2314 else hr
= write_text_node( writer
, &utf8
.text
);
2316 LeaveCriticalSection( &writer
->cs
);
2320 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
2324 case WS_ELEMENT_TYPE_MAPPING
:
2325 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2326 return write_text_node( writer
, text
);
2328 case WS_ATTRIBUTE_TYPE_MAPPING
:
2329 return write_set_attribute_value( writer
, text
);
2331 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2332 switch (writer
->state
)
2334 case WRITER_STATE_STARTATTRIBUTE
:
2335 return write_set_attribute_value( writer
, text
);
2337 case WRITER_STATE_STARTELEMENT
:
2338 return write_text_node( writer
, text
);
2341 FIXME( "writer state %u not handled\n", writer
->state
);
2346 FIXME( "mapping %u not implemented\n", mapping
);
2351 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
2353 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
2354 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
2355 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
2356 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
2359 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
2360 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
2361 return add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
2364 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
2369 case WS_WRITE_REQUIRED_VALUE
:
2370 case WS_WRITE_NILLABLE_VALUE
:
2371 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
2375 case WS_WRITE_REQUIRED_POINTER
:
2376 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
2379 case WS_WRITE_NILLABLE_POINTER
:
2380 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
2381 *ptr
= *(const void **)value
;
2385 return E_INVALIDARG
;
2389 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2390 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2391 const BOOL
*value
, ULONG size
)
2393 WS_XML_UTF8_TEXT utf8
;
2394 unsigned char buf
[6]; /* "false" */
2400 FIXME( "description not supported\n" );
2404 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2405 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
2406 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2408 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2409 utf8
.value
.bytes
= buf
;
2410 utf8
.value
.length
= format_bool( ptr
, buf
);
2411 return write_type_text( writer
, mapping
, &utf8
.text
);
2414 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2415 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2416 const BOOL
*value
, ULONG size
)
2418 WS_XML_UTF8_TEXT utf8
;
2419 unsigned char buf
[5]; /* "-128" */
2425 FIXME( "description not supported\n" );
2429 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2430 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
2431 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2433 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2434 utf8
.value
.bytes
= buf
;
2435 utf8
.value
.length
= format_int8( ptr
, buf
);
2436 return write_type_text( writer
, mapping
, &utf8
.text
);
2439 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2440 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2441 const BOOL
*value
, ULONG size
)
2443 WS_XML_UTF8_TEXT utf8
;
2444 unsigned char buf
[7]; /* "-32768" */
2450 FIXME( "description not supported\n" );
2454 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2455 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
2456 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2458 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2459 utf8
.value
.bytes
= buf
;
2460 utf8
.value
.length
= format_int16( ptr
, buf
);
2461 return write_type_text( writer
, mapping
, &utf8
.text
);
2464 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2465 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2466 const void *value
, ULONG size
)
2468 WS_XML_UTF8_TEXT utf8
;
2469 unsigned char buf
[12]; /* "-2147483648" */
2475 FIXME( "description not supported\n" );
2479 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2480 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
2481 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2483 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2484 utf8
.value
.bytes
= buf
;
2485 utf8
.value
.length
= format_int32( ptr
, buf
);
2486 return write_type_text( writer
, mapping
, &utf8
.text
);
2489 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2490 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2491 const void *value
, ULONG size
)
2493 WS_XML_UTF8_TEXT utf8
;
2494 unsigned char buf
[21]; /* "-9223372036854775808" */
2500 FIXME( "description not supported\n" );
2504 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2505 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
2506 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2508 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2509 utf8
.value
.bytes
= buf
;
2510 utf8
.value
.length
= format_int64( ptr
, buf
);
2511 return write_type_text( writer
, mapping
, &utf8
.text
);
2514 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2515 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2516 const void *value
, ULONG size
)
2518 WS_XML_UTF8_TEXT utf8
;
2519 unsigned char buf
[4]; /* "255" */
2525 FIXME( "description not supported\n" );
2529 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2530 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
2531 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2533 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2534 utf8
.value
.bytes
= buf
;
2535 utf8
.value
.length
= format_uint8( ptr
, buf
);
2536 return write_type_text( writer
, mapping
, &utf8
.text
);
2539 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2540 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2541 const void *value
, ULONG size
)
2543 WS_XML_UTF8_TEXT utf8
;
2544 unsigned char buf
[6]; /* "65535" */
2550 FIXME( "description not supported\n" );
2554 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2555 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
2556 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2558 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2559 utf8
.value
.bytes
= buf
;
2560 utf8
.value
.length
= format_uint16( ptr
, buf
);
2561 return write_type_text( writer
, mapping
, &utf8
.text
);
2564 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2565 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2566 const void *value
, ULONG size
)
2568 WS_XML_UTF8_TEXT utf8
;
2569 unsigned char buf
[11]; /* "4294967295" */
2575 FIXME( "description not supported\n" );
2579 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2580 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
2581 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2583 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2584 utf8
.value
.bytes
= buf
;
2585 utf8
.value
.length
= format_uint32( ptr
, buf
);
2586 return write_type_text( writer
, mapping
, &utf8
.text
);
2589 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2590 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2591 const void *value
, ULONG size
)
2593 WS_XML_UTF8_TEXT utf8
;
2594 unsigned char buf
[21]; /* "18446744073709551615" */
2600 FIXME( "description not supported\n" );
2604 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2605 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
2606 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2608 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2609 utf8
.value
.bytes
= buf
;
2610 utf8
.value
.length
= format_uint64( ptr
, buf
);
2611 return write_type_text( writer
, mapping
, &utf8
.text
);
2614 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2615 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2616 const void *value
, ULONG size
)
2618 WS_XML_UTF8_TEXT utf8
;
2619 unsigned char buf
[34]; /* "0000-00-00T00:00:00.0000000-00:00" */
2620 const WS_DATETIME
*ptr
;
2625 FIXME( "description not supported\n" );
2629 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2630 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
2631 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2632 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
2634 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2635 utf8
.value
.bytes
= buf
;
2636 utf8
.value
.length
= format_datetime( ptr
, buf
);
2637 return write_type_text( writer
, mapping
, &utf8
.text
);
2640 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2641 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2642 const void *value
, ULONG size
)
2644 WS_XML_UTF8_TEXT utf8
;
2645 unsigned char buf
[37]; /* "00000000-0000-0000-0000-000000000000" */
2651 FIXME( "description not supported\n" );
2655 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2656 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
2657 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2659 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2660 utf8
.value
.bytes
= buf
;
2661 utf8
.value
.length
= format_guid( ptr
, buf
);
2662 return write_type_text( writer
, mapping
, &utf8
.text
);
2665 static HRESULT
write_type_unique_id( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2666 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2667 const void *value
, ULONG size
)
2669 WS_XML_UTF8_TEXT utf8
;
2670 WS_XML_UTF16_TEXT utf16
;
2671 unsigned char buf
[46]; /* "urn:uuid:00000000-0000-0000-0000-000000000000" */
2672 const WS_UNIQUE_ID
*ptr
;
2677 FIXME( "description not supported\n" );
2681 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2682 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
2683 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2685 if (ptr
->uri
.length
)
2687 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2688 utf16
.bytes
= (BYTE
*)ptr
->uri
.chars
;
2689 utf16
.byteCount
= ptr
->uri
.length
* sizeof(WCHAR
);
2690 return write_type_text( writer
, mapping
, &utf16
.text
);
2693 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2694 utf8
.value
.bytes
= buf
;
2695 utf8
.value
.length
= format_urn( &ptr
->guid
, buf
);
2696 return write_type_text( writer
, mapping
, &utf8
.text
);
2699 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2700 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2701 const void *value
, ULONG size
)
2703 WS_XML_UTF16_TEXT utf16
;
2704 const WS_STRING
*ptr
;
2709 FIXME( "description not supported\n" );
2713 if (!option
) return E_INVALIDARG
;
2714 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
2715 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2716 if (!ptr
->length
) return S_OK
;
2718 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2719 utf16
.bytes
= (BYTE
*)ptr
->chars
;
2720 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
2721 return write_type_text( writer
, mapping
, &utf16
.text
);
2724 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2725 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2726 const void *value
, ULONG size
)
2728 WS_XML_UTF16_TEXT utf16
;
2735 FIXME( "description not supported\n" );
2739 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2740 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
2741 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2742 if (!(len
= strlenW( ptr
))) return S_OK
;
2744 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2745 utf16
.bytes
= (BYTE
*)ptr
;
2746 utf16
.byteCount
= len
* sizeof(WCHAR
);
2747 return write_type_text( writer
, mapping
, &utf16
.text
);
2750 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2751 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2752 const void *value
, ULONG size
)
2754 WS_XML_BASE64_TEXT base64
;
2755 const WS_BYTES
*ptr
;
2760 FIXME( "description not supported\n" );
2764 if (!option
) return E_INVALIDARG
;
2765 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
2766 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
2767 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
2768 if (!ptr
->length
) return S_OK
;
2770 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2771 base64
.bytes
= ptr
->bytes
;
2772 base64
.length
= ptr
->length
;
2773 return write_type_text( writer
, mapping
, &base64
.text
);
2776 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2777 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2778 const void *value
, ULONG size
)
2780 WS_XML_UTF8_TEXT utf8
;
2781 const WS_XML_STRING
*ptr
;
2786 FIXME( "description not supported\n" );
2790 if (!option
) return E_INVALIDARG
;
2791 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
2792 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2793 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
2794 if (!ptr
->length
) return S_OK
;
2796 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2797 utf8
.value
.bytes
= ptr
->bytes
;
2798 utf8
.value
.length
= ptr
->length
;
2799 return write_type_text( writer
, mapping
, &utf8
.text
);
2802 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
2804 const struct node
*node
;
2805 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
2807 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
2809 for (i
= 0; i
< elem
->attributeCount
; i
++)
2811 if (!elem
->attributes
[i
]->isXmlNs
) continue;
2812 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
2813 *prefix
= elem
->attributes
[i
]->prefix
;
2817 return WS_E_INVALID_FORMAT
;
2820 static HRESULT
write_type_qname( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2821 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2822 const void *value
, ULONG size
)
2824 WS_XML_QNAME_TEXT qname
;
2825 const WS_XML_QNAME
*ptr
;
2826 const WS_XML_STRING
*prefix
;
2831 FIXME( "description not supported\n" );
2835 if (!option
) return E_INVALIDARG
;
2836 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
2837 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2838 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
2840 if (((hr
= find_prefix( writer
, &ptr
->ns
, &prefix
)) != S_OK
)) return hr
;
2842 qname
.text
.textType
= WS_XML_TEXT_TYPE_QNAME
;
2843 qname
.prefix
= (WS_XML_STRING
*)prefix
;
2844 qname
.localName
= (WS_XML_STRING
*)&ptr
->localName
;
2845 qname
.ns
= (WS_XML_STRING
*)&ptr
->ns
;
2846 return write_type_text( writer
, mapping
, &qname
.text
);
2849 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
2851 if (options
& WS_FIELD_POINTER
)
2853 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
2854 return WS_WRITE_REQUIRED_POINTER
;
2865 case WS_UINT16_TYPE
:
2866 case WS_UINT32_TYPE
:
2867 case WS_UINT64_TYPE
:
2868 case WS_DOUBLE_TYPE
:
2869 case WS_DATETIME_TYPE
:
2871 case WS_UNIQUE_ID_TYPE
:
2872 case WS_STRING_TYPE
:
2874 case WS_XML_STRING_TYPE
:
2875 case WS_XML_QNAME_TYPE
:
2876 case WS_STRUCT_TYPE
:
2878 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
2879 return WS_WRITE_REQUIRED_VALUE
;
2882 case WS_DESCRIPTION_TYPE
:
2883 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
2884 return WS_WRITE_REQUIRED_POINTER
;
2887 FIXME( "unhandled type %u\n", type
);
2892 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
2893 const void *, ULONG
);
2895 static HRESULT
write_type_repeating_element( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
2896 const char *buf
, ULONG count
)
2899 ULONG i
, size
, offset
= 0;
2900 WS_WRITE_OPTION option
;
2902 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
2904 /* wrapper element */
2905 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
2908 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
2909 size
= get_type_size( desc
->type
, desc
->typeDescription
);
2911 size
= sizeof(const void *);
2913 for (i
= 0; i
< count
; i
++)
2915 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
2916 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
2917 buf
+ offset
, size
)) != S_OK
) return hr
;
2918 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2922 if (desc
->localName
) hr
= write_endelement_node( writer
);
2926 static HRESULT
write_type_field( struct writer
*, const WS_FIELD_DESCRIPTION
*, const char *, ULONG
);
2928 static HRESULT
write_type_union( struct writer
*writer
, const WS_UNION_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2929 const void *value
, ULONG size
)
2936 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
2938 if (size
< sizeof(enum_value
)) return E_INVALIDARG
;
2939 if ((enum_value
= *(int *)(char *)ptr
+ desc
->enumOffset
) == desc
->noneEnumValue
)
2943 case WS_WRITE_REQUIRED_VALUE
:
2944 return WS_E_INVALID_FORMAT
;
2946 case WS_WRITE_NILLABLE_VALUE
:
2950 ERR( "unhandled write option %u\n", option
);
2951 return E_INVALIDARG
;
2955 for (i
= 0; i
< desc
->fieldCount
; i
++)
2957 if (desc
->fields
[i
]->value
== enum_value
)
2959 offset
= desc
->fields
[i
]->field
.offset
;
2960 return write_type_field( writer
, &desc
->fields
[i
]->field
, ptr
, offset
);
2964 return E_INVALIDARG
;
2967 static HRESULT
write_type_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
2971 WS_TYPE_MAPPING mapping
;
2972 WS_WRITE_OPTION option
;
2973 ULONG count
, size
, field_options
= desc
->options
;
2974 const char *ptr
= buf
+ offset
;
2976 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
2978 FIXME( "options 0x%x not supported\n", desc
->options
);
2982 /* zero-terminated strings are always pointers */
2983 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
2985 if (field_options
& WS_FIELD_POINTER
)
2986 size
= sizeof(const void *);
2988 size
= get_type_size( desc
->type
, desc
->typeDescription
);
2990 if (is_nil_value( ptr
, size
))
2992 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
2993 if (field_options
& WS_FIELD_NILLABLE
)
2995 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
2996 else option
= WS_WRITE_NILLABLE_VALUE
;
3000 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3001 else option
= WS_WRITE_REQUIRED_VALUE
;
3006 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3007 else option
= WS_WRITE_REQUIRED_VALUE
;
3010 switch (desc
->mapping
)
3012 case WS_ATTRIBUTE_FIELD_MAPPING
:
3013 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
3014 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
3016 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3018 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3021 case WS_ELEMENT_FIELD_MAPPING
:
3022 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
3023 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3026 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
3027 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
) return E_INVALIDARG
;
3028 option
= (field_options
& WS_FIELD_OPTIONAL
) ? WS_WRITE_NILLABLE_VALUE
: WS_WRITE_REQUIRED_VALUE
;
3029 return write_type_union( writer
, desc
->typeDescription
, option
, ptr
, size
);
3031 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3032 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
3033 return write_type_repeating_element( writer
, desc
, *(const char **)ptr
, count
);
3035 case WS_TEXT_FIELD_MAPPING
:
3036 switch (writer
->state
)
3038 case WRITER_STATE_STARTELEMENT
:
3039 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
3042 case WRITER_STATE_STARTATTRIBUTE
:
3043 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3047 FIXME( "unhandled writer state %u\n", writer
->state
);
3053 FIXME( "field mapping %u not supported\n", desc
->mapping
);
3057 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
3062 case WS_ATTRIBUTE_TYPE_MAPPING
:
3063 writer
->state
= WRITER_STATE_STARTELEMENT
;
3066 case WS_ELEMENT_TYPE_MAPPING
:
3067 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3076 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3077 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3078 const void *value
, ULONG size
)
3084 if (!desc
) return E_INVALIDARG
;
3085 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
3087 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3089 for (i
= 0; i
< desc
->fieldCount
; i
++)
3091 offset
= desc
->fields
[i
]->offset
;
3092 if ((hr
= write_type_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
) return hr
;
3098 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3099 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3105 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
3108 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
3111 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
3114 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
3117 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
3120 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
3122 case WS_UINT16_TYPE
:
3123 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
3125 case WS_UINT32_TYPE
:
3126 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
3128 case WS_UINT64_TYPE
:
3129 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
3131 case WS_DATETIME_TYPE
:
3132 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
3135 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
3137 case WS_UNIQUE_ID_TYPE
:
3138 return write_type_unique_id( writer
, mapping
, desc
, option
, value
, size
);
3140 case WS_STRING_TYPE
:
3141 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
3144 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
3147 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
3149 case WS_XML_STRING_TYPE
:
3150 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
3152 case WS_XML_QNAME_TYPE
:
3153 return write_type_qname( writer
, mapping
, desc
, option
, value
, size
);
3155 case WS_STRUCT_TYPE
:
3156 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
3159 FIXME( "type %u not supported\n", type
);
3164 /**************************************************************************
3165 * WsWriteAttribute [webservices.@]
3167 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
3168 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3171 struct writer
*writer
= (struct writer
*)handle
;
3174 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3175 if (error
) FIXME( "ignoring error parameter\n" );
3177 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
3178 return E_INVALIDARG
;
3180 EnterCriticalSection( &writer
->cs
);
3182 if (writer
->magic
!= WRITER_MAGIC
)
3184 LeaveCriticalSection( &writer
->cs
);
3185 return E_INVALIDARG
;
3188 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3190 LeaveCriticalSection( &writer
->cs
);
3191 return WS_E_INVALID_OPERATION
;
3194 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) != S_OK
)
3196 LeaveCriticalSection( &writer
->cs
);
3199 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3201 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
3203 LeaveCriticalSection( &writer
->cs
);
3207 /**************************************************************************
3208 * WsWriteElement [webservices.@]
3210 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3211 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3214 struct writer
*writer
= (struct writer
*)handle
;
3217 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3218 if (error
) FIXME( "ignoring error parameter\n" );
3220 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
3221 return E_INVALIDARG
;
3223 EnterCriticalSection( &writer
->cs
);
3225 if (writer
->magic
!= WRITER_MAGIC
)
3227 LeaveCriticalSection( &writer
->cs
);
3228 return E_INVALIDARG
;
3231 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
3233 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
3234 option
, value
, size
)) != S_OK
) goto done
;
3236 hr
= write_endelement_node( writer
);
3239 LeaveCriticalSection( &writer
->cs
);
3243 /**************************************************************************
3244 * WsWriteType [webservices.@]
3246 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3247 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3248 ULONG size
, WS_ERROR
*error
)
3250 struct writer
*writer
= (struct writer
*)handle
;
3253 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
3255 if (error
) FIXME( "ignoring error parameter\n" );
3257 if (!writer
|| !value
) return E_INVALIDARG
;
3259 EnterCriticalSection( &writer
->cs
);
3261 if (writer
->magic
!= WRITER_MAGIC
)
3263 LeaveCriticalSection( &writer
->cs
);
3264 return E_INVALIDARG
;
3269 case WS_ATTRIBUTE_TYPE_MAPPING
:
3270 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
3271 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3274 case WS_ELEMENT_TYPE_MAPPING
:
3275 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3276 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_FORMAT
;
3277 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3280 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3281 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3285 FIXME( "mapping %u not implemented\n", mapping
);
3289 LeaveCriticalSection( &writer
->cs
);
3293 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
3297 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
3298 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
3299 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
3300 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
3301 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
3302 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
3303 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
3304 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
3305 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
3306 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
3307 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
3308 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
3309 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
3310 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
3311 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
3313 FIXME( "unhandled type %u\n", type
);
3318 /**************************************************************************
3319 * WsWriteValue [webservices.@]
3321 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
3322 ULONG size
, WS_ERROR
*error
)
3324 struct writer
*writer
= (struct writer
*)handle
;
3325 WS_TYPE_MAPPING mapping
;
3329 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
3330 if (error
) FIXME( "ignoring error parameter\n" );
3332 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
3334 EnterCriticalSection( &writer
->cs
);
3336 if (writer
->magic
!= WRITER_MAGIC
)
3338 LeaveCriticalSection( &writer
->cs
);
3339 return E_INVALIDARG
;
3342 switch (writer
->state
)
3344 case WRITER_STATE_STARTATTRIBUTE
:
3345 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3348 case WRITER_STATE_STARTELEMENT
:
3349 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3353 hr
= WS_E_INVALID_FORMAT
;
3356 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
3358 LeaveCriticalSection( &writer
->cs
);
3362 /**************************************************************************
3363 * WsWriteArray [webservices.@]
3365 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3366 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
3367 ULONG count
, WS_ERROR
*error
)
3369 struct writer
*writer
= (struct writer
*)handle
;
3374 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3375 value_type
, array
, size
, offset
, count
, error
);
3376 if (error
) FIXME( "ignoring error parameter\n" );
3378 if (!writer
) return E_INVALIDARG
;
3380 EnterCriticalSection( &writer
->cs
);
3382 if (writer
->magic
!= WRITER_MAGIC
)
3384 LeaveCriticalSection( &writer
->cs
);
3385 return E_INVALIDARG
;
3388 if (!writer
->output_type
)
3390 LeaveCriticalSection( &writer
->cs
);
3391 return WS_E_INVALID_OPERATION
;
3394 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
3396 LeaveCriticalSection( &writer
->cs
);
3397 return E_INVALIDARG
;
3400 type_size
= get_type_size( type
, NULL
);
3401 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
3403 LeaveCriticalSection( &writer
->cs
);
3404 return E_INVALIDARG
;
3407 for (i
= offset
; i
< count
; i
++)
3409 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
3410 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
3411 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
3412 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
3413 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
3417 LeaveCriticalSection( &writer
->cs
);
3421 /**************************************************************************
3422 * WsWriteXmlBuffer [webservices.@]
3424 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
3426 struct writer
*writer
= (struct writer
*)handle
;
3427 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
3430 TRACE( "%p %p %p\n", handle
, buffer
, error
);
3431 if (error
) FIXME( "ignoring error parameter\n" );
3433 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
3435 EnterCriticalSection( &writer
->cs
);
3437 if (writer
->magic
!= WRITER_MAGIC
)
3439 LeaveCriticalSection( &writer
->cs
);
3440 return E_INVALIDARG
;
3443 if (xmlbuf
->encoding
!= writer
->output_enc
|| xmlbuf
->charset
!= writer
->output_charset
)
3445 FIXME( "no support for different encoding and/or charset\n" );
3450 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
3451 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
3452 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
3455 LeaveCriticalSection( &writer
->cs
);
3459 /**************************************************************************
3460 * WsWriteXmlBufferToBytes [webservices.@]
3462 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
3463 const WS_XML_WRITER_ENCODING
*encoding
,
3464 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
3465 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
3467 struct writer
*writer
= (struct writer
*)handle
;
3468 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
3473 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
3474 bytes
, size
, error
);
3475 if (error
) FIXME( "ignoring error parameter\n" );
3477 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
3479 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
3481 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
3485 EnterCriticalSection( &writer
->cs
);
3487 if (writer
->magic
!= WRITER_MAGIC
)
3489 LeaveCriticalSection( &writer
->cs
);
3490 return E_INVALIDARG
;
3493 for (i
= 0; i
< count
; i
++)
3495 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
3496 properties
[i
].valueSize
);
3497 if (hr
!= S_OK
) goto done
;
3500 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
3503 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
3505 *size
= xmlbuf
->bytes
.length
;
3509 LeaveCriticalSection( &writer
->cs
);
3513 /**************************************************************************
3514 * WsWriteXmlnsAttribute [webservices.@]
3516 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
3517 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
3519 struct writer
*writer
= (struct writer
*)handle
;
3522 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
3524 if (error
) FIXME( "ignoring error parameter\n" );
3526 if (!writer
|| !ns
) return E_INVALIDARG
;
3528 EnterCriticalSection( &writer
->cs
);
3530 if (writer
->magic
!= WRITER_MAGIC
)
3532 LeaveCriticalSection( &writer
->cs
);
3533 return E_INVALIDARG
;
3536 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3538 LeaveCriticalSection( &writer
->cs
);
3539 return WS_E_INVALID_OPERATION
;
3542 if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
3543 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
3545 LeaveCriticalSection( &writer
->cs
);
3549 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
3550 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
3552 WS_XML_QNAME_TEXT qname
= {{WS_XML_TEXT_TYPE_QNAME
}};
3555 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
3556 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) return hr
;
3558 qname
.prefix
= (WS_XML_STRING
*)prefix
;
3559 qname
.localName
= (WS_XML_STRING
*)localname
;
3560 qname
.ns
= (WS_XML_STRING
*)ns
;
3562 if ((hr
= write_add_text_node( writer
, &qname
.text
)) != S_OK
) return hr
;
3563 return write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 );
3566 /**************************************************************************
3567 * WsWriteQualifiedName [webservices.@]
3569 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
3570 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3573 struct writer
*writer
= (struct writer
*)handle
;
3576 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
3577 debugstr_xmlstr(ns
), error
);
3578 if (error
) FIXME( "ignoring error parameter\n" );
3580 if (!writer
) return E_INVALIDARG
;
3582 EnterCriticalSection( &writer
->cs
);
3584 if (writer
->magic
!= WRITER_MAGIC
)
3586 LeaveCriticalSection( &writer
->cs
);
3587 return E_INVALIDARG
;
3590 if (!writer
->output_type
)
3592 LeaveCriticalSection( &writer
->cs
);
3593 return WS_E_INVALID_OPERATION
;
3596 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3598 LeaveCriticalSection( &writer
->cs
);
3599 return WS_E_INVALID_FORMAT
;
3602 if (!localname
|| (!prefix
&& !ns
))
3604 LeaveCriticalSection( &writer
->cs
);
3605 return E_INVALIDARG
;
3608 hr
= write_qualified_name( writer
, prefix
, localname
, ns
);
3610 LeaveCriticalSection( &writer
->cs
);
3614 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
3616 BOOL success
= FALSE
;
3617 struct node
*node
= writer
->current
;
3621 case WS_MOVE_TO_ROOT_ELEMENT
:
3622 success
= move_to_root_element( writer
->root
, &node
);
3625 case WS_MOVE_TO_NEXT_ELEMENT
:
3626 success
= move_to_next_element( &node
);
3629 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
3630 success
= move_to_prev_element( &node
);
3633 case WS_MOVE_TO_CHILD_ELEMENT
:
3634 success
= move_to_child_element( &node
);
3637 case WS_MOVE_TO_END_ELEMENT
:
3638 success
= move_to_end_element( &node
);
3641 case WS_MOVE_TO_PARENT_ELEMENT
:
3642 success
= move_to_parent_element( &node
);
3645 case WS_MOVE_TO_FIRST_NODE
:
3646 success
= move_to_first_node( &node
);
3649 case WS_MOVE_TO_NEXT_NODE
:
3650 success
= move_to_next_node( &node
);
3653 case WS_MOVE_TO_PREVIOUS_NODE
:
3654 success
= move_to_prev_node( &node
);
3657 case WS_MOVE_TO_CHILD_NODE
:
3658 success
= move_to_child_node( &node
);
3661 case WS_MOVE_TO_BOF
:
3662 success
= move_to_bof( writer
->root
, &node
);
3665 case WS_MOVE_TO_EOF
:
3666 success
= move_to_eof( writer
->root
, &node
);
3670 FIXME( "unhandled move %u\n", move
);
3674 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
3675 writer
->current
= node
;
3682 return success
? S_OK
: WS_E_INVALID_FORMAT
;
3685 /**************************************************************************
3686 * WsMoveWriter [webservices.@]
3688 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
3690 struct writer
*writer
= (struct writer
*)handle
;
3693 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
3694 if (error
) FIXME( "ignoring error parameter\n" );
3696 if (!writer
) return E_INVALIDARG
;
3698 EnterCriticalSection( &writer
->cs
);
3700 if (writer
->magic
!= WRITER_MAGIC
)
3702 LeaveCriticalSection( &writer
->cs
);
3703 return E_INVALIDARG
;
3706 if (!writer
->output_type
)
3708 LeaveCriticalSection( &writer
->cs
);
3709 return WS_E_INVALID_OPERATION
;
3712 hr
= write_move_to( writer
, move
, found
);
3714 LeaveCriticalSection( &writer
->cs
);
3718 /**************************************************************************
3719 * WsGetWriterPosition [webservices.@]
3721 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
3723 struct writer
*writer
= (struct writer
*)handle
;
3725 TRACE( "%p %p %p\n", handle
, pos
, error
);
3726 if (error
) FIXME( "ignoring error parameter\n" );
3728 if (!writer
|| !pos
) return E_INVALIDARG
;
3730 EnterCriticalSection( &writer
->cs
);
3732 if (writer
->magic
!= WRITER_MAGIC
)
3734 LeaveCriticalSection( &writer
->cs
);
3735 return E_INVALIDARG
;
3738 if (!writer
->output_type
)
3740 LeaveCriticalSection( &writer
->cs
);
3741 return WS_E_INVALID_OPERATION
;
3744 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
3745 pos
->node
= writer
->current
;
3747 LeaveCriticalSection( &writer
->cs
);
3751 /**************************************************************************
3752 * WsSetWriterPosition [webservices.@]
3754 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
3756 struct writer
*writer
= (struct writer
*)handle
;
3758 TRACE( "%p %p %p\n", handle
, pos
, error
);
3759 if (error
) FIXME( "ignoring error parameter\n" );
3761 if (!writer
|| !pos
) return E_INVALIDARG
;
3763 EnterCriticalSection( &writer
->cs
);
3765 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
3767 LeaveCriticalSection( &writer
->cs
);
3768 return E_INVALIDARG
;
3771 if (!writer
->output_type
)
3773 LeaveCriticalSection( &writer
->cs
);
3774 return WS_E_INVALID_OPERATION
;
3777 writer
->current
= pos
->node
;
3779 LeaveCriticalSection( &writer
->cs
);
3783 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
3785 struct node
*node
, *parent
;
3786 WS_XML_COMMENT_NODE
*comment
;
3788 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
3789 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
3790 comment
= (WS_XML_COMMENT_NODE
*)node
;
3792 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
3795 return E_OUTOFMEMORY
;
3797 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
3798 comment
->value
.length
= value
->length
;
3800 write_insert_node( writer
, parent
, node
);
3804 static HRESULT
write_comment_text( struct writer
*writer
)
3806 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
3809 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
3810 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
3811 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
3812 write_bytes( writer
, (const BYTE
*)"-->", 3 );
3816 static HRESULT
write_comment_bin( struct writer
*writer
)
3818 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
3821 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
3822 write_char( writer
, RECORD_COMMENT
);
3823 return write_string( writer
, comment
->value
.bytes
, comment
->value
.length
);
3826 static HRESULT
write_comment( struct writer
*writer
)
3828 switch (writer
->output_enc
)
3830 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_comment_text( writer
);
3831 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_comment_bin( writer
);
3833 ERR( "unhandled encoding %u\n", writer
->output_enc
);
3834 return WS_E_NOT_SUPPORTED
;
3838 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
3841 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
3842 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
3843 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
3844 writer
->state
= WRITER_STATE_COMMENT
;
3848 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
3853 for (i
= 0; i
< count
; i
++)
3855 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
3856 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
3857 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
3862 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
3866 switch (node
->nodeType
)
3868 case WS_XML_NODE_TYPE_ELEMENT
:
3870 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
3871 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
3872 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
3874 case WS_XML_NODE_TYPE_TEXT
:
3876 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
3877 return write_text_node( writer
, text
->text
);
3879 case WS_XML_NODE_TYPE_END_ELEMENT
:
3880 return write_endelement_node( writer
);
3882 case WS_XML_NODE_TYPE_COMMENT
:
3884 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
3885 return write_comment_node( writer
, &comment
->value
);
3887 case WS_XML_NODE_TYPE_CDATA
:
3888 return write_cdata_node( writer
);
3890 case WS_XML_NODE_TYPE_END_CDATA
:
3891 return write_endcdata_node( writer
);
3893 case WS_XML_NODE_TYPE_EOF
:
3894 case WS_XML_NODE_TYPE_BOF
:
3898 WARN( "unknown node type %u\n", node
->nodeType
);
3899 return E_INVALIDARG
;
3903 /**************************************************************************
3904 * WsWriteNode [webservices.@]
3906 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
3908 struct writer
*writer
= (struct writer
*)handle
;
3911 TRACE( "%p %p %p\n", handle
, node
, error
);
3912 if (error
) FIXME( "ignoring error parameter\n" );
3914 if (!writer
|| !node
) return E_INVALIDARG
;
3916 EnterCriticalSection( &writer
->cs
);
3918 if (writer
->magic
!= WRITER_MAGIC
)
3920 LeaveCriticalSection( &writer
->cs
);
3921 return E_INVALIDARG
;
3924 if (!writer
->output_type
)
3926 LeaveCriticalSection( &writer
->cs
);
3927 return WS_E_INVALID_OPERATION
;
3930 hr
= write_node( writer
, node
);
3932 LeaveCriticalSection( &writer
->cs
);
3936 static HRESULT
write_tree_node( struct writer
*writer
)
3940 switch (node_type( writer
->current
))
3942 case WS_XML_NODE_TYPE_ELEMENT
:
3943 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3945 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
3946 writer
->state
= WRITER_STATE_STARTELEMENT
;
3949 case WS_XML_NODE_TYPE_TEXT
:
3950 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3952 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
3953 writer
->state
= WRITER_STATE_TEXT
;
3956 case WS_XML_NODE_TYPE_END_ELEMENT
:
3957 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
3958 writer
->state
= WRITER_STATE_ENDELEMENT
;
3961 case WS_XML_NODE_TYPE_COMMENT
:
3962 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3964 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
3965 writer
->state
= WRITER_STATE_COMMENT
;
3968 case WS_XML_NODE_TYPE_CDATA
:
3969 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3971 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
3972 writer
->state
= WRITER_STATE_STARTCDATA
;
3975 case WS_XML_NODE_TYPE_END_CDATA
:
3976 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
3977 writer
->state
= WRITER_STATE_ENDCDATA
;
3980 case WS_XML_NODE_TYPE_EOF
:
3981 case WS_XML_NODE_TYPE_BOF
:
3985 ERR( "unknown node type %u\n", node_type(writer
->current
) );
3986 return E_INVALIDARG
;
3990 static HRESULT
write_tree( struct writer
*writer
)
3994 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3997 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
3998 if (move_to_child_node( &writer
->current
))
4000 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4003 if (move_to_next_node( &writer
->current
))
4005 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4008 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
4010 ERR( "invalid tree\n" );
4011 return WS_E_INVALID_FORMAT
;
4013 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4018 static void write_rewind( struct writer
*writer
)
4020 writer
->write_pos
= 0;
4021 writer
->current
= writer
->root
;
4022 writer
->state
= WRITER_STATE_INITIAL
;
4025 /**************************************************************************
4026 * WsCopyNode [webservices.@]
4028 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
4030 struct writer
*writer
= (struct writer
*)handle
;
4031 struct node
*parent
, *current
, *node
= NULL
;
4034 TRACE( "%p %p %p\n", handle
, reader
, error
);
4035 if (error
) FIXME( "ignoring error parameter\n" );
4037 if (!writer
) return E_INVALIDARG
;
4039 EnterCriticalSection( &writer
->cs
);
4041 if (writer
->magic
!= WRITER_MAGIC
)
4043 LeaveCriticalSection( &writer
->cs
);
4044 return E_INVALIDARG
;
4047 if (!(parent
= find_parent( writer
)))
4049 LeaveCriticalSection( &writer
->cs
);
4050 return WS_E_INVALID_FORMAT
;
4053 if ((hr
= copy_node( reader
, &node
)) != S_OK
) goto done
;
4054 current
= writer
->current
;
4055 write_insert_node( writer
, parent
, node
);
4057 write_rewind( writer
);
4058 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
4059 writer
->current
= current
;
4061 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
4064 LeaveCriticalSection( &writer
->cs
);
4068 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
4070 return write_type_field( writer
, desc
, value
, 0 );
4073 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
4076 for (i
= 0; i
< count
; i
++)
4078 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4080 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
4086 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
4089 return write_type_repeating_element( writer
, desc
, value
, len
);
4092 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4093 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4095 struct writer
*writer
= (struct writer
*)handle
;
4096 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4097 const WS_FIELD_DESCRIPTION
*desc_field
;
4101 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4103 EnterCriticalSection( &writer
->cs
);
4105 if (writer
->magic
!= WRITER_MAGIC
)
4107 LeaveCriticalSection( &writer
->cs
);
4108 return E_INVALIDARG
;
4111 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4113 for (i
= 0; i
< count
; i
++)
4115 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
4116 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
4118 FIXME( "messages type not supported\n" );
4122 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
4123 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
4125 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
4127 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
4129 const void *ptr
= *(const void **)args
[i
];
4130 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
4131 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
4135 hr
= write_endelement_node( writer
);
4138 LeaveCriticalSection( &writer
->cs
);