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
30 #include "webservices.h"
32 #include "wine/debug.h"
33 #include "wine/list.h"
34 #include "webservices_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
38 static const struct prop_desc writer_props
[] =
40 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
41 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
42 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES */
43 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
44 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INDENT */
45 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
46 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_WRITER_PROPERTY_CHARSET */
47 { sizeof(WS_BUFFERS
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFERS */
48 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
49 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BYTES */
50 { sizeof(BOOL
), TRUE
}, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
51 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
52 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
53 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
54 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
55 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
56 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
57 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
58 { sizeof(BOOL
), FALSE
} /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
64 WRITER_STATE_STARTELEMENT
,
65 WRITER_STATE_STARTATTRIBUTE
,
66 WRITER_STATE_STARTCDATA
,
67 WRITER_STATE_ENDSTARTELEMENT
,
70 WRITER_STATE_ENDELEMENT
,
79 unsigned char *write_bufptr
;
80 enum writer_state state
;
83 WS_XML_STRING
*current_ns
;
84 WS_XML_WRITER_ENCODING_TYPE output_enc
;
85 WS_CHARSET output_charset
;
86 WS_XML_WRITER_OUTPUT_TYPE output_type
;
87 WS_WRITE_CALLBACK output_cb
;
88 void *output_cb_state
;
89 struct xmlbuf
*output_buf
;
92 unsigned char *stream_buf
;
93 const WS_XML_DICTIONARY
*dict
;
95 WS_DYNAMIC_STRING_CALLBACK dict_cb
;
98 struct prop prop
[ARRAY_SIZE( writer_props
)];
101 #define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T')
103 static struct writer
*alloc_writer(void)
105 static const ULONG count
= ARRAY_SIZE( writer_props
);
107 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
109 if (!(ret
= calloc( 1, size
))) return NULL
;
111 ret
->magic
= WRITER_MAGIC
;
112 InitializeCriticalSection( &ret
->cs
);
113 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": writer.cs");
115 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
116 ret
->prop_count
= count
;
120 static void free_writer( struct writer
*writer
)
122 destroy_nodes( writer
->root
);
123 free_xml_string( writer
->current_ns
);
124 WsFreeHeap( writer
->output_heap
);
125 free( writer
->stream_buf
);
127 writer
->cs
.DebugInfo
->Spare
[0] = 0;
128 DeleteCriticalSection( &writer
->cs
);
132 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
134 if (!writer
->root
) writer
->root
= eof
;
137 eof
->parent
= writer
->root
;
138 list_add_tail( &writer
->root
->children
, &eof
->entry
);
140 writer
->current
= eof
;
143 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
145 writer
->root
->parent
= bof
;
146 list_add_tail( &bof
->children
, &writer
->root
->entry
);
147 writer
->current
= writer
->root
= bof
;
150 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
152 node
->parent
= parent
;
153 list_add_before( list_tail( &parent
->children
), &node
->entry
);
154 writer
->current
= node
;
157 static struct node
*find_parent( struct writer
*writer
)
159 if (is_valid_parent( writer
->current
)) return writer
->current
;
160 if (is_valid_parent( writer
->current
->parent
)) return writer
->current
->parent
;
164 static HRESULT
init_writer( struct writer
*writer
)
168 writer
->write_pos
= 0;
169 writer
->write_bufptr
= NULL
;
170 destroy_nodes( writer
->root
);
171 writer
->root
= writer
->current
= NULL
;
172 free_xml_string( writer
->current_ns
);
173 writer
->current_ns
= NULL
;
175 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
176 write_insert_eof( writer
, node
);
177 writer
->state
= WRITER_STATE_INITIAL
;
178 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
179 writer
->output_charset
= WS_CHARSET_UTF8
;
181 writer
->dict_do_lookup
= FALSE
;
182 writer
->dict_cb
= NULL
;
183 writer
->dict_cb_state
= NULL
;
187 /**************************************************************************
188 * WsCreateWriter [webservices.@]
190 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
191 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
193 struct writer
*writer
;
194 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
195 WS_CHARSET charset
= WS_CHARSET_UTF8
;
198 TRACE( "%p %lu %p %p\n", properties
, count
, handle
, error
);
199 if (error
) FIXME( "ignoring error parameter\n" );
201 if (!handle
) return E_INVALIDARG
;
202 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
204 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
205 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
206 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
207 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
208 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
209 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
210 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
212 for (i
= 0; i
< count
; i
++)
214 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
215 properties
[i
].valueSize
);
218 free_writer( writer
);
223 hr
= WsCreateHeap( 1 << 20, 0, NULL
, 0, &writer
->output_heap
, NULL
);
226 free_writer( writer
);
230 hr
= init_writer( writer
);
233 free_writer( writer
);
237 TRACE( "created %p\n", writer
);
238 *handle
= (WS_XML_WRITER
*)writer
;
242 /**************************************************************************
243 * WsFreeWriter [webservices.@]
245 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
247 struct writer
*writer
= (struct writer
*)handle
;
249 TRACE( "%p\n", handle
);
253 EnterCriticalSection( &writer
->cs
);
255 if (writer
->magic
!= WRITER_MAGIC
)
257 LeaveCriticalSection( &writer
->cs
);
263 LeaveCriticalSection( &writer
->cs
);
264 free_writer( writer
);
267 /**************************************************************************
268 * WsGetWriterProperty [webservices.@]
270 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
271 void *buf
, ULONG size
, WS_ERROR
*error
)
273 struct writer
*writer
= (struct writer
*)handle
;
276 TRACE( "%p %u %p %lu %p\n", handle
, id
, buf
, size
, error
);
277 if (error
) FIXME( "ignoring error parameter\n" );
279 if (!writer
) return E_INVALIDARG
;
281 EnterCriticalSection( &writer
->cs
);
283 if (writer
->magic
!= WRITER_MAGIC
)
285 LeaveCriticalSection( &writer
->cs
);
289 if (writer
->output_type
!= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
) hr
= WS_E_INVALID_OPERATION
;
294 case WS_XML_WRITER_PROPERTY_BYTES
:
296 WS_BYTES
*bytes
= buf
;
297 if (size
!= sizeof(*bytes
)) hr
= E_INVALIDARG
;
300 bytes
->bytes
= writer
->output_buf
->bytes
.bytes
;
301 bytes
->length
= writer
->output_buf
->bytes
.length
;
305 case WS_XML_WRITER_PROPERTY_BUFFERS
:
306 if (writer
->output_buf
->bytes
.length
)
308 WS_BUFFERS
*buffers
= buf
;
309 if (size
!= sizeof(*buffers
)) hr
= E_INVALIDARG
;
312 buffers
->bufferCount
= 1;
313 buffers
->buffers
= &writer
->output_buf
->bytes
;
319 hr
= prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
323 LeaveCriticalSection( &writer
->cs
);
324 TRACE( "returning %#lx\n", hr
);
328 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
330 /* free current buffer if it's ours */
331 if (writer
->output_buf
&& !writer
->output_buf_user
)
333 free_xmlbuf( writer
->output_buf
);
335 writer
->output_buf
= xmlbuf
;
336 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
337 writer
->write_bufptr
= xmlbuf
->bytes
.bytes
;
338 writer
->write_pos
= 0;
341 static void set_output_stream( struct writer
*writer
, WS_WRITE_CALLBACK callback
, void *state
)
343 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_STREAM
;
344 writer
->output_cb
= callback
;
345 writer
->output_cb_state
= state
;
346 writer
->write_bufptr
= writer
->stream_buf
;
347 writer
->write_pos
= 0;
350 /**************************************************************************
351 * WsSetOutput [webservices.@]
353 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
354 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
355 ULONG count
, WS_ERROR
*error
)
357 struct writer
*writer
= (struct writer
*)handle
;
362 TRACE( "%p %p %p %p %lu %p\n", handle
, encoding
, output
, properties
, count
, error
);
363 if (error
) FIXME( "ignoring error parameter\n" );
365 if (!writer
) return E_INVALIDARG
;
367 EnterCriticalSection( &writer
->cs
);
369 if (writer
->magic
!= WRITER_MAGIC
)
371 LeaveCriticalSection( &writer
->cs
);
375 for (i
= 0; i
< count
; i
++)
377 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
378 properties
[i
].valueSize
);
379 if (hr
!= S_OK
) goto done
;
382 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
384 switch (encoding
->encodingType
)
386 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
388 const WS_XML_WRITER_TEXT_ENCODING
*text
= (const WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
389 if (text
->charSet
!= WS_CHARSET_UTF8
)
391 FIXME( "charset %u not supported\n", text
->charSet
);
395 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
396 writer
->output_charset
= WS_CHARSET_UTF8
;
399 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
401 const WS_XML_WRITER_BINARY_ENCODING
*bin
= (const WS_XML_WRITER_BINARY_ENCODING
*)encoding
;
402 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_BINARY
;
403 writer
->output_charset
= 0;
404 writer
->dict
= bin
->staticDictionary
;
405 writer
->dict_cb
= bin
->dynamicStringCallback
;
406 writer
->dict_cb_state
= bin
->dynamicStringCallbackState
;
410 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
415 switch (output
->outputType
)
417 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
419 struct xmlbuf
*xmlbuf
;
420 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
, 0, writer
->output_enc
, writer
->output_charset
,
421 writer
->dict
, NULL
)))
423 hr
= WS_E_QUOTA_EXCEEDED
;
426 set_output_buffer( writer
, xmlbuf
);
427 writer
->output_buf_user
= FALSE
;
430 case WS_XML_WRITER_OUTPUT_TYPE_STREAM
:
432 const WS_XML_WRITER_STREAM_OUTPUT
*stream
= (const WS_XML_WRITER_STREAM_OUTPUT
*)output
;
433 if (!writer
->stream_buf
&& !(writer
->stream_buf
= malloc( STREAM_BUFSIZE
)))
438 set_output_stream( writer
, stream
->writeCallback
, stream
->writeCallbackState
);
443 FIXME( "output type %u not supported\n", output
->outputType
);
448 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
449 else write_insert_bof( writer
, node
);
452 LeaveCriticalSection( &writer
->cs
);
453 TRACE( "returning %#lx\n", hr
);
457 /**************************************************************************
458 * WsSetOutputToBuffer [webservices.@]
460 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
461 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
464 struct writer
*writer
= (struct writer
*)handle
;
465 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
470 TRACE( "%p %p %p %lu %p\n", handle
, buffer
, properties
, count
, error
);
471 if (error
) FIXME( "ignoring error parameter\n" );
473 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
475 EnterCriticalSection( &writer
->cs
);
477 if (writer
->magic
!= WRITER_MAGIC
)
479 LeaveCriticalSection( &writer
->cs
);
483 for (i
= 0; i
< count
; i
++)
485 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
486 properties
[i
].valueSize
);
487 if (hr
!= S_OK
) goto done
;
490 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
491 writer
->output_enc
= xmlbuf
->encoding
;
492 writer
->output_charset
= xmlbuf
->charset
;
493 set_output_buffer( writer
, xmlbuf
);
494 writer
->output_buf_user
= TRUE
;
496 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
497 else write_insert_bof( writer
, node
);
500 LeaveCriticalSection( &writer
->cs
);
501 TRACE( "returning %#lx\n", hr
);
505 static HRESULT
flush_writer( struct writer
*writer
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
510 if (writer
->write_pos
< min_size
) return S_OK
;
512 buf
.bytes
= writer
->write_bufptr
;
513 buf
.length
= writer
->write_pos
;
514 writer
->output_cb( writer
->output_cb_state
, &buf
, 1, ctx
, error
);
515 writer
->write_pos
= 0;
519 /**************************************************************************
520 * WsFlushWriter [webservices.@]
522 HRESULT WINAPI
WsFlushWriter( WS_XML_WRITER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
525 struct writer
*writer
= (struct writer
*)handle
;
528 TRACE( "%p %lu %p %p\n", handle
, min_size
, ctx
, error
);
529 if (error
) FIXME( "ignoring error parameter\n" );
530 if (ctx
) FIXME( "ignoring ctx parameter\n" );
532 if (!writer
) return E_INVALIDARG
;
534 EnterCriticalSection( &writer
->cs
);
536 if (writer
->magic
!= WRITER_MAGIC
)
538 LeaveCriticalSection( &writer
->cs
);
542 if (writer
->output_type
!= WS_XML_WRITER_OUTPUT_TYPE_STREAM
) hr
= WS_E_INVALID_OPERATION
;
543 else hr
= flush_writer( writer
, min_size
, ctx
, error
);
545 LeaveCriticalSection( &writer
->cs
);
546 TRACE( "returning %#lx\n", hr
);
550 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
552 struct xmlbuf
*buf
= writer
->output_buf
;
556 if (writer
->output_type
== WS_XML_WRITER_OUTPUT_TYPE_STREAM
)
558 if (size
> STREAM_BUFSIZE
) return WS_E_QUOTA_EXCEEDED
;
559 return flush_writer( writer
, STREAM_BUFSIZE
- size
, NULL
, NULL
);
562 if (buf
->size
>= writer
->write_pos
+ size
)
564 buf
->bytes
.length
= writer
->write_pos
+ size
;
567 new_size
= max( buf
->size
* 2, writer
->write_pos
+ size
);
568 if (!(tmp
= ws_realloc( buf
->heap
, buf
->bytes
.bytes
, buf
->size
, new_size
))) return WS_E_QUOTA_EXCEEDED
;
569 writer
->write_bufptr
= buf
->bytes
.bytes
= tmp
;
570 buf
->size
= new_size
;
571 buf
->bytes
.length
= writer
->write_pos
+ size
;
575 static inline void write_char( struct writer
*writer
, unsigned char ch
)
577 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
580 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
582 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
583 writer
->write_pos
+= len
;
592 static const struct escape escape_lt
= { '<', "<", 4 };
593 static const struct escape escape_gt
= { '>', ">", 4 };
594 static const struct escape escape_amp
= { '&', "&", 5 };
595 static const struct escape escape_apos
= { '\'', "'", 6 };
596 static const struct escape escape_quot
= { '"', """, 6 };
598 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
599 const struct escape
**escapes
, ULONG nb_escapes
)
605 for (i
= 0; i
< len
; i
++)
609 for (j
= 0; j
< nb_escapes
; j
++)
611 if (bytes
[i
] == escapes
[j
]->ch
)
613 ptr
= (const BYTE
*)escapes
[j
]->entity
;
614 size
= escapes
[j
]->len
;
618 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
619 write_bytes( writer
, ptr
, size
);
625 static HRESULT
write_attribute_value_text( struct writer
*writer
, const WS_XML_TEXT
*text
, BOOL single
)
627 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
;
628 const struct escape
*escapes
[3];
630 escapes
[0] = single
? &escape_apos
: &escape_quot
;
631 escapes
[1] = &escape_lt
;
632 escapes
[2] = &escape_amp
;
633 return write_bytes_escape( writer
, utf8
->value
.bytes
, utf8
->value
.length
, escapes
, 3 );
636 static HRESULT
write_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
638 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
639 const WS_XML_STRING
*prefix
= NULL
;
643 if (attr
->prefix
) prefix
= attr
->prefix
;
645 /* ' prefix:attr="value"' */
647 size
= attr
->localName
->length
+ 4 /* ' =""' */;
648 if (prefix
&& prefix
->length
) size
+= prefix
->length
+ 1 /* ':' */;
649 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
651 write_char( writer
, ' ' );
652 if (prefix
&& prefix
->length
)
654 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
655 write_char( writer
, ':' );
657 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
658 write_char( writer
, '=' );
659 write_char( writer
, quote
);
660 if (attr
->value
) hr
= write_attribute_value_text( writer
, attr
->value
, attr
->singleQuote
);
661 write_char( writer
, quote
);
666 static HRESULT
write_int31( struct writer
*writer
, ULONG len
)
670 if (len
> 0x7fffffff) return E_INVALIDARG
;
672 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
675 write_char( writer
, len
);
678 write_char( writer
, (len
& 0x7f) | 0x80 );
680 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
681 if ((len
>>= 7) < 0x80)
683 write_char( writer
, len
);
686 write_char( writer
, (len
& 0x7f) | 0x80 );
688 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
689 if ((len
>>= 7) < 0x80)
691 write_char( writer
, len
);
694 write_char( writer
, (len
& 0x7f) | 0x80 );
696 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
697 if ((len
>>= 7) < 0x80)
699 write_char( writer
, len
);
702 write_char( writer
, (len
& 0x7f) | 0x80 );
704 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
705 if ((len
>>= 7) < 0x08)
707 write_char( writer
, len
);
710 return WS_E_INVALID_FORMAT
;
713 static HRESULT
write_string( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
716 if ((hr
= write_int31( writer
, len
)) != S_OK
) return hr
;
717 if ((hr
= write_grow_buffer( writer
, len
)) != S_OK
) return hr
;
718 write_bytes( writer
, bytes
, len
);
722 static HRESULT
write_dict_string( struct writer
*writer
, ULONG id
)
724 if (id
> 0x7fffffff) return E_INVALIDARG
;
725 return write_int31( writer
, id
);
728 static enum record_type
get_attr_text_record_type( const WS_XML_TEXT
*text
, BOOL use_dict
)
730 if (!text
) return RECORD_CHARS8_TEXT
;
731 switch (text
->textType
)
733 case WS_XML_TEXT_TYPE_UTF8
:
735 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
736 if (use_dict
) return RECORD_DICTIONARY_TEXT
;
737 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT
;
738 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT
;
739 return RECORD_CHARS32_TEXT
;
741 case WS_XML_TEXT_TYPE_UTF16
:
743 const WS_XML_UTF16_TEXT
*text_utf16
= (const WS_XML_UTF16_TEXT
*)text
;
744 int len
= text_utf16
->byteCount
/ sizeof(WCHAR
);
745 int len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)text_utf16
->bytes
, len
, NULL
, 0, NULL
, NULL
);
746 if (len_utf8
<= MAX_UINT8
) return RECORD_CHARS8_TEXT
;
747 if (len_utf8
<= MAX_UINT16
) return RECORD_CHARS16_TEXT
;
748 return RECORD_CHARS32_TEXT
;
750 case WS_XML_TEXT_TYPE_BASE64
:
752 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
753 if (text_base64
->length
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
754 if (text_base64
->length
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
755 return RECORD_BYTES32_TEXT
;
757 case WS_XML_TEXT_TYPE_BOOL
:
759 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
760 return text_bool
->value
? RECORD_TRUE_TEXT
: RECORD_FALSE_TEXT
;
762 case WS_XML_TEXT_TYPE_INT32
:
764 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
765 if (!text_int32
->value
) return RECORD_ZERO_TEXT
;
766 if (text_int32
->value
== 1) return RECORD_ONE_TEXT
;
767 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
768 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
769 return RECORD_INT32_TEXT
;
771 case WS_XML_TEXT_TYPE_INT64
:
773 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
774 if (!text_int64
->value
) return RECORD_ZERO_TEXT
;
775 if (text_int64
->value
== 1) return RECORD_ONE_TEXT
;
776 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
777 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
778 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
779 return RECORD_INT64_TEXT
;
781 case WS_XML_TEXT_TYPE_UINT64
:
783 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
784 if (!text_uint64
->value
) return RECORD_ZERO_TEXT
;
785 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT
;
786 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
787 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
788 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
789 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT
;
790 return RECORD_UINT64_TEXT
;
792 case WS_XML_TEXT_TYPE_DOUBLE
:
794 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
795 if (!text_double
->value
) return RECORD_ZERO_TEXT
;
796 if (text_double
->value
== 1) return RECORD_ONE_TEXT
;
797 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
798 return RECORD_DOUBLE_TEXT
;
799 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
800 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
801 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
802 return RECORD_INT64_TEXT
;
804 case WS_XML_TEXT_TYPE_GUID
:
805 return RECORD_GUID_TEXT
;
807 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
808 return RECORD_UNIQUE_ID_TEXT
;
810 case WS_XML_TEXT_TYPE_DATETIME
:
811 return RECORD_DATETIME_TEXT
;
814 FIXME( "unhandled text type %u\n", text
->textType
);
819 static INT64
get_text_value_int( const WS_XML_TEXT
*text
)
821 switch (text
->textType
)
823 case WS_XML_TEXT_TYPE_INT32
:
825 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
826 return text_int32
->value
;
828 case WS_XML_TEXT_TYPE_INT64
:
830 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
831 return text_int64
->value
;
833 case WS_XML_TEXT_TYPE_UINT64
:
835 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
836 return text_uint64
->value
;
838 case WS_XML_TEXT_TYPE_DOUBLE
:
840 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
841 return text_double
->value
;
844 ERR( "unhandled text type %u\n", text
->textType
);
850 static BOOL
get_string_id( struct writer
*writer
, const WS_XML_STRING
*str
, ULONG
*id
)
852 if (writer
->dict
&& str
->dictionary
== writer
->dict
)
860 writer
->dict_cb( writer
->dict_cb_state
, str
, &found
, id
, NULL
);
861 if (found
) *id
= (*id
<< 1) | 1;
867 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
869 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
872 memcpy( buf
, bool_true
, sizeof(bool_true
) );
873 return sizeof(bool_true
);
875 memcpy( buf
, bool_false
, sizeof(bool_false
) );
876 return sizeof(bool_false
);
879 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
881 return wsprintfA( (char *)buf
, "%d", *ptr
);
884 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
886 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
889 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
891 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
894 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
896 static const double precision
= 0.0000000000000001;
897 unsigned char *p
= buf
;
899 int neg
, mag
, mag2
= 0, use_exp
;
903 memcpy( buf
, "NaN", 3 );
910 memcpy( buf
, "-INF", 4 );
913 memcpy( buf
, "INF", 3 );
929 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
932 if (mag
< 0) mag
-= 1;
933 val
= val
/ pow( 10.0, mag
);
937 else if (mag
< 1) mag
= 0;
939 while (val
> precision
|| mag
>= 0)
941 double weight
= pow( 10.0, mag
);
942 if (weight
> 0 && !isinf( weight
))
944 int digit
= floor( val
/ weight
);
945 val
-= digit
* weight
;
946 *(p
++) = '0' + digit
;
948 if (!mag
&& val
> precision
) *(p
++) = '.';
956 if (mag2
> 0) *(p
++) = '+';
965 *(p
++) = '0' + mag2
% 10;
969 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
980 static inline int year_size( int year
)
982 return leap_year( year
) ? 366 : 365;
986 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
988 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
989 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
990 unsigned __int64 ticks
, day_ticks
;
993 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
994 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
996 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1004 day
= ticks
/ TICKS_PER_DAY
;
1005 day_ticks
= ticks
% TICKS_PER_DAY
;
1006 hour
= day_ticks
/ TICKS_PER_HOUR
;
1007 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1008 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1009 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1011 while (day
>= year_size( year
))
1013 day
-= year_size( year
);
1016 while (day
>= month_days
[leap_year( year
)][month
])
1018 day
-= month_days
[leap_year( year
)][month
];
1022 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
1025 static const char fmt_frac
[] = ".%07u";
1026 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
1027 while (buf
[len
- 1] == '0') len
--;
1029 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
1033 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
1035 static const char fmt_tz
[] = "%c%02u:00";
1036 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
1042 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1044 static const char fmt
[] = "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1045 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1046 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1047 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1050 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
1052 static const char fmt
[] = "urn:uuid:%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1053 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1054 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1055 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1058 static ULONG
format_qname( const WS_XML_STRING
*prefix
, const WS_XML_STRING
*localname
, unsigned char *buf
)
1061 if (prefix
&& prefix
->length
)
1063 memcpy( buf
, prefix
->bytes
, prefix
->length
);
1064 len
+= prefix
->length
;
1067 memcpy( buf
+ len
, localname
->bytes
, localname
->length
);
1068 return len
+ localname
->length
;
1071 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
1073 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1078 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
1079 x
= (bin
[0] & 3) << 4;
1082 buf
[i
++] = base64
[x
];
1087 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
1088 x
= (bin
[1] & 0x0f) << 2;
1091 buf
[i
++] = base64
[x
];
1095 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
1096 buf
[i
++] = base64
[bin
[2] & 0x3f];
1103 HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, ULONG
*offset
,
1104 WS_XML_UTF8_TEXT
**ret
)
1106 ULONG len_old
= old
? old
->value
.length
: 0;
1107 if (offset
) *offset
= len_old
;
1109 switch (text
->textType
)
1111 case WS_XML_TEXT_TYPE_UTF8
:
1113 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1115 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
1116 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1117 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
1120 case WS_XML_TEXT_TYPE_UTF16
:
1122 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1123 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1124 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1126 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1127 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1128 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
1129 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1130 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
1133 case WS_XML_TEXT_TYPE_BASE64
:
1135 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
1136 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
1138 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1139 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1140 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1143 case WS_XML_TEXT_TYPE_BOOL
:
1145 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1147 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
1148 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1149 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1152 case WS_XML_TEXT_TYPE_INT32
:
1154 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1155 unsigned char buf
[12]; /* "-2147483648" */
1156 ULONG len
= format_int32( &int32_text
->value
, buf
);
1158 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1159 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1160 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1163 case WS_XML_TEXT_TYPE_INT64
:
1165 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1166 unsigned char buf
[21]; /* "-9223372036854775808" */
1167 ULONG len
= format_int64( &int64_text
->value
, buf
);
1169 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1170 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1171 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1174 case WS_XML_TEXT_TYPE_UINT64
:
1176 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1177 unsigned char buf
[21]; /* "18446744073709551615" */
1178 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1180 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1181 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1182 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1185 case WS_XML_TEXT_TYPE_DOUBLE
:
1187 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1188 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
1189 unsigned int fpword
= _control87( 0, 0 );
1192 _control87( _MCW_EM
| _RC_NEAR
| _PC_64
, _MCW_EM
| _MCW_RC
| _MCW_PC
);
1193 len
= format_double( &double_text
->value
, buf
);
1194 _control87( fpword
, _MCW_EM
| _MCW_RC
| _MCW_PC
);
1195 if (!len
) return E_NOTIMPL
;
1197 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1198 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1199 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1202 case WS_XML_TEXT_TYPE_GUID
:
1204 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1206 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
1207 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1208 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1211 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1213 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1215 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
1216 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1217 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1220 case WS_XML_TEXT_TYPE_DATETIME
:
1222 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
1224 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
1225 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1226 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1229 case WS_XML_TEXT_TYPE_QNAME
:
1231 const WS_XML_QNAME_TEXT
*qn
= (const WS_XML_QNAME_TEXT
*)text
;
1232 ULONG len
= qn
->localName
->length
;
1234 if (qn
->prefix
&& qn
->prefix
->length
) len
+= qn
->prefix
->length
+ 1;
1235 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1236 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1237 (*ret
)->value
.length
= format_qname( qn
->prefix
, qn
->localName
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1241 FIXME( "unhandled text type %u\n", text
->textType
);
1246 static HRESULT
write_attribute_value_bin( struct writer
*writer
, const WS_XML_TEXT
*text
)
1248 enum record_type type
;
1249 BOOL use_dict
= FALSE
;
1253 if (text
&& text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
1255 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1256 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
1258 type
= get_attr_text_record_type( text
, use_dict
);
1260 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1261 write_char( writer
, type
);
1265 case RECORD_CHARS8_TEXT
:
1267 const WS_XML_UTF8_TEXT
*text_utf8
;
1268 WS_XML_UTF8_TEXT
*new = NULL
;
1273 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1274 write_char( writer
, 0 );
1277 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1280 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
1283 len
= text_utf8
->value
.length
;
1284 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
)
1289 write_char( writer
, len
);
1290 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
1294 case RECORD_CHARS16_TEXT
:
1296 const WS_XML_UTF8_TEXT
*text_utf8
;
1297 WS_XML_UTF8_TEXT
*new = NULL
;
1300 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1303 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
1306 len
= text_utf8
->value
.length
;
1307 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
)
1312 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
1313 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
1317 case RECORD_BYTES8_TEXT
:
1319 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
1320 if ((hr
= write_grow_buffer( writer
, 1 + text_base64
->length
)) != S_OK
) return hr
;
1321 write_char( writer
, text_base64
->length
);
1322 write_bytes( writer
, text_base64
->bytes
, text_base64
->length
);
1325 case RECORD_BYTES16_TEXT
:
1327 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
1328 UINT16 len
= text_base64
->length
;
1329 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
1330 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
1331 write_bytes( writer
, text_base64
->bytes
, len
);
1334 case RECORD_ZERO_TEXT
:
1335 case RECORD_ONE_TEXT
:
1336 case RECORD_FALSE_TEXT
:
1337 case RECORD_TRUE_TEXT
:
1340 case RECORD_INT8_TEXT
:
1342 INT8 val
= get_text_value_int( text
);
1343 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1344 write_char( writer
, val
);
1347 case RECORD_INT16_TEXT
:
1349 INT16 val
= get_text_value_int( text
);
1350 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1351 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1354 case RECORD_INT32_TEXT
:
1356 INT32 val
= get_text_value_int( text
);
1357 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1358 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1361 case RECORD_INT64_TEXT
:
1363 INT64 val
= get_text_value_int( text
);
1364 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1365 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1368 case RECORD_UINT64_TEXT
:
1370 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
1371 if ((hr
= write_grow_buffer( writer
, sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
1372 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
1375 case RECORD_DOUBLE_TEXT
:
1377 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
1378 if ((hr
= write_grow_buffer( writer
, sizeof(text_double
->value
) )) != S_OK
) return hr
;
1379 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
1382 case RECORD_GUID_TEXT
:
1384 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
1385 if ((hr
= write_grow_buffer( writer
, sizeof(text_guid
->value
) )) != S_OK
) return hr
;
1386 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
1389 case RECORD_UNIQUE_ID_TEXT
:
1391 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
1392 if ((hr
= write_grow_buffer( writer
, sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
1393 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
1396 case RECORD_DATETIME_TEXT
:
1398 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
1399 UINT64 val
= text_datetime
->value
.ticks
;
1401 assert( val
<= TICKS_MAX
);
1402 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
1403 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
1405 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1406 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1410 FIXME( "unhandled record type %02x\n", type
);
1415 static enum record_type
get_attr_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1417 if (!attr
->prefix
|| !attr
->prefix
->length
)
1419 if (use_dict
) return RECORD_SHORT_DICTIONARY_ATTRIBUTE
;
1420 return RECORD_SHORT_ATTRIBUTE
;
1422 if (attr
->prefix
->length
== 1 && attr
->prefix
->bytes
[0] >= 'a' && attr
->prefix
->bytes
[0] <= 'z')
1424 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
1425 return RECORD_PREFIX_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
1427 if (use_dict
) return RECORD_DICTIONARY_ATTRIBUTE
;
1428 return RECORD_ATTRIBUTE
;
1431 static HRESULT
write_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1434 enum record_type type
= get_attr_record_type( attr
, get_string_id(writer
, attr
->localName
, &id
) );
1437 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1438 write_char( writer
, type
);
1440 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1442 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1443 return write_attribute_value_bin( writer
, attr
->value
);
1445 if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1447 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1448 return write_attribute_value_bin( writer
, attr
->value
);
1453 case RECORD_SHORT_ATTRIBUTE
:
1454 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1457 case RECORD_ATTRIBUTE
:
1458 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1459 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1462 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1463 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1466 case RECORD_DICTIONARY_ATTRIBUTE
:
1467 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1468 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1472 ERR( "unhandled record type %02x\n", type
);
1473 return WS_E_NOT_SUPPORTED
;
1476 return write_attribute_value_bin( writer
, attr
->value
);
1479 static HRESULT
write_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1481 switch (writer
->output_enc
)
1483 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_attribute_text( writer
, attr
);
1484 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_attribute_bin( writer
, attr
);
1486 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1487 return WS_E_NOT_SUPPORTED
;
1491 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1493 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
1496 /**************************************************************************
1497 * WsGetPrefixFromNamespace [webservices.@]
1499 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
1500 BOOL required
, const WS_XML_STRING
**prefix
,
1503 struct writer
*writer
= (struct writer
*)handle
;
1504 WS_XML_ELEMENT_NODE
*elem
;
1508 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
1509 if (error
) FIXME( "ignoring error parameter\n" );
1511 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
1513 EnterCriticalSection( &writer
->cs
);
1515 if (writer
->magic
!= WRITER_MAGIC
)
1517 LeaveCriticalSection( &writer
->cs
);
1518 return E_INVALIDARG
;
1521 elem
= &writer
->current
->hdr
;
1522 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
1524 *prefix
= elem
->prefix
;
1530 if (required
) hr
= WS_E_INVALID_FORMAT
;
1538 LeaveCriticalSection( &writer
->cs
);
1539 TRACE( "returning %#lx\n", hr
);
1543 static HRESULT
write_namespace_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1545 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
1549 /* ' xmlns:prefix="namespace"' */
1551 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
1552 if (attr
->prefix
&& attr
->prefix
->length
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
1553 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1555 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
1556 if (attr
->prefix
&& attr
->prefix
->length
)
1558 write_char( writer
, ':' );
1559 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
1561 write_char( writer
, '=' );
1562 write_char( writer
, quote
);
1563 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1564 write_char( writer
, quote
);
1569 static enum record_type
get_xmlns_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1571 if (!attr
->prefix
|| !attr
->prefix
->length
)
1573 if (use_dict
) return RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
;
1574 return RECORD_SHORT_XMLNS_ATTRIBUTE
;
1576 if (use_dict
) return RECORD_DICTIONARY_XMLNS_ATTRIBUTE
;
1577 return RECORD_XMLNS_ATTRIBUTE
;
1580 static HRESULT
write_namespace_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1583 enum record_type type
= get_xmlns_record_type( attr
, get_string_id(writer
, attr
->ns
, &id
) );
1586 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1587 write_char( writer
, type
);
1591 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1594 case RECORD_XMLNS_ATTRIBUTE
:
1595 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1598 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1599 return write_dict_string( writer
, id
);
1601 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1602 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1603 return write_dict_string( writer
, id
);
1606 ERR( "unhandled record type %02x\n", type
);
1607 return WS_E_NOT_SUPPORTED
;
1610 return write_string( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1613 static HRESULT
write_namespace_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1615 switch (writer
->output_enc
)
1617 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_namespace_attribute_text( writer
, attr
);
1618 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_namespace_attribute_bin( writer
, attr
);
1620 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1621 return WS_E_NOT_SUPPORTED
;
1625 static HRESULT
add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1626 const WS_XML_STRING
*ns
, BOOL single
)
1628 WS_XML_ATTRIBUTE
*attr
;
1629 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1632 if (!(attr
= calloc( 1, sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1634 attr
->singleQuote
= !!single
;
1636 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
1638 free_attribute( attr
);
1639 return E_OUTOFMEMORY
;
1641 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
1643 free_attribute( attr
);
1644 return E_OUTOFMEMORY
;
1646 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1648 free_attribute( attr
);
1654 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
1656 if (!str1
&& !str2
) return TRUE
;
1657 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
1660 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
1661 const WS_XML_STRING
*ns
)
1664 const struct node
*node
;
1666 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
1668 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
1671 for (i
= 0; i
< elem
->attributeCount
; i
++)
1673 if (!elem
->attributes
[i
]->isXmlNs
) continue;
1674 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
1675 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
1681 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1684 if (!(str
= dup_xml_string( ns
, writer
->dict_do_lookup
))) return E_OUTOFMEMORY
;
1685 free_xml_string( writer
->current_ns
);
1686 writer
->current_ns
= str
;
1690 static HRESULT
set_namespaces( struct writer
*writer
)
1692 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1696 if (elem
->ns
->length
&& !namespace_in_scope( elem
, elem
->prefix
, elem
->ns
))
1698 if ((hr
= add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
) return hr
;
1699 if ((hr
= set_current_namespace( writer
, elem
->ns
)) != S_OK
) return hr
;
1702 for (i
= 0; i
< elem
->attributeCount
; i
++)
1704 const WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1705 if (!attr
->ns
->length
|| namespace_in_scope( elem
, attr
->prefix
, attr
->ns
)) continue;
1706 if ((hr
= add_namespace_attribute( writer
, attr
->prefix
, attr
->ns
, FALSE
)) != S_OK
) return hr
;
1712 /**************************************************************************
1713 * WsWriteEndAttribute [webservices.@]
1715 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1717 struct writer
*writer
= (struct writer
*)handle
;
1720 TRACE( "%p %p\n", handle
, error
);
1721 if (error
) FIXME( "ignoring error parameter\n" );
1723 if (!writer
) return E_INVALIDARG
;
1725 EnterCriticalSection( &writer
->cs
);
1727 if (writer
->magic
!= WRITER_MAGIC
)
1729 LeaveCriticalSection( &writer
->cs
);
1730 return E_INVALIDARG
;
1733 writer
->state
= WRITER_STATE_STARTELEMENT
;
1735 LeaveCriticalSection( &writer
->cs
);
1736 TRACE( "returning %#lx\n", hr
);
1740 static HRESULT
write_attributes( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1744 for (i
= 0; i
< elem
->attributeCount
; i
++)
1746 if (elem
->attributes
[i
]->isXmlNs
) continue;
1747 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1749 for (i
= 0; i
< elem
->attributeCount
; i
++)
1751 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
1752 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1754 for (i
= 0; i
< elem
->attributeCount
; i
++)
1756 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
1757 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1762 static HRESULT
write_startelement_text( struct writer
*writer
)
1764 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1768 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
1770 size
= elem
->localName
->length
+ 1 /* '<' */;
1771 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1772 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1774 write_char( writer
, '<' );
1775 if (elem
->prefix
&& elem
->prefix
->length
)
1777 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1778 write_char( writer
, ':' );
1780 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1781 return write_attributes( writer
, elem
);
1784 static enum record_type
get_elem_record_type( const WS_XML_ELEMENT_NODE
*elem
, BOOL use_dict
)
1786 if (!elem
->prefix
|| !elem
->prefix
->length
)
1788 if (use_dict
) return RECORD_SHORT_DICTIONARY_ELEMENT
;
1789 return RECORD_SHORT_ELEMENT
;
1791 if (elem
->prefix
->length
== 1 && elem
->prefix
->bytes
[0] >= 'a' && elem
->prefix
->bytes
[0] <= 'z')
1793 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1794 return RECORD_PREFIX_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1796 if (use_dict
) return RECORD_DICTIONARY_ELEMENT
;
1797 return RECORD_ELEMENT
;
1800 static HRESULT
write_startelement_bin( struct writer
*writer
)
1802 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1804 enum record_type type
= get_elem_record_type( elem
, get_string_id(writer
, elem
->localName
, &id
) );
1807 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1808 write_char( writer
, type
);
1810 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1812 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1813 return write_attributes( writer
, elem
);
1815 if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1817 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1818 return write_attributes( writer
, elem
);
1823 case RECORD_SHORT_ELEMENT
:
1824 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1827 case RECORD_ELEMENT
:
1828 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1829 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1832 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1833 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1836 case RECORD_DICTIONARY_ELEMENT
:
1837 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1838 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1842 ERR( "unhandled record type %02x\n", type
);
1843 return WS_E_NOT_SUPPORTED
;
1846 return write_attributes( writer
, elem
);
1849 static HRESULT
write_startelement( struct writer
*writer
)
1851 switch (writer
->output_enc
)
1853 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_startelement_text( writer
);
1854 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_startelement_bin( writer
);
1856 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1857 return WS_E_NOT_SUPPORTED
;
1861 static struct node
*write_find_startelement( struct writer
*writer
)
1864 for (node
= writer
->current
; node
; node
= node
->parent
)
1866 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
1871 static inline BOOL
is_empty_element( const struct node
*node
)
1873 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
1874 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
1877 static HRESULT
write_endelement_text( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1884 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
1886 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1887 write_char( writer
, '/' );
1888 write_char( writer
, '>' );
1892 /* '</prefix:localname>' */
1894 size
= elem
->localName
->length
+ 3 /* '</>' */;
1895 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1896 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1898 write_char( writer
, '<' );
1899 write_char( writer
, '/' );
1900 if (elem
->prefix
&& elem
->prefix
->length
)
1902 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1903 write_char( writer
, ':' );
1905 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1906 write_char( writer
, '>' );
1910 static HRESULT
write_endelement_bin( struct writer
*writer
)
1913 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_TEXT
) return S_OK
;
1914 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1915 write_char( writer
, RECORD_ENDELEMENT
);
1919 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1921 switch (writer
->output_enc
)
1923 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endelement_text( writer
, elem
);
1924 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_endelement_bin( writer
);
1926 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1927 return WS_E_NOT_SUPPORTED
;
1931 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
1933 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
1934 elem
->isEmpty
= is_empty_element( node
);
1935 return write_endelement( writer
, elem
);
1938 static HRESULT
write_endelement_node( struct writer
*writer
)
1943 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
1944 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1946 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1947 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1949 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
1950 writer
->current
= node
->parent
;
1951 writer
->state
= WRITER_STATE_ENDELEMENT
;
1955 /**************************************************************************
1956 * WsWriteEndElement [webservices.@]
1958 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1960 struct writer
*writer
= (struct writer
*)handle
;
1963 TRACE( "%p %p\n", handle
, error
);
1964 if (error
) FIXME( "ignoring error parameter\n" );
1966 if (!writer
) return E_INVALIDARG
;
1968 EnterCriticalSection( &writer
->cs
);
1970 if (writer
->magic
!= WRITER_MAGIC
)
1972 LeaveCriticalSection( &writer
->cs
);
1973 return E_INVALIDARG
;
1976 hr
= write_endelement_node( writer
);
1978 LeaveCriticalSection( &writer
->cs
);
1979 TRACE( "returning %#lx\n", hr
);
1983 static HRESULT
write_endstartelement_text( struct writer
*writer
)
1986 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1987 write_char( writer
, '>' );
1991 static HRESULT
write_endstartelement( struct writer
*writer
)
1993 switch (writer
->output_enc
)
1995 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endstartelement_text( writer
);
1996 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return S_OK
;
1998 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1999 return WS_E_NOT_SUPPORTED
;
2003 /**************************************************************************
2004 * WsWriteEndStartElement [webservices.@]
2006 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2008 struct writer
*writer
= (struct writer
*)handle
;
2011 TRACE( "%p %p\n", handle
, error
);
2012 if (error
) FIXME( "ignoring error parameter\n" );
2014 if (!writer
) return E_INVALIDARG
;
2016 EnterCriticalSection( &writer
->cs
);
2018 if (writer
->magic
!= WRITER_MAGIC
)
2020 LeaveCriticalSection( &writer
->cs
);
2021 return E_INVALIDARG
;
2024 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_OPERATION
;
2027 if ((hr
= set_namespaces( writer
)) != S_OK
) goto done
;
2028 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
2029 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
2030 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
2034 LeaveCriticalSection( &writer
->cs
);
2035 TRACE( "returning %#lx\n", hr
);
2039 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2040 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2043 WS_XML_ATTRIBUTE
*attr
;
2044 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2047 if (!(attr
= calloc( 1, sizeof(*attr
) ))) return E_OUTOFMEMORY
;
2049 if (!prefix
&& ns
->length
) prefix
= elem
->prefix
;
2051 attr
->singleQuote
= !!single
;
2052 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
2054 free_attribute( attr
);
2055 return E_OUTOFMEMORY
;
2057 if (!(attr
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
2059 free_attribute( attr
);
2060 return E_OUTOFMEMORY
;
2062 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
2064 free_attribute( attr
);
2065 return E_OUTOFMEMORY
;
2067 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
2069 free_attribute( attr
);
2075 /**************************************************************************
2076 * WsWriteStartAttribute [webservices.@]
2078 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2079 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2080 BOOL single
, WS_ERROR
*error
)
2082 struct writer
*writer
= (struct writer
*)handle
;
2085 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
2086 debugstr_xmlstr(ns
), single
, error
);
2087 if (error
) FIXME( "ignoring error parameter\n" );
2089 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
2091 EnterCriticalSection( &writer
->cs
);
2093 if (writer
->magic
!= WRITER_MAGIC
)
2095 LeaveCriticalSection( &writer
->cs
);
2096 return E_INVALIDARG
;
2099 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_OPERATION
;
2100 else if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
2101 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2103 LeaveCriticalSection( &writer
->cs
);
2104 TRACE( "returning %#lx\n", hr
);
2108 /* flush current start element if necessary */
2109 static HRESULT
write_commit( struct writer
*writer
)
2111 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
2114 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
2115 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
2116 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
2117 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
2122 static HRESULT
write_add_cdata_node( struct writer
*writer
)
2124 struct node
*node
, *parent
;
2125 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2126 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2127 write_insert_node( writer
, parent
, node
);
2131 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
2134 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
2135 node
->parent
= writer
->current
;
2136 list_add_tail( &node
->parent
->children
, &node
->entry
);
2140 static HRESULT
write_cdata( struct writer
*writer
)
2143 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
2144 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
2148 static HRESULT
write_cdata_node( struct writer
*writer
)
2151 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
2152 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
2153 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
2154 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
2155 writer
->state
= WRITER_STATE_STARTCDATA
;
2159 /**************************************************************************
2160 * WsWriteStartCData [webservices.@]
2162 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2164 struct writer
*writer
= (struct writer
*)handle
;
2167 TRACE( "%p %p\n", handle
, error
);
2168 if (error
) FIXME( "ignoring error parameter\n" );
2170 if (!writer
) return E_INVALIDARG
;
2172 EnterCriticalSection( &writer
->cs
);
2174 if (writer
->magic
!= WRITER_MAGIC
)
2176 LeaveCriticalSection( &writer
->cs
);
2177 return E_INVALIDARG
;
2180 hr
= write_cdata_node( writer
);
2182 LeaveCriticalSection( &writer
->cs
);
2183 TRACE( "returning %#lx\n", hr
);
2187 static HRESULT
write_endcdata( struct writer
*writer
)
2190 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2191 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
2195 static HRESULT
write_endcdata_node( struct writer
*writer
)
2198 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
2199 writer
->current
= writer
->current
->parent
;
2200 writer
->state
= WRITER_STATE_ENDCDATA
;
2204 /**************************************************************************
2205 * WsWriteEndCData [webservices.@]
2207 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2209 struct writer
*writer
= (struct writer
*)handle
;
2212 TRACE( "%p %p\n", handle
, error
);
2213 if (error
) FIXME( "ignoring error parameter\n" );
2215 if (!writer
) return E_INVALIDARG
;
2217 EnterCriticalSection( &writer
->cs
);
2219 if (writer
->magic
!= WRITER_MAGIC
)
2221 LeaveCriticalSection( &writer
->cs
);
2222 return E_INVALIDARG
;
2225 if (writer
->state
!= WRITER_STATE_TEXT
) hr
= WS_E_INVALID_OPERATION
;
2226 else hr
= write_endcdata_node( writer
);
2228 LeaveCriticalSection( &writer
->cs
);
2229 TRACE( "returning %#lx\n", hr
);
2233 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2234 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
2236 struct node
*node
, *parent
;
2237 WS_XML_ELEMENT_NODE
*elem
;
2239 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2241 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2243 elem
= &parent
->hdr
;
2244 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
2247 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
2250 if (prefix
&& !(elem
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
2253 return E_OUTOFMEMORY
;
2255 if (!(elem
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
2258 return E_OUTOFMEMORY
;
2260 if (!(elem
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
2263 return E_OUTOFMEMORY
;
2265 write_insert_node( writer
, parent
, node
);
2269 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
2272 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
2273 node
->parent
= parent
;
2274 list_add_tail( &parent
->children
, &node
->entry
);
2278 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2279 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
2282 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
2283 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
2284 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
2285 writer
->state
= WRITER_STATE_STARTELEMENT
;
2289 /**************************************************************************
2290 * WsWriteStartElement [webservices.@]
2292 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2293 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2296 struct writer
*writer
= (struct writer
*)handle
;
2299 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
2300 debugstr_xmlstr(ns
), error
);
2301 if (error
) FIXME( "ignoring error parameter\n" );
2303 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
2305 EnterCriticalSection( &writer
->cs
);
2307 if (writer
->magic
!= WRITER_MAGIC
)
2309 LeaveCriticalSection( &writer
->cs
);
2310 return E_INVALIDARG
;
2313 hr
= write_element_node( writer
, prefix
, localname
, ns
);
2315 LeaveCriticalSection( &writer
->cs
);
2316 TRACE( "returning %#lx\n", hr
);
2320 HRESULT
text_to_text( const WS_XML_TEXT
*text
, const WS_XML_TEXT
*old
, ULONG
*offset
, WS_XML_TEXT
**ret
)
2322 if (offset
) *offset
= 0;
2323 switch (text
->textType
)
2325 case WS_XML_TEXT_TYPE_UTF8
:
2327 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2328 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2329 WS_XML_UTF8_TEXT
*new;
2330 ULONG len
= utf8
->value
.length
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2332 if (!(new = alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2333 if (utf8_old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2334 memcpy( new->value
.bytes
+ len_old
, utf8
->value
.bytes
, len
);
2335 if (offset
) *offset
= len_old
;
2339 case WS_XML_TEXT_TYPE_UTF16
:
2341 const WS_XML_UTF16_TEXT
*utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2342 const WS_XML_UTF16_TEXT
*utf16_old
= (const WS_XML_UTF16_TEXT
*)old
;
2343 WS_XML_UTF16_TEXT
*new;
2344 ULONG len
= utf16
->byteCount
, len_old
= utf16_old
? utf16_old
->byteCount
: 0;
2346 if (utf16
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2347 if (!(new = alloc_utf16_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2348 if (utf16_old
) memcpy( new->bytes
, utf16_old
->bytes
, len_old
);
2349 memcpy( new->bytes
+ len_old
, utf16
->bytes
, len
);
2350 if (offset
) *offset
= len_old
;
2354 case WS_XML_TEXT_TYPE_BASE64
:
2356 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2357 const WS_XML_BASE64_TEXT
*base64_old
= (const WS_XML_BASE64_TEXT
*)old
;
2358 WS_XML_BASE64_TEXT
*new;
2359 ULONG len
= base64
->length
, len_old
= base64_old
? base64_old
->length
: 0;
2361 if (!(new = alloc_base64_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2362 if (base64_old
) memcpy( new->bytes
, base64_old
->bytes
, len_old
);
2363 memcpy( new->bytes
+ len_old
, base64
->bytes
, len
);
2364 if (offset
) *offset
= len_old
;
2368 case WS_XML_TEXT_TYPE_BOOL
:
2370 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2371 WS_XML_BOOL_TEXT
*new;
2373 if (!(new = alloc_bool_text( bool_text
->value
))) return E_OUTOFMEMORY
;
2377 case WS_XML_TEXT_TYPE_INT32
:
2379 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2380 WS_XML_INT32_TEXT
*new;
2382 if (!(new = alloc_int32_text( int32_text
->value
))) return E_OUTOFMEMORY
;
2386 case WS_XML_TEXT_TYPE_INT64
:
2388 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2389 WS_XML_INT64_TEXT
*new;
2391 if (!(new = alloc_int64_text( int64_text
->value
))) return E_OUTOFMEMORY
;
2395 case WS_XML_TEXT_TYPE_UINT64
:
2397 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2398 WS_XML_UINT64_TEXT
*new;
2400 if (!(new = alloc_uint64_text( uint64_text
->value
))) return E_OUTOFMEMORY
;
2404 case WS_XML_TEXT_TYPE_DOUBLE
:
2406 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2407 WS_XML_DOUBLE_TEXT
*new;
2409 if (!(new = alloc_double_text( double_text
->value
))) return E_OUTOFMEMORY
;
2413 case WS_XML_TEXT_TYPE_GUID
:
2415 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2416 WS_XML_GUID_TEXT
*new;
2418 if (!(new = alloc_guid_text( &id
->value
))) return E_OUTOFMEMORY
;
2422 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2424 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2425 WS_XML_UNIQUE_ID_TEXT
*new;
2427 if (!(new = alloc_unique_id_text( &id
->value
))) return E_OUTOFMEMORY
;
2431 case WS_XML_TEXT_TYPE_DATETIME
:
2433 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2434 WS_XML_DATETIME_TEXT
*new;
2436 if (!(new = alloc_datetime_text( &dt
->value
))) return E_OUTOFMEMORY
;
2441 FIXME( "unhandled text type %u\n", text
->textType
);
2446 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
2448 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2451 switch (value
->textType
)
2453 case WS_XML_TEXT_TYPE_UTF8
:
2454 case WS_XML_TEXT_TYPE_UTF16
:
2455 case WS_XML_TEXT_TYPE_BASE64
:
2458 case WS_XML_TEXT_TYPE_BOOL
:
2459 case WS_XML_TEXT_TYPE_INT32
:
2460 case WS_XML_TEXT_TYPE_INT64
:
2461 case WS_XML_TEXT_TYPE_UINT64
:
2462 case WS_XML_TEXT_TYPE_DOUBLE
:
2463 case WS_XML_TEXT_TYPE_GUID
:
2464 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2465 case WS_XML_TEXT_TYPE_DATETIME
:
2466 if (elem
->attributes
[elem
->attributeCount
- 1]->value
) return WS_E_INVALID_OPERATION
;
2470 FIXME( "unhandled text type %u\n", value
->textType
);
2474 switch (writer
->output_enc
)
2476 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2478 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
2479 if ((hr
= text_to_utf8text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2481 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
2484 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2486 WS_XML_TEXT
*new, *old
= elem
->attributes
[elem
->attributeCount
- 1]->value
;
2487 if ((hr
= text_to_text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2489 elem
->attributes
[elem
->attributeCount
- 1]->value
= new;
2493 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2500 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
2503 WS_XML_TEXT_NODE
*text
;
2506 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
2507 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
2508 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
2510 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2511 text
= (WS_XML_TEXT_NODE
*)node
;
2513 switch (writer
->output_enc
)
2515 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2517 WS_XML_UTF8_TEXT
*new;
2518 if ((hr
= text_to_utf8text( value
, NULL
, NULL
, &new )) != S_OK
)
2523 text
->text
= &new->text
;
2526 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2529 if ((hr
= text_to_text( value
, NULL
, NULL
, &new )) != S_OK
)
2538 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2543 write_insert_node( writer
, writer
->current
, node
);
2547 static HRESULT
write_text_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2549 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2552 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2554 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
2555 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
2557 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
2559 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
2560 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
2564 return WS_E_INVALID_FORMAT
;
2567 static enum record_type
get_text_record_type( const WS_XML_TEXT
*text
, BOOL use_dict
)
2569 switch (text
->textType
)
2571 case WS_XML_TEXT_TYPE_UTF8
:
2573 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2574 if (use_dict
) return RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
;
2575 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2576 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2577 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2579 case WS_XML_TEXT_TYPE_UTF16
:
2581 const WS_XML_UTF16_TEXT
*text_utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2582 int len
= text_utf16
->byteCount
/ sizeof(WCHAR
);
2583 int len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)text_utf16
->bytes
, len
, NULL
, 0, NULL
, NULL
);
2584 if (len_utf8
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2585 if (len_utf8
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2586 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2588 case WS_XML_TEXT_TYPE_BASE64
:
2590 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2591 ULONG rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2592 if (len
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
2593 if (len
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
2594 return RECORD_BYTES32_TEXT
;
2596 case WS_XML_TEXT_TYPE_BOOL
:
2598 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
2599 return text_bool
->value
? RECORD_TRUE_TEXT_WITH_ENDELEMENT
: RECORD_FALSE_TEXT_WITH_ENDELEMENT
;
2601 case WS_XML_TEXT_TYPE_INT32
:
2603 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
2604 if (!text_int32
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2605 if (text_int32
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2606 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2607 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2608 return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2610 case WS_XML_TEXT_TYPE_INT64
:
2612 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
2613 if (!text_int64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2614 if (text_int64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2615 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2616 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2617 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2618 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2620 case WS_XML_TEXT_TYPE_UINT64
:
2622 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
2623 if (!text_uint64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2624 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2625 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2626 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2627 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2628 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2629 return RECORD_UINT64_TEXT_WITH_ENDELEMENT
;
2631 case WS_XML_TEXT_TYPE_DOUBLE
:
2633 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
2634 if (!text_double
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2635 if (text_double
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2636 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
2637 return RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
;
2638 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2639 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2640 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2641 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2643 case WS_XML_TEXT_TYPE_GUID
:
2644 return RECORD_GUID_TEXT_WITH_ENDELEMENT
;
2646 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2647 return RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
;
2649 case WS_XML_TEXT_TYPE_DATETIME
:
2650 return RECORD_DATETIME_TEXT_WITH_ENDELEMENT
;
2653 FIXME( "unhandled text type %u\n", text
->textType
);
2658 static HRESULT
write_text_bin( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2660 enum record_type type
;
2661 BOOL use_dict
= FALSE
;
2667 FIXME( "no support for appending text in binary mode\n" );
2671 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
2673 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2674 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
2677 switch ((type
= get_text_record_type( text
, use_dict
)))
2679 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2681 const WS_XML_UTF8_TEXT
*text_utf8
;
2682 WS_XML_UTF8_TEXT
*new = NULL
;
2685 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2688 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
2691 len
= text_utf8
->value
.length
;
2692 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
)
2697 write_char( writer
, type
);
2698 write_char( writer
, len
);
2699 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2703 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2705 const WS_XML_UTF8_TEXT
*text_utf8
;
2706 WS_XML_UTF8_TEXT
*new = NULL
;
2709 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2712 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
2715 len
= text_utf8
->value
.length
;
2716 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
)
2721 write_char( writer
, type
);
2722 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2723 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2727 case RECORD_BYTES8_TEXT
:
2729 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2730 UINT8 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2734 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2735 write_char( writer
, rem
? RECORD_BYTES8_TEXT
: RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2736 write_char( writer
, len
);
2737 write_bytes( writer
, text_base64
->bytes
, len
);
2741 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2742 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2743 write_char( writer
, rem
);
2744 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2748 case RECORD_BYTES16_TEXT
:
2750 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2751 UINT16 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2755 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2756 write_char( writer
, rem
? RECORD_BYTES16_TEXT
: RECORD_BYTES16_TEXT_WITH_ENDELEMENT
);
2757 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2758 write_bytes( writer
, text_base64
->bytes
, len
);
2762 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2763 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2764 write_char( writer
, rem
);
2765 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2769 case RECORD_BYTES32_TEXT
:
2771 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2772 UINT32 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2775 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2776 write_char( writer
, rem
? RECORD_BYTES32_TEXT
: RECORD_BYTES32_TEXT_WITH_ENDELEMENT
);
2777 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2778 write_bytes( writer
, text_base64
->bytes
, len
);
2782 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2783 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2784 write_char( writer
, rem
);
2785 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2789 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2790 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2791 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2792 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2794 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2795 write_char( writer
, type
);
2798 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2800 INT8 val
= get_text_value_int( text
);
2801 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2802 write_char( writer
, type
);
2803 write_char( writer
, val
);
2806 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2808 INT16 val
= get_text_value_int( text
);
2809 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2810 write_char( writer
, type
);
2811 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2814 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2816 INT32 val
= get_text_value_int( text
);
2817 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2818 write_char( writer
, type
);
2819 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2822 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2824 INT64 val
= get_text_value_int( text
);
2825 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2826 write_char( writer
, type
);
2827 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2830 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2832 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
2833 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
2834 write_char( writer
, type
);
2835 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
2838 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2840 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
2841 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_double
->value
) )) != S_OK
) return hr
;
2842 write_char( writer
, type
);
2843 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
2846 case RECORD_GUID_TEXT_WITH_ENDELEMENT
:
2848 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
2849 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_guid
->value
) )) != S_OK
) return hr
;
2850 write_char( writer
, type
);
2851 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
2854 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
:
2856 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
2857 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
2858 write_char( writer
, type
);
2859 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
2862 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2864 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
2865 UINT64 val
= text_datetime
->value
.ticks
;
2867 assert( val
<= TICKS_MAX
);
2868 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
2869 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
2871 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2872 write_char( writer
, type
);
2873 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2876 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2878 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2879 write_char( writer
, type
);
2880 return write_dict_string( writer
, id
);
2883 FIXME( "unhandled record type %02x\n", type
);
2888 static HRESULT
write_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2890 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
2892 switch (writer
->output_enc
)
2894 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_text_text( writer
, text
, offset
);
2895 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_text_bin( writer
, text
, offset
);
2897 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2898 return WS_E_NOT_SUPPORTED
;
2902 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
2904 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2908 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
2909 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
2911 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
2912 node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2916 switch (writer
->output_enc
)
2918 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2920 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
2921 offset
= old
->value
.length
;
2922 if ((hr
= text_to_utf8text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2924 node
->text
= &new->text
;
2927 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2929 WS_XML_TEXT
*new, *old
= node
->text
;
2930 if ((hr
= text_to_text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2936 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2941 if ((hr
= write_text( writer
, node
->text
, offset
)) != S_OK
) return hr
;
2943 writer
->state
= WRITER_STATE_TEXT
;
2947 /**************************************************************************
2948 * WsWriteText [webservices.@]
2950 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
2952 struct writer
*writer
= (struct writer
*)handle
;
2955 TRACE( "%p %p %p\n", handle
, text
, error
);
2956 if (error
) FIXME( "ignoring error parameter\n" );
2958 if (!writer
|| !text
) return E_INVALIDARG
;
2960 EnterCriticalSection( &writer
->cs
);
2962 if (writer
->magic
!= WRITER_MAGIC
)
2964 LeaveCriticalSection( &writer
->cs
);
2965 return E_INVALIDARG
;
2968 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
2969 else hr
= write_text_node( writer
, text
);
2971 LeaveCriticalSection( &writer
->cs
);
2972 TRACE( "returning %#lx\n", hr
);
2976 /**************************************************************************
2977 * WsWriteBytes [webservices.@]
2979 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
2981 struct writer
*writer
= (struct writer
*)handle
;
2982 WS_XML_BASE64_TEXT base64
;
2985 TRACE( "%p %p %lu %p\n", handle
, bytes
, count
, error
);
2986 if (error
) FIXME( "ignoring error parameter\n" );
2988 if (!writer
) return E_INVALIDARG
;
2990 EnterCriticalSection( &writer
->cs
);
2992 if (writer
->magic
!= WRITER_MAGIC
)
2994 LeaveCriticalSection( &writer
->cs
);
2995 return E_INVALIDARG
;
2998 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
3001 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
3002 base64
.bytes
= (BYTE
*)bytes
;
3003 base64
.length
= count
;
3005 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
3006 else hr
= write_text_node( writer
, &base64
.text
);
3009 LeaveCriticalSection( &writer
->cs
);
3010 TRACE( "returning %#lx\n", hr
);
3014 /**************************************************************************
3015 * WsWriteChars [webservices.@]
3017 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
3019 struct writer
*writer
= (struct writer
*)handle
;
3020 WS_XML_UTF16_TEXT utf16
;
3023 TRACE( "%p %s %lu %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
3024 if (error
) FIXME( "ignoring error parameter\n" );
3026 if (!writer
) return E_INVALIDARG
;
3028 EnterCriticalSection( &writer
->cs
);
3030 if (writer
->magic
!= WRITER_MAGIC
)
3032 LeaveCriticalSection( &writer
->cs
);
3033 return E_INVALIDARG
;
3036 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
3039 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3040 utf16
.bytes
= (BYTE
*)chars
;
3041 utf16
.byteCount
= count
* sizeof(WCHAR
);
3043 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
3044 else hr
= write_text_node( writer
, &utf16
.text
);
3047 LeaveCriticalSection( &writer
->cs
);
3048 TRACE( "returning %#lx\n", hr
);
3052 /**************************************************************************
3053 * WsWriteCharsUtf8 [webservices.@]
3055 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
3057 struct writer
*writer
= (struct writer
*)handle
;
3058 WS_XML_UTF8_TEXT utf8
;
3061 TRACE( "%p %s %lu %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
3062 if (error
) FIXME( "ignoring error parameter\n" );
3064 if (!writer
) return E_INVALIDARG
;
3066 EnterCriticalSection( &writer
->cs
);
3068 if (writer
->magic
!= WRITER_MAGIC
)
3070 LeaveCriticalSection( &writer
->cs
);
3071 return E_INVALIDARG
;
3074 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
3077 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3078 utf8
.value
.bytes
= (BYTE
*)bytes
;
3079 utf8
.value
.length
= count
;
3081 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
3082 else hr
= write_text_node( writer
, &utf8
.text
);
3085 LeaveCriticalSection( &writer
->cs
);
3086 TRACE( "returning %#lx\n", hr
);
3090 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
3094 case WS_ELEMENT_TYPE_MAPPING
:
3095 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3096 return write_text_node( writer
, text
);
3098 case WS_ATTRIBUTE_TYPE_MAPPING
:
3099 return write_set_attribute_value( writer
, text
);
3101 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3102 switch (writer
->state
)
3104 case WRITER_STATE_STARTATTRIBUTE
:
3105 return write_set_attribute_value( writer
, text
);
3107 case WRITER_STATE_STARTELEMENT
:
3108 return write_text_node( writer
, text
);
3111 FIXME( "writer state %u not handled\n", writer
->state
);
3116 FIXME( "mapping %u not implemented\n", mapping
);
3121 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
3123 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
3124 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
3125 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
3126 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
3129 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
3130 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
3131 return add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
3134 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
3139 case WS_WRITE_REQUIRED_VALUE
:
3140 case WS_WRITE_NILLABLE_VALUE
:
3141 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
3145 case WS_WRITE_REQUIRED_POINTER
:
3146 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
3149 case WS_WRITE_NILLABLE_POINTER
:
3150 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
3151 *ptr
= *(const void **)value
;
3155 return E_INVALIDARG
;
3159 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3160 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3161 const BOOL
*value
, ULONG size
)
3163 WS_XML_BOOL_TEXT text_bool
;
3169 FIXME( "description not supported\n" );
3173 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3174 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
3175 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3177 text_bool
.text
.textType
= WS_XML_TEXT_TYPE_BOOL
;
3178 text_bool
.value
= *ptr
;
3179 return write_type_text( writer
, mapping
, &text_bool
.text
);
3182 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3183 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3184 const BOOL
*value
, ULONG size
)
3186 WS_XML_INT32_TEXT text_int32
;
3192 FIXME( "description not supported\n" );
3196 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3197 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3198 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3200 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3201 text_int32
.value
= *ptr
;
3202 return write_type_text( writer
, mapping
, &text_int32
.text
);
3205 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3206 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3207 const BOOL
*value
, ULONG size
)
3209 WS_XML_INT32_TEXT text_int32
;
3215 FIXME( "description not supported\n" );
3219 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3220 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3221 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3223 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3224 text_int32
.value
= *ptr
;
3225 return write_type_text( writer
, mapping
, &text_int32
.text
);
3228 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3229 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3230 const void *value
, ULONG size
)
3232 WS_XML_INT32_TEXT text_int32
;
3238 FIXME( "description not supported\n" );
3242 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3243 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3244 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3246 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3247 text_int32
.value
= *ptr
;
3248 return write_type_text( writer
, mapping
, &text_int32
.text
);
3251 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3252 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3253 const void *value
, ULONG size
)
3255 WS_XML_INT64_TEXT text_int64
;
3261 FIXME( "description not supported\n" );
3265 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3266 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3267 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3269 text_int64
.text
.textType
= WS_XML_TEXT_TYPE_INT64
;
3270 text_int64
.value
= *ptr
;
3271 return write_type_text( writer
, mapping
, &text_int64
.text
);
3274 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3275 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3276 const void *value
, ULONG size
)
3278 WS_XML_UINT64_TEXT text_uint64
;
3284 FIXME( "description not supported\n" );
3288 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3289 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3290 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3292 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3293 text_uint64
.value
= *ptr
;
3294 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3297 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3298 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3299 const void *value
, ULONG size
)
3301 WS_XML_UINT64_TEXT text_uint64
;
3307 FIXME( "description not supported\n" );
3311 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3312 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3313 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3315 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3316 text_uint64
.value
= *ptr
;
3317 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3320 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3321 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3322 const void *value
, ULONG size
)
3324 WS_XML_UINT64_TEXT text_uint64
;
3330 FIXME( "description not supported\n" );
3334 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3335 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3336 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3338 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3339 text_uint64
.value
= *ptr
;
3340 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3343 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3344 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3345 const void *value
, ULONG size
)
3347 WS_XML_UINT64_TEXT text_uint64
;
3353 FIXME( "description not supported\n" );
3357 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3358 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3359 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3361 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3362 text_uint64
.value
= *ptr
;
3363 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3366 static HRESULT
write_type_double( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3367 const WS_DOUBLE_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3368 const void *value
, ULONG size
)
3370 WS_XML_DOUBLE_TEXT text_double
;
3376 FIXME( "description not supported\n" );
3380 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3381 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(double), (const void **)&ptr
)) != S_OK
) return hr
;
3382 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3384 text_double
.text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
3385 text_double
.value
= *ptr
;
3386 return write_type_text( writer
, mapping
, &text_double
.text
);
3389 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3390 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3391 const void *value
, ULONG size
)
3393 WS_XML_DATETIME_TEXT text_datetime
;
3394 const WS_DATETIME
*ptr
;
3399 FIXME( "description not supported\n" );
3403 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3404 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
3405 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3406 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
3408 text_datetime
.text
.textType
= WS_XML_TEXT_TYPE_DATETIME
;
3409 text_datetime
.value
= *ptr
;
3410 return write_type_text( writer
, mapping
, &text_datetime
.text
);
3413 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3414 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3415 const void *value
, ULONG size
)
3417 WS_XML_GUID_TEXT text_guid
;
3423 FIXME( "description not supported\n" );
3427 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3428 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
3429 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3431 text_guid
.text
.textType
= WS_XML_TEXT_TYPE_GUID
;
3432 text_guid
.value
= *ptr
;
3433 return write_type_text( writer
, mapping
, &text_guid
.text
);
3436 static HRESULT
write_type_unique_id( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3437 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3438 const void *value
, ULONG size
)
3440 WS_XML_UNIQUE_ID_TEXT text_unique_id
;
3441 WS_XML_UTF16_TEXT text_utf16
;
3442 const WS_UNIQUE_ID
*ptr
;
3447 FIXME( "description not supported\n" );
3451 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3452 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3453 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3455 if (ptr
->uri
.length
)
3457 text_utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3458 text_utf16
.bytes
= (BYTE
*)ptr
->uri
.chars
;
3459 text_utf16
.byteCount
= ptr
->uri
.length
* sizeof(WCHAR
);
3460 return write_type_text( writer
, mapping
, &text_utf16
.text
);
3463 text_unique_id
.text
.textType
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
3464 text_unique_id
.value
= ptr
->guid
;
3465 return write_type_text( writer
, mapping
, &text_unique_id
.text
);
3468 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3469 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3470 const void *value
, ULONG size
)
3472 WS_XML_UTF16_TEXT utf16
;
3473 const WS_STRING
*ptr
;
3478 FIXME( "description not supported\n" );
3482 if (!option
) return E_INVALIDARG
;
3483 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3484 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3485 if (!ptr
->length
) return S_OK
;
3487 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3488 utf16
.bytes
= (BYTE
*)ptr
->chars
;
3489 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
3490 return write_type_text( writer
, mapping
, &utf16
.text
);
3493 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3494 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3495 const void *value
, ULONG size
)
3497 WS_XML_UTF16_TEXT utf16
;
3504 FIXME( "description not supported\n" );
3508 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3509 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
3510 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3511 if (!(len
= lstrlenW( ptr
))) return S_OK
;
3513 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3514 utf16
.bytes
= (BYTE
*)ptr
;
3515 utf16
.byteCount
= len
* sizeof(WCHAR
);
3516 return write_type_text( writer
, mapping
, &utf16
.text
);
3519 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3520 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3521 const void *value
, ULONG size
)
3523 WS_XML_BASE64_TEXT base64
;
3524 const WS_BYTES
*ptr
;
3529 FIXME( "description not supported\n" );
3533 if (!option
) return E_INVALIDARG
;
3534 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
3535 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
3536 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
3537 if (!ptr
->length
) return S_OK
;
3539 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
3540 base64
.bytes
= ptr
->bytes
;
3541 base64
.length
= ptr
->length
;
3542 return write_type_text( writer
, mapping
, &base64
.text
);
3545 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3546 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3547 const void *value
, ULONG size
)
3549 WS_XML_UTF8_TEXT utf8
;
3550 const WS_XML_STRING
*ptr
;
3555 FIXME( "description not supported\n" );
3559 if (!option
) return E_INVALIDARG
;
3560 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3561 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3562 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3563 if (!ptr
->length
) return S_OK
;
3565 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3566 utf8
.value
.bytes
= ptr
->bytes
;
3567 utf8
.value
.length
= ptr
->length
;
3568 return write_type_text( writer
, mapping
, &utf8
.text
);
3571 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
3573 const struct node
*node
;
3574 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3576 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3578 for (i
= 0; i
< elem
->attributeCount
; i
++)
3580 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3581 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
3582 *prefix
= elem
->attributes
[i
]->prefix
;
3586 return WS_E_INVALID_FORMAT
;
3589 static HRESULT
write_type_qname( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3590 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3591 const void *value
, ULONG size
)
3593 WS_XML_QNAME_TEXT qname
;
3594 const WS_XML_QNAME
*ptr
;
3595 const WS_XML_STRING
*prefix
;
3600 FIXME( "description not supported\n" );
3604 if (!option
) return E_INVALIDARG
;
3605 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3606 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3607 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3609 if (((hr
= find_prefix( writer
, &ptr
->ns
, &prefix
)) != S_OK
)) return hr
;
3611 qname
.text
.textType
= WS_XML_TEXT_TYPE_QNAME
;
3612 qname
.prefix
= (WS_XML_STRING
*)prefix
;
3613 qname
.localName
= (WS_XML_STRING
*)&ptr
->localName
;
3614 qname
.ns
= (WS_XML_STRING
*)&ptr
->ns
;
3615 return write_type_text( writer
, mapping
, &qname
.text
);
3618 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
3620 if (options
& WS_FIELD_POINTER
)
3622 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
)) return WS_WRITE_NILLABLE_POINTER
;
3623 return WS_WRITE_REQUIRED_POINTER
;
3634 case WS_UINT16_TYPE
:
3635 case WS_UINT32_TYPE
:
3636 case WS_UINT64_TYPE
:
3637 case WS_DOUBLE_TYPE
:
3638 case WS_DATETIME_TYPE
:
3640 case WS_UNIQUE_ID_TYPE
:
3641 case WS_STRING_TYPE
:
3643 case WS_XML_STRING_TYPE
:
3644 case WS_XML_QNAME_TYPE
:
3645 case WS_STRUCT_TYPE
:
3648 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
3649 return WS_WRITE_REQUIRED_VALUE
;
3652 case WS_DESCRIPTION_TYPE
:
3653 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3654 return WS_WRITE_REQUIRED_POINTER
;
3657 FIXME( "unhandled type %u\n", type
);
3662 static HRESULT
find_index( const WS_UNION_DESCRIPTION
*desc
, int value
, ULONG
*idx
)
3666 if (desc
->valueIndices
)
3668 int c
, min
= 0, max
= desc
->fieldCount
- 1;
3671 i
= (min
+ max
) / 2;
3672 c
= value
- desc
->fields
[desc
->valueIndices
[i
]]->value
;
3679 *idx
= desc
->valueIndices
[i
];
3683 return WS_E_INVALID_FORMAT
;
3686 /* fall back to linear search */
3687 for (i
= 0; i
< desc
->fieldCount
; i
++)
3689 if (desc
->fields
[i
]->value
== value
)
3695 return WS_E_INVALID_FORMAT
;
3698 static HRESULT
write_type_field( struct writer
*, const WS_FIELD_DESCRIPTION
*, const char *, ULONG
);
3700 static HRESULT
write_type_union( struct writer
*writer
, const WS_UNION_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3701 const void *value
, ULONG size
)
3708 if (size
< sizeof(enum_value
)) return E_INVALIDARG
;
3709 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3711 enum_value
= *(int *)(char *)ptr
+ desc
->enumOffset
;
3712 if (enum_value
== desc
->noneEnumValue
&& option
== WS_WRITE_NILLABLE_VALUE
) return S_OK
;
3714 if ((hr
= find_index( desc
, enum_value
, &i
)) != S_OK
) return hr
;
3715 return write_type_field( writer
, &desc
->fields
[i
]->field
, ptr
, desc
->fields
[i
]->field
.offset
);
3718 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
3719 const void *, ULONG
);
3721 static HRESULT
write_type_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3725 ULONG i
, size
, offset
= 0;
3726 WS_WRITE_OPTION option
;
3728 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3730 /* wrapper element */
3731 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
3734 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
3735 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3737 size
= sizeof(const void *);
3739 for (i
= 0; i
< count
; i
++)
3741 if (desc
->type
== WS_UNION_TYPE
)
3743 if ((hr
= write_type_union( writer
, desc
->typeDescription
, option
, buf
+ offset
, size
)) != S_OK
)
3748 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
3749 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
3750 buf
+ offset
, size
)) != S_OK
) return hr
;
3751 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3756 if (desc
->localName
) hr
= write_endelement_node( writer
);
3760 static HRESULT
write_type_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3764 WS_TYPE_MAPPING mapping
;
3765 WS_WRITE_OPTION option
;
3766 ULONG count
, size
, field_options
= desc
->options
;
3767 const char *ptr
= buf
+ offset
;
3769 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
3771 FIXME( "options %#lx not supported\n", desc
->options
);
3775 /* zero-terminated strings and descriptions are always pointers */
3776 if (desc
->type
== WS_WSZ_TYPE
|| desc
->type
== WS_DESCRIPTION_TYPE
) field_options
|= WS_FIELD_POINTER
;
3778 if (field_options
& WS_FIELD_POINTER
)
3779 size
= sizeof(const void *);
3781 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3783 if (is_nil_value( ptr
, size
))
3785 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
3786 if (field_options
& (WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
3788 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
3789 else option
= WS_WRITE_NILLABLE_VALUE
;
3793 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3794 else option
= WS_WRITE_REQUIRED_VALUE
;
3799 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3800 else option
= WS_WRITE_REQUIRED_VALUE
;
3803 switch (desc
->mapping
)
3805 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING
:
3806 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3809 case WS_ATTRIBUTE_FIELD_MAPPING
:
3810 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
3811 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
3813 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3815 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3818 case WS_ELEMENT_FIELD_MAPPING
:
3819 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
3820 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3823 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
3824 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
) return E_INVALIDARG
;
3825 option
= (field_options
& WS_FIELD_OPTIONAL
) ? WS_WRITE_NILLABLE_VALUE
: WS_WRITE_REQUIRED_VALUE
;
3826 return write_type_union( writer
, desc
->typeDescription
, option
, ptr
, size
);
3828 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3829 case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING
:
3830 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
3831 return write_type_array( writer
, desc
, *(const char **)ptr
, count
);
3833 case WS_TEXT_FIELD_MAPPING
:
3834 switch (writer
->state
)
3836 case WRITER_STATE_STARTELEMENT
:
3837 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
3840 case WRITER_STATE_STARTATTRIBUTE
:
3841 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3845 FIXME( "unhandled writer state %u\n", writer
->state
);
3850 case WS_ANY_ATTRIBUTES_FIELD_MAPPING
:
3854 FIXME( "field mapping %u not supported\n", desc
->mapping
);
3858 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
3863 case WS_ATTRIBUTE_TYPE_MAPPING
:
3864 writer
->state
= WRITER_STATE_STARTELEMENT
;
3867 case WS_ELEMENT_TYPE_MAPPING
:
3868 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3877 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3878 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3879 const void *value
, ULONG size
)
3885 if (!desc
) return E_INVALIDARG
;
3886 if (desc
->structOptions
) FIXME( "struct options %#lx not supported\n", desc
->structOptions
);
3888 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3889 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3891 for (i
= 0; i
< desc
->fieldCount
; i
++)
3893 offset
= desc
->fields
[i
]->offset
;
3894 if ((hr
= write_type_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
) return hr
;
3900 static const WS_XML_STRING
*get_enum_value_name( const WS_ENUM_DESCRIPTION
*desc
, int value
)
3903 for (i
= 0; i
< desc
->valueCount
; i
++)
3905 if (desc
->values
[i
].value
== value
) return desc
->values
[i
].name
;
3910 static HRESULT
write_type_enum( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3911 const WS_ENUM_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3912 const void *value
, ULONG size
)
3914 const WS_XML_STRING
*name
;
3915 WS_XML_UTF8_TEXT utf8
;
3919 if (!desc
) return E_INVALIDARG
;
3920 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3921 if (!(name
= get_enum_value_name( desc
, *ptr
))) return E_INVALIDARG
;
3923 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3924 utf8
.value
.bytes
= name
->bytes
;
3925 utf8
.value
.length
= name
->length
;
3926 return write_type_text( writer
, mapping
, &utf8
.text
);
3929 static HRESULT
write_type_description( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3930 WS_WRITE_OPTION option
, const void *value
, ULONG size
)
3932 const WS_STRUCT_DESCRIPTION
*ptr
;
3935 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3936 if (ptr
) FIXME( "ignoring type description %p\n", ptr
);
3940 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3941 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3947 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
3950 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
3953 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
3956 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
3959 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
3962 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
3964 case WS_UINT16_TYPE
:
3965 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
3967 case WS_UINT32_TYPE
:
3968 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
3970 case WS_UINT64_TYPE
:
3971 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
3973 case WS_DOUBLE_TYPE
:
3974 return write_type_double( writer
, mapping
, desc
, option
, value
, size
);
3976 case WS_DATETIME_TYPE
:
3977 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
3980 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
3982 case WS_UNIQUE_ID_TYPE
:
3983 return write_type_unique_id( writer
, mapping
, desc
, option
, value
, size
);
3985 case WS_STRING_TYPE
:
3986 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
3989 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
3992 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
3994 case WS_XML_STRING_TYPE
:
3995 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
3997 case WS_XML_QNAME_TYPE
:
3998 return write_type_qname( writer
, mapping
, desc
, option
, value
, size
);
4000 case WS_DESCRIPTION_TYPE
:
4001 return write_type_description( writer
, mapping
, option
, value
, size
);
4003 case WS_STRUCT_TYPE
:
4004 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
4007 return write_type_enum( writer
, mapping
, desc
, option
, value
, size
);
4010 FIXME( "type %u not supported\n", type
);
4015 /**************************************************************************
4016 * WsWriteAttribute [webservices.@]
4018 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
4019 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
4022 struct writer
*writer
= (struct writer
*)handle
;
4025 TRACE( "%p %p %u %p %lu %p\n", handle
, desc
, option
, value
, size
, error
);
4026 if (error
) FIXME( "ignoring error parameter\n" );
4028 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
4029 return E_INVALIDARG
;
4031 EnterCriticalSection( &writer
->cs
);
4033 if (writer
->magic
!= WRITER_MAGIC
)
4035 LeaveCriticalSection( &writer
->cs
);
4036 return E_INVALIDARG
;
4039 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_OPERATION
;
4040 else if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) == S_OK
)
4042 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
4043 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
4046 LeaveCriticalSection( &writer
->cs
);
4047 TRACE( "returning %#lx\n", hr
);
4051 /**************************************************************************
4052 * WsWriteElement [webservices.@]
4054 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4055 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
4058 struct writer
*writer
= (struct writer
*)handle
;
4061 TRACE( "%p %p %u %p %lu %p\n", handle
, desc
, option
, value
, size
, error
);
4062 if (error
) FIXME( "ignoring error parameter\n" );
4064 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
4065 return E_INVALIDARG
;
4067 EnterCriticalSection( &writer
->cs
);
4069 if (writer
->magic
!= WRITER_MAGIC
)
4071 LeaveCriticalSection( &writer
->cs
);
4072 return E_INVALIDARG
;
4075 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4077 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
4078 option
, value
, size
)) != S_OK
) goto done
;
4080 hr
= write_endelement_node( writer
);
4083 LeaveCriticalSection( &writer
->cs
);
4084 TRACE( "returning %#lx\n", hr
);
4088 /**************************************************************************
4089 * WsWriteType [webservices.@]
4091 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
4092 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
4093 ULONG size
, WS_ERROR
*error
)
4095 struct writer
*writer
= (struct writer
*)handle
;
4098 TRACE( "%p %u %u %p %u %p %lu %p\n", handle
, mapping
, type
, desc
, option
, value
,
4100 if (error
) FIXME( "ignoring error parameter\n" );
4102 if (!writer
|| !value
) return E_INVALIDARG
;
4104 EnterCriticalSection( &writer
->cs
);
4106 if (writer
->magic
!= WRITER_MAGIC
)
4108 LeaveCriticalSection( &writer
->cs
);
4109 return E_INVALIDARG
;
4114 case WS_ATTRIBUTE_TYPE_MAPPING
:
4115 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
4116 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
4119 case WS_ELEMENT_TYPE_MAPPING
:
4120 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
4121 case WS_ANY_ELEMENT_TYPE_MAPPING
:
4122 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
4126 FIXME( "mapping %u not implemented\n", mapping
);
4130 LeaveCriticalSection( &writer
->cs
);
4131 TRACE( "returning %#lx\n", hr
);
4135 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
4139 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
4140 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
4141 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
4142 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
4143 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
4144 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
4145 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
4146 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
4147 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
4148 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
4149 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
4150 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
4151 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
4152 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
4153 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
4155 FIXME( "unhandled type %u\n", type
);
4160 /**************************************************************************
4161 * WsWriteValue [webservices.@]
4163 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
4164 ULONG size
, WS_ERROR
*error
)
4166 struct writer
*writer
= (struct writer
*)handle
;
4167 WS_TYPE_MAPPING mapping
;
4171 TRACE( "%p %u %p %lu %p\n", handle
, value_type
, value
, size
, error
);
4172 if (error
) FIXME( "ignoring error parameter\n" );
4174 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
4176 EnterCriticalSection( &writer
->cs
);
4178 if (writer
->magic
!= WRITER_MAGIC
)
4180 LeaveCriticalSection( &writer
->cs
);
4181 return E_INVALIDARG
;
4184 switch (writer
->state
)
4186 case WRITER_STATE_STARTATTRIBUTE
:
4187 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
4190 case WRITER_STATE_STARTELEMENT
:
4191 mapping
= WS_ELEMENT_TYPE_MAPPING
;
4195 hr
= WS_E_INVALID_FORMAT
;
4198 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
4200 LeaveCriticalSection( &writer
->cs
);
4201 TRACE( "returning %#lx\n", hr
);
4205 /**************************************************************************
4206 * WsWriteArray [webservices.@]
4208 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4209 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
4210 ULONG count
, WS_ERROR
*error
)
4212 struct writer
*writer
= (struct writer
*)handle
;
4217 TRACE( "%p %s %s %u %p %lu %lu %lu %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
4218 value_type
, array
, size
, offset
, count
, error
);
4219 if (error
) FIXME( "ignoring error parameter\n" );
4221 if (!writer
) return E_INVALIDARG
;
4223 EnterCriticalSection( &writer
->cs
);
4225 if (writer
->magic
!= WRITER_MAGIC
)
4227 LeaveCriticalSection( &writer
->cs
);
4228 return E_INVALIDARG
;
4231 if (!writer
->output_type
)
4233 hr
= WS_E_INVALID_OPERATION
;
4237 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
4243 type_size
= get_type_size( type
, NULL
);
4244 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
4250 for (i
= offset
; i
< count
; i
++)
4252 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
4253 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
4254 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
4255 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
4256 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
4260 LeaveCriticalSection( &writer
->cs
);
4261 TRACE( "returning %#lx\n", hr
);
4265 /**************************************************************************
4266 * WsWriteXmlBuffer [webservices.@]
4268 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
4270 struct writer
*writer
= (struct writer
*)handle
;
4271 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4274 TRACE( "%p %p %p\n", handle
, buffer
, error
);
4275 if (error
) FIXME( "ignoring error parameter\n" );
4277 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
4279 EnterCriticalSection( &writer
->cs
);
4281 if (writer
->magic
!= WRITER_MAGIC
)
4283 LeaveCriticalSection( &writer
->cs
);
4284 return E_INVALIDARG
;
4287 if (xmlbuf
->encoding
!= writer
->output_enc
|| xmlbuf
->charset
!= writer
->output_charset
)
4289 FIXME( "no support for different encoding and/or charset\n" );
4294 if ((hr
= write_commit( writer
)) != S_OK
) goto done
;
4295 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
4296 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4299 LeaveCriticalSection( &writer
->cs
);
4300 TRACE( "returning %#lx\n", hr
);
4304 /**************************************************************************
4305 * WsWriteXmlBufferToBytes [webservices.@]
4307 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
4308 const WS_XML_WRITER_ENCODING
*encoding
,
4309 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
4310 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
4312 struct writer
*writer
= (struct writer
*)handle
;
4313 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4318 TRACE( "%p %p %p %p %lu %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
4319 bytes
, size
, error
);
4320 if (error
) FIXME( "ignoring error parameter\n" );
4322 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
4324 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
4326 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4330 EnterCriticalSection( &writer
->cs
);
4332 if (writer
->magic
!= WRITER_MAGIC
)
4334 LeaveCriticalSection( &writer
->cs
);
4335 return E_INVALIDARG
;
4338 for (i
= 0; i
< count
; i
++)
4340 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4341 properties
[i
].valueSize
);
4342 if (hr
!= S_OK
) goto done
;
4345 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
4348 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4350 *size
= xmlbuf
->bytes
.length
;
4354 LeaveCriticalSection( &writer
->cs
);
4355 TRACE( "returning %#lx\n", hr
);
4359 /**************************************************************************
4360 * WsWriteXmlnsAttribute [webservices.@]
4362 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4363 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
4365 struct writer
*writer
= (struct writer
*)handle
;
4368 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
4370 if (error
) FIXME( "ignoring error parameter\n" );
4372 if (!writer
|| !ns
) return E_INVALIDARG
;
4374 EnterCriticalSection( &writer
->cs
);
4376 if (writer
->magic
!= WRITER_MAGIC
)
4378 LeaveCriticalSection( &writer
->cs
);
4379 return E_INVALIDARG
;
4382 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_OPERATION
;
4383 else if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
4384 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
4386 LeaveCriticalSection( &writer
->cs
);
4387 TRACE( "returning %#lx\n", hr
);
4391 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
4392 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
4394 WS_XML_QNAME_TEXT qname
= {{WS_XML_TEXT_TYPE_QNAME
}};
4397 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
4398 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) return hr
;
4400 qname
.prefix
= (WS_XML_STRING
*)prefix
;
4401 qname
.localName
= (WS_XML_STRING
*)localname
;
4402 qname
.ns
= (WS_XML_STRING
*)ns
;
4404 if ((hr
= write_add_text_node( writer
, &qname
.text
)) != S_OK
) return hr
;
4405 return write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 );
4408 /**************************************************************************
4409 * WsWriteQualifiedName [webservices.@]
4411 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4412 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4415 struct writer
*writer
= (struct writer
*)handle
;
4418 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
4419 debugstr_xmlstr(ns
), error
);
4420 if (error
) FIXME( "ignoring error parameter\n" );
4422 if (!writer
) return E_INVALIDARG
;
4424 EnterCriticalSection( &writer
->cs
);
4426 if (writer
->magic
!= WRITER_MAGIC
)
4428 LeaveCriticalSection( &writer
->cs
);
4429 return E_INVALIDARG
;
4432 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
4433 else if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_FORMAT
;
4434 else if (!localname
|| (!prefix
&& !ns
)) hr
= E_INVALIDARG
;
4435 else hr
= write_qualified_name( writer
, prefix
, localname
, ns
);
4437 LeaveCriticalSection( &writer
->cs
);
4438 TRACE( "returning %#lx\n", hr
);
4442 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
4444 BOOL success
= FALSE
;
4445 struct node
*node
= writer
->current
;
4449 case WS_MOVE_TO_ROOT_ELEMENT
:
4450 success
= move_to_root_element( writer
->root
, &node
);
4453 case WS_MOVE_TO_NEXT_ELEMENT
:
4454 success
= move_to_next_element( &node
);
4457 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
4458 success
= move_to_prev_element( &node
);
4461 case WS_MOVE_TO_CHILD_ELEMENT
:
4462 success
= move_to_child_element( &node
);
4465 case WS_MOVE_TO_END_ELEMENT
:
4466 success
= move_to_end_element( &node
);
4469 case WS_MOVE_TO_PARENT_ELEMENT
:
4470 success
= move_to_parent_element( &node
);
4473 case WS_MOVE_TO_FIRST_NODE
:
4474 success
= move_to_first_node( &node
);
4477 case WS_MOVE_TO_NEXT_NODE
:
4478 success
= move_to_next_node( &node
);
4481 case WS_MOVE_TO_PREVIOUS_NODE
:
4482 success
= move_to_prev_node( &node
);
4485 case WS_MOVE_TO_CHILD_NODE
:
4486 success
= move_to_child_node( &node
);
4489 case WS_MOVE_TO_BOF
:
4490 success
= move_to_bof( writer
->root
, &node
);
4493 case WS_MOVE_TO_EOF
:
4494 success
= move_to_eof( writer
->root
, &node
);
4498 FIXME( "unhandled move %u\n", move
);
4502 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
4503 writer
->current
= node
;
4510 return success
? S_OK
: WS_E_INVALID_FORMAT
;
4513 /**************************************************************************
4514 * WsMoveWriter [webservices.@]
4516 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
4518 struct writer
*writer
= (struct writer
*)handle
;
4521 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
4522 if (error
) FIXME( "ignoring error parameter\n" );
4524 if (!writer
) return E_INVALIDARG
;
4526 EnterCriticalSection( &writer
->cs
);
4528 if (writer
->magic
!= WRITER_MAGIC
)
4530 LeaveCriticalSection( &writer
->cs
);
4531 return E_INVALIDARG
;
4534 if (writer
->output_type
!= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
) hr
= WS_E_INVALID_OPERATION
;
4535 else hr
= write_move_to( writer
, move
, found
);
4537 LeaveCriticalSection( &writer
->cs
);
4538 TRACE( "returning %#lx\n", hr
);
4542 /**************************************************************************
4543 * WsGetWriterPosition [webservices.@]
4545 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4547 struct writer
*writer
= (struct writer
*)handle
;
4550 TRACE( "%p %p %p\n", handle
, pos
, error
);
4551 if (error
) FIXME( "ignoring error parameter\n" );
4553 if (!writer
|| !pos
) return E_INVALIDARG
;
4555 EnterCriticalSection( &writer
->cs
);
4557 if (writer
->magic
!= WRITER_MAGIC
)
4559 LeaveCriticalSection( &writer
->cs
);
4560 return E_INVALIDARG
;
4563 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
4566 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
4567 pos
->node
= writer
->current
;
4570 LeaveCriticalSection( &writer
->cs
);
4571 TRACE( "returning %#lx\n", hr
);
4575 /**************************************************************************
4576 * WsSetWriterPosition [webservices.@]
4578 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4580 struct writer
*writer
= (struct writer
*)handle
;
4583 TRACE( "%p %p %p\n", handle
, pos
, error
);
4584 if (error
) FIXME( "ignoring error parameter\n" );
4586 if (!writer
|| !pos
) return E_INVALIDARG
;
4588 EnterCriticalSection( &writer
->cs
);
4590 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
4592 LeaveCriticalSection( &writer
->cs
);
4593 return E_INVALIDARG
;
4596 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
4597 else writer
->current
= pos
->node
;
4599 LeaveCriticalSection( &writer
->cs
);
4600 TRACE( "returning %#lx\n", hr
);
4604 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4606 struct node
*node
, *parent
;
4607 WS_XML_COMMENT_NODE
*comment
;
4609 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
4610 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
4611 comment
= (WS_XML_COMMENT_NODE
*)node
;
4613 if (value
->length
&& !(comment
->value
.bytes
= malloc( value
->length
)))
4616 return E_OUTOFMEMORY
;
4618 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
4619 comment
->value
.length
= value
->length
;
4621 write_insert_node( writer
, parent
, node
);
4625 static HRESULT
write_comment_text( struct writer
*writer
)
4627 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4630 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
4631 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
4632 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
4633 write_bytes( writer
, (const BYTE
*)"-->", 3 );
4637 static HRESULT
write_comment_bin( struct writer
*writer
)
4639 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4642 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
4643 write_char( writer
, RECORD_COMMENT
);
4644 return write_string( writer
, comment
->value
.bytes
, comment
->value
.length
);
4647 static HRESULT
write_comment( struct writer
*writer
)
4649 switch (writer
->output_enc
)
4651 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_comment_text( writer
);
4652 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_comment_bin( writer
);
4654 ERR( "unhandled encoding %u\n", writer
->output_enc
);
4655 return WS_E_NOT_SUPPORTED
;
4659 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4662 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
4663 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
4664 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4665 writer
->state
= WRITER_STATE_COMMENT
;
4669 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
4674 for (i
= 0; i
< count
; i
++)
4676 const WS_XML_STRING
*prefix
= attrs
[i
]->prefix
;
4677 const WS_XML_STRING
*localname
= attrs
[i
]->localName
;
4678 const WS_XML_STRING
*ns
= attrs
[i
]->ns
;
4679 BOOL single
= attrs
[i
]->singleQuote
;
4681 if (attrs
[i
]->isXmlNs
)
4683 if ((hr
= add_namespace_attribute( writer
, prefix
, ns
, single
)) != S_OK
) return hr
;
4687 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) != S_OK
) return hr
;
4688 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
4694 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
4698 switch (node
->nodeType
)
4700 case WS_XML_NODE_TYPE_ELEMENT
:
4702 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
4703 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
4704 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
4706 case WS_XML_NODE_TYPE_TEXT
:
4708 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4709 return write_text_node( writer
, text
->text
);
4711 case WS_XML_NODE_TYPE_END_ELEMENT
:
4712 return write_endelement_node( writer
);
4714 case WS_XML_NODE_TYPE_COMMENT
:
4716 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
4717 return write_comment_node( writer
, &comment
->value
);
4719 case WS_XML_NODE_TYPE_CDATA
:
4720 return write_cdata_node( writer
);
4722 case WS_XML_NODE_TYPE_END_CDATA
:
4723 return write_endcdata_node( writer
);
4725 case WS_XML_NODE_TYPE_EOF
:
4726 case WS_XML_NODE_TYPE_BOF
:
4730 WARN( "unknown node type %u\n", node
->nodeType
);
4731 return E_INVALIDARG
;
4735 /**************************************************************************
4736 * WsWriteNode [webservices.@]
4738 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
4740 struct writer
*writer
= (struct writer
*)handle
;
4743 TRACE( "%p %p %p\n", handle
, node
, error
);
4744 if (error
) FIXME( "ignoring error parameter\n" );
4746 if (!writer
|| !node
) return E_INVALIDARG
;
4748 EnterCriticalSection( &writer
->cs
);
4750 if (writer
->magic
!= WRITER_MAGIC
)
4752 LeaveCriticalSection( &writer
->cs
);
4753 return E_INVALIDARG
;
4756 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
4757 else hr
= write_node( writer
, node
);
4759 LeaveCriticalSection( &writer
->cs
);
4760 TRACE( "returning %#lx\n", hr
);
4764 static HRESULT
write_tree_node( struct writer
*writer
)
4768 switch (node_type( writer
->current
))
4770 case WS_XML_NODE_TYPE_ELEMENT
:
4771 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4773 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
4774 writer
->state
= WRITER_STATE_STARTELEMENT
;
4777 case WS_XML_NODE_TYPE_TEXT
:
4778 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4780 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
4781 writer
->state
= WRITER_STATE_TEXT
;
4784 case WS_XML_NODE_TYPE_END_ELEMENT
:
4785 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
4786 writer
->state
= WRITER_STATE_ENDELEMENT
;
4789 case WS_XML_NODE_TYPE_COMMENT
:
4790 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4792 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4793 writer
->state
= WRITER_STATE_COMMENT
;
4796 case WS_XML_NODE_TYPE_CDATA
:
4797 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4799 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
4800 writer
->state
= WRITER_STATE_STARTCDATA
;
4803 case WS_XML_NODE_TYPE_END_CDATA
:
4804 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
4805 writer
->state
= WRITER_STATE_ENDCDATA
;
4808 case WS_XML_NODE_TYPE_EOF
:
4809 case WS_XML_NODE_TYPE_BOF
:
4813 ERR( "unknown node type %u\n", node_type(writer
->current
) );
4814 return E_INVALIDARG
;
4818 static HRESULT
write_tree( struct writer
*writer
)
4822 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4825 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
4826 if (move_to_child_node( &writer
->current
))
4828 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4831 if (move_to_next_node( &writer
->current
))
4833 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4836 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
4838 ERR( "invalid tree\n" );
4839 return WS_E_INVALID_FORMAT
;
4841 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4846 static void write_rewind( struct writer
*writer
)
4848 writer
->write_pos
= 0;
4849 writer
->current
= writer
->root
;
4850 writer
->state
= WRITER_STATE_INITIAL
;
4853 /**************************************************************************
4854 * WsCopyNode [webservices.@]
4856 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
4858 struct writer
*writer
= (struct writer
*)handle
;
4859 struct node
*parent
, *current
, *node
= NULL
;
4862 TRACE( "%p %p %p\n", handle
, reader
, error
);
4863 if (error
) FIXME( "ignoring error parameter\n" );
4865 if (!writer
) return E_INVALIDARG
;
4867 EnterCriticalSection( &writer
->cs
);
4869 if (writer
->magic
!= WRITER_MAGIC
)
4871 LeaveCriticalSection( &writer
->cs
);
4872 return E_INVALIDARG
;
4875 if (!(parent
= find_parent( writer
))) hr
= WS_E_INVALID_FORMAT
;
4878 if ((hr
= copy_node( reader
, writer
->output_enc
, &node
)) != S_OK
) goto done
;
4879 current
= writer
->current
;
4880 write_insert_node( writer
, parent
, node
);
4882 write_rewind( writer
);
4883 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
4884 writer
->current
= current
;
4886 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
4890 LeaveCriticalSection( &writer
->cs
);
4891 TRACE( "returning %#lx\n", hr
);
4895 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
4897 return write_type_field( writer
, desc
, value
, 0 );
4900 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
4903 for (i
= 0; i
< count
; i
++)
4905 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4907 if (params
[i
].outputMessageIndex
!= INVALID_PARAMETER_INDEX
)
4908 ret
= **(const ULONG
**)args
[i
];
4910 ret
= *(const ULONG
*)args
[i
];
4916 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
4919 return write_type_array( writer
, desc
, value
, len
);
4922 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4923 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4925 struct writer
*writer
= (struct writer
*)handle
;
4926 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4927 const WS_FIELD_DESCRIPTION
*desc_field
;
4931 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4933 EnterCriticalSection( &writer
->cs
);
4935 if (writer
->magic
!= WRITER_MAGIC
)
4937 LeaveCriticalSection( &writer
->cs
);
4938 return E_INVALIDARG
;
4941 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4943 for (i
= 0; i
< count
; i
++)
4945 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
4946 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
4948 FIXME( "messages type not supported\n" );
4952 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
4953 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
4956 if (params
[i
].outputMessageIndex
!= INVALID_PARAMETER_INDEX
)
4957 ptr
= *(const void **)args
[i
];
4960 if ((hr
= write_param( writer
, desc_field
, ptr
)) != S_OK
) goto done
;
4962 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
4966 if (params
[i
].outputMessageIndex
!= INVALID_PARAMETER_INDEX
)
4967 ptr
= **(const void ***)args
[i
];
4969 ptr
= *(const void **)args
[i
];
4970 len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
4971 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
4975 hr
= write_endelement_node( writer
);
4978 LeaveCriticalSection( &writer
->cs
);
4982 HRESULT
writer_set_lookup( WS_XML_WRITER
*handle
, BOOL enable
)
4984 struct writer
*writer
= (struct writer
*)handle
;
4986 EnterCriticalSection( &writer
->cs
);
4988 if (writer
->magic
!= WRITER_MAGIC
)
4990 LeaveCriticalSection( &writer
->cs
);
4991 return E_INVALIDARG
;
4994 writer
->dict_do_lookup
= enable
;
4996 LeaveCriticalSection( &writer
->cs
);
5000 HRESULT
writer_set_dict_callback( WS_XML_WRITER
*handle
, WS_DYNAMIC_STRING_CALLBACK cb
, void *state
)
5002 struct writer
*writer
= (struct writer
*)handle
;
5004 EnterCriticalSection( &writer
->cs
);
5006 if (writer
->magic
!= WRITER_MAGIC
)
5008 LeaveCriticalSection( &writer
->cs
);
5009 return E_INVALIDARG
;
5012 writer
->dict_cb
= cb
;
5013 writer
->dict_cb_state
= state
;
5015 LeaveCriticalSection( &writer
->cs
);