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
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "wine/unicode.h"
29 #include "webservices_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
33 static const struct prop_desc writer_props
[] =
35 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
36 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
37 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
38 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
39 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INDENT */
40 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
41 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_WRITER_PROPERTY_CHARSET */
42 { sizeof(WS_BUFFERS
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFERS */
43 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
44 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BYTES */
45 { sizeof(BOOL
), TRUE
}, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
46 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
47 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
48 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
49 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
50 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
51 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
52 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
53 { sizeof(BOOL
), FALSE
} /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
59 WRITER_STATE_STARTELEMENT
,
60 WRITER_STATE_STARTENDELEMENT
,
61 WRITER_STATE_STARTATTRIBUTE
,
62 WRITER_STATE_STARTCDATA
,
63 WRITER_STATE_ENDSTARTELEMENT
,
65 WRITER_STATE_ENDELEMENT
,
72 unsigned char *write_bufptr
;
73 enum writer_state state
;
76 WS_XML_STRING
*current_ns
;
77 WS_XML_WRITER_OUTPUT_TYPE output_type
;
78 struct xmlbuf
*output_buf
;
81 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
84 static struct writer
*alloc_writer(void)
86 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
88 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
90 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
91 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
92 ret
->prop_count
= count
;
96 static void free_writer( struct writer
*writer
)
98 destroy_nodes( writer
->root
);
99 heap_free( writer
->current_ns
);
100 WsFreeHeap( writer
->output_heap
);
104 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
106 if (!writer
->root
) writer
->root
= eof
;
109 eof
->parent
= writer
->root
;
110 list_add_tail( &writer
->root
->children
, &eof
->entry
);
112 writer
->current
= eof
;
115 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
117 writer
->root
->parent
= bof
;
118 list_add_tail( &bof
->children
, &writer
->root
->entry
);
119 writer
->current
= writer
->root
= bof
;
122 static void write_insert_node( struct writer
*writer
, struct node
*node
)
124 node
->parent
= writer
->current
;
125 if (writer
->current
== writer
->root
)
127 struct list
*eof
= list_tail( &writer
->root
->children
);
128 list_add_before( eof
, &node
->entry
);
130 else list_add_tail( &writer
->current
->children
, &node
->entry
);
131 writer
->current
= node
;
134 static HRESULT
write_init_state( struct writer
*writer
)
138 heap_free( writer
->current_ns
);
139 writer
->current_ns
= NULL
;
140 destroy_nodes( writer
->root
);
143 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
144 write_insert_eof( writer
, node
);
145 writer
->state
= WRITER_STATE_INITIAL
;
149 /**************************************************************************
150 * WsCreateWriter [webservices.@]
152 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
153 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
155 struct writer
*writer
;
156 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
157 WS_CHARSET charset
= WS_CHARSET_UTF8
;
160 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
161 if (error
) FIXME( "ignoring error parameter\n" );
163 if (!handle
) return E_INVALIDARG
;
164 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
166 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
167 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
168 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
169 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
170 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
171 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
172 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
174 for (i
= 0; i
< count
; i
++)
176 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
177 properties
[i
].valueSize
);
180 free_writer( writer
);
185 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
186 &max_size
, sizeof(max_size
) );
189 free_writer( writer
);
193 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
196 free_writer( writer
);
200 hr
= write_init_state( writer
);
203 free_writer( writer
);
207 *handle
= (WS_XML_WRITER
*)writer
;
211 /**************************************************************************
212 * WsFreeWriter [webservices.@]
214 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
216 struct writer
*writer
= (struct writer
*)handle
;
218 TRACE( "%p\n", handle
);
219 free_writer( writer
);
222 #define XML_BUFFER_INITIAL_ALLOCATED_SIZE 256
223 static struct xmlbuf
*alloc_xmlbuf( WS_HEAP
*heap
)
227 if (!(ret
= ws_alloc( heap
, sizeof(*ret
) ))) return NULL
;
228 if (!(ret
->ptr
= ws_alloc( heap
, XML_BUFFER_INITIAL_ALLOCATED_SIZE
)))
230 ws_free( heap
, ret
);
234 ret
->size_allocated
= XML_BUFFER_INITIAL_ALLOCATED_SIZE
;
239 static void free_xmlbuf( struct xmlbuf
*xmlbuf
)
242 ws_free( xmlbuf
->heap
, xmlbuf
->ptr
);
243 ws_free( xmlbuf
->heap
, xmlbuf
);
246 /**************************************************************************
247 * WsCreateXmlBuffer [webservices.@]
249 HRESULT WINAPI
WsCreateXmlBuffer( WS_HEAP
*heap
, const WS_XML_BUFFER_PROPERTY
*properties
,
250 ULONG count
, WS_XML_BUFFER
**handle
, WS_ERROR
*error
)
252 struct xmlbuf
*xmlbuf
;
254 if (!heap
|| !handle
) return E_INVALIDARG
;
255 if (count
) FIXME( "properties not implemented\n" );
257 if (!(xmlbuf
= alloc_xmlbuf( heap
))) return E_OUTOFMEMORY
;
259 *handle
= (WS_XML_BUFFER
*)xmlbuf
;
263 /**************************************************************************
264 * WsGetWriterProperty [webservices.@]
266 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
267 void *buf
, ULONG size
, WS_ERROR
*error
)
269 struct writer
*writer
= (struct writer
*)handle
;
271 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
272 if (error
) FIXME( "ignoring error parameter\n" );
274 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
278 case WS_XML_WRITER_PROPERTY_BYTES
:
280 WS_BYTES
*bytes
= buf
;
281 if (size
!= sizeof(*bytes
)) return E_INVALIDARG
;
282 bytes
->bytes
= writer
->output_buf
->ptr
;
283 bytes
->length
= writer
->output_buf
->size
;
287 return prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
291 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
293 /* free current buffer if it's ours */
294 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
296 free_xmlbuf( writer
->output_buf
);
298 writer
->output_buf
= xmlbuf
;
299 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
300 writer
->write_bufptr
= xmlbuf
->ptr
;
301 writer
->write_pos
= 0;
304 /**************************************************************************
305 * WsSetOutput [webservices.@]
307 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
308 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
309 ULONG count
, WS_ERROR
*error
)
311 struct writer
*writer
= (struct writer
*)handle
;
316 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
317 if (error
) FIXME( "ignoring error parameter\n" );
319 if (!writer
) return E_INVALIDARG
;
321 for (i
= 0; i
< count
; i
++)
323 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
324 properties
[i
].valueSize
);
325 if (hr
!= S_OK
) return hr
;
328 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
330 switch (encoding
->encodingType
)
332 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
334 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
335 if (text
->charSet
!= WS_CHARSET_UTF8
)
337 FIXME( "charset %u not supported\n", text
->charSet
);
343 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
346 switch (output
->outputType
)
348 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
350 struct xmlbuf
*xmlbuf
;
352 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
))) return E_OUTOFMEMORY
;
353 set_output_buffer( writer
, xmlbuf
);
357 FIXME( "output type %u not supported\n", output
->outputType
);
361 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
362 write_insert_bof( writer
, node
);
366 /**************************************************************************
367 * WsSetOutputToBuffer [webservices.@]
369 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
370 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
373 struct writer
*writer
= (struct writer
*)handle
;
374 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
379 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
380 if (error
) FIXME( "ignoring error parameter\n" );
382 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
384 for (i
= 0; i
< count
; i
++)
386 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
387 properties
[i
].valueSize
);
388 if (hr
!= S_OK
) return hr
;
391 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
392 set_output_buffer( writer
, xmlbuf
);
394 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
395 write_insert_bof( writer
, node
);
399 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
401 struct xmlbuf
*buf
= writer
->output_buf
;
405 if (buf
->size_allocated
>= writer
->write_pos
+ size
)
407 buf
->size
= writer
->write_pos
+ size
;
410 new_size
= max( buf
->size_allocated
* 2, writer
->write_pos
+ size
);
411 if (!(tmp
= ws_realloc( buf
->heap
, buf
->ptr
, new_size
))) return E_OUTOFMEMORY
;
412 writer
->write_bufptr
= buf
->ptr
= tmp
;
413 buf
->size_allocated
= new_size
;
414 buf
->size
= writer
->write_pos
+ size
;
418 static inline void write_char( struct writer
*writer
, unsigned char ch
)
420 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
423 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
425 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
426 writer
->write_pos
+= len
;
429 static HRESULT
write_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
431 WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)attr
->value
;
432 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
433 const WS_XML_STRING
*prefix
;
437 if (attr
->prefix
) prefix
= attr
->prefix
;
438 else prefix
= writer
->current
->hdr
.prefix
;
440 /* ' prefix:attr="value"' */
442 size
= attr
->localName
->length
+ 4 /* ' =""' */;
443 if (prefix
) size
+= prefix
->length
+ 1 /* ':' */;
444 if (text
) size
+= text
->value
.length
;
445 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
447 write_char( writer
, ' ' );
450 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
451 write_char( writer
, ':' );
453 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
454 write_char( writer
, '=' );
455 write_char( writer
, quote
);
456 if (text
) write_bytes( writer
, text
->value
.bytes
, text
->value
.length
);
457 write_char( writer
, quote
);
462 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
464 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
467 /**************************************************************************
468 * WsGetPrefixFromNamespace [webservices.@]
470 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
471 BOOL required
, const WS_XML_STRING
**prefix
,
474 struct writer
*writer
= (struct writer
*)handle
;
475 WS_XML_ELEMENT_NODE
*elem
;
478 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
479 if (error
) FIXME( "ignoring error parameter\n" );
481 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
483 elem
= &writer
->current
->hdr
;
484 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
486 *prefix
= elem
->prefix
;
491 if (required
) return WS_E_INVALID_FORMAT
;
498 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
501 if (!(str
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
502 heap_free( writer
->current_ns
);
503 writer
->current_ns
= str
;
507 static HRESULT
write_namespace_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
509 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
513 /* ' xmlns:prefix="namespace"' */
515 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
516 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
517 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
519 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
522 write_char( writer
, ':' );
523 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
525 write_char( writer
, '=' );
526 write_char( writer
, quote
);
527 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
528 write_char( writer
, quote
);
533 static HRESULT
write_startelement( struct writer
*writer
)
535 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
539 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
541 size
= elem
->localName
->length
+ 1 /* '<' */;
542 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
543 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
545 write_char( writer
, '<' );
548 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
549 write_char( writer
, ':' );
551 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
552 for (i
= 0; i
< elem
->attributeCount
; i
++)
554 if (elem
->attributes
[i
]->isXmlNs
) continue;
555 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
557 for (i
= 0; i
< elem
->attributeCount
; i
++)
559 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
560 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
562 for (i
= 0; i
< elem
->attributeCount
; i
++)
564 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
565 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
571 static struct node
*write_find_parent_element( struct writer
*writer
)
573 struct node
*node
= writer
->current
;
575 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
576 if (node_type( node
->parent
) == WS_XML_NODE_TYPE_ELEMENT
) return node
->parent
;
580 static HRESULT
write_endelement( struct writer
*writer
)
582 struct node
*node
= write_find_parent_element( writer
);
583 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
587 if (!elem
) return WS_E_INVALID_FORMAT
;
589 /* '</prefix:localname>' */
591 size
= elem
->localName
->length
+ 3 /* '</>' */;
592 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
593 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
595 write_char( writer
, '<' );
596 write_char( writer
, '/' );
599 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
600 write_char( writer
, ':' );
602 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
603 write_char( writer
, '>' );
607 static HRESULT
write_add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
608 const WS_XML_STRING
*ns
, BOOL single
)
610 WS_XML_ATTRIBUTE
*attr
;
611 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
614 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
616 attr
->singleQuote
= !!single
;
618 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
620 free_attribute( attr
);
621 return E_OUTOFMEMORY
;
623 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
625 free_attribute( attr
);
626 return E_OUTOFMEMORY
;
628 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
630 free_attribute( attr
);
636 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
637 const WS_XML_STRING
*ns
)
640 const struct node
*node
;
642 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
644 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
647 for (i
= 0; i
< elem
->attributeCount
; i
++)
649 if (!elem
->attributes
[i
]->isXmlNs
) continue;
650 if (WsXmlStringEquals( elem
->attributes
[i
]->prefix
, prefix
, NULL
) == S_OK
&&
651 WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) == S_OK
)
660 static HRESULT
write_set_element_namespace( struct writer
*writer
)
662 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
665 if (!elem
->ns
->length
|| is_current_namespace( writer
, elem
->ns
) ||
666 namespace_in_scope( elem
, elem
->prefix
, elem
->ns
)) return S_OK
;
668 if ((hr
= write_add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
)
671 return set_current_namespace( writer
, elem
->ns
);
674 static HRESULT
write_endstartelement( struct writer
*writer
)
677 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
678 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
679 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
680 write_char( writer
, '>' );
684 /**************************************************************************
685 * WsWriteEndAttribute [webservices.@]
687 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
689 struct writer
*writer
= (struct writer
*)handle
;
691 TRACE( "%p %p\n", handle
, error
);
692 if (error
) FIXME( "ignoring error parameter\n" );
694 if (!writer
) return E_INVALIDARG
;
696 writer
->state
= WRITER_STATE_STARTELEMENT
;
700 static HRESULT
write_close_element( struct writer
*writer
)
704 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
707 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
708 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
709 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) return hr
;
710 write_char( writer
, '/' );
711 write_char( writer
, '>' );
713 writer
->current
= writer
->current
->parent
;
714 writer
->state
= WRITER_STATE_STARTENDELEMENT
;
719 struct node
*node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
);
720 if (!node
) return E_OUTOFMEMORY
;
722 /* '</prefix:localname>' */
723 if ((hr
= write_endelement( writer
)) != S_OK
)
729 write_insert_node( writer
, node
);
730 writer
->current
= node
->parent
;
731 writer
->state
= WRITER_STATE_ENDELEMENT
;
734 return WS_E_INVALID_OPERATION
;
737 /**************************************************************************
738 * WsWriteEndElement [webservices.@]
740 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
742 struct writer
*writer
= (struct writer
*)handle
;
744 TRACE( "%p %p\n", handle
, error
);
745 if (error
) FIXME( "ignoring error parameter\n" );
747 if (!writer
) return E_INVALIDARG
;
749 return write_close_element( writer
);
752 /**************************************************************************
753 * WsWriteEndStartElement [webservices.@]
755 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
757 struct writer
*writer
= (struct writer
*)handle
;
760 TRACE( "%p %p\n", handle
, error
);
761 if (error
) FIXME( "ignoring error parameter\n" );
763 if (!writer
) return E_INVALIDARG
;
764 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
766 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
767 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
771 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
772 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
775 WS_XML_ATTRIBUTE
*attr
;
776 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
779 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
781 if (!prefix
) prefix
= elem
->prefix
;
783 attr
->singleQuote
= !!single
;
784 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
786 free_attribute( attr
);
787 return E_OUTOFMEMORY
;
789 if (!(attr
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
791 free_attribute( attr
);
792 return E_OUTOFMEMORY
;
794 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
796 free_attribute( attr
);
797 return E_OUTOFMEMORY
;
799 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
801 free_attribute( attr
);
804 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
808 /**************************************************************************
809 * WsWriteStartAttribute [webservices.@]
811 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
812 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
813 BOOL single
, WS_ERROR
*error
)
815 struct writer
*writer
= (struct writer
*)handle
;
817 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
818 debugstr_xmlstr(ns
), single
, error
);
819 if (error
) FIXME( "ignoring error parameter\n" );
821 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
823 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
825 return write_add_attribute( writer
, prefix
, localname
, ns
, single
);
828 /**************************************************************************
829 * WsWriteStartCData [webservices.@]
831 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
833 struct writer
*writer
= (struct writer
*)handle
;
836 TRACE( "%p %p\n", handle
, error
);
837 if (error
) FIXME( "ignoring error parameter\n" );
839 if (!writer
) return E_INVALIDARG
;
841 /* flush current start element if necessary */
842 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& ((hr
= write_endstartelement( writer
)) != S_OK
))
845 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
846 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
847 writer
->state
= WRITER_STATE_STARTCDATA
;
851 /**************************************************************************
852 * WsWriteEndCData [webservices.@]
854 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
856 struct writer
*writer
= (struct writer
*)handle
;
859 TRACE( "%p %p\n", handle
, error
);
860 if (error
) FIXME( "ignoring error parameter\n" );
862 if (!writer
) return E_INVALIDARG
;
863 if (writer
->state
!= WRITER_STATE_STARTCDATA
) return WS_E_INVALID_OPERATION
;
865 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
866 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
867 writer
->state
= WRITER_STATE_ENDCDATA
;
871 /* flush current start element if necessary */
872 static HRESULT
write_flush( struct writer
*writer
)
874 if (writer
->state
== WRITER_STATE_STARTELEMENT
) return write_endstartelement( writer
);
878 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
879 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
882 WS_XML_ELEMENT_NODE
*elem
;
885 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
887 if (!prefix
&& node_type( writer
->current
) == WS_XML_NODE_TYPE_ELEMENT
)
888 prefix
= writer
->current
->hdr
.prefix
;
890 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
893 if (prefix
&& !(elem
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
896 return E_OUTOFMEMORY
;
898 if (!(elem
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
901 return E_OUTOFMEMORY
;
903 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
906 return E_OUTOFMEMORY
;
908 write_insert_node( writer
, node
);
909 writer
->state
= WRITER_STATE_STARTELEMENT
;
913 /**************************************************************************
914 * WsWriteStartElement [webservices.@]
916 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
917 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
920 struct writer
*writer
= (struct writer
*)handle
;
922 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
923 debugstr_xmlstr(ns
), error
);
924 if (error
) FIXME( "ignoring error parameter\n" );
926 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
928 return write_add_element_node( writer
, prefix
, localname
, ns
);
931 static inline void write_set_attribute_value( struct writer
*writer
, WS_XML_TEXT
*text
)
933 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
934 elem
->attributes
[elem
->attributeCount
- 1]->value
= text
;
937 /**************************************************************************
938 * WsWriteText [webservices.@]
940 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
942 struct writer
*writer
= (struct writer
*)handle
;
943 WS_XML_UTF8_TEXT
*dst
, *src
= (WS_XML_UTF8_TEXT
*)text
;
946 TRACE( "%p %p %p\n", handle
, text
, error
);
948 if (!writer
|| !text
) return E_INVALIDARG
;
950 if (text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
952 FIXME( "text type %u not supported\n", text
->textType
);
956 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
)
958 if (!(dst
= alloc_utf8_text( src
->value
.bytes
, src
->value
.length
)))
959 return E_OUTOFMEMORY
;
961 write_set_attribute_value( writer
, &dst
->text
);
965 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
966 if ((hr
= write_grow_buffer( writer
, src
->value
.length
)) != S_OK
) return hr
;
967 write_bytes( writer
, src
->value
.bytes
, src
->value
.length
);
973 static WS_XML_TEXT
*widechar_to_xmltext( const WCHAR
*src
, WS_XML_TEXT_TYPE type
)
977 case WS_XML_TEXT_TYPE_UTF8
:
979 WS_XML_UTF8_TEXT
*text
;
980 int len
= WideCharToMultiByte( CP_UTF8
, 0, src
, -1, NULL
, 0, NULL
, NULL
) - 1;
981 if (!(text
= alloc_utf8_text( NULL
, len
))) return NULL
;
982 WideCharToMultiByte( CP_UTF8
, 0, src
, -1, (char *)text
->value
.bytes
, text
->value
.length
, NULL
, NULL
);
986 FIXME( "unhandled type %u\n", type
);
991 static WS_XML_UTF8_TEXT
*format_bool( const BOOL
*ptr
)
993 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
994 if (*ptr
) return alloc_utf8_text( bool_true
, sizeof(bool_true
) );
995 else return alloc_utf8_text( bool_false
, sizeof(bool_false
) );
998 static WS_XML_UTF8_TEXT
*format_int8( const INT8
*ptr
)
1000 char buf
[5]; /* "-128" */
1001 int len
= wsprintfA( buf
, "%d", *ptr
);
1002 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1005 static WS_XML_UTF8_TEXT
*format_int16( const INT16
*ptr
)
1007 char buf
[7]; /* "-32768" */
1008 int len
= wsprintfA( buf
, "%d", *ptr
);
1009 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1012 static WS_XML_UTF8_TEXT
*format_int32( const INT32
*ptr
)
1014 char buf
[12]; /* "-2147483648" */
1015 int len
= wsprintfA( buf
, "%d", *ptr
);
1016 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1019 static WS_XML_UTF8_TEXT
*format_int64( const INT64
*ptr
)
1021 char buf
[21]; /* "-9223372036854775808" */
1022 int len
= wsprintfA( buf
, "%I64d", *ptr
);
1023 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1026 static WS_XML_UTF8_TEXT
*format_uint8( const UINT8
*ptr
)
1028 char buf
[4]; /* "255" */
1029 int len
= wsprintfA( buf
, "%u", *ptr
);
1030 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1033 static WS_XML_UTF8_TEXT
*format_uint16( const UINT16
*ptr
)
1035 char buf
[6]; /* "65535" */
1036 int len
= wsprintfA( buf
, "%u", *ptr
);
1037 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1040 static WS_XML_UTF8_TEXT
*format_uint32( const UINT32
*ptr
)
1042 char buf
[11]; /* "4294967295" */
1043 int len
= wsprintfA( buf
, "%u", *ptr
);
1044 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1047 static WS_XML_UTF8_TEXT
*format_uint64( const UINT64
*ptr
)
1049 char buf
[21]; /* "18446744073709551615" */
1050 int len
= wsprintfA( buf
, "%I64u", *ptr
);
1051 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1054 static HRESULT
write_add_text_node( struct writer
*writer
, WS_XML_TEXT
*value
)
1057 WS_XML_TEXT_NODE
*text
;
1059 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
1060 text
= (WS_XML_TEXT_NODE
*)node
;
1063 write_insert_node( writer
, node
);
1064 writer
->state
= WRITER_STATE_TEXT
;
1068 static HRESULT
write_text_node( struct writer
*writer
)
1071 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
1072 WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)node
->text
;
1074 if ((hr
= write_grow_buffer( writer
, text
->value
.length
)) != S_OK
) return hr
;
1075 write_bytes( writer
, text
->value
.bytes
, text
->value
.length
);
1079 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1086 case WS_ELEMENT_TYPE_MAPPING
:
1087 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1088 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
1089 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
1090 return write_text_node( writer
);
1092 case WS_ATTRIBUTE_TYPE_MAPPING
:
1093 write_set_attribute_value( writer
, text
);
1096 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1097 switch (writer
->state
)
1099 case WRITER_STATE_STARTATTRIBUTE
:
1100 write_set_attribute_value( writer
, text
);
1103 case WRITER_STATE_STARTELEMENT
:
1104 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
1105 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
1106 return write_text_node( writer
);
1109 FIXME( "writer state %u not handled\n", writer
->state
);
1114 FIXME( "mapping %u not implemented\n", mapping
);
1119 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1120 const WS_BOOL_DESCRIPTION
*desc
, const BOOL
*value
)
1122 WS_XML_UTF8_TEXT
*text
;
1127 FIXME( "description not supported\n" );
1130 if (!(text
= format_bool( value
))) return E_OUTOFMEMORY
;
1131 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1136 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1137 const WS_INT8_DESCRIPTION
*desc
, const INT8
*value
)
1139 WS_XML_UTF8_TEXT
*text
;
1144 FIXME( "description not supported\n" );
1147 if (!(text
= format_int8( value
))) return E_OUTOFMEMORY
;
1148 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1153 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1154 const WS_INT16_DESCRIPTION
*desc
, const INT16
*value
)
1156 WS_XML_UTF8_TEXT
*text
;
1161 FIXME( "description not supported\n" );
1164 if (!(text
= format_int16( value
))) return E_OUTOFMEMORY
;
1165 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1170 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1171 const WS_INT32_DESCRIPTION
*desc
, const INT32
*value
)
1173 WS_XML_UTF8_TEXT
*text
;
1178 FIXME( "description not supported\n" );
1181 if (!(text
= format_int32( value
))) return E_OUTOFMEMORY
;
1182 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1187 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1188 const WS_INT64_DESCRIPTION
*desc
, const INT64
*value
)
1190 WS_XML_UTF8_TEXT
*text
;
1195 FIXME( "description not supported\n" );
1198 if (!(text
= format_int64( value
))) return E_OUTOFMEMORY
;
1199 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1204 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1205 const WS_UINT8_DESCRIPTION
*desc
, const UINT8
*value
)
1207 WS_XML_UTF8_TEXT
*text
;
1212 FIXME( "description not supported\n" );
1215 if (!(text
= format_uint8( value
))) return E_OUTOFMEMORY
;
1216 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1221 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1222 const WS_UINT16_DESCRIPTION
*desc
, const UINT16
*value
)
1224 WS_XML_UTF8_TEXT
*text
;
1229 FIXME( "description not supported\n" );
1232 if (!(text
= format_uint16( value
))) return E_OUTOFMEMORY
;
1233 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1238 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1239 const WS_UINT32_DESCRIPTION
*desc
, const UINT32
*value
)
1241 WS_XML_UTF8_TEXT
*text
;
1246 FIXME( "description not supported\n" );
1249 if (!(text
= format_uint32( value
))) return E_OUTOFMEMORY
;
1250 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1255 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1256 const WS_UINT64_DESCRIPTION
*desc
, const UINT64
*value
)
1258 WS_XML_UTF8_TEXT
*text
;
1263 FIXME( "description not supported\n" );
1266 if (!(text
= format_uint64( value
))) return E_OUTOFMEMORY
;
1267 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1272 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1273 const WS_WSZ_DESCRIPTION
*desc
, const WCHAR
*value
)
1280 FIXME( "description not supported\n" );
1283 if (!(text
= widechar_to_xmltext( value
, WS_XML_TEXT_TYPE_UTF8
))) return E_OUTOFMEMORY
;
1284 if ((hr
= write_type_text( writer
, mapping
, text
)) == S_OK
) return S_OK
;
1289 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
1290 const void *, ULONG
);
1292 static HRESULT
write_type_struct_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
1293 const void *value
, ULONG size
)
1296 WS_TYPE_MAPPING mapping
;
1297 WS_WRITE_OPTION option
;
1299 if (!desc
->options
|| desc
->options
== WS_FIELD_OPTIONAL
) option
= 0;
1300 else if (desc
->options
== WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
1303 FIXME( "options 0x%x not supported\n", desc
->options
);
1307 switch (desc
->mapping
)
1309 case WS_ATTRIBUTE_FIELD_MAPPING
:
1310 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
1311 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
1314 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1317 case WS_ELEMENT_FIELD_MAPPING
:
1318 if ((hr
= write_add_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
)
1321 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1324 case WS_TEXT_FIELD_MAPPING
:
1325 switch (writer
->state
)
1327 case WRITER_STATE_STARTELEMENT
:
1328 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
1331 case WRITER_STATE_STARTATTRIBUTE
:
1332 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1336 FIXME( "unhandled writer state %u\n", writer
->state
);
1342 FIXME( "field mapping %u not supported\n", desc
->mapping
);
1346 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, value
, size
)) != S_OK
)
1351 case WS_ATTRIBUTE_TYPE_MAPPING
:
1352 writer
->state
= WRITER_STATE_STARTELEMENT
;
1355 case WS_ELEMENT_TYPE_MAPPING
:
1356 if ((hr
= write_close_element( writer
)) != S_OK
) return hr
;
1365 static ULONG
get_field_size( const WS_STRUCT_DESCRIPTION
*desc
, ULONG index
)
1367 if (index
< desc
->fieldCount
- 1) return desc
->fields
[index
+ 1]->offset
- desc
->fields
[index
]->offset
;
1368 return desc
->size
- desc
->fields
[index
]->offset
;
1371 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1372 const WS_STRUCT_DESCRIPTION
*desc
, const void *value
)
1378 if (!desc
) return E_INVALIDARG
;
1380 if (desc
->structOptions
)
1382 FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
1386 for (i
= 0; i
< desc
->fieldCount
; i
++)
1388 ptr
= (const char *)value
+ desc
->fields
[i
]->offset
;
1389 size
= get_field_size( desc
, i
);
1390 if ((hr
= write_type_struct_field( writer
, desc
->fields
[i
], ptr
, size
)) != S_OK
)
1397 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1398 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
1403 case WS_STRUCT_TYPE
:
1405 const void * const *ptr
= value
;
1407 if (!desc
|| (option
&& option
!= WS_WRITE_REQUIRED_POINTER
) || size
!= sizeof(*ptr
))
1408 return E_INVALIDARG
;
1410 return write_type_struct( writer
, mapping
, desc
, *ptr
);
1414 const BOOL
*ptr
= value
;
1415 if (option
!= WS_WRITE_REQUIRED_VALUE
|| size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1416 return write_type_bool( writer
, mapping
, desc
, ptr
);
1420 const INT8
*ptr
= value
;
1421 if (option
!= WS_WRITE_REQUIRED_VALUE
|| size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1422 return write_type_int8( writer
, mapping
, desc
, ptr
);
1426 const INT16
*ptr
= value
;
1427 if (option
!= WS_WRITE_REQUIRED_VALUE
|| size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1428 return write_type_int16( writer
, mapping
, desc
, ptr
);
1432 const INT32
*ptr
= value
;
1433 if (option
!= WS_WRITE_REQUIRED_VALUE
|| size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1434 return write_type_int32( writer
, mapping
, desc
, ptr
);
1438 const INT64
*ptr
= value
;
1439 if (option
!= WS_WRITE_REQUIRED_VALUE
|| size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1440 return write_type_int64( writer
, mapping
, desc
, ptr
);
1444 const UINT8
*ptr
= value
;
1445 if (option
!= WS_WRITE_REQUIRED_VALUE
|| size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1446 return write_type_uint8( writer
, mapping
, desc
, ptr
);
1448 case WS_UINT16_TYPE
:
1450 const UINT16
*ptr
= value
;
1451 if (option
!= WS_WRITE_REQUIRED_VALUE
|| size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1452 return write_type_uint16( writer
, mapping
, desc
, ptr
);
1454 case WS_UINT32_TYPE
:
1456 const UINT32
*ptr
= value
;
1457 if (option
!= WS_WRITE_REQUIRED_VALUE
|| size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1458 return write_type_uint32( writer
, mapping
, desc
, ptr
);
1460 case WS_UINT64_TYPE
:
1462 const UINT64
*ptr
= value
;
1463 if (option
!= WS_WRITE_REQUIRED_VALUE
|| size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1464 return write_type_uint64( writer
, mapping
, desc
, ptr
);
1468 const WCHAR
* const *ptr
= value
;
1469 if ((option
&& option
!= WS_WRITE_REQUIRED_POINTER
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1470 return write_type_wsz( writer
, mapping
, desc
, *ptr
);
1473 FIXME( "type %u not supported\n", type
);
1478 /**************************************************************************
1479 * WsWriteAttribute [webservices.@]
1481 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
1482 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
1485 struct writer
*writer
= (struct writer
*)handle
;
1488 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
1489 if (error
) FIXME( "ignoring error parameter\n" );
1491 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
1492 return E_INVALIDARG
;
1494 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
1496 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
,
1497 FALSE
)) != S_OK
) return hr
;
1499 return write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
1500 option
, value
, size
);
1503 /**************************************************************************
1504 * WsWriteElement [webservices.@]
1506 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
1507 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
1510 struct writer
*writer
= (struct writer
*)handle
;
1513 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
1514 if (error
) FIXME( "ignoring error parameter\n" );
1516 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
1517 return E_INVALIDARG
;
1519 if ((hr
= write_add_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
)
1522 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
1523 option
, value
, size
)) != S_OK
) return hr
;
1525 return write_close_element( writer
);
1528 /**************************************************************************
1529 * WsWriteType [webservices.@]
1531 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1532 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
1533 ULONG size
, WS_ERROR
*error
)
1535 struct writer
*writer
= (struct writer
*)handle
;
1538 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
1540 if (error
) FIXME( "ignoring error parameter\n" );
1542 if (!writer
|| !value
) return E_INVALIDARG
;
1546 case WS_ATTRIBUTE_TYPE_MAPPING
:
1547 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) return WS_E_INVALID_FORMAT
;
1548 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1551 case WS_ELEMENT_TYPE_MAPPING
:
1552 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1553 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_FORMAT
;
1554 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1557 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1558 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1562 FIXME( "mapping %u not implemented\n", mapping
);
1569 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
1573 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
1574 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
1575 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
1576 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
1577 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
1578 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
1579 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
1580 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
1581 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
1582 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
1583 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
1584 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
1585 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
1586 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
1587 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
1589 FIXME( "unhandled type %u\n", type
);
1594 /**************************************************************************
1595 * WsWriteValue [webservices.@]
1597 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
1598 ULONG size
, WS_ERROR
*error
)
1600 struct writer
*writer
= (struct writer
*)handle
;
1601 WS_TYPE_MAPPING mapping
;
1604 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
1605 if (error
) FIXME( "ignoring error parameter\n" );
1607 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
1609 switch (writer
->state
)
1611 case WRITER_STATE_STARTATTRIBUTE
:
1612 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1615 case WRITER_STATE_STARTELEMENT
:
1616 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1620 return WS_E_INVALID_FORMAT
;
1623 return write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
1626 /**************************************************************************
1627 * WsWriteXmlBuffer [webservices.@]
1629 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
1631 struct writer
*writer
= (struct writer
*)handle
;
1632 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1635 TRACE( "%p %p %p\n", handle
, buffer
, error
);
1636 if (error
) FIXME( "ignoring error parameter\n" );
1638 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
1640 if ((hr
= write_grow_buffer( writer
, xmlbuf
->size
)) != S_OK
) return hr
;
1641 write_bytes( writer
, xmlbuf
->ptr
, xmlbuf
->size
);
1645 /**************************************************************************
1646 * WsWriteXmlBufferToBytes [webservices.@]
1648 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
1649 const WS_XML_WRITER_ENCODING
*encoding
,
1650 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
1651 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
1653 struct writer
*writer
= (struct writer
*)handle
;
1654 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1659 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
1660 bytes
, size
, error
);
1661 if (error
) FIXME( "ignoring error parameter\n" );
1663 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
1665 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
1667 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
1671 for (i
= 0; i
< count
; i
++)
1673 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
1674 properties
[i
].valueSize
);
1675 if (hr
!= S_OK
) return hr
;
1678 if (!(buf
= ws_alloc( heap
, xmlbuf
->size
))) return WS_E_QUOTA_EXCEEDED
;
1679 memcpy( buf
, xmlbuf
->ptr
, xmlbuf
->size
);
1684 /**************************************************************************
1685 * WsWriteXmlnsAttribute [webservices.@]
1687 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1688 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
1690 struct writer
*writer
= (struct writer
*)handle
;
1692 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
1694 if (error
) FIXME( "ignoring error parameter\n" );
1696 if (!writer
|| !ns
) return E_INVALIDARG
;
1697 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
1699 if (namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
)) return S_OK
;
1700 return write_add_namespace_attribute( writer
, prefix
, ns
, single
);