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_struct_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
2927 const char *buf
, ULONG offset
)
2930 WS_TYPE_MAPPING mapping
;
2931 WS_WRITE_OPTION option
;
2932 ULONG count
, size
, field_options
= desc
->options
;
2933 const char *ptr
= buf
+ offset
;
2935 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
2937 FIXME( "options 0x%x not supported\n", desc
->options
);
2941 /* zero-terminated strings are always pointers */
2942 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
2944 if (field_options
& WS_FIELD_POINTER
)
2945 size
= sizeof(const void *);
2947 size
= get_type_size( desc
->type
, desc
->typeDescription
);
2949 if (is_nil_value( ptr
, size
))
2951 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
2952 if (field_options
& WS_FIELD_NILLABLE
)
2954 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
2955 else option
= WS_WRITE_NILLABLE_VALUE
;
2959 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
2960 else option
= WS_WRITE_REQUIRED_VALUE
;
2965 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
2966 else option
= WS_WRITE_REQUIRED_VALUE
;
2969 switch (desc
->mapping
)
2971 case WS_ATTRIBUTE_FIELD_MAPPING
:
2972 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
2973 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
2975 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2977 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2980 case WS_ELEMENT_FIELD_MAPPING
:
2981 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
2982 mapping
= WS_ELEMENT_TYPE_MAPPING
;
2985 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
2986 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
2987 return write_type_repeating_element( writer
, desc
, *(const char **)ptr
, count
);
2989 case WS_TEXT_FIELD_MAPPING
:
2990 switch (writer
->state
)
2992 case WRITER_STATE_STARTELEMENT
:
2993 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
2996 case WRITER_STATE_STARTATTRIBUTE
:
2997 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3001 FIXME( "unhandled writer state %u\n", writer
->state
);
3007 FIXME( "field mapping %u not supported\n", desc
->mapping
);
3011 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
3016 case WS_ATTRIBUTE_TYPE_MAPPING
:
3017 writer
->state
= WRITER_STATE_STARTELEMENT
;
3020 case WS_ELEMENT_TYPE_MAPPING
:
3021 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3030 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3031 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3032 const void *value
, ULONG size
)
3038 if (!desc
) return E_INVALIDARG
;
3039 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
3041 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3043 for (i
= 0; i
< desc
->fieldCount
; i
++)
3045 offset
= desc
->fields
[i
]->offset
;
3046 if ((hr
= write_type_struct_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
)
3054 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3055 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3061 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
3064 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
3067 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
3070 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
3073 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
3076 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
3078 case WS_UINT16_TYPE
:
3079 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
3081 case WS_UINT32_TYPE
:
3082 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
3084 case WS_UINT64_TYPE
:
3085 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
3087 case WS_DATETIME_TYPE
:
3088 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
3091 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
3093 case WS_UNIQUE_ID_TYPE
:
3094 return write_type_unique_id( writer
, mapping
, desc
, option
, value
, size
);
3096 case WS_STRING_TYPE
:
3097 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
3100 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
3103 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
3105 case WS_XML_STRING_TYPE
:
3106 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
3108 case WS_XML_QNAME_TYPE
:
3109 return write_type_qname( writer
, mapping
, desc
, option
, value
, size
);
3111 case WS_STRUCT_TYPE
:
3112 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
3115 FIXME( "type %u not supported\n", type
);
3120 /**************************************************************************
3121 * WsWriteAttribute [webservices.@]
3123 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
3124 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3127 struct writer
*writer
= (struct writer
*)handle
;
3130 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3131 if (error
) FIXME( "ignoring error parameter\n" );
3133 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
3134 return E_INVALIDARG
;
3136 EnterCriticalSection( &writer
->cs
);
3138 if (writer
->magic
!= WRITER_MAGIC
)
3140 LeaveCriticalSection( &writer
->cs
);
3141 return E_INVALIDARG
;
3144 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3146 LeaveCriticalSection( &writer
->cs
);
3147 return WS_E_INVALID_OPERATION
;
3150 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) != S_OK
)
3152 LeaveCriticalSection( &writer
->cs
);
3155 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3157 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
3159 LeaveCriticalSection( &writer
->cs
);
3163 /**************************************************************************
3164 * WsWriteElement [webservices.@]
3166 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3167 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3170 struct writer
*writer
= (struct writer
*)handle
;
3173 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3174 if (error
) FIXME( "ignoring error parameter\n" );
3176 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
3177 return E_INVALIDARG
;
3179 EnterCriticalSection( &writer
->cs
);
3181 if (writer
->magic
!= WRITER_MAGIC
)
3183 LeaveCriticalSection( &writer
->cs
);
3184 return E_INVALIDARG
;
3187 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
3189 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
3190 option
, value
, size
)) != S_OK
) goto done
;
3192 hr
= write_endelement_node( writer
);
3195 LeaveCriticalSection( &writer
->cs
);
3199 /**************************************************************************
3200 * WsWriteType [webservices.@]
3202 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3203 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3204 ULONG size
, WS_ERROR
*error
)
3206 struct writer
*writer
= (struct writer
*)handle
;
3209 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
3211 if (error
) FIXME( "ignoring error parameter\n" );
3213 if (!writer
|| !value
) return E_INVALIDARG
;
3215 EnterCriticalSection( &writer
->cs
);
3217 if (writer
->magic
!= WRITER_MAGIC
)
3219 LeaveCriticalSection( &writer
->cs
);
3220 return E_INVALIDARG
;
3225 case WS_ATTRIBUTE_TYPE_MAPPING
:
3226 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
3227 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3230 case WS_ELEMENT_TYPE_MAPPING
:
3231 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3232 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_FORMAT
;
3233 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3236 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3237 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3241 FIXME( "mapping %u not implemented\n", mapping
);
3245 LeaveCriticalSection( &writer
->cs
);
3249 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
3253 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
3254 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
3255 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
3256 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
3257 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
3258 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
3259 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
3260 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
3261 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
3262 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
3263 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
3264 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
3265 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
3266 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
3267 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
3269 FIXME( "unhandled type %u\n", type
);
3274 /**************************************************************************
3275 * WsWriteValue [webservices.@]
3277 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
3278 ULONG size
, WS_ERROR
*error
)
3280 struct writer
*writer
= (struct writer
*)handle
;
3281 WS_TYPE_MAPPING mapping
;
3285 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
3286 if (error
) FIXME( "ignoring error parameter\n" );
3288 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
3290 EnterCriticalSection( &writer
->cs
);
3292 if (writer
->magic
!= WRITER_MAGIC
)
3294 LeaveCriticalSection( &writer
->cs
);
3295 return E_INVALIDARG
;
3298 switch (writer
->state
)
3300 case WRITER_STATE_STARTATTRIBUTE
:
3301 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3304 case WRITER_STATE_STARTELEMENT
:
3305 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3309 hr
= WS_E_INVALID_FORMAT
;
3312 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
3314 LeaveCriticalSection( &writer
->cs
);
3318 /**************************************************************************
3319 * WsWriteArray [webservices.@]
3321 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3322 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
3323 ULONG count
, WS_ERROR
*error
)
3325 struct writer
*writer
= (struct writer
*)handle
;
3330 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3331 value_type
, array
, size
, offset
, count
, error
);
3332 if (error
) FIXME( "ignoring error parameter\n" );
3334 if (!writer
) return E_INVALIDARG
;
3336 EnterCriticalSection( &writer
->cs
);
3338 if (writer
->magic
!= WRITER_MAGIC
)
3340 LeaveCriticalSection( &writer
->cs
);
3341 return E_INVALIDARG
;
3344 if (!writer
->output_type
)
3346 LeaveCriticalSection( &writer
->cs
);
3347 return WS_E_INVALID_OPERATION
;
3350 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
3352 LeaveCriticalSection( &writer
->cs
);
3353 return E_INVALIDARG
;
3356 type_size
= get_type_size( type
, NULL
);
3357 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
3359 LeaveCriticalSection( &writer
->cs
);
3360 return E_INVALIDARG
;
3363 for (i
= offset
; i
< count
; i
++)
3365 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
3366 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
3367 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
3368 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
3369 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
3373 LeaveCriticalSection( &writer
->cs
);
3377 /**************************************************************************
3378 * WsWriteXmlBuffer [webservices.@]
3380 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
3382 struct writer
*writer
= (struct writer
*)handle
;
3383 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
3386 TRACE( "%p %p %p\n", handle
, buffer
, error
);
3387 if (error
) FIXME( "ignoring error parameter\n" );
3389 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
3391 EnterCriticalSection( &writer
->cs
);
3393 if (writer
->magic
!= WRITER_MAGIC
)
3395 LeaveCriticalSection( &writer
->cs
);
3396 return E_INVALIDARG
;
3399 if (xmlbuf
->encoding
!= writer
->output_enc
|| xmlbuf
->charset
!= writer
->output_charset
)
3401 FIXME( "no support for different encoding and/or charset\n" );
3406 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
3407 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
3408 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
3411 LeaveCriticalSection( &writer
->cs
);
3415 /**************************************************************************
3416 * WsWriteXmlBufferToBytes [webservices.@]
3418 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
3419 const WS_XML_WRITER_ENCODING
*encoding
,
3420 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
3421 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
3423 struct writer
*writer
= (struct writer
*)handle
;
3424 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
3429 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
3430 bytes
, size
, error
);
3431 if (error
) FIXME( "ignoring error parameter\n" );
3433 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
3435 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
3437 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
3441 EnterCriticalSection( &writer
->cs
);
3443 if (writer
->magic
!= WRITER_MAGIC
)
3445 LeaveCriticalSection( &writer
->cs
);
3446 return E_INVALIDARG
;
3449 for (i
= 0; i
< count
; i
++)
3451 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
3452 properties
[i
].valueSize
);
3453 if (hr
!= S_OK
) goto done
;
3456 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
3459 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
3461 *size
= xmlbuf
->bytes
.length
;
3465 LeaveCriticalSection( &writer
->cs
);
3469 /**************************************************************************
3470 * WsWriteXmlnsAttribute [webservices.@]
3472 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
3473 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
3475 struct writer
*writer
= (struct writer
*)handle
;
3478 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
3480 if (error
) FIXME( "ignoring error parameter\n" );
3482 if (!writer
|| !ns
) return E_INVALIDARG
;
3484 EnterCriticalSection( &writer
->cs
);
3486 if (writer
->magic
!= WRITER_MAGIC
)
3488 LeaveCriticalSection( &writer
->cs
);
3489 return E_INVALIDARG
;
3492 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3494 LeaveCriticalSection( &writer
->cs
);
3495 return WS_E_INVALID_OPERATION
;
3498 if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
3499 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
3501 LeaveCriticalSection( &writer
->cs
);
3505 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
3506 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
3508 WS_XML_QNAME_TEXT qname
= {{WS_XML_TEXT_TYPE_QNAME
}};
3511 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
3512 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) return hr
;
3514 qname
.prefix
= (WS_XML_STRING
*)prefix
;
3515 qname
.localName
= (WS_XML_STRING
*)localname
;
3516 qname
.ns
= (WS_XML_STRING
*)ns
;
3518 if ((hr
= write_add_text_node( writer
, &qname
.text
)) != S_OK
) return hr
;
3519 return write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 );
3522 /**************************************************************************
3523 * WsWriteQualifiedName [webservices.@]
3525 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
3526 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3529 struct writer
*writer
= (struct writer
*)handle
;
3532 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
3533 debugstr_xmlstr(ns
), error
);
3534 if (error
) FIXME( "ignoring error parameter\n" );
3536 if (!writer
) return E_INVALIDARG
;
3538 EnterCriticalSection( &writer
->cs
);
3540 if (writer
->magic
!= WRITER_MAGIC
)
3542 LeaveCriticalSection( &writer
->cs
);
3543 return E_INVALIDARG
;
3546 if (!writer
->output_type
)
3548 LeaveCriticalSection( &writer
->cs
);
3549 return WS_E_INVALID_OPERATION
;
3552 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3554 LeaveCriticalSection( &writer
->cs
);
3555 return WS_E_INVALID_FORMAT
;
3558 if (!localname
|| (!prefix
&& !ns
))
3560 LeaveCriticalSection( &writer
->cs
);
3561 return E_INVALIDARG
;
3564 hr
= write_qualified_name( writer
, prefix
, localname
, ns
);
3566 LeaveCriticalSection( &writer
->cs
);
3570 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
3572 BOOL success
= FALSE
;
3573 struct node
*node
= writer
->current
;
3577 case WS_MOVE_TO_ROOT_ELEMENT
:
3578 success
= move_to_root_element( writer
->root
, &node
);
3581 case WS_MOVE_TO_NEXT_ELEMENT
:
3582 success
= move_to_next_element( &node
);
3585 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
3586 success
= move_to_prev_element( &node
);
3589 case WS_MOVE_TO_CHILD_ELEMENT
:
3590 success
= move_to_child_element( &node
);
3593 case WS_MOVE_TO_END_ELEMENT
:
3594 success
= move_to_end_element( &node
);
3597 case WS_MOVE_TO_PARENT_ELEMENT
:
3598 success
= move_to_parent_element( &node
);
3601 case WS_MOVE_TO_FIRST_NODE
:
3602 success
= move_to_first_node( &node
);
3605 case WS_MOVE_TO_NEXT_NODE
:
3606 success
= move_to_next_node( &node
);
3609 case WS_MOVE_TO_PREVIOUS_NODE
:
3610 success
= move_to_prev_node( &node
);
3613 case WS_MOVE_TO_CHILD_NODE
:
3614 success
= move_to_child_node( &node
);
3617 case WS_MOVE_TO_BOF
:
3618 success
= move_to_bof( writer
->root
, &node
);
3621 case WS_MOVE_TO_EOF
:
3622 success
= move_to_eof( writer
->root
, &node
);
3626 FIXME( "unhandled move %u\n", move
);
3630 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
3631 writer
->current
= node
;
3638 return success
? S_OK
: WS_E_INVALID_FORMAT
;
3641 /**************************************************************************
3642 * WsMoveWriter [webservices.@]
3644 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
3646 struct writer
*writer
= (struct writer
*)handle
;
3649 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
3650 if (error
) FIXME( "ignoring error parameter\n" );
3652 if (!writer
) return E_INVALIDARG
;
3654 EnterCriticalSection( &writer
->cs
);
3656 if (writer
->magic
!= WRITER_MAGIC
)
3658 LeaveCriticalSection( &writer
->cs
);
3659 return E_INVALIDARG
;
3662 if (!writer
->output_type
)
3664 LeaveCriticalSection( &writer
->cs
);
3665 return WS_E_INVALID_OPERATION
;
3668 hr
= write_move_to( writer
, move
, found
);
3670 LeaveCriticalSection( &writer
->cs
);
3674 /**************************************************************************
3675 * WsGetWriterPosition [webservices.@]
3677 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
3679 struct writer
*writer
= (struct writer
*)handle
;
3681 TRACE( "%p %p %p\n", handle
, pos
, error
);
3682 if (error
) FIXME( "ignoring error parameter\n" );
3684 if (!writer
|| !pos
) return E_INVALIDARG
;
3686 EnterCriticalSection( &writer
->cs
);
3688 if (writer
->magic
!= WRITER_MAGIC
)
3690 LeaveCriticalSection( &writer
->cs
);
3691 return E_INVALIDARG
;
3694 if (!writer
->output_type
)
3696 LeaveCriticalSection( &writer
->cs
);
3697 return WS_E_INVALID_OPERATION
;
3700 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
3701 pos
->node
= writer
->current
;
3703 LeaveCriticalSection( &writer
->cs
);
3707 /**************************************************************************
3708 * WsSetWriterPosition [webservices.@]
3710 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
3712 struct writer
*writer
= (struct writer
*)handle
;
3714 TRACE( "%p %p %p\n", handle
, pos
, error
);
3715 if (error
) FIXME( "ignoring error parameter\n" );
3717 if (!writer
|| !pos
) return E_INVALIDARG
;
3719 EnterCriticalSection( &writer
->cs
);
3721 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
3723 LeaveCriticalSection( &writer
->cs
);
3724 return E_INVALIDARG
;
3727 if (!writer
->output_type
)
3729 LeaveCriticalSection( &writer
->cs
);
3730 return WS_E_INVALID_OPERATION
;
3733 writer
->current
= pos
->node
;
3735 LeaveCriticalSection( &writer
->cs
);
3739 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
3741 struct node
*node
, *parent
;
3742 WS_XML_COMMENT_NODE
*comment
;
3744 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
3745 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
3746 comment
= (WS_XML_COMMENT_NODE
*)node
;
3748 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
3751 return E_OUTOFMEMORY
;
3753 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
3754 comment
->value
.length
= value
->length
;
3756 write_insert_node( writer
, parent
, node
);
3760 static HRESULT
write_comment_text( struct writer
*writer
)
3762 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
3765 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
3766 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
3767 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
3768 write_bytes( writer
, (const BYTE
*)"-->", 3 );
3772 static HRESULT
write_comment_bin( struct writer
*writer
)
3774 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
3777 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
3778 write_char( writer
, RECORD_COMMENT
);
3779 return write_string( writer
, comment
->value
.bytes
, comment
->value
.length
);
3782 static HRESULT
write_comment( struct writer
*writer
)
3784 switch (writer
->output_enc
)
3786 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_comment_text( writer
);
3787 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_comment_bin( writer
);
3789 ERR( "unhandled encoding %u\n", writer
->output_enc
);
3790 return WS_E_NOT_SUPPORTED
;
3794 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
3797 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
3798 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
3799 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
3800 writer
->state
= WRITER_STATE_COMMENT
;
3804 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
3809 for (i
= 0; i
< count
; i
++)
3811 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
3812 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
3813 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
3818 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
3822 switch (node
->nodeType
)
3824 case WS_XML_NODE_TYPE_ELEMENT
:
3826 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
3827 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
3828 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
3830 case WS_XML_NODE_TYPE_TEXT
:
3832 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
3833 return write_text_node( writer
, text
->text
);
3835 case WS_XML_NODE_TYPE_END_ELEMENT
:
3836 return write_endelement_node( writer
);
3838 case WS_XML_NODE_TYPE_COMMENT
:
3840 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
3841 return write_comment_node( writer
, &comment
->value
);
3843 case WS_XML_NODE_TYPE_CDATA
:
3844 return write_cdata_node( writer
);
3846 case WS_XML_NODE_TYPE_END_CDATA
:
3847 return write_endcdata_node( writer
);
3849 case WS_XML_NODE_TYPE_EOF
:
3850 case WS_XML_NODE_TYPE_BOF
:
3854 WARN( "unknown node type %u\n", node
->nodeType
);
3855 return E_INVALIDARG
;
3859 /**************************************************************************
3860 * WsWriteNode [webservices.@]
3862 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
3864 struct writer
*writer
= (struct writer
*)handle
;
3867 TRACE( "%p %p %p\n", handle
, node
, error
);
3868 if (error
) FIXME( "ignoring error parameter\n" );
3870 if (!writer
|| !node
) return E_INVALIDARG
;
3872 EnterCriticalSection( &writer
->cs
);
3874 if (writer
->magic
!= WRITER_MAGIC
)
3876 LeaveCriticalSection( &writer
->cs
);
3877 return E_INVALIDARG
;
3880 if (!writer
->output_type
)
3882 LeaveCriticalSection( &writer
->cs
);
3883 return WS_E_INVALID_OPERATION
;
3886 hr
= write_node( writer
, node
);
3888 LeaveCriticalSection( &writer
->cs
);
3892 static HRESULT
write_tree_node( struct writer
*writer
)
3896 switch (node_type( writer
->current
))
3898 case WS_XML_NODE_TYPE_ELEMENT
:
3899 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3901 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
3902 writer
->state
= WRITER_STATE_STARTELEMENT
;
3905 case WS_XML_NODE_TYPE_TEXT
:
3906 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3908 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
3909 writer
->state
= WRITER_STATE_TEXT
;
3912 case WS_XML_NODE_TYPE_END_ELEMENT
:
3913 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
3914 writer
->state
= WRITER_STATE_ENDELEMENT
;
3917 case WS_XML_NODE_TYPE_COMMENT
:
3918 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3920 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
3921 writer
->state
= WRITER_STATE_COMMENT
;
3924 case WS_XML_NODE_TYPE_CDATA
:
3925 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3927 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
3928 writer
->state
= WRITER_STATE_STARTCDATA
;
3931 case WS_XML_NODE_TYPE_END_CDATA
:
3932 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
3933 writer
->state
= WRITER_STATE_ENDCDATA
;
3936 case WS_XML_NODE_TYPE_EOF
:
3937 case WS_XML_NODE_TYPE_BOF
:
3941 ERR( "unknown node type %u\n", node_type(writer
->current
) );
3942 return E_INVALIDARG
;
3946 static HRESULT
write_tree( struct writer
*writer
)
3950 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3953 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
3954 if (move_to_child_node( &writer
->current
))
3956 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3959 if (move_to_next_node( &writer
->current
))
3961 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3964 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
3966 ERR( "invalid tree\n" );
3967 return WS_E_INVALID_FORMAT
;
3969 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3974 static void write_rewind( struct writer
*writer
)
3976 writer
->write_pos
= 0;
3977 writer
->current
= writer
->root
;
3978 writer
->state
= WRITER_STATE_INITIAL
;
3981 /**************************************************************************
3982 * WsCopyNode [webservices.@]
3984 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
3986 struct writer
*writer
= (struct writer
*)handle
;
3987 struct node
*parent
, *current
, *node
= NULL
;
3990 TRACE( "%p %p %p\n", handle
, reader
, error
);
3991 if (error
) FIXME( "ignoring error parameter\n" );
3993 if (!writer
) return E_INVALIDARG
;
3995 EnterCriticalSection( &writer
->cs
);
3997 if (writer
->magic
!= WRITER_MAGIC
)
3999 LeaveCriticalSection( &writer
->cs
);
4000 return E_INVALIDARG
;
4003 if (!(parent
= find_parent( writer
)))
4005 LeaveCriticalSection( &writer
->cs
);
4006 return WS_E_INVALID_FORMAT
;
4009 if ((hr
= copy_node( reader
, &node
)) != S_OK
) goto done
;
4010 current
= writer
->current
;
4011 write_insert_node( writer
, parent
, node
);
4013 write_rewind( writer
);
4014 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
4015 writer
->current
= current
;
4017 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
4020 LeaveCriticalSection( &writer
->cs
);
4024 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
4026 return write_type_struct_field( writer
, desc
, value
, 0 );
4029 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
4032 for (i
= 0; i
< count
; i
++)
4034 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4036 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
4042 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
4045 return write_type_repeating_element( writer
, desc
, value
, len
);
4048 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4049 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4051 struct writer
*writer
= (struct writer
*)handle
;
4052 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4053 const WS_FIELD_DESCRIPTION
*desc_field
;
4057 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4059 EnterCriticalSection( &writer
->cs
);
4061 if (writer
->magic
!= WRITER_MAGIC
)
4063 LeaveCriticalSection( &writer
->cs
);
4064 return E_INVALIDARG
;
4067 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4069 for (i
= 0; i
< count
; i
++)
4071 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
4072 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
4074 FIXME( "messages type not supported\n" );
4078 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
4079 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
4081 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
4083 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
4085 const void *ptr
= *(const void **)args
[i
];
4086 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
4087 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
4091 hr
= write_endelement_node( writer
);
4094 LeaveCriticalSection( &writer
->cs
);