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_XML_WRITER_OUTPUT_TYPE output_type
;
84 struct xmlbuf
*output_buf
;
87 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
90 #define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T')
92 static struct writer
*alloc_writer(void)
94 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
96 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
98 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
100 ret
->magic
= WRITER_MAGIC
;
101 InitializeCriticalSection( &ret
->cs
);
102 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": writer.cs");
104 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
105 ret
->prop_count
= count
;
109 static void free_writer( struct writer
*writer
)
111 destroy_nodes( writer
->root
);
112 heap_free( writer
->current_ns
);
113 WsFreeHeap( writer
->output_heap
);
115 writer
->cs
.DebugInfo
->Spare
[0] = 0;
116 DeleteCriticalSection( &writer
->cs
);
120 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
122 if (!writer
->root
) writer
->root
= eof
;
125 eof
->parent
= writer
->root
;
126 list_add_tail( &writer
->root
->children
, &eof
->entry
);
128 writer
->current
= eof
;
131 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
133 writer
->root
->parent
= bof
;
134 list_add_tail( &bof
->children
, &writer
->root
->entry
);
135 writer
->current
= writer
->root
= bof
;
138 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
140 node
->parent
= parent
;
141 list_add_before( list_tail( &parent
->children
), &node
->entry
);
142 writer
->current
= node
;
145 static struct node
*find_parent( struct writer
*writer
)
147 if (is_valid_parent( writer
->current
)) return writer
->current
;
148 if (is_valid_parent( writer
->current
->parent
)) return writer
->current
->parent
;
152 static HRESULT
init_writer( struct writer
*writer
)
156 writer
->write_pos
= 0;
157 writer
->write_bufptr
= NULL
;
158 destroy_nodes( writer
->root
);
159 writer
->root
= writer
->current
= NULL
;
160 heap_free( writer
->current_ns
);
161 writer
->current_ns
= NULL
;
163 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
164 write_insert_eof( writer
, node
);
165 writer
->state
= WRITER_STATE_INITIAL
;
166 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
170 /**************************************************************************
171 * WsCreateWriter [webservices.@]
173 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
174 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
176 struct writer
*writer
;
177 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
178 WS_CHARSET charset
= WS_CHARSET_UTF8
;
181 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
182 if (error
) FIXME( "ignoring error parameter\n" );
184 if (!handle
) return E_INVALIDARG
;
185 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
187 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
188 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
189 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
190 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
191 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
192 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
193 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
195 for (i
= 0; i
< count
; i
++)
197 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
198 properties
[i
].valueSize
);
201 free_writer( writer
);
206 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
207 &max_size
, sizeof(max_size
) );
210 free_writer( writer
);
214 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
217 free_writer( writer
);
221 hr
= init_writer( writer
);
224 free_writer( writer
);
228 *handle
= (WS_XML_WRITER
*)writer
;
232 /**************************************************************************
233 * WsFreeWriter [webservices.@]
235 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
237 struct writer
*writer
= (struct writer
*)handle
;
239 TRACE( "%p\n", handle
);
243 EnterCriticalSection( &writer
->cs
);
245 if (writer
->magic
!= WRITER_MAGIC
)
247 LeaveCriticalSection( &writer
->cs
);
253 LeaveCriticalSection( &writer
->cs
);
254 free_writer( writer
);
257 /**************************************************************************
258 * WsGetWriterProperty [webservices.@]
260 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
261 void *buf
, ULONG size
, WS_ERROR
*error
)
263 struct writer
*writer
= (struct writer
*)handle
;
266 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
267 if (error
) FIXME( "ignoring error parameter\n" );
269 if (!writer
) return E_INVALIDARG
;
271 EnterCriticalSection( &writer
->cs
);
273 if (writer
->magic
!= WRITER_MAGIC
)
275 LeaveCriticalSection( &writer
->cs
);
279 if (!writer
->output_type
)
281 LeaveCriticalSection( &writer
->cs
);
282 return WS_E_INVALID_OPERATION
;
287 case WS_XML_WRITER_PROPERTY_BYTES
:
289 WS_BYTES
*bytes
= buf
;
290 if (size
!= sizeof(*bytes
)) hr
= E_INVALIDARG
;
293 bytes
->bytes
= writer
->output_buf
->bytes
.bytes
;
294 bytes
->length
= writer
->output_buf
->bytes
.length
;
298 case WS_XML_WRITER_PROPERTY_BUFFERS
:
299 if (writer
->output_buf
->bytes
.length
)
301 WS_BUFFERS
*buffers
= buf
;
302 if (size
!= sizeof(*buffers
)) hr
= E_INVALIDARG
;
305 buffers
->bufferCount
= 1;
306 buffers
->buffers
= &writer
->output_buf
->bytes
;
312 hr
= prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
315 LeaveCriticalSection( &writer
->cs
);
319 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
321 /* free current buffer if it's ours */
322 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
324 free_xmlbuf( writer
->output_buf
);
326 writer
->output_buf
= xmlbuf
;
327 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
328 writer
->write_bufptr
= xmlbuf
->bytes
.bytes
;
329 writer
->write_pos
= 0;
332 /**************************************************************************
333 * WsSetOutput [webservices.@]
335 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
336 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
337 ULONG count
, WS_ERROR
*error
)
339 struct writer
*writer
= (struct writer
*)handle
;
344 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
345 if (error
) FIXME( "ignoring error parameter\n" );
347 if (!writer
) return E_INVALIDARG
;
349 EnterCriticalSection( &writer
->cs
);
351 if (writer
->magic
!= WRITER_MAGIC
)
353 LeaveCriticalSection( &writer
->cs
);
357 for (i
= 0; i
< count
; i
++)
359 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
360 properties
[i
].valueSize
);
361 if (hr
!= S_OK
) goto done
;
364 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
366 switch (encoding
->encodingType
)
368 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
370 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
371 if (text
->charSet
!= WS_CHARSET_UTF8
)
373 FIXME( "charset %u not supported\n", text
->charSet
);
377 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
380 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
382 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_BINARY
;
386 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
391 switch (output
->outputType
)
393 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
395 struct xmlbuf
*xmlbuf
;
397 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
))) hr
= WS_E_QUOTA_EXCEEDED
;
398 else set_output_buffer( writer
, xmlbuf
);
402 FIXME( "output type %u not supported\n", output
->outputType
);
407 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
408 else write_insert_bof( writer
, node
);
411 LeaveCriticalSection( &writer
->cs
);
415 /**************************************************************************
416 * WsSetOutputToBuffer [webservices.@]
418 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
419 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
422 struct writer
*writer
= (struct writer
*)handle
;
423 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
428 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
429 if (error
) FIXME( "ignoring error parameter\n" );
431 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
433 EnterCriticalSection( &writer
->cs
);
435 if (writer
->magic
!= WRITER_MAGIC
)
437 LeaveCriticalSection( &writer
->cs
);
441 for (i
= 0; i
< count
; i
++)
443 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
444 properties
[i
].valueSize
);
445 if (hr
!= S_OK
) goto done
;
448 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
449 set_output_buffer( writer
, xmlbuf
);
451 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
452 else write_insert_bof( writer
, node
);
455 LeaveCriticalSection( &writer
->cs
);
459 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
461 struct xmlbuf
*buf
= writer
->output_buf
;
465 if (buf
->size
>= writer
->write_pos
+ size
)
467 buf
->bytes
.length
= writer
->write_pos
+ size
;
470 new_size
= max( buf
->size
* 2, writer
->write_pos
+ size
);
471 if (!(tmp
= ws_realloc( buf
->heap
, buf
->bytes
.bytes
, buf
->size
, new_size
))) return WS_E_QUOTA_EXCEEDED
;
472 writer
->write_bufptr
= buf
->bytes
.bytes
= tmp
;
473 buf
->size
= new_size
;
474 buf
->bytes
.length
= writer
->write_pos
+ size
;
478 static inline void write_char( struct writer
*writer
, unsigned char ch
)
480 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
483 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
485 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
486 writer
->write_pos
+= len
;
495 static const struct escape escape_lt
= { '<', "<", 4 };
496 static const struct escape escape_gt
= { '>', ">", 4 };
497 static const struct escape escape_amp
= { '&', "&", 5 };
498 static const struct escape escape_apos
= { '\'', "'", 6 };
499 static const struct escape escape_quot
= { '"', """, 6 };
501 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
502 const struct escape
**escapes
, ULONG nb_escapes
)
508 for (i
= 0; i
< len
; i
++)
512 for (j
= 0; j
< nb_escapes
; j
++)
514 if (bytes
[i
] == escapes
[j
]->ch
)
516 ptr
= (const BYTE
*)escapes
[j
]->entity
;
517 size
= escapes
[j
]->len
;
521 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
522 write_bytes( writer
, ptr
, size
);
528 static HRESULT
write_attribute_value_text( struct writer
*writer
, const WS_XML_TEXT
*text
, BOOL single
)
530 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
;
531 const struct escape
*escapes
[3];
533 escapes
[0] = single
? &escape_apos
: &escape_quot
;
534 escapes
[1] = &escape_lt
;
535 escapes
[2] = &escape_amp
;
536 return write_bytes_escape( writer
, utf8
->value
.bytes
, utf8
->value
.length
, escapes
, 3 );
539 static HRESULT
write_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
541 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
542 const WS_XML_STRING
*prefix
= NULL
;
546 if (attr
->prefix
) prefix
= attr
->prefix
;
548 /* ' prefix:attr="value"' */
550 size
= attr
->localName
->length
+ 4 /* ' =""' */;
551 if (prefix
&& prefix
->length
) size
+= prefix
->length
+ 1 /* ':' */;
552 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
554 write_char( writer
, ' ' );
555 if (prefix
&& prefix
->length
)
557 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
558 write_char( writer
, ':' );
560 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
561 write_char( writer
, '=' );
562 write_char( writer
, quote
);
563 if (attr
->value
) hr
= write_attribute_value_text( writer
, attr
->value
, attr
->singleQuote
);
564 write_char( writer
, quote
);
569 static enum record_type
get_attr_record_type( const WS_XML_ATTRIBUTE
*attr
)
571 if (!attr
->prefix
|| !attr
->prefix
->length
) return RECORD_SHORT_ATTRIBUTE
;
572 if (attr
->prefix
->length
== 1 && attr
->prefix
->bytes
[0] >= 'a' && attr
->prefix
->bytes
[0] <= 'z')
574 return RECORD_PREFIX_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
576 return RECORD_ATTRIBUTE
;
579 static HRESULT
write_int31( struct writer
*writer
, ULONG len
)
583 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
586 write_char( writer
, len
);
589 write_char( writer
, (len
& 0x7f) | 0x80 );
591 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
592 if ((len
>>= 7) < 0x80)
594 write_char( writer
, len
);
597 write_char( writer
, (len
& 0x7f) | 0x80 );
599 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
600 if ((len
>>= 7) < 0x80)
602 write_char( writer
, len
);
605 write_char( writer
, (len
& 0x7f) | 0x80 );
607 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
608 if ((len
>>= 7) < 0x80)
610 write_char( writer
, len
);
613 write_char( writer
, (len
& 0x7f) | 0x80 );
615 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
616 if ((len
>>= 7) < 0x08)
618 write_char( writer
, len
);
621 return WS_E_INVALID_FORMAT
;
624 static HRESULT
write_string( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
627 if ((hr
= write_int31( writer
, len
)) != S_OK
) return hr
;
628 if ((hr
= write_grow_buffer( writer
, len
)) != S_OK
) return hr
;
629 write_bytes( writer
, bytes
, len
);
633 static enum record_type
get_text_record_type( const WS_XML_TEXT
*text
, BOOL attr
)
635 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
636 if (!utf8
|| utf8
->value
.length
<= 0xff) return attr
? RECORD_CHARS8_TEXT
: RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
640 static HRESULT
write_attribute_value_bin( struct writer
*writer
, const WS_XML_TEXT
*text
)
642 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
;
643 enum record_type type
= get_text_record_type( text
, TRUE
);
646 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
647 write_char( writer
, type
);
651 case RECORD_CHARS8_TEXT
:
652 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
653 if (!utf8
|| !utf8
->value
.length
) write_char( writer
, 0 );
656 write_char( writer
, utf8
->value
.length
);
657 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
)) != S_OK
) return hr
;
658 write_bytes( writer
, utf8
->value
.bytes
, utf8
->value
.length
);
663 ERR( "unhandled record type %u\n", type
);
664 return WS_E_NOT_SUPPORTED
;
668 static HRESULT
write_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
670 enum record_type type
= get_attr_record_type( attr
);
673 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
674 write_char( writer
, type
);
676 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
678 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
679 return write_attribute_value_bin( writer
, attr
->value
);
684 case RECORD_SHORT_ATTRIBUTE
:
685 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
688 case RECORD_ATTRIBUTE
:
689 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
690 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
694 ERR( "unhandled record type %u\n", type
);
695 return WS_E_NOT_SUPPORTED
;
698 return write_attribute_value_bin( writer
, attr
->value
);
701 static HRESULT
write_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
703 switch (writer
->output_enc
)
705 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_attribute_text( writer
, attr
);
706 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_attribute_bin( writer
, attr
);
708 ERR( "unhandled encoding %u\n", writer
->output_enc
);
709 return WS_E_NOT_SUPPORTED
;
713 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
715 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
718 /**************************************************************************
719 * WsGetPrefixFromNamespace [webservices.@]
721 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
722 BOOL required
, const WS_XML_STRING
**prefix
,
725 struct writer
*writer
= (struct writer
*)handle
;
726 WS_XML_ELEMENT_NODE
*elem
;
730 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
731 if (error
) FIXME( "ignoring error parameter\n" );
733 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
735 EnterCriticalSection( &writer
->cs
);
737 if (writer
->magic
!= WRITER_MAGIC
)
739 LeaveCriticalSection( &writer
->cs
);
743 elem
= &writer
->current
->hdr
;
744 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
746 *prefix
= elem
->prefix
;
752 if (required
) hr
= WS_E_INVALID_FORMAT
;
760 LeaveCriticalSection( &writer
->cs
);
764 static HRESULT
write_namespace_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
766 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
770 /* ' xmlns:prefix="namespace"' */
772 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
773 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
774 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
776 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
779 write_char( writer
, ':' );
780 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
782 write_char( writer
, '=' );
783 write_char( writer
, quote
);
784 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
785 write_char( writer
, quote
);
790 static enum record_type
get_xmlns_record_type( const WS_XML_ATTRIBUTE
*attr
)
792 if (!attr
->prefix
|| !attr
->prefix
->length
) return RECORD_SHORT_XMLNS_ATTRIBUTE
;
793 return RECORD_XMLNS_ATTRIBUTE
;
796 static HRESULT
write_namespace_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
798 enum record_type type
= get_xmlns_record_type( attr
);
801 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
802 write_char( writer
, type
);
806 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
809 case RECORD_XMLNS_ATTRIBUTE
:
810 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
814 ERR( "unhandled record type %u\n", type
);
815 return WS_E_NOT_SUPPORTED
;
818 return write_string( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
821 static HRESULT
write_namespace_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
823 switch (writer
->output_enc
)
825 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_namespace_attribute_text( writer
, attr
);
826 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_namespace_attribute_bin( writer
, attr
);
828 ERR( "unhandled encoding %u\n", writer
->output_enc
);
829 return WS_E_NOT_SUPPORTED
;
833 static HRESULT
add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
834 const WS_XML_STRING
*ns
, BOOL single
)
836 WS_XML_ATTRIBUTE
*attr
;
837 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
840 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
842 attr
->singleQuote
= !!single
;
844 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
846 free_attribute( attr
);
847 return E_OUTOFMEMORY
;
849 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
851 free_attribute( attr
);
852 return E_OUTOFMEMORY
;
854 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
856 free_attribute( attr
);
862 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
864 if (!str1
&& !str2
) return TRUE
;
865 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
868 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
869 const WS_XML_STRING
*ns
)
872 const struct node
*node
;
874 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
876 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
879 for (i
= 0; i
< elem
->attributeCount
; i
++)
881 if (!elem
->attributes
[i
]->isXmlNs
) continue;
882 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
883 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
889 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
892 if (!(str
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
893 heap_free( writer
->current_ns
);
894 writer
->current_ns
= str
;
898 static HRESULT
set_namespaces( struct writer
*writer
)
900 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
904 if (elem
->ns
->length
&& !namespace_in_scope( elem
, elem
->prefix
, elem
->ns
))
906 if ((hr
= add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
) return hr
;
907 if ((hr
= set_current_namespace( writer
, elem
->ns
)) != S_OK
) return hr
;
910 for (i
= 0; i
< elem
->attributeCount
; i
++)
912 const WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
913 if (!attr
->ns
->length
|| namespace_in_scope( elem
, attr
->prefix
, attr
->ns
)) continue;
914 if ((hr
= add_namespace_attribute( writer
, attr
->prefix
, attr
->ns
, FALSE
)) != S_OK
) return hr
;
920 /**************************************************************************
921 * WsWriteEndAttribute [webservices.@]
923 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
925 struct writer
*writer
= (struct writer
*)handle
;
927 TRACE( "%p %p\n", handle
, error
);
928 if (error
) FIXME( "ignoring error parameter\n" );
930 if (!writer
) return E_INVALIDARG
;
932 EnterCriticalSection( &writer
->cs
);
934 if (writer
->magic
!= WRITER_MAGIC
)
936 LeaveCriticalSection( &writer
->cs
);
940 writer
->state
= WRITER_STATE_STARTELEMENT
;
942 LeaveCriticalSection( &writer
->cs
);
946 static HRESULT
write_attributes( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
950 for (i
= 0; i
< elem
->attributeCount
; i
++)
952 if (elem
->attributes
[i
]->isXmlNs
) continue;
953 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
955 for (i
= 0; i
< elem
->attributeCount
; i
++)
957 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
958 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
960 for (i
= 0; i
< elem
->attributeCount
; i
++)
962 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
963 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
968 static HRESULT
write_startelement_text( struct writer
*writer
)
970 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
974 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
976 size
= elem
->localName
->length
+ 1 /* '<' */;
977 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
978 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
980 write_char( writer
, '<' );
981 if (elem
->prefix
&& elem
->prefix
->length
)
983 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
984 write_char( writer
, ':' );
986 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
987 return write_attributes( writer
, elem
);
990 static enum record_type
get_elem_record_type( const WS_XML_ELEMENT_NODE
*elem
)
992 if (!elem
->prefix
|| !elem
->prefix
->length
) return RECORD_SHORT_ELEMENT
;
993 if (elem
->prefix
->length
== 1 && elem
->prefix
->bytes
[0] >= 'a' && elem
->prefix
->bytes
[0] <= 'z')
995 return RECORD_PREFIX_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
997 return RECORD_ELEMENT
;
1000 static HRESULT
write_startelement_bin( struct writer
*writer
)
1002 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1003 enum record_type type
= get_elem_record_type( elem
);
1006 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1007 write_char( writer
, type
);
1009 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1011 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1012 return write_attributes( writer
, elem
);
1017 case RECORD_SHORT_ELEMENT
:
1018 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1021 case RECORD_ELEMENT
:
1022 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1023 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1027 ERR( "unhandled record type %u\n", type
);
1028 return WS_E_NOT_SUPPORTED
;
1031 return write_attributes( writer
, elem
);
1034 static HRESULT
write_startelement( struct writer
*writer
)
1036 switch (writer
->output_enc
)
1038 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_startelement_text( writer
);
1039 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_startelement_bin( writer
);
1041 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1042 return WS_E_NOT_SUPPORTED
;
1046 static struct node
*write_find_startelement( struct writer
*writer
)
1049 for (node
= writer
->current
; node
; node
= node
->parent
)
1051 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
1056 static inline BOOL
is_empty_element( const struct node
*node
)
1058 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
1059 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
1062 static HRESULT
write_endelement_text( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1069 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
1071 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1072 write_char( writer
, '/' );
1073 write_char( writer
, '>' );
1077 /* '</prefix:localname>' */
1079 size
= elem
->localName
->length
+ 3 /* '</>' */;
1080 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1081 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1083 write_char( writer
, '<' );
1084 write_char( writer
, '/' );
1085 if (elem
->prefix
&& elem
->prefix
->length
)
1087 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1088 write_char( writer
, ':' );
1090 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1091 write_char( writer
, '>' );
1095 static HRESULT
write_endelement_bin( struct writer
*writer
)
1098 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_TEXT
) return S_OK
;
1099 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1100 write_char( writer
, RECORD_ENDELEMENT
);
1104 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1106 switch (writer
->output_enc
)
1108 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endelement_text( writer
, elem
);
1109 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_endelement_bin( writer
);
1111 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1112 return WS_E_NOT_SUPPORTED
;
1116 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
1118 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
1119 elem
->isEmpty
= is_empty_element( node
);
1120 return write_endelement( writer
, elem
);
1123 static HRESULT
write_endelement_node( struct writer
*writer
)
1128 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
1129 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1131 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1132 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1134 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
1135 writer
->current
= node
->parent
;
1136 writer
->state
= WRITER_STATE_ENDELEMENT
;
1140 /**************************************************************************
1141 * WsWriteEndElement [webservices.@]
1143 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1145 struct writer
*writer
= (struct writer
*)handle
;
1148 TRACE( "%p %p\n", handle
, error
);
1149 if (error
) FIXME( "ignoring error parameter\n" );
1151 if (!writer
) return E_INVALIDARG
;
1153 EnterCriticalSection( &writer
->cs
);
1155 if (writer
->magic
!= WRITER_MAGIC
)
1157 LeaveCriticalSection( &writer
->cs
);
1158 return E_INVALIDARG
;
1161 hr
= write_endelement_node( writer
);
1163 LeaveCriticalSection( &writer
->cs
);
1167 static HRESULT
write_endstartelement_text( struct writer
*writer
)
1170 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1171 write_char( writer
, '>' );
1175 static HRESULT
write_endstartelement( struct writer
*writer
)
1177 switch (writer
->output_enc
)
1179 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endstartelement_text( writer
);
1180 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return S_OK
;
1182 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1183 return WS_E_NOT_SUPPORTED
;
1187 /**************************************************************************
1188 * WsWriteEndStartElement [webservices.@]
1190 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1192 struct writer
*writer
= (struct writer
*)handle
;
1195 TRACE( "%p %p\n", handle
, error
);
1196 if (error
) FIXME( "ignoring error parameter\n" );
1198 if (!writer
) return E_INVALIDARG
;
1200 EnterCriticalSection( &writer
->cs
);
1202 if (writer
->magic
!= WRITER_MAGIC
)
1204 LeaveCriticalSection( &writer
->cs
);
1205 return E_INVALIDARG
;
1208 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1210 LeaveCriticalSection( &writer
->cs
);
1211 return WS_E_INVALID_OPERATION
;
1214 if ((hr
= set_namespaces( writer
)) != S_OK
) goto done
;
1215 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
1216 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
1217 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1220 LeaveCriticalSection( &writer
->cs
);
1224 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1225 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1228 WS_XML_ATTRIBUTE
*attr
;
1229 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1232 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1234 if (!prefix
&& ns
->length
) prefix
= elem
->prefix
;
1236 attr
->singleQuote
= !!single
;
1237 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
1239 free_attribute( attr
);
1240 return E_OUTOFMEMORY
;
1242 if (!(attr
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1244 free_attribute( attr
);
1245 return E_OUTOFMEMORY
;
1247 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
1249 free_attribute( attr
);
1250 return E_OUTOFMEMORY
;
1252 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1254 free_attribute( attr
);
1260 /**************************************************************************
1261 * WsWriteStartAttribute [webservices.@]
1263 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1264 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1265 BOOL single
, WS_ERROR
*error
)
1267 struct writer
*writer
= (struct writer
*)handle
;
1270 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1271 debugstr_xmlstr(ns
), single
, error
);
1272 if (error
) FIXME( "ignoring error parameter\n" );
1274 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1276 EnterCriticalSection( &writer
->cs
);
1278 if (writer
->magic
!= WRITER_MAGIC
)
1280 LeaveCriticalSection( &writer
->cs
);
1281 return E_INVALIDARG
;
1284 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1286 LeaveCriticalSection( &writer
->cs
);
1287 return WS_E_INVALID_OPERATION
;
1290 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
1291 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1293 LeaveCriticalSection( &writer
->cs
);
1297 /* flush current start element if necessary */
1298 static HRESULT
write_flush( struct writer
*writer
)
1300 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1303 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1304 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1305 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
1306 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1311 static HRESULT
write_add_cdata_node( struct writer
*writer
)
1313 struct node
*node
, *parent
;
1314 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1315 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1316 write_insert_node( writer
, parent
, node
);
1320 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
1323 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
1324 node
->parent
= writer
->current
;
1325 list_add_tail( &node
->parent
->children
, &node
->entry
);
1329 static HRESULT
write_cdata( struct writer
*writer
)
1332 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
1333 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
1337 static HRESULT
write_cdata_node( struct writer
*writer
)
1340 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1341 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
1342 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
1343 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
1344 writer
->state
= WRITER_STATE_STARTCDATA
;
1348 /**************************************************************************
1349 * WsWriteStartCData [webservices.@]
1351 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1353 struct writer
*writer
= (struct writer
*)handle
;
1356 TRACE( "%p %p\n", handle
, error
);
1357 if (error
) FIXME( "ignoring error parameter\n" );
1359 if (!writer
) return E_INVALIDARG
;
1361 EnterCriticalSection( &writer
->cs
);
1363 if (writer
->magic
!= WRITER_MAGIC
)
1365 LeaveCriticalSection( &writer
->cs
);
1366 return E_INVALIDARG
;
1369 hr
= write_cdata_node( writer
);
1371 LeaveCriticalSection( &writer
->cs
);
1375 static HRESULT
write_endcdata( struct writer
*writer
)
1378 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
1379 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
1383 static HRESULT
write_endcdata_node( struct writer
*writer
)
1386 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
1387 writer
->current
= writer
->current
->parent
;
1388 writer
->state
= WRITER_STATE_ENDCDATA
;
1392 /**************************************************************************
1393 * WsWriteEndCData [webservices.@]
1395 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1397 struct writer
*writer
= (struct writer
*)handle
;
1400 TRACE( "%p %p\n", handle
, error
);
1401 if (error
) FIXME( "ignoring error parameter\n" );
1403 if (!writer
) return E_INVALIDARG
;
1405 EnterCriticalSection( &writer
->cs
);
1407 if (writer
->magic
!= WRITER_MAGIC
)
1409 LeaveCriticalSection( &writer
->cs
);
1410 return E_INVALIDARG
;
1413 if (writer
->state
!= WRITER_STATE_TEXT
)
1415 LeaveCriticalSection( &writer
->cs
);
1416 return WS_E_INVALID_OPERATION
;
1419 hr
= write_endcdata_node( writer
);
1421 LeaveCriticalSection( &writer
->cs
);
1425 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1426 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1428 struct node
*node
, *parent
;
1429 WS_XML_ELEMENT_NODE
*elem
;
1431 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1433 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1435 elem
= &parent
->hdr
;
1436 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
1439 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
1442 if (prefix
&& !(elem
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
1445 return E_OUTOFMEMORY
;
1447 if (!(elem
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1450 return E_OUTOFMEMORY
;
1452 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
1455 return E_OUTOFMEMORY
;
1457 write_insert_node( writer
, parent
, node
);
1461 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
1464 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1465 node
->parent
= parent
;
1466 list_add_tail( &parent
->children
, &node
->entry
);
1470 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1471 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1474 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1475 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
1476 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
1477 writer
->state
= WRITER_STATE_STARTELEMENT
;
1481 /**************************************************************************
1482 * WsWriteStartElement [webservices.@]
1484 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1485 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1488 struct writer
*writer
= (struct writer
*)handle
;
1491 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1492 debugstr_xmlstr(ns
), error
);
1493 if (error
) FIXME( "ignoring error parameter\n" );
1495 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1497 EnterCriticalSection( &writer
->cs
);
1499 if (writer
->magic
!= WRITER_MAGIC
)
1501 LeaveCriticalSection( &writer
->cs
);
1502 return E_INVALIDARG
;
1505 hr
= write_element_node( writer
, prefix
, localname
, ns
);
1507 LeaveCriticalSection( &writer
->cs
);
1511 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
1513 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1516 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1517 return sizeof(bool_true
);
1519 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1520 return sizeof(bool_false
);
1523 static ULONG
format_int8( const INT8
*ptr
, unsigned char *buf
)
1525 return wsprintfA( (char *)buf
, "%d", *ptr
);
1528 static ULONG
format_int16( const INT16
*ptr
, unsigned char *buf
)
1530 return wsprintfA( (char *)buf
, "%d", *ptr
);
1533 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1535 return wsprintfA( (char *)buf
, "%d", *ptr
);
1538 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1540 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1543 static ULONG
format_uint8( const UINT8
*ptr
, unsigned char *buf
)
1545 return wsprintfA( (char *)buf
, "%u", *ptr
);
1548 static ULONG
format_uint16( const UINT16
*ptr
, unsigned char *buf
)
1550 return wsprintfA( (char *)buf
, "%u", *ptr
);
1553 static ULONG
format_uint32( const UINT32
*ptr
, unsigned char *buf
)
1555 return wsprintfA( (char *)buf
, "%u", *ptr
);
1558 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1560 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1563 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
1566 static const long double precision
= 0.0000000000000001;
1567 unsigned char *p
= buf
;
1568 long double val
= *ptr
;
1569 int neg
, mag
, mag2
, use_exp
;
1573 memcpy( buf
, "NaN", 3 );
1580 memcpy( buf
, "-INF", 4 );
1583 memcpy( buf
, "INF", 3 );
1592 if ((neg
= val
< 0))
1598 mag
= log10l( val
);
1599 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1602 if (mag
< 0) mag
-= 1;
1603 val
= val
/ powl( 10.0, mag
);
1607 else if (mag
< 1) mag
= 0;
1609 while (val
> precision
|| mag
>= 0)
1611 long double weight
= powl( 10.0, mag
);
1612 if (weight
> 0 && !isinf( weight
))
1614 int digit
= floorl( val
/ weight
);
1615 val
-= digit
* weight
;
1616 *(p
++) = '0' + digit
;
1618 if (!mag
&& val
> precision
) *(p
++) = '.';
1626 if (mag2
> 0) *(p
++) = '+';
1635 *(p
++) = '0' + mag2
% 10;
1639 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1649 FIXME( "powl not found at build time\n" );
1654 static inline int year_size( int year
)
1656 return leap_year( year
) ? 366 : 365;
1660 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
1662 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
1663 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
1664 unsigned __int64 ticks
, day_ticks
;
1667 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
1668 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
1670 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1671 tz_hour
= TZ_OFFSET
;
1678 day
= ticks
/ TICKS_PER_DAY
;
1679 day_ticks
= ticks
% TICKS_PER_DAY
;
1680 hour
= day_ticks
/ TICKS_PER_HOUR
;
1681 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1682 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1683 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1685 while (day
>= year_size( year
))
1687 day
-= year_size( year
);
1690 while (day
>= month_days
[leap_year( year
)][month
])
1692 day
-= month_days
[leap_year( year
)][month
];
1696 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
1699 static const char fmt_frac
[] = ".%07u";
1700 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
1701 while (buf
[len
- 1] == '0') len
--;
1703 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
1707 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
1709 static const char fmt_tz
[] = "%c%02u:00";
1710 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
1716 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1718 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1719 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1720 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1721 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1724 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
1726 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1727 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1728 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1729 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1732 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
1734 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1739 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
1740 x
= (bin
[0] & 3) << 4;
1743 buf
[i
++] = base64
[x
];
1748 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
1749 x
= (bin
[1] & 0x0f) << 2;
1752 buf
[i
++] = base64
[x
];
1756 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
1757 buf
[i
++] = base64
[bin
[2] & 0x3f];
1764 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, WS_XML_UTF8_TEXT
**ret
)
1766 ULONG len_old
= old
? old
->value
.length
: 0;
1768 switch (text
->textType
)
1770 case WS_XML_TEXT_TYPE_UTF8
:
1772 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1774 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
1775 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1776 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
1779 case WS_XML_TEXT_TYPE_UTF16
:
1781 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1782 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1783 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1785 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1786 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1787 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
1788 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1789 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
1792 case WS_XML_TEXT_TYPE_BASE64
:
1794 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
1795 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
1797 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1798 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1799 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1802 case WS_XML_TEXT_TYPE_BOOL
:
1804 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1806 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
1807 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1808 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1811 case WS_XML_TEXT_TYPE_INT32
:
1813 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1814 unsigned char buf
[12]; /* "-2147483648" */
1815 ULONG len
= format_int32( &int32_text
->value
, buf
);
1817 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1818 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1819 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1822 case WS_XML_TEXT_TYPE_INT64
:
1824 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1825 unsigned char buf
[21]; /* "-9223372036854775808" */
1826 ULONG len
= format_int64( &int64_text
->value
, buf
);
1828 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1829 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1830 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1833 case WS_XML_TEXT_TYPE_UINT64
:
1835 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1836 unsigned char buf
[21]; /* "18446744073709551615" */
1837 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1839 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1840 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1841 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1844 case WS_XML_TEXT_TYPE_DOUBLE
:
1846 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1847 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
1848 unsigned short fpword
;
1851 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
1852 len
= format_double( &double_text
->value
, buf
);
1853 restore_fpword( fpword
);
1854 if (!len
) return E_NOTIMPL
;
1856 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1857 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1858 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1861 case WS_XML_TEXT_TYPE_GUID
:
1863 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1865 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
1866 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1867 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1870 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1872 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1874 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
1875 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1876 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1879 case WS_XML_TEXT_TYPE_DATETIME
:
1881 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
1883 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
1884 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1885 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1889 FIXME( "unhandled text type %u\n", text
->textType
);
1894 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
1896 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1897 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
1900 switch (value
->textType
)
1902 case WS_XML_TEXT_TYPE_UTF8
:
1903 case WS_XML_TEXT_TYPE_UTF16
:
1904 case WS_XML_TEXT_TYPE_BASE64
:
1907 case WS_XML_TEXT_TYPE_BOOL
:
1908 case WS_XML_TEXT_TYPE_INT32
:
1909 case WS_XML_TEXT_TYPE_INT64
:
1910 case WS_XML_TEXT_TYPE_UINT64
:
1911 case WS_XML_TEXT_TYPE_DOUBLE
:
1912 case WS_XML_TEXT_TYPE_GUID
:
1913 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1914 case WS_XML_TEXT_TYPE_DATETIME
:
1915 if (old
) return WS_E_INVALID_OPERATION
;
1919 FIXME( "unhandled text type %u\n", value
->textType
);
1923 if ((hr
= text_to_utf8text( value
, old
, &new )) != S_OK
) return hr
;
1926 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
1931 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
1934 WS_XML_TEXT_NODE
*text
;
1935 WS_XML_UTF8_TEXT
*utf8
;
1938 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
1939 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
1940 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
1942 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1943 if ((hr
= text_to_utf8text( value
, NULL
, &utf8
)) != S_OK
)
1948 text
= (WS_XML_TEXT_NODE
*)node
;
1949 text
->text
= &utf8
->text
;
1951 write_insert_node( writer
, writer
->current
, node
);
1955 static HRESULT
write_text_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
1957 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1960 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1962 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
1963 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
1965 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
1967 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
1968 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
1972 return WS_E_INVALID_FORMAT
;
1975 static HRESULT
write_text_bin( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
1977 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1978 enum record_type type
= get_text_record_type( text
, FALSE
);
1983 FIXME( "no support for appending text in binary mode\n" );
1984 return WS_E_NOT_SUPPORTED
;
1989 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
1990 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1991 write_char( writer
, type
);
1992 if (!utf8
|| !utf8
->value
.length
) write_char( writer
, 0 );
1995 write_char( writer
, utf8
->value
.length
);
1996 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
)) != S_OK
) return hr
;
1997 write_bytes( writer
, utf8
->value
.bytes
, utf8
->value
.length
);
2002 FIXME( "unhandled record type %u\n", type
);
2003 return WS_E_NOT_SUPPORTED
;
2007 static HRESULT
write_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2009 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
2011 switch (writer
->output_enc
)
2013 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_text_text( writer
, text
, offset
);
2014 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_text_bin( writer
, text
, offset
);
2016 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2017 return WS_E_NOT_SUPPORTED
;
2021 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
2023 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2027 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2028 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
2031 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
2032 node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2036 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
2038 offset
= old
->value
.length
;
2039 if ((hr
= text_to_utf8text( text
, old
, &new )) != S_OK
) return hr
;
2041 node
->text
= &new->text
;
2044 if ((hr
= write_text( writer
, node
->text
, offset
)) != S_OK
) return hr
;
2046 writer
->state
= WRITER_STATE_TEXT
;
2050 /**************************************************************************
2051 * WsWriteText [webservices.@]
2053 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
2055 struct writer
*writer
= (struct writer
*)handle
;
2058 TRACE( "%p %p %p\n", handle
, text
, error
);
2059 if (error
) FIXME( "ignoring error parameter\n" );
2061 if (!writer
|| !text
) return E_INVALIDARG
;
2063 EnterCriticalSection( &writer
->cs
);
2065 if (writer
->magic
!= WRITER_MAGIC
)
2067 LeaveCriticalSection( &writer
->cs
);
2068 return E_INVALIDARG
;
2071 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
2072 else hr
= write_text_node( writer
, text
);
2074 LeaveCriticalSection( &writer
->cs
);
2078 /**************************************************************************
2079 * WsWriteBytes [webservices.@]
2081 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
2083 struct writer
*writer
= (struct writer
*)handle
;
2084 WS_XML_BASE64_TEXT base64
;
2087 TRACE( "%p %p %u %p\n", handle
, bytes
, count
, error
);
2088 if (error
) FIXME( "ignoring error parameter\n" );
2090 if (!writer
) return E_INVALIDARG
;
2092 EnterCriticalSection( &writer
->cs
);
2094 if (writer
->magic
!= WRITER_MAGIC
)
2096 LeaveCriticalSection( &writer
->cs
);
2097 return E_INVALIDARG
;
2100 if (!writer
->output_type
)
2102 LeaveCriticalSection( &writer
->cs
);
2103 return WS_E_INVALID_OPERATION
;
2106 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2107 base64
.bytes
= (BYTE
*)bytes
;
2108 base64
.length
= count
;
2110 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
2111 else hr
= write_text_node( writer
, &base64
.text
);
2113 LeaveCriticalSection( &writer
->cs
);
2117 /**************************************************************************
2118 * WsWriteChars [webservices.@]
2120 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
2122 struct writer
*writer
= (struct writer
*)handle
;
2123 WS_XML_UTF16_TEXT utf16
;
2126 TRACE( "%p %s %u %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
2127 if (error
) FIXME( "ignoring error parameter\n" );
2129 if (!writer
) return E_INVALIDARG
;
2131 EnterCriticalSection( &writer
->cs
);
2133 if (writer
->magic
!= WRITER_MAGIC
)
2135 LeaveCriticalSection( &writer
->cs
);
2136 return E_INVALIDARG
;
2139 if (!writer
->output_type
)
2141 LeaveCriticalSection( &writer
->cs
);
2142 return WS_E_INVALID_OPERATION
;
2145 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2146 utf16
.bytes
= (BYTE
*)chars
;
2147 utf16
.byteCount
= count
* sizeof(WCHAR
);
2149 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
2150 else hr
= write_text_node( writer
, &utf16
.text
);
2152 LeaveCriticalSection( &writer
->cs
);
2156 /**************************************************************************
2157 * WsWriteCharsUtf8 [webservices.@]
2159 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
2161 struct writer
*writer
= (struct writer
*)handle
;
2162 WS_XML_UTF8_TEXT utf8
;
2165 TRACE( "%p %s %u %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
2166 if (error
) FIXME( "ignoring error parameter\n" );
2168 if (!writer
) return E_INVALIDARG
;
2170 EnterCriticalSection( &writer
->cs
);
2172 if (writer
->magic
!= WRITER_MAGIC
)
2174 LeaveCriticalSection( &writer
->cs
);
2175 return E_INVALIDARG
;
2178 if (!writer
->output_type
)
2180 LeaveCriticalSection( &writer
->cs
);
2181 return WS_E_INVALID_OPERATION
;
2184 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2185 utf8
.value
.bytes
= (BYTE
*)bytes
;
2186 utf8
.value
.length
= count
;
2188 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
2189 else hr
= write_text_node( writer
, &utf8
.text
);
2191 LeaveCriticalSection( &writer
->cs
);
2195 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
2199 case WS_ELEMENT_TYPE_MAPPING
:
2200 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2201 return write_text_node( writer
, text
);
2203 case WS_ATTRIBUTE_TYPE_MAPPING
:
2204 return write_set_attribute_value( writer
, text
);
2206 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2207 switch (writer
->state
)
2209 case WRITER_STATE_STARTATTRIBUTE
:
2210 return write_set_attribute_value( writer
, text
);
2212 case WRITER_STATE_STARTELEMENT
:
2213 return write_text_node( writer
, text
);
2216 FIXME( "writer state %u not handled\n", writer
->state
);
2221 FIXME( "mapping %u not implemented\n", mapping
);
2226 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
2228 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
2229 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
2230 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
2231 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
2234 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
2235 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
2236 return add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
2239 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
2244 case WS_WRITE_REQUIRED_VALUE
:
2245 case WS_WRITE_NILLABLE_VALUE
:
2246 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
2250 case WS_WRITE_REQUIRED_POINTER
:
2251 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
2254 case WS_WRITE_NILLABLE_POINTER
:
2255 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
2256 *ptr
= *(const void **)value
;
2260 return E_INVALIDARG
;
2264 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2265 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2266 const BOOL
*value
, ULONG size
)
2268 WS_XML_UTF8_TEXT utf8
;
2269 unsigned char buf
[6]; /* "false" */
2275 FIXME( "description not supported\n" );
2279 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2280 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
2281 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2283 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2284 utf8
.value
.bytes
= buf
;
2285 utf8
.value
.length
= format_bool( ptr
, buf
);
2286 return write_type_text( writer
, mapping
, &utf8
.text
);
2289 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2290 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2291 const BOOL
*value
, ULONG size
)
2293 WS_XML_UTF8_TEXT utf8
;
2294 unsigned char buf
[5]; /* "-128" */
2300 FIXME( "description not supported\n" );
2304 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2305 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
2306 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2308 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2309 utf8
.value
.bytes
= buf
;
2310 utf8
.value
.length
= format_int8( ptr
, buf
);
2311 return write_type_text( writer
, mapping
, &utf8
.text
);
2314 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2315 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2316 const BOOL
*value
, ULONG size
)
2318 WS_XML_UTF8_TEXT utf8
;
2319 unsigned char buf
[7]; /* "-32768" */
2325 FIXME( "description not supported\n" );
2329 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2330 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
2331 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2333 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2334 utf8
.value
.bytes
= buf
;
2335 utf8
.value
.length
= format_int16( ptr
, buf
);
2336 return write_type_text( writer
, mapping
, &utf8
.text
);
2339 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2340 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2341 const void *value
, ULONG size
)
2343 WS_XML_UTF8_TEXT utf8
;
2344 unsigned char buf
[12]; /* "-2147483648" */
2350 FIXME( "description not supported\n" );
2354 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2355 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
2356 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2358 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2359 utf8
.value
.bytes
= buf
;
2360 utf8
.value
.length
= format_int32( ptr
, buf
);
2361 return write_type_text( writer
, mapping
, &utf8
.text
);
2364 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2365 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2366 const void *value
, ULONG size
)
2368 WS_XML_UTF8_TEXT utf8
;
2369 unsigned char buf
[21]; /* "-9223372036854775808" */
2375 FIXME( "description not supported\n" );
2379 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2380 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
2381 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2383 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2384 utf8
.value
.bytes
= buf
;
2385 utf8
.value
.length
= format_int64( ptr
, buf
);
2386 return write_type_text( writer
, mapping
, &utf8
.text
);
2389 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2390 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2391 const void *value
, ULONG size
)
2393 WS_XML_UTF8_TEXT utf8
;
2394 unsigned char buf
[4]; /* "255" */
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(UINT8
), (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_uint8( ptr
, buf
);
2411 return write_type_text( writer
, mapping
, &utf8
.text
);
2414 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2415 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2416 const void *value
, ULONG size
)
2418 WS_XML_UTF8_TEXT utf8
;
2419 unsigned char buf
[6]; /* "65535" */
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(UINT16
), (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_uint16( ptr
, buf
);
2436 return write_type_text( writer
, mapping
, &utf8
.text
);
2439 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2440 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2441 const void *value
, ULONG size
)
2443 WS_XML_UTF8_TEXT utf8
;
2444 unsigned char buf
[11]; /* "4294967295" */
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(UINT32
), (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_uint32( ptr
, buf
);
2461 return write_type_text( writer
, mapping
, &utf8
.text
);
2464 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2465 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2466 const void *value
, ULONG size
)
2468 WS_XML_UTF8_TEXT utf8
;
2469 unsigned char buf
[21]; /* "18446744073709551615" */
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(UINT64
), (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_uint64( ptr
, buf
);
2486 return write_type_text( writer
, mapping
, &utf8
.text
);
2489 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2490 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2491 const void *value
, ULONG size
)
2493 WS_XML_UTF8_TEXT utf8
;
2494 unsigned char buf
[34]; /* "0000-00-00T00:00:00.0000000-00:00" */
2495 const WS_DATETIME
*ptr
;
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(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
2506 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2507 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
2509 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2510 utf8
.value
.bytes
= buf
;
2511 utf8
.value
.length
= format_datetime( ptr
, buf
);
2512 return write_type_text( writer
, mapping
, &utf8
.text
);
2515 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2516 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2517 const void *value
, ULONG size
)
2519 WS_XML_UTF8_TEXT utf8
;
2520 unsigned char buf
[37]; /* "00000000-0000-0000-0000-000000000000" */
2526 FIXME( "description not supported\n" );
2530 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2531 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
2532 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2534 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2535 utf8
.value
.bytes
= buf
;
2536 utf8
.value
.length
= format_guid( ptr
, buf
);
2537 return write_type_text( writer
, mapping
, &utf8
.text
);
2540 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2541 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2542 const void *value
, ULONG size
)
2544 WS_XML_UTF16_TEXT utf16
;
2545 const WS_STRING
*ptr
;
2550 FIXME( "description not supported\n" );
2554 if (!option
) return E_INVALIDARG
;
2555 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
2556 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2557 if (!ptr
->length
) return S_OK
;
2559 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2560 utf16
.bytes
= (BYTE
*)ptr
->chars
;
2561 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
2562 return write_type_text( writer
, mapping
, &utf16
.text
);
2565 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2566 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2567 const void *value
, ULONG size
)
2569 WS_XML_UTF16_TEXT utf16
;
2576 FIXME( "description not supported\n" );
2580 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2581 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
2582 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2583 if (!(len
= strlenW( ptr
))) return S_OK
;
2585 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2586 utf16
.bytes
= (BYTE
*)ptr
;
2587 utf16
.byteCount
= len
* sizeof(WCHAR
);
2588 return write_type_text( writer
, mapping
, &utf16
.text
);
2591 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2592 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2593 const void *value
, ULONG size
)
2595 WS_XML_BASE64_TEXT base64
;
2596 const WS_BYTES
*ptr
;
2601 FIXME( "description not supported\n" );
2605 if (!option
) return E_INVALIDARG
;
2606 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
2607 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
2608 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
2609 if (!ptr
->length
) return S_OK
;
2611 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2612 base64
.bytes
= ptr
->bytes
;
2613 base64
.length
= ptr
->length
;
2614 return write_type_text( writer
, mapping
, &base64
.text
);
2617 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2618 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2619 const void *value
, ULONG size
)
2621 WS_XML_UTF8_TEXT utf8
;
2622 const WS_XML_STRING
*ptr
;
2627 FIXME( "description not supported\n" );
2631 if (!option
) return E_INVALIDARG
;
2632 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
2633 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2634 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
2635 if (!ptr
->length
) return S_OK
;
2637 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2638 utf8
.value
.bytes
= ptr
->bytes
;
2639 utf8
.value
.length
= ptr
->length
;
2640 return write_type_text( writer
, mapping
, &utf8
.text
);
2643 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
2645 if (options
& WS_FIELD_POINTER
)
2647 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
2648 return WS_WRITE_REQUIRED_POINTER
;
2659 case WS_UINT16_TYPE
:
2660 case WS_UINT32_TYPE
:
2661 case WS_UINT64_TYPE
:
2662 case WS_DOUBLE_TYPE
:
2663 case WS_DATETIME_TYPE
:
2665 case WS_STRING_TYPE
:
2667 case WS_XML_STRING_TYPE
:
2668 case WS_STRUCT_TYPE
:
2670 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
2671 return WS_WRITE_REQUIRED_VALUE
;
2674 case WS_DESCRIPTION_TYPE
:
2675 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
2676 return WS_WRITE_REQUIRED_POINTER
;
2679 FIXME( "unhandled type %u\n", type
);
2684 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
2685 const void *, ULONG
);
2687 static HRESULT
write_type_repeating_element( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
2688 const char *buf
, ULONG count
)
2691 ULONG i
, size
, offset
= 0;
2692 WS_WRITE_OPTION option
;
2694 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
2696 /* wrapper element */
2697 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
2700 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
2701 size
= get_type_size( desc
->type
, desc
->typeDescription
);
2703 size
= sizeof(const void *);
2705 for (i
= 0; i
< count
; i
++)
2707 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
2708 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
2709 buf
+ offset
, size
)) != S_OK
) return hr
;
2710 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2714 if (desc
->localName
) hr
= write_endelement_node( writer
);
2718 static HRESULT
write_type_struct_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
2719 const char *buf
, ULONG offset
)
2722 WS_TYPE_MAPPING mapping
;
2723 WS_WRITE_OPTION option
;
2724 ULONG count
, size
, field_options
= desc
->options
;
2725 const char *ptr
= buf
+ offset
;
2727 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
2729 FIXME( "options 0x%x not supported\n", desc
->options
);
2733 /* zero-terminated strings are always pointers */
2734 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
2736 if (field_options
& WS_FIELD_POINTER
)
2737 size
= sizeof(const void *);
2739 size
= get_type_size( desc
->type
, desc
->typeDescription
);
2741 if (is_nil_value( ptr
, size
))
2743 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
2744 if (field_options
& WS_FIELD_NILLABLE
)
2746 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
2747 else option
= WS_WRITE_NILLABLE_VALUE
;
2749 else return E_INVALIDARG
;
2753 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
2754 else option
= WS_WRITE_REQUIRED_VALUE
;
2757 switch (desc
->mapping
)
2759 case WS_ATTRIBUTE_FIELD_MAPPING
:
2760 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
2761 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
2763 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2765 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2768 case WS_ELEMENT_FIELD_MAPPING
:
2769 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
2770 mapping
= WS_ELEMENT_TYPE_MAPPING
;
2773 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
2774 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
2775 return write_type_repeating_element( writer
, desc
, *(const char **)ptr
, count
);
2777 case WS_TEXT_FIELD_MAPPING
:
2778 switch (writer
->state
)
2780 case WRITER_STATE_STARTELEMENT
:
2781 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
2784 case WRITER_STATE_STARTATTRIBUTE
:
2785 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2789 FIXME( "unhandled writer state %u\n", writer
->state
);
2795 FIXME( "field mapping %u not supported\n", desc
->mapping
);
2799 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
2804 case WS_ATTRIBUTE_TYPE_MAPPING
:
2805 writer
->state
= WRITER_STATE_STARTELEMENT
;
2808 case WS_ELEMENT_TYPE_MAPPING
:
2809 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2818 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2819 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2820 const void *value
, ULONG size
)
2826 if (!desc
) return E_INVALIDARG
;
2827 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
2829 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
2831 for (i
= 0; i
< desc
->fieldCount
; i
++)
2833 offset
= desc
->fields
[i
]->offset
;
2834 if ((hr
= write_type_struct_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
)
2842 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
2843 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
2849 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
2852 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
2855 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
2858 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
2861 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
2864 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
2866 case WS_UINT16_TYPE
:
2867 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
2869 case WS_UINT32_TYPE
:
2870 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
2872 case WS_UINT64_TYPE
:
2873 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
2875 case WS_DATETIME_TYPE
:
2876 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
2879 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
2881 case WS_STRING_TYPE
:
2882 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
2885 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
2888 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
2890 case WS_XML_STRING_TYPE
:
2891 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
2893 case WS_STRUCT_TYPE
:
2894 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
2897 FIXME( "type %u not supported\n", type
);
2902 /**************************************************************************
2903 * WsWriteAttribute [webservices.@]
2905 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
2906 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
2909 struct writer
*writer
= (struct writer
*)handle
;
2912 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
2913 if (error
) FIXME( "ignoring error parameter\n" );
2915 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
2916 return E_INVALIDARG
;
2918 EnterCriticalSection( &writer
->cs
);
2920 if (writer
->magic
!= WRITER_MAGIC
)
2922 LeaveCriticalSection( &writer
->cs
);
2923 return E_INVALIDARG
;
2926 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
2928 LeaveCriticalSection( &writer
->cs
);
2929 return WS_E_INVALID_OPERATION
;
2932 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) != S_OK
)
2934 LeaveCriticalSection( &writer
->cs
);
2937 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2939 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
2941 LeaveCriticalSection( &writer
->cs
);
2945 /**************************************************************************
2946 * WsWriteElement [webservices.@]
2948 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
2949 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
2952 struct writer
*writer
= (struct writer
*)handle
;
2955 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
2956 if (error
) FIXME( "ignoring error parameter\n" );
2958 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
2959 return E_INVALIDARG
;
2961 EnterCriticalSection( &writer
->cs
);
2963 if (writer
->magic
!= WRITER_MAGIC
)
2965 LeaveCriticalSection( &writer
->cs
);
2966 return E_INVALIDARG
;
2969 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
2971 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
2972 option
, value
, size
)) != S_OK
) goto done
;
2974 hr
= write_endelement_node( writer
);
2977 LeaveCriticalSection( &writer
->cs
);
2981 /**************************************************************************
2982 * WsWriteType [webservices.@]
2984 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
2985 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
2986 ULONG size
, WS_ERROR
*error
)
2988 struct writer
*writer
= (struct writer
*)handle
;
2991 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
2993 if (error
) FIXME( "ignoring error parameter\n" );
2995 if (!writer
|| !value
) return E_INVALIDARG
;
2997 EnterCriticalSection( &writer
->cs
);
2999 if (writer
->magic
!= WRITER_MAGIC
)
3001 LeaveCriticalSection( &writer
->cs
);
3002 return E_INVALIDARG
;
3007 case WS_ATTRIBUTE_TYPE_MAPPING
:
3008 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
3009 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3012 case WS_ELEMENT_TYPE_MAPPING
:
3013 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3014 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_FORMAT
;
3015 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3018 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3019 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3023 FIXME( "mapping %u not implemented\n", mapping
);
3027 LeaveCriticalSection( &writer
->cs
);
3031 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
3035 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
3036 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
3037 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
3038 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
3039 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
3040 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
3041 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
3042 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
3043 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
3044 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
3045 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
3046 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
3047 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
3048 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
3049 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
3051 FIXME( "unhandled type %u\n", type
);
3056 /**************************************************************************
3057 * WsWriteValue [webservices.@]
3059 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
3060 ULONG size
, WS_ERROR
*error
)
3062 struct writer
*writer
= (struct writer
*)handle
;
3063 WS_TYPE_MAPPING mapping
;
3067 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
3068 if (error
) FIXME( "ignoring error parameter\n" );
3070 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
3072 EnterCriticalSection( &writer
->cs
);
3074 if (writer
->magic
!= WRITER_MAGIC
)
3076 LeaveCriticalSection( &writer
->cs
);
3077 return E_INVALIDARG
;
3080 switch (writer
->state
)
3082 case WRITER_STATE_STARTATTRIBUTE
:
3083 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3086 case WRITER_STATE_STARTELEMENT
:
3087 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3091 hr
= WS_E_INVALID_FORMAT
;
3094 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
3096 LeaveCriticalSection( &writer
->cs
);
3100 /**************************************************************************
3101 * WsWriteArray [webservices.@]
3103 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3104 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
3105 ULONG count
, WS_ERROR
*error
)
3107 struct writer
*writer
= (struct writer
*)handle
;
3112 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3113 value_type
, array
, size
, offset
, count
, error
);
3114 if (error
) FIXME( "ignoring error parameter\n" );
3116 if (!writer
) return E_INVALIDARG
;
3118 EnterCriticalSection( &writer
->cs
);
3120 if (writer
->magic
!= WRITER_MAGIC
)
3122 LeaveCriticalSection( &writer
->cs
);
3123 return E_INVALIDARG
;
3126 if (!writer
->output_type
)
3128 LeaveCriticalSection( &writer
->cs
);
3129 return WS_E_INVALID_OPERATION
;
3132 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
3134 LeaveCriticalSection( &writer
->cs
);
3135 return E_INVALIDARG
;
3138 type_size
= get_type_size( type
, NULL
);
3139 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
3141 LeaveCriticalSection( &writer
->cs
);
3142 return E_INVALIDARG
;
3145 for (i
= offset
; i
< count
; i
++)
3147 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
3148 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
3149 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
3150 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
3151 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
3155 LeaveCriticalSection( &writer
->cs
);
3159 /**************************************************************************
3160 * WsWriteXmlBuffer [webservices.@]
3162 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
3164 struct writer
*writer
= (struct writer
*)handle
;
3165 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
3168 TRACE( "%p %p %p\n", handle
, buffer
, error
);
3169 if (error
) FIXME( "ignoring error parameter\n" );
3171 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
3173 EnterCriticalSection( &writer
->cs
);
3175 if (writer
->magic
!= WRITER_MAGIC
)
3177 LeaveCriticalSection( &writer
->cs
);
3178 return E_INVALIDARG
;
3181 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
3182 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
3183 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
3186 LeaveCriticalSection( &writer
->cs
);
3190 /**************************************************************************
3191 * WsWriteXmlBufferToBytes [webservices.@]
3193 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
3194 const WS_XML_WRITER_ENCODING
*encoding
,
3195 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
3196 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
3198 struct writer
*writer
= (struct writer
*)handle
;
3199 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
3204 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
3205 bytes
, size
, error
);
3206 if (error
) FIXME( "ignoring error parameter\n" );
3208 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
3210 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
3212 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
3216 EnterCriticalSection( &writer
->cs
);
3218 if (writer
->magic
!= WRITER_MAGIC
)
3220 LeaveCriticalSection( &writer
->cs
);
3221 return E_INVALIDARG
;
3224 for (i
= 0; i
< count
; i
++)
3226 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
3227 properties
[i
].valueSize
);
3228 if (hr
!= S_OK
) goto done
;
3231 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
3234 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
3236 *size
= xmlbuf
->bytes
.length
;
3240 LeaveCriticalSection( &writer
->cs
);
3244 /**************************************************************************
3245 * WsWriteXmlnsAttribute [webservices.@]
3247 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
3248 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
3250 struct writer
*writer
= (struct writer
*)handle
;
3253 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
3255 if (error
) FIXME( "ignoring error parameter\n" );
3257 if (!writer
|| !ns
) return E_INVALIDARG
;
3259 EnterCriticalSection( &writer
->cs
);
3261 if (writer
->magic
!= WRITER_MAGIC
)
3263 LeaveCriticalSection( &writer
->cs
);
3264 return E_INVALIDARG
;
3267 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3269 LeaveCriticalSection( &writer
->cs
);
3270 return WS_E_INVALID_OPERATION
;
3273 if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
3274 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
3276 LeaveCriticalSection( &writer
->cs
);
3280 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
3282 const struct node
*node
;
3283 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3285 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3287 for (i
= 0; i
< elem
->attributeCount
; i
++)
3289 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3290 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
3291 *prefix
= elem
->attributes
[i
]->prefix
;
3295 return WS_E_INVALID_FORMAT
;
3298 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
3299 const WS_XML_STRING
*localname
)
3304 if ((hr
= write_grow_buffer( writer
, prefix
->length
+ localname
->length
+ 1 )) != S_OK
) return hr
;
3305 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
3306 write_char( writer
, ':' );
3308 else if ((hr
= write_grow_buffer( writer
, localname
->length
)) != S_OK
) return hr
;
3309 write_bytes( writer
, localname
->bytes
, localname
->length
);
3313 /**************************************************************************
3314 * WsWriteQualifiedName [webservices.@]
3316 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
3317 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3320 struct writer
*writer
= (struct writer
*)handle
;
3323 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
3324 debugstr_xmlstr(ns
), error
);
3325 if (error
) FIXME( "ignoring error parameter\n" );
3327 if (!writer
) return E_INVALIDARG
;
3329 EnterCriticalSection( &writer
->cs
);
3331 if (writer
->magic
!= WRITER_MAGIC
)
3333 LeaveCriticalSection( &writer
->cs
);
3334 return E_INVALIDARG
;
3337 if (!writer
->output_type
)
3339 LeaveCriticalSection( &writer
->cs
);
3340 return WS_E_INVALID_OPERATION
;
3343 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3345 LeaveCriticalSection( &writer
->cs
);
3346 return WS_E_INVALID_FORMAT
;
3349 if (!localname
|| (!prefix
&& !ns
))
3351 LeaveCriticalSection( &writer
->cs
);
3352 return E_INVALIDARG
;
3355 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
3356 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) goto done
;
3357 hr
= write_qualified_name( writer
, prefix
, localname
);
3360 LeaveCriticalSection( &writer
->cs
);
3364 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
3366 BOOL success
= FALSE
;
3367 struct node
*node
= writer
->current
;
3371 case WS_MOVE_TO_ROOT_ELEMENT
:
3372 success
= move_to_root_element( writer
->root
, &node
);
3375 case WS_MOVE_TO_NEXT_ELEMENT
:
3376 success
= move_to_next_element( &node
);
3379 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
3380 success
= move_to_prev_element( &node
);
3383 case WS_MOVE_TO_CHILD_ELEMENT
:
3384 success
= move_to_child_element( &node
);
3387 case WS_MOVE_TO_END_ELEMENT
:
3388 success
= move_to_end_element( &node
);
3391 case WS_MOVE_TO_PARENT_ELEMENT
:
3392 success
= move_to_parent_element( &node
);
3395 case WS_MOVE_TO_FIRST_NODE
:
3396 success
= move_to_first_node( &node
);
3399 case WS_MOVE_TO_NEXT_NODE
:
3400 success
= move_to_next_node( &node
);
3403 case WS_MOVE_TO_PREVIOUS_NODE
:
3404 success
= move_to_prev_node( &node
);
3407 case WS_MOVE_TO_CHILD_NODE
:
3408 success
= move_to_child_node( &node
);
3411 case WS_MOVE_TO_BOF
:
3412 success
= move_to_bof( writer
->root
, &node
);
3415 case WS_MOVE_TO_EOF
:
3416 success
= move_to_eof( writer
->root
, &node
);
3420 FIXME( "unhandled move %u\n", move
);
3424 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
3425 writer
->current
= node
;
3432 return success
? S_OK
: WS_E_INVALID_FORMAT
;
3435 /**************************************************************************
3436 * WsMoveWriter [webservices.@]
3438 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
3440 struct writer
*writer
= (struct writer
*)handle
;
3443 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
3444 if (error
) FIXME( "ignoring error parameter\n" );
3446 if (!writer
) return E_INVALIDARG
;
3448 EnterCriticalSection( &writer
->cs
);
3450 if (writer
->magic
!= WRITER_MAGIC
)
3452 LeaveCriticalSection( &writer
->cs
);
3453 return E_INVALIDARG
;
3456 if (!writer
->output_type
)
3458 LeaveCriticalSection( &writer
->cs
);
3459 return WS_E_INVALID_OPERATION
;
3462 hr
= write_move_to( writer
, move
, found
);
3464 LeaveCriticalSection( &writer
->cs
);
3468 /**************************************************************************
3469 * WsGetWriterPosition [webservices.@]
3471 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
3473 struct writer
*writer
= (struct writer
*)handle
;
3475 TRACE( "%p %p %p\n", handle
, pos
, error
);
3476 if (error
) FIXME( "ignoring error parameter\n" );
3478 if (!writer
|| !pos
) return E_INVALIDARG
;
3480 EnterCriticalSection( &writer
->cs
);
3482 if (writer
->magic
!= WRITER_MAGIC
)
3484 LeaveCriticalSection( &writer
->cs
);
3485 return E_INVALIDARG
;
3488 if (!writer
->output_type
)
3490 LeaveCriticalSection( &writer
->cs
);
3491 return WS_E_INVALID_OPERATION
;
3494 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
3495 pos
->node
= writer
->current
;
3497 LeaveCriticalSection( &writer
->cs
);
3501 /**************************************************************************
3502 * WsSetWriterPosition [webservices.@]
3504 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
3506 struct writer
*writer
= (struct writer
*)handle
;
3508 TRACE( "%p %p %p\n", handle
, pos
, error
);
3509 if (error
) FIXME( "ignoring error parameter\n" );
3511 if (!writer
|| !pos
) return E_INVALIDARG
;
3513 EnterCriticalSection( &writer
->cs
);
3515 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
3517 LeaveCriticalSection( &writer
->cs
);
3518 return E_INVALIDARG
;
3521 if (!writer
->output_type
)
3523 LeaveCriticalSection( &writer
->cs
);
3524 return WS_E_INVALID_OPERATION
;
3527 writer
->current
= pos
->node
;
3529 LeaveCriticalSection( &writer
->cs
);
3533 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
3535 struct node
*node
, *parent
;
3536 WS_XML_COMMENT_NODE
*comment
;
3538 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
3539 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
3540 comment
= (WS_XML_COMMENT_NODE
*)node
;
3542 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
3545 return E_OUTOFMEMORY
;
3547 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
3548 comment
->value
.length
= value
->length
;
3550 write_insert_node( writer
, parent
, node
);
3554 static HRESULT
write_comment( struct writer
*writer
)
3556 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
3559 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
3560 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
3561 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
3562 write_bytes( writer
, (const BYTE
*)"-->", 3 );
3566 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
3569 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
3570 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
3571 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
3572 writer
->state
= WRITER_STATE_COMMENT
;
3576 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
3581 for (i
= 0; i
< count
; i
++)
3583 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
3584 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
3585 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
3590 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
3594 switch (node
->nodeType
)
3596 case WS_XML_NODE_TYPE_ELEMENT
:
3598 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
3599 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
3600 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
3602 case WS_XML_NODE_TYPE_TEXT
:
3604 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
3605 return write_text_node( writer
, text
->text
);
3607 case WS_XML_NODE_TYPE_END_ELEMENT
:
3608 return write_endelement_node( writer
);
3610 case WS_XML_NODE_TYPE_COMMENT
:
3612 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
3613 return write_comment_node( writer
, &comment
->value
);
3615 case WS_XML_NODE_TYPE_CDATA
:
3616 return write_cdata_node( writer
);
3618 case WS_XML_NODE_TYPE_END_CDATA
:
3619 return write_endcdata_node( writer
);
3621 case WS_XML_NODE_TYPE_EOF
:
3622 case WS_XML_NODE_TYPE_BOF
:
3626 WARN( "unknown node type %u\n", node
->nodeType
);
3627 return E_INVALIDARG
;
3631 /**************************************************************************
3632 * WsWriteNode [webservices.@]
3634 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
3636 struct writer
*writer
= (struct writer
*)handle
;
3639 TRACE( "%p %p %p\n", handle
, node
, error
);
3640 if (error
) FIXME( "ignoring error parameter\n" );
3642 if (!writer
|| !node
) return E_INVALIDARG
;
3644 EnterCriticalSection( &writer
->cs
);
3646 if (writer
->magic
!= WRITER_MAGIC
)
3648 LeaveCriticalSection( &writer
->cs
);
3649 return E_INVALIDARG
;
3652 if (!writer
->output_type
)
3654 LeaveCriticalSection( &writer
->cs
);
3655 return WS_E_INVALID_OPERATION
;
3658 hr
= write_node( writer
, node
);
3660 LeaveCriticalSection( &writer
->cs
);
3664 static HRESULT
write_tree_node( struct writer
*writer
)
3668 switch (node_type( writer
->current
))
3670 case WS_XML_NODE_TYPE_ELEMENT
:
3671 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3673 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
3674 writer
->state
= WRITER_STATE_STARTELEMENT
;
3677 case WS_XML_NODE_TYPE_TEXT
:
3678 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3680 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
3681 writer
->state
= WRITER_STATE_TEXT
;
3684 case WS_XML_NODE_TYPE_END_ELEMENT
:
3685 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
3686 writer
->state
= WRITER_STATE_ENDELEMENT
;
3689 case WS_XML_NODE_TYPE_COMMENT
:
3690 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3692 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
3693 writer
->state
= WRITER_STATE_COMMENT
;
3696 case WS_XML_NODE_TYPE_CDATA
:
3697 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3699 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
3700 writer
->state
= WRITER_STATE_STARTCDATA
;
3703 case WS_XML_NODE_TYPE_END_CDATA
:
3704 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
3705 writer
->state
= WRITER_STATE_ENDCDATA
;
3708 case WS_XML_NODE_TYPE_EOF
:
3709 case WS_XML_NODE_TYPE_BOF
:
3713 ERR( "unknown node type %u\n", node_type(writer
->current
) );
3714 return E_INVALIDARG
;
3718 static HRESULT
write_tree( struct writer
*writer
)
3722 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3725 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
3726 if (move_to_child_node( &writer
->current
))
3728 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3731 if (move_to_next_node( &writer
->current
))
3733 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3736 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
3738 ERR( "invalid tree\n" );
3739 return WS_E_INVALID_FORMAT
;
3741 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3746 static void write_rewind( struct writer
*writer
)
3748 writer
->write_pos
= 0;
3749 writer
->current
= writer
->root
;
3750 writer
->state
= WRITER_STATE_INITIAL
;
3753 /**************************************************************************
3754 * WsCopyNode [webservices.@]
3756 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
3758 struct writer
*writer
= (struct writer
*)handle
;
3759 struct node
*parent
, *current
, *node
= NULL
;
3762 TRACE( "%p %p %p\n", handle
, reader
, error
);
3763 if (error
) FIXME( "ignoring error parameter\n" );
3765 if (!writer
) return E_INVALIDARG
;
3767 EnterCriticalSection( &writer
->cs
);
3769 if (writer
->magic
!= WRITER_MAGIC
)
3771 LeaveCriticalSection( &writer
->cs
);
3772 return E_INVALIDARG
;
3775 if (!(parent
= find_parent( writer
)))
3777 LeaveCriticalSection( &writer
->cs
);
3778 return WS_E_INVALID_FORMAT
;
3781 if ((hr
= copy_node( reader
, &node
)) != S_OK
) goto done
;
3782 current
= writer
->current
;
3783 write_insert_node( writer
, parent
, node
);
3785 write_rewind( writer
);
3786 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
3787 writer
->current
= current
;
3789 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
3792 LeaveCriticalSection( &writer
->cs
);
3796 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
3798 return write_type_struct_field( writer
, desc
, value
, 0 );
3801 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
3804 for (i
= 0; i
< count
; i
++)
3806 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
3808 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
3814 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
3817 return write_type_repeating_element( writer
, desc
, value
, len
);
3820 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3821 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
3823 struct writer
*writer
= (struct writer
*)handle
;
3824 const WS_STRUCT_DESCRIPTION
*desc_struct
;
3825 const WS_FIELD_DESCRIPTION
*desc_field
;
3829 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
3831 EnterCriticalSection( &writer
->cs
);
3833 if (writer
->magic
!= WRITER_MAGIC
)
3835 LeaveCriticalSection( &writer
->cs
);
3836 return E_INVALIDARG
;
3839 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
3841 for (i
= 0; i
< count
; i
++)
3843 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
3844 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
3846 FIXME( "messages type not supported\n" );
3850 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
3851 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
3853 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
3855 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
3857 const void *ptr
= *(const void **)args
[i
];
3858 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
3859 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
3863 hr
= write_endelement_node( writer
);
3866 LeaveCriticalSection( &writer
->cs
);