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/heap.h"
32 #include "wine/list.h"
33 #include "wine/unicode.h"
34 #include "webservices_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
38 static const struct prop_desc writer_props
[] =
40 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
41 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
42 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
43 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
44 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INDENT */
45 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
46 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_WRITER_PROPERTY_CHARSET */
47 { sizeof(WS_BUFFERS
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFERS */
48 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
49 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BYTES */
50 { sizeof(BOOL
), TRUE
}, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
51 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
52 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
53 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
54 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
55 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
56 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
57 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
58 { sizeof(BOOL
), FALSE
} /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
64 WRITER_STATE_STARTELEMENT
,
65 WRITER_STATE_STARTATTRIBUTE
,
66 WRITER_STATE_STARTCDATA
,
67 WRITER_STATE_ENDSTARTELEMENT
,
70 WRITER_STATE_ENDELEMENT
,
79 unsigned char *write_bufptr
;
80 enum writer_state state
;
83 WS_XML_STRING
*current_ns
;
84 WS_XML_WRITER_ENCODING_TYPE output_enc
;
85 WS_CHARSET output_charset
;
86 WS_XML_WRITER_OUTPUT_TYPE output_type
;
87 struct xmlbuf
*output_buf
;
89 const WS_XML_DICTIONARY
*dict
;
91 WS_DYNAMIC_STRING_CALLBACK dict_cb
;
94 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
97 #define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T')
99 static struct writer
*alloc_writer(void)
101 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
103 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
105 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
107 ret
->magic
= WRITER_MAGIC
;
108 InitializeCriticalSection( &ret
->cs
);
109 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": writer.cs");
111 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
112 ret
->prop_count
= count
;
116 static void free_writer( struct writer
*writer
)
118 destroy_nodes( writer
->root
);
119 free_xml_string( writer
->current_ns
);
120 WsFreeHeap( writer
->output_heap
);
122 writer
->cs
.DebugInfo
->Spare
[0] = 0;
123 DeleteCriticalSection( &writer
->cs
);
127 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
129 if (!writer
->root
) writer
->root
= eof
;
132 eof
->parent
= writer
->root
;
133 list_add_tail( &writer
->root
->children
, &eof
->entry
);
135 writer
->current
= eof
;
138 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
140 writer
->root
->parent
= bof
;
141 list_add_tail( &bof
->children
, &writer
->root
->entry
);
142 writer
->current
= writer
->root
= bof
;
145 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
147 node
->parent
= parent
;
148 list_add_before( list_tail( &parent
->children
), &node
->entry
);
149 writer
->current
= node
;
152 static struct node
*find_parent( struct writer
*writer
)
154 if (is_valid_parent( writer
->current
)) return writer
->current
;
155 if (is_valid_parent( writer
->current
->parent
)) return writer
->current
->parent
;
159 static HRESULT
init_writer( struct writer
*writer
)
163 writer
->write_pos
= 0;
164 writer
->write_bufptr
= NULL
;
165 destroy_nodes( writer
->root
);
166 writer
->root
= writer
->current
= NULL
;
167 free_xml_string( writer
->current_ns
);
168 writer
->current_ns
= NULL
;
170 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
171 write_insert_eof( writer
, node
);
172 writer
->state
= WRITER_STATE_INITIAL
;
173 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
174 writer
->output_charset
= WS_CHARSET_UTF8
;
176 writer
->dict_do_lookup
= FALSE
;
177 writer
->dict_cb
= NULL
;
178 writer
->dict_cb_state
= NULL
;
182 /**************************************************************************
183 * WsCreateWriter [webservices.@]
185 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
186 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
188 struct writer
*writer
;
189 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
190 WS_CHARSET charset
= WS_CHARSET_UTF8
;
193 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
194 if (error
) FIXME( "ignoring error parameter\n" );
196 if (!handle
) return E_INVALIDARG
;
197 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
199 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
200 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
201 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
202 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
203 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
204 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
205 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
207 for (i
= 0; i
< count
; i
++)
209 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
210 properties
[i
].valueSize
);
213 free_writer( writer
);
218 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
219 &max_size
, sizeof(max_size
) );
222 free_writer( writer
);
226 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
229 free_writer( writer
);
233 hr
= init_writer( writer
);
236 free_writer( writer
);
240 TRACE( "created %p\n", writer
);
241 *handle
= (WS_XML_WRITER
*)writer
;
245 /**************************************************************************
246 * WsFreeWriter [webservices.@]
248 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
250 struct writer
*writer
= (struct writer
*)handle
;
252 TRACE( "%p\n", handle
);
256 EnterCriticalSection( &writer
->cs
);
258 if (writer
->magic
!= WRITER_MAGIC
)
260 LeaveCriticalSection( &writer
->cs
);
266 LeaveCriticalSection( &writer
->cs
);
267 free_writer( writer
);
270 /**************************************************************************
271 * WsGetWriterProperty [webservices.@]
273 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
274 void *buf
, ULONG size
, WS_ERROR
*error
)
276 struct writer
*writer
= (struct writer
*)handle
;
279 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
280 if (error
) FIXME( "ignoring error parameter\n" );
282 if (!writer
) return E_INVALIDARG
;
284 EnterCriticalSection( &writer
->cs
);
286 if (writer
->magic
!= WRITER_MAGIC
)
288 LeaveCriticalSection( &writer
->cs
);
292 if (!writer
->output_type
)
294 LeaveCriticalSection( &writer
->cs
);
295 return WS_E_INVALID_OPERATION
;
300 case WS_XML_WRITER_PROPERTY_BYTES
:
302 WS_BYTES
*bytes
= buf
;
303 if (size
!= sizeof(*bytes
)) hr
= E_INVALIDARG
;
306 bytes
->bytes
= writer
->output_buf
->bytes
.bytes
;
307 bytes
->length
= writer
->output_buf
->bytes
.length
;
311 case WS_XML_WRITER_PROPERTY_BUFFERS
:
312 if (writer
->output_buf
->bytes
.length
)
314 WS_BUFFERS
*buffers
= buf
;
315 if (size
!= sizeof(*buffers
)) hr
= E_INVALIDARG
;
318 buffers
->bufferCount
= 1;
319 buffers
->buffers
= &writer
->output_buf
->bytes
;
325 hr
= prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
328 LeaveCriticalSection( &writer
->cs
);
332 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
334 /* free current buffer if it's ours */
335 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
337 free_xmlbuf( writer
->output_buf
);
339 writer
->output_buf
= xmlbuf
;
340 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
341 writer
->write_bufptr
= xmlbuf
->bytes
.bytes
;
342 writer
->write_pos
= 0;
345 /**************************************************************************
346 * WsSetOutput [webservices.@]
348 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
349 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
350 ULONG count
, WS_ERROR
*error
)
352 struct writer
*writer
= (struct writer
*)handle
;
357 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
358 if (error
) FIXME( "ignoring error parameter\n" );
360 if (!writer
) return E_INVALIDARG
;
362 EnterCriticalSection( &writer
->cs
);
364 if (writer
->magic
!= WRITER_MAGIC
)
366 LeaveCriticalSection( &writer
->cs
);
370 for (i
= 0; i
< count
; i
++)
372 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
373 properties
[i
].valueSize
);
374 if (hr
!= S_OK
) goto done
;
377 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
379 switch (encoding
->encodingType
)
381 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
383 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
384 if (text
->charSet
!= WS_CHARSET_UTF8
)
386 FIXME( "charset %u not supported\n", text
->charSet
);
390 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_TEXT
;
391 writer
->output_charset
= WS_CHARSET_UTF8
;
394 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
396 WS_XML_WRITER_BINARY_ENCODING
*bin
= (WS_XML_WRITER_BINARY_ENCODING
*)encoding
;
397 writer
->output_enc
= WS_XML_WRITER_ENCODING_TYPE_BINARY
;
398 writer
->output_charset
= 0;
399 writer
->dict
= bin
->staticDictionary
;
400 writer
->dict_cb
= bin
->dynamicStringCallback
;
401 writer
->dict_cb_state
= bin
->dynamicStringCallbackState
;
405 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
410 switch (output
->outputType
)
412 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
414 struct xmlbuf
*xmlbuf
;
415 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
, 0, writer
->output_enc
, writer
->output_charset
,
416 writer
->dict
, NULL
)))
418 hr
= WS_E_QUOTA_EXCEEDED
;
421 set_output_buffer( writer
, xmlbuf
);
425 FIXME( "output type %u not supported\n", output
->outputType
);
430 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
431 else write_insert_bof( writer
, node
);
434 LeaveCriticalSection( &writer
->cs
);
438 /**************************************************************************
439 * WsSetOutputToBuffer [webservices.@]
441 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
442 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
445 struct writer
*writer
= (struct writer
*)handle
;
446 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
451 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
452 if (error
) FIXME( "ignoring error parameter\n" );
454 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
456 EnterCriticalSection( &writer
->cs
);
458 if (writer
->magic
!= WRITER_MAGIC
)
460 LeaveCriticalSection( &writer
->cs
);
464 for (i
= 0; i
< count
; i
++)
466 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
467 properties
[i
].valueSize
);
468 if (hr
!= S_OK
) goto done
;
471 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
472 writer
->output_enc
= xmlbuf
->encoding
;
473 writer
->output_charset
= xmlbuf
->charset
;
474 set_output_buffer( writer
, xmlbuf
);
476 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
477 else write_insert_bof( writer
, node
);
480 LeaveCriticalSection( &writer
->cs
);
484 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
486 struct xmlbuf
*buf
= writer
->output_buf
;
490 if (buf
->size
>= writer
->write_pos
+ size
)
492 buf
->bytes
.length
= writer
->write_pos
+ size
;
495 new_size
= max( buf
->size
* 2, writer
->write_pos
+ size
);
496 if (!(tmp
= ws_realloc( buf
->heap
, buf
->bytes
.bytes
, buf
->size
, new_size
))) return WS_E_QUOTA_EXCEEDED
;
497 writer
->write_bufptr
= buf
->bytes
.bytes
= tmp
;
498 buf
->size
= new_size
;
499 buf
->bytes
.length
= writer
->write_pos
+ size
;
503 static inline void write_char( struct writer
*writer
, unsigned char ch
)
505 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
508 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
510 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
511 writer
->write_pos
+= len
;
520 static const struct escape escape_lt
= { '<', "<", 4 };
521 static const struct escape escape_gt
= { '>', ">", 4 };
522 static const struct escape escape_amp
= { '&', "&", 5 };
523 static const struct escape escape_apos
= { '\'', "'", 6 };
524 static const struct escape escape_quot
= { '"', """, 6 };
526 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
527 const struct escape
**escapes
, ULONG nb_escapes
)
533 for (i
= 0; i
< len
; i
++)
537 for (j
= 0; j
< nb_escapes
; j
++)
539 if (bytes
[i
] == escapes
[j
]->ch
)
541 ptr
= (const BYTE
*)escapes
[j
]->entity
;
542 size
= escapes
[j
]->len
;
546 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
547 write_bytes( writer
, ptr
, size
);
553 static HRESULT
write_attribute_value_text( struct writer
*writer
, const WS_XML_TEXT
*text
, BOOL single
)
555 WS_XML_UTF8_TEXT
*utf8
= (WS_XML_UTF8_TEXT
*)text
;
556 const struct escape
*escapes
[3];
558 escapes
[0] = single
? &escape_apos
: &escape_quot
;
559 escapes
[1] = &escape_lt
;
560 escapes
[2] = &escape_amp
;
561 return write_bytes_escape( writer
, utf8
->value
.bytes
, utf8
->value
.length
, escapes
, 3 );
564 static HRESULT
write_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
566 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
567 const WS_XML_STRING
*prefix
= NULL
;
571 if (attr
->prefix
) prefix
= attr
->prefix
;
573 /* ' prefix:attr="value"' */
575 size
= attr
->localName
->length
+ 4 /* ' =""' */;
576 if (prefix
&& prefix
->length
) size
+= prefix
->length
+ 1 /* ':' */;
577 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
579 write_char( writer
, ' ' );
580 if (prefix
&& prefix
->length
)
582 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
583 write_char( writer
, ':' );
585 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
586 write_char( writer
, '=' );
587 write_char( writer
, quote
);
588 if (attr
->value
) hr
= write_attribute_value_text( writer
, attr
->value
, attr
->singleQuote
);
589 write_char( writer
, quote
);
594 static HRESULT
write_int31( struct writer
*writer
, ULONG len
)
598 if (len
> 0x7fffffff) return E_INVALIDARG
;
600 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
603 write_char( writer
, len
);
606 write_char( writer
, (len
& 0x7f) | 0x80 );
608 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
609 if ((len
>>= 7) < 0x80)
611 write_char( writer
, len
);
614 write_char( writer
, (len
& 0x7f) | 0x80 );
616 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
617 if ((len
>>= 7) < 0x80)
619 write_char( writer
, len
);
622 write_char( writer
, (len
& 0x7f) | 0x80 );
624 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
625 if ((len
>>= 7) < 0x80)
627 write_char( writer
, len
);
630 write_char( writer
, (len
& 0x7f) | 0x80 );
632 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
633 if ((len
>>= 7) < 0x08)
635 write_char( writer
, len
);
638 return WS_E_INVALID_FORMAT
;
641 static HRESULT
write_string( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
644 if ((hr
= write_int31( writer
, len
)) != S_OK
) return hr
;
645 if ((hr
= write_grow_buffer( writer
, len
)) != S_OK
) return hr
;
646 write_bytes( writer
, bytes
, len
);
650 static HRESULT
write_dict_string( struct writer
*writer
, ULONG id
)
652 if (id
> 0x7fffffff) return E_INVALIDARG
;
653 return write_int31( writer
, id
);
656 static enum record_type
get_attr_text_record_type( const WS_XML_TEXT
*text
, BOOL use_dict
)
658 if (!text
) return RECORD_CHARS8_TEXT
;
659 switch (text
->textType
)
661 case WS_XML_TEXT_TYPE_UTF8
:
663 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
664 if (use_dict
) return RECORD_DICTIONARY_TEXT
;
665 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT
;
666 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT
;
667 return RECORD_CHARS32_TEXT
;
669 case WS_XML_TEXT_TYPE_UTF16
:
671 const WS_XML_UTF16_TEXT
*text_utf16
= (const WS_XML_UTF16_TEXT
*)text
;
672 int len
= text_utf16
->byteCount
/ sizeof(WCHAR
);
673 int len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)text_utf16
->bytes
, len
, NULL
, 0, NULL
, NULL
);
674 if (len_utf8
<= MAX_UINT8
) return RECORD_CHARS8_TEXT
;
675 if (len_utf8
<= MAX_UINT16
) return RECORD_CHARS16_TEXT
;
676 return RECORD_CHARS32_TEXT
;
678 case WS_XML_TEXT_TYPE_BASE64
:
680 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
681 if (text_base64
->length
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
682 if (text_base64
->length
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
683 return RECORD_BYTES32_TEXT
;
685 case WS_XML_TEXT_TYPE_BOOL
:
687 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
688 return text_bool
->value
? RECORD_TRUE_TEXT
: RECORD_FALSE_TEXT
;
690 case WS_XML_TEXT_TYPE_INT32
:
692 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
693 if (!text_int32
->value
) return RECORD_ZERO_TEXT
;
694 if (text_int32
->value
== 1) return RECORD_ONE_TEXT
;
695 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
696 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
697 return RECORD_INT32_TEXT
;
699 case WS_XML_TEXT_TYPE_INT64
:
701 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
702 if (!text_int64
->value
) return RECORD_ZERO_TEXT
;
703 if (text_int64
->value
== 1) return RECORD_ONE_TEXT
;
704 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
705 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
706 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
707 return RECORD_INT64_TEXT
;
709 case WS_XML_TEXT_TYPE_UINT64
:
711 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
712 if (!text_uint64
->value
) return RECORD_ZERO_TEXT
;
713 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT
;
714 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
715 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
716 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
717 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT
;
718 return RECORD_UINT64_TEXT
;
720 case WS_XML_TEXT_TYPE_DOUBLE
:
722 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
723 if (!text_double
->value
) return RECORD_ZERO_TEXT
;
724 if (text_double
->value
== 1) return RECORD_ONE_TEXT
;
725 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
726 return RECORD_DOUBLE_TEXT
;
727 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT
;
728 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT
;
729 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT
;
730 return RECORD_INT64_TEXT
;
732 case WS_XML_TEXT_TYPE_GUID
:
733 return RECORD_GUID_TEXT
;
735 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
736 return RECORD_UNIQUE_ID_TEXT
;
738 case WS_XML_TEXT_TYPE_DATETIME
:
739 return RECORD_DATETIME_TEXT
;
742 FIXME( "unhandled text type %u\n", text
->textType
);
747 static INT64
get_text_value_int( const WS_XML_TEXT
*text
)
749 switch (text
->textType
)
751 case WS_XML_TEXT_TYPE_INT32
:
753 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
754 return text_int32
->value
;
756 case WS_XML_TEXT_TYPE_INT64
:
758 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
759 return text_int64
->value
;
761 case WS_XML_TEXT_TYPE_UINT64
:
763 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
764 return text_uint64
->value
;
766 case WS_XML_TEXT_TYPE_DOUBLE
:
768 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
769 return text_double
->value
;
772 ERR( "unhandled text type %u\n", text
->textType
);
778 static BOOL
get_string_id( struct writer
*writer
, const WS_XML_STRING
*str
, ULONG
*id
)
780 if (writer
->dict
&& str
->dictionary
== writer
->dict
)
788 writer
->dict_cb( writer
->dict_cb_state
, str
, &found
, id
, NULL
);
789 if (found
) *id
= (*id
<< 1) | 1;
795 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
797 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
800 memcpy( buf
, bool_true
, sizeof(bool_true
) );
801 return sizeof(bool_true
);
803 memcpy( buf
, bool_false
, sizeof(bool_false
) );
804 return sizeof(bool_false
);
807 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
809 return wsprintfA( (char *)buf
, "%d", *ptr
);
812 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
814 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
817 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
819 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
822 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
825 static const long double precision
= 0.0000000000000001;
826 unsigned char *p
= buf
;
827 long double val
= *ptr
;
828 int neg
, mag
, mag2
, use_exp
;
832 memcpy( buf
, "NaN", 3 );
839 memcpy( buf
, "-INF", 4 );
842 memcpy( buf
, "INF", 3 );
858 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
861 if (mag
< 0) mag
-= 1;
862 val
= val
/ powl( 10.0, mag
);
866 else if (mag
< 1) mag
= 0;
868 while (val
> precision
|| mag
>= 0)
870 long double weight
= powl( 10.0, mag
);
871 if (weight
> 0 && !isinf( weight
))
873 int digit
= floorl( val
/ weight
);
874 val
-= digit
* weight
;
875 *(p
++) = '0' + digit
;
877 if (!mag
&& val
> precision
) *(p
++) = '.';
885 if (mag2
> 0) *(p
++) = '+';
894 *(p
++) = '0' + mag2
% 10;
898 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
908 FIXME( "powl not found at build time\n" );
913 static inline int year_size( int year
)
915 return leap_year( year
) ? 366 : 365;
919 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
921 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
922 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
923 unsigned __int64 ticks
, day_ticks
;
926 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
927 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
929 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
937 day
= ticks
/ TICKS_PER_DAY
;
938 day_ticks
= ticks
% TICKS_PER_DAY
;
939 hour
= day_ticks
/ TICKS_PER_HOUR
;
940 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
941 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
942 sec_frac
= day_ticks
% TICKS_PER_SEC
;
944 while (day
>= year_size( year
))
946 day
-= year_size( year
);
949 while (day
>= month_days
[leap_year( year
)][month
])
951 day
-= month_days
[leap_year( year
)][month
];
955 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
958 static const char fmt_frac
[] = ".%07u";
959 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
960 while (buf
[len
- 1] == '0') len
--;
962 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
966 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
968 static const char fmt_tz
[] = "%c%02u:00";
969 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
975 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
977 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
978 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
979 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
980 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
983 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
985 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
986 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
987 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
988 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
991 static ULONG
format_qname( const WS_XML_STRING
*prefix
, const WS_XML_STRING
*localname
, unsigned char *buf
)
994 if (prefix
&& prefix
->length
)
996 memcpy( buf
, prefix
->bytes
, prefix
->length
);
997 len
+= prefix
->length
;
1000 memcpy( buf
+ len
, localname
->bytes
, localname
->length
);
1001 return len
+ localname
->length
;
1004 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
1006 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1011 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
1012 x
= (bin
[0] & 3) << 4;
1015 buf
[i
++] = base64
[x
];
1020 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
1021 x
= (bin
[1] & 0x0f) << 2;
1024 buf
[i
++] = base64
[x
];
1028 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
1029 buf
[i
++] = base64
[bin
[2] & 0x3f];
1036 HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, ULONG
*offset
,
1037 WS_XML_UTF8_TEXT
**ret
)
1039 ULONG len_old
= old
? old
->value
.length
: 0;
1040 if (offset
) *offset
= len_old
;
1042 switch (text
->textType
)
1044 case WS_XML_TEXT_TYPE_UTF8
:
1046 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1048 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
1049 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1050 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
1053 case WS_XML_TEXT_TYPE_UTF16
:
1055 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1056 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1057 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1059 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1060 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1061 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
1062 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1063 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
1066 case WS_XML_TEXT_TYPE_BASE64
:
1068 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
1069 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
1071 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1072 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1073 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1076 case WS_XML_TEXT_TYPE_BOOL
:
1078 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1080 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
1081 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1082 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1085 case WS_XML_TEXT_TYPE_INT32
:
1087 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1088 unsigned char buf
[12]; /* "-2147483648" */
1089 ULONG len
= format_int32( &int32_text
->value
, buf
);
1091 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1092 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1093 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1096 case WS_XML_TEXT_TYPE_INT64
:
1098 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1099 unsigned char buf
[21]; /* "-9223372036854775808" */
1100 ULONG len
= format_int64( &int64_text
->value
, buf
);
1102 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1103 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1104 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1107 case WS_XML_TEXT_TYPE_UINT64
:
1109 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1110 unsigned char buf
[21]; /* "18446744073709551615" */
1111 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1113 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1114 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1115 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1118 case WS_XML_TEXT_TYPE_DOUBLE
:
1120 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1121 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
1122 unsigned short fpword
;
1125 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
1126 len
= format_double( &double_text
->value
, buf
);
1127 restore_fpword( fpword
);
1128 if (!len
) return E_NOTIMPL
;
1130 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1131 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1132 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1135 case WS_XML_TEXT_TYPE_GUID
:
1137 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1139 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
1140 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1141 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1144 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1146 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1148 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
1149 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1150 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1153 case WS_XML_TEXT_TYPE_DATETIME
:
1155 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
1157 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
1158 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1159 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1162 case WS_XML_TEXT_TYPE_QNAME
:
1164 const WS_XML_QNAME_TEXT
*qn
= (const WS_XML_QNAME_TEXT
*)text
;
1165 ULONG len
= qn
->localName
->length
;
1167 if (qn
->prefix
&& qn
->prefix
->length
) len
+= qn
->prefix
->length
+ 1;
1168 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1169 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1170 (*ret
)->value
.length
= format_qname( qn
->prefix
, qn
->localName
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1174 FIXME( "unhandled text type %u\n", text
->textType
);
1179 static HRESULT
write_attribute_value_bin( struct writer
*writer
, const WS_XML_TEXT
*text
)
1181 enum record_type type
;
1182 BOOL use_dict
= FALSE
;
1186 if (text
&& text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
1188 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1189 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
1191 type
= get_attr_text_record_type( text
, use_dict
);
1193 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1194 write_char( writer
, type
);
1198 case RECORD_CHARS8_TEXT
:
1200 const WS_XML_UTF8_TEXT
*text_utf8
;
1201 WS_XML_UTF8_TEXT
*new = NULL
;
1206 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1207 write_char( writer
, 0 );
1210 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1213 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
1216 len
= text_utf8
->value
.length
;
1217 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
)
1222 write_char( writer
, len
);
1223 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
1227 case RECORD_CHARS16_TEXT
:
1229 const WS_XML_UTF8_TEXT
*text_utf8
;
1230 WS_XML_UTF8_TEXT
*new = NULL
;
1233 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
1236 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
1239 len
= text_utf8
->value
.length
;
1240 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
)
1245 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
1246 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
1250 case RECORD_BYTES8_TEXT
:
1252 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
1253 if ((hr
= write_grow_buffer( writer
, 1 + text_base64
->length
)) != S_OK
) return hr
;
1254 write_char( writer
, text_base64
->length
);
1255 write_bytes( writer
, text_base64
->bytes
, text_base64
->length
);
1258 case RECORD_BYTES16_TEXT
:
1260 WS_XML_BASE64_TEXT
*text_base64
= (WS_XML_BASE64_TEXT
*)text
;
1261 UINT16 len
= text_base64
->length
;
1262 if ((hr
= write_grow_buffer( writer
, sizeof(len
) + len
)) != S_OK
) return hr
;
1263 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
1264 write_bytes( writer
, text_base64
->bytes
, len
);
1267 case RECORD_ZERO_TEXT
:
1268 case RECORD_ONE_TEXT
:
1269 case RECORD_FALSE_TEXT
:
1270 case RECORD_TRUE_TEXT
:
1273 case RECORD_INT8_TEXT
:
1275 INT8 val
= get_text_value_int( text
);
1276 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1277 write_char( writer
, val
);
1280 case RECORD_INT16_TEXT
:
1282 INT16 val
= get_text_value_int( text
);
1283 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1284 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1287 case RECORD_INT32_TEXT
:
1289 INT32 val
= get_text_value_int( text
);
1290 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1291 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1294 case RECORD_INT64_TEXT
:
1296 INT64 val
= get_text_value_int( text
);
1297 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1298 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1301 case RECORD_UINT64_TEXT
:
1303 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
1304 if ((hr
= write_grow_buffer( writer
, sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
1305 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
1308 case RECORD_DOUBLE_TEXT
:
1310 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
1311 if ((hr
= write_grow_buffer( writer
, sizeof(text_double
->value
) )) != S_OK
) return hr
;
1312 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
1315 case RECORD_GUID_TEXT
:
1317 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
1318 if ((hr
= write_grow_buffer( writer
, sizeof(text_guid
->value
) )) != S_OK
) return hr
;
1319 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
1322 case RECORD_UNIQUE_ID_TEXT
:
1324 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
1325 if ((hr
= write_grow_buffer( writer
, sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
1326 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
1329 case RECORD_DATETIME_TEXT
:
1331 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
1332 UINT64 val
= text_datetime
->value
.ticks
;
1334 assert( val
<= TICKS_MAX
);
1335 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
1336 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
1338 if ((hr
= write_grow_buffer( writer
, sizeof(val
) )) != S_OK
) return hr
;
1339 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
1343 FIXME( "unhandled record type %02x\n", type
);
1348 static enum record_type
get_attr_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1350 if (!attr
->prefix
|| !attr
->prefix
->length
)
1352 if (use_dict
) return RECORD_SHORT_DICTIONARY_ATTRIBUTE
;
1353 return RECORD_SHORT_ATTRIBUTE
;
1355 if (attr
->prefix
->length
== 1 && attr
->prefix
->bytes
[0] >= 'a' && attr
->prefix
->bytes
[0] <= 'z')
1357 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
1358 return RECORD_PREFIX_ATTRIBUTE_A
+ attr
->prefix
->bytes
[0] - 'a';
1360 if (use_dict
) return RECORD_DICTIONARY_ATTRIBUTE
;
1361 return RECORD_ATTRIBUTE
;
1364 static HRESULT
write_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1367 enum record_type type
= get_attr_record_type( attr
, get_string_id(writer
, attr
->localName
, &id
) );
1370 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1371 write_char( writer
, type
);
1373 if (type
>= RECORD_PREFIX_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_ATTRIBUTE_Z
)
1375 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1376 return write_attribute_value_bin( writer
, attr
->value
);
1378 if (type
>= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A
&& type
<= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z
)
1380 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1381 return write_attribute_value_bin( writer
, attr
->value
);
1386 case RECORD_SHORT_ATTRIBUTE
:
1387 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1390 case RECORD_ATTRIBUTE
:
1391 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1392 if ((hr
= write_string( writer
, attr
->localName
->bytes
, attr
->localName
->length
)) != S_OK
) return hr
;
1395 case RECORD_SHORT_DICTIONARY_ATTRIBUTE
:
1396 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1399 case RECORD_DICTIONARY_ATTRIBUTE
:
1400 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1401 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1405 ERR( "unhandled record type %02x\n", type
);
1406 return WS_E_NOT_SUPPORTED
;
1409 return write_attribute_value_bin( writer
, attr
->value
);
1412 static HRESULT
write_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1414 switch (writer
->output_enc
)
1416 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_attribute_text( writer
, attr
);
1417 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_attribute_bin( writer
, attr
);
1419 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1420 return WS_E_NOT_SUPPORTED
;
1424 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1426 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
1429 /**************************************************************************
1430 * WsGetPrefixFromNamespace [webservices.@]
1432 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
1433 BOOL required
, const WS_XML_STRING
**prefix
,
1436 struct writer
*writer
= (struct writer
*)handle
;
1437 WS_XML_ELEMENT_NODE
*elem
;
1441 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
1442 if (error
) FIXME( "ignoring error parameter\n" );
1444 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
1446 EnterCriticalSection( &writer
->cs
);
1448 if (writer
->magic
!= WRITER_MAGIC
)
1450 LeaveCriticalSection( &writer
->cs
);
1451 return E_INVALIDARG
;
1454 elem
= &writer
->current
->hdr
;
1455 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
1457 *prefix
= elem
->prefix
;
1463 if (required
) hr
= WS_E_INVALID_FORMAT
;
1471 LeaveCriticalSection( &writer
->cs
);
1475 static HRESULT
write_namespace_attribute_text( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1477 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
1481 /* ' xmlns:prefix="namespace"' */
1483 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
1484 if (attr
->prefix
&& attr
->prefix
->length
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
1485 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1487 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
1488 if (attr
->prefix
&& attr
->prefix
->length
)
1490 write_char( writer
, ':' );
1491 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
1493 write_char( writer
, '=' );
1494 write_char( writer
, quote
);
1495 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1496 write_char( writer
, quote
);
1501 static enum record_type
get_xmlns_record_type( const WS_XML_ATTRIBUTE
*attr
, BOOL use_dict
)
1503 if (!attr
->prefix
|| !attr
->prefix
->length
)
1505 if (use_dict
) return RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
;
1506 return RECORD_SHORT_XMLNS_ATTRIBUTE
;
1508 if (use_dict
) return RECORD_DICTIONARY_XMLNS_ATTRIBUTE
;
1509 return RECORD_XMLNS_ATTRIBUTE
;
1512 static HRESULT
write_namespace_attribute_bin( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1515 enum record_type type
= get_xmlns_record_type( attr
, get_string_id(writer
, attr
->ns
, &id
) );
1518 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1519 write_char( writer
, type
);
1523 case RECORD_SHORT_XMLNS_ATTRIBUTE
:
1526 case RECORD_XMLNS_ATTRIBUTE
:
1527 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1530 case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE
:
1531 return write_dict_string( writer
, id
);
1533 case RECORD_DICTIONARY_XMLNS_ATTRIBUTE
:
1534 if ((hr
= write_string( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
)) != S_OK
) return hr
;
1535 return write_dict_string( writer
, id
);
1538 ERR( "unhandled record type %02x\n", type
);
1539 return WS_E_NOT_SUPPORTED
;
1542 return write_string( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
1545 static HRESULT
write_namespace_attribute( struct writer
*writer
, const WS_XML_ATTRIBUTE
*attr
)
1547 switch (writer
->output_enc
)
1549 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_namespace_attribute_text( writer
, attr
);
1550 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_namespace_attribute_bin( writer
, attr
);
1552 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1553 return WS_E_NOT_SUPPORTED
;
1557 static HRESULT
add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1558 const WS_XML_STRING
*ns
, BOOL single
)
1560 WS_XML_ATTRIBUTE
*attr
;
1561 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1564 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1566 attr
->singleQuote
= !!single
;
1568 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
1570 free_attribute( attr
);
1571 return E_OUTOFMEMORY
;
1573 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
1575 free_attribute( attr
);
1576 return E_OUTOFMEMORY
;
1578 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1580 free_attribute( attr
);
1586 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
1588 if (!str1
&& !str2
) return TRUE
;
1589 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
1592 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
1593 const WS_XML_STRING
*ns
)
1596 const struct node
*node
;
1598 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
1600 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
1603 for (i
= 0; i
< elem
->attributeCount
; i
++)
1605 if (!elem
->attributes
[i
]->isXmlNs
) continue;
1606 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
1607 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
1613 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
1616 if (!(str
= dup_xml_string( ns
, writer
->dict_do_lookup
))) return E_OUTOFMEMORY
;
1617 free_xml_string( writer
->current_ns
);
1618 writer
->current_ns
= str
;
1622 static HRESULT
set_namespaces( struct writer
*writer
)
1624 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1628 if (elem
->ns
->length
&& !namespace_in_scope( elem
, elem
->prefix
, elem
->ns
))
1630 if ((hr
= add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
) return hr
;
1631 if ((hr
= set_current_namespace( writer
, elem
->ns
)) != S_OK
) return hr
;
1634 for (i
= 0; i
< elem
->attributeCount
; i
++)
1636 const WS_XML_ATTRIBUTE
*attr
= elem
->attributes
[i
];
1637 if (!attr
->ns
->length
|| namespace_in_scope( elem
, attr
->prefix
, attr
->ns
)) continue;
1638 if ((hr
= add_namespace_attribute( writer
, attr
->prefix
, attr
->ns
, FALSE
)) != S_OK
) return hr
;
1644 /**************************************************************************
1645 * WsWriteEndAttribute [webservices.@]
1647 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1649 struct writer
*writer
= (struct writer
*)handle
;
1651 TRACE( "%p %p\n", handle
, error
);
1652 if (error
) FIXME( "ignoring error parameter\n" );
1654 if (!writer
) return E_INVALIDARG
;
1656 EnterCriticalSection( &writer
->cs
);
1658 if (writer
->magic
!= WRITER_MAGIC
)
1660 LeaveCriticalSection( &writer
->cs
);
1661 return E_INVALIDARG
;
1664 writer
->state
= WRITER_STATE_STARTELEMENT
;
1666 LeaveCriticalSection( &writer
->cs
);
1670 static HRESULT
write_attributes( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1674 for (i
= 0; i
< elem
->attributeCount
; i
++)
1676 if (elem
->attributes
[i
]->isXmlNs
) continue;
1677 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1679 for (i
= 0; i
< elem
->attributeCount
; i
++)
1681 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
1682 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1684 for (i
= 0; i
< elem
->attributeCount
; i
++)
1686 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
1687 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
1692 static HRESULT
write_startelement_text( struct writer
*writer
)
1694 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1698 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
1700 size
= elem
->localName
->length
+ 1 /* '<' */;
1701 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1702 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1704 write_char( writer
, '<' );
1705 if (elem
->prefix
&& elem
->prefix
->length
)
1707 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1708 write_char( writer
, ':' );
1710 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1711 return write_attributes( writer
, elem
);
1714 static enum record_type
get_elem_record_type( const WS_XML_ELEMENT_NODE
*elem
, BOOL use_dict
)
1716 if (!elem
->prefix
|| !elem
->prefix
->length
)
1718 if (use_dict
) return RECORD_SHORT_DICTIONARY_ELEMENT
;
1719 return RECORD_SHORT_ELEMENT
;
1721 if (elem
->prefix
->length
== 1 && elem
->prefix
->bytes
[0] >= 'a' && elem
->prefix
->bytes
[0] <= 'z')
1723 if (use_dict
) return RECORD_PREFIX_DICTIONARY_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1724 return RECORD_PREFIX_ELEMENT_A
+ elem
->prefix
->bytes
[0] - 'a';
1726 if (use_dict
) return RECORD_DICTIONARY_ELEMENT
;
1727 return RECORD_ELEMENT
;
1730 static HRESULT
write_startelement_bin( struct writer
*writer
)
1732 const WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1734 enum record_type type
= get_elem_record_type( elem
, get_string_id(writer
, elem
->localName
, &id
) );
1737 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1738 write_char( writer
, type
);
1740 if (type
>= RECORD_PREFIX_ELEMENT_A
&& type
<= RECORD_PREFIX_ELEMENT_Z
)
1742 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1743 return write_attributes( writer
, elem
);
1745 if (type
>= RECORD_PREFIX_DICTIONARY_ELEMENT_A
&& type
<= RECORD_PREFIX_DICTIONARY_ELEMENT_Z
)
1747 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1748 return write_attributes( writer
, elem
);
1753 case RECORD_SHORT_ELEMENT
:
1754 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1757 case RECORD_ELEMENT
:
1758 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1759 if ((hr
= write_string( writer
, elem
->localName
->bytes
, elem
->localName
->length
)) != S_OK
) return hr
;
1762 case RECORD_SHORT_DICTIONARY_ELEMENT
:
1763 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1766 case RECORD_DICTIONARY_ELEMENT
:
1767 if ((hr
= write_string( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
)) != S_OK
) return hr
;
1768 if ((hr
= write_dict_string( writer
, id
)) != S_OK
) return hr
;
1772 ERR( "unhandled record type %02x\n", type
);
1773 return WS_E_NOT_SUPPORTED
;
1776 return write_attributes( writer
, elem
);
1779 static HRESULT
write_startelement( struct writer
*writer
)
1781 switch (writer
->output_enc
)
1783 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_startelement_text( writer
);
1784 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_startelement_bin( writer
);
1786 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1787 return WS_E_NOT_SUPPORTED
;
1791 static struct node
*write_find_startelement( struct writer
*writer
)
1794 for (node
= writer
->current
; node
; node
= node
->parent
)
1796 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
1801 static inline BOOL
is_empty_element( const struct node
*node
)
1803 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
1804 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
1807 static HRESULT
write_endelement_text( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1814 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
1816 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
1817 write_char( writer
, '/' );
1818 write_char( writer
, '>' );
1822 /* '</prefix:localname>' */
1824 size
= elem
->localName
->length
+ 3 /* '</>' */;
1825 if (elem
->prefix
&& elem
->prefix
->length
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
1826 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
1828 write_char( writer
, '<' );
1829 write_char( writer
, '/' );
1830 if (elem
->prefix
&& elem
->prefix
->length
)
1832 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
1833 write_char( writer
, ':' );
1835 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
1836 write_char( writer
, '>' );
1840 static HRESULT
write_endelement_bin( struct writer
*writer
)
1843 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_TEXT
) return S_OK
;
1844 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1845 write_char( writer
, RECORD_ENDELEMENT
);
1849 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
1851 switch (writer
->output_enc
)
1853 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endelement_text( writer
, elem
);
1854 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_endelement_bin( writer
);
1856 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1857 return WS_E_NOT_SUPPORTED
;
1861 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
1863 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
1864 elem
->isEmpty
= is_empty_element( node
);
1865 return write_endelement( writer
, elem
);
1868 static HRESULT
write_endelement_node( struct writer
*writer
)
1873 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
1874 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
1876 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
1877 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
1879 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
1880 writer
->current
= node
->parent
;
1881 writer
->state
= WRITER_STATE_ENDELEMENT
;
1885 /**************************************************************************
1886 * WsWriteEndElement [webservices.@]
1888 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1890 struct writer
*writer
= (struct writer
*)handle
;
1893 TRACE( "%p %p\n", handle
, error
);
1894 if (error
) FIXME( "ignoring error parameter\n" );
1896 if (!writer
) return E_INVALIDARG
;
1898 EnterCriticalSection( &writer
->cs
);
1900 if (writer
->magic
!= WRITER_MAGIC
)
1902 LeaveCriticalSection( &writer
->cs
);
1903 return E_INVALIDARG
;
1906 hr
= write_endelement_node( writer
);
1908 LeaveCriticalSection( &writer
->cs
);
1912 static HRESULT
write_endstartelement_text( struct writer
*writer
)
1915 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
1916 write_char( writer
, '>' );
1920 static HRESULT
write_endstartelement( struct writer
*writer
)
1922 switch (writer
->output_enc
)
1924 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_endstartelement_text( writer
);
1925 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return S_OK
;
1927 ERR( "unhandled encoding %u\n", writer
->output_enc
);
1928 return WS_E_NOT_SUPPORTED
;
1932 /**************************************************************************
1933 * WsWriteEndStartElement [webservices.@]
1935 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1937 struct writer
*writer
= (struct writer
*)handle
;
1940 TRACE( "%p %p\n", handle
, error
);
1941 if (error
) FIXME( "ignoring error parameter\n" );
1943 if (!writer
) return E_INVALIDARG
;
1945 EnterCriticalSection( &writer
->cs
);
1947 if (writer
->magic
!= WRITER_MAGIC
)
1949 LeaveCriticalSection( &writer
->cs
);
1950 return E_INVALIDARG
;
1953 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
1955 LeaveCriticalSection( &writer
->cs
);
1956 return WS_E_INVALID_OPERATION
;
1959 if ((hr
= set_namespaces( writer
)) != S_OK
) goto done
;
1960 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
1961 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
1962 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
1965 LeaveCriticalSection( &writer
->cs
);
1969 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1970 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1973 WS_XML_ATTRIBUTE
*attr
;
1974 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1977 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
1979 if (!prefix
&& ns
->length
) prefix
= elem
->prefix
;
1981 attr
->singleQuote
= !!single
;
1982 if (prefix
&& !(attr
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
1984 free_attribute( attr
);
1985 return E_OUTOFMEMORY
;
1987 if (!(attr
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
1989 free_attribute( attr
);
1990 return E_OUTOFMEMORY
;
1992 if (!(attr
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
1994 free_attribute( attr
);
1995 return E_OUTOFMEMORY
;
1997 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
1999 free_attribute( attr
);
2005 /**************************************************************************
2006 * WsWriteStartAttribute [webservices.@]
2008 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2009 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2010 BOOL single
, WS_ERROR
*error
)
2012 struct writer
*writer
= (struct writer
*)handle
;
2015 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
2016 debugstr_xmlstr(ns
), single
, error
);
2017 if (error
) FIXME( "ignoring error parameter\n" );
2019 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
2021 EnterCriticalSection( &writer
->cs
);
2023 if (writer
->magic
!= WRITER_MAGIC
)
2025 LeaveCriticalSection( &writer
->cs
);
2026 return E_INVALIDARG
;
2029 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
2031 LeaveCriticalSection( &writer
->cs
);
2032 return WS_E_INVALID_OPERATION
;
2035 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
2036 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2038 LeaveCriticalSection( &writer
->cs
);
2042 /* flush current start element if necessary */
2043 static HRESULT
write_flush( struct writer
*writer
)
2045 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
2048 if ((hr
= set_namespaces( writer
)) != S_OK
) return hr
;
2049 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
2050 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
2051 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
2056 static HRESULT
write_add_cdata_node( struct writer
*writer
)
2058 struct node
*node
, *parent
;
2059 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2060 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
2061 write_insert_node( writer
, parent
, node
);
2065 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
2068 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
2069 node
->parent
= writer
->current
;
2070 list_add_tail( &node
->parent
->children
, &node
->entry
);
2074 static HRESULT
write_cdata( struct writer
*writer
)
2077 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
2078 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
2082 static HRESULT
write_cdata_node( struct writer
*writer
)
2085 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2086 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
2087 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
2088 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
2089 writer
->state
= WRITER_STATE_STARTCDATA
;
2093 /**************************************************************************
2094 * WsWriteStartCData [webservices.@]
2096 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2098 struct writer
*writer
= (struct writer
*)handle
;
2101 TRACE( "%p %p\n", handle
, error
);
2102 if (error
) FIXME( "ignoring error parameter\n" );
2104 if (!writer
) return E_INVALIDARG
;
2106 EnterCriticalSection( &writer
->cs
);
2108 if (writer
->magic
!= WRITER_MAGIC
)
2110 LeaveCriticalSection( &writer
->cs
);
2111 return E_INVALIDARG
;
2114 hr
= write_cdata_node( writer
);
2116 LeaveCriticalSection( &writer
->cs
);
2120 static HRESULT
write_endcdata( struct writer
*writer
)
2123 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2124 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
2128 static HRESULT
write_endcdata_node( struct writer
*writer
)
2131 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
2132 writer
->current
= writer
->current
->parent
;
2133 writer
->state
= WRITER_STATE_ENDCDATA
;
2137 /**************************************************************************
2138 * WsWriteEndCData [webservices.@]
2140 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
2142 struct writer
*writer
= (struct writer
*)handle
;
2145 TRACE( "%p %p\n", handle
, error
);
2146 if (error
) FIXME( "ignoring error parameter\n" );
2148 if (!writer
) return E_INVALIDARG
;
2150 EnterCriticalSection( &writer
->cs
);
2152 if (writer
->magic
!= WRITER_MAGIC
)
2154 LeaveCriticalSection( &writer
->cs
);
2155 return E_INVALIDARG
;
2158 if (writer
->state
!= WRITER_STATE_TEXT
)
2160 LeaveCriticalSection( &writer
->cs
);
2161 return WS_E_INVALID_OPERATION
;
2164 hr
= write_endcdata_node( writer
);
2166 LeaveCriticalSection( &writer
->cs
);
2170 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2171 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
2173 struct node
*node
, *parent
;
2174 WS_XML_ELEMENT_NODE
*elem
;
2176 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
2178 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2180 elem
= &parent
->hdr
;
2181 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
2184 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
2187 if (prefix
&& !(elem
->prefix
= dup_xml_string( prefix
, writer
->dict_do_lookup
)))
2190 return E_OUTOFMEMORY
;
2192 if (!(elem
->localName
= dup_xml_string( localname
, writer
->dict_do_lookup
)))
2195 return E_OUTOFMEMORY
;
2197 if (!(elem
->ns
= dup_xml_string( ns
, writer
->dict_do_lookup
)))
2200 return E_OUTOFMEMORY
;
2202 write_insert_node( writer
, parent
, node
);
2206 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
2209 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
2210 node
->parent
= parent
;
2211 list_add_tail( &parent
->children
, &node
->entry
);
2215 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2216 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
2219 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2220 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
2221 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
2222 writer
->state
= WRITER_STATE_STARTELEMENT
;
2226 /**************************************************************************
2227 * WsWriteStartElement [webservices.@]
2229 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2230 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2233 struct writer
*writer
= (struct writer
*)handle
;
2236 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
2237 debugstr_xmlstr(ns
), error
);
2238 if (error
) FIXME( "ignoring error parameter\n" );
2240 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
2242 EnterCriticalSection( &writer
->cs
);
2244 if (writer
->magic
!= WRITER_MAGIC
)
2246 LeaveCriticalSection( &writer
->cs
);
2247 return E_INVALIDARG
;
2250 hr
= write_element_node( writer
, prefix
, localname
, ns
);
2252 LeaveCriticalSection( &writer
->cs
);
2256 HRESULT
text_to_text( const WS_XML_TEXT
*text
, const WS_XML_TEXT
*old
, ULONG
*offset
, WS_XML_TEXT
**ret
)
2258 if (offset
) *offset
= 0;
2259 switch (text
->textType
)
2261 case WS_XML_TEXT_TYPE_UTF8
:
2263 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2264 const WS_XML_UTF8_TEXT
*utf8_old
= (const WS_XML_UTF8_TEXT
*)old
;
2265 WS_XML_UTF8_TEXT
*new;
2266 ULONG len
= utf8
->value
.length
, len_old
= utf8_old
? utf8_old
->value
.length
: 0;
2268 if (!(new = alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2269 if (utf8_old
) memcpy( new->value
.bytes
, utf8_old
->value
.bytes
, len_old
);
2270 memcpy( new->value
.bytes
+ len_old
, utf8
->value
.bytes
, len
);
2271 if (offset
) *offset
= len_old
;
2275 case WS_XML_TEXT_TYPE_UTF16
:
2277 const WS_XML_UTF16_TEXT
*utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2278 const WS_XML_UTF16_TEXT
*utf16_old
= (const WS_XML_UTF16_TEXT
*)old
;
2279 WS_XML_UTF16_TEXT
*new;
2280 ULONG len
= utf16
->byteCount
, len_old
= utf16_old
? utf16_old
->byteCount
: 0;
2282 if (utf16
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
2283 if (!(new = alloc_utf16_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2284 if (utf16_old
) memcpy( new->bytes
, utf16_old
->bytes
, len_old
);
2285 memcpy( new->bytes
+ len_old
, utf16
->bytes
, len
);
2286 if (offset
) *offset
= len_old
;
2290 case WS_XML_TEXT_TYPE_BASE64
:
2292 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
2293 const WS_XML_BASE64_TEXT
*base64_old
= (const WS_XML_BASE64_TEXT
*)old
;
2294 WS_XML_BASE64_TEXT
*new;
2295 ULONG len
= base64
->length
, len_old
= base64_old
? base64_old
->length
: 0;
2297 if (!(new = alloc_base64_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
2298 if (base64_old
) memcpy( new->bytes
, base64_old
->bytes
, len_old
);
2299 memcpy( new->bytes
+ len_old
, base64
->bytes
, len
);
2300 if (offset
) *offset
= len_old
;
2304 case WS_XML_TEXT_TYPE_BOOL
:
2306 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
2307 WS_XML_BOOL_TEXT
*new;
2309 if (!(new = alloc_bool_text( bool_text
->value
))) return E_OUTOFMEMORY
;
2313 case WS_XML_TEXT_TYPE_INT32
:
2315 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
2316 WS_XML_INT32_TEXT
*new;
2318 if (!(new = alloc_int32_text( int32_text
->value
))) return E_OUTOFMEMORY
;
2322 case WS_XML_TEXT_TYPE_INT64
:
2324 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
2325 WS_XML_INT64_TEXT
*new;
2327 if (!(new = alloc_int64_text( int64_text
->value
))) return E_OUTOFMEMORY
;
2331 case WS_XML_TEXT_TYPE_UINT64
:
2333 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
2334 WS_XML_UINT64_TEXT
*new;
2336 if (!(new = alloc_uint64_text( uint64_text
->value
))) return E_OUTOFMEMORY
;
2340 case WS_XML_TEXT_TYPE_DOUBLE
:
2342 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
2343 WS_XML_DOUBLE_TEXT
*new;
2345 if (!(new = alloc_double_text( double_text
->value
))) return E_OUTOFMEMORY
;
2349 case WS_XML_TEXT_TYPE_GUID
:
2351 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
2352 WS_XML_GUID_TEXT
*new;
2354 if (!(new = alloc_guid_text( &id
->value
))) return E_OUTOFMEMORY
;
2358 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2360 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
2361 WS_XML_UNIQUE_ID_TEXT
*new;
2363 if (!(new = alloc_unique_id_text( &id
->value
))) return E_OUTOFMEMORY
;
2367 case WS_XML_TEXT_TYPE_DATETIME
:
2369 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
2370 WS_XML_DATETIME_TEXT
*new;
2372 if (!(new = alloc_datetime_text( &dt
->value
))) return E_OUTOFMEMORY
;
2377 FIXME( "unhandled text type %u\n", text
->textType
);
2382 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
2384 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
2387 switch (value
->textType
)
2389 case WS_XML_TEXT_TYPE_UTF8
:
2390 case WS_XML_TEXT_TYPE_UTF16
:
2391 case WS_XML_TEXT_TYPE_BASE64
:
2394 case WS_XML_TEXT_TYPE_BOOL
:
2395 case WS_XML_TEXT_TYPE_INT32
:
2396 case WS_XML_TEXT_TYPE_INT64
:
2397 case WS_XML_TEXT_TYPE_UINT64
:
2398 case WS_XML_TEXT_TYPE_DOUBLE
:
2399 case WS_XML_TEXT_TYPE_GUID
:
2400 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2401 case WS_XML_TEXT_TYPE_DATETIME
:
2402 if (elem
->attributes
[elem
->attributeCount
- 1]->value
) return WS_E_INVALID_OPERATION
;
2406 FIXME( "unhandled text type %u\n", value
->textType
);
2410 switch (writer
->output_enc
)
2412 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2414 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
2415 if ((hr
= text_to_utf8text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2417 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
2420 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2422 WS_XML_TEXT
*new, *old
= elem
->attributes
[elem
->attributeCount
- 1]->value
;
2423 if ((hr
= text_to_text( value
, old
, NULL
, &new )) != S_OK
) return hr
;
2425 elem
->attributes
[elem
->attributeCount
- 1]->value
= new;
2429 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2436 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
2439 WS_XML_TEXT_NODE
*text
;
2442 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
2443 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
2444 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
2446 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
2447 text
= (WS_XML_TEXT_NODE
*)node
;
2449 switch (writer
->output_enc
)
2451 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2453 WS_XML_UTF8_TEXT
*new;
2454 if ((hr
= text_to_utf8text( value
, NULL
, NULL
, &new )) != S_OK
)
2459 text
->text
= &new->text
;
2462 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2465 if ((hr
= text_to_text( value
, NULL
, NULL
, &new )) != S_OK
)
2474 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2479 write_insert_node( writer
, writer
->current
, node
);
2483 static HRESULT
write_text_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2485 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2488 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
2490 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
2491 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
2493 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
2495 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
2496 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
2500 return WS_E_INVALID_FORMAT
;
2503 static enum record_type
get_text_record_type( const WS_XML_TEXT
*text
, BOOL use_dict
)
2505 switch (text
->textType
)
2507 case WS_XML_TEXT_TYPE_UTF8
:
2509 const WS_XML_UTF8_TEXT
*text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2510 if (use_dict
) return RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
;
2511 if (text_utf8
->value
.length
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2512 if (text_utf8
->value
.length
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2513 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2515 case WS_XML_TEXT_TYPE_UTF16
:
2517 const WS_XML_UTF16_TEXT
*text_utf16
= (const WS_XML_UTF16_TEXT
*)text
;
2518 int len
= text_utf16
->byteCount
/ sizeof(WCHAR
);
2519 int len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, (const WCHAR
*)text_utf16
->bytes
, len
, NULL
, 0, NULL
, NULL
);
2520 if (len_utf8
<= MAX_UINT8
) return RECORD_CHARS8_TEXT_WITH_ENDELEMENT
;
2521 if (len_utf8
<= MAX_UINT16
) return RECORD_CHARS16_TEXT_WITH_ENDELEMENT
;
2522 return RECORD_CHARS32_TEXT_WITH_ENDELEMENT
;
2524 case WS_XML_TEXT_TYPE_BASE64
:
2526 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2527 ULONG rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2528 if (len
<= MAX_UINT8
) return RECORD_BYTES8_TEXT
;
2529 if (len
<= MAX_UINT16
) return RECORD_BYTES16_TEXT
;
2530 return RECORD_BYTES32_TEXT
;
2532 case WS_XML_TEXT_TYPE_BOOL
:
2534 const WS_XML_BOOL_TEXT
*text_bool
= (const WS_XML_BOOL_TEXT
*)text
;
2535 return text_bool
->value
? RECORD_TRUE_TEXT_WITH_ENDELEMENT
: RECORD_FALSE_TEXT_WITH_ENDELEMENT
;
2537 case WS_XML_TEXT_TYPE_INT32
:
2539 const WS_XML_INT32_TEXT
*text_int32
= (const WS_XML_INT32_TEXT
*)text
;
2540 if (!text_int32
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2541 if (text_int32
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2542 if (text_int32
->value
>= MIN_INT8
&& text_int32
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2543 if (text_int32
->value
>= MIN_INT16
&& text_int32
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2544 return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2546 case WS_XML_TEXT_TYPE_INT64
:
2548 const WS_XML_INT64_TEXT
*text_int64
= (const WS_XML_INT64_TEXT
*)text
;
2549 if (!text_int64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2550 if (text_int64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2551 if (text_int64
->value
>= MIN_INT8
&& text_int64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2552 if (text_int64
->value
>= MIN_INT16
&& text_int64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2553 if (text_int64
->value
>= MIN_INT32
&& text_int64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2554 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2556 case WS_XML_TEXT_TYPE_UINT64
:
2558 const WS_XML_UINT64_TEXT
*text_uint64
= (const WS_XML_UINT64_TEXT
*)text
;
2559 if (!text_uint64
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2560 if (text_uint64
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2561 if (text_uint64
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2562 if (text_uint64
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2563 if (text_uint64
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2564 if (text_uint64
->value
<= MAX_INT64
) return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2565 return RECORD_UINT64_TEXT_WITH_ENDELEMENT
;
2567 case WS_XML_TEXT_TYPE_DOUBLE
:
2569 const WS_XML_DOUBLE_TEXT
*text_double
= (const WS_XML_DOUBLE_TEXT
*)text
;
2570 if (!text_double
->value
) return RECORD_ZERO_TEXT_WITH_ENDELEMENT
;
2571 if (text_double
->value
== 1) return RECORD_ONE_TEXT_WITH_ENDELEMENT
;
2572 if (isinf( text_double
->value
) || (INT64
)text_double
->value
!= text_double
->value
)
2573 return RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
;
2574 if (text_double
->value
<= MAX_INT8
) return RECORD_INT8_TEXT_WITH_ENDELEMENT
;
2575 if (text_double
->value
<= MAX_INT16
) return RECORD_INT16_TEXT_WITH_ENDELEMENT
;
2576 if (text_double
->value
<= MAX_INT32
) return RECORD_INT32_TEXT_WITH_ENDELEMENT
;
2577 return RECORD_INT64_TEXT_WITH_ENDELEMENT
;
2579 case WS_XML_TEXT_TYPE_GUID
:
2580 return RECORD_GUID_TEXT_WITH_ENDELEMENT
;
2582 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
2583 return RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
;
2585 case WS_XML_TEXT_TYPE_DATETIME
:
2586 return RECORD_DATETIME_TEXT_WITH_ENDELEMENT
;
2589 FIXME( "unhandled text type %u\n", text
->textType
);
2594 static HRESULT
write_text_bin( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2596 enum record_type type
;
2597 BOOL use_dict
= FALSE
;
2603 FIXME( "no support for appending text in binary mode\n" );
2607 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
)
2609 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2610 use_dict
= get_string_id( writer
, &utf8
->value
, &id
);
2613 switch ((type
= get_text_record_type( text
, use_dict
)))
2615 case RECORD_CHARS8_TEXT_WITH_ENDELEMENT
:
2617 const WS_XML_UTF8_TEXT
*text_utf8
;
2618 WS_XML_UTF8_TEXT
*new = NULL
;
2621 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2624 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
2627 len
= text_utf8
->value
.length
;
2628 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
)
2633 write_char( writer
, type
);
2634 write_char( writer
, len
);
2635 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2639 case RECORD_CHARS16_TEXT_WITH_ENDELEMENT
:
2641 const WS_XML_UTF8_TEXT
*text_utf8
;
2642 WS_XML_UTF8_TEXT
*new = NULL
;
2645 if (text
->textType
== WS_XML_TEXT_TYPE_UTF8
) text_utf8
= (const WS_XML_UTF8_TEXT
*)text
;
2648 if ((hr
= text_to_utf8text( text
, NULL
, NULL
, &new )) != S_OK
) return hr
;
2651 len
= text_utf8
->value
.length
;
2652 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
)
2657 write_char( writer
, type
);
2658 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2659 write_bytes( writer
, text_utf8
->value
.bytes
, len
);
2663 case RECORD_BYTES8_TEXT
:
2665 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2666 UINT8 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2670 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2671 write_char( writer
, rem
? RECORD_BYTES8_TEXT
: RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2672 write_char( writer
, len
);
2673 write_bytes( writer
, text_base64
->bytes
, len
);
2677 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2678 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2679 write_char( writer
, rem
);
2680 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2684 case RECORD_BYTES16_TEXT
:
2686 const WS_XML_BASE64_TEXT
*text_base64
= (const WS_XML_BASE64_TEXT
*)text
;
2687 UINT16 rem
= text_base64
->length
% 3, len
= text_base64
->length
- rem
;
2691 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(len
) + len
)) != S_OK
) return hr
;
2692 write_char( writer
, rem
? RECORD_BYTES16_TEXT
: RECORD_BYTES16_TEXT_WITH_ENDELEMENT
);
2693 write_bytes( writer
, (const BYTE
*)&len
, sizeof(len
) );
2694 write_bytes( writer
, text_base64
->bytes
, len
);
2698 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
2699 write_char( writer
, RECORD_BYTES8_TEXT_WITH_ENDELEMENT
);
2700 write_char( writer
, rem
);
2701 write_bytes( writer
, (const BYTE
*)text_base64
->bytes
+ len
, rem
);
2705 case RECORD_ZERO_TEXT_WITH_ENDELEMENT
:
2706 case RECORD_ONE_TEXT_WITH_ENDELEMENT
:
2707 case RECORD_FALSE_TEXT_WITH_ENDELEMENT
:
2708 case RECORD_TRUE_TEXT_WITH_ENDELEMENT
:
2710 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2711 write_char( writer
, type
);
2714 case RECORD_INT8_TEXT_WITH_ENDELEMENT
:
2716 INT8 val
= get_text_value_int( text
);
2717 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2718 write_char( writer
, type
);
2719 write_char( writer
, val
);
2722 case RECORD_INT16_TEXT_WITH_ENDELEMENT
:
2724 INT16 val
= get_text_value_int( text
);
2725 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2726 write_char( writer
, type
);
2727 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2730 case RECORD_INT32_TEXT_WITH_ENDELEMENT
:
2732 INT32 val
= get_text_value_int( text
);
2733 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2734 write_char( writer
, type
);
2735 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2738 case RECORD_INT64_TEXT_WITH_ENDELEMENT
:
2740 INT64 val
= get_text_value_int( text
);
2741 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2742 write_char( writer
, type
);
2743 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2746 case RECORD_UINT64_TEXT_WITH_ENDELEMENT
:
2748 WS_XML_UINT64_TEXT
*text_uint64
= (WS_XML_UINT64_TEXT
*)text
;
2749 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_uint64
->value
) )) != S_OK
) return hr
;
2750 write_char( writer
, type
);
2751 write_bytes( writer
, (const BYTE
*)&text_uint64
->value
, sizeof(text_uint64
->value
) );
2754 case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT
:
2756 WS_XML_DOUBLE_TEXT
*text_double
= (WS_XML_DOUBLE_TEXT
*)text
;
2757 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_double
->value
) )) != S_OK
) return hr
;
2758 write_char( writer
, type
);
2759 write_bytes( writer
, (const BYTE
*)&text_double
->value
, sizeof(text_double
->value
) );
2762 case RECORD_GUID_TEXT_WITH_ENDELEMENT
:
2764 WS_XML_GUID_TEXT
*text_guid
= (WS_XML_GUID_TEXT
*)text
;
2765 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_guid
->value
) )) != S_OK
) return hr
;
2766 write_char( writer
, type
);
2767 write_bytes( writer
, (const BYTE
*)&text_guid
->value
, sizeof(text_guid
->value
) );
2770 case RECORD_UNIQUE_ID_TEXT_WITH_ENDELEMENT
:
2772 WS_XML_UNIQUE_ID_TEXT
*text_unique_id
= (WS_XML_UNIQUE_ID_TEXT
*)text
;
2773 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(text_unique_id
->value
) )) != S_OK
) return hr
;
2774 write_char( writer
, type
);
2775 write_bytes( writer
, (const BYTE
*)&text_unique_id
->value
, sizeof(text_unique_id
->value
) );
2778 case RECORD_DATETIME_TEXT_WITH_ENDELEMENT
:
2780 WS_XML_DATETIME_TEXT
*text_datetime
= (WS_XML_DATETIME_TEXT
*)text
;
2781 UINT64 val
= text_datetime
->value
.ticks
;
2783 assert( val
<= TICKS_MAX
);
2784 if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_UTC
) val
|= (UINT64
)1 << 62;
2785 else if (text_datetime
->value
.format
== WS_DATETIME_FORMAT_LOCAL
) val
|= (UINT64
)1 << 63;
2787 if ((hr
= write_grow_buffer( writer
, 1 + sizeof(val
) )) != S_OK
) return hr
;
2788 write_char( writer
, type
);
2789 write_bytes( writer
, (const BYTE
*)&val
, sizeof(val
) );
2792 case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT
:
2794 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
2795 write_char( writer
, type
);
2796 return write_dict_string( writer
, id
);
2799 FIXME( "unhandled record type %02x\n", type
);
2804 static HRESULT
write_text( struct writer
*writer
, const WS_XML_TEXT
*text
, ULONG offset
)
2806 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
2808 switch (writer
->output_enc
)
2810 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_text_text( writer
, text
, offset
);
2811 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_text_bin( writer
, text
, offset
);
2813 ERR( "unhandled encoding %u\n", writer
->output_enc
);
2814 return WS_E_NOT_SUPPORTED
;
2818 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
2820 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2824 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
2825 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
2827 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
2828 node
= (WS_XML_TEXT_NODE
*)writer
->current
;
2832 switch (writer
->output_enc
)
2834 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
2836 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
2837 offset
= old
->value
.length
;
2838 if ((hr
= text_to_utf8text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2840 node
->text
= &new->text
;
2843 case WS_XML_WRITER_ENCODING_TYPE_BINARY
:
2845 WS_XML_TEXT
*new, *old
= node
->text
;
2846 if ((hr
= text_to_text( text
, old
, &offset
, &new )) != S_OK
) return hr
;
2852 FIXME( "unhandled output encoding %u\n", writer
->output_enc
);
2857 if ((hr
= write_text( writer
, node
->text
, offset
)) != S_OK
) return hr
;
2859 writer
->state
= WRITER_STATE_TEXT
;
2863 /**************************************************************************
2864 * WsWriteText [webservices.@]
2866 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
2868 struct writer
*writer
= (struct writer
*)handle
;
2871 TRACE( "%p %p %p\n", handle
, text
, error
);
2872 if (error
) FIXME( "ignoring error parameter\n" );
2874 if (!writer
|| !text
) return E_INVALIDARG
;
2876 EnterCriticalSection( &writer
->cs
);
2878 if (writer
->magic
!= WRITER_MAGIC
)
2880 LeaveCriticalSection( &writer
->cs
);
2881 return E_INVALIDARG
;
2884 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
2885 else hr
= write_text_node( writer
, text
);
2887 LeaveCriticalSection( &writer
->cs
);
2891 /**************************************************************************
2892 * WsWriteBytes [webservices.@]
2894 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
2896 struct writer
*writer
= (struct writer
*)handle
;
2897 WS_XML_BASE64_TEXT base64
;
2900 TRACE( "%p %p %u %p\n", handle
, bytes
, count
, error
);
2901 if (error
) FIXME( "ignoring error parameter\n" );
2903 if (!writer
) return E_INVALIDARG
;
2905 EnterCriticalSection( &writer
->cs
);
2907 if (writer
->magic
!= WRITER_MAGIC
)
2909 LeaveCriticalSection( &writer
->cs
);
2910 return E_INVALIDARG
;
2913 if (!writer
->output_type
)
2915 LeaveCriticalSection( &writer
->cs
);
2916 return WS_E_INVALID_OPERATION
;
2919 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2920 base64
.bytes
= (BYTE
*)bytes
;
2921 base64
.length
= count
;
2923 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
2924 else hr
= write_text_node( writer
, &base64
.text
);
2926 LeaveCriticalSection( &writer
->cs
);
2930 /**************************************************************************
2931 * WsWriteChars [webservices.@]
2933 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
2935 struct writer
*writer
= (struct writer
*)handle
;
2936 WS_XML_UTF16_TEXT utf16
;
2939 TRACE( "%p %s %u %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
2940 if (error
) FIXME( "ignoring error parameter\n" );
2942 if (!writer
) return E_INVALIDARG
;
2944 EnterCriticalSection( &writer
->cs
);
2946 if (writer
->magic
!= WRITER_MAGIC
)
2948 LeaveCriticalSection( &writer
->cs
);
2949 return E_INVALIDARG
;
2952 if (!writer
->output_type
)
2954 LeaveCriticalSection( &writer
->cs
);
2955 return WS_E_INVALID_OPERATION
;
2958 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2959 utf16
.bytes
= (BYTE
*)chars
;
2960 utf16
.byteCount
= count
* sizeof(WCHAR
);
2962 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
2963 else hr
= write_text_node( writer
, &utf16
.text
);
2965 LeaveCriticalSection( &writer
->cs
);
2969 /**************************************************************************
2970 * WsWriteCharsUtf8 [webservices.@]
2972 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
2974 struct writer
*writer
= (struct writer
*)handle
;
2975 WS_XML_UTF8_TEXT utf8
;
2978 TRACE( "%p %s %u %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
2979 if (error
) FIXME( "ignoring error parameter\n" );
2981 if (!writer
) return E_INVALIDARG
;
2983 EnterCriticalSection( &writer
->cs
);
2985 if (writer
->magic
!= WRITER_MAGIC
)
2987 LeaveCriticalSection( &writer
->cs
);
2988 return E_INVALIDARG
;
2991 if (!writer
->output_type
)
2993 LeaveCriticalSection( &writer
->cs
);
2994 return WS_E_INVALID_OPERATION
;
2997 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2998 utf8
.value
.bytes
= (BYTE
*)bytes
;
2999 utf8
.value
.length
= count
;
3001 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
3002 else hr
= write_text_node( writer
, &utf8
.text
);
3004 LeaveCriticalSection( &writer
->cs
);
3008 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
3012 case WS_ELEMENT_TYPE_MAPPING
:
3013 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3014 return write_text_node( writer
, text
);
3016 case WS_ATTRIBUTE_TYPE_MAPPING
:
3017 return write_set_attribute_value( writer
, text
);
3019 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3020 switch (writer
->state
)
3022 case WRITER_STATE_STARTATTRIBUTE
:
3023 return write_set_attribute_value( writer
, text
);
3025 case WRITER_STATE_STARTELEMENT
:
3026 return write_text_node( writer
, text
);
3029 FIXME( "writer state %u not handled\n", writer
->state
);
3034 FIXME( "mapping %u not implemented\n", mapping
);
3039 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
3041 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
3042 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
3043 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
3044 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
3047 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
3048 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
3049 return add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
3052 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
3057 case WS_WRITE_REQUIRED_VALUE
:
3058 case WS_WRITE_NILLABLE_VALUE
:
3059 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
3063 case WS_WRITE_REQUIRED_POINTER
:
3064 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
3067 case WS_WRITE_NILLABLE_POINTER
:
3068 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
3069 *ptr
= *(const void **)value
;
3073 return E_INVALIDARG
;
3077 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3078 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3079 const BOOL
*value
, ULONG size
)
3081 WS_XML_BOOL_TEXT text_bool
;
3087 FIXME( "description not supported\n" );
3091 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3092 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
3093 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3095 text_bool
.text
.textType
= WS_XML_TEXT_TYPE_BOOL
;
3096 text_bool
.value
= *ptr
;
3097 return write_type_text( writer
, mapping
, &text_bool
.text
);
3100 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3101 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3102 const BOOL
*value
, ULONG size
)
3104 WS_XML_INT32_TEXT text_int32
;
3110 FIXME( "description not supported\n" );
3114 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3115 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3116 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3118 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3119 text_int32
.value
= *ptr
;
3120 return write_type_text( writer
, mapping
, &text_int32
.text
);
3123 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3124 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3125 const BOOL
*value
, ULONG size
)
3127 WS_XML_INT32_TEXT text_int32
;
3133 FIXME( "description not supported\n" );
3137 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3138 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3139 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3141 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3142 text_int32
.value
= *ptr
;
3143 return write_type_text( writer
, mapping
, &text_int32
.text
);
3146 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3147 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3148 const void *value
, ULONG size
)
3150 WS_XML_INT32_TEXT text_int32
;
3156 FIXME( "description not supported\n" );
3160 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3161 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3162 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3164 text_int32
.text
.textType
= WS_XML_TEXT_TYPE_INT32
;
3165 text_int32
.value
= *ptr
;
3166 return write_type_text( writer
, mapping
, &text_int32
.text
);
3169 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3170 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3171 const void *value
, ULONG size
)
3173 WS_XML_INT64_TEXT text_int64
;
3179 FIXME( "description not supported\n" );
3183 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3184 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3185 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3187 text_int64
.text
.textType
= WS_XML_TEXT_TYPE_INT64
;
3188 text_int64
.value
= *ptr
;
3189 return write_type_text( writer
, mapping
, &text_int64
.text
);
3192 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3193 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3194 const void *value
, ULONG size
)
3196 WS_XML_UINT64_TEXT text_uint64
;
3202 FIXME( "description not supported\n" );
3206 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3207 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
3208 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3210 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3211 text_uint64
.value
= *ptr
;
3212 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3215 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3216 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3217 const void *value
, ULONG size
)
3219 WS_XML_UINT64_TEXT text_uint64
;
3225 FIXME( "description not supported\n" );
3229 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3230 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
3231 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3233 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3234 text_uint64
.value
= *ptr
;
3235 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3238 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3239 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3240 const void *value
, ULONG size
)
3242 WS_XML_UINT64_TEXT text_uint64
;
3248 FIXME( "description not supported\n" );
3252 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3253 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
3254 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3256 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3257 text_uint64
.value
= *ptr
;
3258 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3261 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3262 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3263 const void *value
, ULONG size
)
3265 WS_XML_UINT64_TEXT text_uint64
;
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(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
3277 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3279 text_uint64
.text
.textType
= WS_XML_TEXT_TYPE_UINT64
;
3280 text_uint64
.value
= *ptr
;
3281 return write_type_text( writer
, mapping
, &text_uint64
.text
);
3284 static HRESULT
write_type_double( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3285 const WS_DOUBLE_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3286 const void *value
, ULONG size
)
3288 WS_XML_DOUBLE_TEXT text_double
;
3294 FIXME( "description not supported\n" );
3298 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3299 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(double), (const void **)&ptr
)) != S_OK
) return hr
;
3300 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3302 text_double
.text
.textType
= WS_XML_TEXT_TYPE_DOUBLE
;
3303 text_double
.value
= *ptr
;
3304 return write_type_text( writer
, mapping
, &text_double
.text
);
3307 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3308 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3309 const void *value
, ULONG size
)
3311 WS_XML_DATETIME_TEXT text_datetime
;
3312 const WS_DATETIME
*ptr
;
3317 FIXME( "description not supported\n" );
3321 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3322 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
3323 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3324 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
3326 text_datetime
.text
.textType
= WS_XML_TEXT_TYPE_DATETIME
;
3327 text_datetime
.value
= *ptr
;
3328 return write_type_text( writer
, mapping
, &text_datetime
.text
);
3331 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3332 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3333 const void *value
, ULONG size
)
3335 WS_XML_GUID_TEXT text_guid
;
3341 FIXME( "description not supported\n" );
3345 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3346 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
3347 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3349 text_guid
.text
.textType
= WS_XML_TEXT_TYPE_GUID
;
3350 text_guid
.value
= *ptr
;
3351 return write_type_text( writer
, mapping
, &text_guid
.text
);
3354 static HRESULT
write_type_unique_id( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3355 const WS_UNIQUE_ID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3356 const void *value
, ULONG size
)
3358 WS_XML_UNIQUE_ID_TEXT text_unique_id
;
3359 WS_XML_UTF16_TEXT text_utf16
;
3360 const WS_UNIQUE_ID
*ptr
;
3365 FIXME( "description not supported\n" );
3369 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3370 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3371 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3373 if (ptr
->uri
.length
)
3375 text_utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3376 text_utf16
.bytes
= (BYTE
*)ptr
->uri
.chars
;
3377 text_utf16
.byteCount
= ptr
->uri
.length
* sizeof(WCHAR
);
3378 return write_type_text( writer
, mapping
, &text_utf16
.text
);
3381 text_unique_id
.text
.textType
= WS_XML_TEXT_TYPE_UNIQUE_ID
;
3382 text_unique_id
.value
= ptr
->guid
;
3383 return write_type_text( writer
, mapping
, &text_unique_id
.text
);
3386 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3387 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3388 const void *value
, ULONG size
)
3390 WS_XML_UTF16_TEXT utf16
;
3391 const WS_STRING
*ptr
;
3396 FIXME( "description not supported\n" );
3400 if (!option
) return E_INVALIDARG
;
3401 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3402 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3403 if (!ptr
->length
) return S_OK
;
3405 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3406 utf16
.bytes
= (BYTE
*)ptr
->chars
;
3407 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
3408 return write_type_text( writer
, mapping
, &utf16
.text
);
3411 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3412 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3413 const void *value
, ULONG size
)
3415 WS_XML_UTF16_TEXT utf16
;
3422 FIXME( "description not supported\n" );
3426 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
3427 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
3428 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3429 if (!(len
= strlenW( ptr
))) return S_OK
;
3431 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
3432 utf16
.bytes
= (BYTE
*)ptr
;
3433 utf16
.byteCount
= len
* sizeof(WCHAR
);
3434 return write_type_text( writer
, mapping
, &utf16
.text
);
3437 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3438 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3439 const void *value
, ULONG size
)
3441 WS_XML_BASE64_TEXT base64
;
3442 const WS_BYTES
*ptr
;
3447 FIXME( "description not supported\n" );
3451 if (!option
) return E_INVALIDARG
;
3452 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
3453 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
3454 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
3455 if (!ptr
->length
) return S_OK
;
3457 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
3458 base64
.bytes
= ptr
->bytes
;
3459 base64
.length
= ptr
->length
;
3460 return write_type_text( writer
, mapping
, &base64
.text
);
3463 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3464 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3465 const void *value
, ULONG size
)
3467 WS_XML_UTF8_TEXT utf8
;
3468 const WS_XML_STRING
*ptr
;
3473 FIXME( "description not supported\n" );
3477 if (!option
) return E_INVALIDARG
;
3478 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
3479 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3480 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3481 if (!ptr
->length
) return S_OK
;
3483 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
3484 utf8
.value
.bytes
= ptr
->bytes
;
3485 utf8
.value
.length
= ptr
->length
;
3486 return write_type_text( writer
, mapping
, &utf8
.text
);
3489 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
3491 const struct node
*node
;
3492 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
3494 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
3496 for (i
= 0; i
< elem
->attributeCount
; i
++)
3498 if (!elem
->attributes
[i
]->isXmlNs
) continue;
3499 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
3500 *prefix
= elem
->attributes
[i
]->prefix
;
3504 return WS_E_INVALID_FORMAT
;
3507 static HRESULT
write_type_qname( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3508 const WS_XML_QNAME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3509 const void *value
, ULONG size
)
3511 WS_XML_QNAME_TEXT qname
;
3512 const WS_XML_QNAME
*ptr
;
3513 const WS_XML_STRING
*prefix
;
3518 FIXME( "description not supported\n" );
3522 if (!option
) return E_INVALIDARG
;
3523 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(*ptr
), (const void **)&ptr
)) != S_OK
) return hr
;
3524 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
3525 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
3527 if (((hr
= find_prefix( writer
, &ptr
->ns
, &prefix
)) != S_OK
)) return hr
;
3529 qname
.text
.textType
= WS_XML_TEXT_TYPE_QNAME
;
3530 qname
.prefix
= (WS_XML_STRING
*)prefix
;
3531 qname
.localName
= (WS_XML_STRING
*)&ptr
->localName
;
3532 qname
.ns
= (WS_XML_STRING
*)&ptr
->ns
;
3533 return write_type_text( writer
, mapping
, &qname
.text
);
3536 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
3538 if (options
& WS_FIELD_POINTER
)
3540 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3541 return WS_WRITE_REQUIRED_POINTER
;
3552 case WS_UINT16_TYPE
:
3553 case WS_UINT32_TYPE
:
3554 case WS_UINT64_TYPE
:
3555 case WS_DOUBLE_TYPE
:
3556 case WS_DATETIME_TYPE
:
3558 case WS_UNIQUE_ID_TYPE
:
3559 case WS_STRING_TYPE
:
3561 case WS_XML_STRING_TYPE
:
3562 case WS_XML_QNAME_TYPE
:
3563 case WS_STRUCT_TYPE
:
3566 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
3567 return WS_WRITE_REQUIRED_VALUE
;
3570 case WS_DESCRIPTION_TYPE
:
3571 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
3572 return WS_WRITE_REQUIRED_POINTER
;
3575 FIXME( "unhandled type %u\n", type
);
3580 static HRESULT
write_type_field( struct writer
*, const WS_FIELD_DESCRIPTION
*, const char *, ULONG
);
3582 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
3583 const void *, ULONG
);
3585 static HRESULT
write_type_union( struct writer
*writer
, const WS_UNION_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3586 const void *value
, ULONG size
)
3593 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3595 if (size
< sizeof(enum_value
)) return E_INVALIDARG
;
3596 if ((enum_value
= *(int *)(char *)ptr
+ desc
->enumOffset
) == desc
->noneEnumValue
)
3600 case WS_WRITE_REQUIRED_VALUE
:
3601 return WS_E_INVALID_FORMAT
;
3603 case WS_WRITE_NILLABLE_VALUE
:
3607 ERR( "unhandled write option %u\n", option
);
3608 return E_INVALIDARG
;
3612 for (i
= 0; i
< desc
->fieldCount
; i
++)
3614 if (desc
->fields
[i
]->value
== enum_value
)
3616 offset
= desc
->fields
[i
]->field
.offset
;
3617 return write_type_field( writer
, &desc
->fields
[i
]->field
, ptr
, offset
);
3621 return E_INVALIDARG
;
3624 static HRESULT
write_type_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3628 ULONG i
, size
, offset
= 0;
3629 WS_WRITE_OPTION option
;
3631 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
3633 /* wrapper element */
3634 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
3637 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
3638 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3640 size
= sizeof(const void *);
3642 for (i
= 0; i
< count
; i
++)
3644 if (desc
->type
== WS_UNION_TYPE
)
3646 if ((hr
= write_type_union( writer
, desc
->typeDescription
, option
, buf
+ offset
, size
)) != S_OK
)
3651 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
3652 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
3653 buf
+ offset
, size
)) != S_OK
) return hr
;
3654 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3659 if (desc
->localName
) hr
= write_endelement_node( writer
);
3663 static HRESULT
write_type_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const char *buf
,
3667 WS_TYPE_MAPPING mapping
;
3668 WS_WRITE_OPTION option
;
3669 ULONG count
, size
, field_options
= desc
->options
;
3670 const char *ptr
= buf
+ offset
;
3672 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
3674 FIXME( "options 0x%x not supported\n", desc
->options
);
3678 /* zero-terminated strings are always pointers */
3679 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
3681 if (field_options
& WS_FIELD_POINTER
)
3682 size
= sizeof(const void *);
3684 size
= get_type_size( desc
->type
, desc
->typeDescription
);
3686 if (is_nil_value( ptr
, size
))
3688 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
3689 if (field_options
& WS_FIELD_NILLABLE
)
3691 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
3692 else option
= WS_WRITE_NILLABLE_VALUE
;
3696 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3697 else option
= WS_WRITE_REQUIRED_VALUE
;
3702 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
3703 else option
= WS_WRITE_REQUIRED_VALUE
;
3706 switch (desc
->mapping
)
3708 case WS_ATTRIBUTE_FIELD_MAPPING
:
3709 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
3710 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
3712 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3714 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3717 case WS_ELEMENT_FIELD_MAPPING
:
3718 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
3719 mapping
= WS_ELEMENT_TYPE_MAPPING
;
3722 case WS_ELEMENT_CHOICE_FIELD_MAPPING
:
3723 if (desc
->type
!= WS_UNION_TYPE
|| !desc
->typeDescription
) return E_INVALIDARG
;
3724 option
= (field_options
& WS_FIELD_OPTIONAL
) ? WS_WRITE_NILLABLE_VALUE
: WS_WRITE_REQUIRED_VALUE
;
3725 return write_type_union( writer
, desc
->typeDescription
, option
, ptr
, size
);
3727 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
3728 case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING
:
3729 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
3730 return write_type_array( writer
, desc
, *(const char **)ptr
, count
);
3732 case WS_TEXT_FIELD_MAPPING
:
3733 switch (writer
->state
)
3735 case WRITER_STATE_STARTELEMENT
:
3736 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
3739 case WRITER_STATE_STARTATTRIBUTE
:
3740 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
3744 FIXME( "unhandled writer state %u\n", writer
->state
);
3750 FIXME( "field mapping %u not supported\n", desc
->mapping
);
3754 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
3759 case WS_ATTRIBUTE_TYPE_MAPPING
:
3760 writer
->state
= WRITER_STATE_STARTELEMENT
;
3763 case WS_ELEMENT_TYPE_MAPPING
:
3764 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
3773 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
3774 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
3775 const void *value
, ULONG size
)
3781 if (!desc
) return E_INVALIDARG
;
3782 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
3784 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
3786 for (i
= 0; i
< desc
->fieldCount
; i
++)
3788 offset
= desc
->fields
[i
]->offset
;
3789 if ((hr
= write_type_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
) return hr
;
3795 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3796 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3802 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
3805 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
3808 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
3811 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
3814 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
3817 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
3819 case WS_UINT16_TYPE
:
3820 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
3822 case WS_UINT32_TYPE
:
3823 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
3825 case WS_UINT64_TYPE
:
3826 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
3828 case WS_DOUBLE_TYPE
:
3829 return write_type_double( writer
, mapping
, desc
, option
, value
, size
);
3831 case WS_DATETIME_TYPE
:
3832 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
3835 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
3837 case WS_UNIQUE_ID_TYPE
:
3838 return write_type_unique_id( writer
, mapping
, desc
, option
, value
, size
);
3840 case WS_STRING_TYPE
:
3841 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
3844 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
3847 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
3849 case WS_XML_STRING_TYPE
:
3850 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
3852 case WS_XML_QNAME_TYPE
:
3853 return write_type_qname( writer
, mapping
, desc
, option
, value
, size
);
3855 case WS_STRUCT_TYPE
:
3856 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
3859 FIXME( "type %u not supported\n", type
);
3864 /**************************************************************************
3865 * WsWriteAttribute [webservices.@]
3867 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
3868 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3871 struct writer
*writer
= (struct writer
*)handle
;
3874 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3875 if (error
) FIXME( "ignoring error parameter\n" );
3877 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
3878 return E_INVALIDARG
;
3880 EnterCriticalSection( &writer
->cs
);
3882 if (writer
->magic
!= WRITER_MAGIC
)
3884 LeaveCriticalSection( &writer
->cs
);
3885 return E_INVALIDARG
;
3888 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
3890 LeaveCriticalSection( &writer
->cs
);
3891 return WS_E_INVALID_OPERATION
;
3894 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) != S_OK
)
3896 LeaveCriticalSection( &writer
->cs
);
3899 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
3901 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
3903 LeaveCriticalSection( &writer
->cs
);
3907 /**************************************************************************
3908 * WsWriteElement [webservices.@]
3910 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3911 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
3914 struct writer
*writer
= (struct writer
*)handle
;
3917 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
3918 if (error
) FIXME( "ignoring error parameter\n" );
3920 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
3921 return E_INVALIDARG
;
3923 EnterCriticalSection( &writer
->cs
);
3925 if (writer
->magic
!= WRITER_MAGIC
)
3927 LeaveCriticalSection( &writer
->cs
);
3928 return E_INVALIDARG
;
3931 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
3933 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
3934 option
, value
, size
)) != S_OK
) goto done
;
3936 hr
= write_endelement_node( writer
);
3939 LeaveCriticalSection( &writer
->cs
);
3943 /**************************************************************************
3944 * WsWriteType [webservices.@]
3946 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
3947 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
3948 ULONG size
, WS_ERROR
*error
)
3950 struct writer
*writer
= (struct writer
*)handle
;
3953 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
3955 if (error
) FIXME( "ignoring error parameter\n" );
3957 if (!writer
|| !value
) return E_INVALIDARG
;
3959 EnterCriticalSection( &writer
->cs
);
3961 if (writer
->magic
!= WRITER_MAGIC
)
3963 LeaveCriticalSection( &writer
->cs
);
3964 return E_INVALIDARG
;
3969 case WS_ATTRIBUTE_TYPE_MAPPING
:
3970 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
3971 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3974 case WS_ELEMENT_TYPE_MAPPING
:
3975 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
3976 case WS_ANY_ELEMENT_TYPE_MAPPING
:
3977 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
3981 FIXME( "mapping %u not implemented\n", mapping
);
3985 LeaveCriticalSection( &writer
->cs
);
3989 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
3993 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
3994 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
3995 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
3996 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
3997 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
3998 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
3999 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
4000 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
4001 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
4002 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
4003 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
4004 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
4005 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
4006 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
4007 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
4009 FIXME( "unhandled type %u\n", type
);
4014 /**************************************************************************
4015 * WsWriteValue [webservices.@]
4017 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
4018 ULONG size
, WS_ERROR
*error
)
4020 struct writer
*writer
= (struct writer
*)handle
;
4021 WS_TYPE_MAPPING mapping
;
4025 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
4026 if (error
) FIXME( "ignoring error parameter\n" );
4028 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
4030 EnterCriticalSection( &writer
->cs
);
4032 if (writer
->magic
!= WRITER_MAGIC
)
4034 LeaveCriticalSection( &writer
->cs
);
4035 return E_INVALIDARG
;
4038 switch (writer
->state
)
4040 case WRITER_STATE_STARTATTRIBUTE
:
4041 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
4044 case WRITER_STATE_STARTELEMENT
:
4045 mapping
= WS_ELEMENT_TYPE_MAPPING
;
4049 hr
= WS_E_INVALID_FORMAT
;
4052 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
4054 LeaveCriticalSection( &writer
->cs
);
4058 /**************************************************************************
4059 * WsWriteArray [webservices.@]
4061 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4062 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
4063 ULONG count
, WS_ERROR
*error
)
4065 struct writer
*writer
= (struct writer
*)handle
;
4070 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
4071 value_type
, array
, size
, offset
, count
, error
);
4072 if (error
) FIXME( "ignoring error parameter\n" );
4074 if (!writer
) return E_INVALIDARG
;
4076 EnterCriticalSection( &writer
->cs
);
4078 if (writer
->magic
!= WRITER_MAGIC
)
4080 LeaveCriticalSection( &writer
->cs
);
4081 return E_INVALIDARG
;
4084 if (!writer
->output_type
)
4086 LeaveCriticalSection( &writer
->cs
);
4087 return WS_E_INVALID_OPERATION
;
4090 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
4092 LeaveCriticalSection( &writer
->cs
);
4093 return E_INVALIDARG
;
4096 type_size
= get_type_size( type
, NULL
);
4097 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
4099 LeaveCriticalSection( &writer
->cs
);
4100 return E_INVALIDARG
;
4103 for (i
= offset
; i
< count
; i
++)
4105 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
4106 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
4107 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
4108 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
4109 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
4113 LeaveCriticalSection( &writer
->cs
);
4117 /**************************************************************************
4118 * WsWriteXmlBuffer [webservices.@]
4120 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
4122 struct writer
*writer
= (struct writer
*)handle
;
4123 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4126 TRACE( "%p %p %p\n", handle
, buffer
, error
);
4127 if (error
) FIXME( "ignoring error parameter\n" );
4129 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
4131 EnterCriticalSection( &writer
->cs
);
4133 if (writer
->magic
!= WRITER_MAGIC
)
4135 LeaveCriticalSection( &writer
->cs
);
4136 return E_INVALIDARG
;
4139 if (xmlbuf
->encoding
!= writer
->output_enc
|| xmlbuf
->charset
!= writer
->output_charset
)
4141 FIXME( "no support for different encoding and/or charset\n" );
4146 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
4147 if ((hr
= write_grow_buffer( writer
, xmlbuf
->bytes
.length
)) != S_OK
) goto done
;
4148 write_bytes( writer
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4151 LeaveCriticalSection( &writer
->cs
);
4155 /**************************************************************************
4156 * WsWriteXmlBufferToBytes [webservices.@]
4158 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
4159 const WS_XML_WRITER_ENCODING
*encoding
,
4160 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
4161 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
4163 struct writer
*writer
= (struct writer
*)handle
;
4164 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
4169 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
4170 bytes
, size
, error
);
4171 if (error
) FIXME( "ignoring error parameter\n" );
4173 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
4175 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
4177 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
4181 EnterCriticalSection( &writer
->cs
);
4183 if (writer
->magic
!= WRITER_MAGIC
)
4185 LeaveCriticalSection( &writer
->cs
);
4186 return E_INVALIDARG
;
4189 for (i
= 0; i
< count
; i
++)
4191 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
4192 properties
[i
].valueSize
);
4193 if (hr
!= S_OK
) goto done
;
4196 if (!(buf
= ws_alloc( heap
, xmlbuf
->bytes
.length
))) hr
= WS_E_QUOTA_EXCEEDED
;
4199 memcpy( buf
, xmlbuf
->bytes
.bytes
, xmlbuf
->bytes
.length
);
4201 *size
= xmlbuf
->bytes
.length
;
4205 LeaveCriticalSection( &writer
->cs
);
4209 /**************************************************************************
4210 * WsWriteXmlnsAttribute [webservices.@]
4212 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4213 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
4215 struct writer
*writer
= (struct writer
*)handle
;
4218 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
4220 if (error
) FIXME( "ignoring error parameter\n" );
4222 if (!writer
|| !ns
) return E_INVALIDARG
;
4224 EnterCriticalSection( &writer
->cs
);
4226 if (writer
->magic
!= WRITER_MAGIC
)
4228 LeaveCriticalSection( &writer
->cs
);
4229 return E_INVALIDARG
;
4232 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4234 LeaveCriticalSection( &writer
->cs
);
4235 return WS_E_INVALID_OPERATION
;
4238 if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
4239 hr
= add_namespace_attribute( writer
, prefix
, ns
, single
);
4241 LeaveCriticalSection( &writer
->cs
);
4245 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
4246 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
4248 WS_XML_QNAME_TEXT qname
= {{WS_XML_TEXT_TYPE_QNAME
}};
4251 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4252 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) return hr
;
4254 qname
.prefix
= (WS_XML_STRING
*)prefix
;
4255 qname
.localName
= (WS_XML_STRING
*)localname
;
4256 qname
.ns
= (WS_XML_STRING
*)ns
;
4258 if ((hr
= write_add_text_node( writer
, &qname
.text
)) != S_OK
) return hr
;
4259 return write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 );
4262 /**************************************************************************
4263 * WsWriteQualifiedName [webservices.@]
4265 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
4266 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
4269 struct writer
*writer
= (struct writer
*)handle
;
4272 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
4273 debugstr_xmlstr(ns
), error
);
4274 if (error
) FIXME( "ignoring error parameter\n" );
4276 if (!writer
) return E_INVALIDARG
;
4278 EnterCriticalSection( &writer
->cs
);
4280 if (writer
->magic
!= WRITER_MAGIC
)
4282 LeaveCriticalSection( &writer
->cs
);
4283 return E_INVALIDARG
;
4286 if (!writer
->output_type
)
4288 LeaveCriticalSection( &writer
->cs
);
4289 return WS_E_INVALID_OPERATION
;
4292 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
4294 LeaveCriticalSection( &writer
->cs
);
4295 return WS_E_INVALID_FORMAT
;
4298 if (!localname
|| (!prefix
&& !ns
))
4300 LeaveCriticalSection( &writer
->cs
);
4301 return E_INVALIDARG
;
4304 hr
= write_qualified_name( writer
, prefix
, localname
, ns
);
4306 LeaveCriticalSection( &writer
->cs
);
4310 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
4312 BOOL success
= FALSE
;
4313 struct node
*node
= writer
->current
;
4317 case WS_MOVE_TO_ROOT_ELEMENT
:
4318 success
= move_to_root_element( writer
->root
, &node
);
4321 case WS_MOVE_TO_NEXT_ELEMENT
:
4322 success
= move_to_next_element( &node
);
4325 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
4326 success
= move_to_prev_element( &node
);
4329 case WS_MOVE_TO_CHILD_ELEMENT
:
4330 success
= move_to_child_element( &node
);
4333 case WS_MOVE_TO_END_ELEMENT
:
4334 success
= move_to_end_element( &node
);
4337 case WS_MOVE_TO_PARENT_ELEMENT
:
4338 success
= move_to_parent_element( &node
);
4341 case WS_MOVE_TO_FIRST_NODE
:
4342 success
= move_to_first_node( &node
);
4345 case WS_MOVE_TO_NEXT_NODE
:
4346 success
= move_to_next_node( &node
);
4349 case WS_MOVE_TO_PREVIOUS_NODE
:
4350 success
= move_to_prev_node( &node
);
4353 case WS_MOVE_TO_CHILD_NODE
:
4354 success
= move_to_child_node( &node
);
4357 case WS_MOVE_TO_BOF
:
4358 success
= move_to_bof( writer
->root
, &node
);
4361 case WS_MOVE_TO_EOF
:
4362 success
= move_to_eof( writer
->root
, &node
);
4366 FIXME( "unhandled move %u\n", move
);
4370 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
4371 writer
->current
= node
;
4378 return success
? S_OK
: WS_E_INVALID_FORMAT
;
4381 /**************************************************************************
4382 * WsMoveWriter [webservices.@]
4384 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
4386 struct writer
*writer
= (struct writer
*)handle
;
4389 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
4390 if (error
) FIXME( "ignoring error parameter\n" );
4392 if (!writer
) return E_INVALIDARG
;
4394 EnterCriticalSection( &writer
->cs
);
4396 if (writer
->magic
!= WRITER_MAGIC
)
4398 LeaveCriticalSection( &writer
->cs
);
4399 return E_INVALIDARG
;
4402 if (!writer
->output_type
)
4404 LeaveCriticalSection( &writer
->cs
);
4405 return WS_E_INVALID_OPERATION
;
4408 hr
= write_move_to( writer
, move
, found
);
4410 LeaveCriticalSection( &writer
->cs
);
4414 /**************************************************************************
4415 * WsGetWriterPosition [webservices.@]
4417 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4419 struct writer
*writer
= (struct writer
*)handle
;
4421 TRACE( "%p %p %p\n", handle
, pos
, error
);
4422 if (error
) FIXME( "ignoring error parameter\n" );
4424 if (!writer
|| !pos
) return E_INVALIDARG
;
4426 EnterCriticalSection( &writer
->cs
);
4428 if (writer
->magic
!= WRITER_MAGIC
)
4430 LeaveCriticalSection( &writer
->cs
);
4431 return E_INVALIDARG
;
4434 if (!writer
->output_type
)
4436 LeaveCriticalSection( &writer
->cs
);
4437 return WS_E_INVALID_OPERATION
;
4440 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
4441 pos
->node
= writer
->current
;
4443 LeaveCriticalSection( &writer
->cs
);
4447 /**************************************************************************
4448 * WsSetWriterPosition [webservices.@]
4450 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
4452 struct writer
*writer
= (struct writer
*)handle
;
4454 TRACE( "%p %p %p\n", handle
, pos
, error
);
4455 if (error
) FIXME( "ignoring error parameter\n" );
4457 if (!writer
|| !pos
) return E_INVALIDARG
;
4459 EnterCriticalSection( &writer
->cs
);
4461 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
4463 LeaveCriticalSection( &writer
->cs
);
4464 return E_INVALIDARG
;
4467 if (!writer
->output_type
)
4469 LeaveCriticalSection( &writer
->cs
);
4470 return WS_E_INVALID_OPERATION
;
4473 writer
->current
= pos
->node
;
4475 LeaveCriticalSection( &writer
->cs
);
4479 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4481 struct node
*node
, *parent
;
4482 WS_XML_COMMENT_NODE
*comment
;
4484 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
4485 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
4486 comment
= (WS_XML_COMMENT_NODE
*)node
;
4488 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
4491 return E_OUTOFMEMORY
;
4493 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
4494 comment
->value
.length
= value
->length
;
4496 write_insert_node( writer
, parent
, node
);
4500 static HRESULT
write_comment_text( struct writer
*writer
)
4502 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4505 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
4506 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
4507 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
4508 write_bytes( writer
, (const BYTE
*)"-->", 3 );
4512 static HRESULT
write_comment_bin( struct writer
*writer
)
4514 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
4517 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
4518 write_char( writer
, RECORD_COMMENT
);
4519 return write_string( writer
, comment
->value
.bytes
, comment
->value
.length
);
4522 static HRESULT
write_comment( struct writer
*writer
)
4524 switch (writer
->output_enc
)
4526 case WS_XML_WRITER_ENCODING_TYPE_TEXT
: return write_comment_text( writer
);
4527 case WS_XML_WRITER_ENCODING_TYPE_BINARY
: return write_comment_bin( writer
);
4529 ERR( "unhandled encoding %u\n", writer
->output_enc
);
4530 return WS_E_NOT_SUPPORTED
;
4534 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
4537 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
4538 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
4539 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4540 writer
->state
= WRITER_STATE_COMMENT
;
4544 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
4549 for (i
= 0; i
< count
; i
++)
4551 const WS_XML_STRING
*prefix
= attrs
[i
]->prefix
;
4552 const WS_XML_STRING
*localname
= attrs
[i
]->localName
;
4553 const WS_XML_STRING
*ns
= attrs
[i
]->ns
;
4554 BOOL single
= attrs
[i
]->singleQuote
;
4556 if (attrs
[i
]->isXmlNs
)
4558 if ((hr
= add_namespace_attribute( writer
, prefix
, ns
, single
)) != S_OK
) return hr
;
4562 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) != S_OK
) return hr
;
4563 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
4569 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
4573 switch (node
->nodeType
)
4575 case WS_XML_NODE_TYPE_ELEMENT
:
4577 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
4578 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
4579 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
4581 case WS_XML_NODE_TYPE_TEXT
:
4583 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
4584 return write_text_node( writer
, text
->text
);
4586 case WS_XML_NODE_TYPE_END_ELEMENT
:
4587 return write_endelement_node( writer
);
4589 case WS_XML_NODE_TYPE_COMMENT
:
4591 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
4592 return write_comment_node( writer
, &comment
->value
);
4594 case WS_XML_NODE_TYPE_CDATA
:
4595 return write_cdata_node( writer
);
4597 case WS_XML_NODE_TYPE_END_CDATA
:
4598 return write_endcdata_node( writer
);
4600 case WS_XML_NODE_TYPE_EOF
:
4601 case WS_XML_NODE_TYPE_BOF
:
4605 WARN( "unknown node type %u\n", node
->nodeType
);
4606 return E_INVALIDARG
;
4610 /**************************************************************************
4611 * WsWriteNode [webservices.@]
4613 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
4615 struct writer
*writer
= (struct writer
*)handle
;
4618 TRACE( "%p %p %p\n", handle
, node
, error
);
4619 if (error
) FIXME( "ignoring error parameter\n" );
4621 if (!writer
|| !node
) return E_INVALIDARG
;
4623 EnterCriticalSection( &writer
->cs
);
4625 if (writer
->magic
!= WRITER_MAGIC
)
4627 LeaveCriticalSection( &writer
->cs
);
4628 return E_INVALIDARG
;
4631 if (!writer
->output_type
)
4633 LeaveCriticalSection( &writer
->cs
);
4634 return WS_E_INVALID_OPERATION
;
4637 hr
= write_node( writer
, node
);
4639 LeaveCriticalSection( &writer
->cs
);
4643 static HRESULT
write_tree_node( struct writer
*writer
)
4647 switch (node_type( writer
->current
))
4649 case WS_XML_NODE_TYPE_ELEMENT
:
4650 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4652 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
4653 writer
->state
= WRITER_STATE_STARTELEMENT
;
4656 case WS_XML_NODE_TYPE_TEXT
:
4657 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4659 if ((hr
= write_text( writer
, ((const WS_XML_TEXT_NODE
*)writer
->current
)->text
, 0 )) != S_OK
) return hr
;
4660 writer
->state
= WRITER_STATE_TEXT
;
4663 case WS_XML_NODE_TYPE_END_ELEMENT
:
4664 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
4665 writer
->state
= WRITER_STATE_ENDELEMENT
;
4668 case WS_XML_NODE_TYPE_COMMENT
:
4669 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4671 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
4672 writer
->state
= WRITER_STATE_COMMENT
;
4675 case WS_XML_NODE_TYPE_CDATA
:
4676 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
4678 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
4679 writer
->state
= WRITER_STATE_STARTCDATA
;
4682 case WS_XML_NODE_TYPE_END_CDATA
:
4683 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
4684 writer
->state
= WRITER_STATE_ENDCDATA
;
4687 case WS_XML_NODE_TYPE_EOF
:
4688 case WS_XML_NODE_TYPE_BOF
:
4692 ERR( "unknown node type %u\n", node_type(writer
->current
) );
4693 return E_INVALIDARG
;
4697 static HRESULT
write_tree( struct writer
*writer
)
4701 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4704 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
4705 if (move_to_child_node( &writer
->current
))
4707 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4710 if (move_to_next_node( &writer
->current
))
4712 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4715 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
4717 ERR( "invalid tree\n" );
4718 return WS_E_INVALID_FORMAT
;
4720 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
4725 static void write_rewind( struct writer
*writer
)
4727 writer
->write_pos
= 0;
4728 writer
->current
= writer
->root
;
4729 writer
->state
= WRITER_STATE_INITIAL
;
4732 /**************************************************************************
4733 * WsCopyNode [webservices.@]
4735 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
4737 struct writer
*writer
= (struct writer
*)handle
;
4738 struct node
*parent
, *current
, *node
= NULL
;
4741 TRACE( "%p %p %p\n", handle
, reader
, error
);
4742 if (error
) FIXME( "ignoring error parameter\n" );
4744 if (!writer
) return E_INVALIDARG
;
4746 EnterCriticalSection( &writer
->cs
);
4748 if (writer
->magic
!= WRITER_MAGIC
)
4750 LeaveCriticalSection( &writer
->cs
);
4751 return E_INVALIDARG
;
4754 if (!(parent
= find_parent( writer
)))
4756 LeaveCriticalSection( &writer
->cs
);
4757 return WS_E_INVALID_FORMAT
;
4760 if ((hr
= copy_node( reader
, writer
->output_enc
, &node
)) != S_OK
) goto done
;
4761 current
= writer
->current
;
4762 write_insert_node( writer
, parent
, node
);
4764 write_rewind( writer
);
4765 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
4766 writer
->current
= current
;
4768 WsMoveReader( reader
, WS_MOVE_TO_NEXT_NODE
, NULL
, NULL
);
4771 LeaveCriticalSection( &writer
->cs
);
4775 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
4777 return write_type_field( writer
, desc
, value
, 0 );
4780 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
4783 for (i
= 0; i
< count
; i
++)
4785 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
4787 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
4793 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
4796 return write_type_array( writer
, desc
, value
, len
);
4799 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
4800 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
4802 struct writer
*writer
= (struct writer
*)handle
;
4803 const WS_STRUCT_DESCRIPTION
*desc_struct
;
4804 const WS_FIELD_DESCRIPTION
*desc_field
;
4808 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
4810 EnterCriticalSection( &writer
->cs
);
4812 if (writer
->magic
!= WRITER_MAGIC
)
4814 LeaveCriticalSection( &writer
->cs
);
4815 return E_INVALIDARG
;
4818 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
4820 for (i
= 0; i
< count
; i
++)
4822 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
4823 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
4825 FIXME( "messages type not supported\n" );
4829 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
4830 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
4832 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
4834 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
4836 const void *ptr
= *(const void **)args
[i
];
4837 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
4838 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
4842 hr
= write_endelement_node( writer
);
4845 LeaveCriticalSection( &writer
->cs
);
4849 HRESULT
writer_enable_lookup( WS_XML_WRITER
*handle
)
4851 struct writer
*writer
= (struct writer
*)handle
;
4853 EnterCriticalSection( &writer
->cs
);
4855 if (writer
->magic
!= WRITER_MAGIC
)
4857 LeaveCriticalSection( &writer
->cs
);
4858 return E_INVALIDARG
;
4861 writer
->dict_do_lookup
= TRUE
;
4863 LeaveCriticalSection( &writer
->cs
);