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
29 #include "webservices.h"
31 #include "wine/debug.h"
32 #include "wine/heap.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
= heap_alloc_zero( 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 heap_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 %u %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
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
224 &max_size
, sizeof(max_size
) );
227 free_writer( writer
);
231 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
234 free_writer( writer
);
238 hr
= init_writer( writer
);
241 free_writer( writer
);
245 TRACE( "created %p\n", writer
);
246 *handle
= (WS_XML_WRITER
*)writer
;
250 /**************************************************************************
251 * WsFreeWriter [webservices.@]
253 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
255 struct writer
*writer
= (struct writer
*)handle
;
257 TRACE( "%p\n", handle
);
261 EnterCriticalSection( &writer
->cs
);
263 if (writer
->magic
!= WRITER_MAGIC
)
265 LeaveCriticalSection( &writer
->cs
);
271 LeaveCriticalSection( &writer
->cs
);
272 free_writer( writer
);
275 /**************************************************************************
276 * WsGetWriterProperty [webservices.@]
278 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
279 void *buf
, ULONG size
, WS_ERROR
*error
)
281 struct writer
*writer
= (struct writer
*)handle
;
284 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
285 if (error
) FIXME( "ignoring error parameter\n" );
287 if (!writer
) return E_INVALIDARG
;
289 EnterCriticalSection( &writer
->cs
);
291 if (writer
->magic
!= WRITER_MAGIC
)
293 LeaveCriticalSection( &writer
->cs
);
297 if (writer
->output_type
!= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
) hr
= WS_E_INVALID_OPERATION
;
302 case WS_XML_WRITER_PROPERTY_BYTES
:
304 WS_BYTES
*bytes
= buf
;
305 if (size
!= sizeof(*bytes
)) hr
= E_INVALIDARG
;
308 bytes
->bytes
= writer
->output_buf
->bytes
.bytes
;
309 bytes
->length
= writer
->output_buf
->bytes
.length
;
313 case WS_XML_WRITER_PROPERTY_BUFFERS
:
314 if (writer
->output_buf
->bytes
.length
)
316 WS_BUFFERS
*buffers
= buf
;
317 if (size
!= sizeof(*buffers
)) hr
= E_INVALIDARG
;
320 buffers
->bufferCount
= 1;
321 buffers
->buffers
= &writer
->output_buf
->bytes
;
327 hr
= prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
331 LeaveCriticalSection( &writer
->cs
);
332 TRACE( "returning %08x\n", hr
);
336 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
338 /* free current buffer if it's ours */
339 if (writer
->output_buf
&& !writer
->output_buf_user
)
341 free_xmlbuf( writer
->output_buf
);
343 writer
->output_buf
= xmlbuf
;
344 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
345 writer
->write_bufptr
= xmlbuf
->bytes
.bytes
;
346 writer
->write_pos
= 0;
349 static void set_output_stream( struct writer
*writer
, WS_WRITE_CALLBACK callback
, void *state
)
351 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_STREAM
;
352 writer
->output_cb
= callback
;
353 writer
->output_cb_state
= state
;
354 writer
->write_bufptr
= writer
->stream_buf
;
355 writer
->write_pos
= 0;
358 /**************************************************************************
359 * WsSetOutput [webservices.@]
361 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
362 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
363 ULONG count
, WS_ERROR
*error
)
365 struct writer
*writer
= (struct writer
*)handle
;
370 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
371 if (error
) FIXME( "ignoring error parameter\n" );
373 if (!writer
) return E_INVALIDARG
;
375 EnterCriticalSection( &writer
->cs
);
377 if (writer
->magic
!= WRITER_MAGIC
)
379 LeaveCriticalSection( &writer
->cs
);
383 for (i
= 0; i
< count
; i
++)
385 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
386 properties
[i
].valueSize
);
387 if (hr
!= S_OK
) goto done
;
390 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
392 switch (encoding
->encodingType
)
394 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
396 const WS_XML_WRITER_TEXT_ENCODING
*text
= (const WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
397 if (text
->charSet
!= WS_CHARSET_UTF8
)
399 FIXME( "charset %u not supported\n", text
->charSet
);
403 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
404 writer
->output_charset
= WS_CHARSET_UTF8
;
407 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
409 const WS_XML_WRITER_BINARY_ENCODING
*bin
= (const WS_XML_WRITER_BINARY_ENCODING
*)encoding
;
410 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_BINARY
;
411 writer
->output_charset
= 0;
412 writer
->dict
= bin
->staticDictionary
;
413 writer
->dict_cb
= bin
->dynamicStringCallback
;
414 writer
->dict_cb_state
= bin
->dynamicStringCallbackState
;
418 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
423 switch (output
->outputType
)
425 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
427 struct xmlbuf
*xmlbuf
;
428 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
, 0, writer
->output_enc
, writer
->output_charset
,
429 writer
->dict
, NULL
)))
431 hr
= WS_E_QUOTA_EXCEEDED
;
434 set_output_buffer( writer
, xmlbuf
);
435 writer
->output_buf_user
= FALSE
;
438 case WS_XML_WRITER_OUTPUT_TYPE_STREAM
:
440 const WS_XML_WRITER_STREAM_OUTPUT
*stream
= (const WS_XML_WRITER_STREAM_OUTPUT
*)output
;
441 if (!writer
->stream_buf
&& !(writer
->stream_buf
= heap_alloc( STREAM_BUFSIZE
)))
446 set_output_stream( writer
, stream
->writeCallback
, stream
->writeCallbackState
);
451 FIXME( "output type %u not supported\n", output
->outputType
);
456 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
457 else write_insert_bof( writer
, node
);
460 LeaveCriticalSection( &writer
->cs
);
461 TRACE( "returning %08x\n", hr
);
465 /**************************************************************************
466 * WsSetOutputToBuffer [webservices.@]
468 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
469 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
472 struct writer
*writer
= (struct writer
*)handle
;
473 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
478 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
479 if (error
) FIXME( "ignoring error parameter\n" );
481 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
483 EnterCriticalSection( &writer
->cs
);
485 if (writer
->magic
!= WRITER_MAGIC
)
487 LeaveCriticalSection( &writer
->cs
);
491 for (i
= 0; i
< count
; i
++)
493 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
494 properties
[i
].valueSize
);
495 if (hr
!= S_OK
) goto done
;
498 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
499 writer
->output_enc
= xmlbuf
->encoding
;
500 writer
->output_charset
= xmlbuf
->charset
;
501 set_output_buffer( writer
, xmlbuf
);
502 writer
->output_buf_user
= TRUE
;
504 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
505 else write_insert_bof( writer
, node
);
508 LeaveCriticalSection( &writer
->cs
);
509 TRACE( "returning %08x\n", hr
);
513 static HRESULT
flush_writer( struct writer
*writer
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
518 if (writer
->write_pos
< min_size
) return S_OK
;
520 buf
.bytes
= writer
->write_bufptr
;
521 buf
.length
= writer
->write_pos
;
522 writer
->output_cb( writer
->output_cb_state
, &buf
, 1, ctx
, error
);
523 writer
->write_pos
= 0;
527 /**************************************************************************
528 * WsFlushWriter [webservices.@]
530 HRESULT WINAPI
WsFlushWriter( WS_XML_WRITER
*handle
, ULONG min_size
, const WS_ASYNC_CONTEXT
*ctx
,
533 struct writer
*writer
= (struct writer
*)handle
;
536 TRACE( "%p %u %p %p\n", handle
, min_size
, ctx
, error
);
537 if (error
) FIXME( "ignoring error parameter\n" );
538 if (ctx
) FIXME( "ignoring ctx parameter\n" );
540 if (!writer
) return E_INVALIDARG
;
542 EnterCriticalSection( &writer
->cs
);
544 if (writer
->magic
!= WRITER_MAGIC
)
546 LeaveCriticalSection( &writer
->cs
);
550 if (writer
->output_type
!= WS_XML_WRITER_OUTPUT_TYPE_STREAM
) hr
= WS_E_INVALID_OPERATION
;
551 else hr
= flush_writer( writer
, min_size
, ctx
, error
);
553 LeaveCriticalSection( &writer
->cs
);
554 TRACE( "returning %08x\n", hr
);
558 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
560 struct xmlbuf
*buf
= writer
->output_buf
;
564 if (writer
->output_type
== WS_XML_WRITER_OUTPUT_TYPE_STREAM
)
566 if (size
> STREAM_BUFSIZE
) return WS_E_QUOTA_EXCEEDED
;
567 return flush_writer( writer
, STREAM_BUFSIZE
- size
, NULL
, NULL
);
570 if (buf
->size
>= writer
->write_pos
+ size
)
572 buf
->bytes
.length
= writer
->write_pos
+ size
;
575 new_size
= max( buf
->size
* 2, writer
->write_pos
+ size
);
576 if (!(tmp
= ws_realloc( buf
->heap
, buf
->bytes
.bytes
, buf
->size
, new_size
))) return WS_E_QUOTA_EXCEEDED
;
577 writer
->write_bufptr
= buf
->bytes
.bytes
= tmp
;
578 buf
->size
= new_size
;
579 buf
->bytes
.length
= writer
->write_pos
+ size
;
583 static inline void write_char( struct writer
*writer
, unsigned char ch
)
585 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
588 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
590 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
591 writer
->write_pos
+= len
;
600 static const struct escape escape_lt
= { '<', "<", 4 };
601 static const struct escape escape_gt
= { '>', ">", 4 };
602 static const struct escape escape_amp
= { '&', "&", 5 };
603 static const struct escape escape_apos
= { '\'', "'", 6 };
604 static const struct escape escape_quot
= { '"', """, 6 };
606 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
607 const struct escape
**escapes
, ULONG nb_escapes
)
613 for (i
= 0; i
< len
; i
++)
617 for (j
= 0; j
< nb_escapes
; j
++)
619 if (bytes
[i
] == escapes
[j
]->ch
)
621 ptr
= (const BYTE
*)escapes
[j
]->entity
;
622 size
= escapes
[j
]->len
;
626 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
627 write_bytes( writer
, ptr
, size
);
633 static HRESULT
write_attribute_value_text( struct writer
*writer
, const WS_XML_TEXT
*text
, BOOL single
)
635 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
;
636 const struct escape
*escapes
[3];
638 escapes
[0] = single
? &escape_apos
: &escape_quot
;
639 escapes
[1] = &escape_lt
;
640 escapes
[2] = &escape_amp
;
641 return write_bytes_escape( writer
, utf8
->value
.bytes
, utf8
->value
.length
, escapes
, 3 );
644 static HRESULT
write_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
646 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
647 const WS_XML_STRING
*prefix
= NULL
;
651 if (attr
->prefix
) prefix
= attr
->prefix
;
653 /* ' prefix:attr="value"' */
655 size
= attr
->localName
->length
+ 4 /* ' =""' */;
656 if (prefix
&& prefix
->length
) size
+= prefix
->length
+ 1 /* ':' */;
657 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
659 write_char( writer
, ' ' );
660 if (prefix
&& prefix
->length
)
662 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
663 write_char( writer
, ':' );
665 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
666 write_char( writer
, '=' );
667 write_char( writer
, quote
);
668 if (attr
->value
) hr
= write_attribute_value_text( writer
, attr
->value
, attr
->singleQuote
);
669 write_char( writer
, quote
);
674 static HRESULT
write_int31( struct writer
*writer
, ULONG len
)
678 if (len
> 0x7fffffff) return E_INVALIDARG
;
680 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
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) < 0x80)
707 write_char( writer
, len
);
710 write_char( writer
, (len
& 0x7f) | 0x80 );
712 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
713 if ((len
>>= 7) < 0x08)
715 write_char( writer
, len
);
718 return WS_E_INVALID_FORMAT
;
721 static HRESULT
write_string( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
724 if ((hr
= write_int31( writer
, len
)) != S_OK
) return hr
;
725 if ((hr
= write_grow_buffer( writer
, len
)) != S_OK
) return hr
;
726 write_bytes( writer
, bytes
, len
);
730 static HRESULT
write_dict_string( struct writer
*writer
, ULONG id
)
732 if (id
> 0x7fffffff) return E_INVALIDARG
;
733 return write_int31( writer
, id
);
736 static enum record_type
get_attr_text_record_type( const WS_XML_TEXT
*text
, BOOL use_dict
)
738 if (!text
) return RECORD_CHARS8_TEXT
;
739 switch (text
->textType
)
741 case WS_XML_TEXT_TYPE_UTF8
:
743 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
744 if (use_dict
) return RECORD_DICTIONARY_TEXT
;
745 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT
;
746 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT
;
747 return RECORD_CHARS32_TEXT
;
749 case WS_XML_TEXT_TYPE_UTF16
:
751 const WS_XML_UTF16_TEXT
*text_utf16
= (const WS_XML_UTF16_TEXT
*)text
;
752 int len
= text_utf16
->byteCount
/ sizeof(WCHAR
);
753 int len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)text_utf16
->bytes
, len
, NULL
, 0, NULL
, NULL
);
754 if (len_utf8
<= MAX_UINT8
) return RECORD_CHARS8_TEXT
;
755 if (len_utf8
<= MAX_UINT16
) return RECORD_CHARS16_TEXT
;
756 return RECORD_CHARS32_TEXT
;
758 case WS_XML_TEXT_TYPE_BASE64
:
760 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
761 if (text_base64
->length
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
762 if (text_base64
->length
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
763 return RECORD_BYTES32_TEXT
;
765 case WS_XML_TEXT_TYPE_BOOL
:
767 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
768 return text_bool
->value
? RECORD_TRUE_TEXT
: RECORD_FALSE_TEXT
;
770 case WS_XML_TEXT_TYPE_INT32
:
772 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
773 if (!text_int32
->value
) return RECORD_ZERO_TEXT
;
774 if (text_int32
->value
== 1) return RECORD_ONE_TEXT
;
775 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
776 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
777 return RECORD_INT32_TEXT
;
779 case WS_XML_TEXT_TYPE_INT64
:
781 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
782 if (!text_int64
->value
) return RECORD_ZERO_TEXT
;
783 if (text_int64
->value
== 1) return RECORD_ONE_TEXT
;
784 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
785 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
786 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
787 return RECORD_INT64_TEXT
;
789 case WS_XML_TEXT_TYPE_UINT64
:
791 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
792 if (!text_uint64
->value
) return RECORD_ZERO_TEXT
;
793 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT
;
794 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
795 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
796 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
797 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT
;
798 return RECORD_UINT64_TEXT
;
800 case WS_XML_TEXT_TYPE_DOUBLE
:
802 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
803 if (!text_double
->value
) return RECORD_ZERO_TEXT
;
804 if (text_double
->value
== 1) return RECORD_ONE_TEXT
;
805 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
806 return RECORD_DOUBLE_TEXT
;
807 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
808 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
809 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
810 return RECORD_INT64_TEXT
;
812 case WS_XML_TEXT_TYPE_GUID
:
813 return RECORD_GUID_TEXT
;
815 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
816 return RECORD_UNIQUE_ID_TEXT
;
818 case WS_XML_TEXT_TYPE_DATETIME
:
819 return RECORD_DATETIME_TEXT
;
822 FIXME( "unhandled text type %u\n", text
->textType
);
827 static INT64
get_text_value_int( const WS_XML_TEXT
*text
)
829 switch (text
->textType
)
831 case WS_XML_TEXT_TYPE_INT32
:
833 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
834 return text_int32
->value
;
836 case WS_XML_TEXT_TYPE_INT64
:
838 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
839 return text_int64
->value
;
841 case WS_XML_TEXT_TYPE_UINT64
:
843 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
844 return text_uint64
->value
;
846 case WS_XML_TEXT_TYPE_DOUBLE
:
848 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
849 return text_double
->value
;
852 ERR( "unhandled text type %u\n", text
->textType
);
858 static BOOL
get_string_id( struct writer
*writer
, const WS_XML_STRING
*str
, ULONG
*id
)
860 if (writer
->dict
&& str
->dictionary
== writer
->dict
)
868 writer
->dict_cb( writer
->dict_cb_state
, str
, &found
, id
, NULL
);
869 if (found
) *id
= (*id
<< 1) | 1;
875 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
877 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
880 memcpy( buf
, bool_true
, sizeof(bool_true
) );
881 return sizeof(bool_true
);
883 memcpy( buf
, bool_false
, sizeof(bool_false
) );
884 return sizeof(bool_false
);
887 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
889 return wsprintfA( (char *)buf
, "%d", *ptr
);
892 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
894 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
897 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
899 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
902 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
904 static const double precision
= 0.0000000000000001;
905 unsigned char *p
= buf
;
907 int neg
, mag
, mag2
, use_exp
;
911 memcpy( buf
, "NaN", 3 );
918 memcpy( buf
, "-INF", 4 );
921 memcpy( buf
, "INF", 3 );
937 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
940 if (mag
< 0) mag
-= 1;
941 val
= val
/ pow( 10.0, mag
);
945 else if (mag
< 1) mag
= 0;
947 while (val
> precision
|| mag
>= 0)
949 double weight
= pow( 10.0, mag
);
950 if (weight
> 0 && !isinf( weight
))
952 int digit
= floor( val
/ weight
);
953 val
-= digit
* weight
;
954 *(p
++) = '0' + digit
;
956 if (!mag
&& val
> precision
) *(p
++) = '.';
964 if (mag2
> 0) *(p
++) = '+';
973 *(p
++) = '0' + mag2
% 10;
977 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
988 static inline int year_size( int year
)
990 return leap_year( year
) ? 366 : 365;
994 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
996 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
997 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
998 unsigned __int64 ticks
, day_ticks
;
1001 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
1002 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
1004 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1005 tz_hour
= TZ_OFFSET
;
1012 day
= ticks
/ TICKS_PER_DAY
;
1013 day_ticks
= ticks
% TICKS_PER_DAY
;
1014 hour
= day_ticks
/ TICKS_PER_HOUR
;
1015 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1016 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1017 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1019 while (day
>= year_size( year
))
1021 day
-= year_size( year
);
1024 while (day
>= month_days
[leap_year( year
)][month
])
1026 day
-= month_days
[leap_year( year
)][month
];
1030 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
1033 static const char fmt_frac
[] = ".%07u";
1034 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
1035 while (buf
[len
- 1] == '0') len
--;
1037 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
1041 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
1043 static const char fmt_tz
[] = "%c%02u:00";
1044 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
1050 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1052 static const char fmt
[] = "%08x-%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_urn( const GUID
*ptr
, unsigned char *buf
)
1060 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1061 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1062 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1063 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1066 static ULONG
format_qname( const WS_XML_STRING
*prefix
, const WS_XML_STRING
*localname
, unsigned char *buf
)
1069 if (prefix
&& prefix
->length
)
1071 memcpy( buf
, prefix
->bytes
, prefix
->length
);
1072 len
+= prefix
->length
;
1075 memcpy( buf
+ len
, localname
->bytes
, localname
->length
);
1076 return len
+ localname
->length
;
1079 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
1081 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1086 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
1087 x
= (bin
[0] & 3) << 4;
1090 buf
[i
++] = base64
[x
];
1095 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
1096 x
= (bin
[1] & 0x0f) << 2;
1099 buf
[i
++] = base64
[x
];
1103 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
1104 buf
[i
++] = base64
[bin
[2] & 0x3f];
1111 HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, ULONG
*offset
,
1112 WS_XML_UTF8_TEXT
**ret
)
1114 ULONG len_old
= old
? old
->value
.length
: 0;
1115 if (offset
) *offset
= len_old
;
1117 switch (text
->textType
)
1119 case WS_XML_TEXT_TYPE_UTF8
:
1121 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1123 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
1124 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1125 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
1128 case WS_XML_TEXT_TYPE_UTF16
:
1130 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1131 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1132 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1134 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1135 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1136 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
1137 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1138 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
1141 case WS_XML_TEXT_TYPE_BASE64
:
1143 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
1144 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
1146 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1147 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1148 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1151 case WS_XML_TEXT_TYPE_BOOL
:
1153 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1155 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
1156 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1157 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1160 case WS_XML_TEXT_TYPE_INT32
:
1162 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1163 unsigned char buf
[12]; /* "-2147483648" */
1164 ULONG len
= format_int32( &int32_text
->value
, buf
);
1166 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1167 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1168 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1171 case WS_XML_TEXT_TYPE_INT64
:
1173 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1174 unsigned char buf
[21]; /* "-9223372036854775808" */
1175 ULONG len
= format_int64( &int64_text
->value
, buf
);
1177 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1178 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1179 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1182 case WS_XML_TEXT_TYPE_UINT64
:
1184 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1185 unsigned char buf
[21]; /* "18446744073709551615" */
1186 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1188 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1189 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1190 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1193 case WS_XML_TEXT_TYPE_DOUBLE
:
1195 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1196 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
1197 unsigned int fpword
= _control87( 0, 0 );
1200 _control87( _MCW_EM
| _RC_NEAR
| _PC_64
, _MCW_EM
| _MCW_RC
| _MCW_PC
);
1201 len
= format_double( &double_text
->value
, buf
);
1202 _control87( fpword
, _MCW_EM
| _MCW_RC
| _MCW_PC
);
1203 if (!len
) return E_NOTIMPL
;
1205 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1206 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1207 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1210 case WS_XML_TEXT_TYPE_GUID
:
1212 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1214 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
1215 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1216 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1219 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1221 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1223 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
1224 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1225 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1228 case WS_XML_TEXT_TYPE_DATETIME
:
1230 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
1232 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
1233 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1234 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1237 case WS_XML_TEXT_TYPE_QNAME
:
1239 const WS_XML_QNAME_TEXT
*qn
= (const WS_XML_QNAME_TEXT
*)text
;
1240 ULONG len
= qn
->localName
->length
;
1242 if (qn
->prefix
&& qn
->prefix
->length
) len
+= qn
->prefix
->length
+ 1;
1243 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1244 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1245 (*ret
)->value
.length
= format_qname( qn
->prefix
, qn
->localName
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1249 FIXME( "unhandled text type %u\n", text
->textType
);
1254 static HRESULT
write_attribute_value_bin( struct writer
*writer
, const WS_XML_TEXT
*text
)
1256 enum record_type type
;
1257 BOOL use_dict
= FALSE
;
1261 if (text
&& text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
1263 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1264 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
1266 type
= get_attr_text_record_type( text
, use_dict
);
1268 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1269 write_char( writer
, type
);
1273 case RECORD_CHARS8_TEXT
:
1275 const WS_XML_UTF8_TEXT
*text_utf8
;
1276 WS_XML_UTF8_TEXT
*new = NULL
;
1281 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1282 write_char( writer
, 0 );
1285 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1288 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
1291 len
= text_utf8
->value
.length
;
1292 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
)
1297 write_char( writer
, len
);
1298 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
1302 case RECORD_CHARS16_TEXT
:
1304 const WS_XML_UTF8_TEXT
*text_utf8
;
1305 WS_XML_UTF8_TEXT
*new = NULL
;
1308 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1311 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
1314 len
= text_utf8
->value
.length
;
1315 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
)
1320 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
1321 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
1325 case RECORD_BYTES8_TEXT
:
1327 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
1328 if ((hr
= write_grow_buffer( writer
, 1 + text_base64
->length
)) != S_OK
) return hr
;
1329 write_char( writer
, text_base64
->length
);
1330 write_bytes( writer
, text_base64
->bytes
, text_base64
->length
);
1333 case RECORD_BYTES16_TEXT
:
1335 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
1336 UINT16 len
= text_base64
->length
;
1337 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
1338 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
1339 write_bytes( writer
, text_base64
->bytes
, len
);
1342 case RECORD_ZERO_TEXT
:
1343 case RECORD_ONE_TEXT
:
1344 case RECORD_FALSE_TEXT
:
1345 case RECORD_TRUE_TEXT
:
1348 case RECORD_INT8_TEXT
:
1350 INT8 val
= get_text_value_int( text
);
1351 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1352 write_char( writer
, val
);
1355 case RECORD_INT16_TEXT
:
1357 INT16 val
= get_text_value_int( text
);
1358 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1359 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1362 case RECORD_INT32_TEXT
:
1364 INT32 val
= get_text_value_int( text
);
1365 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1366 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1369 case RECORD_INT64_TEXT
:
1371 INT64 val
= get_text_value_int( text
);
1372 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1373 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1376 case RECORD_UINT64_TEXT
:
1378 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
1379 if ((hr
= write_grow_buffer( writer
, sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
1380 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
1383 case RECORD_DOUBLE_TEXT
:
1385 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
1386 if ((hr
= write_grow_buffer( writer
, sizeof(text_double
->value
) )) != S_OK
) return hr
;
1387 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
1390 case RECORD_GUID_TEXT
:
1392 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
1393 if ((hr
= write_grow_buffer( writer
, sizeof(text_guid
->value
) )) != S_OK
) return hr
;
1394 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
1397 case RECORD_UNIQUE_ID_TEXT
:
1399 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
1400 if ((hr
= write_grow_buffer( writer
, sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
1401 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
1404 case RECORD_DATETIME_TEXT
:
1406 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
1407 UINT64 val
= text_datetime
->value
.ticks
;
1409 assert( val
<= TICKS_MAX
);
1410 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
1411 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
1413 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1414 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1418 FIXME( "unhandled record type %02x\n", type
);
1423 static enum record_type
get_attr_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1425 if (!attr
->prefix
|| !attr
->prefix
->length
)
1427 if (use_dict
) return RECORD_SHORT_DICTIONARY_ATTRIBUTE
;
1428 return RECORD_SHORT_ATTRIBUTE
;
1430 if (attr
->prefix
->length
== 1 && attr
->prefix
->bytes
[0] >= 'a' && attr
->prefix
->bytes
[0] <= 'z')
1432 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
1433 return RECORD_PREFIX_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
1435 if (use_dict
) return RECORD_DICTIONARY_ATTRIBUTE
;
1436 return RECORD_ATTRIBUTE
;
1439 static HRESULT
write_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1442 enum record_type type
= get_attr_record_type( attr
, get_string_id(writer
, attr
->localName
, &id
) );
1445 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1446 write_char( writer
, type
);
1448 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1450 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1451 return write_attribute_value_bin( writer
, attr
->value
);
1453 if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1455 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1456 return write_attribute_value_bin( writer
, attr
->value
);
1461 case RECORD_SHORT_ATTRIBUTE
:
1462 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1465 case RECORD_ATTRIBUTE
:
1466 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1467 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1470 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1471 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1474 case RECORD_DICTIONARY_ATTRIBUTE
:
1475 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1476 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1480 ERR( "unhandled record type %02x\n", type
);
1481 return WS_E_NOT_SUPPORTED
;
1484 return write_attribute_value_bin( writer
, attr
->value
);
1487 static HRESULT
write_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1489 switch (writer
->output_enc
)
1491 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_attribute_text( writer
, attr
);
1492 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_attribute_bin( writer
, attr
);
1494 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1495 return WS_E_NOT_SUPPORTED
;
1499 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1501 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
1504 /**************************************************************************
1505 * WsGetPrefixFromNamespace [webservices.@]
1507 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
1508 BOOL required
, const WS_XML_STRING
**prefix
,
1511 struct writer
*writer
= (struct writer
*)handle
;
1512 WS_XML_ELEMENT_NODE
*elem
;
1516 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
1517 if (error
) FIXME( "ignoring error parameter\n" );
1519 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
1521 EnterCriticalSection( &writer
->cs
);
1523 if (writer
->magic
!= WRITER_MAGIC
)
1525 LeaveCriticalSection( &writer
->cs
);
1526 return E_INVALIDARG
;
1529 elem
= &writer
->current
->hdr
;
1530 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
1532 *prefix
= elem
->prefix
;
1538 if (required
) hr
= WS_E_INVALID_FORMAT
;
1546 LeaveCriticalSection( &writer
->cs
);
1547 TRACE( "returning %08x\n", hr
);
1551 static HRESULT
write_namespace_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1553 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
1557 /* ' xmlns:prefix="namespace"' */
1559 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
1560 if (attr
->prefix
&& attr
->prefix
->length
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
1561 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1563 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
1564 if (attr
->prefix
&& attr
->prefix
->length
)
1566 write_char( writer
, ':' );
1567 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
1569 write_char( writer
, '=' );
1570 write_char( writer
, quote
);
1571 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1572 write_char( writer
, quote
);
1577 static enum record_type
get_xmlns_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1579 if (!attr
->prefix
|| !attr
->prefix
->length
)
1581 if (use_dict
) return RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
;
1582 return RECORD_SHORT_XMLNS_ATTRIBUTE
;
1584 if (use_dict
) return RECORD_DICTIONARY_XMLNS_ATTRIBUTE
;
1585 return RECORD_XMLNS_ATTRIBUTE
;
1588 static HRESULT
write_namespace_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1591 enum record_type type
= get_xmlns_record_type( attr
, get_string_id(writer
, attr
->ns
, &id
) );
1594 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1595 write_char( writer
, type
);
1599 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1602 case RECORD_XMLNS_ATTRIBUTE
:
1603 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1606 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1607 return write_dict_string( writer
, id
);
1609 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1610 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1611 return write_dict_string( writer
, id
);
1614 ERR( "unhandled record type %02x\n", type
);
1615 return WS_E_NOT_SUPPORTED
;
1618 return write_string( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1621 static HRESULT
write_namespace_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1623 switch (writer
->output_enc
)
1625 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_namespace_attribute_text( writer
, attr
);
1626 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_namespace_attribute_bin( writer
, attr
);
1628 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1629 return WS_E_NOT_SUPPORTED
;
1633 static HRESULT
add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1634 const WS_XML_STRING
*ns
, BOOL single
)
1636 WS_XML_ATTRIBUTE
*attr
;
1637 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1640 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1642 attr
->singleQuote
= !!single
;
1644 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
1646 free_attribute( attr
);
1647 return E_OUTOFMEMORY
;
1649 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
1651 free_attribute( attr
);
1652 return E_OUTOFMEMORY
;
1654 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1656 free_attribute( attr
);
1662 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
1664 if (!str1
&& !str2
) return TRUE
;
1665 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
1668 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
1669 const WS_XML_STRING
*ns
)
1672 const struct node
*node
;
1674 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
1676 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
1679 for (i
= 0; i
< elem
->attributeCount
; i
++)
1681 if (!elem
->attributes
[i
]->isXmlNs
) continue;
1682 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
1683 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
1689 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1692 if (!(str
= dup_xml_string( ns
, writer
->dict_do_lookup
))) return E_OUTOFMEMORY
;
1693 free_xml_string( writer
->current_ns
);
1694 writer
->current_ns
= str
;
1698 static HRESULT
set_namespaces( struct writer
*writer
)
1700 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1704 if (elem
->ns
->length
&& !namespace_in_scope( elem
, elem
->prefix
, elem
->ns
))
1706 if ((hr
= add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
) return hr
;
1707 if ((hr
= set_current_namespace( writer
, elem
->ns
)) != S_OK
) return hr
;
1710 for (i
= 0; i
< elem
->attributeCount
; i
++)
1712 const WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1713 if (!attr
->ns
->length
|| namespace_in_scope( elem
, attr
->prefix
, attr
->ns
)) continue;
1714 if ((hr
= add_namespace_attribute( writer
, attr
->prefix
, attr
->ns
, FALSE
)) != S_OK
) return hr
;
1720 /**************************************************************************
1721 * WsWriteEndAttribute [webservices.@]
1723 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1725 struct writer
*writer
= (struct writer
*)handle
;
1728 TRACE( "%p %p\n", handle
, error
);
1729 if (error
) FIXME( "ignoring error parameter\n" );
1731 if (!writer
) return E_INVALIDARG
;
1733 EnterCriticalSection( &writer
->cs
);
1735 if (writer
->magic
!= WRITER_MAGIC
)
1737 LeaveCriticalSection( &writer
->cs
);
1738 return E_INVALIDARG
;
1741 writer
->state
= WRITER_STATE_STARTELEMENT
;
1743 LeaveCriticalSection( &writer
->cs
);
1744 TRACE( "returning %08x\n", hr
);
1748 static HRESULT
write_attributes( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1752 for (i
= 0; i
< elem
->attributeCount
; i
++)
1754 if (elem
->attributes
[i
]->isXmlNs
) continue;
1755 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1757 for (i
= 0; i
< elem
->attributeCount
; i
++)
1759 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
1760 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1762 for (i
= 0; i
< elem
->attributeCount
; i
++)
1764 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
1765 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1770 static HRESULT
write_startelement_text( struct writer
*writer
)
1772 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1776 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
1778 size
= elem
->localName
->length
+ 1 /* '<' */;
1779 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1780 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1782 write_char( writer
, '<' );
1783 if (elem
->prefix
&& elem
->prefix
->length
)
1785 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1786 write_char( writer
, ':' );
1788 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1789 return write_attributes( writer
, elem
);
1792 static enum record_type
get_elem_record_type( const WS_XML_ELEMENT_NODE
*elem
, BOOL use_dict
)
1794 if (!elem
->prefix
|| !elem
->prefix
->length
)
1796 if (use_dict
) return RECORD_SHORT_DICTIONARY_ELEMENT
;
1797 return RECORD_SHORT_ELEMENT
;
1799 if (elem
->prefix
->length
== 1 && elem
->prefix
->bytes
[0] >= 'a' && elem
->prefix
->bytes
[0] <= 'z')
1801 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1802 return RECORD_PREFIX_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1804 if (use_dict
) return RECORD_DICTIONARY_ELEMENT
;
1805 return RECORD_ELEMENT
;
1808 static HRESULT
write_startelement_bin( struct writer
*writer
)
1810 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1812 enum record_type type
= get_elem_record_type( elem
, get_string_id(writer
, elem
->localName
, &id
) );
1815 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1816 write_char( writer
, type
);
1818 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1820 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1821 return write_attributes( writer
, elem
);
1823 if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1825 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1826 return write_attributes( writer
, elem
);
1831 case RECORD_SHORT_ELEMENT
:
1832 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1835 case RECORD_ELEMENT
:
1836 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1837 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1840 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1841 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1844 case RECORD_DICTIONARY_ELEMENT
:
1845 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1846 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1850 ERR( "unhandled record type %02x\n", type
);
1851 return WS_E_NOT_SUPPORTED
;
1854 return write_attributes( writer
, elem
);
1857 static HRESULT
write_startelement( struct writer
*writer
)
1859 switch (writer
->output_enc
)
1861 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_startelement_text( writer
);
1862 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_startelement_bin( writer
);
1864 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1865 return WS_E_NOT_SUPPORTED
;
1869 static struct node
*write_find_startelement( struct writer
*writer
)
1872 for (node
= writer
->current
; node
; node
= node
->parent
)
1874 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
1879 static inline BOOL
is_empty_element( const struct node
*node
)
1881 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
1882 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
1885 static HRESULT
write_endelement_text( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1892 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
1894 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1895 write_char( writer
, '/' );
1896 write_char( writer
, '>' );
1900 /* '</prefix:localname>' */
1902 size
= elem
->localName
->length
+ 3 /* '</>' */;
1903 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1904 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1906 write_char( writer
, '<' );
1907 write_char( writer
, '/' );
1908 if (elem
->prefix
&& elem
->prefix
->length
)
1910 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1911 write_char( writer
, ':' );
1913 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1914 write_char( writer
, '>' );
1918 static HRESULT
write_endelement_bin( struct writer
*writer
)
1921 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_TEXT
) return S_OK
;
1922 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1923 write_char( writer
, RECORD_ENDELEMENT
);
1927 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1929 switch (writer
->output_enc
)
1931 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endelement_text( writer
, elem
);
1932 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_endelement_bin( writer
);
1934 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1935 return WS_E_NOT_SUPPORTED
;
1939 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
1941 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
1942 elem
->isEmpty
= is_empty_element( node
);
1943 return write_endelement( writer
, elem
);
1946 static HRESULT
write_endelement_node( struct writer
*writer
)
1951 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
1952 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1954 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1955 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1957 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
1958 writer
->current
= node
->parent
;
1959 writer
->state
= WRITER_STATE_ENDELEMENT
;
1963 /**************************************************************************
1964 * WsWriteEndElement [webservices.@]
1966 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1968 struct writer
*writer
= (struct writer
*)handle
;
1971 TRACE( "%p %p\n", handle
, error
);
1972 if (error
) FIXME( "ignoring error parameter\n" );
1974 if (!writer
) return E_INVALIDARG
;
1976 EnterCriticalSection( &writer
->cs
);
1978 if (writer
->magic
!= WRITER_MAGIC
)
1980 LeaveCriticalSection( &writer
->cs
);
1981 return E_INVALIDARG
;
1984 hr
= write_endelement_node( writer
);
1986 LeaveCriticalSection( &writer
->cs
);
1987 TRACE( "returning %08x\n", hr
);
1991 static HRESULT
write_endstartelement_text( struct writer
*writer
)
1994 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1995 write_char( writer
, '>' );
1999 static HRESULT
write_endstartelement( struct writer
*writer
)
2001 switch (writer
->output_enc
)
2003 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endstartelement_text( writer
);
2004 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return S_OK
;
2006 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2007 return WS_E_NOT_SUPPORTED
;
2011 /**************************************************************************
2012 * WsWriteEndStartElement [webservices.@]
2014 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2016 struct writer
*writer
= (struct writer
*)handle
;
2019 TRACE( "%p %p\n", handle
, error
);
2020 if (error
) FIXME( "ignoring error parameter\n" );
2022 if (!writer
) return E_INVALIDARG
;
2024 EnterCriticalSection( &writer
->cs
);
2026 if (writer
->magic
!= WRITER_MAGIC
)
2028 LeaveCriticalSection( &writer
->cs
);
2029 return E_INVALIDARG
;
2032 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_OPERATION
;
2035 if ((hr
= set_namespaces( writer
)) != S_OK
) goto done
;
2036 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
2037 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
2038 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
2042 LeaveCriticalSection( &writer
->cs
);
2043 TRACE( "returning %08x\n", hr
);
2047 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2048 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2051 WS_XML_ATTRIBUTE
*attr
;
2052 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2055 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
2057 if (!prefix
&& ns
->length
) prefix
= elem
->prefix
;
2059 attr
->singleQuote
= !!single
;
2060 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
2062 free_attribute( attr
);
2063 return E_OUTOFMEMORY
;
2065 if (!(attr
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
2067 free_attribute( attr
);
2068 return E_OUTOFMEMORY
;
2070 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
2072 free_attribute( attr
);
2073 return E_OUTOFMEMORY
;
2075 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
2077 free_attribute( attr
);
2083 /**************************************************************************
2084 * WsWriteStartAttribute [webservices.@]
2086 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2087 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2088 BOOL single
, WS_ERROR
*error
)
2090 struct writer
*writer
= (struct writer
*)handle
;
2093 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
2094 debugstr_xmlstr(ns
), single
, error
);
2095 if (error
) FIXME( "ignoring error parameter\n" );
2097 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
2099 EnterCriticalSection( &writer
->cs
);
2101 if (writer
->magic
!= WRITER_MAGIC
)
2103 LeaveCriticalSection( &writer
->cs
);
2104 return E_INVALIDARG
;
2107 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_OPERATION
;
2108 else if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
2109 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2111 LeaveCriticalSection( &writer
->cs
);
2112 TRACE( "returning %08x\n", hr
);
2116 /* flush current start element if necessary */
2117 static HRESULT
write_commit( struct writer
*writer
)
2119 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
2122 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
2123 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
2124 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
2125 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
2130 static HRESULT
write_add_cdata_node( struct writer
*writer
)
2132 struct node
*node
, *parent
;
2133 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2134 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2135 write_insert_node( writer
, parent
, node
);
2139 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
2142 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
2143 node
->parent
= writer
->current
;
2144 list_add_tail( &node
->parent
->children
, &node
->entry
);
2148 static HRESULT
write_cdata( struct writer
*writer
)
2151 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
2152 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
2156 static HRESULT
write_cdata_node( struct writer
*writer
)
2159 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
2160 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
2161 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
2162 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
2163 writer
->state
= WRITER_STATE_STARTCDATA
;
2167 /**************************************************************************
2168 * WsWriteStartCData [webservices.@]
2170 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2172 struct writer
*writer
= (struct writer
*)handle
;
2175 TRACE( "%p %p\n", handle
, error
);
2176 if (error
) FIXME( "ignoring error parameter\n" );
2178 if (!writer
) return E_INVALIDARG
;
2180 EnterCriticalSection( &writer
->cs
);
2182 if (writer
->magic
!= WRITER_MAGIC
)
2184 LeaveCriticalSection( &writer
->cs
);
2185 return E_INVALIDARG
;
2188 hr
= write_cdata_node( writer
);
2190 LeaveCriticalSection( &writer
->cs
);
2191 TRACE( "returning %08x\n", hr
);
2195 static HRESULT
write_endcdata( struct writer
*writer
)
2198 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2199 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
2203 static HRESULT
write_endcdata_node( struct writer
*writer
)
2206 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
2207 writer
->current
= writer
->current
->parent
;
2208 writer
->state
= WRITER_STATE_ENDCDATA
;
2212 /**************************************************************************
2213 * WsWriteEndCData [webservices.@]
2215 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2217 struct writer
*writer
= (struct writer
*)handle
;
2220 TRACE( "%p %p\n", handle
, error
);
2221 if (error
) FIXME( "ignoring error parameter\n" );
2223 if (!writer
) return E_INVALIDARG
;
2225 EnterCriticalSection( &writer
->cs
);
2227 if (writer
->magic
!= WRITER_MAGIC
)
2229 LeaveCriticalSection( &writer
->cs
);
2230 return E_INVALIDARG
;
2233 if (writer
->state
!= WRITER_STATE_TEXT
) hr
= WS_E_INVALID_OPERATION
;
2234 else hr
= write_endcdata_node( writer
);
2236 LeaveCriticalSection( &writer
->cs
);
2237 TRACE( "returning %08x\n", hr
);
2241 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2242 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
2244 struct node
*node
, *parent
;
2245 WS_XML_ELEMENT_NODE
*elem
;
2247 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2249 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2251 elem
= &parent
->hdr
;
2252 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
2255 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
2258 if (prefix
&& !(elem
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
2261 return E_OUTOFMEMORY
;
2263 if (!(elem
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
2266 return E_OUTOFMEMORY
;
2268 if (!(elem
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
2271 return E_OUTOFMEMORY
;
2273 write_insert_node( writer
, parent
, node
);
2277 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
2280 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
2281 node
->parent
= parent
;
2282 list_add_tail( &parent
->children
, &node
->entry
);
2286 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2287 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
2290 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
2291 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
2292 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
2293 writer
->state
= WRITER_STATE_STARTELEMENT
;
2297 /**************************************************************************
2298 * WsWriteStartElement [webservices.@]
2300 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2301 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2304 struct writer
*writer
= (struct writer
*)handle
;
2307 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
2308 debugstr_xmlstr(ns
), error
);
2309 if (error
) FIXME( "ignoring error parameter\n" );
2311 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
2313 EnterCriticalSection( &writer
->cs
);
2315 if (writer
->magic
!= WRITER_MAGIC
)
2317 LeaveCriticalSection( &writer
->cs
);
2318 return E_INVALIDARG
;
2321 hr
= write_element_node( writer
, prefix
, localname
, ns
);
2323 LeaveCriticalSection( &writer
->cs
);
2324 TRACE( "returning %08x\n", hr
);
2328 HRESULT
text_to_text( const WS_XML_TEXT
*text
, const WS_XML_TEXT
*old
, ULONG
*offset
, WS_XML_TEXT
**ret
)
2330 if (offset
) *offset
= 0;
2331 switch (text
->textType
)
2333 case WS_XML_TEXT_TYPE_UTF8
:
2335 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2336 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2337 WS_XML_UTF8_TEXT
*new;
2338 ULONG len
= utf8
->value
.length
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2340 if (!(new = alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2341 if (utf8_old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2342 memcpy( new->value
.bytes
+ len_old
, utf8
->value
.bytes
, len
);
2343 if (offset
) *offset
= len_old
;
2347 case WS_XML_TEXT_TYPE_UTF16
:
2349 const WS_XML_UTF16_TEXT
*utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2350 const WS_XML_UTF16_TEXT
*utf16_old
= (const WS_XML_UTF16_TEXT
*)old
;
2351 WS_XML_UTF16_TEXT
*new;
2352 ULONG len
= utf16
->byteCount
, len_old
= utf16_old
? utf16_old
->byteCount
: 0;
2354 if (utf16
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2355 if (!(new = alloc_utf16_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2356 if (utf16_old
) memcpy( new->bytes
, utf16_old
->bytes
, len_old
);
2357 memcpy( new->bytes
+ len_old
, utf16
->bytes
, len
);
2358 if (offset
) *offset
= len_old
;
2362 case WS_XML_TEXT_TYPE_BASE64
:
2364 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2365 const WS_XML_BASE64_TEXT
*base64_old
= (const WS_XML_BASE64_TEXT
*)old
;
2366 WS_XML_BASE64_TEXT
*new;
2367 ULONG len
= base64
->length
, len_old
= base64_old
? base64_old
->length
: 0;
2369 if (!(new = alloc_base64_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2370 if (base64_old
) memcpy( new->bytes
, base64_old
->bytes
, len_old
);
2371 memcpy( new->bytes
+ len_old
, base64
->bytes
, len
);
2372 if (offset
) *offset
= len_old
;
2376 case WS_XML_TEXT_TYPE_BOOL
:
2378 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2379 WS_XML_BOOL_TEXT
*new;
2381 if (!(new = alloc_bool_text( bool_text
->value
))) return E_OUTOFMEMORY
;
2385 case WS_XML_TEXT_TYPE_INT32
:
2387 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2388 WS_XML_INT32_TEXT
*new;
2390 if (!(new = alloc_int32_text( int32_text
->value
))) return E_OUTOFMEMORY
;
2394 case WS_XML_TEXT_TYPE_INT64
:
2396 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2397 WS_XML_INT64_TEXT
*new;
2399 if (!(new = alloc_int64_text( int64_text
->value
))) return E_OUTOFMEMORY
;
2403 case WS_XML_TEXT_TYPE_UINT64
:
2405 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2406 WS_XML_UINT64_TEXT
*new;
2408 if (!(new = alloc_uint64_text( uint64_text
->value
))) return E_OUTOFMEMORY
;
2412 case WS_XML_TEXT_TYPE_DOUBLE
:
2414 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2415 WS_XML_DOUBLE_TEXT
*new;
2417 if (!(new = alloc_double_text( double_text
->value
))) return E_OUTOFMEMORY
;
2421 case WS_XML_TEXT_TYPE_GUID
:
2423 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2424 WS_XML_GUID_TEXT
*new;
2426 if (!(new = alloc_guid_text( &id
->value
))) return E_OUTOFMEMORY
;
2430 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2432 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2433 WS_XML_UNIQUE_ID_TEXT
*new;
2435 if (!(new = alloc_unique_id_text( &id
->value
))) return E_OUTOFMEMORY
;
2439 case WS_XML_TEXT_TYPE_DATETIME
:
2441 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2442 WS_XML_DATETIME_TEXT
*new;
2444 if (!(new = alloc_datetime_text( &dt
->value
))) return E_OUTOFMEMORY
;
2449 FIXME( "unhandled text type %u\n", text
->textType
);
2454 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
2456 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2459 switch (value
->textType
)
2461 case WS_XML_TEXT_TYPE_UTF8
:
2462 case WS_XML_TEXT_TYPE_UTF16
:
2463 case WS_XML_TEXT_TYPE_BASE64
:
2466 case WS_XML_TEXT_TYPE_BOOL
:
2467 case WS_XML_TEXT_TYPE_INT32
:
2468 case WS_XML_TEXT_TYPE_INT64
:
2469 case WS_XML_TEXT_TYPE_UINT64
:
2470 case WS_XML_TEXT_TYPE_DOUBLE
:
2471 case WS_XML_TEXT_TYPE_GUID
:
2472 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2473 case WS_XML_TEXT_TYPE_DATETIME
:
2474 if (elem
->attributes
[elem
->attributeCount
- 1]->value
) return WS_E_INVALID_OPERATION
;
2478 FIXME( "unhandled text type %u\n", value
->textType
);
2482 switch (writer
->output_enc
)
2484 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2486 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
2487 if ((hr
= text_to_utf8text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2489 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
2492 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2494 WS_XML_TEXT
*new, *old
= elem
->attributes
[elem
->attributeCount
- 1]->value
;
2495 if ((hr
= text_to_text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2497 elem
->attributes
[elem
->attributeCount
- 1]->value
= new;
2501 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2508 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
2511 WS_XML_TEXT_NODE
*text
;
2514 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
2515 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
2516 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
2518 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2519 text
= (WS_XML_TEXT_NODE
*)node
;
2521 switch (writer
->output_enc
)
2523 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2525 WS_XML_UTF8_TEXT
*new;
2526 if ((hr
= text_to_utf8text( value
, NULL
, NULL
, &new )) != S_OK
)
2531 text
->text
= &new->text
;
2534 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2537 if ((hr
= text_to_text( value
, NULL
, NULL
, &new )) != S_OK
)
2546 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2551 write_insert_node( writer
, writer
->current
, node
);
2555 static HRESULT
write_text_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2557 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2560 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2562 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
2563 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
2565 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
2567 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
2568 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
2572 return WS_E_INVALID_FORMAT
;
2575 static enum record_type
get_text_record_type( const WS_XML_TEXT
*text
, BOOL use_dict
)
2577 switch (text
->textType
)
2579 case WS_XML_TEXT_TYPE_UTF8
:
2581 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2582 if (use_dict
) return RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
;
2583 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2584 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2585 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2587 case WS_XML_TEXT_TYPE_UTF16
:
2589 const WS_XML_UTF16_TEXT
*text_utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2590 int len
= text_utf16
->byteCount
/ sizeof(WCHAR
);
2591 int len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)text_utf16
->bytes
, len
, NULL
, 0, NULL
, NULL
);
2592 if (len_utf8
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2593 if (len_utf8
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2594 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2596 case WS_XML_TEXT_TYPE_BASE64
:
2598 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2599 ULONG rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2600 if (len
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
2601 if (len
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
2602 return RECORD_BYTES32_TEXT
;
2604 case WS_XML_TEXT_TYPE_BOOL
:
2606 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
2607 return text_bool
->value
? RECORD_TRUE_TEXT_WITH_ENDELEMENT
: RECORD_FALSE_TEXT_WITH_ENDELEMENT
;
2609 case WS_XML_TEXT_TYPE_INT32
:
2611 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
2612 if (!text_int32
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2613 if (text_int32
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2614 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2615 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2616 return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2618 case WS_XML_TEXT_TYPE_INT64
:
2620 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
2621 if (!text_int64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2622 if (text_int64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2623 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2624 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2625 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2626 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2628 case WS_XML_TEXT_TYPE_UINT64
:
2630 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
2631 if (!text_uint64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2632 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2633 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2634 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2635 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2636 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2637 return RECORD_UINT64_TEXT_WITH_ENDELEMENT
;
2639 case WS_XML_TEXT_TYPE_DOUBLE
:
2641 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
2642 if (!text_double
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2643 if (text_double
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2644 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
2645 return RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
;
2646 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2647 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2648 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2649 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2651 case WS_XML_TEXT_TYPE_GUID
:
2652 return RECORD_GUID_TEXT_WITH_ENDELEMENT
;
2654 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2655 return RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
;
2657 case WS_XML_TEXT_TYPE_DATETIME
:
2658 return RECORD_DATETIME_TEXT_WITH_ENDELEMENT
;
2661 FIXME( "unhandled text type %u\n", text
->textType
);
2666 static HRESULT
write_text_bin( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2668 enum record_type type
;
2669 BOOL use_dict
= FALSE
;
2675 FIXME( "no support for appending text in binary mode\n" );
2679 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
2681 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2682 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
2685 switch ((type
= get_text_record_type( text
, use_dict
)))
2687 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2689 const WS_XML_UTF8_TEXT
*text_utf8
;
2690 WS_XML_UTF8_TEXT
*new = NULL
;
2693 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2696 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
2699 len
= text_utf8
->value
.length
;
2700 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
)
2705 write_char( writer
, type
);
2706 write_char( writer
, len
);
2707 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2711 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2713 const WS_XML_UTF8_TEXT
*text_utf8
;
2714 WS_XML_UTF8_TEXT
*new = NULL
;
2717 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2720 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
2723 len
= text_utf8
->value
.length
;
2724 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
)
2729 write_char( writer
, type
);
2730 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2731 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2735 case RECORD_BYTES8_TEXT
:
2737 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2738 UINT8 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2742 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2743 write_char( writer
, rem
? RECORD_BYTES8_TEXT
: RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2744 write_char( writer
, len
);
2745 write_bytes( writer
, text_base64
->bytes
, len
);
2749 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2750 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2751 write_char( writer
, rem
);
2752 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2756 case RECORD_BYTES16_TEXT
:
2758 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2759 UINT16 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2763 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2764 write_char( writer
, rem
? RECORD_BYTES16_TEXT
: RECORD_BYTES16_TEXT_WITH_ENDELEMENT
);
2765 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2766 write_bytes( writer
, text_base64
->bytes
, len
);
2770 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2771 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2772 write_char( writer
, rem
);
2773 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2777 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2778 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2779 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2780 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2782 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2783 write_char( writer
, type
);
2786 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2788 INT8 val
= get_text_value_int( text
);
2789 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2790 write_char( writer
, type
);
2791 write_char( writer
, val
);
2794 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2796 INT16 val
= get_text_value_int( text
);
2797 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2798 write_char( writer
, type
);
2799 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2802 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2804 INT32 val
= get_text_value_int( text
);
2805 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2806 write_char( writer
, type
);
2807 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2810 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2812 INT64 val
= get_text_value_int( text
);
2813 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2814 write_char( writer
, type
);
2815 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2818 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2820 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
2821 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
2822 write_char( writer
, type
);
2823 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
2826 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2828 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
2829 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_double
->value
) )) != S_OK
) return hr
;
2830 write_char( writer
, type
);
2831 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
2834 case RECORD_GUID_TEXT_WITH_ENDELEMENT
:
2836 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
2837 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_guid
->value
) )) != S_OK
) return hr
;
2838 write_char( writer
, type
);
2839 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
2842 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
:
2844 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
2845 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
2846 write_char( writer
, type
);
2847 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
2850 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2852 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
2853 UINT64 val
= text_datetime
->value
.ticks
;
2855 assert( val
<= TICKS_MAX
);
2856 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
2857 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
2859 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2860 write_char( writer
, type
);
2861 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2864 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2866 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2867 write_char( writer
, type
);
2868 return write_dict_string( writer
, id
);
2871 FIXME( "unhandled record type %02x\n", type
);
2876 static HRESULT
write_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2878 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
2880 switch (writer
->output_enc
)
2882 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_text_text( writer
, text
, offset
);
2883 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_text_bin( writer
, text
, offset
);
2885 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2886 return WS_E_NOT_SUPPORTED
;
2890 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
2892 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2896 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
2897 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
2899 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
2900 node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2904 switch (writer
->output_enc
)
2906 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2908 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
2909 offset
= old
->value
.length
;
2910 if ((hr
= text_to_utf8text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2912 node
->text
= &new->text
;
2915 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2917 WS_XML_TEXT
*new, *old
= node
->text
;
2918 if ((hr
= text_to_text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2924 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2929 if ((hr
= write_text( writer
, node
->text
, offset
)) != S_OK
) return hr
;
2931 writer
->state
= WRITER_STATE_TEXT
;
2935 /**************************************************************************
2936 * WsWriteText [webservices.@]
2938 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
2940 struct writer
*writer
= (struct writer
*)handle
;
2943 TRACE( "%p %p %p\n", handle
, text
, error
);
2944 if (error
) FIXME( "ignoring error parameter\n" );
2946 if (!writer
|| !text
) return E_INVALIDARG
;
2948 EnterCriticalSection( &writer
->cs
);
2950 if (writer
->magic
!= WRITER_MAGIC
)
2952 LeaveCriticalSection( &writer
->cs
);
2953 return E_INVALIDARG
;
2956 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
2957 else hr
= write_text_node( writer
, text
);
2959 LeaveCriticalSection( &writer
->cs
);
2960 TRACE( "returning %08x\n", hr
);
2964 /**************************************************************************
2965 * WsWriteBytes [webservices.@]
2967 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
2969 struct writer
*writer
= (struct writer
*)handle
;
2970 WS_XML_BASE64_TEXT base64
;
2973 TRACE( "%p %p %u %p\n", handle
, bytes
, count
, error
);
2974 if (error
) FIXME( "ignoring error parameter\n" );
2976 if (!writer
) return E_INVALIDARG
;
2978 EnterCriticalSection( &writer
->cs
);
2980 if (writer
->magic
!= WRITER_MAGIC
)
2982 LeaveCriticalSection( &writer
->cs
);
2983 return E_INVALIDARG
;
2986 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
2989 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2990 base64
.bytes
= (BYTE
*)bytes
;
2991 base64
.length
= count
;
2993 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
2994 else hr
= write_text_node( writer
, &base64
.text
);
2997 LeaveCriticalSection( &writer
->cs
);
2998 TRACE( "returning %08x\n", hr
);
3002 /**************************************************************************
3003 * WsWriteChars [webservices.@]
3005 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
3007 struct writer
*writer
= (struct writer
*)handle
;
3008 WS_XML_UTF16_TEXT utf16
;
3011 TRACE( "%p %s %u %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
3012 if (error
) FIXME( "ignoring error parameter\n" );
3014 if (!writer
) return E_INVALIDARG
;
3016 EnterCriticalSection( &writer
->cs
);
3018 if (writer
->magic
!= WRITER_MAGIC
)
3020 LeaveCriticalSection( &writer
->cs
);
3021 return E_INVALIDARG
;
3024 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
3027 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3028 utf16
.bytes
= (BYTE
*)chars
;
3029 utf16
.byteCount
= count
* sizeof(WCHAR
);
3031 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
3032 else hr
= write_text_node( writer
, &utf16
.text
);
3035 LeaveCriticalSection( &writer
->cs
);
3036 TRACE( "returning %08x\n", hr
);
3040 /**************************************************************************
3041 * WsWriteCharsUtf8 [webservices.@]
3043 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
3045 struct writer
*writer
= (struct writer
*)handle
;
3046 WS_XML_UTF8_TEXT utf8
;
3049 TRACE( "%p %s %u %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
3050 if (error
) FIXME( "ignoring error parameter\n" );
3052 if (!writer
) return E_INVALIDARG
;
3054 EnterCriticalSection( &writer
->cs
);
3056 if (writer
->magic
!= WRITER_MAGIC
)
3058 LeaveCriticalSection( &writer
->cs
);
3059 return E_INVALIDARG
;
3062 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
3065 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3066 utf8
.value
.bytes
= (BYTE
*)bytes
;
3067 utf8
.value
.length
= count
;
3069 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
3070 else hr
= write_text_node( writer
, &utf8
.text
);
3073 LeaveCriticalSection( &writer
->cs
);
3074 TRACE( "returning %08x\n", hr
);
3078 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
3082 case WS_ELEMENT_TYPE_MAPPING
:
3083 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3084 return write_text_node( writer
, text
);
3086 case WS_ATTRIBUTE_TYPE_MAPPING
:
3087 return write_set_attribute_value( writer
, text
);
3089 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3090 switch (writer
->state
)
3092 case WRITER_STATE_STARTATTRIBUTE
:
3093 return write_set_attribute_value( writer
, text
);
3095 case WRITER_STATE_STARTELEMENT
:
3096 return write_text_node( writer
, text
);
3099 FIXME( "writer state %u not handled\n", writer
->state
);
3104 FIXME( "mapping %u not implemented\n", mapping
);
3109 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
3111 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
3112 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
3113 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
3114 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
3117 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
3118 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
3119 return add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
3122 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
3127 case WS_WRITE_REQUIRED_VALUE
:
3128 case WS_WRITE_NILLABLE_VALUE
:
3129 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
3133 case WS_WRITE_REQUIRED_POINTER
:
3134 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
3137 case WS_WRITE_NILLABLE_POINTER
:
3138 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
3139 *ptr
= *(const void **)value
;
3143 return E_INVALIDARG
;
3147 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3148 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3149 const BOOL
*value
, ULONG size
)
3151 WS_XML_BOOL_TEXT text_bool
;
3157 FIXME( "description not supported\n" );
3161 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3162 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
3163 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3165 text_bool
.text
.textType
= WS_XML_TEXT_TYPE_BOOL
;
3166 text_bool
.value
= *ptr
;
3167 return write_type_text( writer
, mapping
, &text_bool
.text
);
3170 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3171 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3172 const BOOL
*value
, ULONG size
)
3174 WS_XML_INT32_TEXT text_int32
;
3180 FIXME( "description not supported\n" );
3184 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3185 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3186 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3188 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3189 text_int32
.value
= *ptr
;
3190 return write_type_text( writer
, mapping
, &text_int32
.text
);
3193 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3194 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3195 const BOOL
*value
, ULONG size
)
3197 WS_XML_INT32_TEXT text_int32
;
3203 FIXME( "description not supported\n" );
3207 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3208 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3209 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3211 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3212 text_int32
.value
= *ptr
;
3213 return write_type_text( writer
, mapping
, &text_int32
.text
);
3216 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3217 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3218 const void *value
, ULONG size
)
3220 WS_XML_INT32_TEXT text_int32
;
3226 FIXME( "description not supported\n" );
3230 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3231 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3232 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3234 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3235 text_int32
.value
= *ptr
;
3236 return write_type_text( writer
, mapping
, &text_int32
.text
);
3239 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3240 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3241 const void *value
, ULONG size
)
3243 WS_XML_INT64_TEXT text_int64
;
3249 FIXME( "description not supported\n" );
3253 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3254 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3255 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3257 text_int64
.text
.textType
= WS_XML_TEXT_TYPE_INT64
;
3258 text_int64
.value
= *ptr
;
3259 return write_type_text( writer
, mapping
, &text_int64
.text
);
3262 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3263 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3264 const void *value
, ULONG size
)
3266 WS_XML_UINT64_TEXT text_uint64
;
3272 FIXME( "description not supported\n" );
3276 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3277 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3278 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3280 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3281 text_uint64
.value
= *ptr
;
3282 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3285 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3286 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3287 const void *value
, ULONG size
)
3289 WS_XML_UINT64_TEXT text_uint64
;
3295 FIXME( "description not supported\n" );
3299 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3300 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3301 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3303 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3304 text_uint64
.value
= *ptr
;
3305 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3308 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3309 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3310 const void *value
, ULONG size
)
3312 WS_XML_UINT64_TEXT text_uint64
;
3318 FIXME( "description not supported\n" );
3322 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3323 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3324 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3326 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3327 text_uint64
.value
= *ptr
;
3328 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3331 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3332 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3333 const void *value
, ULONG size
)
3335 WS_XML_UINT64_TEXT text_uint64
;
3341 FIXME( "description not supported\n" );
3345 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3346 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3347 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3349 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3350 text_uint64
.value
= *ptr
;
3351 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3354 static HRESULT
write_type_double( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3355 const WS_DOUBLE_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3356 const void *value
, ULONG size
)
3358 WS_XML_DOUBLE_TEXT text_double
;
3364 FIXME( "description not supported\n" );
3368 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3369 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(double), (const void **)&ptr
)) != S_OK
) return hr
;
3370 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3372 text_double
.text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
3373 text_double
.value
= *ptr
;
3374 return write_type_text( writer
, mapping
, &text_double
.text
);
3377 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3378 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3379 const void *value
, ULONG size
)
3381 WS_XML_DATETIME_TEXT text_datetime
;
3382 const WS_DATETIME
*ptr
;
3387 FIXME( "description not supported\n" );
3391 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3392 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
3393 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3394 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
3396 text_datetime
.text
.textType
= WS_XML_TEXT_TYPE_DATETIME
;
3397 text_datetime
.value
= *ptr
;
3398 return write_type_text( writer
, mapping
, &text_datetime
.text
);
3401 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3402 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3403 const void *value
, ULONG size
)
3405 WS_XML_GUID_TEXT text_guid
;
3411 FIXME( "description not supported\n" );
3415 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3416 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
3417 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3419 text_guid
.text
.textType
= WS_XML_TEXT_TYPE_GUID
;
3420 text_guid
.value
= *ptr
;
3421 return write_type_text( writer
, mapping
, &text_guid
.text
);
3424 static HRESULT
write_type_unique_id( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3425 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3426 const void *value
, ULONG size
)
3428 WS_XML_UNIQUE_ID_TEXT text_unique_id
;
3429 WS_XML_UTF16_TEXT text_utf16
;
3430 const WS_UNIQUE_ID
*ptr
;
3435 FIXME( "description not supported\n" );
3439 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3440 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3441 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3443 if (ptr
->uri
.length
)
3445 text_utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3446 text_utf16
.bytes
= (BYTE
*)ptr
->uri
.chars
;
3447 text_utf16
.byteCount
= ptr
->uri
.length
* sizeof(WCHAR
);
3448 return write_type_text( writer
, mapping
, &text_utf16
.text
);
3451 text_unique_id
.text
.textType
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
3452 text_unique_id
.value
= ptr
->guid
;
3453 return write_type_text( writer
, mapping
, &text_unique_id
.text
);
3456 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3457 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3458 const void *value
, ULONG size
)
3460 WS_XML_UTF16_TEXT utf16
;
3461 const WS_STRING
*ptr
;
3466 FIXME( "description not supported\n" );
3470 if (!option
) return E_INVALIDARG
;
3471 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3472 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3473 if (!ptr
->length
) return S_OK
;
3475 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3476 utf16
.bytes
= (BYTE
*)ptr
->chars
;
3477 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
3478 return write_type_text( writer
, mapping
, &utf16
.text
);
3481 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3482 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3483 const void *value
, ULONG size
)
3485 WS_XML_UTF16_TEXT utf16
;
3492 FIXME( "description not supported\n" );
3496 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3497 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
3498 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3499 if (!(len
= lstrlenW( ptr
))) return S_OK
;
3501 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3502 utf16
.bytes
= (BYTE
*)ptr
;
3503 utf16
.byteCount
= len
* sizeof(WCHAR
);
3504 return write_type_text( writer
, mapping
, &utf16
.text
);
3507 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3508 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3509 const void *value
, ULONG size
)
3511 WS_XML_BASE64_TEXT base64
;
3512 const WS_BYTES
*ptr
;
3517 FIXME( "description not supported\n" );
3521 if (!option
) return E_INVALIDARG
;
3522 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
3523 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
3524 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
3525 if (!ptr
->length
) return S_OK
;
3527 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
3528 base64
.bytes
= ptr
->bytes
;
3529 base64
.length
= ptr
->length
;
3530 return write_type_text( writer
, mapping
, &base64
.text
);
3533 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3534 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3535 const void *value
, ULONG size
)
3537 WS_XML_UTF8_TEXT utf8
;
3538 const WS_XML_STRING
*ptr
;
3543 FIXME( "description not supported\n" );
3547 if (!option
) return E_INVALIDARG
;
3548 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3549 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3550 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3551 if (!ptr
->length
) return S_OK
;
3553 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3554 utf8
.value
.bytes
= ptr
->bytes
;
3555 utf8
.value
.length
= ptr
->length
;
3556 return write_type_text( writer
, mapping
, &utf8
.text
);
3559 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
3561 const struct node
*node
;
3562 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3564 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3566 for (i
= 0; i
< elem
->attributeCount
; i
++)
3568 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3569 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
3570 *prefix
= elem
->attributes
[i
]->prefix
;
3574 return WS_E_INVALID_FORMAT
;
3577 static HRESULT
write_type_qname( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3578 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3579 const void *value
, ULONG size
)
3581 WS_XML_QNAME_TEXT qname
;
3582 const WS_XML_QNAME
*ptr
;
3583 const WS_XML_STRING
*prefix
;
3588 FIXME( "description not supported\n" );
3592 if (!option
) return E_INVALIDARG
;
3593 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3594 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3595 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3597 if (((hr
= find_prefix( writer
, &ptr
->ns
, &prefix
)) != S_OK
)) return hr
;
3599 qname
.text
.textType
= WS_XML_TEXT_TYPE_QNAME
;
3600 qname
.prefix
= (WS_XML_STRING
*)prefix
;
3601 qname
.localName
= (WS_XML_STRING
*)&ptr
->localName
;
3602 qname
.ns
= (WS_XML_STRING
*)&ptr
->ns
;
3603 return write_type_text( writer
, mapping
, &qname
.text
);
3606 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
3608 if (options
& WS_FIELD_POINTER
)
3610 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
)) return WS_WRITE_NILLABLE_POINTER
;
3611 return WS_WRITE_REQUIRED_POINTER
;
3622 case WS_UINT16_TYPE
:
3623 case WS_UINT32_TYPE
:
3624 case WS_UINT64_TYPE
:
3625 case WS_DOUBLE_TYPE
:
3626 case WS_DATETIME_TYPE
:
3628 case WS_UNIQUE_ID_TYPE
:
3629 case WS_STRING_TYPE
:
3631 case WS_XML_STRING_TYPE
:
3632 case WS_XML_QNAME_TYPE
:
3633 case WS_STRUCT_TYPE
:
3636 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
3637 return WS_WRITE_REQUIRED_VALUE
;
3640 case WS_DESCRIPTION_TYPE
:
3641 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3642 return WS_WRITE_REQUIRED_POINTER
;
3645 FIXME( "unhandled type %u\n", type
);
3650 static HRESULT
find_index( const WS_UNION_DESCRIPTION
*desc
, int value
, ULONG
*idx
)
3654 if (desc
->valueIndices
)
3656 int c
, min
= 0, max
= desc
->fieldCount
- 1;
3659 i
= (min
+ max
) / 2;
3660 c
= value
- desc
->fields
[desc
->valueIndices
[i
]]->value
;
3667 *idx
= desc
->valueIndices
[i
];
3671 return WS_E_INVALID_FORMAT
;
3674 /* fall back to linear search */
3675 for (i
= 0; i
< desc
->fieldCount
; i
++)
3677 if (desc
->fields
[i
]->value
== value
)
3683 return WS_E_INVALID_FORMAT
;
3686 static HRESULT
write_type_field( struct writer
*, const WS_FIELD_DESCRIPTION
*, const char *, ULONG
);
3688 static HRESULT
write_type_union( struct writer
*writer
, const WS_UNION_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3689 const void *value
, ULONG size
)
3696 if (size
< sizeof(enum_value
)) return E_INVALIDARG
;
3697 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3699 enum_value
= *(int *)(char *)ptr
+ desc
->enumOffset
;
3700 if (enum_value
== desc
->noneEnumValue
&& option
== WS_WRITE_NILLABLE_VALUE
) return S_OK
;
3702 if ((hr
= find_index( desc
, enum_value
, &i
)) != S_OK
) return hr
;
3703 return write_type_field( writer
, &desc
->fields
[i
]->field
, ptr
, desc
->fields
[i
]->field
.offset
);
3706 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
3707 const void *, ULONG
);
3709 static HRESULT
write_type_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3713 ULONG i
, size
, offset
= 0;
3714 WS_WRITE_OPTION option
;
3716 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3718 /* wrapper element */
3719 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
3722 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
3723 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3725 size
= sizeof(const void *);
3727 for (i
= 0; i
< count
; i
++)
3729 if (desc
->type
== WS_UNION_TYPE
)
3731 if ((hr
= write_type_union( writer
, desc
->typeDescription
, option
, buf
+ offset
, size
)) != S_OK
)
3736 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
3737 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
3738 buf
+ offset
, size
)) != S_OK
) return hr
;
3739 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3744 if (desc
->localName
) hr
= write_endelement_node( writer
);
3748 static HRESULT
write_type_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3752 WS_TYPE_MAPPING mapping
;
3753 WS_WRITE_OPTION option
;
3754 ULONG count
, size
, field_options
= desc
->options
;
3755 const char *ptr
= buf
+ offset
;
3757 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
3759 FIXME( "options 0x%x not supported\n", desc
->options
);
3763 /* zero-terminated strings and descriptions are always pointers */
3764 if (desc
->type
== WS_WSZ_TYPE
|| desc
->type
== WS_DESCRIPTION_TYPE
) field_options
|= WS_FIELD_POINTER
;
3766 if (field_options
& WS_FIELD_POINTER
)
3767 size
= sizeof(const void *);
3769 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3771 if (is_nil_value( ptr
, size
))
3773 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
3774 if (field_options
& (WS_FIELD_NILLABLE
|WS_FIELD_NILLABLE_ITEM
))
3776 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
3777 else option
= WS_WRITE_NILLABLE_VALUE
;
3781 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3782 else option
= WS_WRITE_REQUIRED_VALUE
;
3787 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3788 else option
= WS_WRITE_REQUIRED_VALUE
;
3791 switch (desc
->mapping
)
3793 case WS_TYPE_ATTRIBUTE_FIELD_MAPPING
:
3794 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3797 case WS_ATTRIBUTE_FIELD_MAPPING
:
3798 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
3799 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
3801 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3803 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3806 case WS_ELEMENT_FIELD_MAPPING
:
3807 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
3808 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3811 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
3812 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
) return E_INVALIDARG
;
3813 option
= (field_options
& WS_FIELD_OPTIONAL
) ? WS_WRITE_NILLABLE_VALUE
: WS_WRITE_REQUIRED_VALUE
;
3814 return write_type_union( writer
, desc
->typeDescription
, option
, ptr
, size
);
3816 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3817 case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING
:
3818 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
3819 return write_type_array( writer
, desc
, *(const char **)ptr
, count
);
3821 case WS_TEXT_FIELD_MAPPING
:
3822 switch (writer
->state
)
3824 case WRITER_STATE_STARTELEMENT
:
3825 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
3828 case WRITER_STATE_STARTATTRIBUTE
:
3829 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3833 FIXME( "unhandled writer state %u\n", writer
->state
);
3838 case WS_ANY_ATTRIBUTES_FIELD_MAPPING
:
3842 FIXME( "field mapping %u not supported\n", desc
->mapping
);
3846 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
3851 case WS_ATTRIBUTE_TYPE_MAPPING
:
3852 writer
->state
= WRITER_STATE_STARTELEMENT
;
3855 case WS_ELEMENT_TYPE_MAPPING
:
3856 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3865 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3866 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3867 const void *value
, ULONG size
)
3873 if (!desc
) return E_INVALIDARG
;
3874 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
3876 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3877 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3879 for (i
= 0; i
< desc
->fieldCount
; i
++)
3881 offset
= desc
->fields
[i
]->offset
;
3882 if ((hr
= write_type_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
) return hr
;
3888 static const WS_XML_STRING
*get_enum_value_name( const WS_ENUM_DESCRIPTION
*desc
, int value
)
3891 for (i
= 0; i
< desc
->valueCount
; i
++)
3893 if (desc
->values
[i
].value
== value
) return desc
->values
[i
].name
;
3898 static HRESULT
write_type_enum( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3899 const WS_ENUM_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3900 const void *value
, ULONG size
)
3902 const WS_XML_STRING
*name
;
3903 WS_XML_UTF8_TEXT utf8
;
3907 if (!desc
) return E_INVALIDARG
;
3908 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3909 if (!(name
= get_enum_value_name( desc
, *ptr
))) return E_INVALIDARG
;
3911 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3912 utf8
.value
.bytes
= name
->bytes
;
3913 utf8
.value
.length
= name
->length
;
3914 return write_type_text( writer
, mapping
, &utf8
.text
);
3917 static HRESULT
write_type_description( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3918 WS_WRITE_OPTION option
, const void *value
, ULONG size
)
3920 const WS_STRUCT_DESCRIPTION
*ptr
;
3923 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3924 if (ptr
) FIXME( "ignoring type description %p\n", ptr
);
3928 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3929 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3935 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
3938 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
3941 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
3944 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
3947 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
3950 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
3952 case WS_UINT16_TYPE
:
3953 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
3955 case WS_UINT32_TYPE
:
3956 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
3958 case WS_UINT64_TYPE
:
3959 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
3961 case WS_DOUBLE_TYPE
:
3962 return write_type_double( writer
, mapping
, desc
, option
, value
, size
);
3964 case WS_DATETIME_TYPE
:
3965 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
3968 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
3970 case WS_UNIQUE_ID_TYPE
:
3971 return write_type_unique_id( writer
, mapping
, desc
, option
, value
, size
);
3973 case WS_STRING_TYPE
:
3974 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
3977 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
3980 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
3982 case WS_XML_STRING_TYPE
:
3983 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
3985 case WS_XML_QNAME_TYPE
:
3986 return write_type_qname( writer
, mapping
, desc
, option
, value
, size
);
3988 case WS_DESCRIPTION_TYPE
:
3989 return write_type_description( writer
, mapping
, option
, value
, size
);
3991 case WS_STRUCT_TYPE
:
3992 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
3995 return write_type_enum( writer
, mapping
, desc
, option
, value
, size
);
3998 FIXME( "type %u not supported\n", type
);
4003 /**************************************************************************
4004 * WsWriteAttribute [webservices.@]
4006 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
4007 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
4010 struct writer
*writer
= (struct writer
*)handle
;
4013 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
4014 if (error
) FIXME( "ignoring error parameter\n" );
4016 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
4017 return E_INVALIDARG
;
4019 EnterCriticalSection( &writer
->cs
);
4021 if (writer
->magic
!= WRITER_MAGIC
)
4023 LeaveCriticalSection( &writer
->cs
);
4024 return E_INVALIDARG
;
4027 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_OPERATION
;
4028 else if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) == S_OK
)
4030 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
4031 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
4034 LeaveCriticalSection( &writer
->cs
);
4035 TRACE( "returning %08x\n", hr
);
4039 /**************************************************************************
4040 * WsWriteElement [webservices.@]
4042 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4043 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
4046 struct writer
*writer
= (struct writer
*)handle
;
4049 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
4050 if (error
) FIXME( "ignoring error parameter\n" );
4052 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
4053 return E_INVALIDARG
;
4055 EnterCriticalSection( &writer
->cs
);
4057 if (writer
->magic
!= WRITER_MAGIC
)
4059 LeaveCriticalSection( &writer
->cs
);
4060 return E_INVALIDARG
;
4063 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4065 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
4066 option
, value
, size
)) != S_OK
) goto done
;
4068 hr
= write_endelement_node( writer
);
4071 LeaveCriticalSection( &writer
->cs
);
4072 TRACE( "returning %08x\n", hr
);
4076 /**************************************************************************
4077 * WsWriteType [webservices.@]
4079 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
4080 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
4081 ULONG size
, WS_ERROR
*error
)
4083 struct writer
*writer
= (struct writer
*)handle
;
4086 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
4088 if (error
) FIXME( "ignoring error parameter\n" );
4090 if (!writer
|| !value
) return E_INVALIDARG
;
4092 EnterCriticalSection( &writer
->cs
);
4094 if (writer
->magic
!= WRITER_MAGIC
)
4096 LeaveCriticalSection( &writer
->cs
);
4097 return E_INVALIDARG
;
4102 case WS_ATTRIBUTE_TYPE_MAPPING
:
4103 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
4104 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
4107 case WS_ELEMENT_TYPE_MAPPING
:
4108 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
4109 case WS_ANY_ELEMENT_TYPE_MAPPING
:
4110 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
4114 FIXME( "mapping %u not implemented\n", mapping
);
4118 LeaveCriticalSection( &writer
->cs
);
4119 TRACE( "returning %08x\n", hr
);
4123 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
4127 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
4128 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
4129 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
4130 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
4131 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
4132 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
4133 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
4134 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
4135 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
4136 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
4137 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
4138 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
4139 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
4140 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
4141 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
4143 FIXME( "unhandled type %u\n", type
);
4148 /**************************************************************************
4149 * WsWriteValue [webservices.@]
4151 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
4152 ULONG size
, WS_ERROR
*error
)
4154 struct writer
*writer
= (struct writer
*)handle
;
4155 WS_TYPE_MAPPING mapping
;
4159 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
4160 if (error
) FIXME( "ignoring error parameter\n" );
4162 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
4164 EnterCriticalSection( &writer
->cs
);
4166 if (writer
->magic
!= WRITER_MAGIC
)
4168 LeaveCriticalSection( &writer
->cs
);
4169 return E_INVALIDARG
;
4172 switch (writer
->state
)
4174 case WRITER_STATE_STARTATTRIBUTE
:
4175 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
4178 case WRITER_STATE_STARTELEMENT
:
4179 mapping
= WS_ELEMENT_TYPE_MAPPING
;
4183 hr
= WS_E_INVALID_FORMAT
;
4186 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
4188 LeaveCriticalSection( &writer
->cs
);
4189 TRACE( "returning %08x\n", hr
);
4193 /**************************************************************************
4194 * WsWriteArray [webservices.@]
4196 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4197 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
4198 ULONG count
, WS_ERROR
*error
)
4200 struct writer
*writer
= (struct writer
*)handle
;
4205 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
4206 value_type
, array
, size
, offset
, count
, error
);
4207 if (error
) FIXME( "ignoring error parameter\n" );
4209 if (!writer
) return E_INVALIDARG
;
4211 EnterCriticalSection( &writer
->cs
);
4213 if (writer
->magic
!= WRITER_MAGIC
)
4215 LeaveCriticalSection( &writer
->cs
);
4216 return E_INVALIDARG
;
4219 if (!writer
->output_type
)
4221 hr
= WS_E_INVALID_OPERATION
;
4225 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
4231 type_size
= get_type_size( type
, NULL
);
4232 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
4238 for (i
= offset
; i
< count
; i
++)
4240 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
4241 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
4242 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
4243 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
4244 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
4248 LeaveCriticalSection( &writer
->cs
);
4249 TRACE( "returning %08x\n", hr
);
4253 /**************************************************************************
4254 * WsWriteXmlBuffer [webservices.@]
4256 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
4258 struct writer
*writer
= (struct writer
*)handle
;
4259 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4262 TRACE( "%p %p %p\n", handle
, buffer
, error
);
4263 if (error
) FIXME( "ignoring error parameter\n" );
4265 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
4267 EnterCriticalSection( &writer
->cs
);
4269 if (writer
->magic
!= WRITER_MAGIC
)
4271 LeaveCriticalSection( &writer
->cs
);
4272 return E_INVALIDARG
;
4275 if (xmlbuf
->encoding
!= writer
->output_enc
|| xmlbuf
->charset
!= writer
->output_charset
)
4277 FIXME( "no support for different encoding and/or charset\n" );
4282 if ((hr
= write_commit( writer
)) != S_OK
) goto done
;
4283 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
4284 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4287 LeaveCriticalSection( &writer
->cs
);
4288 TRACE( "returning %08x\n", hr
);
4292 /**************************************************************************
4293 * WsWriteXmlBufferToBytes [webservices.@]
4295 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
4296 const WS_XML_WRITER_ENCODING
*encoding
,
4297 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
4298 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
4300 struct writer
*writer
= (struct writer
*)handle
;
4301 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4306 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
4307 bytes
, size
, error
);
4308 if (error
) FIXME( "ignoring error parameter\n" );
4310 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
4312 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
4314 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4318 EnterCriticalSection( &writer
->cs
);
4320 if (writer
->magic
!= WRITER_MAGIC
)
4322 LeaveCriticalSection( &writer
->cs
);
4323 return E_INVALIDARG
;
4326 for (i
= 0; i
< count
; i
++)
4328 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4329 properties
[i
].valueSize
);
4330 if (hr
!= S_OK
) goto done
;
4333 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
4336 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4338 *size
= xmlbuf
->bytes
.length
;
4342 LeaveCriticalSection( &writer
->cs
);
4343 TRACE( "returning %08x\n", hr
);
4347 /**************************************************************************
4348 * WsWriteXmlnsAttribute [webservices.@]
4350 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4351 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
4353 struct writer
*writer
= (struct writer
*)handle
;
4356 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
4358 if (error
) FIXME( "ignoring error parameter\n" );
4360 if (!writer
|| !ns
) return E_INVALIDARG
;
4362 EnterCriticalSection( &writer
->cs
);
4364 if (writer
->magic
!= WRITER_MAGIC
)
4366 LeaveCriticalSection( &writer
->cs
);
4367 return E_INVALIDARG
;
4370 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_OPERATION
;
4371 else if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
4372 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
4374 LeaveCriticalSection( &writer
->cs
);
4375 TRACE( "returning %08x\n", hr
);
4379 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
4380 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
4382 WS_XML_QNAME_TEXT qname
= {{WS_XML_TEXT_TYPE_QNAME
}};
4385 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
4386 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) return hr
;
4388 qname
.prefix
= (WS_XML_STRING
*)prefix
;
4389 qname
.localName
= (WS_XML_STRING
*)localname
;
4390 qname
.ns
= (WS_XML_STRING
*)ns
;
4392 if ((hr
= write_add_text_node( writer
, &qname
.text
)) != S_OK
) return hr
;
4393 return write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 );
4396 /**************************************************************************
4397 * WsWriteQualifiedName [webservices.@]
4399 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4400 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4403 struct writer
*writer
= (struct writer
*)handle
;
4406 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
4407 debugstr_xmlstr(ns
), error
);
4408 if (error
) FIXME( "ignoring error parameter\n" );
4410 if (!writer
) return E_INVALIDARG
;
4412 EnterCriticalSection( &writer
->cs
);
4414 if (writer
->magic
!= WRITER_MAGIC
)
4416 LeaveCriticalSection( &writer
->cs
);
4417 return E_INVALIDARG
;
4420 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
4421 else if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_FORMAT
;
4422 else if (!localname
|| (!prefix
&& !ns
)) hr
= E_INVALIDARG
;
4423 else hr
= write_qualified_name( writer
, prefix
, localname
, ns
);
4425 LeaveCriticalSection( &writer
->cs
);
4426 TRACE( "returning %08x\n", hr
);
4430 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
4432 BOOL success
= FALSE
;
4433 struct node
*node
= writer
->current
;
4437 case WS_MOVE_TO_ROOT_ELEMENT
:
4438 success
= move_to_root_element( writer
->root
, &node
);
4441 case WS_MOVE_TO_NEXT_ELEMENT
:
4442 success
= move_to_next_element( &node
);
4445 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
4446 success
= move_to_prev_element( &node
);
4449 case WS_MOVE_TO_CHILD_ELEMENT
:
4450 success
= move_to_child_element( &node
);
4453 case WS_MOVE_TO_END_ELEMENT
:
4454 success
= move_to_end_element( &node
);
4457 case WS_MOVE_TO_PARENT_ELEMENT
:
4458 success
= move_to_parent_element( &node
);
4461 case WS_MOVE_TO_FIRST_NODE
:
4462 success
= move_to_first_node( &node
);
4465 case WS_MOVE_TO_NEXT_NODE
:
4466 success
= move_to_next_node( &node
);
4469 case WS_MOVE_TO_PREVIOUS_NODE
:
4470 success
= move_to_prev_node( &node
);
4473 case WS_MOVE_TO_CHILD_NODE
:
4474 success
= move_to_child_node( &node
);
4477 case WS_MOVE_TO_BOF
:
4478 success
= move_to_bof( writer
->root
, &node
);
4481 case WS_MOVE_TO_EOF
:
4482 success
= move_to_eof( writer
->root
, &node
);
4486 FIXME( "unhandled move %u\n", move
);
4490 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
4491 writer
->current
= node
;
4498 return success
? S_OK
: WS_E_INVALID_FORMAT
;
4501 /**************************************************************************
4502 * WsMoveWriter [webservices.@]
4504 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
4506 struct writer
*writer
= (struct writer
*)handle
;
4509 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
4510 if (error
) FIXME( "ignoring error parameter\n" );
4512 if (!writer
) return E_INVALIDARG
;
4514 EnterCriticalSection( &writer
->cs
);
4516 if (writer
->magic
!= WRITER_MAGIC
)
4518 LeaveCriticalSection( &writer
->cs
);
4519 return E_INVALIDARG
;
4522 if (writer
->output_type
!= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
) hr
= WS_E_INVALID_OPERATION
;
4523 else hr
= write_move_to( writer
, move
, found
);
4525 LeaveCriticalSection( &writer
->cs
);
4526 TRACE( "returning %08x\n", hr
);
4530 /**************************************************************************
4531 * WsGetWriterPosition [webservices.@]
4533 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4535 struct writer
*writer
= (struct writer
*)handle
;
4538 TRACE( "%p %p %p\n", handle
, pos
, error
);
4539 if (error
) FIXME( "ignoring error parameter\n" );
4541 if (!writer
|| !pos
) return E_INVALIDARG
;
4543 EnterCriticalSection( &writer
->cs
);
4545 if (writer
->magic
!= WRITER_MAGIC
)
4547 LeaveCriticalSection( &writer
->cs
);
4548 return E_INVALIDARG
;
4551 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
4554 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
4555 pos
->node
= writer
->current
;
4558 LeaveCriticalSection( &writer
->cs
);
4559 TRACE( "returning %08x\n", hr
);
4563 /**************************************************************************
4564 * WsSetWriterPosition [webservices.@]
4566 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4568 struct writer
*writer
= (struct writer
*)handle
;
4571 TRACE( "%p %p %p\n", handle
, pos
, error
);
4572 if (error
) FIXME( "ignoring error parameter\n" );
4574 if (!writer
|| !pos
) return E_INVALIDARG
;
4576 EnterCriticalSection( &writer
->cs
);
4578 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
4580 LeaveCriticalSection( &writer
->cs
);
4581 return E_INVALIDARG
;
4584 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
4585 else writer
->current
= pos
->node
;
4587 LeaveCriticalSection( &writer
->cs
);
4588 TRACE( "returning %08x\n", hr
);
4592 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4594 struct node
*node
, *parent
;
4595 WS_XML_COMMENT_NODE
*comment
;
4597 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
4598 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
4599 comment
= (WS_XML_COMMENT_NODE
*)node
;
4601 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
4604 return E_OUTOFMEMORY
;
4606 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
4607 comment
->value
.length
= value
->length
;
4609 write_insert_node( writer
, parent
, node
);
4613 static HRESULT
write_comment_text( struct writer
*writer
)
4615 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4618 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
4619 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
4620 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
4621 write_bytes( writer
, (const BYTE
*)"-->", 3 );
4625 static HRESULT
write_comment_bin( struct writer
*writer
)
4627 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4630 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
4631 write_char( writer
, RECORD_COMMENT
);
4632 return write_string( writer
, comment
->value
.bytes
, comment
->value
.length
);
4635 static HRESULT
write_comment( struct writer
*writer
)
4637 switch (writer
->output_enc
)
4639 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_comment_text( writer
);
4640 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_comment_bin( writer
);
4642 ERR( "unhandled encoding %u\n", writer
->output_enc
);
4643 return WS_E_NOT_SUPPORTED
;
4647 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4650 if ((hr
= write_commit( writer
)) != S_OK
) return hr
;
4651 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
4652 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4653 writer
->state
= WRITER_STATE_COMMENT
;
4657 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
4662 for (i
= 0; i
< count
; i
++)
4664 const WS_XML_STRING
*prefix
= attrs
[i
]->prefix
;
4665 const WS_XML_STRING
*localname
= attrs
[i
]->localName
;
4666 const WS_XML_STRING
*ns
= attrs
[i
]->ns
;
4667 BOOL single
= attrs
[i
]->singleQuote
;
4669 if (attrs
[i
]->isXmlNs
)
4671 if ((hr
= add_namespace_attribute( writer
, prefix
, ns
, single
)) != S_OK
) return hr
;
4675 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) != S_OK
) return hr
;
4676 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
4682 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
4686 switch (node
->nodeType
)
4688 case WS_XML_NODE_TYPE_ELEMENT
:
4690 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
4691 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
4692 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
4694 case WS_XML_NODE_TYPE_TEXT
:
4696 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4697 return write_text_node( writer
, text
->text
);
4699 case WS_XML_NODE_TYPE_END_ELEMENT
:
4700 return write_endelement_node( writer
);
4702 case WS_XML_NODE_TYPE_COMMENT
:
4704 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
4705 return write_comment_node( writer
, &comment
->value
);
4707 case WS_XML_NODE_TYPE_CDATA
:
4708 return write_cdata_node( writer
);
4710 case WS_XML_NODE_TYPE_END_CDATA
:
4711 return write_endcdata_node( writer
);
4713 case WS_XML_NODE_TYPE_EOF
:
4714 case WS_XML_NODE_TYPE_BOF
:
4718 WARN( "unknown node type %u\n", node
->nodeType
);
4719 return E_INVALIDARG
;
4723 /**************************************************************************
4724 * WsWriteNode [webservices.@]
4726 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
4728 struct writer
*writer
= (struct writer
*)handle
;
4731 TRACE( "%p %p %p\n", handle
, node
, error
);
4732 if (error
) FIXME( "ignoring error parameter\n" );
4734 if (!writer
|| !node
) return E_INVALIDARG
;
4736 EnterCriticalSection( &writer
->cs
);
4738 if (writer
->magic
!= WRITER_MAGIC
)
4740 LeaveCriticalSection( &writer
->cs
);
4741 return E_INVALIDARG
;
4744 if (!writer
->output_type
) hr
= WS_E_INVALID_OPERATION
;
4745 else hr
= write_node( writer
, node
);
4747 LeaveCriticalSection( &writer
->cs
);
4748 TRACE( "returning %08x\n", hr
);
4752 static HRESULT
write_tree_node( struct writer
*writer
)
4756 switch (node_type( writer
->current
))
4758 case WS_XML_NODE_TYPE_ELEMENT
:
4759 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4761 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
4762 writer
->state
= WRITER_STATE_STARTELEMENT
;
4765 case WS_XML_NODE_TYPE_TEXT
:
4766 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4768 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
4769 writer
->state
= WRITER_STATE_TEXT
;
4772 case WS_XML_NODE_TYPE_END_ELEMENT
:
4773 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
4774 writer
->state
= WRITER_STATE_ENDELEMENT
;
4777 case WS_XML_NODE_TYPE_COMMENT
:
4778 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4780 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4781 writer
->state
= WRITER_STATE_COMMENT
;
4784 case WS_XML_NODE_TYPE_CDATA
:
4785 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4787 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
4788 writer
->state
= WRITER_STATE_STARTCDATA
;
4791 case WS_XML_NODE_TYPE_END_CDATA
:
4792 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
4793 writer
->state
= WRITER_STATE_ENDCDATA
;
4796 case WS_XML_NODE_TYPE_EOF
:
4797 case WS_XML_NODE_TYPE_BOF
:
4801 ERR( "unknown node type %u\n", node_type(writer
->current
) );
4802 return E_INVALIDARG
;
4806 static HRESULT
write_tree( struct writer
*writer
)
4810 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4813 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
4814 if (move_to_child_node( &writer
->current
))
4816 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4819 if (move_to_next_node( &writer
->current
))
4821 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4824 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
4826 ERR( "invalid tree\n" );
4827 return WS_E_INVALID_FORMAT
;
4829 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4834 static void write_rewind( struct writer
*writer
)
4836 writer
->write_pos
= 0;
4837 writer
->current
= writer
->root
;
4838 writer
->state
= WRITER_STATE_INITIAL
;
4841 /**************************************************************************
4842 * WsCopyNode [webservices.@]
4844 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
4846 struct writer
*writer
= (struct writer
*)handle
;
4847 struct node
*parent
, *current
, *node
= NULL
;
4850 TRACE( "%p %p %p\n", handle
, reader
, error
);
4851 if (error
) FIXME( "ignoring error parameter\n" );
4853 if (!writer
) return E_INVALIDARG
;
4855 EnterCriticalSection( &writer
->cs
);
4857 if (writer
->magic
!= WRITER_MAGIC
)
4859 LeaveCriticalSection( &writer
->cs
);
4860 return E_INVALIDARG
;
4863 if (!(parent
= find_parent( writer
))) hr
= WS_E_INVALID_FORMAT
;
4866 if ((hr
= copy_node( reader
, writer
->output_enc
, &node
)) != S_OK
) goto done
;
4867 current
= writer
->current
;
4868 write_insert_node( writer
, parent
, node
);
4870 write_rewind( writer
);
4871 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
4872 writer
->current
= current
;
4874 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
4878 LeaveCriticalSection( &writer
->cs
);
4879 TRACE( "returning %08x\n", hr
);
4883 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
4885 return write_type_field( writer
, desc
, value
, 0 );
4888 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
4891 for (i
= 0; i
< count
; i
++)
4893 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4895 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
4901 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
4904 return write_type_array( writer
, desc
, value
, len
);
4907 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4908 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4910 struct writer
*writer
= (struct writer
*)handle
;
4911 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4912 const WS_FIELD_DESCRIPTION
*desc_field
;
4916 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4918 EnterCriticalSection( &writer
->cs
);
4920 if (writer
->magic
!= WRITER_MAGIC
)
4922 LeaveCriticalSection( &writer
->cs
);
4923 return E_INVALIDARG
;
4926 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4928 for (i
= 0; i
< count
; i
++)
4930 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
4931 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
4933 FIXME( "messages type not supported\n" );
4937 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
4938 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
4940 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
4942 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
4944 const void *ptr
= *(const void **)args
[i
];
4945 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
4946 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
4950 hr
= write_endelement_node( writer
);
4953 LeaveCriticalSection( &writer
->cs
);
4957 HRESULT
writer_set_lookup( WS_XML_WRITER
*handle
, BOOL enable
)
4959 struct writer
*writer
= (struct writer
*)handle
;
4961 EnterCriticalSection( &writer
->cs
);
4963 if (writer
->magic
!= WRITER_MAGIC
)
4965 LeaveCriticalSection( &writer
->cs
);
4966 return E_INVALIDARG
;
4969 writer
->dict_do_lookup
= enable
;
4971 LeaveCriticalSection( &writer
->cs
);
4975 HRESULT
writer_set_dict_callback( WS_XML_WRITER
*handle
, WS_DYNAMIC_STRING_CALLBACK cb
, void *state
)
4977 struct writer
*writer
= (struct writer
*)handle
;
4979 EnterCriticalSection( &writer
->cs
);
4981 if (writer
->magic
!= WRITER_MAGIC
)
4983 LeaveCriticalSection( &writer
->cs
);
4984 return E_INVALIDARG
;
4987 writer
->dict_cb
= cb
;
4988 writer
->dict_cb_state
= state
;
4990 LeaveCriticalSection( &writer
->cs
);