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
28 #include "webservices.h"
30 #include "wine/debug.h"
31 #include "wine/list.h"
32 #include "wine/unicode.h"
33 #include "webservices_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
37 static const struct prop_desc writer_props
[] =
39 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
40 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
41 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
42 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
43 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INDENT */
44 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
45 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_WRITER_PROPERTY_CHARSET */
46 { sizeof(WS_BUFFERS
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFERS */
47 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
48 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BYTES */
49 { sizeof(BOOL
), TRUE
}, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
50 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
51 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
52 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
53 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
54 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
55 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
56 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
57 { sizeof(BOOL
), FALSE
} /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
63 WRITER_STATE_STARTELEMENT
,
64 WRITER_STATE_STARTATTRIBUTE
,
65 WRITER_STATE_STARTCDATA
,
66 WRITER_STATE_ENDSTARTELEMENT
,
69 WRITER_STATE_ENDELEMENT
,
78 unsigned char *write_bufptr
;
79 enum writer_state state
;
82 WS_XML_STRING
*current_ns
;
83 WS_XML_WRITER_ENCODING_TYPE output_enc
;
84 WS_CHARSET output_charset
;
85 WS_XML_WRITER_OUTPUT_TYPE output_type
;
86 struct xmlbuf
*output_buf
;
88 const WS_XML_DICTIONARY
*dict
;
90 WS_DYNAMIC_STRING_CALLBACK dict_cb
;
93 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
96 #define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T')
98 static struct writer
*alloc_writer(void)
100 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
102 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
104 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
106 ret
->magic
= WRITER_MAGIC
;
107 InitializeCriticalSection( &ret
->cs
);
108 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": writer.cs");
110 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
111 ret
->prop_count
= count
;
115 static void free_writer( struct writer
*writer
)
117 destroy_nodes( writer
->root
);
118 free_xml_string( writer
->current_ns
);
119 WsFreeHeap( writer
->output_heap
);
121 writer
->cs
.DebugInfo
->Spare
[0] = 0;
122 DeleteCriticalSection( &writer
->cs
);
126 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
128 if (!writer
->root
) writer
->root
= eof
;
131 eof
->parent
= writer
->root
;
132 list_add_tail( &writer
->root
->children
, &eof
->entry
);
134 writer
->current
= eof
;
137 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
139 writer
->root
->parent
= bof
;
140 list_add_tail( &bof
->children
, &writer
->root
->entry
);
141 writer
->current
= writer
->root
= bof
;
144 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
146 node
->parent
= parent
;
147 list_add_before( list_tail( &parent
->children
), &node
->entry
);
148 writer
->current
= node
;
151 static struct node
*find_parent( struct writer
*writer
)
153 if (is_valid_parent( writer
->current
)) return writer
->current
;
154 if (is_valid_parent( writer
->current
->parent
)) return writer
->current
->parent
;
158 static HRESULT
init_writer( struct writer
*writer
)
162 writer
->write_pos
= 0;
163 writer
->write_bufptr
= NULL
;
164 destroy_nodes( writer
->root
);
165 writer
->root
= writer
->current
= NULL
;
166 free_xml_string( writer
->current_ns
);
167 writer
->current_ns
= NULL
;
169 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
170 write_insert_eof( writer
, node
);
171 writer
->state
= WRITER_STATE_INITIAL
;
172 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
173 writer
->output_charset
= WS_CHARSET_UTF8
;
175 writer
->dict_do_lookup
= FALSE
;
176 writer
->dict_cb
= NULL
;
177 writer
->dict_cb_state
= NULL
;
181 /**************************************************************************
182 * WsCreateWriter [webservices.@]
184 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
185 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
187 struct writer
*writer
;
188 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
189 WS_CHARSET charset
= WS_CHARSET_UTF8
;
192 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
193 if (error
) FIXME( "ignoring error parameter\n" );
195 if (!handle
) return E_INVALIDARG
;
196 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
198 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
199 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
200 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
201 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
202 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
203 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
204 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
206 for (i
= 0; i
< count
; i
++)
208 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
209 properties
[i
].valueSize
);
212 free_writer( writer
);
217 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
218 &max_size
, sizeof(max_size
) );
221 free_writer( writer
);
225 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
228 free_writer( writer
);
232 hr
= init_writer( writer
);
235 free_writer( writer
);
239 TRACE( "created %p\n", writer
);
240 *handle
= (WS_XML_WRITER
*)writer
;
244 /**************************************************************************
245 * WsFreeWriter [webservices.@]
247 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
249 struct writer
*writer
= (struct writer
*)handle
;
251 TRACE( "%p\n", handle
);
255 EnterCriticalSection( &writer
->cs
);
257 if (writer
->magic
!= WRITER_MAGIC
)
259 LeaveCriticalSection( &writer
->cs
);
265 LeaveCriticalSection( &writer
->cs
);
266 free_writer( writer
);
269 /**************************************************************************
270 * WsGetWriterProperty [webservices.@]
272 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
273 void *buf
, ULONG size
, WS_ERROR
*error
)
275 struct writer
*writer
= (struct writer
*)handle
;
278 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
279 if (error
) FIXME( "ignoring error parameter\n" );
281 if (!writer
) return E_INVALIDARG
;
283 EnterCriticalSection( &writer
->cs
);
285 if (writer
->magic
!= WRITER_MAGIC
)
287 LeaveCriticalSection( &writer
->cs
);
291 if (!writer
->output_type
)
293 LeaveCriticalSection( &writer
->cs
);
294 return WS_E_INVALID_OPERATION
;
299 case WS_XML_WRITER_PROPERTY_BYTES
:
301 WS_BYTES
*bytes
= buf
;
302 if (size
!= sizeof(*bytes
)) hr
= E_INVALIDARG
;
305 bytes
->bytes
= writer
->output_buf
->bytes
.bytes
;
306 bytes
->length
= writer
->output_buf
->bytes
.length
;
310 case WS_XML_WRITER_PROPERTY_BUFFERS
:
311 if (writer
->output_buf
->bytes
.length
)
313 WS_BUFFERS
*buffers
= buf
;
314 if (size
!= sizeof(*buffers
)) hr
= E_INVALIDARG
;
317 buffers
->bufferCount
= 1;
318 buffers
->buffers
= &writer
->output_buf
->bytes
;
324 hr
= prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
327 LeaveCriticalSection( &writer
->cs
);
331 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
333 /* free current buffer if it's ours */
334 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
336 free_xmlbuf( writer
->output_buf
);
338 writer
->output_buf
= xmlbuf
;
339 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
340 writer
->write_bufptr
= xmlbuf
->bytes
.bytes
;
341 writer
->write_pos
= 0;
344 /**************************************************************************
345 * WsSetOutput [webservices.@]
347 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
348 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
349 ULONG count
, WS_ERROR
*error
)
351 struct writer
*writer
= (struct writer
*)handle
;
356 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
357 if (error
) FIXME( "ignoring error parameter\n" );
359 if (!writer
) return E_INVALIDARG
;
361 EnterCriticalSection( &writer
->cs
);
363 if (writer
->magic
!= WRITER_MAGIC
)
365 LeaveCriticalSection( &writer
->cs
);
369 for (i
= 0; i
< count
; i
++)
371 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
372 properties
[i
].valueSize
);
373 if (hr
!= S_OK
) goto done
;
376 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
378 switch (encoding
->encodingType
)
380 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
382 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
383 if (text
->charSet
!= WS_CHARSET_UTF8
)
385 FIXME( "charset %u not supported\n", text
->charSet
);
389 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
390 writer
->output_charset
= WS_CHARSET_UTF8
;
393 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
395 WS_XML_WRITER_BINARY_ENCODING
*bin
= (WS_XML_WRITER_BINARY_ENCODING
*)encoding
;
396 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_BINARY
;
397 writer
->output_charset
= 0;
398 writer
->dict
= bin
->staticDictionary
;
399 writer
->dict_cb
= bin
->dynamicStringCallback
;
400 writer
->dict_cb_state
= bin
->dynamicStringCallbackState
;
404 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
409 switch (output
->outputType
)
411 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
413 struct xmlbuf
*xmlbuf
;
414 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
, 0, writer
->output_enc
, writer
->output_charset
,
415 writer
->dict
, NULL
)))
417 hr
= WS_E_QUOTA_EXCEEDED
;
420 set_output_buffer( writer
, xmlbuf
);
424 FIXME( "output type %u not supported\n", output
->outputType
);
429 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
430 else write_insert_bof( writer
, node
);
433 LeaveCriticalSection( &writer
->cs
);
437 /**************************************************************************
438 * WsSetOutputToBuffer [webservices.@]
440 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
441 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
444 struct writer
*writer
= (struct writer
*)handle
;
445 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
450 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
451 if (error
) FIXME( "ignoring error parameter\n" );
453 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
455 EnterCriticalSection( &writer
->cs
);
457 if (writer
->magic
!= WRITER_MAGIC
)
459 LeaveCriticalSection( &writer
->cs
);
463 for (i
= 0; i
< count
; i
++)
465 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
466 properties
[i
].valueSize
);
467 if (hr
!= S_OK
) goto done
;
470 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
471 writer
->output_enc
= xmlbuf
->encoding
;
472 writer
->output_charset
= xmlbuf
->charset
;
473 set_output_buffer( writer
, xmlbuf
);
475 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
476 else write_insert_bof( writer
, node
);
479 LeaveCriticalSection( &writer
->cs
);
483 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
485 struct xmlbuf
*buf
= writer
->output_buf
;
489 if (buf
->size
>= writer
->write_pos
+ size
)
491 buf
->bytes
.length
= writer
->write_pos
+ size
;
494 new_size
= max( buf
->size
* 2, writer
->write_pos
+ size
);
495 if (!(tmp
= ws_realloc( buf
->heap
, buf
->bytes
.bytes
, buf
->size
, new_size
))) return WS_E_QUOTA_EXCEEDED
;
496 writer
->write_bufptr
= buf
->bytes
.bytes
= tmp
;
497 buf
->size
= new_size
;
498 buf
->bytes
.length
= writer
->write_pos
+ size
;
502 static inline void write_char( struct writer
*writer
, unsigned char ch
)
504 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
507 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
509 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
510 writer
->write_pos
+= len
;
519 static const struct escape escape_lt
= { '<', "<", 4 };
520 static const struct escape escape_gt
= { '>', ">", 4 };
521 static const struct escape escape_amp
= { '&', "&", 5 };
522 static const struct escape escape_apos
= { '\'', "'", 6 };
523 static const struct escape escape_quot
= { '"', """, 6 };
525 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
526 const struct escape
**escapes
, ULONG nb_escapes
)
532 for (i
= 0; i
< len
; i
++)
536 for (j
= 0; j
< nb_escapes
; j
++)
538 if (bytes
[i
] == escapes
[j
]->ch
)
540 ptr
= (const BYTE
*)escapes
[j
]->entity
;
541 size
= escapes
[j
]->len
;
545 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
546 write_bytes( writer
, ptr
, size
);
552 static HRESULT
write_attribute_value_text( struct writer
*writer
, const WS_XML_TEXT
*text
, BOOL single
)
554 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
;
555 const struct escape
*escapes
[3];
557 escapes
[0] = single
? &escape_apos
: &escape_quot
;
558 escapes
[1] = &escape_lt
;
559 escapes
[2] = &escape_amp
;
560 return write_bytes_escape( writer
, utf8
->value
.bytes
, utf8
->value
.length
, escapes
, 3 );
563 static HRESULT
write_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
565 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
566 const WS_XML_STRING
*prefix
= NULL
;
570 if (attr
->prefix
) prefix
= attr
->prefix
;
572 /* ' prefix:attr="value"' */
574 size
= attr
->localName
->length
+ 4 /* ' =""' */;
575 if (prefix
&& prefix
->length
) size
+= prefix
->length
+ 1 /* ':' */;
576 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
578 write_char( writer
, ' ' );
579 if (prefix
&& prefix
->length
)
581 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
582 write_char( writer
, ':' );
584 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
585 write_char( writer
, '=' );
586 write_char( writer
, quote
);
587 if (attr
->value
) hr
= write_attribute_value_text( writer
, attr
->value
, attr
->singleQuote
);
588 write_char( writer
, quote
);
593 static HRESULT
write_int31( struct writer
*writer
, ULONG len
)
597 if (len
> 0x7fffffff) return E_INVALIDARG
;
599 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
602 write_char( writer
, len
);
605 write_char( writer
, (len
& 0x7f) | 0x80 );
607 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
608 if ((len
>>= 7) < 0x80)
610 write_char( writer
, len
);
613 write_char( writer
, (len
& 0x7f) | 0x80 );
615 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
616 if ((len
>>= 7) < 0x80)
618 write_char( writer
, len
);
621 write_char( writer
, (len
& 0x7f) | 0x80 );
623 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
624 if ((len
>>= 7) < 0x80)
626 write_char( writer
, len
);
629 write_char( writer
, (len
& 0x7f) | 0x80 );
631 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
632 if ((len
>>= 7) < 0x08)
634 write_char( writer
, len
);
637 return WS_E_INVALID_FORMAT
;
640 static HRESULT
write_string( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
643 if ((hr
= write_int31( writer
, len
)) != S_OK
) return hr
;
644 if ((hr
= write_grow_buffer( writer
, len
)) != S_OK
) return hr
;
645 write_bytes( writer
, bytes
, len
);
649 static HRESULT
write_dict_string( struct writer
*writer
, ULONG id
)
652 if (id
> 0x7fffffff) return E_INVALIDARG
;
653 if ((hr
= write_int31( writer
, id
)) != S_OK
) return hr
;
657 static enum record_type
get_attr_text_record_type( const WS_XML_TEXT
*text
, BOOL use_dict
)
659 if (!text
) return RECORD_CHARS8_TEXT
;
660 switch (text
->textType
)
662 case WS_XML_TEXT_TYPE_UTF8
:
664 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
665 if (use_dict
) return RECORD_DICTIONARY_TEXT
;
666 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT
;
667 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT
;
668 return RECORD_CHARS32_TEXT
;
670 case WS_XML_TEXT_TYPE_UTF16
:
672 const WS_XML_UTF16_TEXT
*text_utf16
= (const WS_XML_UTF16_TEXT
*)text
;
673 int len
= text_utf16
->byteCount
/ sizeof(WCHAR
);
674 int len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)text_utf16
->bytes
, len
, NULL
, 0, NULL
, NULL
);
675 if (len_utf8
<= MAX_UINT8
) return RECORD_CHARS8_TEXT
;
676 if (len_utf8
<= MAX_UINT16
) return RECORD_CHARS16_TEXT
;
677 return RECORD_CHARS32_TEXT
;
679 case WS_XML_TEXT_TYPE_BASE64
:
681 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
682 if (text_base64
->length
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
683 if (text_base64
->length
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
684 return RECORD_BYTES32_TEXT
;
686 case WS_XML_TEXT_TYPE_BOOL
:
688 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
689 return text_bool
->value
? RECORD_TRUE_TEXT
: RECORD_FALSE_TEXT
;
691 case WS_XML_TEXT_TYPE_INT32
:
693 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
694 if (!text_int32
->value
) return RECORD_ZERO_TEXT
;
695 if (text_int32
->value
== 1) return RECORD_ONE_TEXT
;
696 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
697 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
698 return RECORD_INT32_TEXT
;
700 case WS_XML_TEXT_TYPE_INT64
:
702 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
703 if (!text_int64
->value
) return RECORD_ZERO_TEXT
;
704 if (text_int64
->value
== 1) return RECORD_ONE_TEXT
;
705 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
706 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
707 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
708 return RECORD_INT64_TEXT
;
710 case WS_XML_TEXT_TYPE_UINT64
:
712 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
713 if (!text_uint64
->value
) return RECORD_ZERO_TEXT
;
714 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT
;
715 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
716 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
717 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
718 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT
;
719 return RECORD_UINT64_TEXT
;
721 case WS_XML_TEXT_TYPE_DOUBLE
:
723 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
724 if (!text_double
->value
) return RECORD_ZERO_TEXT
;
725 if (text_double
->value
== 1) return RECORD_ONE_TEXT
;
726 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
727 return RECORD_DOUBLE_TEXT
;
728 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
729 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
730 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
731 return RECORD_INT64_TEXT
;
733 case WS_XML_TEXT_TYPE_GUID
:
734 return RECORD_GUID_TEXT
;
736 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
737 return RECORD_UNIQUE_ID_TEXT
;
739 case WS_XML_TEXT_TYPE_DATETIME
:
740 return RECORD_DATETIME_TEXT
;
743 FIXME( "unhandled text type %u\n", text
->textType
);
748 static INT64
get_text_value_int( const WS_XML_TEXT
*text
)
750 switch (text
->textType
)
752 case WS_XML_TEXT_TYPE_INT32
:
754 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
755 return text_int32
->value
;
757 case WS_XML_TEXT_TYPE_INT64
:
759 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
760 return text_int64
->value
;
762 case WS_XML_TEXT_TYPE_UINT64
:
764 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
765 return text_uint64
->value
;
767 case WS_XML_TEXT_TYPE_DOUBLE
:
769 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
770 return text_double
->value
;
773 ERR( "unhandled text type %u\n", text
->textType
);
779 static BOOL
get_string_id( struct writer
*writer
, const WS_XML_STRING
*str
, ULONG
*id
)
781 if (writer
->dict
&& str
->dictionary
== writer
->dict
)
789 writer
->dict_cb( writer
->dict_cb_state
, str
, &found
, id
, NULL
);
790 if (found
) *id
= (*id
<< 1) | 1;
796 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
798 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
801 memcpy( buf
, bool_true
, sizeof(bool_true
) );
802 return sizeof(bool_true
);
804 memcpy( buf
, bool_false
, sizeof(bool_false
) );
805 return sizeof(bool_false
);
808 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
810 return wsprintfA( (char *)buf
, "%d", *ptr
);
813 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
815 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
818 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
820 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
823 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
826 static const long double precision
= 0.0000000000000001;
827 unsigned char *p
= buf
;
828 long double val
= *ptr
;
829 int neg
, mag
, mag2
, use_exp
;
833 memcpy( buf
, "NaN", 3 );
840 memcpy( buf
, "-INF", 4 );
843 memcpy( buf
, "INF", 3 );
859 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
862 if (mag
< 0) mag
-= 1;
863 val
= val
/ powl( 10.0, mag
);
867 else if (mag
< 1) mag
= 0;
869 while (val
> precision
|| mag
>= 0)
871 long double weight
= powl( 10.0, mag
);
872 if (weight
> 0 && !isinf( weight
))
874 int digit
= floorl( val
/ weight
);
875 val
-= digit
* weight
;
876 *(p
++) = '0' + digit
;
878 if (!mag
&& val
> precision
) *(p
++) = '.';
886 if (mag2
> 0) *(p
++) = '+';
895 *(p
++) = '0' + mag2
% 10;
899 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
909 FIXME( "powl not found at build time\n" );
914 static inline int year_size( int year
)
916 return leap_year( year
) ? 366 : 365;
920 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
922 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
923 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
924 unsigned __int64 ticks
, day_ticks
;
927 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
928 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
930 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
938 day
= ticks
/ TICKS_PER_DAY
;
939 day_ticks
= ticks
% TICKS_PER_DAY
;
940 hour
= day_ticks
/ TICKS_PER_HOUR
;
941 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
942 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
943 sec_frac
= day_ticks
% TICKS_PER_SEC
;
945 while (day
>= year_size( year
))
947 day
-= year_size( year
);
950 while (day
>= month_days
[leap_year( year
)][month
])
952 day
-= month_days
[leap_year( year
)][month
];
956 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
959 static const char fmt_frac
[] = ".%07u";
960 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
961 while (buf
[len
- 1] == '0') len
--;
963 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
967 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
969 static const char fmt_tz
[] = "%c%02u:00";
970 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
976 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
978 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
979 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
980 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
981 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
984 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
986 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
987 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
988 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
989 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
992 static ULONG
format_qname( const WS_XML_STRING
*prefix
, const WS_XML_STRING
*localname
, unsigned char *buf
)
995 if (prefix
&& prefix
->length
)
997 memcpy( buf
, prefix
->bytes
, prefix
->length
);
998 len
+= prefix
->length
;
1001 memcpy( buf
+ len
, localname
->bytes
, localname
->length
);
1002 return len
+ localname
->length
;
1005 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
1007 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1012 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
1013 x
= (bin
[0] & 3) << 4;
1016 buf
[i
++] = base64
[x
];
1021 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
1022 x
= (bin
[1] & 0x0f) << 2;
1025 buf
[i
++] = base64
[x
];
1029 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
1030 buf
[i
++] = base64
[bin
[2] & 0x3f];
1037 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, ULONG
*offset
,
1038 WS_XML_UTF8_TEXT
**ret
)
1040 ULONG len_old
= old
? old
->value
.length
: 0;
1041 if (offset
) *offset
= len_old
;
1043 switch (text
->textType
)
1045 case WS_XML_TEXT_TYPE_UTF8
:
1047 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1049 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
1050 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1051 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
1054 case WS_XML_TEXT_TYPE_UTF16
:
1056 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1057 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1058 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1060 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1061 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1062 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
1063 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1064 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
1067 case WS_XML_TEXT_TYPE_BASE64
:
1069 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
1070 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
1072 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1073 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1074 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1077 case WS_XML_TEXT_TYPE_BOOL
:
1079 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1081 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
1082 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1083 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1086 case WS_XML_TEXT_TYPE_INT32
:
1088 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1089 unsigned char buf
[12]; /* "-2147483648" */
1090 ULONG len
= format_int32( &int32_text
->value
, buf
);
1092 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1093 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1094 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1097 case WS_XML_TEXT_TYPE_INT64
:
1099 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1100 unsigned char buf
[21]; /* "-9223372036854775808" */
1101 ULONG len
= format_int64( &int64_text
->value
, buf
);
1103 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1104 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1105 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1108 case WS_XML_TEXT_TYPE_UINT64
:
1110 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1111 unsigned char buf
[21]; /* "18446744073709551615" */
1112 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1114 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1115 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1116 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1119 case WS_XML_TEXT_TYPE_DOUBLE
:
1121 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1122 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
1123 unsigned short fpword
;
1126 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
1127 len
= format_double( &double_text
->value
, buf
);
1128 restore_fpword( fpword
);
1129 if (!len
) return E_NOTIMPL
;
1131 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1132 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1133 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1136 case WS_XML_TEXT_TYPE_GUID
:
1138 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1140 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
1141 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1142 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1145 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1147 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1149 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
1150 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1151 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1154 case WS_XML_TEXT_TYPE_DATETIME
:
1156 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
1158 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
1159 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1160 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1163 case WS_XML_TEXT_TYPE_QNAME
:
1165 const WS_XML_QNAME_TEXT
*qn
= (const WS_XML_QNAME_TEXT
*)text
;
1166 ULONG len
= qn
->localName
->length
;
1168 if (qn
->prefix
&& qn
->prefix
->length
) len
+= qn
->prefix
->length
+ 1;
1169 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1170 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1171 (*ret
)->value
.length
= format_qname( qn
->prefix
, qn
->localName
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1175 FIXME( "unhandled text type %u\n", text
->textType
);
1180 static HRESULT
write_attribute_value_bin( struct writer
*writer
, const WS_XML_TEXT
*text
)
1182 enum record_type type
;
1183 BOOL use_dict
= FALSE
;
1187 if (text
&& text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
1189 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1190 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
1192 type
= get_attr_text_record_type( text
, use_dict
);
1194 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1195 write_char( writer
, type
);
1199 case RECORD_CHARS8_TEXT
:
1201 const WS_XML_UTF8_TEXT
*text_utf8
;
1202 WS_XML_UTF8_TEXT
*new = NULL
;
1207 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1208 write_char( writer
, 0 );
1211 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1214 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
1217 len
= text_utf8
->value
.length
;
1218 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
)
1223 write_char( writer
, len
);
1224 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
1228 case RECORD_CHARS16_TEXT
:
1230 const WS_XML_UTF8_TEXT
*text_utf8
;
1231 WS_XML_UTF8_TEXT
*new = NULL
;
1234 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1237 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
1240 len
= text_utf8
->value
.length
;
1241 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
)
1246 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
1247 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
1251 case RECORD_BYTES8_TEXT
:
1253 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
1254 if ((hr
= write_grow_buffer( writer
, 1 + text_base64
->length
)) != S_OK
) return hr
;
1255 write_char( writer
, text_base64
->length
);
1256 write_bytes( writer
, text_base64
->bytes
, text_base64
->length
);
1259 case RECORD_BYTES16_TEXT
:
1261 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
1262 UINT16 len
= text_base64
->length
;
1263 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
1264 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
1265 write_bytes( writer
, text_base64
->bytes
, len
);
1268 case RECORD_ZERO_TEXT
:
1269 case RECORD_ONE_TEXT
:
1270 case RECORD_FALSE_TEXT
:
1271 case RECORD_TRUE_TEXT
:
1274 case RECORD_INT8_TEXT
:
1276 INT8 val
= get_text_value_int( text
);
1277 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1278 write_char( writer
, val
);
1281 case RECORD_INT16_TEXT
:
1283 INT16 val
= get_text_value_int( text
);
1284 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1285 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1288 case RECORD_INT32_TEXT
:
1290 INT32 val
= get_text_value_int( text
);
1291 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1292 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1295 case RECORD_INT64_TEXT
:
1297 INT64 val
= get_text_value_int( text
);
1298 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1299 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1302 case RECORD_UINT64_TEXT
:
1304 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
1305 if ((hr
= write_grow_buffer( writer
, sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
1306 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
1309 case RECORD_DOUBLE_TEXT
:
1311 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
1312 if ((hr
= write_grow_buffer( writer
, sizeof(text_double
->value
) )) != S_OK
) return hr
;
1313 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
1316 case RECORD_GUID_TEXT
:
1318 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
1319 if ((hr
= write_grow_buffer( writer
, sizeof(text_guid
->value
) )) != S_OK
) return hr
;
1320 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
1323 case RECORD_UNIQUE_ID_TEXT
:
1325 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
1326 if ((hr
= write_grow_buffer( writer
, sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
1327 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
1330 case RECORD_DATETIME_TEXT
:
1332 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
1333 UINT64 val
= text_datetime
->value
.ticks
;
1335 assert( val
<= TICKS_MAX
);
1336 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
1337 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
1339 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1340 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1344 FIXME( "unhandled record type %02x\n", type
);
1349 static enum record_type
get_attr_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1351 if (!attr
->prefix
|| !attr
->prefix
->length
)
1353 if (use_dict
) return RECORD_SHORT_DICTIONARY_ATTRIBUTE
;
1354 return RECORD_SHORT_ATTRIBUTE
;
1356 if (attr
->prefix
->length
== 1 && attr
->prefix
->bytes
[0] >= 'a' && attr
->prefix
->bytes
[0] <= 'z')
1358 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
1359 return RECORD_PREFIX_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
1361 if (use_dict
) return RECORD_DICTIONARY_ATTRIBUTE
;
1362 return RECORD_ATTRIBUTE
;
1365 static HRESULT
write_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1368 enum record_type type
= get_attr_record_type( attr
, get_string_id(writer
, attr
->localName
, &id
) );
1371 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1372 write_char( writer
, type
);
1374 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1376 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1377 return write_attribute_value_bin( writer
, attr
->value
);
1379 if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1381 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1382 return write_attribute_value_bin( writer
, attr
->value
);
1387 case RECORD_SHORT_ATTRIBUTE
:
1388 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1391 case RECORD_ATTRIBUTE
:
1392 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1393 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1396 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1397 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1400 case RECORD_DICTIONARY_ATTRIBUTE
:
1401 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1402 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1406 ERR( "unhandled record type %02x\n", type
);
1407 return WS_E_NOT_SUPPORTED
;
1410 return write_attribute_value_bin( writer
, attr
->value
);
1413 static HRESULT
write_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1415 switch (writer
->output_enc
)
1417 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_attribute_text( writer
, attr
);
1418 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_attribute_bin( writer
, attr
);
1420 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1421 return WS_E_NOT_SUPPORTED
;
1425 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1427 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
1430 /**************************************************************************
1431 * WsGetPrefixFromNamespace [webservices.@]
1433 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
1434 BOOL required
, const WS_XML_STRING
**prefix
,
1437 struct writer
*writer
= (struct writer
*)handle
;
1438 WS_XML_ELEMENT_NODE
*elem
;
1442 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
1443 if (error
) FIXME( "ignoring error parameter\n" );
1445 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
1447 EnterCriticalSection( &writer
->cs
);
1449 if (writer
->magic
!= WRITER_MAGIC
)
1451 LeaveCriticalSection( &writer
->cs
);
1452 return E_INVALIDARG
;
1455 elem
= &writer
->current
->hdr
;
1456 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
1458 *prefix
= elem
->prefix
;
1464 if (required
) hr
= WS_E_INVALID_FORMAT
;
1472 LeaveCriticalSection( &writer
->cs
);
1476 static HRESULT
write_namespace_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1478 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
1482 /* ' xmlns:prefix="namespace"' */
1484 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
1485 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
1486 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1488 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
1491 write_char( writer
, ':' );
1492 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
1494 write_char( writer
, '=' );
1495 write_char( writer
, quote
);
1496 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1497 write_char( writer
, quote
);
1502 static enum record_type
get_xmlns_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1504 if (!attr
->prefix
|| !attr
->prefix
->length
)
1506 if (use_dict
) return RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
;
1507 return RECORD_SHORT_XMLNS_ATTRIBUTE
;
1509 if (use_dict
) return RECORD_DICTIONARY_XMLNS_ATTRIBUTE
;
1510 return RECORD_XMLNS_ATTRIBUTE
;
1513 static HRESULT
write_namespace_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1516 enum record_type type
= get_xmlns_record_type( attr
, get_string_id(writer
, attr
->ns
, &id
) );
1519 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1520 write_char( writer
, type
);
1524 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1527 case RECORD_XMLNS_ATTRIBUTE
:
1528 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1531 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1532 return write_dict_string( writer
, id
);
1534 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1535 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1536 return write_dict_string( writer
, id
);
1539 ERR( "unhandled record type %02x\n", type
);
1540 return WS_E_NOT_SUPPORTED
;
1543 return write_string( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1546 static HRESULT
write_namespace_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1548 switch (writer
->output_enc
)
1550 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_namespace_attribute_text( writer
, attr
);
1551 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_namespace_attribute_bin( writer
, attr
);
1553 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1554 return WS_E_NOT_SUPPORTED
;
1558 static HRESULT
add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1559 const WS_XML_STRING
*ns
, BOOL single
)
1561 WS_XML_ATTRIBUTE
*attr
;
1562 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1565 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1567 attr
->singleQuote
= !!single
;
1569 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
1571 free_attribute( attr
);
1572 return E_OUTOFMEMORY
;
1574 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
1576 free_attribute( attr
);
1577 return E_OUTOFMEMORY
;
1579 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1581 free_attribute( attr
);
1587 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
1589 if (!str1
&& !str2
) return TRUE
;
1590 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
1593 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
1594 const WS_XML_STRING
*ns
)
1597 const struct node
*node
;
1599 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
1601 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
1604 for (i
= 0; i
< elem
->attributeCount
; i
++)
1606 if (!elem
->attributes
[i
]->isXmlNs
) continue;
1607 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
1608 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
1614 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1617 if (!(str
= dup_xml_string( ns
, writer
->dict_do_lookup
))) return E_OUTOFMEMORY
;
1618 free_xml_string( writer
->current_ns
);
1619 writer
->current_ns
= str
;
1623 static HRESULT
set_namespaces( struct writer
*writer
)
1625 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1629 if (elem
->ns
->length
&& !namespace_in_scope( elem
, elem
->prefix
, elem
->ns
))
1631 if ((hr
= add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
) return hr
;
1632 if ((hr
= set_current_namespace( writer
, elem
->ns
)) != S_OK
) return hr
;
1635 for (i
= 0; i
< elem
->attributeCount
; i
++)
1637 const WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1638 if (!attr
->ns
->length
|| namespace_in_scope( elem
, attr
->prefix
, attr
->ns
)) continue;
1639 if ((hr
= add_namespace_attribute( writer
, attr
->prefix
, attr
->ns
, FALSE
)) != S_OK
) return hr
;
1645 /**************************************************************************
1646 * WsWriteEndAttribute [webservices.@]
1648 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1650 struct writer
*writer
= (struct writer
*)handle
;
1652 TRACE( "%p %p\n", handle
, error
);
1653 if (error
) FIXME( "ignoring error parameter\n" );
1655 if (!writer
) return E_INVALIDARG
;
1657 EnterCriticalSection( &writer
->cs
);
1659 if (writer
->magic
!= WRITER_MAGIC
)
1661 LeaveCriticalSection( &writer
->cs
);
1662 return E_INVALIDARG
;
1665 writer
->state
= WRITER_STATE_STARTELEMENT
;
1667 LeaveCriticalSection( &writer
->cs
);
1671 static HRESULT
write_attributes( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1675 for (i
= 0; i
< elem
->attributeCount
; i
++)
1677 if (elem
->attributes
[i
]->isXmlNs
) continue;
1678 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1680 for (i
= 0; i
< elem
->attributeCount
; i
++)
1682 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
1683 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1685 for (i
= 0; i
< elem
->attributeCount
; i
++)
1687 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
1688 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1693 static HRESULT
write_startelement_text( struct writer
*writer
)
1695 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1699 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
1701 size
= elem
->localName
->length
+ 1 /* '<' */;
1702 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1703 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1705 write_char( writer
, '<' );
1706 if (elem
->prefix
&& elem
->prefix
->length
)
1708 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1709 write_char( writer
, ':' );
1711 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1712 return write_attributes( writer
, elem
);
1715 static enum record_type
get_elem_record_type( const WS_XML_ELEMENT_NODE
*elem
, BOOL use_dict
)
1717 if (!elem
->prefix
|| !elem
->prefix
->length
)
1719 if (use_dict
) return RECORD_SHORT_DICTIONARY_ELEMENT
;
1720 return RECORD_SHORT_ELEMENT
;
1722 if (elem
->prefix
->length
== 1 && elem
->prefix
->bytes
[0] >= 'a' && elem
->prefix
->bytes
[0] <= 'z')
1724 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1725 return RECORD_PREFIX_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1727 if (use_dict
) return RECORD_DICTIONARY_ELEMENT
;
1728 return RECORD_ELEMENT
;
1731 static HRESULT
write_startelement_bin( struct writer
*writer
)
1733 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1735 enum record_type type
= get_elem_record_type( elem
, get_string_id(writer
, elem
->localName
, &id
) );
1738 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1739 write_char( writer
, type
);
1741 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1743 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1744 return write_attributes( writer
, elem
);
1746 if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1748 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1749 return write_attributes( writer
, elem
);
1754 case RECORD_SHORT_ELEMENT
:
1755 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1758 case RECORD_ELEMENT
:
1759 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1760 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1763 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1764 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1767 case RECORD_DICTIONARY_ELEMENT
:
1768 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1769 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1773 ERR( "unhandled record type %02x\n", type
);
1774 return WS_E_NOT_SUPPORTED
;
1777 return write_attributes( writer
, elem
);
1780 static HRESULT
write_startelement( struct writer
*writer
)
1782 switch (writer
->output_enc
)
1784 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_startelement_text( writer
);
1785 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_startelement_bin( writer
);
1787 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1788 return WS_E_NOT_SUPPORTED
;
1792 static struct node
*write_find_startelement( struct writer
*writer
)
1795 for (node
= writer
->current
; node
; node
= node
->parent
)
1797 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
1802 static inline BOOL
is_empty_element( const struct node
*node
)
1804 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
1805 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
1808 static HRESULT
write_endelement_text( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1815 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
1817 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1818 write_char( writer
, '/' );
1819 write_char( writer
, '>' );
1823 /* '</prefix:localname>' */
1825 size
= elem
->localName
->length
+ 3 /* '</>' */;
1826 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1827 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1829 write_char( writer
, '<' );
1830 write_char( writer
, '/' );
1831 if (elem
->prefix
&& elem
->prefix
->length
)
1833 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1834 write_char( writer
, ':' );
1836 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1837 write_char( writer
, '>' );
1841 static HRESULT
write_endelement_bin( struct writer
*writer
)
1844 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_TEXT
) return S_OK
;
1845 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1846 write_char( writer
, RECORD_ENDELEMENT
);
1850 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1852 switch (writer
->output_enc
)
1854 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endelement_text( writer
, elem
);
1855 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_endelement_bin( writer
);
1857 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1858 return WS_E_NOT_SUPPORTED
;
1862 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
1864 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
1865 elem
->isEmpty
= is_empty_element( node
);
1866 return write_endelement( writer
, elem
);
1869 static HRESULT
write_endelement_node( struct writer
*writer
)
1874 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
1875 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1877 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1878 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1880 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
1881 writer
->current
= node
->parent
;
1882 writer
->state
= WRITER_STATE_ENDELEMENT
;
1886 /**************************************************************************
1887 * WsWriteEndElement [webservices.@]
1889 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1891 struct writer
*writer
= (struct writer
*)handle
;
1894 TRACE( "%p %p\n", handle
, error
);
1895 if (error
) FIXME( "ignoring error parameter\n" );
1897 if (!writer
) return E_INVALIDARG
;
1899 EnterCriticalSection( &writer
->cs
);
1901 if (writer
->magic
!= WRITER_MAGIC
)
1903 LeaveCriticalSection( &writer
->cs
);
1904 return E_INVALIDARG
;
1907 hr
= write_endelement_node( writer
);
1909 LeaveCriticalSection( &writer
->cs
);
1913 static HRESULT
write_endstartelement_text( struct writer
*writer
)
1916 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1917 write_char( writer
, '>' );
1921 static HRESULT
write_endstartelement( struct writer
*writer
)
1923 switch (writer
->output_enc
)
1925 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endstartelement_text( writer
);
1926 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return S_OK
;
1928 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1929 return WS_E_NOT_SUPPORTED
;
1933 /**************************************************************************
1934 * WsWriteEndStartElement [webservices.@]
1936 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1938 struct writer
*writer
= (struct writer
*)handle
;
1941 TRACE( "%p %p\n", handle
, error
);
1942 if (error
) FIXME( "ignoring error parameter\n" );
1944 if (!writer
) return E_INVALIDARG
;
1946 EnterCriticalSection( &writer
->cs
);
1948 if (writer
->magic
!= WRITER_MAGIC
)
1950 LeaveCriticalSection( &writer
->cs
);
1951 return E_INVALIDARG
;
1954 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1956 LeaveCriticalSection( &writer
->cs
);
1957 return WS_E_INVALID_OPERATION
;
1960 if ((hr
= set_namespaces( writer
)) != S_OK
) goto done
;
1961 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
1962 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
1963 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1966 LeaveCriticalSection( &writer
->cs
);
1970 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1971 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1974 WS_XML_ATTRIBUTE
*attr
;
1975 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1978 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1980 if (!prefix
&& ns
->length
) prefix
= elem
->prefix
;
1982 attr
->singleQuote
= !!single
;
1983 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
1985 free_attribute( attr
);
1986 return E_OUTOFMEMORY
;
1988 if (!(attr
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
1990 free_attribute( attr
);
1991 return E_OUTOFMEMORY
;
1993 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
1995 free_attribute( attr
);
1996 return E_OUTOFMEMORY
;
1998 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
2000 free_attribute( attr
);
2006 /**************************************************************************
2007 * WsWriteStartAttribute [webservices.@]
2009 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2010 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2011 BOOL single
, WS_ERROR
*error
)
2013 struct writer
*writer
= (struct writer
*)handle
;
2016 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
2017 debugstr_xmlstr(ns
), single
, error
);
2018 if (error
) FIXME( "ignoring error parameter\n" );
2020 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
2022 EnterCriticalSection( &writer
->cs
);
2024 if (writer
->magic
!= WRITER_MAGIC
)
2026 LeaveCriticalSection( &writer
->cs
);
2027 return E_INVALIDARG
;
2030 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
2032 LeaveCriticalSection( &writer
->cs
);
2033 return WS_E_INVALID_OPERATION
;
2036 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
2037 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2039 LeaveCriticalSection( &writer
->cs
);
2043 /* flush current start element if necessary */
2044 static HRESULT
write_flush( struct writer
*writer
)
2046 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
2049 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
2050 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
2051 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
2052 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
2057 static HRESULT
write_add_cdata_node( struct writer
*writer
)
2059 struct node
*node
, *parent
;
2060 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2061 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2062 write_insert_node( writer
, parent
, node
);
2066 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
2069 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
2070 node
->parent
= writer
->current
;
2071 list_add_tail( &node
->parent
->children
, &node
->entry
);
2075 static HRESULT
write_cdata( struct writer
*writer
)
2078 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
2079 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
2083 static HRESULT
write_cdata_node( struct writer
*writer
)
2086 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2087 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
2088 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
2089 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
2090 writer
->state
= WRITER_STATE_STARTCDATA
;
2094 /**************************************************************************
2095 * WsWriteStartCData [webservices.@]
2097 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2099 struct writer
*writer
= (struct writer
*)handle
;
2102 TRACE( "%p %p\n", handle
, error
);
2103 if (error
) FIXME( "ignoring error parameter\n" );
2105 if (!writer
) return E_INVALIDARG
;
2107 EnterCriticalSection( &writer
->cs
);
2109 if (writer
->magic
!= WRITER_MAGIC
)
2111 LeaveCriticalSection( &writer
->cs
);
2112 return E_INVALIDARG
;
2115 hr
= write_cdata_node( writer
);
2117 LeaveCriticalSection( &writer
->cs
);
2121 static HRESULT
write_endcdata( struct writer
*writer
)
2124 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2125 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
2129 static HRESULT
write_endcdata_node( struct writer
*writer
)
2132 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
2133 writer
->current
= writer
->current
->parent
;
2134 writer
->state
= WRITER_STATE_ENDCDATA
;
2138 /**************************************************************************
2139 * WsWriteEndCData [webservices.@]
2141 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2143 struct writer
*writer
= (struct writer
*)handle
;
2146 TRACE( "%p %p\n", handle
, error
);
2147 if (error
) FIXME( "ignoring error parameter\n" );
2149 if (!writer
) return E_INVALIDARG
;
2151 EnterCriticalSection( &writer
->cs
);
2153 if (writer
->magic
!= WRITER_MAGIC
)
2155 LeaveCriticalSection( &writer
->cs
);
2156 return E_INVALIDARG
;
2159 if (writer
->state
!= WRITER_STATE_TEXT
)
2161 LeaveCriticalSection( &writer
->cs
);
2162 return WS_E_INVALID_OPERATION
;
2165 hr
= write_endcdata_node( writer
);
2167 LeaveCriticalSection( &writer
->cs
);
2171 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2172 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
2174 struct node
*node
, *parent
;
2175 WS_XML_ELEMENT_NODE
*elem
;
2177 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2179 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2181 elem
= &parent
->hdr
;
2182 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
2185 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
2188 if (prefix
&& !(elem
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
2191 return E_OUTOFMEMORY
;
2193 if (!(elem
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
2196 return E_OUTOFMEMORY
;
2198 if (!(elem
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
2201 return E_OUTOFMEMORY
;
2203 write_insert_node( writer
, parent
, node
);
2207 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
2210 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
2211 node
->parent
= parent
;
2212 list_add_tail( &parent
->children
, &node
->entry
);
2216 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2217 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
2220 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2221 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
2222 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
2223 writer
->state
= WRITER_STATE_STARTELEMENT
;
2227 /**************************************************************************
2228 * WsWriteStartElement [webservices.@]
2230 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2231 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2234 struct writer
*writer
= (struct writer
*)handle
;
2237 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
2238 debugstr_xmlstr(ns
), error
);
2239 if (error
) FIXME( "ignoring error parameter\n" );
2241 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
2243 EnterCriticalSection( &writer
->cs
);
2245 if (writer
->magic
!= WRITER_MAGIC
)
2247 LeaveCriticalSection( &writer
->cs
);
2248 return E_INVALIDARG
;
2251 hr
= write_element_node( writer
, prefix
, localname
, ns
);
2253 LeaveCriticalSection( &writer
->cs
);
2257 static HRESULT
text_to_text( const WS_XML_TEXT
*text
, const WS_XML_TEXT
*old
, ULONG
*offset
, WS_XML_TEXT
**ret
)
2259 if (offset
) *offset
= 0;
2260 switch (text
->textType
)
2262 case WS_XML_TEXT_TYPE_UTF8
:
2264 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2265 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2266 WS_XML_UTF8_TEXT
*new;
2267 ULONG len
= utf8
->value
.length
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2269 if (!(new = alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2270 if (utf8_old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2271 memcpy( new->value
.bytes
+ len_old
, utf8
->value
.bytes
, len
);
2272 if (offset
) *offset
= len_old
;
2276 case WS_XML_TEXT_TYPE_UTF16
:
2278 const WS_XML_UTF16_TEXT
*utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2279 const WS_XML_UTF16_TEXT
*utf16_old
= (const WS_XML_UTF16_TEXT
*)old
;
2280 WS_XML_UTF16_TEXT
*new;
2281 ULONG len
= utf16
->byteCount
, len_old
= utf16_old
? utf16_old
->byteCount
: 0;
2283 if (utf16
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2284 if (!(new = alloc_utf16_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2285 if (utf16_old
) memcpy( new->bytes
, utf16_old
->bytes
, len_old
);
2286 memcpy( new->bytes
+ len_old
, utf16
->bytes
, len
);
2287 if (offset
) *offset
= len_old
;
2291 case WS_XML_TEXT_TYPE_BASE64
:
2293 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2294 const WS_XML_BASE64_TEXT
*base64_old
= (const WS_XML_BASE64_TEXT
*)old
;
2295 WS_XML_BASE64_TEXT
*new;
2296 ULONG len
= base64
->length
, len_old
= base64_old
? base64_old
->length
: 0;
2298 if (!(new = alloc_base64_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2299 if (base64_old
) memcpy( new->bytes
, base64_old
->bytes
, len_old
);
2300 memcpy( new->bytes
+ len_old
, base64
->bytes
, len
);
2301 if (offset
) *offset
= len_old
;
2305 case WS_XML_TEXT_TYPE_BOOL
:
2307 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2308 WS_XML_BOOL_TEXT
*new;
2310 if (!(new = alloc_bool_text( bool_text
->value
))) return E_OUTOFMEMORY
;
2314 case WS_XML_TEXT_TYPE_INT32
:
2316 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2317 WS_XML_INT32_TEXT
*new;
2319 if (!(new = alloc_int32_text( int32_text
->value
))) return E_OUTOFMEMORY
;
2323 case WS_XML_TEXT_TYPE_INT64
:
2325 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2326 WS_XML_INT64_TEXT
*new;
2328 if (!(new = alloc_int64_text( int64_text
->value
))) return E_OUTOFMEMORY
;
2332 case WS_XML_TEXT_TYPE_UINT64
:
2334 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2335 WS_XML_UINT64_TEXT
*new;
2337 if (!(new = alloc_uint64_text( uint64_text
->value
))) return E_OUTOFMEMORY
;
2341 case WS_XML_TEXT_TYPE_DOUBLE
:
2343 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2344 WS_XML_DOUBLE_TEXT
*new;
2346 if (!(new = alloc_double_text( double_text
->value
))) return E_OUTOFMEMORY
;
2350 case WS_XML_TEXT_TYPE_GUID
:
2352 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2353 WS_XML_GUID_TEXT
*new;
2355 if (!(new = alloc_guid_text( &id
->value
))) return E_OUTOFMEMORY
;
2359 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2361 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2362 WS_XML_UNIQUE_ID_TEXT
*new;
2364 if (!(new = alloc_unique_id_text( &id
->value
))) return E_OUTOFMEMORY
;
2368 case WS_XML_TEXT_TYPE_DATETIME
:
2370 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2371 WS_XML_DATETIME_TEXT
*new;
2373 if (!(new = alloc_datetime_text( &dt
->value
))) return E_OUTOFMEMORY
;
2378 FIXME( "unhandled text type %u\n", text
->textType
);
2383 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
2385 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2388 switch (value
->textType
)
2390 case WS_XML_TEXT_TYPE_UTF8
:
2391 case WS_XML_TEXT_TYPE_UTF16
:
2392 case WS_XML_TEXT_TYPE_BASE64
:
2395 case WS_XML_TEXT_TYPE_BOOL
:
2396 case WS_XML_TEXT_TYPE_INT32
:
2397 case WS_XML_TEXT_TYPE_INT64
:
2398 case WS_XML_TEXT_TYPE_UINT64
:
2399 case WS_XML_TEXT_TYPE_DOUBLE
:
2400 case WS_XML_TEXT_TYPE_GUID
:
2401 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2402 case WS_XML_TEXT_TYPE_DATETIME
:
2403 if (elem
->attributes
[elem
->attributeCount
- 1]->value
) return WS_E_INVALID_OPERATION
;
2407 FIXME( "unhandled text type %u\n", value
->textType
);
2411 switch (writer
->output_enc
)
2413 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2415 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
2416 if ((hr
= text_to_utf8text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2418 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
2421 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2423 WS_XML_TEXT
*new, *old
= elem
->attributes
[elem
->attributeCount
- 1]->value
;
2424 if ((hr
= text_to_text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2426 elem
->attributes
[elem
->attributeCount
- 1]->value
= new;
2430 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2437 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
2440 WS_XML_TEXT_NODE
*text
;
2443 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
2444 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
2445 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
2447 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2448 text
= (WS_XML_TEXT_NODE
*)node
;
2450 switch (writer
->output_enc
)
2452 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2454 WS_XML_UTF8_TEXT
*new;
2455 if ((hr
= text_to_utf8text( value
, NULL
, NULL
, &new )) != S_OK
)
2460 text
->text
= &new->text
;
2463 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2466 if ((hr
= text_to_text( value
, NULL
, NULL
, &new )) != S_OK
)
2475 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2480 write_insert_node( writer
, writer
->current
, node
);
2484 static HRESULT
write_text_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2486 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2489 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2491 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
2492 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
2494 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
2496 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
2497 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
2501 return WS_E_INVALID_FORMAT
;
2504 static enum record_type
get_text_record_type( const WS_XML_TEXT
*text
, BOOL use_dict
)
2506 switch (text
->textType
)
2508 case WS_XML_TEXT_TYPE_UTF8
:
2510 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2511 if (use_dict
) return RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
;
2512 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2513 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2514 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2516 case WS_XML_TEXT_TYPE_UTF16
:
2518 const WS_XML_UTF16_TEXT
*text_utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2519 int len
= text_utf16
->byteCount
/ sizeof(WCHAR
);
2520 int len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)text_utf16
->bytes
, len
, NULL
, 0, NULL
, NULL
);
2521 if (len_utf8
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2522 if (len_utf8
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2523 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2525 case WS_XML_TEXT_TYPE_BASE64
:
2527 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2528 ULONG rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2529 if (len
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
2530 if (len
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
2531 return RECORD_BYTES32_TEXT
;
2533 case WS_XML_TEXT_TYPE_BOOL
:
2535 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
2536 return text_bool
->value
? RECORD_TRUE_TEXT_WITH_ENDELEMENT
: RECORD_FALSE_TEXT_WITH_ENDELEMENT
;
2538 case WS_XML_TEXT_TYPE_INT32
:
2540 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
2541 if (!text_int32
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2542 if (text_int32
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2543 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2544 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2545 return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2547 case WS_XML_TEXT_TYPE_INT64
:
2549 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
2550 if (!text_int64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2551 if (text_int64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2552 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2553 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2554 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2555 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2557 case WS_XML_TEXT_TYPE_UINT64
:
2559 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
2560 if (!text_uint64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2561 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2562 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2563 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2564 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2565 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2566 return RECORD_UINT64_TEXT_WITH_ENDELEMENT
;
2568 case WS_XML_TEXT_TYPE_DOUBLE
:
2570 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
2571 if (!text_double
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2572 if (text_double
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2573 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
2574 return RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
;
2575 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2576 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2577 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2578 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2580 case WS_XML_TEXT_TYPE_GUID
:
2581 return RECORD_GUID_TEXT_WITH_ENDELEMENT
;
2583 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2584 return RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
;
2586 case WS_XML_TEXT_TYPE_DATETIME
:
2587 return RECORD_DATETIME_TEXT_WITH_ENDELEMENT
;
2590 FIXME( "unhandled text type %u\n", text
->textType
);
2595 static HRESULT
write_text_bin( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2597 enum record_type type
;
2598 BOOL use_dict
= FALSE
;
2604 FIXME( "no support for appending text in binary mode\n" );
2608 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
2610 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2611 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
2614 switch ((type
= get_text_record_type( text
, use_dict
)))
2616 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2618 const WS_XML_UTF8_TEXT
*text_utf8
;
2619 WS_XML_UTF8_TEXT
*new = NULL
;
2622 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2625 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
2628 len
= text_utf8
->value
.length
;
2629 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
)
2634 write_char( writer
, type
);
2635 write_char( writer
, len
);
2636 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2640 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2642 const WS_XML_UTF8_TEXT
*text_utf8
;
2643 WS_XML_UTF8_TEXT
*new = NULL
;
2646 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2649 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
2652 len
= text_utf8
->value
.length
;
2653 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
)
2658 write_char( writer
, type
);
2659 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2660 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2664 case RECORD_BYTES8_TEXT
:
2666 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2667 UINT8 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2671 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2672 write_char( writer
, rem
? RECORD_BYTES8_TEXT
: RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2673 write_char( writer
, len
);
2674 write_bytes( writer
, text_base64
->bytes
, len
);
2678 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2679 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2680 write_char( writer
, rem
);
2681 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2685 case RECORD_BYTES16_TEXT
:
2687 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2688 UINT16 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2692 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2693 write_char( writer
, rem
? RECORD_BYTES16_TEXT
: RECORD_BYTES16_TEXT_WITH_ENDELEMENT
);
2694 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2695 write_bytes( writer
, text_base64
->bytes
, len
);
2699 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2700 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2701 write_char( writer
, rem
);
2702 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2706 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2707 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2708 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2709 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2711 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2712 write_char( writer
, type
);
2715 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2717 INT8 val
= get_text_value_int( text
);
2718 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2719 write_char( writer
, type
);
2720 write_char( writer
, val
);
2723 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2725 INT16 val
= get_text_value_int( text
);
2726 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2727 write_char( writer
, type
);
2728 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2731 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2733 INT32 val
= get_text_value_int( text
);
2734 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2735 write_char( writer
, type
);
2736 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2739 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2741 INT64 val
= get_text_value_int( text
);
2742 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2743 write_char( writer
, type
);
2744 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2747 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2749 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
2750 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
2751 write_char( writer
, type
);
2752 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
2755 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2757 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
2758 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_double
->value
) )) != S_OK
) return hr
;
2759 write_char( writer
, type
);
2760 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
2763 case RECORD_GUID_TEXT_WITH_ENDELEMENT
:
2765 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
2766 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_guid
->value
) )) != S_OK
) return hr
;
2767 write_char( writer
, type
);
2768 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
2771 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
:
2773 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
2774 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
2775 write_char( writer
, type
);
2776 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
2779 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2781 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
2782 UINT64 val
= text_datetime
->value
.ticks
;
2784 assert( val
<= TICKS_MAX
);
2785 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
2786 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
2788 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2789 write_char( writer
, type
);
2790 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2793 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2795 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2796 write_char( writer
, type
);
2797 return write_dict_string( writer
, id
);
2800 FIXME( "unhandled record type %02x\n", type
);
2805 static HRESULT
write_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2807 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
2809 switch (writer
->output_enc
)
2811 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_text_text( writer
, text
, offset
);
2812 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_text_bin( writer
, text
, offset
);
2814 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2815 return WS_E_NOT_SUPPORTED
;
2819 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
2821 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2825 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2826 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
2828 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
2829 node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2833 switch (writer
->output_enc
)
2835 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2837 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
2838 offset
= old
->value
.length
;
2839 if ((hr
= text_to_utf8text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2841 node
->text
= &new->text
;
2844 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2846 WS_XML_TEXT
*new, *old
= node
->text
;
2847 if ((hr
= text_to_text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2853 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2858 if ((hr
= write_text( writer
, node
->text
, offset
)) != S_OK
) return hr
;
2860 writer
->state
= WRITER_STATE_TEXT
;
2864 /**************************************************************************
2865 * WsWriteText [webservices.@]
2867 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
2869 struct writer
*writer
= (struct writer
*)handle
;
2872 TRACE( "%p %p %p\n", handle
, text
, error
);
2873 if (error
) FIXME( "ignoring error parameter\n" );
2875 if (!writer
|| !text
) return E_INVALIDARG
;
2877 EnterCriticalSection( &writer
->cs
);
2879 if (writer
->magic
!= WRITER_MAGIC
)
2881 LeaveCriticalSection( &writer
->cs
);
2882 return E_INVALIDARG
;
2885 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
2886 else hr
= write_text_node( writer
, text
);
2888 LeaveCriticalSection( &writer
->cs
);
2892 /**************************************************************************
2893 * WsWriteBytes [webservices.@]
2895 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
2897 struct writer
*writer
= (struct writer
*)handle
;
2898 WS_XML_BASE64_TEXT base64
;
2901 TRACE( "%p %p %u %p\n", handle
, bytes
, count
, error
);
2902 if (error
) FIXME( "ignoring error parameter\n" );
2904 if (!writer
) return E_INVALIDARG
;
2906 EnterCriticalSection( &writer
->cs
);
2908 if (writer
->magic
!= WRITER_MAGIC
)
2910 LeaveCriticalSection( &writer
->cs
);
2911 return E_INVALIDARG
;
2914 if (!writer
->output_type
)
2916 LeaveCriticalSection( &writer
->cs
);
2917 return WS_E_INVALID_OPERATION
;
2920 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2921 base64
.bytes
= (BYTE
*)bytes
;
2922 base64
.length
= count
;
2924 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
2925 else hr
= write_text_node( writer
, &base64
.text
);
2927 LeaveCriticalSection( &writer
->cs
);
2931 /**************************************************************************
2932 * WsWriteChars [webservices.@]
2934 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
2936 struct writer
*writer
= (struct writer
*)handle
;
2937 WS_XML_UTF16_TEXT utf16
;
2940 TRACE( "%p %s %u %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
2941 if (error
) FIXME( "ignoring error parameter\n" );
2943 if (!writer
) return E_INVALIDARG
;
2945 EnterCriticalSection( &writer
->cs
);
2947 if (writer
->magic
!= WRITER_MAGIC
)
2949 LeaveCriticalSection( &writer
->cs
);
2950 return E_INVALIDARG
;
2953 if (!writer
->output_type
)
2955 LeaveCriticalSection( &writer
->cs
);
2956 return WS_E_INVALID_OPERATION
;
2959 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2960 utf16
.bytes
= (BYTE
*)chars
;
2961 utf16
.byteCount
= count
* sizeof(WCHAR
);
2963 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
2964 else hr
= write_text_node( writer
, &utf16
.text
);
2966 LeaveCriticalSection( &writer
->cs
);
2970 /**************************************************************************
2971 * WsWriteCharsUtf8 [webservices.@]
2973 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
2975 struct writer
*writer
= (struct writer
*)handle
;
2976 WS_XML_UTF8_TEXT utf8
;
2979 TRACE( "%p %s %u %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
2980 if (error
) FIXME( "ignoring error parameter\n" );
2982 if (!writer
) return E_INVALIDARG
;
2984 EnterCriticalSection( &writer
->cs
);
2986 if (writer
->magic
!= WRITER_MAGIC
)
2988 LeaveCriticalSection( &writer
->cs
);
2989 return E_INVALIDARG
;
2992 if (!writer
->output_type
)
2994 LeaveCriticalSection( &writer
->cs
);
2995 return WS_E_INVALID_OPERATION
;
2998 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2999 utf8
.value
.bytes
= (BYTE
*)bytes
;
3000 utf8
.value
.length
= count
;
3002 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
3003 else hr
= write_text_node( writer
, &utf8
.text
);
3005 LeaveCriticalSection( &writer
->cs
);
3009 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
3013 case WS_ELEMENT_TYPE_MAPPING
:
3014 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3015 return write_text_node( writer
, text
);
3017 case WS_ATTRIBUTE_TYPE_MAPPING
:
3018 return write_set_attribute_value( writer
, text
);
3020 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3021 switch (writer
->state
)
3023 case WRITER_STATE_STARTATTRIBUTE
:
3024 return write_set_attribute_value( writer
, text
);
3026 case WRITER_STATE_STARTELEMENT
:
3027 return write_text_node( writer
, text
);
3030 FIXME( "writer state %u not handled\n", writer
->state
);
3035 FIXME( "mapping %u not implemented\n", mapping
);
3040 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
3042 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
3043 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
3044 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
3045 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
3048 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
3049 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
3050 return add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
3053 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
3058 case WS_WRITE_REQUIRED_VALUE
:
3059 case WS_WRITE_NILLABLE_VALUE
:
3060 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
3064 case WS_WRITE_REQUIRED_POINTER
:
3065 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
3068 case WS_WRITE_NILLABLE_POINTER
:
3069 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
3070 *ptr
= *(const void **)value
;
3074 return E_INVALIDARG
;
3078 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3079 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3080 const BOOL
*value
, ULONG size
)
3082 WS_XML_BOOL_TEXT text_bool
;
3088 FIXME( "description not supported\n" );
3092 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3093 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
3094 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3096 text_bool
.text
.textType
= WS_XML_TEXT_TYPE_BOOL
;
3097 text_bool
.value
= *ptr
;
3098 return write_type_text( writer
, mapping
, &text_bool
.text
);
3101 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3102 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3103 const BOOL
*value
, ULONG size
)
3105 WS_XML_INT32_TEXT text_int32
;
3111 FIXME( "description not supported\n" );
3115 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3116 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3117 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3119 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3120 text_int32
.value
= *ptr
;
3121 return write_type_text( writer
, mapping
, &text_int32
.text
);
3124 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3125 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3126 const BOOL
*value
, ULONG size
)
3128 WS_XML_INT32_TEXT text_int32
;
3134 FIXME( "description not supported\n" );
3138 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3139 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3140 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3142 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3143 text_int32
.value
= *ptr
;
3144 return write_type_text( writer
, mapping
, &text_int32
.text
);
3147 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3148 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3149 const void *value
, ULONG size
)
3151 WS_XML_INT32_TEXT text_int32
;
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(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3163 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3165 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3166 text_int32
.value
= *ptr
;
3167 return write_type_text( writer
, mapping
, &text_int32
.text
);
3170 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3171 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3172 const void *value
, ULONG size
)
3174 WS_XML_INT64_TEXT text_int64
;
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(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3186 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3188 text_int64
.text
.textType
= WS_XML_TEXT_TYPE_INT64
;
3189 text_int64
.value
= *ptr
;
3190 return write_type_text( writer
, mapping
, &text_int64
.text
);
3193 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3194 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3195 const void *value
, ULONG size
)
3197 WS_XML_UINT64_TEXT text_uint64
;
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(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3209 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3211 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3212 text_uint64
.value
= *ptr
;
3213 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3216 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3217 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3218 const void *value
, ULONG size
)
3220 WS_XML_UINT64_TEXT text_uint64
;
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(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3232 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3234 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3235 text_uint64
.value
= *ptr
;
3236 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3239 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3240 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3241 const void *value
, ULONG size
)
3243 WS_XML_UINT64_TEXT text_uint64
;
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(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3255 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3257 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3258 text_uint64
.value
= *ptr
;
3259 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3262 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3263 const WS_UINT64_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(UINT64
), (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_double( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3286 const WS_DOUBLE_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3287 const void *value
, ULONG size
)
3289 WS_XML_DOUBLE_TEXT text_double
;
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(double), (const void **)&ptr
)) != S_OK
) return hr
;
3301 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3303 text_double
.text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
3304 text_double
.value
= *ptr
;
3305 return write_type_text( writer
, mapping
, &text_double
.text
);
3308 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3309 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3310 const void *value
, ULONG size
)
3312 WS_XML_DATETIME_TEXT text_datetime
;
3313 const WS_DATETIME
*ptr
;
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(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
3324 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3325 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
3327 text_datetime
.text
.textType
= WS_XML_TEXT_TYPE_DATETIME
;
3328 text_datetime
.value
= *ptr
;
3329 return write_type_text( writer
, mapping
, &text_datetime
.text
);
3332 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3333 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3334 const void *value
, ULONG size
)
3336 WS_XML_GUID_TEXT text_guid
;
3342 FIXME( "description not supported\n" );
3346 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3347 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
3348 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3350 text_guid
.text
.textType
= WS_XML_TEXT_TYPE_GUID
;
3351 text_guid
.value
= *ptr
;
3352 return write_type_text( writer
, mapping
, &text_guid
.text
);
3355 static HRESULT
write_type_unique_id( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3356 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3357 const void *value
, ULONG size
)
3359 WS_XML_UNIQUE_ID_TEXT text_unique_id
;
3360 WS_XML_UTF16_TEXT text_utf16
;
3361 const WS_UNIQUE_ID
*ptr
;
3366 FIXME( "description not supported\n" );
3370 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3371 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3372 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3374 if (ptr
->uri
.length
)
3376 text_utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3377 text_utf16
.bytes
= (BYTE
*)ptr
->uri
.chars
;
3378 text_utf16
.byteCount
= ptr
->uri
.length
* sizeof(WCHAR
);
3379 return write_type_text( writer
, mapping
, &text_utf16
.text
);
3382 text_unique_id
.text
.textType
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
3383 text_unique_id
.value
= ptr
->guid
;
3384 return write_type_text( writer
, mapping
, &text_unique_id
.text
);
3387 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3388 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3389 const void *value
, ULONG size
)
3391 WS_XML_UTF16_TEXT utf16
;
3392 const WS_STRING
*ptr
;
3397 FIXME( "description not supported\n" );
3401 if (!option
) return E_INVALIDARG
;
3402 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3403 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3404 if (!ptr
->length
) return S_OK
;
3406 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3407 utf16
.bytes
= (BYTE
*)ptr
->chars
;
3408 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
3409 return write_type_text( writer
, mapping
, &utf16
.text
);
3412 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3413 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3414 const void *value
, ULONG size
)
3416 WS_XML_UTF16_TEXT utf16
;
3423 FIXME( "description not supported\n" );
3427 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3428 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
3429 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3430 if (!(len
= strlenW( ptr
))) return S_OK
;
3432 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3433 utf16
.bytes
= (BYTE
*)ptr
;
3434 utf16
.byteCount
= len
* sizeof(WCHAR
);
3435 return write_type_text( writer
, mapping
, &utf16
.text
);
3438 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3439 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3440 const void *value
, ULONG size
)
3442 WS_XML_BASE64_TEXT base64
;
3443 const WS_BYTES
*ptr
;
3448 FIXME( "description not supported\n" );
3452 if (!option
) return E_INVALIDARG
;
3453 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
3454 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
3455 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
3456 if (!ptr
->length
) return S_OK
;
3458 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
3459 base64
.bytes
= ptr
->bytes
;
3460 base64
.length
= ptr
->length
;
3461 return write_type_text( writer
, mapping
, &base64
.text
);
3464 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3465 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3466 const void *value
, ULONG size
)
3468 WS_XML_UTF8_TEXT utf8
;
3469 const WS_XML_STRING
*ptr
;
3474 FIXME( "description not supported\n" );
3478 if (!option
) return E_INVALIDARG
;
3479 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3480 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3481 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3482 if (!ptr
->length
) return S_OK
;
3484 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3485 utf8
.value
.bytes
= ptr
->bytes
;
3486 utf8
.value
.length
= ptr
->length
;
3487 return write_type_text( writer
, mapping
, &utf8
.text
);
3490 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
3492 const struct node
*node
;
3493 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3495 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3497 for (i
= 0; i
< elem
->attributeCount
; i
++)
3499 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3500 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
3501 *prefix
= elem
->attributes
[i
]->prefix
;
3505 return WS_E_INVALID_FORMAT
;
3508 static HRESULT
write_type_qname( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3509 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3510 const void *value
, ULONG size
)
3512 WS_XML_QNAME_TEXT qname
;
3513 const WS_XML_QNAME
*ptr
;
3514 const WS_XML_STRING
*prefix
;
3519 FIXME( "description not supported\n" );
3523 if (!option
) return E_INVALIDARG
;
3524 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3525 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3526 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3528 if (((hr
= find_prefix( writer
, &ptr
->ns
, &prefix
)) != S_OK
)) return hr
;
3530 qname
.text
.textType
= WS_XML_TEXT_TYPE_QNAME
;
3531 qname
.prefix
= (WS_XML_STRING
*)prefix
;
3532 qname
.localName
= (WS_XML_STRING
*)&ptr
->localName
;
3533 qname
.ns
= (WS_XML_STRING
*)&ptr
->ns
;
3534 return write_type_text( writer
, mapping
, &qname
.text
);
3537 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
3539 if (options
& WS_FIELD_POINTER
)
3541 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3542 return WS_WRITE_REQUIRED_POINTER
;
3553 case WS_UINT16_TYPE
:
3554 case WS_UINT32_TYPE
:
3555 case WS_UINT64_TYPE
:
3556 case WS_DOUBLE_TYPE
:
3557 case WS_DATETIME_TYPE
:
3559 case WS_UNIQUE_ID_TYPE
:
3560 case WS_STRING_TYPE
:
3562 case WS_XML_STRING_TYPE
:
3563 case WS_XML_QNAME_TYPE
:
3564 case WS_STRUCT_TYPE
:
3567 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
3568 return WS_WRITE_REQUIRED_VALUE
;
3571 case WS_DESCRIPTION_TYPE
:
3572 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3573 return WS_WRITE_REQUIRED_POINTER
;
3576 FIXME( "unhandled type %u\n", type
);
3581 static HRESULT
write_type_field( struct writer
*, const WS_FIELD_DESCRIPTION
*, const char *, ULONG
);
3583 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
3584 const void *, ULONG
);
3586 static HRESULT
write_type_union( struct writer
*writer
, const WS_UNION_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3587 const void *value
, ULONG size
)
3594 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3596 if (size
< sizeof(enum_value
)) return E_INVALIDARG
;
3597 if ((enum_value
= *(int *)(char *)ptr
+ desc
->enumOffset
) == desc
->noneEnumValue
)
3601 case WS_WRITE_REQUIRED_VALUE
:
3602 return WS_E_INVALID_FORMAT
;
3604 case WS_WRITE_NILLABLE_VALUE
:
3608 ERR( "unhandled write option %u\n", option
);
3609 return E_INVALIDARG
;
3613 for (i
= 0; i
< desc
->fieldCount
; i
++)
3615 if (desc
->fields
[i
]->value
== enum_value
)
3617 offset
= desc
->fields
[i
]->field
.offset
;
3618 return write_type_field( writer
, &desc
->fields
[i
]->field
, ptr
, offset
);
3622 return E_INVALIDARG
;
3625 static HRESULT
write_type_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3629 ULONG i
, size
, offset
= 0;
3630 WS_WRITE_OPTION option
;
3632 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3634 /* wrapper element */
3635 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
3638 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
3639 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3641 size
= sizeof(const void *);
3643 for (i
= 0; i
< count
; i
++)
3645 if (desc
->type
== WS_UNION_TYPE
)
3647 if ((hr
= write_type_union( writer
, desc
->typeDescription
, option
, buf
+ offset
, size
)) != S_OK
)
3652 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
3653 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
3654 buf
+ offset
, size
)) != S_OK
) return hr
;
3655 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3660 if (desc
->localName
) hr
= write_endelement_node( writer
);
3664 static HRESULT
write_type_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3668 WS_TYPE_MAPPING mapping
;
3669 WS_WRITE_OPTION option
;
3670 ULONG count
, size
, field_options
= desc
->options
;
3671 const char *ptr
= buf
+ offset
;
3673 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
3675 FIXME( "options 0x%x not supported\n", desc
->options
);
3679 /* zero-terminated strings are always pointers */
3680 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
3682 if (field_options
& WS_FIELD_POINTER
)
3683 size
= sizeof(const void *);
3685 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3687 if (is_nil_value( ptr
, size
))
3689 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
3690 if (field_options
& WS_FIELD_NILLABLE
)
3692 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
3693 else option
= WS_WRITE_NILLABLE_VALUE
;
3697 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3698 else option
= WS_WRITE_REQUIRED_VALUE
;
3703 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3704 else option
= WS_WRITE_REQUIRED_VALUE
;
3707 switch (desc
->mapping
)
3709 case WS_ATTRIBUTE_FIELD_MAPPING
:
3710 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
3711 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
3713 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3715 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3718 case WS_ELEMENT_FIELD_MAPPING
:
3719 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
3720 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3723 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
3724 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
) return E_INVALIDARG
;
3725 option
= (field_options
& WS_FIELD_OPTIONAL
) ? WS_WRITE_NILLABLE_VALUE
: WS_WRITE_REQUIRED_VALUE
;
3726 return write_type_union( writer
, desc
->typeDescription
, option
, ptr
, size
);
3728 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3729 case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING
:
3730 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
3731 return write_type_array( writer
, desc
, *(const char **)ptr
, count
);
3733 case WS_TEXT_FIELD_MAPPING
:
3734 switch (writer
->state
)
3736 case WRITER_STATE_STARTELEMENT
:
3737 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
3740 case WRITER_STATE_STARTATTRIBUTE
:
3741 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3745 FIXME( "unhandled writer state %u\n", writer
->state
);
3751 FIXME( "field mapping %u not supported\n", desc
->mapping
);
3755 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
3760 case WS_ATTRIBUTE_TYPE_MAPPING
:
3761 writer
->state
= WRITER_STATE_STARTELEMENT
;
3764 case WS_ELEMENT_TYPE_MAPPING
:
3765 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3774 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3775 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3776 const void *value
, ULONG size
)
3782 if (!desc
) return E_INVALIDARG
;
3783 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
3785 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3787 for (i
= 0; i
< desc
->fieldCount
; i
++)
3789 offset
= desc
->fields
[i
]->offset
;
3790 if ((hr
= write_type_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
) return hr
;
3796 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3797 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3803 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
3806 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
3809 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
3812 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
3815 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
3818 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
3820 case WS_UINT16_TYPE
:
3821 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
3823 case WS_UINT32_TYPE
:
3824 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
3826 case WS_UINT64_TYPE
:
3827 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
3829 case WS_DOUBLE_TYPE
:
3830 return write_type_double( writer
, mapping
, desc
, option
, value
, size
);
3832 case WS_DATETIME_TYPE
:
3833 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
3836 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
3838 case WS_UNIQUE_ID_TYPE
:
3839 return write_type_unique_id( writer
, mapping
, desc
, option
, value
, size
);
3841 case WS_STRING_TYPE
:
3842 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
3845 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
3848 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
3850 case WS_XML_STRING_TYPE
:
3851 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
3853 case WS_XML_QNAME_TYPE
:
3854 return write_type_qname( writer
, mapping
, desc
, option
, value
, size
);
3856 case WS_STRUCT_TYPE
:
3857 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
3860 FIXME( "type %u not supported\n", type
);
3865 /**************************************************************************
3866 * WsWriteAttribute [webservices.@]
3868 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
3869 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3872 struct writer
*writer
= (struct writer
*)handle
;
3875 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3876 if (error
) FIXME( "ignoring error parameter\n" );
3878 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
3879 return E_INVALIDARG
;
3881 EnterCriticalSection( &writer
->cs
);
3883 if (writer
->magic
!= WRITER_MAGIC
)
3885 LeaveCriticalSection( &writer
->cs
);
3886 return E_INVALIDARG
;
3889 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3891 LeaveCriticalSection( &writer
->cs
);
3892 return WS_E_INVALID_OPERATION
;
3895 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) != S_OK
)
3897 LeaveCriticalSection( &writer
->cs
);
3900 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3902 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
3904 LeaveCriticalSection( &writer
->cs
);
3908 /**************************************************************************
3909 * WsWriteElement [webservices.@]
3911 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3912 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3915 struct writer
*writer
= (struct writer
*)handle
;
3918 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3919 if (error
) FIXME( "ignoring error parameter\n" );
3921 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
3922 return E_INVALIDARG
;
3924 EnterCriticalSection( &writer
->cs
);
3926 if (writer
->magic
!= WRITER_MAGIC
)
3928 LeaveCriticalSection( &writer
->cs
);
3929 return E_INVALIDARG
;
3932 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
3934 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
3935 option
, value
, size
)) != S_OK
) goto done
;
3937 hr
= write_endelement_node( writer
);
3940 LeaveCriticalSection( &writer
->cs
);
3944 /**************************************************************************
3945 * WsWriteType [webservices.@]
3947 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3948 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3949 ULONG size
, WS_ERROR
*error
)
3951 struct writer
*writer
= (struct writer
*)handle
;
3954 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
3956 if (error
) FIXME( "ignoring error parameter\n" );
3958 if (!writer
|| !value
) return E_INVALIDARG
;
3960 EnterCriticalSection( &writer
->cs
);
3962 if (writer
->magic
!= WRITER_MAGIC
)
3964 LeaveCriticalSection( &writer
->cs
);
3965 return E_INVALIDARG
;
3970 case WS_ATTRIBUTE_TYPE_MAPPING
:
3971 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
3972 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3975 case WS_ELEMENT_TYPE_MAPPING
:
3976 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3977 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3978 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3982 FIXME( "mapping %u not implemented\n", mapping
);
3986 LeaveCriticalSection( &writer
->cs
);
3990 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
3994 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
3995 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
3996 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
3997 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
3998 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
3999 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
4000 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
4001 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
4002 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
4003 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
4004 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
4005 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
4006 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
4007 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
4008 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
4010 FIXME( "unhandled type %u\n", type
);
4015 /**************************************************************************
4016 * WsWriteValue [webservices.@]
4018 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
4019 ULONG size
, WS_ERROR
*error
)
4021 struct writer
*writer
= (struct writer
*)handle
;
4022 WS_TYPE_MAPPING mapping
;
4026 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
4027 if (error
) FIXME( "ignoring error parameter\n" );
4029 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
4031 EnterCriticalSection( &writer
->cs
);
4033 if (writer
->magic
!= WRITER_MAGIC
)
4035 LeaveCriticalSection( &writer
->cs
);
4036 return E_INVALIDARG
;
4039 switch (writer
->state
)
4041 case WRITER_STATE_STARTATTRIBUTE
:
4042 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
4045 case WRITER_STATE_STARTELEMENT
:
4046 mapping
= WS_ELEMENT_TYPE_MAPPING
;
4050 hr
= WS_E_INVALID_FORMAT
;
4053 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
4055 LeaveCriticalSection( &writer
->cs
);
4059 /**************************************************************************
4060 * WsWriteArray [webservices.@]
4062 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4063 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
4064 ULONG count
, WS_ERROR
*error
)
4066 struct writer
*writer
= (struct writer
*)handle
;
4071 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
4072 value_type
, array
, size
, offset
, count
, error
);
4073 if (error
) FIXME( "ignoring error parameter\n" );
4075 if (!writer
) return E_INVALIDARG
;
4077 EnterCriticalSection( &writer
->cs
);
4079 if (writer
->magic
!= WRITER_MAGIC
)
4081 LeaveCriticalSection( &writer
->cs
);
4082 return E_INVALIDARG
;
4085 if (!writer
->output_type
)
4087 LeaveCriticalSection( &writer
->cs
);
4088 return WS_E_INVALID_OPERATION
;
4091 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
4093 LeaveCriticalSection( &writer
->cs
);
4094 return E_INVALIDARG
;
4097 type_size
= get_type_size( type
, NULL
);
4098 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
4100 LeaveCriticalSection( &writer
->cs
);
4101 return E_INVALIDARG
;
4104 for (i
= offset
; i
< count
; i
++)
4106 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
4107 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
4108 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
4109 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
4110 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
4114 LeaveCriticalSection( &writer
->cs
);
4118 /**************************************************************************
4119 * WsWriteXmlBuffer [webservices.@]
4121 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
4123 struct writer
*writer
= (struct writer
*)handle
;
4124 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4127 TRACE( "%p %p %p\n", handle
, buffer
, error
);
4128 if (error
) FIXME( "ignoring error parameter\n" );
4130 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
4132 EnterCriticalSection( &writer
->cs
);
4134 if (writer
->magic
!= WRITER_MAGIC
)
4136 LeaveCriticalSection( &writer
->cs
);
4137 return E_INVALIDARG
;
4140 if (xmlbuf
->encoding
!= writer
->output_enc
|| xmlbuf
->charset
!= writer
->output_charset
)
4142 FIXME( "no support for different encoding and/or charset\n" );
4147 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
4148 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
4149 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4152 LeaveCriticalSection( &writer
->cs
);
4156 /**************************************************************************
4157 * WsWriteXmlBufferToBytes [webservices.@]
4159 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
4160 const WS_XML_WRITER_ENCODING
*encoding
,
4161 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
4162 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
4164 struct writer
*writer
= (struct writer
*)handle
;
4165 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4170 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
4171 bytes
, size
, error
);
4172 if (error
) FIXME( "ignoring error parameter\n" );
4174 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
4176 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
4178 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4182 EnterCriticalSection( &writer
->cs
);
4184 if (writer
->magic
!= WRITER_MAGIC
)
4186 LeaveCriticalSection( &writer
->cs
);
4187 return E_INVALIDARG
;
4190 for (i
= 0; i
< count
; i
++)
4192 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4193 properties
[i
].valueSize
);
4194 if (hr
!= S_OK
) goto done
;
4197 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
4200 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4202 *size
= xmlbuf
->bytes
.length
;
4206 LeaveCriticalSection( &writer
->cs
);
4210 /**************************************************************************
4211 * WsWriteXmlnsAttribute [webservices.@]
4213 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4214 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
4216 struct writer
*writer
= (struct writer
*)handle
;
4219 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
4221 if (error
) FIXME( "ignoring error parameter\n" );
4223 if (!writer
|| !ns
) return E_INVALIDARG
;
4225 EnterCriticalSection( &writer
->cs
);
4227 if (writer
->magic
!= WRITER_MAGIC
)
4229 LeaveCriticalSection( &writer
->cs
);
4230 return E_INVALIDARG
;
4233 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4235 LeaveCriticalSection( &writer
->cs
);
4236 return WS_E_INVALID_OPERATION
;
4239 if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
4240 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
4242 LeaveCriticalSection( &writer
->cs
);
4246 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
4247 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
4249 WS_XML_QNAME_TEXT qname
= {{WS_XML_TEXT_TYPE_QNAME
}};
4252 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4253 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) return hr
;
4255 qname
.prefix
= (WS_XML_STRING
*)prefix
;
4256 qname
.localName
= (WS_XML_STRING
*)localname
;
4257 qname
.ns
= (WS_XML_STRING
*)ns
;
4259 if ((hr
= write_add_text_node( writer
, &qname
.text
)) != S_OK
) return hr
;
4260 return write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 );
4263 /**************************************************************************
4264 * WsWriteQualifiedName [webservices.@]
4266 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4267 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4270 struct writer
*writer
= (struct writer
*)handle
;
4273 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
4274 debugstr_xmlstr(ns
), error
);
4275 if (error
) FIXME( "ignoring error parameter\n" );
4277 if (!writer
) return E_INVALIDARG
;
4279 EnterCriticalSection( &writer
->cs
);
4281 if (writer
->magic
!= WRITER_MAGIC
)
4283 LeaveCriticalSection( &writer
->cs
);
4284 return E_INVALIDARG
;
4287 if (!writer
->output_type
)
4289 LeaveCriticalSection( &writer
->cs
);
4290 return WS_E_INVALID_OPERATION
;
4293 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4295 LeaveCriticalSection( &writer
->cs
);
4296 return WS_E_INVALID_FORMAT
;
4299 if (!localname
|| (!prefix
&& !ns
))
4301 LeaveCriticalSection( &writer
->cs
);
4302 return E_INVALIDARG
;
4305 hr
= write_qualified_name( writer
, prefix
, localname
, ns
);
4307 LeaveCriticalSection( &writer
->cs
);
4311 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
4313 BOOL success
= FALSE
;
4314 struct node
*node
= writer
->current
;
4318 case WS_MOVE_TO_ROOT_ELEMENT
:
4319 success
= move_to_root_element( writer
->root
, &node
);
4322 case WS_MOVE_TO_NEXT_ELEMENT
:
4323 success
= move_to_next_element( &node
);
4326 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
4327 success
= move_to_prev_element( &node
);
4330 case WS_MOVE_TO_CHILD_ELEMENT
:
4331 success
= move_to_child_element( &node
);
4334 case WS_MOVE_TO_END_ELEMENT
:
4335 success
= move_to_end_element( &node
);
4338 case WS_MOVE_TO_PARENT_ELEMENT
:
4339 success
= move_to_parent_element( &node
);
4342 case WS_MOVE_TO_FIRST_NODE
:
4343 success
= move_to_first_node( &node
);
4346 case WS_MOVE_TO_NEXT_NODE
:
4347 success
= move_to_next_node( &node
);
4350 case WS_MOVE_TO_PREVIOUS_NODE
:
4351 success
= move_to_prev_node( &node
);
4354 case WS_MOVE_TO_CHILD_NODE
:
4355 success
= move_to_child_node( &node
);
4358 case WS_MOVE_TO_BOF
:
4359 success
= move_to_bof( writer
->root
, &node
);
4362 case WS_MOVE_TO_EOF
:
4363 success
= move_to_eof( writer
->root
, &node
);
4367 FIXME( "unhandled move %u\n", move
);
4371 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
4372 writer
->current
= node
;
4379 return success
? S_OK
: WS_E_INVALID_FORMAT
;
4382 /**************************************************************************
4383 * WsMoveWriter [webservices.@]
4385 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
4387 struct writer
*writer
= (struct writer
*)handle
;
4390 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
4391 if (error
) FIXME( "ignoring error parameter\n" );
4393 if (!writer
) return E_INVALIDARG
;
4395 EnterCriticalSection( &writer
->cs
);
4397 if (writer
->magic
!= WRITER_MAGIC
)
4399 LeaveCriticalSection( &writer
->cs
);
4400 return E_INVALIDARG
;
4403 if (!writer
->output_type
)
4405 LeaveCriticalSection( &writer
->cs
);
4406 return WS_E_INVALID_OPERATION
;
4409 hr
= write_move_to( writer
, move
, found
);
4411 LeaveCriticalSection( &writer
->cs
);
4415 /**************************************************************************
4416 * WsGetWriterPosition [webservices.@]
4418 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4420 struct writer
*writer
= (struct writer
*)handle
;
4422 TRACE( "%p %p %p\n", handle
, pos
, error
);
4423 if (error
) FIXME( "ignoring error parameter\n" );
4425 if (!writer
|| !pos
) return E_INVALIDARG
;
4427 EnterCriticalSection( &writer
->cs
);
4429 if (writer
->magic
!= WRITER_MAGIC
)
4431 LeaveCriticalSection( &writer
->cs
);
4432 return E_INVALIDARG
;
4435 if (!writer
->output_type
)
4437 LeaveCriticalSection( &writer
->cs
);
4438 return WS_E_INVALID_OPERATION
;
4441 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
4442 pos
->node
= writer
->current
;
4444 LeaveCriticalSection( &writer
->cs
);
4448 /**************************************************************************
4449 * WsSetWriterPosition [webservices.@]
4451 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4453 struct writer
*writer
= (struct writer
*)handle
;
4455 TRACE( "%p %p %p\n", handle
, pos
, error
);
4456 if (error
) FIXME( "ignoring error parameter\n" );
4458 if (!writer
|| !pos
) return E_INVALIDARG
;
4460 EnterCriticalSection( &writer
->cs
);
4462 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
4464 LeaveCriticalSection( &writer
->cs
);
4465 return E_INVALIDARG
;
4468 if (!writer
->output_type
)
4470 LeaveCriticalSection( &writer
->cs
);
4471 return WS_E_INVALID_OPERATION
;
4474 writer
->current
= pos
->node
;
4476 LeaveCriticalSection( &writer
->cs
);
4480 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4482 struct node
*node
, *parent
;
4483 WS_XML_COMMENT_NODE
*comment
;
4485 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
4486 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
4487 comment
= (WS_XML_COMMENT_NODE
*)node
;
4489 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
4492 return E_OUTOFMEMORY
;
4494 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
4495 comment
->value
.length
= value
->length
;
4497 write_insert_node( writer
, parent
, node
);
4501 static HRESULT
write_comment_text( struct writer
*writer
)
4503 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4506 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
4507 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
4508 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
4509 write_bytes( writer
, (const BYTE
*)"-->", 3 );
4513 static HRESULT
write_comment_bin( struct writer
*writer
)
4515 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4518 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
4519 write_char( writer
, RECORD_COMMENT
);
4520 return write_string( writer
, comment
->value
.bytes
, comment
->value
.length
);
4523 static HRESULT
write_comment( struct writer
*writer
)
4525 switch (writer
->output_enc
)
4527 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_comment_text( writer
);
4528 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_comment_bin( writer
);
4530 ERR( "unhandled encoding %u\n", writer
->output_enc
);
4531 return WS_E_NOT_SUPPORTED
;
4535 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4538 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4539 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
4540 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4541 writer
->state
= WRITER_STATE_COMMENT
;
4545 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
4550 for (i
= 0; i
< count
; i
++)
4552 const WS_XML_STRING
*prefix
= attrs
[i
]->prefix
;
4553 const WS_XML_STRING
*localname
= attrs
[i
]->localName
;
4554 const WS_XML_STRING
*ns
= attrs
[i
]->ns
;
4555 BOOL single
= attrs
[i
]->singleQuote
;
4557 if (attrs
[i
]->isXmlNs
)
4559 if ((hr
= add_namespace_attribute( writer
, prefix
, ns
, single
)) != S_OK
) return hr
;
4563 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) != S_OK
) return hr
;
4564 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
4570 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
4574 switch (node
->nodeType
)
4576 case WS_XML_NODE_TYPE_ELEMENT
:
4578 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
4579 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
4580 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
4582 case WS_XML_NODE_TYPE_TEXT
:
4584 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4585 return write_text_node( writer
, text
->text
);
4587 case WS_XML_NODE_TYPE_END_ELEMENT
:
4588 return write_endelement_node( writer
);
4590 case WS_XML_NODE_TYPE_COMMENT
:
4592 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
4593 return write_comment_node( writer
, &comment
->value
);
4595 case WS_XML_NODE_TYPE_CDATA
:
4596 return write_cdata_node( writer
);
4598 case WS_XML_NODE_TYPE_END_CDATA
:
4599 return write_endcdata_node( writer
);
4601 case WS_XML_NODE_TYPE_EOF
:
4602 case WS_XML_NODE_TYPE_BOF
:
4606 WARN( "unknown node type %u\n", node
->nodeType
);
4607 return E_INVALIDARG
;
4611 /**************************************************************************
4612 * WsWriteNode [webservices.@]
4614 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
4616 struct writer
*writer
= (struct writer
*)handle
;
4619 TRACE( "%p %p %p\n", handle
, node
, error
);
4620 if (error
) FIXME( "ignoring error parameter\n" );
4622 if (!writer
|| !node
) return E_INVALIDARG
;
4624 EnterCriticalSection( &writer
->cs
);
4626 if (writer
->magic
!= WRITER_MAGIC
)
4628 LeaveCriticalSection( &writer
->cs
);
4629 return E_INVALIDARG
;
4632 if (!writer
->output_type
)
4634 LeaveCriticalSection( &writer
->cs
);
4635 return WS_E_INVALID_OPERATION
;
4638 hr
= write_node( writer
, node
);
4640 LeaveCriticalSection( &writer
->cs
);
4644 static HRESULT
write_tree_node( struct writer
*writer
)
4648 switch (node_type( writer
->current
))
4650 case WS_XML_NODE_TYPE_ELEMENT
:
4651 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4653 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
4654 writer
->state
= WRITER_STATE_STARTELEMENT
;
4657 case WS_XML_NODE_TYPE_TEXT
:
4658 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4660 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
4661 writer
->state
= WRITER_STATE_TEXT
;
4664 case WS_XML_NODE_TYPE_END_ELEMENT
:
4665 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
4666 writer
->state
= WRITER_STATE_ENDELEMENT
;
4669 case WS_XML_NODE_TYPE_COMMENT
:
4670 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4672 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4673 writer
->state
= WRITER_STATE_COMMENT
;
4676 case WS_XML_NODE_TYPE_CDATA
:
4677 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4679 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
4680 writer
->state
= WRITER_STATE_STARTCDATA
;
4683 case WS_XML_NODE_TYPE_END_CDATA
:
4684 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
4685 writer
->state
= WRITER_STATE_ENDCDATA
;
4688 case WS_XML_NODE_TYPE_EOF
:
4689 case WS_XML_NODE_TYPE_BOF
:
4693 ERR( "unknown node type %u\n", node_type(writer
->current
) );
4694 return E_INVALIDARG
;
4698 static HRESULT
write_tree( struct writer
*writer
)
4702 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4705 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
4706 if (move_to_child_node( &writer
->current
))
4708 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4711 if (move_to_next_node( &writer
->current
))
4713 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4716 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
4718 ERR( "invalid tree\n" );
4719 return WS_E_INVALID_FORMAT
;
4721 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4726 static void write_rewind( struct writer
*writer
)
4728 writer
->write_pos
= 0;
4729 writer
->current
= writer
->root
;
4730 writer
->state
= WRITER_STATE_INITIAL
;
4733 /**************************************************************************
4734 * WsCopyNode [webservices.@]
4736 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
4738 struct writer
*writer
= (struct writer
*)handle
;
4739 struct node
*parent
, *current
, *node
= NULL
;
4742 TRACE( "%p %p %p\n", handle
, reader
, error
);
4743 if (error
) FIXME( "ignoring error parameter\n" );
4745 if (!writer
) return E_INVALIDARG
;
4747 EnterCriticalSection( &writer
->cs
);
4749 if (writer
->magic
!= WRITER_MAGIC
)
4751 LeaveCriticalSection( &writer
->cs
);
4752 return E_INVALIDARG
;
4755 if (!(parent
= find_parent( writer
)))
4757 LeaveCriticalSection( &writer
->cs
);
4758 return WS_E_INVALID_FORMAT
;
4761 if ((hr
= copy_node( reader
, &node
)) != S_OK
) goto done
;
4762 current
= writer
->current
;
4763 write_insert_node( writer
, parent
, node
);
4765 write_rewind( writer
);
4766 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
4767 writer
->current
= current
;
4769 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
4772 LeaveCriticalSection( &writer
->cs
);
4776 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
4778 return write_type_field( writer
, desc
, value
, 0 );
4781 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
4784 for (i
= 0; i
< count
; i
++)
4786 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4788 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
4794 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
4797 return write_type_array( writer
, desc
, value
, len
);
4800 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4801 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4803 struct writer
*writer
= (struct writer
*)handle
;
4804 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4805 const WS_FIELD_DESCRIPTION
*desc_field
;
4809 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4811 EnterCriticalSection( &writer
->cs
);
4813 if (writer
->magic
!= WRITER_MAGIC
)
4815 LeaveCriticalSection( &writer
->cs
);
4816 return E_INVALIDARG
;
4819 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4821 for (i
= 0; i
< count
; i
++)
4823 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
4824 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
4826 FIXME( "messages type not supported\n" );
4830 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
4831 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
4833 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
4835 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
4837 const void *ptr
= *(const void **)args
[i
];
4838 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
4839 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
4843 hr
= write_endelement_node( writer
);
4846 LeaveCriticalSection( &writer
->cs
);
4850 HRESULT
writer_enable_lookup( WS_XML_WRITER
*handle
)
4852 struct writer
*writer
= (struct writer
*)handle
;
4854 EnterCriticalSection( &writer
->cs
);
4856 if (writer
->magic
!= WRITER_MAGIC
)
4858 LeaveCriticalSection( &writer
->cs
);
4859 return E_INVALIDARG
;
4862 writer
->dict_do_lookup
= TRUE
;
4864 LeaveCriticalSection( &writer
->cs
);