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_BASE64
:
672 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
673 if (text_base64
->length
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
674 if (text_base64
->length
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
675 return RECORD_BYTES32_TEXT
;
677 case WS_XML_TEXT_TYPE_BOOL
:
679 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
680 return text_bool
->value
? RECORD_TRUE_TEXT
: RECORD_FALSE_TEXT
;
682 case WS_XML_TEXT_TYPE_INT32
:
684 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
685 if (!text_int32
->value
) return RECORD_ZERO_TEXT
;
686 if (text_int32
->value
== 1) return RECORD_ONE_TEXT
;
687 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
688 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
689 return RECORD_INT32_TEXT
;
691 case WS_XML_TEXT_TYPE_INT64
:
693 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
694 if (!text_int64
->value
) return RECORD_ZERO_TEXT
;
695 if (text_int64
->value
== 1) return RECORD_ONE_TEXT
;
696 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
697 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
698 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
699 return RECORD_INT64_TEXT
;
701 case WS_XML_TEXT_TYPE_UINT64
:
703 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
704 if (!text_uint64
->value
) return RECORD_ZERO_TEXT
;
705 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT
;
706 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
707 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
708 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
709 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT
;
710 return RECORD_UINT64_TEXT
;
712 case WS_XML_TEXT_TYPE_DOUBLE
:
714 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
715 if (!text_double
->value
) return RECORD_ZERO_TEXT
;
716 if (text_double
->value
== 1) return RECORD_ONE_TEXT
;
717 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
718 return RECORD_DOUBLE_TEXT
;
719 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
720 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
721 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
722 return RECORD_INT64_TEXT
;
724 case WS_XML_TEXT_TYPE_GUID
:
725 return RECORD_GUID_TEXT
;
727 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
728 return RECORD_UNIQUE_ID_TEXT
;
730 case WS_XML_TEXT_TYPE_DATETIME
:
731 return RECORD_DATETIME_TEXT
;
734 FIXME( "unhandled text type %u\n", text
->textType
);
739 static INT64
get_text_value_int( const WS_XML_TEXT
*text
)
741 switch (text
->textType
)
743 case WS_XML_TEXT_TYPE_INT32
:
745 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
746 return text_int32
->value
;
748 case WS_XML_TEXT_TYPE_INT64
:
750 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
751 return text_int64
->value
;
753 case WS_XML_TEXT_TYPE_UINT64
:
755 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
756 return text_uint64
->value
;
758 case WS_XML_TEXT_TYPE_DOUBLE
:
760 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
761 return text_double
->value
;
764 ERR( "unhandled text type %u\n", text
->textType
);
770 static BOOL
get_string_id( struct writer
*writer
, const WS_XML_STRING
*str
, ULONG
*id
)
772 if (writer
->dict
&& str
->dictionary
== writer
->dict
)
780 writer
->dict_cb( writer
->dict_cb_state
, str
, &found
, id
, NULL
);
781 if (found
) *id
= (*id
<< 1) | 1;
787 static HRESULT
write_attribute_value_bin( struct writer
*writer
, const WS_XML_TEXT
*text
)
789 enum record_type type
;
790 BOOL use_dict
= FALSE
;
794 if (text
&& text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
796 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
797 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
799 type
= get_attr_text_record_type( text
, use_dict
);
801 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
802 write_char( writer
, type
);
806 case RECORD_CHARS8_TEXT
:
808 WS_XML_UTF8_TEXT
*text_utf8
= (WS_XML_UTF8_TEXT
*)text
;
811 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
812 write_char( writer
, 0 );
815 if ((hr
= write_grow_buffer( writer
, 1 + text_utf8
->value
.length
)) != S_OK
) return hr
;
816 write_char( writer
, text_utf8
->value
.length
);
817 write_bytes( writer
, text_utf8
->value
.bytes
, text_utf8
->value
.length
);
820 case RECORD_CHARS16_TEXT
:
822 WS_XML_UTF8_TEXT
*text_utf8
= (WS_XML_UTF8_TEXT
*)text
;
823 UINT16 len
= text_utf8
->value
.length
;
824 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
825 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
826 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
829 case RECORD_BYTES8_TEXT
:
831 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
832 if ((hr
= write_grow_buffer( writer
, 1 + text_base64
->length
)) != S_OK
) return hr
;
833 write_char( writer
, text_base64
->length
);
834 write_bytes( writer
, text_base64
->bytes
, text_base64
->length
);
837 case RECORD_BYTES16_TEXT
:
839 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
840 UINT16 len
= text_base64
->length
;
841 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
842 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
843 write_bytes( writer
, text_base64
->bytes
, len
);
846 case RECORD_ZERO_TEXT
:
847 case RECORD_ONE_TEXT
:
848 case RECORD_FALSE_TEXT
:
849 case RECORD_TRUE_TEXT
:
852 case RECORD_INT8_TEXT
:
854 INT8 val
= get_text_value_int( text
);
855 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
856 write_char( writer
, val
);
859 case RECORD_INT16_TEXT
:
861 INT16 val
= get_text_value_int( text
);
862 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
863 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
866 case RECORD_INT32_TEXT
:
868 INT32 val
= get_text_value_int( text
);
869 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
870 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
873 case RECORD_INT64_TEXT
:
875 INT64 val
= get_text_value_int( text
);
876 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
877 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
880 case RECORD_UINT64_TEXT
:
882 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
883 if ((hr
= write_grow_buffer( writer
, sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
884 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
887 case RECORD_DOUBLE_TEXT
:
889 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
890 if ((hr
= write_grow_buffer( writer
, sizeof(text_double
->value
) )) != S_OK
) return hr
;
891 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
894 case RECORD_GUID_TEXT
:
896 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
897 if ((hr
= write_grow_buffer( writer
, sizeof(text_guid
->value
) )) != S_OK
) return hr
;
898 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
901 case RECORD_UNIQUE_ID_TEXT
:
903 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
904 if ((hr
= write_grow_buffer( writer
, sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
905 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
908 case RECORD_DATETIME_TEXT
:
910 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
911 UINT64 val
= text_datetime
->value
.ticks
;
913 assert( val
<= TICKS_MAX
);
914 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
915 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
917 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
918 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
922 FIXME( "unhandled record type %02x\n", type
);
927 static enum record_type
get_attr_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
929 if (!attr
->prefix
|| !attr
->prefix
->length
)
931 if (use_dict
) return RECORD_SHORT_DICTIONARY_ATTRIBUTE
;
932 return RECORD_SHORT_ATTRIBUTE
;
934 if (attr
->prefix
->length
== 1 && attr
->prefix
->bytes
[0] >= 'a' && attr
->prefix
->bytes
[0] <= 'z')
936 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
937 return RECORD_PREFIX_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
939 if (use_dict
) return RECORD_DICTIONARY_ATTRIBUTE
;
940 return RECORD_ATTRIBUTE
;
943 static HRESULT
write_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
946 enum record_type type
= get_attr_record_type( attr
, get_string_id(writer
, attr
->localName
, &id
) );
949 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
950 write_char( writer
, type
);
952 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
954 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
955 return write_attribute_value_bin( writer
, attr
->value
);
957 if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
959 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
960 return write_attribute_value_bin( writer
, attr
->value
);
965 case RECORD_SHORT_ATTRIBUTE
:
966 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
969 case RECORD_ATTRIBUTE
:
970 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
971 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
974 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
975 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
978 case RECORD_DICTIONARY_ATTRIBUTE
:
979 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
980 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
984 ERR( "unhandled record type %02x\n", type
);
985 return WS_E_NOT_SUPPORTED
;
988 return write_attribute_value_bin( writer
, attr
->value
);
991 static HRESULT
write_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
993 switch (writer
->output_enc
)
995 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_attribute_text( writer
, attr
);
996 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_attribute_bin( writer
, attr
);
998 ERR( "unhandled encoding %u\n", writer
->output_enc
);
999 return WS_E_NOT_SUPPORTED
;
1003 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1005 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
1008 /**************************************************************************
1009 * WsGetPrefixFromNamespace [webservices.@]
1011 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
1012 BOOL required
, const WS_XML_STRING
**prefix
,
1015 struct writer
*writer
= (struct writer
*)handle
;
1016 WS_XML_ELEMENT_NODE
*elem
;
1020 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
1021 if (error
) FIXME( "ignoring error parameter\n" );
1023 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
1025 EnterCriticalSection( &writer
->cs
);
1027 if (writer
->magic
!= WRITER_MAGIC
)
1029 LeaveCriticalSection( &writer
->cs
);
1030 return E_INVALIDARG
;
1033 elem
= &writer
->current
->hdr
;
1034 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
1036 *prefix
= elem
->prefix
;
1042 if (required
) hr
= WS_E_INVALID_FORMAT
;
1050 LeaveCriticalSection( &writer
->cs
);
1054 static HRESULT
write_namespace_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1056 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
1060 /* ' xmlns:prefix="namespace"' */
1062 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
1063 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
1064 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1066 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
1069 write_char( writer
, ':' );
1070 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
1072 write_char( writer
, '=' );
1073 write_char( writer
, quote
);
1074 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1075 write_char( writer
, quote
);
1080 static enum record_type
get_xmlns_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1082 if (!attr
->prefix
|| !attr
->prefix
->length
)
1084 if (use_dict
) return RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
;
1085 return RECORD_SHORT_XMLNS_ATTRIBUTE
;
1087 if (use_dict
) return RECORD_DICTIONARY_XMLNS_ATTRIBUTE
;
1088 return RECORD_XMLNS_ATTRIBUTE
;
1091 static HRESULT
write_namespace_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1094 enum record_type type
= get_xmlns_record_type( attr
, get_string_id(writer
, attr
->ns
, &id
) );
1097 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1098 write_char( writer
, type
);
1102 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1105 case RECORD_XMLNS_ATTRIBUTE
:
1106 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1109 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1110 return write_dict_string( writer
, id
);
1112 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1113 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1114 return write_dict_string( writer
, id
);
1117 ERR( "unhandled record type %02x\n", type
);
1118 return WS_E_NOT_SUPPORTED
;
1121 return write_string( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1124 static HRESULT
write_namespace_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1126 switch (writer
->output_enc
)
1128 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_namespace_attribute_text( writer
, attr
);
1129 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_namespace_attribute_bin( writer
, attr
);
1131 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1132 return WS_E_NOT_SUPPORTED
;
1136 static HRESULT
add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1137 const WS_XML_STRING
*ns
, BOOL single
)
1139 WS_XML_ATTRIBUTE
*attr
;
1140 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1143 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1145 attr
->singleQuote
= !!single
;
1147 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
1149 free_attribute( attr
);
1150 return E_OUTOFMEMORY
;
1152 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
1154 free_attribute( attr
);
1155 return E_OUTOFMEMORY
;
1157 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1159 free_attribute( attr
);
1165 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
1167 if (!str1
&& !str2
) return TRUE
;
1168 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
1171 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
1172 const WS_XML_STRING
*ns
)
1175 const struct node
*node
;
1177 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
1179 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
1182 for (i
= 0; i
< elem
->attributeCount
; i
++)
1184 if (!elem
->attributes
[i
]->isXmlNs
) continue;
1185 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
1186 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
1192 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1195 if (!(str
= dup_xml_string( ns
, writer
->dict_do_lookup
))) return E_OUTOFMEMORY
;
1196 free_xml_string( writer
->current_ns
);
1197 writer
->current_ns
= str
;
1201 static HRESULT
set_namespaces( struct writer
*writer
)
1203 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1207 if (elem
->ns
->length
&& !namespace_in_scope( elem
, elem
->prefix
, elem
->ns
))
1209 if ((hr
= add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
) return hr
;
1210 if ((hr
= set_current_namespace( writer
, elem
->ns
)) != S_OK
) return hr
;
1213 for (i
= 0; i
< elem
->attributeCount
; i
++)
1215 const WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1216 if (!attr
->ns
->length
|| namespace_in_scope( elem
, attr
->prefix
, attr
->ns
)) continue;
1217 if ((hr
= add_namespace_attribute( writer
, attr
->prefix
, attr
->ns
, FALSE
)) != S_OK
) return hr
;
1223 /**************************************************************************
1224 * WsWriteEndAttribute [webservices.@]
1226 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1228 struct writer
*writer
= (struct writer
*)handle
;
1230 TRACE( "%p %p\n", handle
, error
);
1231 if (error
) FIXME( "ignoring error parameter\n" );
1233 if (!writer
) return E_INVALIDARG
;
1235 EnterCriticalSection( &writer
->cs
);
1237 if (writer
->magic
!= WRITER_MAGIC
)
1239 LeaveCriticalSection( &writer
->cs
);
1240 return E_INVALIDARG
;
1243 writer
->state
= WRITER_STATE_STARTELEMENT
;
1245 LeaveCriticalSection( &writer
->cs
);
1249 static HRESULT
write_attributes( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1253 for (i
= 0; i
< elem
->attributeCount
; i
++)
1255 if (elem
->attributes
[i
]->isXmlNs
) continue;
1256 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1258 for (i
= 0; i
< elem
->attributeCount
; i
++)
1260 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
1261 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1263 for (i
= 0; i
< elem
->attributeCount
; i
++)
1265 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
1266 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1271 static HRESULT
write_startelement_text( struct writer
*writer
)
1273 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1277 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
1279 size
= elem
->localName
->length
+ 1 /* '<' */;
1280 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1281 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1283 write_char( writer
, '<' );
1284 if (elem
->prefix
&& elem
->prefix
->length
)
1286 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1287 write_char( writer
, ':' );
1289 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1290 return write_attributes( writer
, elem
);
1293 static enum record_type
get_elem_record_type( const WS_XML_ELEMENT_NODE
*elem
, BOOL use_dict
)
1295 if (!elem
->prefix
|| !elem
->prefix
->length
)
1297 if (use_dict
) return RECORD_SHORT_DICTIONARY_ELEMENT
;
1298 return RECORD_SHORT_ELEMENT
;
1300 if (elem
->prefix
->length
== 1 && elem
->prefix
->bytes
[0] >= 'a' && elem
->prefix
->bytes
[0] <= 'z')
1302 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1303 return RECORD_PREFIX_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1305 if (use_dict
) return RECORD_DICTIONARY_ELEMENT
;
1306 return RECORD_ELEMENT
;
1309 static HRESULT
write_startelement_bin( struct writer
*writer
)
1311 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1313 enum record_type type
= get_elem_record_type( elem
, get_string_id(writer
, elem
->localName
, &id
) );
1316 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1317 write_char( writer
, type
);
1319 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1321 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1322 return write_attributes( writer
, elem
);
1324 if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1326 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1327 return write_attributes( writer
, elem
);
1332 case RECORD_SHORT_ELEMENT
:
1333 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1336 case RECORD_ELEMENT
:
1337 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1338 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1341 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1342 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1345 case RECORD_DICTIONARY_ELEMENT
:
1346 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1347 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1351 ERR( "unhandled record type %02x\n", type
);
1352 return WS_E_NOT_SUPPORTED
;
1355 return write_attributes( writer
, elem
);
1358 static HRESULT
write_startelement( struct writer
*writer
)
1360 switch (writer
->output_enc
)
1362 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_startelement_text( writer
);
1363 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_startelement_bin( writer
);
1365 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1366 return WS_E_NOT_SUPPORTED
;
1370 static struct node
*write_find_startelement( struct writer
*writer
)
1373 for (node
= writer
->current
; node
; node
= node
->parent
)
1375 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
1380 static inline BOOL
is_empty_element( const struct node
*node
)
1382 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
1383 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
1386 static HRESULT
write_endelement_text( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1393 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
1395 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1396 write_char( writer
, '/' );
1397 write_char( writer
, '>' );
1401 /* '</prefix:localname>' */
1403 size
= elem
->localName
->length
+ 3 /* '</>' */;
1404 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1405 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1407 write_char( writer
, '<' );
1408 write_char( writer
, '/' );
1409 if (elem
->prefix
&& elem
->prefix
->length
)
1411 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1412 write_char( writer
, ':' );
1414 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1415 write_char( writer
, '>' );
1419 static HRESULT
write_endelement_bin( struct writer
*writer
)
1422 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_TEXT
) return S_OK
;
1423 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1424 write_char( writer
, RECORD_ENDELEMENT
);
1428 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1430 switch (writer
->output_enc
)
1432 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endelement_text( writer
, elem
);
1433 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_endelement_bin( writer
);
1435 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1436 return WS_E_NOT_SUPPORTED
;
1440 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
1442 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
1443 elem
->isEmpty
= is_empty_element( node
);
1444 return write_endelement( writer
, elem
);
1447 static HRESULT
write_endelement_node( struct writer
*writer
)
1452 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
1453 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1455 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1456 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1458 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
1459 writer
->current
= node
->parent
;
1460 writer
->state
= WRITER_STATE_ENDELEMENT
;
1464 /**************************************************************************
1465 * WsWriteEndElement [webservices.@]
1467 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1469 struct writer
*writer
= (struct writer
*)handle
;
1472 TRACE( "%p %p\n", handle
, error
);
1473 if (error
) FIXME( "ignoring error parameter\n" );
1475 if (!writer
) return E_INVALIDARG
;
1477 EnterCriticalSection( &writer
->cs
);
1479 if (writer
->magic
!= WRITER_MAGIC
)
1481 LeaveCriticalSection( &writer
->cs
);
1482 return E_INVALIDARG
;
1485 hr
= write_endelement_node( writer
);
1487 LeaveCriticalSection( &writer
->cs
);
1491 static HRESULT
write_endstartelement_text( struct writer
*writer
)
1494 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1495 write_char( writer
, '>' );
1499 static HRESULT
write_endstartelement( struct writer
*writer
)
1501 switch (writer
->output_enc
)
1503 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endstartelement_text( writer
);
1504 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return S_OK
;
1506 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1507 return WS_E_NOT_SUPPORTED
;
1511 /**************************************************************************
1512 * WsWriteEndStartElement [webservices.@]
1514 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1516 struct writer
*writer
= (struct writer
*)handle
;
1519 TRACE( "%p %p\n", handle
, error
);
1520 if (error
) FIXME( "ignoring error parameter\n" );
1522 if (!writer
) return E_INVALIDARG
;
1524 EnterCriticalSection( &writer
->cs
);
1526 if (writer
->magic
!= WRITER_MAGIC
)
1528 LeaveCriticalSection( &writer
->cs
);
1529 return E_INVALIDARG
;
1532 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1534 LeaveCriticalSection( &writer
->cs
);
1535 return WS_E_INVALID_OPERATION
;
1538 if ((hr
= set_namespaces( writer
)) != S_OK
) goto done
;
1539 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
1540 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
1541 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1544 LeaveCriticalSection( &writer
->cs
);
1548 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1549 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1552 WS_XML_ATTRIBUTE
*attr
;
1553 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1556 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1558 if (!prefix
&& ns
->length
) prefix
= elem
->prefix
;
1560 attr
->singleQuote
= !!single
;
1561 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
1563 free_attribute( attr
);
1564 return E_OUTOFMEMORY
;
1566 if (!(attr
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
1568 free_attribute( attr
);
1569 return E_OUTOFMEMORY
;
1571 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
1573 free_attribute( attr
);
1574 return E_OUTOFMEMORY
;
1576 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1578 free_attribute( attr
);
1584 /**************************************************************************
1585 * WsWriteStartAttribute [webservices.@]
1587 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1588 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1589 BOOL single
, WS_ERROR
*error
)
1591 struct writer
*writer
= (struct writer
*)handle
;
1594 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1595 debugstr_xmlstr(ns
), single
, error
);
1596 if (error
) FIXME( "ignoring error parameter\n" );
1598 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1600 EnterCriticalSection( &writer
->cs
);
1602 if (writer
->magic
!= WRITER_MAGIC
)
1604 LeaveCriticalSection( &writer
->cs
);
1605 return E_INVALIDARG
;
1608 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1610 LeaveCriticalSection( &writer
->cs
);
1611 return WS_E_INVALID_OPERATION
;
1614 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
1615 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
1617 LeaveCriticalSection( &writer
->cs
);
1621 /* flush current start element if necessary */
1622 static HRESULT
write_flush( struct writer
*writer
)
1624 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1627 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1628 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1629 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
1630 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1635 static HRESULT
write_add_cdata_node( struct writer
*writer
)
1637 struct node
*node
, *parent
;
1638 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1639 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1640 write_insert_node( writer
, parent
, node
);
1644 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
1647 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
1648 node
->parent
= writer
->current
;
1649 list_add_tail( &node
->parent
->children
, &node
->entry
);
1653 static HRESULT
write_cdata( struct writer
*writer
)
1656 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
1657 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
1661 static HRESULT
write_cdata_node( struct writer
*writer
)
1664 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1665 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
1666 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
1667 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
1668 writer
->state
= WRITER_STATE_STARTCDATA
;
1672 /**************************************************************************
1673 * WsWriteStartCData [webservices.@]
1675 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1677 struct writer
*writer
= (struct writer
*)handle
;
1680 TRACE( "%p %p\n", handle
, error
);
1681 if (error
) FIXME( "ignoring error parameter\n" );
1683 if (!writer
) return E_INVALIDARG
;
1685 EnterCriticalSection( &writer
->cs
);
1687 if (writer
->magic
!= WRITER_MAGIC
)
1689 LeaveCriticalSection( &writer
->cs
);
1690 return E_INVALIDARG
;
1693 hr
= write_cdata_node( writer
);
1695 LeaveCriticalSection( &writer
->cs
);
1699 static HRESULT
write_endcdata( struct writer
*writer
)
1702 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
1703 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
1707 static HRESULT
write_endcdata_node( struct writer
*writer
)
1710 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
1711 writer
->current
= writer
->current
->parent
;
1712 writer
->state
= WRITER_STATE_ENDCDATA
;
1716 /**************************************************************************
1717 * WsWriteEndCData [webservices.@]
1719 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1721 struct writer
*writer
= (struct writer
*)handle
;
1724 TRACE( "%p %p\n", handle
, error
);
1725 if (error
) FIXME( "ignoring error parameter\n" );
1727 if (!writer
) return E_INVALIDARG
;
1729 EnterCriticalSection( &writer
->cs
);
1731 if (writer
->magic
!= WRITER_MAGIC
)
1733 LeaveCriticalSection( &writer
->cs
);
1734 return E_INVALIDARG
;
1737 if (writer
->state
!= WRITER_STATE_TEXT
)
1739 LeaveCriticalSection( &writer
->cs
);
1740 return WS_E_INVALID_OPERATION
;
1743 hr
= write_endcdata_node( writer
);
1745 LeaveCriticalSection( &writer
->cs
);
1749 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1750 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1752 struct node
*node
, *parent
;
1753 WS_XML_ELEMENT_NODE
*elem
;
1755 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1757 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1759 elem
= &parent
->hdr
;
1760 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
1763 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
1766 if (prefix
&& !(elem
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
1769 return E_OUTOFMEMORY
;
1771 if (!(elem
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
1774 return E_OUTOFMEMORY
;
1776 if (!(elem
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
1779 return E_OUTOFMEMORY
;
1781 write_insert_node( writer
, parent
, node
);
1785 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
1788 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1789 node
->parent
= parent
;
1790 list_add_tail( &parent
->children
, &node
->entry
);
1794 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1795 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1798 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1799 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
1800 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
1801 writer
->state
= WRITER_STATE_STARTELEMENT
;
1805 /**************************************************************************
1806 * WsWriteStartElement [webservices.@]
1808 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1809 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1812 struct writer
*writer
= (struct writer
*)handle
;
1815 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1816 debugstr_xmlstr(ns
), error
);
1817 if (error
) FIXME( "ignoring error parameter\n" );
1819 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1821 EnterCriticalSection( &writer
->cs
);
1823 if (writer
->magic
!= WRITER_MAGIC
)
1825 LeaveCriticalSection( &writer
->cs
);
1826 return E_INVALIDARG
;
1829 hr
= write_element_node( writer
, prefix
, localname
, ns
);
1831 LeaveCriticalSection( &writer
->cs
);
1835 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
1837 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1840 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1841 return sizeof(bool_true
);
1843 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1844 return sizeof(bool_false
);
1847 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1849 return wsprintfA( (char *)buf
, "%d", *ptr
);
1852 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1854 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1857 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1859 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1862 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
1865 static const long double precision
= 0.0000000000000001;
1866 unsigned char *p
= buf
;
1867 long double val
= *ptr
;
1868 int neg
, mag
, mag2
, use_exp
;
1872 memcpy( buf
, "NaN", 3 );
1879 memcpy( buf
, "-INF", 4 );
1882 memcpy( buf
, "INF", 3 );
1891 if ((neg
= val
< 0))
1897 mag
= log10l( val
);
1898 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1901 if (mag
< 0) mag
-= 1;
1902 val
= val
/ powl( 10.0, mag
);
1906 else if (mag
< 1) mag
= 0;
1908 while (val
> precision
|| mag
>= 0)
1910 long double weight
= powl( 10.0, mag
);
1911 if (weight
> 0 && !isinf( weight
))
1913 int digit
= floorl( val
/ weight
);
1914 val
-= digit
* weight
;
1915 *(p
++) = '0' + digit
;
1917 if (!mag
&& val
> precision
) *(p
++) = '.';
1925 if (mag2
> 0) *(p
++) = '+';
1934 *(p
++) = '0' + mag2
% 10;
1938 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1948 FIXME( "powl not found at build time\n" );
1953 static inline int year_size( int year
)
1955 return leap_year( year
) ? 366 : 365;
1959 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
1961 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
1962 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
1963 unsigned __int64 ticks
, day_ticks
;
1966 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
1967 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
1969 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1970 tz_hour
= TZ_OFFSET
;
1977 day
= ticks
/ TICKS_PER_DAY
;
1978 day_ticks
= ticks
% TICKS_PER_DAY
;
1979 hour
= day_ticks
/ TICKS_PER_HOUR
;
1980 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1981 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1982 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1984 while (day
>= year_size( year
))
1986 day
-= year_size( year
);
1989 while (day
>= month_days
[leap_year( year
)][month
])
1991 day
-= month_days
[leap_year( year
)][month
];
1995 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
1998 static const char fmt_frac
[] = ".%07u";
1999 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
2000 while (buf
[len
- 1] == '0') len
--;
2002 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
2006 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
2008 static const char fmt_tz
[] = "%c%02u:00";
2009 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
2015 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
2017 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
2018 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
2019 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
2020 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
2023 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
2025 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
2026 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
2027 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
2028 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
2031 static ULONG
format_qname( const WS_XML_STRING
*prefix
, const WS_XML_STRING
*localname
, unsigned char *buf
)
2034 if (prefix
&& prefix
->length
)
2036 memcpy( buf
, prefix
->bytes
, prefix
->length
);
2037 len
+= prefix
->length
;
2040 memcpy( buf
+ len
, localname
->bytes
, localname
->length
);
2041 return len
+ localname
->length
;
2044 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
2046 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2051 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
2052 x
= (bin
[0] & 3) << 4;
2055 buf
[i
++] = base64
[x
];
2060 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
2061 x
= (bin
[1] & 0x0f) << 2;
2064 buf
[i
++] = base64
[x
];
2068 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
2069 buf
[i
++] = base64
[bin
[2] & 0x3f];
2076 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, ULONG
*offset
,
2077 WS_XML_UTF8_TEXT
**ret
)
2079 ULONG len_old
= old
? old
->value
.length
: 0;
2080 if (offset
) *offset
= len_old
;
2082 switch (text
->textType
)
2084 case WS_XML_TEXT_TYPE_UTF8
:
2086 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
2088 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
2089 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2090 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
2093 case WS_XML_TEXT_TYPE_UTF16
:
2095 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
2096 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
2097 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
2099 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2100 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
2101 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
2102 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2103 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
2106 case WS_XML_TEXT_TYPE_BASE64
:
2108 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2109 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
2111 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2112 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2113 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2116 case WS_XML_TEXT_TYPE_BOOL
:
2118 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2120 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
2121 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2122 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2125 case WS_XML_TEXT_TYPE_INT32
:
2127 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2128 unsigned char buf
[12]; /* "-2147483648" */
2129 ULONG len
= format_int32( &int32_text
->value
, buf
);
2131 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2132 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2133 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2136 case WS_XML_TEXT_TYPE_INT64
:
2138 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2139 unsigned char buf
[21]; /* "-9223372036854775808" */
2140 ULONG len
= format_int64( &int64_text
->value
, buf
);
2142 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2143 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2144 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2147 case WS_XML_TEXT_TYPE_UINT64
:
2149 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2150 unsigned char buf
[21]; /* "18446744073709551615" */
2151 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
2153 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2154 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2155 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2158 case WS_XML_TEXT_TYPE_DOUBLE
:
2160 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2161 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
2162 unsigned short fpword
;
2165 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
2166 len
= format_double( &double_text
->value
, buf
);
2167 restore_fpword( fpword
);
2168 if (!len
) return E_NOTIMPL
;
2170 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2171 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2172 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
2175 case WS_XML_TEXT_TYPE_GUID
:
2177 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2179 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
2180 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2181 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2184 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2186 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2188 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
2189 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2190 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2193 case WS_XML_TEXT_TYPE_DATETIME
:
2195 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2197 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
2198 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2199 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2202 case WS_XML_TEXT_TYPE_QNAME
:
2204 const WS_XML_QNAME_TEXT
*qn
= (const WS_XML_QNAME_TEXT
*)text
;
2205 ULONG len
= qn
->localName
->length
;
2207 if (qn
->prefix
&& qn
->prefix
->length
) len
+= qn
->prefix
->length
+ 1;
2208 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2209 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
2210 (*ret
)->value
.length
= format_qname( qn
->prefix
, qn
->localName
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
2214 FIXME( "unhandled text type %u\n", text
->textType
);
2219 static HRESULT
text_to_text( const WS_XML_TEXT
*text
, const WS_XML_TEXT
*old
, ULONG
*offset
, WS_XML_TEXT
**ret
)
2221 if (offset
) *offset
= 0;
2222 switch (text
->textType
)
2224 case WS_XML_TEXT_TYPE_UTF8
:
2226 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2227 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2228 WS_XML_UTF8_TEXT
*new;
2229 ULONG len
= utf8
->value
.length
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2231 if (!(new = alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2232 if (utf8_old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2233 memcpy( new->value
.bytes
+ len_old
, utf8
->value
.bytes
, len
);
2234 if (offset
) *offset
= len_old
;
2238 case WS_XML_TEXT_TYPE_UTF16
:
2240 const WS_XML_UTF16_TEXT
*utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2241 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2242 WS_XML_UTF8_TEXT
*new;
2243 const WCHAR
*str
= (const WCHAR
*)utf16
->bytes
;
2244 ULONG len
= utf16
->byteCount
/ sizeof(WCHAR
), len_utf8
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2246 if (utf16
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2247 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
2248 if (!(new = alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
2249 if (old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2250 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)new->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
2251 if (offset
) *offset
= len_old
;
2255 case WS_XML_TEXT_TYPE_BASE64
:
2257 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2258 const WS_XML_BASE64_TEXT
*base64_old
= (const WS_XML_BASE64_TEXT
*)old
;
2259 WS_XML_BASE64_TEXT
*new;
2260 ULONG len
= base64
->length
, len_old
= base64_old
? base64_old
->length
: 0;
2262 if (!(new = alloc_base64_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2263 if (base64_old
) memcpy( new->bytes
, base64_old
->bytes
, len_old
);
2264 memcpy( new->bytes
+ len_old
, base64
->bytes
, len
);
2265 if (offset
) *offset
= len_old
;
2269 case WS_XML_TEXT_TYPE_BOOL
:
2271 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2272 WS_XML_BOOL_TEXT
*new;
2274 if (!(new = alloc_bool_text( bool_text
->value
))) return E_OUTOFMEMORY
;
2278 case WS_XML_TEXT_TYPE_INT32
:
2280 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2281 WS_XML_INT32_TEXT
*new;
2283 if (!(new = alloc_int32_text( int32_text
->value
))) return E_OUTOFMEMORY
;
2287 case WS_XML_TEXT_TYPE_INT64
:
2289 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2290 WS_XML_INT64_TEXT
*new;
2292 if (!(new = alloc_int64_text( int64_text
->value
))) return E_OUTOFMEMORY
;
2296 case WS_XML_TEXT_TYPE_UINT64
:
2298 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2299 WS_XML_UINT64_TEXT
*new;
2301 if (!(new = alloc_uint64_text( uint64_text
->value
))) return E_OUTOFMEMORY
;
2305 case WS_XML_TEXT_TYPE_DOUBLE
:
2307 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2308 WS_XML_DOUBLE_TEXT
*new;
2310 if (!(new = alloc_double_text( double_text
->value
))) return E_OUTOFMEMORY
;
2314 case WS_XML_TEXT_TYPE_GUID
:
2316 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2317 WS_XML_GUID_TEXT
*new;
2319 if (!(new = alloc_guid_text( &id
->value
))) return E_OUTOFMEMORY
;
2323 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2325 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2326 WS_XML_UNIQUE_ID_TEXT
*new;
2328 if (!(new = alloc_unique_id_text( &id
->value
))) return E_OUTOFMEMORY
;
2332 case WS_XML_TEXT_TYPE_DATETIME
:
2334 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2335 WS_XML_DATETIME_TEXT
*new;
2337 if (!(new = alloc_datetime_text( &dt
->value
))) return E_OUTOFMEMORY
;
2342 FIXME( "unhandled text type %u\n", text
->textType
);
2347 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
2349 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2352 switch (value
->textType
)
2354 case WS_XML_TEXT_TYPE_UTF8
:
2355 case WS_XML_TEXT_TYPE_UTF16
:
2356 case WS_XML_TEXT_TYPE_BASE64
:
2359 case WS_XML_TEXT_TYPE_BOOL
:
2360 case WS_XML_TEXT_TYPE_INT32
:
2361 case WS_XML_TEXT_TYPE_INT64
:
2362 case WS_XML_TEXT_TYPE_UINT64
:
2363 case WS_XML_TEXT_TYPE_DOUBLE
:
2364 case WS_XML_TEXT_TYPE_GUID
:
2365 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2366 case WS_XML_TEXT_TYPE_DATETIME
:
2367 if (elem
->attributes
[elem
->attributeCount
- 1]->value
) return WS_E_INVALID_OPERATION
;
2371 FIXME( "unhandled text type %u\n", value
->textType
);
2375 switch (writer
->output_enc
)
2377 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2379 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
2380 if ((hr
= text_to_utf8text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2382 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
2385 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2387 WS_XML_TEXT
*new, *old
= elem
->attributes
[elem
->attributeCount
- 1]->value
;
2388 if ((hr
= text_to_text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2390 elem
->attributes
[elem
->attributeCount
- 1]->value
= new;
2394 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2401 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
2404 WS_XML_TEXT_NODE
*text
;
2407 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
2408 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
2409 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
2411 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2412 text
= (WS_XML_TEXT_NODE
*)node
;
2414 switch (writer
->output_enc
)
2416 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2418 WS_XML_UTF8_TEXT
*new;
2419 if ((hr
= text_to_utf8text( value
, NULL
, NULL
, &new )) != S_OK
)
2424 text
->text
= &new->text
;
2427 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2430 if ((hr
= text_to_text( value
, NULL
, NULL
, &new )) != S_OK
)
2439 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2444 write_insert_node( writer
, writer
->current
, node
);
2448 static HRESULT
write_text_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2450 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2453 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2455 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
2456 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
2458 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
2460 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
2461 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
2465 return WS_E_INVALID_FORMAT
;
2468 static enum record_type
get_text_record_type( const WS_XML_TEXT
*text
, BOOL use_dict
)
2470 switch (text
->textType
)
2472 case WS_XML_TEXT_TYPE_UTF8
:
2474 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2475 if (use_dict
) return RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
;
2476 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2477 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2478 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2480 case WS_XML_TEXT_TYPE_BASE64
:
2482 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2483 ULONG rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2484 if (len
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
2485 if (len
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
2486 return RECORD_BYTES32_TEXT
;
2488 case WS_XML_TEXT_TYPE_BOOL
:
2490 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
2491 return text_bool
->value
? RECORD_TRUE_TEXT_WITH_ENDELEMENT
: RECORD_FALSE_TEXT_WITH_ENDELEMENT
;
2493 case WS_XML_TEXT_TYPE_INT32
:
2495 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
2496 if (!text_int32
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2497 if (text_int32
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2498 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2499 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2500 return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2502 case WS_XML_TEXT_TYPE_INT64
:
2504 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
2505 if (!text_int64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2506 if (text_int64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2507 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2508 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2509 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2510 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2512 case WS_XML_TEXT_TYPE_UINT64
:
2514 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
2515 if (!text_uint64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2516 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2517 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2518 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2519 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2520 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2521 return RECORD_UINT64_TEXT_WITH_ENDELEMENT
;
2523 case WS_XML_TEXT_TYPE_DOUBLE
:
2525 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
2526 if (!text_double
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2527 if (text_double
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2528 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
2529 return RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
;
2530 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2531 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2532 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2533 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2535 case WS_XML_TEXT_TYPE_GUID
:
2536 return RECORD_GUID_TEXT_WITH_ENDELEMENT
;
2538 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2539 return RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
;
2541 case WS_XML_TEXT_TYPE_DATETIME
:
2542 return RECORD_DATETIME_TEXT_WITH_ENDELEMENT
;
2545 FIXME( "unhandled text type %u\n", text
->textType
);
2550 static HRESULT
write_text_bin( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2552 enum record_type type
;
2553 BOOL use_dict
= FALSE
;
2559 FIXME( "no support for appending text in binary mode\n" );
2563 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
2565 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2566 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
2569 switch ((type
= get_text_record_type( text
, use_dict
)))
2571 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2573 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2574 UINT8 len
= text_utf8
->value
.length
;
2576 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2577 write_char( writer
, type
);
2578 write_char( writer
, len
);
2579 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2582 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2584 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2585 UINT16 len
= text_utf8
->value
.length
;
2587 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2588 write_char( writer
, type
);
2589 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2590 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2593 case RECORD_BYTES8_TEXT
:
2595 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2596 UINT8 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2600 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2601 write_char( writer
, rem
? RECORD_BYTES8_TEXT
: RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2602 write_char( writer
, len
);
2603 write_bytes( writer
, text_base64
->bytes
, len
);
2607 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2608 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2609 write_char( writer
, rem
);
2610 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2614 case RECORD_BYTES16_TEXT
:
2616 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2617 UINT16 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2621 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2622 write_char( writer
, rem
? RECORD_BYTES16_TEXT
: RECORD_BYTES16_TEXT_WITH_ENDELEMENT
);
2623 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2624 write_bytes( writer
, text_base64
->bytes
, len
);
2628 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2629 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2630 write_char( writer
, rem
);
2631 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2635 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2636 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2637 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2638 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2640 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2641 write_char( writer
, type
);
2644 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2646 INT8 val
= get_text_value_int( text
);
2647 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2648 write_char( writer
, type
);
2649 write_char( writer
, val
);
2652 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2654 INT16 val
= get_text_value_int( text
);
2655 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2656 write_char( writer
, type
);
2657 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2660 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2662 INT32 val
= get_text_value_int( text
);
2663 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2664 write_char( writer
, type
);
2665 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2668 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2670 INT64 val
= get_text_value_int( text
);
2671 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2672 write_char( writer
, type
);
2673 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2676 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2678 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
2679 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
2680 write_char( writer
, type
);
2681 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
2684 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2686 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
2687 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_double
->value
) )) != S_OK
) return hr
;
2688 write_char( writer
, type
);
2689 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
2692 case RECORD_GUID_TEXT_WITH_ENDELEMENT
:
2694 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
2695 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_guid
->value
) )) != S_OK
) return hr
;
2696 write_char( writer
, type
);
2697 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
2700 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
:
2702 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
2703 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
2704 write_char( writer
, type
);
2705 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
2708 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2710 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
2711 UINT64 val
= text_datetime
->value
.ticks
;
2713 assert( val
<= TICKS_MAX
);
2714 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
2715 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
2717 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2718 write_char( writer
, type
);
2719 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2722 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2724 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2725 write_char( writer
, type
);
2726 return write_dict_string( writer
, id
);
2729 FIXME( "unhandled record type %02x\n", type
);
2734 static HRESULT
write_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2736 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
2738 switch (writer
->output_enc
)
2740 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_text_text( writer
, text
, offset
);
2741 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_text_bin( writer
, text
, offset
);
2743 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2744 return WS_E_NOT_SUPPORTED
;
2748 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
2750 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2754 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2755 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
2757 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
2758 node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2762 switch (writer
->output_enc
)
2764 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2766 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
2767 offset
= old
->value
.length
;
2768 if ((hr
= text_to_utf8text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2770 node
->text
= &new->text
;
2773 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2775 WS_XML_TEXT
*new, *old
= node
->text
;
2776 if ((hr
= text_to_text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2782 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2787 if ((hr
= write_text( writer
, node
->text
, offset
)) != S_OK
) return hr
;
2789 writer
->state
= WRITER_STATE_TEXT
;
2793 /**************************************************************************
2794 * WsWriteText [webservices.@]
2796 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
2798 struct writer
*writer
= (struct writer
*)handle
;
2801 TRACE( "%p %p %p\n", handle
, text
, error
);
2802 if (error
) FIXME( "ignoring error parameter\n" );
2804 if (!writer
|| !text
) return E_INVALIDARG
;
2806 EnterCriticalSection( &writer
->cs
);
2808 if (writer
->magic
!= WRITER_MAGIC
)
2810 LeaveCriticalSection( &writer
->cs
);
2811 return E_INVALIDARG
;
2814 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
2815 else hr
= write_text_node( writer
, text
);
2817 LeaveCriticalSection( &writer
->cs
);
2821 /**************************************************************************
2822 * WsWriteBytes [webservices.@]
2824 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
2826 struct writer
*writer
= (struct writer
*)handle
;
2827 WS_XML_BASE64_TEXT base64
;
2830 TRACE( "%p %p %u %p\n", handle
, bytes
, count
, error
);
2831 if (error
) FIXME( "ignoring error parameter\n" );
2833 if (!writer
) return E_INVALIDARG
;
2835 EnterCriticalSection( &writer
->cs
);
2837 if (writer
->magic
!= WRITER_MAGIC
)
2839 LeaveCriticalSection( &writer
->cs
);
2840 return E_INVALIDARG
;
2843 if (!writer
->output_type
)
2845 LeaveCriticalSection( &writer
->cs
);
2846 return WS_E_INVALID_OPERATION
;
2849 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2850 base64
.bytes
= (BYTE
*)bytes
;
2851 base64
.length
= count
;
2853 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
2854 else hr
= write_text_node( writer
, &base64
.text
);
2856 LeaveCriticalSection( &writer
->cs
);
2860 /**************************************************************************
2861 * WsWriteChars [webservices.@]
2863 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
2865 struct writer
*writer
= (struct writer
*)handle
;
2866 WS_XML_UTF16_TEXT utf16
;
2869 TRACE( "%p %s %u %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
2870 if (error
) FIXME( "ignoring error parameter\n" );
2872 if (!writer
) return E_INVALIDARG
;
2874 EnterCriticalSection( &writer
->cs
);
2876 if (writer
->magic
!= WRITER_MAGIC
)
2878 LeaveCriticalSection( &writer
->cs
);
2879 return E_INVALIDARG
;
2882 if (!writer
->output_type
)
2884 LeaveCriticalSection( &writer
->cs
);
2885 return WS_E_INVALID_OPERATION
;
2888 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2889 utf16
.bytes
= (BYTE
*)chars
;
2890 utf16
.byteCount
= count
* sizeof(WCHAR
);
2892 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
2893 else hr
= write_text_node( writer
, &utf16
.text
);
2895 LeaveCriticalSection( &writer
->cs
);
2899 /**************************************************************************
2900 * WsWriteCharsUtf8 [webservices.@]
2902 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
2904 struct writer
*writer
= (struct writer
*)handle
;
2905 WS_XML_UTF8_TEXT utf8
;
2908 TRACE( "%p %s %u %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
2909 if (error
) FIXME( "ignoring error parameter\n" );
2911 if (!writer
) return E_INVALIDARG
;
2913 EnterCriticalSection( &writer
->cs
);
2915 if (writer
->magic
!= WRITER_MAGIC
)
2917 LeaveCriticalSection( &writer
->cs
);
2918 return E_INVALIDARG
;
2921 if (!writer
->output_type
)
2923 LeaveCriticalSection( &writer
->cs
);
2924 return WS_E_INVALID_OPERATION
;
2927 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2928 utf8
.value
.bytes
= (BYTE
*)bytes
;
2929 utf8
.value
.length
= count
;
2931 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
2932 else hr
= write_text_node( writer
, &utf8
.text
);
2934 LeaveCriticalSection( &writer
->cs
);
2938 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
2942 case WS_ELEMENT_TYPE_MAPPING
:
2943 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2944 return write_text_node( writer
, text
);
2946 case WS_ATTRIBUTE_TYPE_MAPPING
:
2947 return write_set_attribute_value( writer
, text
);
2949 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2950 switch (writer
->state
)
2952 case WRITER_STATE_STARTATTRIBUTE
:
2953 return write_set_attribute_value( writer
, text
);
2955 case WRITER_STATE_STARTELEMENT
:
2956 return write_text_node( writer
, text
);
2959 FIXME( "writer state %u not handled\n", writer
->state
);
2964 FIXME( "mapping %u not implemented\n", mapping
);
2969 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
2971 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
2972 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
2973 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
2974 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
2977 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
2978 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
2979 return add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
2982 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
2987 case WS_WRITE_REQUIRED_VALUE
:
2988 case WS_WRITE_NILLABLE_VALUE
:
2989 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
2993 case WS_WRITE_REQUIRED_POINTER
:
2994 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
2997 case WS_WRITE_NILLABLE_POINTER
:
2998 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
2999 *ptr
= *(const void **)value
;
3003 return E_INVALIDARG
;
3007 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3008 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3009 const BOOL
*value
, ULONG size
)
3011 WS_XML_BOOL_TEXT text_bool
;
3017 FIXME( "description not supported\n" );
3021 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3022 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
3023 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3025 text_bool
.text
.textType
= WS_XML_TEXT_TYPE_BOOL
;
3026 text_bool
.value
= *ptr
;
3027 return write_type_text( writer
, mapping
, &text_bool
.text
);
3030 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3031 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3032 const BOOL
*value
, ULONG size
)
3034 WS_XML_INT32_TEXT text_int32
;
3040 FIXME( "description not supported\n" );
3044 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3045 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3046 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3048 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3049 text_int32
.value
= *ptr
;
3050 return write_type_text( writer
, mapping
, &text_int32
.text
);
3053 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3054 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3055 const BOOL
*value
, ULONG size
)
3057 WS_XML_INT32_TEXT text_int32
;
3063 FIXME( "description not supported\n" );
3067 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3068 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3069 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3071 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3072 text_int32
.value
= *ptr
;
3073 return write_type_text( writer
, mapping
, &text_int32
.text
);
3076 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3077 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3078 const void *value
, ULONG size
)
3080 WS_XML_INT32_TEXT text_int32
;
3086 FIXME( "description not supported\n" );
3090 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3091 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3092 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3094 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3095 text_int32
.value
= *ptr
;
3096 return write_type_text( writer
, mapping
, &text_int32
.text
);
3099 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3100 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3101 const void *value
, ULONG size
)
3103 WS_XML_INT64_TEXT text_int64
;
3109 FIXME( "description not supported\n" );
3113 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3114 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3115 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3117 text_int64
.text
.textType
= WS_XML_TEXT_TYPE_INT64
;
3118 text_int64
.value
= *ptr
;
3119 return write_type_text( writer
, mapping
, &text_int64
.text
);
3122 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3123 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3124 const void *value
, ULONG size
)
3126 WS_XML_UINT64_TEXT text_uint64
;
3132 FIXME( "description not supported\n" );
3136 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3137 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3138 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3140 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3141 text_uint64
.value
= *ptr
;
3142 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3145 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3146 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3147 const void *value
, ULONG size
)
3149 WS_XML_UINT64_TEXT text_uint64
;
3155 FIXME( "description not supported\n" );
3159 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3160 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3161 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3163 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3164 text_uint64
.value
= *ptr
;
3165 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3168 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3169 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3170 const void *value
, ULONG size
)
3172 WS_XML_UINT64_TEXT text_uint64
;
3178 FIXME( "description not supported\n" );
3182 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3183 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3184 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3186 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3187 text_uint64
.value
= *ptr
;
3188 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3191 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3192 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3193 const void *value
, ULONG size
)
3195 WS_XML_UINT64_TEXT text_uint64
;
3201 FIXME( "description not supported\n" );
3205 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3206 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3207 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3209 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3210 text_uint64
.value
= *ptr
;
3211 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3214 static HRESULT
write_type_double( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3215 const WS_DOUBLE_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3216 const void *value
, ULONG size
)
3218 WS_XML_DOUBLE_TEXT text_double
;
3224 FIXME( "description not supported\n" );
3228 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3229 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(double), (const void **)&ptr
)) != S_OK
) return hr
;
3230 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3232 text_double
.text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
3233 text_double
.value
= *ptr
;
3234 return write_type_text( writer
, mapping
, &text_double
.text
);
3237 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3238 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3239 const void *value
, ULONG size
)
3241 WS_XML_DATETIME_TEXT text_datetime
;
3242 const WS_DATETIME
*ptr
;
3247 FIXME( "description not supported\n" );
3251 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3252 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
3253 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3254 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
3256 text_datetime
.text
.textType
= WS_XML_TEXT_TYPE_DATETIME
;
3257 text_datetime
.value
= *ptr
;
3258 return write_type_text( writer
, mapping
, &text_datetime
.text
);
3261 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3262 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3263 const void *value
, ULONG size
)
3265 WS_XML_GUID_TEXT text_guid
;
3271 FIXME( "description not supported\n" );
3275 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3276 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
3277 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3279 text_guid
.text
.textType
= WS_XML_TEXT_TYPE_GUID
;
3280 text_guid
.value
= *ptr
;
3281 return write_type_text( writer
, mapping
, &text_guid
.text
);
3284 static HRESULT
write_type_unique_id( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3285 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3286 const void *value
, ULONG size
)
3288 WS_XML_UNIQUE_ID_TEXT text_unique_id
;
3289 WS_XML_UTF16_TEXT text_utf16
;
3290 const WS_UNIQUE_ID
*ptr
;
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(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3301 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3303 if (ptr
->uri
.length
)
3305 text_utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3306 text_utf16
.bytes
= (BYTE
*)ptr
->uri
.chars
;
3307 text_utf16
.byteCount
= ptr
->uri
.length
* sizeof(WCHAR
);
3308 return write_type_text( writer
, mapping
, &text_utf16
.text
);
3311 text_unique_id
.text
.textType
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
3312 text_unique_id
.value
= ptr
->guid
;
3313 return write_type_text( writer
, mapping
, &text_unique_id
.text
);
3316 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3317 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3318 const void *value
, ULONG size
)
3320 WS_XML_UTF16_TEXT utf16
;
3321 const WS_STRING
*ptr
;
3326 FIXME( "description not supported\n" );
3330 if (!option
) return E_INVALIDARG
;
3331 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3332 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3333 if (!ptr
->length
) return S_OK
;
3335 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3336 utf16
.bytes
= (BYTE
*)ptr
->chars
;
3337 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
3338 return write_type_text( writer
, mapping
, &utf16
.text
);
3341 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3342 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3343 const void *value
, ULONG size
)
3345 WS_XML_UTF16_TEXT utf16
;
3352 FIXME( "description not supported\n" );
3356 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3357 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
3358 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3359 if (!(len
= strlenW( ptr
))) return S_OK
;
3361 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3362 utf16
.bytes
= (BYTE
*)ptr
;
3363 utf16
.byteCount
= len
* sizeof(WCHAR
);
3364 return write_type_text( writer
, mapping
, &utf16
.text
);
3367 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3368 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3369 const void *value
, ULONG size
)
3371 WS_XML_BASE64_TEXT base64
;
3372 const WS_BYTES
*ptr
;
3377 FIXME( "description not supported\n" );
3381 if (!option
) return E_INVALIDARG
;
3382 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
3383 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
3384 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
3385 if (!ptr
->length
) return S_OK
;
3387 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
3388 base64
.bytes
= ptr
->bytes
;
3389 base64
.length
= ptr
->length
;
3390 return write_type_text( writer
, mapping
, &base64
.text
);
3393 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3394 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3395 const void *value
, ULONG size
)
3397 WS_XML_UTF8_TEXT utf8
;
3398 const WS_XML_STRING
*ptr
;
3403 FIXME( "description not supported\n" );
3407 if (!option
) return E_INVALIDARG
;
3408 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3409 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3410 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3411 if (!ptr
->length
) return S_OK
;
3413 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3414 utf8
.value
.bytes
= ptr
->bytes
;
3415 utf8
.value
.length
= ptr
->length
;
3416 return write_type_text( writer
, mapping
, &utf8
.text
);
3419 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
3421 const struct node
*node
;
3422 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3424 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3426 for (i
= 0; i
< elem
->attributeCount
; i
++)
3428 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3429 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
3430 *prefix
= elem
->attributes
[i
]->prefix
;
3434 return WS_E_INVALID_FORMAT
;
3437 static HRESULT
write_type_qname( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3438 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3439 const void *value
, ULONG size
)
3441 WS_XML_QNAME_TEXT qname
;
3442 const WS_XML_QNAME
*ptr
;
3443 const WS_XML_STRING
*prefix
;
3448 FIXME( "description not supported\n" );
3452 if (!option
) return E_INVALIDARG
;
3453 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3454 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3455 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3457 if (((hr
= find_prefix( writer
, &ptr
->ns
, &prefix
)) != S_OK
)) return hr
;
3459 qname
.text
.textType
= WS_XML_TEXT_TYPE_QNAME
;
3460 qname
.prefix
= (WS_XML_STRING
*)prefix
;
3461 qname
.localName
= (WS_XML_STRING
*)&ptr
->localName
;
3462 qname
.ns
= (WS_XML_STRING
*)&ptr
->ns
;
3463 return write_type_text( writer
, mapping
, &qname
.text
);
3466 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
3468 if (options
& WS_FIELD_POINTER
)
3470 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3471 return WS_WRITE_REQUIRED_POINTER
;
3482 case WS_UINT16_TYPE
:
3483 case WS_UINT32_TYPE
:
3484 case WS_UINT64_TYPE
:
3485 case WS_DOUBLE_TYPE
:
3486 case WS_DATETIME_TYPE
:
3488 case WS_UNIQUE_ID_TYPE
:
3489 case WS_STRING_TYPE
:
3491 case WS_XML_STRING_TYPE
:
3492 case WS_XML_QNAME_TYPE
:
3493 case WS_STRUCT_TYPE
:
3495 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
3496 return WS_WRITE_REQUIRED_VALUE
;
3499 case WS_DESCRIPTION_TYPE
:
3500 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3501 return WS_WRITE_REQUIRED_POINTER
;
3504 FIXME( "unhandled type %u\n", type
);
3509 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
3510 const void *, ULONG
);
3512 static HRESULT
write_type_repeating_element( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
3513 const char *buf
, ULONG count
)
3516 ULONG i
, size
, offset
= 0;
3517 WS_WRITE_OPTION option
;
3519 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3521 /* wrapper element */
3522 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
3525 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
3526 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3528 size
= sizeof(const void *);
3530 for (i
= 0; i
< count
; i
++)
3532 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
3533 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
3534 buf
+ offset
, size
)) != S_OK
) return hr
;
3535 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3539 if (desc
->localName
) hr
= write_endelement_node( writer
);
3543 static HRESULT
write_type_field( struct writer
*, const WS_FIELD_DESCRIPTION
*, const char *, ULONG
);
3545 static HRESULT
write_type_union( struct writer
*writer
, const WS_UNION_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3546 const void *value
, ULONG size
)
3553 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3555 if (size
< sizeof(enum_value
)) return E_INVALIDARG
;
3556 if ((enum_value
= *(int *)(char *)ptr
+ desc
->enumOffset
) == desc
->noneEnumValue
)
3560 case WS_WRITE_REQUIRED_VALUE
:
3561 return WS_E_INVALID_FORMAT
;
3563 case WS_WRITE_NILLABLE_VALUE
:
3567 ERR( "unhandled write option %u\n", option
);
3568 return E_INVALIDARG
;
3572 for (i
= 0; i
< desc
->fieldCount
; i
++)
3574 if (desc
->fields
[i
]->value
== enum_value
)
3576 offset
= desc
->fields
[i
]->field
.offset
;
3577 return write_type_field( writer
, &desc
->fields
[i
]->field
, ptr
, offset
);
3581 return E_INVALIDARG
;
3584 static HRESULT
write_type_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3588 WS_TYPE_MAPPING mapping
;
3589 WS_WRITE_OPTION option
;
3590 ULONG count
, size
, field_options
= desc
->options
;
3591 const char *ptr
= buf
+ offset
;
3593 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
3595 FIXME( "options 0x%x not supported\n", desc
->options
);
3599 /* zero-terminated strings are always pointers */
3600 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
3602 if (field_options
& WS_FIELD_POINTER
)
3603 size
= sizeof(const void *);
3605 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3607 if (is_nil_value( ptr
, size
))
3609 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
3610 if (field_options
& WS_FIELD_NILLABLE
)
3612 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
3613 else option
= WS_WRITE_NILLABLE_VALUE
;
3617 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3618 else option
= WS_WRITE_REQUIRED_VALUE
;
3623 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3624 else option
= WS_WRITE_REQUIRED_VALUE
;
3627 switch (desc
->mapping
)
3629 case WS_ATTRIBUTE_FIELD_MAPPING
:
3630 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
3631 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
3633 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3635 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3638 case WS_ELEMENT_FIELD_MAPPING
:
3639 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
3640 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3643 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
3644 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
) return E_INVALIDARG
;
3645 option
= (field_options
& WS_FIELD_OPTIONAL
) ? WS_WRITE_NILLABLE_VALUE
: WS_WRITE_REQUIRED_VALUE
;
3646 return write_type_union( writer
, desc
->typeDescription
, option
, ptr
, size
);
3648 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3649 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
3650 return write_type_repeating_element( writer
, desc
, *(const char **)ptr
, count
);
3652 case WS_TEXT_FIELD_MAPPING
:
3653 switch (writer
->state
)
3655 case WRITER_STATE_STARTELEMENT
:
3656 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
3659 case WRITER_STATE_STARTATTRIBUTE
:
3660 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3664 FIXME( "unhandled writer state %u\n", writer
->state
);
3670 FIXME( "field mapping %u not supported\n", desc
->mapping
);
3674 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
3679 case WS_ATTRIBUTE_TYPE_MAPPING
:
3680 writer
->state
= WRITER_STATE_STARTELEMENT
;
3683 case WS_ELEMENT_TYPE_MAPPING
:
3684 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3693 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3694 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3695 const void *value
, ULONG size
)
3701 if (!desc
) return E_INVALIDARG
;
3702 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
3704 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3706 for (i
= 0; i
< desc
->fieldCount
; i
++)
3708 offset
= desc
->fields
[i
]->offset
;
3709 if ((hr
= write_type_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
) return hr
;
3715 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3716 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3722 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
3725 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
3728 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
3731 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
3734 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
3737 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
3739 case WS_UINT16_TYPE
:
3740 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
3742 case WS_UINT32_TYPE
:
3743 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
3745 case WS_UINT64_TYPE
:
3746 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
3748 case WS_DOUBLE_TYPE
:
3749 return write_type_double( writer
, mapping
, desc
, option
, value
, size
);
3751 case WS_DATETIME_TYPE
:
3752 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
3755 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
3757 case WS_UNIQUE_ID_TYPE
:
3758 return write_type_unique_id( writer
, mapping
, desc
, option
, value
, size
);
3760 case WS_STRING_TYPE
:
3761 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
3764 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
3767 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
3769 case WS_XML_STRING_TYPE
:
3770 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
3772 case WS_XML_QNAME_TYPE
:
3773 return write_type_qname( writer
, mapping
, desc
, option
, value
, size
);
3775 case WS_STRUCT_TYPE
:
3776 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
3779 FIXME( "type %u not supported\n", type
);
3784 /**************************************************************************
3785 * WsWriteAttribute [webservices.@]
3787 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
3788 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3791 struct writer
*writer
= (struct writer
*)handle
;
3794 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3795 if (error
) FIXME( "ignoring error parameter\n" );
3797 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
3798 return E_INVALIDARG
;
3800 EnterCriticalSection( &writer
->cs
);
3802 if (writer
->magic
!= WRITER_MAGIC
)
3804 LeaveCriticalSection( &writer
->cs
);
3805 return E_INVALIDARG
;
3808 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3810 LeaveCriticalSection( &writer
->cs
);
3811 return WS_E_INVALID_OPERATION
;
3814 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) != S_OK
)
3816 LeaveCriticalSection( &writer
->cs
);
3819 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3821 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
3823 LeaveCriticalSection( &writer
->cs
);
3827 /**************************************************************************
3828 * WsWriteElement [webservices.@]
3830 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3831 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3834 struct writer
*writer
= (struct writer
*)handle
;
3837 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3838 if (error
) FIXME( "ignoring error parameter\n" );
3840 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
3841 return E_INVALIDARG
;
3843 EnterCriticalSection( &writer
->cs
);
3845 if (writer
->magic
!= WRITER_MAGIC
)
3847 LeaveCriticalSection( &writer
->cs
);
3848 return E_INVALIDARG
;
3851 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
3853 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
3854 option
, value
, size
)) != S_OK
) goto done
;
3856 hr
= write_endelement_node( writer
);
3859 LeaveCriticalSection( &writer
->cs
);
3863 /**************************************************************************
3864 * WsWriteType [webservices.@]
3866 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3867 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3868 ULONG size
, WS_ERROR
*error
)
3870 struct writer
*writer
= (struct writer
*)handle
;
3873 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
3875 if (error
) FIXME( "ignoring error parameter\n" );
3877 if (!writer
|| !value
) return E_INVALIDARG
;
3879 EnterCriticalSection( &writer
->cs
);
3881 if (writer
->magic
!= WRITER_MAGIC
)
3883 LeaveCriticalSection( &writer
->cs
);
3884 return E_INVALIDARG
;
3889 case WS_ATTRIBUTE_TYPE_MAPPING
:
3890 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
3891 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3894 case WS_ELEMENT_TYPE_MAPPING
:
3895 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3896 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_FORMAT
;
3897 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3900 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3901 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3905 FIXME( "mapping %u not implemented\n", mapping
);
3909 LeaveCriticalSection( &writer
->cs
);
3913 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
3917 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
3918 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
3919 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
3920 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
3921 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
3922 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
3923 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
3924 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
3925 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
3926 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
3927 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
3928 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
3929 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
3930 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
3931 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
3933 FIXME( "unhandled type %u\n", type
);
3938 /**************************************************************************
3939 * WsWriteValue [webservices.@]
3941 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
3942 ULONG size
, WS_ERROR
*error
)
3944 struct writer
*writer
= (struct writer
*)handle
;
3945 WS_TYPE_MAPPING mapping
;
3949 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
3950 if (error
) FIXME( "ignoring error parameter\n" );
3952 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
3954 EnterCriticalSection( &writer
->cs
);
3956 if (writer
->magic
!= WRITER_MAGIC
)
3958 LeaveCriticalSection( &writer
->cs
);
3959 return E_INVALIDARG
;
3962 switch (writer
->state
)
3964 case WRITER_STATE_STARTATTRIBUTE
:
3965 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3968 case WRITER_STATE_STARTELEMENT
:
3969 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3973 hr
= WS_E_INVALID_FORMAT
;
3976 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
3978 LeaveCriticalSection( &writer
->cs
);
3982 /**************************************************************************
3983 * WsWriteArray [webservices.@]
3985 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
3986 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
3987 ULONG count
, WS_ERROR
*error
)
3989 struct writer
*writer
= (struct writer
*)handle
;
3994 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
3995 value_type
, array
, size
, offset
, count
, error
);
3996 if (error
) FIXME( "ignoring error parameter\n" );
3998 if (!writer
) return E_INVALIDARG
;
4000 EnterCriticalSection( &writer
->cs
);
4002 if (writer
->magic
!= WRITER_MAGIC
)
4004 LeaveCriticalSection( &writer
->cs
);
4005 return E_INVALIDARG
;
4008 if (!writer
->output_type
)
4010 LeaveCriticalSection( &writer
->cs
);
4011 return WS_E_INVALID_OPERATION
;
4014 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
4016 LeaveCriticalSection( &writer
->cs
);
4017 return E_INVALIDARG
;
4020 type_size
= get_type_size( type
, NULL
);
4021 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
4023 LeaveCriticalSection( &writer
->cs
);
4024 return E_INVALIDARG
;
4027 for (i
= offset
; i
< count
; i
++)
4029 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
4030 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
4031 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
4032 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
4033 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
4037 LeaveCriticalSection( &writer
->cs
);
4041 /**************************************************************************
4042 * WsWriteXmlBuffer [webservices.@]
4044 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
4046 struct writer
*writer
= (struct writer
*)handle
;
4047 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4050 TRACE( "%p %p %p\n", handle
, buffer
, error
);
4051 if (error
) FIXME( "ignoring error parameter\n" );
4053 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
4055 EnterCriticalSection( &writer
->cs
);
4057 if (writer
->magic
!= WRITER_MAGIC
)
4059 LeaveCriticalSection( &writer
->cs
);
4060 return E_INVALIDARG
;
4063 if (xmlbuf
->encoding
!= writer
->output_enc
|| xmlbuf
->charset
!= writer
->output_charset
)
4065 FIXME( "no support for different encoding and/or charset\n" );
4070 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
4071 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
4072 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4075 LeaveCriticalSection( &writer
->cs
);
4079 /**************************************************************************
4080 * WsWriteXmlBufferToBytes [webservices.@]
4082 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
4083 const WS_XML_WRITER_ENCODING
*encoding
,
4084 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
4085 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
4087 struct writer
*writer
= (struct writer
*)handle
;
4088 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4093 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
4094 bytes
, size
, error
);
4095 if (error
) FIXME( "ignoring error parameter\n" );
4097 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
4099 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
4101 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4105 EnterCriticalSection( &writer
->cs
);
4107 if (writer
->magic
!= WRITER_MAGIC
)
4109 LeaveCriticalSection( &writer
->cs
);
4110 return E_INVALIDARG
;
4113 for (i
= 0; i
< count
; i
++)
4115 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4116 properties
[i
].valueSize
);
4117 if (hr
!= S_OK
) goto done
;
4120 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
4123 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4125 *size
= xmlbuf
->bytes
.length
;
4129 LeaveCriticalSection( &writer
->cs
);
4133 /**************************************************************************
4134 * WsWriteXmlnsAttribute [webservices.@]
4136 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4137 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
4139 struct writer
*writer
= (struct writer
*)handle
;
4142 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
4144 if (error
) FIXME( "ignoring error parameter\n" );
4146 if (!writer
|| !ns
) return E_INVALIDARG
;
4148 EnterCriticalSection( &writer
->cs
);
4150 if (writer
->magic
!= WRITER_MAGIC
)
4152 LeaveCriticalSection( &writer
->cs
);
4153 return E_INVALIDARG
;
4156 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4158 LeaveCriticalSection( &writer
->cs
);
4159 return WS_E_INVALID_OPERATION
;
4162 if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
4163 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
4165 LeaveCriticalSection( &writer
->cs
);
4169 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
4170 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
4172 WS_XML_QNAME_TEXT qname
= {{WS_XML_TEXT_TYPE_QNAME
}};
4175 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4176 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) return hr
;
4178 qname
.prefix
= (WS_XML_STRING
*)prefix
;
4179 qname
.localName
= (WS_XML_STRING
*)localname
;
4180 qname
.ns
= (WS_XML_STRING
*)ns
;
4182 if ((hr
= write_add_text_node( writer
, &qname
.text
)) != S_OK
) return hr
;
4183 return write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 );
4186 /**************************************************************************
4187 * WsWriteQualifiedName [webservices.@]
4189 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4190 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4193 struct writer
*writer
= (struct writer
*)handle
;
4196 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
4197 debugstr_xmlstr(ns
), error
);
4198 if (error
) FIXME( "ignoring error parameter\n" );
4200 if (!writer
) return E_INVALIDARG
;
4202 EnterCriticalSection( &writer
->cs
);
4204 if (writer
->magic
!= WRITER_MAGIC
)
4206 LeaveCriticalSection( &writer
->cs
);
4207 return E_INVALIDARG
;
4210 if (!writer
->output_type
)
4212 LeaveCriticalSection( &writer
->cs
);
4213 return WS_E_INVALID_OPERATION
;
4216 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4218 LeaveCriticalSection( &writer
->cs
);
4219 return WS_E_INVALID_FORMAT
;
4222 if (!localname
|| (!prefix
&& !ns
))
4224 LeaveCriticalSection( &writer
->cs
);
4225 return E_INVALIDARG
;
4228 hr
= write_qualified_name( writer
, prefix
, localname
, ns
);
4230 LeaveCriticalSection( &writer
->cs
);
4234 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
4236 BOOL success
= FALSE
;
4237 struct node
*node
= writer
->current
;
4241 case WS_MOVE_TO_ROOT_ELEMENT
:
4242 success
= move_to_root_element( writer
->root
, &node
);
4245 case WS_MOVE_TO_NEXT_ELEMENT
:
4246 success
= move_to_next_element( &node
);
4249 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
4250 success
= move_to_prev_element( &node
);
4253 case WS_MOVE_TO_CHILD_ELEMENT
:
4254 success
= move_to_child_element( &node
);
4257 case WS_MOVE_TO_END_ELEMENT
:
4258 success
= move_to_end_element( &node
);
4261 case WS_MOVE_TO_PARENT_ELEMENT
:
4262 success
= move_to_parent_element( &node
);
4265 case WS_MOVE_TO_FIRST_NODE
:
4266 success
= move_to_first_node( &node
);
4269 case WS_MOVE_TO_NEXT_NODE
:
4270 success
= move_to_next_node( &node
);
4273 case WS_MOVE_TO_PREVIOUS_NODE
:
4274 success
= move_to_prev_node( &node
);
4277 case WS_MOVE_TO_CHILD_NODE
:
4278 success
= move_to_child_node( &node
);
4281 case WS_MOVE_TO_BOF
:
4282 success
= move_to_bof( writer
->root
, &node
);
4285 case WS_MOVE_TO_EOF
:
4286 success
= move_to_eof( writer
->root
, &node
);
4290 FIXME( "unhandled move %u\n", move
);
4294 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
4295 writer
->current
= node
;
4302 return success
? S_OK
: WS_E_INVALID_FORMAT
;
4305 /**************************************************************************
4306 * WsMoveWriter [webservices.@]
4308 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
4310 struct writer
*writer
= (struct writer
*)handle
;
4313 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
4314 if (error
) FIXME( "ignoring error parameter\n" );
4316 if (!writer
) return E_INVALIDARG
;
4318 EnterCriticalSection( &writer
->cs
);
4320 if (writer
->magic
!= WRITER_MAGIC
)
4322 LeaveCriticalSection( &writer
->cs
);
4323 return E_INVALIDARG
;
4326 if (!writer
->output_type
)
4328 LeaveCriticalSection( &writer
->cs
);
4329 return WS_E_INVALID_OPERATION
;
4332 hr
= write_move_to( writer
, move
, found
);
4334 LeaveCriticalSection( &writer
->cs
);
4338 /**************************************************************************
4339 * WsGetWriterPosition [webservices.@]
4341 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4343 struct writer
*writer
= (struct writer
*)handle
;
4345 TRACE( "%p %p %p\n", handle
, pos
, error
);
4346 if (error
) FIXME( "ignoring error parameter\n" );
4348 if (!writer
|| !pos
) return E_INVALIDARG
;
4350 EnterCriticalSection( &writer
->cs
);
4352 if (writer
->magic
!= WRITER_MAGIC
)
4354 LeaveCriticalSection( &writer
->cs
);
4355 return E_INVALIDARG
;
4358 if (!writer
->output_type
)
4360 LeaveCriticalSection( &writer
->cs
);
4361 return WS_E_INVALID_OPERATION
;
4364 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
4365 pos
->node
= writer
->current
;
4367 LeaveCriticalSection( &writer
->cs
);
4371 /**************************************************************************
4372 * WsSetWriterPosition [webservices.@]
4374 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4376 struct writer
*writer
= (struct writer
*)handle
;
4378 TRACE( "%p %p %p\n", handle
, pos
, error
);
4379 if (error
) FIXME( "ignoring error parameter\n" );
4381 if (!writer
|| !pos
) return E_INVALIDARG
;
4383 EnterCriticalSection( &writer
->cs
);
4385 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
4387 LeaveCriticalSection( &writer
->cs
);
4388 return E_INVALIDARG
;
4391 if (!writer
->output_type
)
4393 LeaveCriticalSection( &writer
->cs
);
4394 return WS_E_INVALID_OPERATION
;
4397 writer
->current
= pos
->node
;
4399 LeaveCriticalSection( &writer
->cs
);
4403 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4405 struct node
*node
, *parent
;
4406 WS_XML_COMMENT_NODE
*comment
;
4408 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
4409 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
4410 comment
= (WS_XML_COMMENT_NODE
*)node
;
4412 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
4415 return E_OUTOFMEMORY
;
4417 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
4418 comment
->value
.length
= value
->length
;
4420 write_insert_node( writer
, parent
, node
);
4424 static HRESULT
write_comment_text( struct writer
*writer
)
4426 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4429 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
4430 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
4431 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
4432 write_bytes( writer
, (const BYTE
*)"-->", 3 );
4436 static HRESULT
write_comment_bin( struct writer
*writer
)
4438 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4441 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
4442 write_char( writer
, RECORD_COMMENT
);
4443 return write_string( writer
, comment
->value
.bytes
, comment
->value
.length
);
4446 static HRESULT
write_comment( struct writer
*writer
)
4448 switch (writer
->output_enc
)
4450 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_comment_text( writer
);
4451 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_comment_bin( writer
);
4453 ERR( "unhandled encoding %u\n", writer
->output_enc
);
4454 return WS_E_NOT_SUPPORTED
;
4458 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4461 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4462 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
4463 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4464 writer
->state
= WRITER_STATE_COMMENT
;
4468 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
4473 for (i
= 0; i
< count
; i
++)
4475 const WS_XML_STRING
*prefix
= attrs
[i
]->prefix
;
4476 const WS_XML_STRING
*localname
= attrs
[i
]->localName
;
4477 const WS_XML_STRING
*ns
= attrs
[i
]->ns
;
4478 BOOL single
= attrs
[i
]->singleQuote
;
4480 if (attrs
[i
]->isXmlNs
)
4482 if ((hr
= add_namespace_attribute( writer
, prefix
, ns
, single
)) != S_OK
) return hr
;
4486 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) != S_OK
) return hr
;
4487 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
4493 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
4497 switch (node
->nodeType
)
4499 case WS_XML_NODE_TYPE_ELEMENT
:
4501 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
4502 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
4503 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
4505 case WS_XML_NODE_TYPE_TEXT
:
4507 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4508 return write_text_node( writer
, text
->text
);
4510 case WS_XML_NODE_TYPE_END_ELEMENT
:
4511 return write_endelement_node( writer
);
4513 case WS_XML_NODE_TYPE_COMMENT
:
4515 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
4516 return write_comment_node( writer
, &comment
->value
);
4518 case WS_XML_NODE_TYPE_CDATA
:
4519 return write_cdata_node( writer
);
4521 case WS_XML_NODE_TYPE_END_CDATA
:
4522 return write_endcdata_node( writer
);
4524 case WS_XML_NODE_TYPE_EOF
:
4525 case WS_XML_NODE_TYPE_BOF
:
4529 WARN( "unknown node type %u\n", node
->nodeType
);
4530 return E_INVALIDARG
;
4534 /**************************************************************************
4535 * WsWriteNode [webservices.@]
4537 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
4539 struct writer
*writer
= (struct writer
*)handle
;
4542 TRACE( "%p %p %p\n", handle
, node
, error
);
4543 if (error
) FIXME( "ignoring error parameter\n" );
4545 if (!writer
|| !node
) return E_INVALIDARG
;
4547 EnterCriticalSection( &writer
->cs
);
4549 if (writer
->magic
!= WRITER_MAGIC
)
4551 LeaveCriticalSection( &writer
->cs
);
4552 return E_INVALIDARG
;
4555 if (!writer
->output_type
)
4557 LeaveCriticalSection( &writer
->cs
);
4558 return WS_E_INVALID_OPERATION
;
4561 hr
= write_node( writer
, node
);
4563 LeaveCriticalSection( &writer
->cs
);
4567 static HRESULT
write_tree_node( struct writer
*writer
)
4571 switch (node_type( writer
->current
))
4573 case WS_XML_NODE_TYPE_ELEMENT
:
4574 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4576 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
4577 writer
->state
= WRITER_STATE_STARTELEMENT
;
4580 case WS_XML_NODE_TYPE_TEXT
:
4581 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4583 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
4584 writer
->state
= WRITER_STATE_TEXT
;
4587 case WS_XML_NODE_TYPE_END_ELEMENT
:
4588 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
4589 writer
->state
= WRITER_STATE_ENDELEMENT
;
4592 case WS_XML_NODE_TYPE_COMMENT
:
4593 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4595 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4596 writer
->state
= WRITER_STATE_COMMENT
;
4599 case WS_XML_NODE_TYPE_CDATA
:
4600 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4602 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
4603 writer
->state
= WRITER_STATE_STARTCDATA
;
4606 case WS_XML_NODE_TYPE_END_CDATA
:
4607 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
4608 writer
->state
= WRITER_STATE_ENDCDATA
;
4611 case WS_XML_NODE_TYPE_EOF
:
4612 case WS_XML_NODE_TYPE_BOF
:
4616 ERR( "unknown node type %u\n", node_type(writer
->current
) );
4617 return E_INVALIDARG
;
4621 static HRESULT
write_tree( struct writer
*writer
)
4625 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4628 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
4629 if (move_to_child_node( &writer
->current
))
4631 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4634 if (move_to_next_node( &writer
->current
))
4636 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4639 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
4641 ERR( "invalid tree\n" );
4642 return WS_E_INVALID_FORMAT
;
4644 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4649 static void write_rewind( struct writer
*writer
)
4651 writer
->write_pos
= 0;
4652 writer
->current
= writer
->root
;
4653 writer
->state
= WRITER_STATE_INITIAL
;
4656 /**************************************************************************
4657 * WsCopyNode [webservices.@]
4659 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
4661 struct writer
*writer
= (struct writer
*)handle
;
4662 struct node
*parent
, *current
, *node
= NULL
;
4665 TRACE( "%p %p %p\n", handle
, reader
, error
);
4666 if (error
) FIXME( "ignoring error parameter\n" );
4668 if (!writer
) return E_INVALIDARG
;
4670 EnterCriticalSection( &writer
->cs
);
4672 if (writer
->magic
!= WRITER_MAGIC
)
4674 LeaveCriticalSection( &writer
->cs
);
4675 return E_INVALIDARG
;
4678 if (!(parent
= find_parent( writer
)))
4680 LeaveCriticalSection( &writer
->cs
);
4681 return WS_E_INVALID_FORMAT
;
4684 if ((hr
= copy_node( reader
, &node
)) != S_OK
) goto done
;
4685 current
= writer
->current
;
4686 write_insert_node( writer
, parent
, node
);
4688 write_rewind( writer
);
4689 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
4690 writer
->current
= current
;
4692 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
4695 LeaveCriticalSection( &writer
->cs
);
4699 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
4701 return write_type_field( writer
, desc
, value
, 0 );
4704 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
4707 for (i
= 0; i
< count
; i
++)
4709 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4711 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
4717 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
4720 return write_type_repeating_element( writer
, desc
, value
, len
);
4723 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4724 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4726 struct writer
*writer
= (struct writer
*)handle
;
4727 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4728 const WS_FIELD_DESCRIPTION
*desc_field
;
4732 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4734 EnterCriticalSection( &writer
->cs
);
4736 if (writer
->magic
!= WRITER_MAGIC
)
4738 LeaveCriticalSection( &writer
->cs
);
4739 return E_INVALIDARG
;
4742 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4744 for (i
= 0; i
< count
; i
++)
4746 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
4747 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
4749 FIXME( "messages type not supported\n" );
4753 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
4754 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
4756 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
4758 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
4760 const void *ptr
= *(const void **)args
[i
];
4761 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
4762 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
4766 hr
= write_endelement_node( writer
);
4769 LeaveCriticalSection( &writer
->cs
);
4773 HRESULT
writer_enable_lookup( WS_XML_WRITER
*handle
)
4775 struct writer
*writer
= (struct writer
*)handle
;
4777 EnterCriticalSection( &writer
->cs
);
4779 if (writer
->magic
!= WRITER_MAGIC
)
4781 LeaveCriticalSection( &writer
->cs
);
4782 return E_INVALIDARG
;
4785 writer
->dict_do_lookup
= TRUE
;
4787 LeaveCriticalSection( &writer
->cs
);