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
27 #include "webservices.h"
29 #include "wine/debug.h"
30 #include "wine/list.h"
31 #include "wine/unicode.h"
32 #include "webservices_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
36 static const struct prop_desc writer_props
[] =
38 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
39 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
40 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
41 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
42 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INDENT */
43 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
44 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_WRITER_PROPERTY_CHARSET */
45 { sizeof(WS_BUFFERS
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFERS */
46 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
47 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BYTES */
48 { sizeof(BOOL
), TRUE
}, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
49 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
50 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
51 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
52 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
53 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
54 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
55 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
56 { sizeof(BOOL
), FALSE
} /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
62 WRITER_STATE_STARTELEMENT
,
63 WRITER_STATE_STARTATTRIBUTE
,
64 WRITER_STATE_STARTCDATA
,
65 WRITER_STATE_ENDSTARTELEMENT
,
68 WRITER_STATE_ENDELEMENT
,
77 unsigned char *write_bufptr
;
78 enum writer_state state
;
81 WS_XML_STRING
*current_ns
;
82 WS_XML_WRITER_OUTPUT_TYPE output_type
;
83 struct xmlbuf
*output_buf
;
86 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
89 #define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T')
91 static struct writer
*alloc_writer(void)
93 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
95 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
97 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
99 ret
->magic
= WRITER_MAGIC
;
100 InitializeCriticalSection( &ret
->cs
);
101 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": writer.cs");
103 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
104 ret
->prop_count
= count
;
108 static void free_writer( struct writer
*writer
)
110 destroy_nodes( writer
->root
);
111 heap_free( writer
->current_ns
);
112 WsFreeHeap( writer
->output_heap
);
114 writer
->cs
.DebugInfo
->Spare
[0] = 0;
115 DeleteCriticalSection( &writer
->cs
);
119 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
121 if (!writer
->root
) writer
->root
= eof
;
124 eof
->parent
= writer
->root
;
125 list_add_tail( &writer
->root
->children
, &eof
->entry
);
127 writer
->current
= eof
;
130 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
132 writer
->root
->parent
= bof
;
133 list_add_tail( &bof
->children
, &writer
->root
->entry
);
134 writer
->current
= writer
->root
= bof
;
137 static void write_insert_node( struct writer
*writer
, struct node
*parent
, struct node
*node
)
139 node
->parent
= parent
;
140 list_add_before( list_tail( &parent
->children
), &node
->entry
);
141 writer
->current
= node
;
144 static struct node
*find_parent( struct writer
*writer
)
146 if (is_valid_parent( writer
->current
)) return writer
->current
;
147 if (is_valid_parent( writer
->current
->parent
)) return writer
->current
->parent
;
151 static HRESULT
init_writer( struct writer
*writer
)
155 writer
->write_pos
= 0;
156 writer
->write_bufptr
= NULL
;
157 destroy_nodes( writer
->root
);
158 writer
->root
= writer
->current
= NULL
;
159 heap_free( writer
->current_ns
);
160 writer
->current_ns
= NULL
;
162 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
163 write_insert_eof( writer
, node
);
164 writer
->state
= WRITER_STATE_INITIAL
;
168 /**************************************************************************
169 * WsCreateWriter [webservices.@]
171 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
172 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
174 struct writer
*writer
;
175 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
176 WS_CHARSET charset
= WS_CHARSET_UTF8
;
179 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
180 if (error
) FIXME( "ignoring error parameter\n" );
182 if (!handle
) return E_INVALIDARG
;
183 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
185 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
186 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
187 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
188 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
189 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
190 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
191 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
193 for (i
= 0; i
< count
; i
++)
195 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
196 properties
[i
].valueSize
);
199 free_writer( writer
);
204 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
205 &max_size
, sizeof(max_size
) );
208 free_writer( writer
);
212 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
215 free_writer( writer
);
219 hr
= init_writer( writer
);
222 free_writer( writer
);
226 *handle
= (WS_XML_WRITER
*)writer
;
230 /**************************************************************************
231 * WsFreeWriter [webservices.@]
233 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
235 struct writer
*writer
= (struct writer
*)handle
;
237 TRACE( "%p\n", handle
);
241 EnterCriticalSection( &writer
->cs
);
243 if (writer
->magic
!= WRITER_MAGIC
)
245 LeaveCriticalSection( &writer
->cs
);
251 LeaveCriticalSection( &writer
->cs
);
252 free_writer( writer
);
255 /**************************************************************************
256 * WsGetWriterProperty [webservices.@]
258 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
259 void *buf
, ULONG size
, WS_ERROR
*error
)
261 struct writer
*writer
= (struct writer
*)handle
;
264 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
265 if (error
) FIXME( "ignoring error parameter\n" );
267 if (!writer
) return E_INVALIDARG
;
269 EnterCriticalSection( &writer
->cs
);
271 if (writer
->magic
!= WRITER_MAGIC
)
273 LeaveCriticalSection( &writer
->cs
);
277 if (!writer
->output_type
)
279 LeaveCriticalSection( &writer
->cs
);
280 return WS_E_INVALID_OPERATION
;
285 case WS_XML_WRITER_PROPERTY_BYTES
:
287 WS_BYTES
*bytes
= buf
;
288 if (size
!= sizeof(*bytes
)) hr
= E_INVALIDARG
;
291 bytes
->bytes
= writer
->output_buf
->ptr
;
292 bytes
->length
= writer
->output_buf
->size
;
297 hr
= prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
300 LeaveCriticalSection( &writer
->cs
);
304 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
306 /* free current buffer if it's ours */
307 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
309 free_xmlbuf( writer
->output_buf
);
311 writer
->output_buf
= xmlbuf
;
312 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
313 writer
->write_bufptr
= xmlbuf
->ptr
;
314 writer
->write_pos
= 0;
317 /**************************************************************************
318 * WsSetOutput [webservices.@]
320 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
321 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
322 ULONG count
, WS_ERROR
*error
)
324 struct writer
*writer
= (struct writer
*)handle
;
329 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
330 if (error
) FIXME( "ignoring error parameter\n" );
332 if (!writer
) return E_INVALIDARG
;
334 EnterCriticalSection( &writer
->cs
);
336 if (writer
->magic
!= WRITER_MAGIC
)
338 LeaveCriticalSection( &writer
->cs
);
342 for (i
= 0; i
< count
; i
++)
344 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
345 properties
[i
].valueSize
);
346 if (hr
!= S_OK
) goto done
;
349 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
351 switch (encoding
->encodingType
)
353 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
355 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
356 if (text
->charSet
!= WS_CHARSET_UTF8
)
358 FIXME( "charset %u not supported\n", text
->charSet
);
365 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
370 switch (output
->outputType
)
372 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
374 struct xmlbuf
*xmlbuf
;
376 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
))) hr
= WS_E_QUOTA_EXCEEDED
;
377 else set_output_buffer( writer
, xmlbuf
);
381 FIXME( "output type %u not supported\n", output
->outputType
);
386 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) hr
= E_OUTOFMEMORY
;
387 else write_insert_bof( writer
, node
);
390 LeaveCriticalSection( &writer
->cs
);
394 /**************************************************************************
395 * WsSetOutputToBuffer [webservices.@]
397 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
398 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
401 struct writer
*writer
= (struct writer
*)handle
;
402 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
407 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
408 if (error
) FIXME( "ignoring error parameter\n" );
410 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
412 EnterCriticalSection( &writer
->cs
);
414 if (writer
->magic
!= WRITER_MAGIC
)
416 LeaveCriticalSection( &writer
->cs
);
420 for (i
= 0; i
< count
; i
++)
422 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
423 properties
[i
].valueSize
);
424 if (hr
!= S_OK
) goto done
;
427 if ((hr
= init_writer( writer
)) != S_OK
) goto done
;
428 set_output_buffer( writer
, xmlbuf
);
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 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
440 struct xmlbuf
*buf
= writer
->output_buf
;
444 if (buf
->size_allocated
>= writer
->write_pos
+ size
)
446 buf
->size
= writer
->write_pos
+ size
;
449 new_size
= max( buf
->size_allocated
* 2, writer
->write_pos
+ size
);
450 if (!(tmp
= ws_realloc( buf
->heap
, buf
->ptr
, buf
->size_allocated
, new_size
))) return WS_E_QUOTA_EXCEEDED
;
451 writer
->write_bufptr
= buf
->ptr
= tmp
;
452 buf
->size_allocated
= new_size
;
453 buf
->size
= writer
->write_pos
+ size
;
457 static inline void write_char( struct writer
*writer
, unsigned char ch
)
459 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
462 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
464 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
465 writer
->write_pos
+= len
;
474 static const struct escape escape_lt
= { '<', "<", 4 };
475 static const struct escape escape_gt
= { '>', ">", 4 };
476 static const struct escape escape_amp
= { '&', "&", 5 };
477 static const struct escape escape_apos
= { '\'', "'", 6 };
478 static const struct escape escape_quot
= { '"', """, 6 };
480 static HRESULT
write_bytes_escape( struct writer
*writer
, const BYTE
*bytes
, ULONG len
,
481 const struct escape
**escapes
, ULONG nb_escapes
)
487 for (i
= 0; i
< len
; i
++)
491 for (j
= 0; j
< nb_escapes
; j
++)
493 if (bytes
[i
] == escapes
[j
]->ch
)
495 ptr
= (const BYTE
*)escapes
[j
]->entity
;
496 size
= escapes
[j
]->len
;
500 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
501 write_bytes( writer
, ptr
, size
);
507 static HRESULT
write_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
509 WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)attr
->value
;
510 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
511 const WS_XML_STRING
*prefix
;
515 if (attr
->prefix
) prefix
= attr
->prefix
;
516 else prefix
= writer
->current
->hdr
.prefix
;
518 /* ' prefix:attr="value"' */
520 size
= attr
->localName
->length
+ 4 /* ' =""' */;
521 if (prefix
) size
+= prefix
->length
+ 1 /* ':' */;
522 if (text
) size
+= text
->value
.length
;
523 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
525 write_char( writer
, ' ' );
528 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
529 write_char( writer
, ':' );
531 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
532 write_char( writer
, '=' );
533 write_char( writer
, quote
);
536 const struct escape
*escapes
[3];
537 escapes
[0] = attr
->singleQuote
? &escape_apos
: &escape_quot
;
538 escapes
[1] = &escape_lt
;
539 escapes
[2] = &escape_amp
;
540 hr
= write_bytes_escape( writer
, text
->value
.bytes
, text
->value
.length
, escapes
, 3 );
542 write_char( writer
, quote
);
547 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
549 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
552 /**************************************************************************
553 * WsGetPrefixFromNamespace [webservices.@]
555 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
556 BOOL required
, const WS_XML_STRING
**prefix
,
559 struct writer
*writer
= (struct writer
*)handle
;
560 WS_XML_ELEMENT_NODE
*elem
;
564 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
565 if (error
) FIXME( "ignoring error parameter\n" );
567 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
569 EnterCriticalSection( &writer
->cs
);
571 if (writer
->magic
!= WRITER_MAGIC
)
573 LeaveCriticalSection( &writer
->cs
);
577 elem
= &writer
->current
->hdr
;
578 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
580 *prefix
= elem
->prefix
;
586 if (required
) hr
= WS_E_INVALID_FORMAT
;
594 LeaveCriticalSection( &writer
->cs
);
598 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
601 if (!(str
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
602 heap_free( writer
->current_ns
);
603 writer
->current_ns
= str
;
607 static HRESULT
write_namespace_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
609 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
613 /* ' xmlns:prefix="namespace"' */
615 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
616 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
617 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
619 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
622 write_char( writer
, ':' );
623 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
625 write_char( writer
, '=' );
626 write_char( writer
, quote
);
627 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
628 write_char( writer
, quote
);
633 static HRESULT
write_add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
634 const WS_XML_STRING
*ns
, BOOL single
)
636 WS_XML_ATTRIBUTE
*attr
;
637 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
640 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
642 attr
->singleQuote
= !!single
;
644 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
646 free_attribute( attr
);
647 return E_OUTOFMEMORY
;
649 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
651 free_attribute( attr
);
652 return E_OUTOFMEMORY
;
654 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
656 free_attribute( attr
);
662 static inline BOOL
str_equal( const WS_XML_STRING
*str1
, const WS_XML_STRING
*str2
)
664 if (!str1
&& !str2
) return TRUE
;
665 return WsXmlStringEquals( str1
, str2
, NULL
) == S_OK
;
668 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
669 const WS_XML_STRING
*ns
)
672 const struct node
*node
;
674 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
676 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
679 for (i
= 0; i
< elem
->attributeCount
; i
++)
681 if (!elem
->attributes
[i
]->isXmlNs
) continue;
682 if (str_equal( elem
->attributes
[i
]->prefix
, prefix
) &&
683 str_equal( elem
->attributes
[i
]->ns
, ns
)) return TRUE
;
689 static HRESULT
write_set_element_namespace( struct writer
*writer
)
691 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
694 if (!elem
->ns
->length
|| namespace_in_scope( elem
, elem
->prefix
, elem
->ns
)) return S_OK
;
696 if ((hr
= write_add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
)
699 return set_current_namespace( writer
, elem
->ns
);
702 /**************************************************************************
703 * WsWriteEndAttribute [webservices.@]
705 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
707 struct writer
*writer
= (struct writer
*)handle
;
709 TRACE( "%p %p\n", handle
, error
);
710 if (error
) FIXME( "ignoring error parameter\n" );
712 if (!writer
) return E_INVALIDARG
;
714 EnterCriticalSection( &writer
->cs
);
716 if (writer
->magic
!= WRITER_MAGIC
)
718 LeaveCriticalSection( &writer
->cs
);
722 writer
->state
= WRITER_STATE_STARTELEMENT
;
724 LeaveCriticalSection( &writer
->cs
);
728 static HRESULT
write_startelement( struct writer
*writer
)
730 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
734 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
736 size
= elem
->localName
->length
+ 1 /* '<' */;
737 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
738 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
740 write_char( writer
, '<' );
743 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
744 write_char( writer
, ':' );
746 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
747 for (i
= 0; i
< elem
->attributeCount
; i
++)
749 if (elem
->attributes
[i
]->isXmlNs
) continue;
750 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
752 for (i
= 0; i
< elem
->attributeCount
; i
++)
754 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
755 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
757 for (i
= 0; i
< elem
->attributeCount
; i
++)
759 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
760 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
765 static struct node
*write_find_startelement( struct writer
*writer
)
768 for (node
= writer
->current
; node
; node
= node
->parent
)
770 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
775 static inline BOOL
is_empty_element( const struct node
*node
)
777 const struct node
*head
= LIST_ENTRY( list_head( &node
->children
), struct node
, entry
);
778 return node_type( head
) == WS_XML_NODE_TYPE_END_ELEMENT
;
781 static HRESULT
write_endelement( struct writer
*writer
, const WS_XML_ELEMENT_NODE
*elem
)
788 if (elem
->isEmpty
&& writer
->state
!= WRITER_STATE_ENDSTARTELEMENT
)
790 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
791 write_char( writer
, '/' );
792 write_char( writer
, '>' );
796 /* '</prefix:localname>' */
798 size
= elem
->localName
->length
+ 3 /* '</>' */;
799 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
800 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
802 write_char( writer
, '<' );
803 write_char( writer
, '/' );
806 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
807 write_char( writer
, ':' );
809 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
810 write_char( writer
, '>' );
814 static HRESULT
write_close_element( struct writer
*writer
, struct node
*node
)
816 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
817 elem
->isEmpty
= is_empty_element( node
);
818 return write_endelement( writer
, elem
);
821 static HRESULT
write_endelement_node( struct writer
*writer
)
826 if (!(node
= write_find_startelement( writer
))) return WS_E_INVALID_FORMAT
;
827 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
829 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
830 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
832 if ((hr
= write_close_element( writer
, node
)) != S_OK
) return hr
;
833 writer
->current
= node
->parent
;
834 writer
->state
= WRITER_STATE_ENDELEMENT
;
838 /**************************************************************************
839 * WsWriteEndElement [webservices.@]
841 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
843 struct writer
*writer
= (struct writer
*)handle
;
846 TRACE( "%p %p\n", handle
, error
);
847 if (error
) FIXME( "ignoring error parameter\n" );
849 if (!writer
) return E_INVALIDARG
;
851 EnterCriticalSection( &writer
->cs
);
853 if (writer
->magic
!= WRITER_MAGIC
)
855 LeaveCriticalSection( &writer
->cs
);
859 hr
= write_endelement_node( writer
);
861 LeaveCriticalSection( &writer
->cs
);
865 static HRESULT
write_endstartelement( struct writer
*writer
)
868 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
869 write_char( writer
, '>' );
873 /**************************************************************************
874 * WsWriteEndStartElement [webservices.@]
876 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
878 struct writer
*writer
= (struct writer
*)handle
;
881 TRACE( "%p %p\n", handle
, error
);
882 if (error
) FIXME( "ignoring error parameter\n" );
884 if (!writer
) return E_INVALIDARG
;
886 EnterCriticalSection( &writer
->cs
);
888 if (writer
->magic
!= WRITER_MAGIC
)
890 LeaveCriticalSection( &writer
->cs
);
894 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
896 LeaveCriticalSection( &writer
->cs
);
897 return WS_E_INVALID_OPERATION
;
900 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) goto done
;
901 if ((hr
= write_startelement( writer
)) != S_OK
) goto done
;
902 if ((hr
= write_endstartelement( writer
)) != S_OK
) goto done
;
903 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
906 LeaveCriticalSection( &writer
->cs
);
910 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
911 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
914 WS_XML_ATTRIBUTE
*attr
;
915 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
918 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
920 if (!prefix
) prefix
= elem
->prefix
;
922 attr
->singleQuote
= !!single
;
923 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
925 free_attribute( attr
);
926 return E_OUTOFMEMORY
;
928 if (!(attr
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
930 free_attribute( attr
);
931 return E_OUTOFMEMORY
;
933 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
935 free_attribute( attr
);
936 return E_OUTOFMEMORY
;
938 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
940 free_attribute( attr
);
946 /**************************************************************************
947 * WsWriteStartAttribute [webservices.@]
949 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
950 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
951 BOOL single
, WS_ERROR
*error
)
953 struct writer
*writer
= (struct writer
*)handle
;
956 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
957 debugstr_xmlstr(ns
), single
, error
);
958 if (error
) FIXME( "ignoring error parameter\n" );
960 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
962 EnterCriticalSection( &writer
->cs
);
964 if (writer
->magic
!= WRITER_MAGIC
)
966 LeaveCriticalSection( &writer
->cs
);
970 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
972 LeaveCriticalSection( &writer
->cs
);
973 return WS_E_INVALID_OPERATION
;
976 if ((hr
= write_add_attribute( writer
, prefix
, localname
, ns
, single
)) == S_OK
)
977 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
979 LeaveCriticalSection( &writer
->cs
);
983 /* flush current start element if necessary */
984 static HRESULT
write_flush( struct writer
*writer
)
986 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
989 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
990 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
991 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
992 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
997 static HRESULT
write_add_cdata_node( struct writer
*writer
)
999 struct node
*node
, *parent
;
1000 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1001 if (!(node
= alloc_node( WS_XML_NODE_TYPE_CDATA
))) return E_OUTOFMEMORY
;
1002 write_insert_node( writer
, parent
, node
);
1006 static HRESULT
write_add_endcdata_node( struct writer
*writer
)
1009 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_CDATA
))) return E_OUTOFMEMORY
;
1010 node
->parent
= writer
->current
;
1011 list_add_tail( &node
->parent
->children
, &node
->entry
);
1015 static HRESULT
write_cdata( struct writer
*writer
)
1018 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
1019 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
1023 static HRESULT
write_cdata_node( struct writer
*writer
)
1026 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1027 if ((hr
= write_add_cdata_node( writer
)) != S_OK
) return hr
;
1028 if ((hr
= write_add_endcdata_node( writer
)) != S_OK
) return hr
;
1029 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
1030 writer
->state
= WRITER_STATE_STARTCDATA
;
1034 /**************************************************************************
1035 * WsWriteStartCData [webservices.@]
1037 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1039 struct writer
*writer
= (struct writer
*)handle
;
1042 TRACE( "%p %p\n", handle
, error
);
1043 if (error
) FIXME( "ignoring error parameter\n" );
1045 if (!writer
) return E_INVALIDARG
;
1047 EnterCriticalSection( &writer
->cs
);
1049 if (writer
->magic
!= WRITER_MAGIC
)
1051 LeaveCriticalSection( &writer
->cs
);
1052 return E_INVALIDARG
;
1055 hr
= write_cdata_node( writer
);
1057 LeaveCriticalSection( &writer
->cs
);
1061 static HRESULT
write_endcdata( struct writer
*writer
)
1064 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
1065 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
1069 static HRESULT
write_endcdata_node( struct writer
*writer
)
1072 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
1073 writer
->current
= writer
->current
->parent
;
1074 writer
->state
= WRITER_STATE_ENDCDATA
;
1078 /**************************************************************************
1079 * WsWriteEndCData [webservices.@]
1081 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
1083 struct writer
*writer
= (struct writer
*)handle
;
1086 TRACE( "%p %p\n", handle
, error
);
1087 if (error
) FIXME( "ignoring error parameter\n" );
1089 if (!writer
) return E_INVALIDARG
;
1091 EnterCriticalSection( &writer
->cs
);
1093 if (writer
->magic
!= WRITER_MAGIC
)
1095 LeaveCriticalSection( &writer
->cs
);
1096 return E_INVALIDARG
;
1099 if (writer
->state
!= WRITER_STATE_TEXT
)
1101 LeaveCriticalSection( &writer
->cs
);
1102 return WS_E_INVALID_OPERATION
;
1105 hr
= write_endcdata_node( writer
);
1107 LeaveCriticalSection( &writer
->cs
);
1111 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1112 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1114 struct node
*node
, *parent
;
1115 WS_XML_ELEMENT_NODE
*elem
;
1117 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
1119 if (!prefix
&& node_type( parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1121 elem
= &parent
->hdr
;
1122 if (WsXmlStringEquals( ns
, elem
->ns
, NULL
) == S_OK
) prefix
= elem
->prefix
;
1125 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
1128 if (prefix
&& !(elem
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
1131 return E_OUTOFMEMORY
;
1133 if (!(elem
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
1136 return E_OUTOFMEMORY
;
1138 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
1141 return E_OUTOFMEMORY
;
1143 write_insert_node( writer
, parent
, node
);
1147 static HRESULT
write_add_endelement_node( struct writer
*writer
, struct node
*parent
)
1150 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
1151 node
->parent
= parent
;
1152 list_add_tail( &parent
->children
, &node
->entry
);
1156 static HRESULT
write_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
1157 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
1160 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1161 if ((hr
= write_add_element_node( writer
, prefix
, localname
, ns
)) != S_OK
) return hr
;
1162 if ((hr
= write_add_endelement_node( writer
, writer
->current
)) != S_OK
) return hr
;
1163 writer
->state
= WRITER_STATE_STARTELEMENT
;
1167 /**************************************************************************
1168 * WsWriteStartElement [webservices.@]
1170 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1171 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
1174 struct writer
*writer
= (struct writer
*)handle
;
1177 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
1178 debugstr_xmlstr(ns
), error
);
1179 if (error
) FIXME( "ignoring error parameter\n" );
1181 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
1183 EnterCriticalSection( &writer
->cs
);
1185 if (writer
->magic
!= WRITER_MAGIC
)
1187 LeaveCriticalSection( &writer
->cs
);
1188 return E_INVALIDARG
;
1191 hr
= write_element_node( writer
, prefix
, localname
, ns
);
1193 LeaveCriticalSection( &writer
->cs
);
1197 static ULONG
format_bool( const BOOL
*ptr
, unsigned char *buf
)
1199 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1202 memcpy( buf
, bool_true
, sizeof(bool_true
) );
1203 return sizeof(bool_true
);
1205 memcpy( buf
, bool_false
, sizeof(bool_false
) );
1206 return sizeof(bool_false
);
1209 static ULONG
format_int8( const INT8
*ptr
, unsigned char *buf
)
1211 return wsprintfA( (char *)buf
, "%d", *ptr
);
1214 static ULONG
format_int16( const INT16
*ptr
, unsigned char *buf
)
1216 return wsprintfA( (char *)buf
, "%d", *ptr
);
1219 static ULONG
format_int32( const INT32
*ptr
, unsigned char *buf
)
1221 return wsprintfA( (char *)buf
, "%d", *ptr
);
1224 static ULONG
format_int64( const INT64
*ptr
, unsigned char *buf
)
1226 return wsprintfA( (char *)buf
, "%I64d", *ptr
);
1229 static ULONG
format_uint8( const UINT8
*ptr
, unsigned char *buf
)
1231 return wsprintfA( (char *)buf
, "%u", *ptr
);
1234 static ULONG
format_uint16( const UINT16
*ptr
, unsigned char *buf
)
1236 return wsprintfA( (char *)buf
, "%u", *ptr
);
1239 static ULONG
format_uint32( const UINT32
*ptr
, unsigned char *buf
)
1241 return wsprintfA( (char *)buf
, "%u", *ptr
);
1244 static ULONG
format_uint64( const UINT64
*ptr
, unsigned char *buf
)
1246 return wsprintfA( (char *)buf
, "%I64u", *ptr
);
1249 static ULONG
format_double( const double *ptr
, unsigned char *buf
)
1252 static const long double precision
= 0.0000000000000001;
1253 unsigned char *p
= buf
;
1254 long double val
= *ptr
;
1255 int neg
, mag
, mag2
, use_exp
;
1259 memcpy( buf
, "NaN", 3 );
1266 memcpy( buf
, "-INF", 4 );
1269 memcpy( buf
, "INF", 3 );
1278 if ((neg
= val
< 0))
1284 mag
= log10l( val
);
1285 use_exp
= (mag
>= 15 || (neg
&& mag
>= 1) || mag
<= -1);
1288 if (mag
< 0) mag
-= 1;
1289 val
= val
/ powl( 10.0, mag
);
1293 else if (mag
< 1) mag
= 0;
1295 while (val
> precision
|| mag
>= 0)
1297 long double weight
= powl( 10.0, mag
);
1298 if (weight
> 0 && !isinf( weight
))
1300 int digit
= floorl( val
/ weight
);
1301 val
-= digit
* weight
;
1302 *(p
++) = '0' + digit
;
1304 if (!mag
&& val
> precision
) *(p
++) = '.';
1312 if (mag2
> 0) *(p
++) = '+';
1321 *(p
++) = '0' + mag2
% 10;
1325 for (i
= -mag
, j
= -1; i
< j
; i
++, j
--)
1335 FIXME( "powl not found at build time\n" );
1340 static inline int year_size( int year
)
1342 return leap_year( year
) ? 366 : 365;
1346 static ULONG
format_datetime( const WS_DATETIME
*ptr
, unsigned char *buf
)
1348 static const char fmt
[] = "%04u-%02u-%02uT%02u:%02u:%02u";
1349 int day
, hour
, min
, sec
, sec_frac
, month
= 0, year
= 1, tz_hour
;
1350 unsigned __int64 ticks
, day_ticks
;
1353 if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
&&
1354 ptr
->ticks
>= TICKS_1601_01_01
+ TZ_OFFSET
* TICKS_PER_HOUR
)
1356 ticks
= ptr
->ticks
- TZ_OFFSET
* TICKS_PER_HOUR
;
1357 tz_hour
= TZ_OFFSET
;
1364 day
= ticks
/ TICKS_PER_DAY
;
1365 day_ticks
= ticks
% TICKS_PER_DAY
;
1366 hour
= day_ticks
/ TICKS_PER_HOUR
;
1367 min
= (day_ticks
% TICKS_PER_HOUR
) / TICKS_PER_MIN
;
1368 sec
= (day_ticks
% TICKS_PER_MIN
) / TICKS_PER_SEC
;
1369 sec_frac
= day_ticks
% TICKS_PER_SEC
;
1371 while (day
>= year_size( year
))
1373 day
-= year_size( year
);
1376 while (day
>= month_days
[leap_year( year
)][month
])
1378 day
-= month_days
[leap_year( year
)][month
];
1382 len
= sprintf( (char *)buf
, fmt
, year
, month
+ 1, day
+ 1, hour
, min
, sec
);
1385 static const char fmt_frac
[] = ".%07u";
1386 len
+= sprintf( (char *)buf
+ len
, fmt_frac
, sec_frac
);
1387 while (buf
[len
- 1] == '0') len
--;
1389 if (ptr
->format
== WS_DATETIME_FORMAT_UTC
)
1393 else if (ptr
->format
== WS_DATETIME_FORMAT_LOCAL
)
1395 static const char fmt_tz
[] = "%c%02u:00";
1396 len
+= sprintf( (char *)buf
+ len
, fmt_tz
, tz_hour
? '-' : '+', tz_hour
);
1402 static ULONG
format_guid( const GUID
*ptr
, unsigned char *buf
)
1404 static const char fmt
[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1405 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1406 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1407 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1410 static ULONG
format_urn( const GUID
*ptr
, unsigned char *buf
)
1412 static const char fmt
[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
1413 return sprintf( (char *)buf
, fmt
, ptr
->Data1
, ptr
->Data2
, ptr
->Data3
,
1414 ptr
->Data4
[0], ptr
->Data4
[1], ptr
->Data4
[2], ptr
->Data4
[3],
1415 ptr
->Data4
[4], ptr
->Data4
[5], ptr
->Data4
[6], ptr
->Data4
[7] );
1418 static ULONG
encode_base64( const unsigned char *bin
, ULONG len
, unsigned char *buf
)
1420 static const char base64
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1425 buf
[i
++] = base64
[(bin
[0] & 0xfc) >> 2];
1426 x
= (bin
[0] & 3) << 4;
1429 buf
[i
++] = base64
[x
];
1434 buf
[i
++] = base64
[x
| ((bin
[1] & 0xf0) >> 4)];
1435 x
= (bin
[1] & 0x0f) << 2;
1438 buf
[i
++] = base64
[x
];
1442 buf
[i
++] = base64
[x
| ((bin
[2] & 0xc0) >> 6)];
1443 buf
[i
++] = base64
[bin
[2] & 0x3f];
1450 static HRESULT
text_to_utf8text( const WS_XML_TEXT
*text
, const WS_XML_UTF8_TEXT
*old
, WS_XML_UTF8_TEXT
**ret
)
1452 ULONG len_old
= old
? old
->value
.length
: 0;
1454 switch (text
->textType
)
1456 case WS_XML_TEXT_TYPE_UTF8
:
1458 const WS_XML_UTF8_TEXT
*src
= (const WS_XML_UTF8_TEXT
*)text
;
1460 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ src
->value
.length
))) return E_OUTOFMEMORY
;
1461 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1462 memcpy( (*ret
)->value
.bytes
+ len_old
, src
->value
.bytes
, src
->value
.length
);
1465 case WS_XML_TEXT_TYPE_UTF16
:
1467 const WS_XML_UTF16_TEXT
*src
= (const WS_XML_UTF16_TEXT
*)text
;
1468 const WCHAR
*str
= (const WCHAR
*)src
->bytes
;
1469 ULONG len
= src
->byteCount
/ sizeof(WCHAR
), len_utf8
;
1471 if (src
->byteCount
% sizeof(WCHAR
)) return E_INVALIDARG
;
1472 len_utf8
= WideCharToMultiByte( CP_UTF8
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
1473 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len_utf8
))) return E_OUTOFMEMORY
;
1474 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1475 WideCharToMultiByte( CP_UTF8
, 0, str
, len
, (char *)(*ret
)->value
.bytes
+ len_old
, len_utf8
, NULL
, NULL
);
1478 case WS_XML_TEXT_TYPE_BASE64
:
1480 const WS_XML_BASE64_TEXT
*base64
= (const WS_XML_BASE64_TEXT
*)text
;
1481 ULONG len
= ((4 * base64
->length
/ 3) + 3) & ~3;
1483 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1484 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1485 (*ret
)->value
.length
= encode_base64( base64
->bytes
, base64
->length
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1488 case WS_XML_TEXT_TYPE_BOOL
:
1490 const WS_XML_BOOL_TEXT
*bool_text
= (const WS_XML_BOOL_TEXT
*)text
;
1492 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 5 ))) return E_OUTOFMEMORY
;
1493 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1494 (*ret
)->value
.length
= format_bool( &bool_text
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1497 case WS_XML_TEXT_TYPE_INT32
:
1499 const WS_XML_INT32_TEXT
*int32_text
= (const WS_XML_INT32_TEXT
*)text
;
1500 unsigned char buf
[12]; /* "-2147483648" */
1501 ULONG len
= format_int32( &int32_text
->value
, buf
);
1503 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1504 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1505 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1508 case WS_XML_TEXT_TYPE_INT64
:
1510 const WS_XML_INT64_TEXT
*int64_text
= (const WS_XML_INT64_TEXT
*)text
;
1511 unsigned char buf
[21]; /* "-9223372036854775808" */
1512 ULONG len
= format_int64( &int64_text
->value
, buf
);
1514 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1515 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1516 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1519 case WS_XML_TEXT_TYPE_UINT64
:
1521 const WS_XML_UINT64_TEXT
*uint64_text
= (const WS_XML_UINT64_TEXT
*)text
;
1522 unsigned char buf
[21]; /* "18446744073709551615" */
1523 ULONG len
= format_uint64( &uint64_text
->value
, buf
);
1525 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1526 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1527 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1530 case WS_XML_TEXT_TYPE_DOUBLE
:
1532 const WS_XML_DOUBLE_TEXT
*double_text
= (const WS_XML_DOUBLE_TEXT
*)text
;
1533 unsigned char buf
[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
1534 unsigned short fpword
;
1537 if (!set_fpword( 0x37f, &fpword
)) return E_NOTIMPL
;
1538 len
= format_double( &double_text
->value
, buf
);
1539 restore_fpword( fpword
);
1540 if (!len
) return E_NOTIMPL
;
1542 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ len
))) return E_OUTOFMEMORY
;
1543 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1544 memcpy( (*ret
)->value
.bytes
+ len_old
, buf
, len
);
1547 case WS_XML_TEXT_TYPE_GUID
:
1549 const WS_XML_GUID_TEXT
*id
= (const WS_XML_GUID_TEXT
*)text
;
1551 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 37 ))) return E_OUTOFMEMORY
;
1552 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1553 (*ret
)->value
.length
= format_guid( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1556 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1558 const WS_XML_UNIQUE_ID_TEXT
*id
= (const WS_XML_UNIQUE_ID_TEXT
*)text
;
1560 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 46 ))) return E_OUTOFMEMORY
;
1561 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1562 (*ret
)->value
.length
= format_urn( &id
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1565 case WS_XML_TEXT_TYPE_DATETIME
:
1567 const WS_XML_DATETIME_TEXT
*dt
= (const WS_XML_DATETIME_TEXT
*)text
;
1569 if (!(*ret
= alloc_utf8_text( NULL
, len_old
+ 34 ))) return E_OUTOFMEMORY
;
1570 if (old
) memcpy( (*ret
)->value
.bytes
, old
->value
.bytes
, len_old
);
1571 (*ret
)->value
.length
= format_datetime( &dt
->value
, (*ret
)->value
.bytes
+ len_old
) + len_old
;
1575 FIXME( "unhandled text type %u\n", text
->textType
);
1580 static HRESULT
write_set_attribute_value( struct writer
*writer
, const WS_XML_TEXT
*value
)
1582 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
1583 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)elem
->attributes
[elem
->attributeCount
- 1]->value
;
1586 switch (value
->textType
)
1588 case WS_XML_TEXT_TYPE_UTF8
:
1589 case WS_XML_TEXT_TYPE_UTF16
:
1590 case WS_XML_TEXT_TYPE_BASE64
:
1593 case WS_XML_TEXT_TYPE_BOOL
:
1594 case WS_XML_TEXT_TYPE_INT32
:
1595 case WS_XML_TEXT_TYPE_INT64
:
1596 case WS_XML_TEXT_TYPE_UINT64
:
1597 case WS_XML_TEXT_TYPE_DOUBLE
:
1598 case WS_XML_TEXT_TYPE_GUID
:
1599 case WS_XML_TEXT_TYPE_UNIQUE_ID
:
1600 case WS_XML_TEXT_TYPE_DATETIME
:
1601 if (old
) return WS_E_INVALID_OPERATION
;
1605 FIXME( "unhandled text type %u\n", value
->textType
);
1609 if ((hr
= text_to_utf8text( value
, old
, &new )) != S_OK
) return hr
;
1612 elem
->attributes
[elem
->attributeCount
- 1]->value
= &new->text
;
1617 static HRESULT
write_add_text_node( struct writer
*writer
, const WS_XML_TEXT
*value
)
1620 WS_XML_TEXT_NODE
*text
;
1621 WS_XML_UTF8_TEXT
*utf8
;
1624 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_ELEMENT
&&
1625 node_type( writer
->current
) != WS_XML_NODE_TYPE_BOF
&&
1626 node_type( writer
->current
) != WS_XML_NODE_TYPE_CDATA
) return WS_E_INVALID_FORMAT
;
1628 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1629 if ((hr
= text_to_utf8text( value
, NULL
, &utf8
)) != S_OK
)
1634 text
= (WS_XML_TEXT_NODE
*)node
;
1635 text
->text
= &utf8
->text
;
1637 write_insert_node( writer
, writer
->current
, node
);
1641 static HRESULT
write_text( struct writer
*writer
, ULONG offset
)
1643 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)writer
->current
;
1644 const WS_XML_UTF8_TEXT
*utf8
= (const WS_XML_UTF8_TEXT
*)text
->text
;
1647 if (!writer
->current
->parent
) return WS_E_INVALID_FORMAT
;
1648 if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_ELEMENT
)
1650 const struct escape
*escapes
[3] = { &escape_lt
, &escape_gt
, &escape_amp
};
1651 return write_bytes_escape( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
, escapes
, 3 );
1653 else if (node_type( writer
->current
->parent
) == WS_XML_NODE_TYPE_CDATA
)
1655 if ((hr
= write_grow_buffer( writer
, utf8
->value
.length
- offset
)) != S_OK
) return hr
;
1656 write_bytes( writer
, utf8
->value
.bytes
+ offset
, utf8
->value
.length
- offset
);
1660 return WS_E_INVALID_FORMAT
;
1663 static HRESULT
write_text_node( struct writer
*writer
, const WS_XML_TEXT
*text
)
1668 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
1669 if (node_type( writer
->current
) != WS_XML_NODE_TYPE_TEXT
)
1672 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
1676 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
1677 WS_XML_UTF8_TEXT
*new, *old
= (WS_XML_UTF8_TEXT
*)node
->text
;
1679 offset
= old
->value
.length
;
1680 if ((hr
= text_to_utf8text( text
, old
, &new )) != S_OK
) return hr
;
1682 node
->text
= &new->text
;
1685 if ((hr
= write_text( writer
, offset
)) != S_OK
) return hr
;
1687 writer
->state
= WRITER_STATE_TEXT
;
1691 /**************************************************************************
1692 * WsWriteText [webservices.@]
1694 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
1696 struct writer
*writer
= (struct writer
*)handle
;
1699 TRACE( "%p %p %p\n", handle
, text
, error
);
1700 if (error
) FIXME( "ignoring error parameter\n" );
1702 if (!writer
|| !text
) return E_INVALIDARG
;
1704 EnterCriticalSection( &writer
->cs
);
1706 if (writer
->magic
!= WRITER_MAGIC
)
1708 LeaveCriticalSection( &writer
->cs
);
1709 return E_INVALIDARG
;
1712 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, text
);
1713 else hr
= write_text_node( writer
, text
);
1715 LeaveCriticalSection( &writer
->cs
);
1719 /**************************************************************************
1720 * WsWriteBytes [webservices.@]
1722 HRESULT WINAPI
WsWriteBytes( WS_XML_WRITER
*handle
, const void *bytes
, ULONG count
, WS_ERROR
*error
)
1724 struct writer
*writer
= (struct writer
*)handle
;
1725 WS_XML_BASE64_TEXT base64
;
1728 TRACE( "%p %p %u %p\n", handle
, bytes
, count
, error
);
1729 if (error
) FIXME( "ignoring error parameter\n" );
1731 if (!writer
) return E_INVALIDARG
;
1733 EnterCriticalSection( &writer
->cs
);
1735 if (writer
->magic
!= WRITER_MAGIC
)
1737 LeaveCriticalSection( &writer
->cs
);
1738 return E_INVALIDARG
;
1741 if (!writer
->output_type
)
1743 LeaveCriticalSection( &writer
->cs
);
1744 return WS_E_INVALID_OPERATION
;
1747 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
1748 base64
.bytes
= (BYTE
*)bytes
;
1749 base64
.length
= count
;
1751 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &base64
.text
);
1752 else hr
= write_text_node( writer
, &base64
.text
);
1754 LeaveCriticalSection( &writer
->cs
);
1758 /**************************************************************************
1759 * WsWriteChars [webservices.@]
1761 HRESULT WINAPI
WsWriteChars( WS_XML_WRITER
*handle
, const WCHAR
*chars
, ULONG count
, WS_ERROR
*error
)
1763 struct writer
*writer
= (struct writer
*)handle
;
1764 WS_XML_UTF16_TEXT utf16
;
1767 TRACE( "%p %s %u %p\n", handle
, debugstr_wn(chars
, count
), count
, error
);
1768 if (error
) FIXME( "ignoring error parameter\n" );
1770 if (!writer
) return E_INVALIDARG
;
1772 EnterCriticalSection( &writer
->cs
);
1774 if (writer
->magic
!= WRITER_MAGIC
)
1776 LeaveCriticalSection( &writer
->cs
);
1777 return E_INVALIDARG
;
1780 if (!writer
->output_type
)
1782 LeaveCriticalSection( &writer
->cs
);
1783 return WS_E_INVALID_OPERATION
;
1786 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
1787 utf16
.bytes
= (BYTE
*)chars
;
1788 utf16
.byteCount
= count
* sizeof(WCHAR
);
1790 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf16
.text
);
1791 else hr
= write_text_node( writer
, &utf16
.text
);
1793 LeaveCriticalSection( &writer
->cs
);
1797 /**************************************************************************
1798 * WsWriteCharsUtf8 [webservices.@]
1800 HRESULT WINAPI
WsWriteCharsUtf8( WS_XML_WRITER
*handle
, const BYTE
*bytes
, ULONG count
, WS_ERROR
*error
)
1802 struct writer
*writer
= (struct writer
*)handle
;
1803 WS_XML_UTF8_TEXT utf8
;
1806 TRACE( "%p %s %u %p\n", handle
, debugstr_an((const char *)bytes
, count
), count
, error
);
1807 if (error
) FIXME( "ignoring error parameter\n" );
1809 if (!writer
) return E_INVALIDARG
;
1811 EnterCriticalSection( &writer
->cs
);
1813 if (writer
->magic
!= WRITER_MAGIC
)
1815 LeaveCriticalSection( &writer
->cs
);
1816 return E_INVALIDARG
;
1819 if (!writer
->output_type
)
1821 LeaveCriticalSection( &writer
->cs
);
1822 return WS_E_INVALID_OPERATION
;
1825 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1826 utf8
.value
.bytes
= (BYTE
*)bytes
;
1827 utf8
.value
.length
= count
;
1829 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
) hr
= write_set_attribute_value( writer
, &utf8
.text
);
1830 else hr
= write_text_node( writer
, &utf8
.text
);
1832 LeaveCriticalSection( &writer
->cs
);
1836 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
, const WS_XML_TEXT
*text
)
1840 case WS_ELEMENT_TYPE_MAPPING
:
1841 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1842 return write_text_node( writer
, text
);
1844 case WS_ATTRIBUTE_TYPE_MAPPING
:
1845 return write_set_attribute_value( writer
, text
);
1847 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1848 switch (writer
->state
)
1850 case WRITER_STATE_STARTATTRIBUTE
:
1851 return write_set_attribute_value( writer
, text
);
1853 case WRITER_STATE_STARTELEMENT
:
1854 return write_text_node( writer
, text
);
1857 FIXME( "writer state %u not handled\n", writer
->state
);
1862 FIXME( "mapping %u not implemented\n", mapping
);
1867 static HRESULT
write_add_nil_attribute( struct writer
*writer
)
1869 static const WS_XML_STRING prefix
= {1, (BYTE
*)"a"};
1870 static const WS_XML_STRING localname
= {3, (BYTE
*)"nil"};
1871 static const WS_XML_STRING ns
= {41, (BYTE
*)"http://www.w3.org/2001/XMLSchema-instance"};
1872 static const WS_XML_UTF8_TEXT value
= {{WS_XML_TEXT_TYPE_UTF8
}, {4, (BYTE
*)"true"}};
1875 if ((hr
= write_add_attribute( writer
, &prefix
, &localname
, &ns
, FALSE
)) != S_OK
) return hr
;
1876 if ((hr
= write_set_attribute_value( writer
, &value
.text
)) != S_OK
) return hr
;
1877 return write_add_namespace_attribute( writer
, &prefix
, &ns
, FALSE
);
1880 static HRESULT
get_value_ptr( WS_WRITE_OPTION option
, const void *value
, ULONG size
, ULONG expected_size
,
1885 case WS_WRITE_REQUIRED_VALUE
:
1886 case WS_WRITE_NILLABLE_VALUE
:
1887 if (!value
|| size
!= expected_size
) return E_INVALIDARG
;
1891 case WS_WRITE_REQUIRED_POINTER
:
1892 if (size
!= sizeof(const void *) || !(*ptr
= *(const void **)value
)) return E_INVALIDARG
;
1895 case WS_WRITE_NILLABLE_POINTER
:
1896 if (size
!= sizeof(const void *)) return E_INVALIDARG
;
1897 *ptr
= *(const void **)value
;
1901 return E_INVALIDARG
;
1905 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1906 const WS_BOOL_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1907 const BOOL
*value
, ULONG size
)
1909 WS_XML_UTF8_TEXT utf8
;
1910 unsigned char buf
[6]; /* "false" */
1916 FIXME( "description not supported\n" );
1920 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1921 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(BOOL
), (const void **)&ptr
)) != S_OK
) return hr
;
1922 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1924 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1925 utf8
.value
.bytes
= buf
;
1926 utf8
.value
.length
= format_bool( ptr
, buf
);
1927 return write_type_text( writer
, mapping
, &utf8
.text
);
1930 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1931 const WS_INT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1932 const BOOL
*value
, ULONG size
)
1934 WS_XML_UTF8_TEXT utf8
;
1935 unsigned char buf
[5]; /* "-128" */
1941 FIXME( "description not supported\n" );
1945 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1946 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT8
), (const void **)&ptr
)) != S_OK
) return hr
;
1947 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1949 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1950 utf8
.value
.bytes
= buf
;
1951 utf8
.value
.length
= format_int8( ptr
, buf
);
1952 return write_type_text( writer
, mapping
, &utf8
.text
);
1955 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1956 const WS_INT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1957 const BOOL
*value
, ULONG size
)
1959 WS_XML_UTF8_TEXT utf8
;
1960 unsigned char buf
[7]; /* "-32768" */
1966 FIXME( "description not supported\n" );
1970 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1971 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT16
), (const void **)&ptr
)) != S_OK
) return hr
;
1972 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1974 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
1975 utf8
.value
.bytes
= buf
;
1976 utf8
.value
.length
= format_int16( ptr
, buf
);
1977 return write_type_text( writer
, mapping
, &utf8
.text
);
1980 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1981 const WS_INT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
1982 const void *value
, ULONG size
)
1984 WS_XML_UTF8_TEXT utf8
;
1985 unsigned char buf
[12]; /* "-2147483648" */
1991 FIXME( "description not supported\n" );
1995 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
1996 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT32
), (const void **)&ptr
)) != S_OK
) return hr
;
1997 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
1999 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2000 utf8
.value
.bytes
= buf
;
2001 utf8
.value
.length
= format_int32( ptr
, buf
);
2002 return write_type_text( writer
, mapping
, &utf8
.text
);
2005 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2006 const WS_INT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2007 const void *value
, ULONG size
)
2009 WS_XML_UTF8_TEXT utf8
;
2010 unsigned char buf
[21]; /* "-9223372036854775808" */
2016 FIXME( "description not supported\n" );
2020 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2021 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(INT64
), (const void **)&ptr
)) != S_OK
) return hr
;
2022 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2024 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2025 utf8
.value
.bytes
= buf
;
2026 utf8
.value
.length
= format_int64( ptr
, buf
);
2027 return write_type_text( writer
, mapping
, &utf8
.text
);
2030 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2031 const WS_UINT8_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2032 const void *value
, ULONG size
)
2034 WS_XML_UTF8_TEXT utf8
;
2035 unsigned char buf
[4]; /* "255" */
2041 FIXME( "description not supported\n" );
2045 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2046 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT8
), (const void **)&ptr
)) != S_OK
) return hr
;
2047 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2049 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2050 utf8
.value
.bytes
= buf
;
2051 utf8
.value
.length
= format_uint8( ptr
, buf
);
2052 return write_type_text( writer
, mapping
, &utf8
.text
);
2055 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2056 const WS_UINT16_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2057 const void *value
, ULONG size
)
2059 WS_XML_UTF8_TEXT utf8
;
2060 unsigned char buf
[6]; /* "65535" */
2066 FIXME( "description not supported\n" );
2070 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2071 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT16
), (const void **)&ptr
)) != S_OK
) return hr
;
2072 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2074 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2075 utf8
.value
.bytes
= buf
;
2076 utf8
.value
.length
= format_uint16( ptr
, buf
);
2077 return write_type_text( writer
, mapping
, &utf8
.text
);
2080 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2081 const WS_UINT32_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2082 const void *value
, ULONG size
)
2084 WS_XML_UTF8_TEXT utf8
;
2085 unsigned char buf
[11]; /* "4294967295" */
2091 FIXME( "description not supported\n" );
2095 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2096 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT32
), (const void **)&ptr
)) != S_OK
) return hr
;
2097 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2099 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2100 utf8
.value
.bytes
= buf
;
2101 utf8
.value
.length
= format_uint32( ptr
, buf
);
2102 return write_type_text( writer
, mapping
, &utf8
.text
);
2105 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2106 const WS_UINT64_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2107 const void *value
, ULONG size
)
2109 WS_XML_UTF8_TEXT utf8
;
2110 unsigned char buf
[21]; /* "18446744073709551615" */
2116 FIXME( "description not supported\n" );
2120 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2121 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(UINT64
), (const void **)&ptr
)) != S_OK
) return hr
;
2122 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2124 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2125 utf8
.value
.bytes
= buf
;
2126 utf8
.value
.length
= format_uint64( ptr
, buf
);
2127 return write_type_text( writer
, mapping
, &utf8
.text
);
2130 static HRESULT
write_type_datetime( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2131 const WS_DATETIME_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2132 const void *value
, ULONG size
)
2134 WS_XML_UTF8_TEXT utf8
;
2135 unsigned char buf
[34]; /* "0000-00-00T00:00:00.0000000-00:00" */
2136 const WS_DATETIME
*ptr
;
2141 FIXME( "description not supported\n" );
2145 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2146 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_DATETIME
), (const void **)&ptr
)) != S_OK
) return hr
;
2147 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2148 if (ptr
->ticks
> TICKS_MAX
|| ptr
->format
> WS_DATETIME_FORMAT_NONE
) return WS_E_INVALID_FORMAT
;
2150 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2151 utf8
.value
.bytes
= buf
;
2152 utf8
.value
.length
= format_datetime( ptr
, buf
);
2153 return write_type_text( writer
, mapping
, &utf8
.text
);
2156 static HRESULT
write_type_guid( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2157 const WS_GUID_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2158 const void *value
, ULONG size
)
2160 WS_XML_UTF8_TEXT utf8
;
2161 unsigned char buf
[37]; /* "00000000-0000-0000-0000-000000000000" */
2167 FIXME( "description not supported\n" );
2171 if (!option
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2172 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(GUID
), (const void **)&ptr
)) != S_OK
) return hr
;
2173 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2175 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2176 utf8
.value
.bytes
= buf
;
2177 utf8
.value
.length
= format_guid( ptr
, buf
);
2178 return write_type_text( writer
, mapping
, &utf8
.text
);
2181 static HRESULT
write_type_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2182 const WS_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2183 const void *value
, ULONG size
)
2185 WS_XML_UTF16_TEXT utf16
;
2186 const WS_STRING
*ptr
;
2191 FIXME( "description not supported\n" );
2195 if (!option
) return E_INVALIDARG
;
2196 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
2197 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2198 if (!ptr
->length
) return S_OK
;
2200 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2201 utf16
.bytes
= (BYTE
*)ptr
->chars
;
2202 utf16
.byteCount
= ptr
->length
* sizeof(WCHAR
);
2203 return write_type_text( writer
, mapping
, &utf16
.text
);
2206 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2207 const WS_WSZ_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2208 const void *value
, ULONG size
)
2210 WS_XML_UTF16_TEXT utf16
;
2217 FIXME( "description not supported\n" );
2221 if (!option
|| option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
) return E_INVALIDARG
;
2222 if ((hr
= get_value_ptr( option
, value
, size
, 0, (const void **)&ptr
)) != S_OK
) return hr
;
2223 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2224 if (!(len
= strlenW( ptr
))) return S_OK
;
2226 utf16
.text
.textType
= WS_XML_TEXT_TYPE_UTF16
;
2227 utf16
.bytes
= (BYTE
*)ptr
;
2228 utf16
.byteCount
= len
* sizeof(WCHAR
);
2229 return write_type_text( writer
, mapping
, &utf16
.text
);
2232 static HRESULT
write_type_bytes( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2233 const WS_BYTES_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2234 const void *value
, ULONG size
)
2236 WS_XML_BASE64_TEXT base64
;
2237 const WS_BYTES
*ptr
;
2242 FIXME( "description not supported\n" );
2246 if (!option
) return E_INVALIDARG
;
2247 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_BYTES
), (const void **)&ptr
)) != S_OK
) return hr
;
2248 if ((option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) ||
2249 (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
)) return write_add_nil_attribute( writer
);
2250 if (!ptr
->length
) return S_OK
;
2252 base64
.text
.textType
= WS_XML_TEXT_TYPE_BASE64
;
2253 base64
.bytes
= ptr
->bytes
;
2254 base64
.length
= ptr
->length
;
2255 return write_type_text( writer
, mapping
, &base64
.text
);
2258 static HRESULT
write_type_xml_string( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2259 const WS_XML_STRING_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2260 const void *value
, ULONG size
)
2262 WS_XML_UTF8_TEXT utf8
;
2263 const WS_XML_STRING
*ptr
;
2268 FIXME( "description not supported\n" );
2272 if (!option
) return E_INVALIDARG
;
2273 if ((hr
= get_value_ptr( option
, value
, size
, sizeof(WS_XML_STRING
), (const void **)&ptr
)) != S_OK
) return hr
;
2274 if (option
== WS_WRITE_NILLABLE_POINTER
&& !ptr
) return write_add_nil_attribute( writer
);
2275 if (option
== WS_WRITE_NILLABLE_VALUE
&& is_nil_value( value
, size
)) return write_add_nil_attribute( writer
);
2276 if (!ptr
->length
) return S_OK
;
2278 utf8
.text
.textType
= WS_XML_TEXT_TYPE_UTF8
;
2279 utf8
.value
.bytes
= ptr
->bytes
;
2280 utf8
.value
.length
= ptr
->length
;
2281 return write_type_text( writer
, mapping
, &utf8
.text
);
2284 static WS_WRITE_OPTION
get_field_write_option( WS_TYPE type
, ULONG options
)
2286 if (options
& WS_FIELD_POINTER
)
2288 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
2289 return WS_WRITE_REQUIRED_POINTER
;
2300 case WS_UINT16_TYPE
:
2301 case WS_UINT32_TYPE
:
2302 case WS_UINT64_TYPE
:
2303 case WS_DOUBLE_TYPE
:
2304 case WS_DATETIME_TYPE
:
2306 case WS_STRING_TYPE
:
2308 case WS_XML_STRING_TYPE
:
2309 case WS_STRUCT_TYPE
:
2311 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_VALUE
;
2312 return WS_WRITE_REQUIRED_VALUE
;
2315 case WS_DESCRIPTION_TYPE
:
2316 if (options
& (WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
)) return WS_WRITE_NILLABLE_POINTER
;
2317 return WS_WRITE_REQUIRED_POINTER
;
2320 FIXME( "unhandled type %u\n", type
);
2325 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
2326 const void *, ULONG
);
2328 static HRESULT
write_type_repeating_element( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
2329 const char *buf
, ULONG count
)
2332 ULONG i
, size
, offset
= 0;
2333 WS_WRITE_OPTION option
;
2335 if (!(option
= get_field_write_option( desc
->type
, desc
->options
))) return E_INVALIDARG
;
2337 /* wrapper element */
2338 if (desc
->localName
&& ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
))
2341 if (option
== WS_WRITE_REQUIRED_VALUE
|| option
== WS_WRITE_NILLABLE_VALUE
)
2342 size
= get_type_size( desc
->type
, desc
->typeDescription
);
2344 size
= sizeof(const void *);
2346 for (i
= 0; i
< count
; i
++)
2348 if ((hr
= write_element_node( writer
, NULL
, desc
->itemLocalName
, desc
->itemNs
)) != S_OK
) return hr
;
2349 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
,
2350 buf
+ offset
, size
)) != S_OK
) return hr
;
2351 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2355 if (desc
->localName
) hr
= write_endelement_node( writer
);
2359 static HRESULT
write_type_struct_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
2360 const char *buf
, ULONG offset
)
2363 WS_TYPE_MAPPING mapping
;
2364 WS_WRITE_OPTION option
;
2365 ULONG count
, size
, field_options
= desc
->options
;
2366 const char *ptr
= buf
+ offset
;
2368 if (field_options
& ~(WS_FIELD_POINTER
|WS_FIELD_OPTIONAL
|WS_FIELD_NILLABLE
))
2370 FIXME( "options 0x%x not supported\n", desc
->options
);
2374 /* zero-terminated strings are always pointers */
2375 if (desc
->type
== WS_WSZ_TYPE
) field_options
|= WS_FIELD_POINTER
;
2377 if (field_options
& WS_FIELD_POINTER
)
2378 size
= sizeof(const void *);
2380 size
= get_type_size( desc
->type
, desc
->typeDescription
);
2382 if (is_nil_value( ptr
, size
))
2384 if (field_options
& WS_FIELD_OPTIONAL
) return S_OK
;
2385 if (field_options
& WS_FIELD_NILLABLE
)
2387 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_NILLABLE_POINTER
;
2388 else option
= WS_WRITE_NILLABLE_VALUE
;
2390 else return E_INVALIDARG
;
2394 if (field_options
& WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
2395 else option
= WS_WRITE_REQUIRED_VALUE
;
2398 switch (desc
->mapping
)
2400 case WS_ATTRIBUTE_FIELD_MAPPING
:
2401 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
2402 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
2404 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2406 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2409 case WS_ELEMENT_FIELD_MAPPING
:
2410 if ((hr
= write_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
) return hr
;
2411 mapping
= WS_ELEMENT_TYPE_MAPPING
;
2414 case WS_REPEATING_ELEMENT_FIELD_MAPPING
:
2415 count
= *(const ULONG
*)(buf
+ desc
->countOffset
);
2416 return write_type_repeating_element( writer
, desc
, *(const char **)ptr
, count
);
2418 case WS_TEXT_FIELD_MAPPING
:
2419 switch (writer
->state
)
2421 case WRITER_STATE_STARTELEMENT
:
2422 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
2425 case WRITER_STATE_STARTATTRIBUTE
:
2426 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2430 FIXME( "unhandled writer state %u\n", writer
->state
);
2436 FIXME( "field mapping %u not supported\n", desc
->mapping
);
2440 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, ptr
, size
)) != S_OK
)
2445 case WS_ATTRIBUTE_TYPE_MAPPING
:
2446 writer
->state
= WRITER_STATE_STARTELEMENT
;
2449 case WS_ELEMENT_TYPE_MAPPING
:
2450 if ((hr
= write_endelement_node( writer
)) != S_OK
) return hr
;
2459 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
2460 const WS_STRUCT_DESCRIPTION
*desc
, WS_WRITE_OPTION option
,
2461 const void *value
, ULONG size
)
2467 if (!desc
) return E_INVALIDARG
;
2468 if (desc
->structOptions
) FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
2470 if ((hr
= get_value_ptr( option
, value
, size
, desc
->size
, &ptr
)) != S_OK
) return hr
;
2472 for (i
= 0; i
< desc
->fieldCount
; i
++)
2474 offset
= desc
->fields
[i
]->offset
;
2475 if ((hr
= write_type_struct_field( writer
, desc
->fields
[i
], ptr
, offset
)) != S_OK
)
2483 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
2484 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
2490 return write_type_bool( writer
, mapping
, desc
, option
, value
, size
);
2493 return write_type_int8( writer
, mapping
, desc
, option
, value
, size
);
2496 return write_type_int16( writer
, mapping
, desc
, option
, value
, size
);
2499 return write_type_int32( writer
, mapping
, desc
, option
, value
, size
);
2502 return write_type_int64( writer
, mapping
, desc
, option
, value
, size
);
2505 return write_type_uint8( writer
, mapping
, desc
, option
, value
, size
);
2507 case WS_UINT16_TYPE
:
2508 return write_type_uint16( writer
, mapping
, desc
, option
, value
, size
);
2510 case WS_UINT32_TYPE
:
2511 return write_type_uint32( writer
, mapping
, desc
, option
, value
, size
);
2513 case WS_UINT64_TYPE
:
2514 return write_type_uint64( writer
, mapping
, desc
, option
, value
, size
);
2516 case WS_DATETIME_TYPE
:
2517 return write_type_datetime( writer
, mapping
, desc
, option
, value
, size
);
2520 return write_type_guid( writer
, mapping
, desc
, option
, value
, size
);
2522 case WS_STRING_TYPE
:
2523 return write_type_string( writer
, mapping
, desc
, option
, value
, size
);
2526 return write_type_wsz( writer
, mapping
, desc
, option
, value
, size
);
2529 return write_type_bytes( writer
, mapping
, desc
, option
, value
, size
);
2531 case WS_XML_STRING_TYPE
:
2532 return write_type_xml_string( writer
, mapping
, desc
, option
, value
, size
);
2534 case WS_STRUCT_TYPE
:
2535 return write_type_struct( writer
, mapping
, desc
, option
, value
, size
);
2538 FIXME( "type %u not supported\n", type
);
2543 /**************************************************************************
2544 * WsWriteAttribute [webservices.@]
2546 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
2547 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
2550 struct writer
*writer
= (struct writer
*)handle
;
2553 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
2554 if (error
) FIXME( "ignoring error parameter\n" );
2556 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
2557 return E_INVALIDARG
;
2559 EnterCriticalSection( &writer
->cs
);
2561 if (writer
->magic
!= WRITER_MAGIC
)
2563 LeaveCriticalSection( &writer
->cs
);
2564 return E_INVALIDARG
;
2567 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
2569 LeaveCriticalSection( &writer
->cs
);
2570 return WS_E_INVALID_OPERATION
;
2573 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
, FALSE
)) != S_OK
)
2575 LeaveCriticalSection( &writer
->cs
);
2578 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
2580 hr
= write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
, option
, value
, size
);
2582 LeaveCriticalSection( &writer
->cs
);
2586 /**************************************************************************
2587 * WsWriteElement [webservices.@]
2589 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
2590 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
2593 struct writer
*writer
= (struct writer
*)handle
;
2596 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
2597 if (error
) FIXME( "ignoring error parameter\n" );
2599 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
2600 return E_INVALIDARG
;
2602 EnterCriticalSection( &writer
->cs
);
2604 if (writer
->magic
!= WRITER_MAGIC
)
2606 LeaveCriticalSection( &writer
->cs
);
2607 return E_INVALIDARG
;
2610 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
2612 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
2613 option
, value
, size
)) != S_OK
) goto done
;
2615 hr
= write_endelement_node( writer
);
2618 LeaveCriticalSection( &writer
->cs
);
2622 /**************************************************************************
2623 * WsWriteType [webservices.@]
2625 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
2626 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
2627 ULONG size
, WS_ERROR
*error
)
2629 struct writer
*writer
= (struct writer
*)handle
;
2632 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
2634 if (error
) FIXME( "ignoring error parameter\n" );
2636 if (!writer
|| !value
) return E_INVALIDARG
;
2638 EnterCriticalSection( &writer
->cs
);
2640 if (writer
->magic
!= WRITER_MAGIC
)
2642 LeaveCriticalSection( &writer
->cs
);
2643 return E_INVALIDARG
;
2648 case WS_ATTRIBUTE_TYPE_MAPPING
:
2649 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) hr
= WS_E_INVALID_FORMAT
;
2650 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
2653 case WS_ELEMENT_TYPE_MAPPING
:
2654 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
2655 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) hr
= WS_E_INVALID_FORMAT
;
2656 else hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
2659 case WS_ANY_ELEMENT_TYPE_MAPPING
:
2660 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
2664 FIXME( "mapping %u not implemented\n", mapping
);
2668 LeaveCriticalSection( &writer
->cs
);
2672 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
2676 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
2677 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
2678 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
2679 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
2680 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
2681 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
2682 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
2683 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
2684 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
2685 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
2686 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
2687 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
2688 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
2689 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
2690 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
2692 FIXME( "unhandled type %u\n", type
);
2697 /**************************************************************************
2698 * WsWriteValue [webservices.@]
2700 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
2701 ULONG size
, WS_ERROR
*error
)
2703 struct writer
*writer
= (struct writer
*)handle
;
2704 WS_TYPE_MAPPING mapping
;
2708 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
2709 if (error
) FIXME( "ignoring error parameter\n" );
2711 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
2713 EnterCriticalSection( &writer
->cs
);
2715 if (writer
->magic
!= WRITER_MAGIC
)
2717 LeaveCriticalSection( &writer
->cs
);
2718 return E_INVALIDARG
;
2721 switch (writer
->state
)
2723 case WRITER_STATE_STARTATTRIBUTE
:
2724 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
2727 case WRITER_STATE_STARTELEMENT
:
2728 mapping
= WS_ELEMENT_TYPE_MAPPING
;
2732 hr
= WS_E_INVALID_FORMAT
;
2735 if (hr
== S_OK
) hr
= write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
2737 LeaveCriticalSection( &writer
->cs
);
2741 /**************************************************************************
2742 * WsWriteArray [webservices.@]
2744 HRESULT WINAPI
WsWriteArray( WS_XML_WRITER
*handle
, const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2745 WS_VALUE_TYPE value_type
, const void *array
, ULONG size
, ULONG offset
,
2746 ULONG count
, WS_ERROR
*error
)
2748 struct writer
*writer
= (struct writer
*)handle
;
2753 TRACE( "%p %s %s %u %p %u %u %u %p\n", handle
, debugstr_xmlstr(localname
), debugstr_xmlstr(ns
),
2754 value_type
, array
, size
, offset
, count
, error
);
2755 if (error
) FIXME( "ignoring error parameter\n" );
2757 if (!writer
) return E_INVALIDARG
;
2759 EnterCriticalSection( &writer
->cs
);
2761 if (writer
->magic
!= WRITER_MAGIC
)
2763 LeaveCriticalSection( &writer
->cs
);
2764 return E_INVALIDARG
;
2767 if (!writer
->output_type
)
2769 LeaveCriticalSection( &writer
->cs
);
2770 return WS_E_INVALID_OPERATION
;
2773 if (!localname
|| !ns
|| (type
= map_value_type( value_type
)) == ~0u)
2775 LeaveCriticalSection( &writer
->cs
);
2776 return E_INVALIDARG
;
2779 type_size
= get_type_size( type
, NULL
);
2780 if (size
% type_size
|| (offset
+ count
) * type_size
> size
|| (count
&& !array
))
2782 LeaveCriticalSection( &writer
->cs
);
2783 return E_INVALIDARG
;
2786 for (i
= offset
; i
< count
; i
++)
2788 const char *ptr
= (const char *)array
+ (offset
+ i
) * type_size
;
2789 if ((hr
= write_element_node( writer
, NULL
, localname
, ns
)) != S_OK
) goto done
;
2790 if ((hr
= write_type( writer
, WS_ELEMENT_TYPE_MAPPING
, type
, NULL
, WS_WRITE_REQUIRED_POINTER
,
2791 &ptr
, sizeof(ptr
) )) != S_OK
) goto done
;
2792 if ((hr
= write_endelement_node( writer
)) != S_OK
) goto done
;
2796 LeaveCriticalSection( &writer
->cs
);
2800 /**************************************************************************
2801 * WsWriteXmlBuffer [webservices.@]
2803 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
2805 struct writer
*writer
= (struct writer
*)handle
;
2806 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
2809 TRACE( "%p %p %p\n", handle
, buffer
, error
);
2810 if (error
) FIXME( "ignoring error parameter\n" );
2812 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
2814 EnterCriticalSection( &writer
->cs
);
2816 if (writer
->magic
!= WRITER_MAGIC
)
2818 LeaveCriticalSection( &writer
->cs
);
2819 return E_INVALIDARG
;
2822 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
2823 if ((hr
= write_grow_buffer( writer
, xmlbuf
->size
)) != S_OK
) goto done
;
2824 write_bytes( writer
, xmlbuf
->ptr
, xmlbuf
->size
);
2827 LeaveCriticalSection( &writer
->cs
);
2831 /**************************************************************************
2832 * WsWriteXmlBufferToBytes [webservices.@]
2834 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
2835 const WS_XML_WRITER_ENCODING
*encoding
,
2836 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
2837 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
2839 struct writer
*writer
= (struct writer
*)handle
;
2840 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
2845 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
2846 bytes
, size
, error
);
2847 if (error
) FIXME( "ignoring error parameter\n" );
2849 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
2851 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
2853 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
2857 EnterCriticalSection( &writer
->cs
);
2859 if (writer
->magic
!= WRITER_MAGIC
)
2861 LeaveCriticalSection( &writer
->cs
);
2862 return E_INVALIDARG
;
2865 for (i
= 0; i
< count
; i
++)
2867 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
2868 properties
[i
].valueSize
);
2869 if (hr
!= S_OK
) goto done
;
2872 if (!(buf
= ws_alloc( heap
, xmlbuf
->size
))) hr
= WS_E_QUOTA_EXCEEDED
;
2875 memcpy( buf
, xmlbuf
->ptr
, xmlbuf
->size
);
2877 *size
= xmlbuf
->size
;
2881 LeaveCriticalSection( &writer
->cs
);
2885 /**************************************************************************
2886 * WsWriteXmlnsAttribute [webservices.@]
2888 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2889 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
2891 struct writer
*writer
= (struct writer
*)handle
;
2894 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
2896 if (error
) FIXME( "ignoring error parameter\n" );
2898 if (!writer
|| !ns
) return E_INVALIDARG
;
2900 EnterCriticalSection( &writer
->cs
);
2902 if (writer
->magic
!= WRITER_MAGIC
)
2904 LeaveCriticalSection( &writer
->cs
);
2905 return E_INVALIDARG
;
2908 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
2910 LeaveCriticalSection( &writer
->cs
);
2911 return WS_E_INVALID_OPERATION
;
2914 if (!namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
))
2915 hr
= write_add_namespace_attribute( writer
, prefix
, ns
, single
);
2917 LeaveCriticalSection( &writer
->cs
);
2921 static HRESULT
find_prefix( struct writer
*writer
, const WS_XML_STRING
*ns
, const WS_XML_STRING
**prefix
)
2923 const struct node
*node
;
2924 for (node
= writer
->current
; node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
; node
= node
->parent
)
2926 const WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
2928 for (i
= 0; i
< elem
->attributeCount
; i
++)
2930 if (!elem
->attributes
[i
]->isXmlNs
) continue;
2931 if (WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) != S_OK
) continue;
2932 *prefix
= elem
->attributes
[i
]->prefix
;
2936 return WS_E_INVALID_FORMAT
;
2939 static HRESULT
write_qualified_name( struct writer
*writer
, const WS_XML_STRING
*prefix
,
2940 const WS_XML_STRING
*localname
)
2945 if ((hr
= write_grow_buffer( writer
, prefix
->length
+ localname
->length
+ 1 )) != S_OK
) return hr
;
2946 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
2947 write_char( writer
, ':' );
2949 else if ((hr
= write_grow_buffer( writer
, localname
->length
)) != S_OK
) return hr
;
2950 write_bytes( writer
, localname
->bytes
, localname
->length
);
2954 /**************************************************************************
2955 * WsWriteQualifiedName [webservices.@]
2957 HRESULT WINAPI
WsWriteQualifiedName( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
2958 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
2961 struct writer
*writer
= (struct writer
*)handle
;
2964 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
2965 debugstr_xmlstr(ns
), error
);
2966 if (error
) FIXME( "ignoring error parameter\n" );
2968 if (!writer
) return E_INVALIDARG
;
2970 EnterCriticalSection( &writer
->cs
);
2972 if (writer
->magic
!= WRITER_MAGIC
)
2974 LeaveCriticalSection( &writer
->cs
);
2975 return E_INVALIDARG
;
2978 if (!writer
->output_type
)
2980 LeaveCriticalSection( &writer
->cs
);
2981 return WS_E_INVALID_OPERATION
;
2984 if (writer
->state
!= WRITER_STATE_STARTELEMENT
)
2986 LeaveCriticalSection( &writer
->cs
);
2987 return WS_E_INVALID_FORMAT
;
2990 if (!localname
|| (!prefix
&& !ns
))
2992 LeaveCriticalSection( &writer
->cs
);
2993 return E_INVALIDARG
;
2996 if ((hr
= write_flush( writer
)) != S_OK
) goto done
;
2997 if (!prefix
&& ((hr
= find_prefix( writer
, ns
, &prefix
)) != S_OK
)) goto done
;
2998 hr
= write_qualified_name( writer
, prefix
, localname
);
3001 LeaveCriticalSection( &writer
->cs
);
3005 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
3007 BOOL success
= FALSE
;
3008 struct node
*node
= writer
->current
;
3012 case WS_MOVE_TO_ROOT_ELEMENT
:
3013 success
= move_to_root_element( writer
->root
, &node
);
3016 case WS_MOVE_TO_NEXT_ELEMENT
:
3017 success
= move_to_next_element( &node
);
3020 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
3021 success
= move_to_prev_element( &node
);
3024 case WS_MOVE_TO_CHILD_ELEMENT
:
3025 success
= move_to_child_element( &node
);
3028 case WS_MOVE_TO_END_ELEMENT
:
3029 success
= move_to_end_element( &node
);
3032 case WS_MOVE_TO_PARENT_ELEMENT
:
3033 success
= move_to_parent_element( &node
);
3036 case WS_MOVE_TO_FIRST_NODE
:
3037 success
= move_to_first_node( &node
);
3040 case WS_MOVE_TO_NEXT_NODE
:
3041 success
= move_to_next_node( &node
);
3044 case WS_MOVE_TO_PREVIOUS_NODE
:
3045 success
= move_to_prev_node( &node
);
3048 case WS_MOVE_TO_CHILD_NODE
:
3049 success
= move_to_child_node( &node
);
3052 case WS_MOVE_TO_BOF
:
3053 success
= move_to_bof( writer
->root
, &node
);
3056 case WS_MOVE_TO_EOF
:
3057 success
= move_to_eof( writer
->root
, &node
);
3061 FIXME( "unhandled move %u\n", move
);
3065 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
3066 writer
->current
= node
;
3073 return success
? S_OK
: WS_E_INVALID_FORMAT
;
3076 /**************************************************************************
3077 * WsMoveWriter [webservices.@]
3079 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
3081 struct writer
*writer
= (struct writer
*)handle
;
3084 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
3085 if (error
) FIXME( "ignoring error parameter\n" );
3087 if (!writer
) return E_INVALIDARG
;
3089 EnterCriticalSection( &writer
->cs
);
3091 if (writer
->magic
!= WRITER_MAGIC
)
3093 LeaveCriticalSection( &writer
->cs
);
3094 return E_INVALIDARG
;
3097 if (!writer
->output_type
)
3099 LeaveCriticalSection( &writer
->cs
);
3100 return WS_E_INVALID_OPERATION
;
3103 hr
= write_move_to( writer
, move
, found
);
3105 LeaveCriticalSection( &writer
->cs
);
3109 /**************************************************************************
3110 * WsGetWriterPosition [webservices.@]
3112 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
3114 struct writer
*writer
= (struct writer
*)handle
;
3116 TRACE( "%p %p %p\n", handle
, pos
, error
);
3117 if (error
) FIXME( "ignoring error parameter\n" );
3119 if (!writer
|| !pos
) return E_INVALIDARG
;
3121 EnterCriticalSection( &writer
->cs
);
3123 if (writer
->magic
!= WRITER_MAGIC
)
3125 LeaveCriticalSection( &writer
->cs
);
3126 return E_INVALIDARG
;
3129 if (!writer
->output_type
)
3131 LeaveCriticalSection( &writer
->cs
);
3132 return WS_E_INVALID_OPERATION
;
3135 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
3136 pos
->node
= writer
->current
;
3138 LeaveCriticalSection( &writer
->cs
);
3142 /**************************************************************************
3143 * WsSetWriterPosition [webservices.@]
3145 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
3147 struct writer
*writer
= (struct writer
*)handle
;
3149 TRACE( "%p %p %p\n", handle
, pos
, error
);
3150 if (error
) FIXME( "ignoring error parameter\n" );
3152 if (!writer
|| !pos
) return E_INVALIDARG
;
3154 EnterCriticalSection( &writer
->cs
);
3156 if (writer
->magic
!= WRITER_MAGIC
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
)
3158 LeaveCriticalSection( &writer
->cs
);
3159 return E_INVALIDARG
;
3162 if (!writer
->output_type
)
3164 LeaveCriticalSection( &writer
->cs
);
3165 return WS_E_INVALID_OPERATION
;
3168 writer
->current
= pos
->node
;
3170 LeaveCriticalSection( &writer
->cs
);
3174 static HRESULT
write_add_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
3176 struct node
*node
, *parent
;
3177 WS_XML_COMMENT_NODE
*comment
;
3179 if (!(parent
= find_parent( writer
))) return WS_E_INVALID_FORMAT
;
3180 if (!(node
= alloc_node( WS_XML_NODE_TYPE_COMMENT
))) return E_OUTOFMEMORY
;
3181 comment
= (WS_XML_COMMENT_NODE
*)node
;
3183 if (value
->length
&& !(comment
->value
.bytes
= heap_alloc( value
->length
)))
3186 return E_OUTOFMEMORY
;
3188 memcpy( comment
->value
.bytes
, value
->bytes
, value
->length
);
3189 comment
->value
.length
= value
->length
;
3191 write_insert_node( writer
, parent
, node
);
3195 static HRESULT
write_comment( struct writer
*writer
)
3197 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)writer
->current
;
3200 if ((hr
= write_grow_buffer( writer
, comment
->value
.length
+ 7 )) != S_OK
) return hr
;
3201 write_bytes( writer
, (const BYTE
*)"<!--", 4 );
3202 write_bytes( writer
, comment
->value
.bytes
, comment
->value
.length
);
3203 write_bytes( writer
, (const BYTE
*)"-->", 3 );
3207 static HRESULT
write_comment_node( struct writer
*writer
, const WS_XML_STRING
*value
)
3210 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
3211 if ((hr
= write_add_comment_node( writer
, value
)) != S_OK
) return hr
;
3212 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
3213 writer
->state
= WRITER_STATE_COMMENT
;
3217 static HRESULT
write_set_attributes( struct writer
*writer
, WS_XML_ATTRIBUTE
**attrs
, ULONG count
)
3222 for (i
= 0; i
< count
; i
++)
3224 if ((hr
= write_add_attribute( writer
, attrs
[i
]->prefix
, attrs
[i
]->localName
, attrs
[i
]->ns
,
3225 attrs
[i
]->singleQuote
)) != S_OK
) return hr
;
3226 if ((hr
= write_set_attribute_value( writer
, attrs
[i
]->value
)) != S_OK
) return hr
;
3231 static HRESULT
write_node( struct writer
*writer
, const WS_XML_NODE
*node
)
3235 switch (node
->nodeType
)
3237 case WS_XML_NODE_TYPE_ELEMENT
:
3239 const WS_XML_ELEMENT_NODE
*elem
= (const WS_XML_ELEMENT_NODE
*)node
;
3240 if ((hr
= write_element_node( writer
, elem
->prefix
, elem
->localName
, elem
->ns
)) != S_OK
) return hr
;
3241 return write_set_attributes( writer
, elem
->attributes
, elem
->attributeCount
);
3243 case WS_XML_NODE_TYPE_TEXT
:
3245 const WS_XML_TEXT_NODE
*text
= (const WS_XML_TEXT_NODE
*)node
;
3246 return write_text_node( writer
, text
->text
);
3248 case WS_XML_NODE_TYPE_END_ELEMENT
:
3249 return write_endelement_node( writer
);
3251 case WS_XML_NODE_TYPE_COMMENT
:
3253 const WS_XML_COMMENT_NODE
*comment
= (const WS_XML_COMMENT_NODE
*)node
;
3254 return write_comment_node( writer
, &comment
->value
);
3256 case WS_XML_NODE_TYPE_CDATA
:
3257 return write_cdata_node( writer
);
3259 case WS_XML_NODE_TYPE_END_CDATA
:
3260 return write_endcdata_node( writer
);
3262 case WS_XML_NODE_TYPE_EOF
:
3263 case WS_XML_NODE_TYPE_BOF
:
3267 WARN( "unknown node type %u\n", node
->nodeType
);
3268 return E_INVALIDARG
;
3272 /**************************************************************************
3273 * WsWriteNode [webservices.@]
3275 HRESULT WINAPI
WsWriteNode( WS_XML_WRITER
*handle
, const WS_XML_NODE
*node
, WS_ERROR
*error
)
3277 struct writer
*writer
= (struct writer
*)handle
;
3280 TRACE( "%p %p %p\n", handle
, node
, error
);
3281 if (error
) FIXME( "ignoring error parameter\n" );
3283 if (!writer
|| !node
) return E_INVALIDARG
;
3285 EnterCriticalSection( &writer
->cs
);
3287 if (writer
->magic
!= WRITER_MAGIC
)
3289 LeaveCriticalSection( &writer
->cs
);
3290 return E_INVALIDARG
;
3293 if (!writer
->output_type
)
3295 LeaveCriticalSection( &writer
->cs
);
3296 return WS_E_INVALID_OPERATION
;
3299 hr
= write_node( writer
, node
);
3301 LeaveCriticalSection( &writer
->cs
);
3305 static HRESULT
write_tree_node( struct writer
*writer
)
3309 switch (node_type( writer
->current
))
3311 case WS_XML_NODE_TYPE_ELEMENT
:
3312 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3314 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
3315 writer
->state
= WRITER_STATE_STARTELEMENT
;
3318 case WS_XML_NODE_TYPE_TEXT
:
3319 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3321 if ((hr
= write_text( writer
, 0 )) != S_OK
) return hr
;
3322 writer
->state
= WRITER_STATE_TEXT
;
3325 case WS_XML_NODE_TYPE_END_ELEMENT
:
3326 if ((hr
= write_close_element( writer
, writer
->current
->parent
)) != S_OK
) return hr
;
3327 writer
->state
= WRITER_STATE_ENDELEMENT
;
3330 case WS_XML_NODE_TYPE_COMMENT
:
3331 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3333 if ((hr
= write_comment( writer
)) != S_OK
) return hr
;
3334 writer
->state
= WRITER_STATE_COMMENT
;
3337 case WS_XML_NODE_TYPE_CDATA
:
3338 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& (hr
= write_endstartelement( writer
)) != S_OK
)
3340 if ((hr
= write_cdata( writer
)) != S_OK
) return hr
;
3341 writer
->state
= WRITER_STATE_STARTCDATA
;
3344 case WS_XML_NODE_TYPE_END_CDATA
:
3345 if ((hr
= write_endcdata( writer
)) != S_OK
) return hr
;
3346 writer
->state
= WRITER_STATE_ENDCDATA
;
3349 case WS_XML_NODE_TYPE_EOF
:
3350 case WS_XML_NODE_TYPE_BOF
:
3354 ERR( "unknown node type %u\n", node_type(writer
->current
) );
3355 return E_INVALIDARG
;
3359 static HRESULT
write_tree( struct writer
*writer
)
3363 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3366 if (node_type( writer
->current
) == WS_XML_NODE_TYPE_EOF
) break;
3367 if (move_to_child_node( &writer
->current
))
3369 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3372 if (move_to_next_node( &writer
->current
))
3374 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3377 if (!move_to_parent_node( &writer
->current
) || !move_to_next_node( &writer
->current
))
3379 ERR( "invalid tree\n" );
3380 return WS_E_INVALID_FORMAT
;
3382 if ((hr
= write_tree_node( writer
)) != S_OK
) return hr
;
3387 static void write_rewind( struct writer
*writer
)
3389 writer
->write_pos
= 0;
3390 writer
->current
= writer
->root
;
3391 writer
->state
= WRITER_STATE_INITIAL
;
3394 /**************************************************************************
3395 * WsCopyNode [webservices.@]
3397 HRESULT WINAPI
WsCopyNode( WS_XML_WRITER
*handle
, WS_XML_READER
*reader
, WS_ERROR
*error
)
3399 struct writer
*writer
= (struct writer
*)handle
;
3400 struct node
*parent
, *current
, *node
= NULL
;
3403 TRACE( "%p %p %p\n", handle
, reader
, error
);
3404 if (error
) FIXME( "ignoring error parameter\n" );
3406 if (!writer
) return E_INVALIDARG
;
3408 EnterCriticalSection( &writer
->cs
);
3410 if (writer
->magic
!= WRITER_MAGIC
)
3412 LeaveCriticalSection( &writer
->cs
);
3413 return E_INVALIDARG
;
3416 if (!(parent
= find_parent( writer
)))
3418 LeaveCriticalSection( &writer
->cs
);
3419 return WS_E_INVALID_FORMAT
;
3422 if ((hr
= copy_node( reader
, &node
)) != S_OK
) goto done
;
3423 current
= writer
->current
;
3424 write_insert_node( writer
, parent
, node
);
3426 write_rewind( writer
);
3427 if ((hr
= write_tree( writer
)) != S_OK
) goto done
;
3428 writer
->current
= current
;
3431 LeaveCriticalSection( &writer
->cs
);
3435 static HRESULT
write_param( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
)
3437 return write_type_struct_field( writer
, desc
, value
, 0 );
3440 static ULONG
get_array_len( const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, ULONG index
, const void **args
)
3443 for (i
= 0; i
< count
; i
++)
3445 if (params
[i
].inputMessageIndex
!= index
|| params
[i
].parameterType
!= WS_PARAMETER_TYPE_ARRAY_COUNT
)
3447 if (args
[i
]) ret
= *(const ULONG
*)args
[i
];
3453 static HRESULT
write_param_array( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
, const void *value
,
3456 return write_type_repeating_element( writer
, desc
, value
, len
);
3459 HRESULT
write_input_params( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
3460 const WS_PARAMETER_DESCRIPTION
*params
, ULONG count
, const void **args
)
3462 struct writer
*writer
= (struct writer
*)handle
;
3463 const WS_STRUCT_DESCRIPTION
*desc_struct
;
3464 const WS_FIELD_DESCRIPTION
*desc_field
;
3468 if (desc
->type
!= WS_STRUCT_TYPE
|| !(desc_struct
= desc
->typeDescription
)) return E_INVALIDARG
;
3470 EnterCriticalSection( &writer
->cs
);
3472 if (writer
->magic
!= WRITER_MAGIC
)
3474 LeaveCriticalSection( &writer
->cs
);
3475 return E_INVALIDARG
;
3478 if ((hr
= write_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
) goto done
;
3480 for (i
= 0; i
< count
; i
++)
3482 if (params
[i
].inputMessageIndex
== INVALID_PARAMETER_INDEX
) continue;
3483 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_MESSAGES
)
3485 FIXME( "messages type not supported\n" );
3489 if ((hr
= get_param_desc( desc_struct
, params
[i
].inputMessageIndex
, &desc_field
)) != S_OK
) goto done
;
3490 if (params
[i
].parameterType
== WS_PARAMETER_TYPE_NORMAL
)
3492 if ((hr
= write_param( writer
, desc_field
, args
[i
] )) != S_OK
) goto done
;
3494 else if (params
[i
].parameterType
== WS_PARAMETER_TYPE_ARRAY
)
3496 const void *ptr
= *(const void **)args
[i
];
3497 ULONG len
= get_array_len( params
, count
, params
[i
].inputMessageIndex
, args
);
3498 if ((hr
= write_param_array( writer
, desc_field
, ptr
, len
)) != S_OK
) goto done
;
3502 hr
= write_endelement_node( writer
);
3505 LeaveCriticalSection( &writer
->cs
);