quartz: Fix a typo in an ERR() message.
[wine.git] / dlls / webservices / writer.c
blob20e17d0165637aaa6a01ce1b5edb5fa69d2741fa
1 /*
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
19 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winuser.h"
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 */
56 enum writer_state
58 WRITER_STATE_INITIAL,
59 WRITER_STATE_STARTELEMENT,
60 WRITER_STATE_STARTENDELEMENT,
61 WRITER_STATE_STARTATTRIBUTE,
62 WRITER_STATE_STARTCDATA,
63 WRITER_STATE_ENDSTARTELEMENT,
64 WRITER_STATE_TEXT,
65 WRITER_STATE_ENDELEMENT,
66 WRITER_STATE_ENDCDATA
69 struct writer
71 ULONG write_pos;
72 unsigned char *write_bufptr;
73 enum writer_state state;
74 struct node *root;
75 struct node *current;
76 WS_XML_STRING *current_ns;
77 WS_XML_WRITER_OUTPUT_TYPE output_type;
78 struct xmlbuf *output_buf;
79 WS_HEAP *output_heap;
80 ULONG prop_count;
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]);
87 struct writer *ret;
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;
93 return ret;
96 static void free_writer( struct writer *writer )
98 destroy_nodes( writer->root );
99 heap_free( writer->current_ns );
100 WsFreeHeap( writer->output_heap );
101 heap_free( writer );
104 static void write_insert_eof( struct writer *writer, struct node *eof )
106 if (!writer->root) writer->root = eof;
107 else
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 )
136 struct node *node;
138 heap_free( writer->current_ns );
139 writer->current_ns = NULL;
140 destroy_nodes( writer->root );
141 writer->root = NULL;
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;
146 return S_OK;
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;
158 HRESULT hr;
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 );
178 if (hr != S_OK)
180 free_writer( writer );
181 return hr;
185 hr = prop_get( writer->prop, writer->prop_count, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE,
186 &max_size, sizeof(max_size) );
187 if (hr != S_OK)
189 free_writer( writer );
190 return hr;
193 hr = WsCreateHeap( max_size, 0, NULL, 0, &writer->output_heap, NULL );
194 if (hr != S_OK)
196 free_writer( writer );
197 return hr;
200 hr = write_init_state( writer );
201 if (hr != S_OK)
203 free_writer( writer );
204 return hr;
207 *handle = (WS_XML_WRITER *)writer;
208 return S_OK;
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 )
225 struct xmlbuf *ret;
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 );
231 return NULL;
233 ret->heap = heap;
234 ret->size_allocated = XML_BUFFER_INITIAL_ALLOCATED_SIZE;
235 ret->size = 0;
236 return ret;
239 static void free_xmlbuf( struct xmlbuf *xmlbuf )
241 if (!xmlbuf) return;
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;
260 return S_OK;
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;
276 switch (id)
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;
284 return S_OK;
286 default:
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;
312 struct node *node;
313 HRESULT hr;
314 ULONG i;
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 );
338 return E_NOTIMPL;
340 break;
342 default:
343 FIXME( "encoding type %u not supported\n", encoding->encodingType );
344 return E_NOTIMPL;
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 );
354 break;
356 default:
357 FIXME( "output type %u not supported\n", output->outputType );
358 return E_NOTIMPL;
361 if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
362 write_insert_bof( writer, node );
363 return S_OK;
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,
371 WS_ERROR *error )
373 struct writer *writer = (struct writer *)handle;
374 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
375 struct node *node;
376 HRESULT hr;
377 ULONG i;
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 );
396 return S_OK;
399 static HRESULT write_grow_buffer( struct writer *writer, ULONG size )
401 struct xmlbuf *buf = writer->output_buf;
402 SIZE_T new_size;
403 void *tmp;
405 if (buf->size_allocated >= writer->write_pos + size)
407 buf->size = writer->write_pos + size;
408 return S_OK;
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;
415 return S_OK;
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;
434 ULONG size;
435 HRESULT hr;
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, ' ' );
448 if (prefix)
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 );
459 return S_OK;
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,
472 WS_ERROR *error )
474 struct writer *writer = (struct writer *)handle;
475 WS_XML_ELEMENT_NODE *elem;
476 BOOL found = FALSE;
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;
487 found = TRUE;
489 if (!found)
491 if (required) return WS_E_INVALID_FORMAT;
492 *prefix = NULL;
493 return S_FALSE;
495 return S_OK;
498 static HRESULT set_current_namespace( struct writer *writer, const WS_XML_STRING *ns )
500 WS_XML_STRING *str;
501 if (!(str = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
502 heap_free( writer->current_ns );
503 writer->current_ns = str;
504 return S_OK;
507 static HRESULT write_namespace_attribute( struct writer *writer, WS_XML_ATTRIBUTE *attr )
509 unsigned char quote = attr->singleQuote ? '\'' : '"';
510 ULONG size;
511 HRESULT hr;
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 );
520 if (attr->prefix)
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 );
530 return S_OK;
533 static HRESULT write_startelement( struct writer *writer )
535 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
536 ULONG size, i;
537 HRESULT hr;
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, '<' );
546 if (elem->prefix)
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;
568 return S_OK;
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;
577 return NULL;
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;
584 ULONG size;
585 HRESULT hr;
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, '/' );
597 if (elem->prefix)
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, '>' );
604 return S_OK;
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;
612 HRESULT hr;
614 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
616 attr->singleQuote = !!single;
617 attr->isXmlNs = 1;
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 );
631 return hr;
633 return S_OK;
636 static const WS_XML_ATTRIBUTE *find_namespace_attribute( const WS_XML_ELEMENT_NODE *elem,
637 const WS_XML_STRING *prefix,
638 const WS_XML_STRING *ns )
640 ULONG i;
641 for (i = 0; i < elem->attributeCount; i++)
643 if (!elem->attributes[i]->isXmlNs) continue;
644 if (WsXmlStringEquals( elem->attributes[i]->prefix, prefix, NULL ) == S_OK &&
645 WsXmlStringEquals( elem->attributes[i]->ns, ns, NULL ) == S_OK)
647 return elem->attributes[i];
650 return NULL;
653 static HRESULT write_set_element_namespace( struct writer *writer )
655 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
656 HRESULT hr;
658 if (!elem->ns->length || is_current_namespace( writer, elem->ns ) ||
659 find_namespace_attribute( elem, elem->prefix, elem->ns )) return S_OK;
661 if ((hr = write_add_namespace_attribute( writer, elem->prefix, elem->ns, FALSE )) != S_OK)
662 return hr;
664 return set_current_namespace( writer, elem->ns );
667 static HRESULT write_endstartelement( struct writer *writer )
669 HRESULT hr;
670 if ((hr = write_set_element_namespace( writer )) != S_OK) return hr;
671 if ((hr = write_startelement( writer )) != S_OK) return hr;
672 if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
673 write_char( writer, '>' );
674 return S_OK;
677 /**************************************************************************
678 * WsWriteEndAttribute [webservices.@]
680 HRESULT WINAPI WsWriteEndAttribute( WS_XML_WRITER *handle, WS_ERROR *error )
682 struct writer *writer = (struct writer *)handle;
684 TRACE( "%p %p\n", handle, error );
685 if (error) FIXME( "ignoring error parameter\n" );
687 if (!writer) return E_INVALIDARG;
689 writer->state = WRITER_STATE_STARTELEMENT;
690 return S_OK;
693 static HRESULT write_close_element( struct writer *writer )
695 HRESULT hr;
697 if (writer->state == WRITER_STATE_STARTELEMENT)
699 /* '/>' */
700 if ((hr = write_set_element_namespace( writer )) != S_OK) return hr;
701 if ((hr = write_startelement( writer )) != S_OK) return hr;
702 if ((hr = write_grow_buffer( writer, 2 )) != S_OK) return hr;
703 write_char( writer, '/' );
704 write_char( writer, '>' );
706 writer->current = writer->current->parent;
707 writer->state = WRITER_STATE_STARTENDELEMENT;
708 return S_OK;
710 else
712 struct node *node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT );
713 if (!node) return E_OUTOFMEMORY;
715 /* '</prefix:localname>' */
716 if ((hr = write_endelement( writer )) != S_OK)
718 free_node( node );
719 return hr;
722 write_insert_node( writer, node );
723 writer->current = node->parent;
724 writer->state = WRITER_STATE_ENDELEMENT;
725 return S_OK;
727 return WS_E_INVALID_OPERATION;
730 /**************************************************************************
731 * WsWriteEndElement [webservices.@]
733 HRESULT WINAPI WsWriteEndElement( WS_XML_WRITER *handle, WS_ERROR *error )
735 struct writer *writer = (struct writer *)handle;
737 TRACE( "%p %p\n", handle, error );
738 if (error) FIXME( "ignoring error parameter\n" );
740 if (!writer) return E_INVALIDARG;
742 return write_close_element( writer );
745 /**************************************************************************
746 * WsWriteEndStartElement [webservices.@]
748 HRESULT WINAPI WsWriteEndStartElement( WS_XML_WRITER *handle, WS_ERROR *error )
750 struct writer *writer = (struct writer *)handle;
751 HRESULT hr;
753 TRACE( "%p %p\n", handle, error );
754 if (error) FIXME( "ignoring error parameter\n" );
756 if (!writer) return E_INVALIDARG;
757 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
759 if ((hr = write_endstartelement( writer )) != S_OK) return hr;
760 writer->state = WRITER_STATE_ENDSTARTELEMENT;
761 return S_OK;
764 static HRESULT write_add_attribute( struct writer *writer, const WS_XML_STRING *prefix,
765 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
766 BOOL single )
768 WS_XML_ATTRIBUTE *attr;
769 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
770 HRESULT hr;
772 if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
774 if (!prefix) prefix = elem->prefix;
776 attr->singleQuote = !!single;
777 if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
779 free_attribute( attr );
780 return E_OUTOFMEMORY;
782 if (!(attr->localName = alloc_xml_string( localname->bytes, localname->length )))
784 free_attribute( attr );
785 return E_OUTOFMEMORY;
787 if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
789 free_attribute( attr );
790 return E_OUTOFMEMORY;
792 if ((hr = append_attribute( elem, attr )) != S_OK)
794 free_attribute( attr );
795 return hr;
797 writer->state = WRITER_STATE_STARTATTRIBUTE;
798 return S_OK;
801 /**************************************************************************
802 * WsWriteStartAttribute [webservices.@]
804 HRESULT WINAPI WsWriteStartAttribute( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
805 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
806 BOOL single, WS_ERROR *error )
808 struct writer *writer = (struct writer *)handle;
810 TRACE( "%p %s %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
811 debugstr_xmlstr(ns), single, error );
812 if (error) FIXME( "ignoring error parameter\n" );
814 if (!writer || !localname || !ns) return E_INVALIDARG;
816 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
818 return write_add_attribute( writer, prefix, localname, ns, single );
821 /**************************************************************************
822 * WsWriteStartCData [webservices.@]
824 HRESULT WINAPI WsWriteStartCData( WS_XML_WRITER *handle, WS_ERROR *error )
826 struct writer *writer = (struct writer *)handle;
827 HRESULT hr;
829 TRACE( "%p %p\n", handle, error );
830 if (error) FIXME( "ignoring error parameter\n" );
832 if (!writer) return E_INVALIDARG;
834 /* flush current start element if necessary */
835 if (writer->state == WRITER_STATE_STARTELEMENT && ((hr = write_endstartelement( writer )) != S_OK))
836 return hr;
838 if ((hr = write_grow_buffer( writer, 9 )) != S_OK) return hr;
839 write_bytes( writer, (const BYTE *)"<![CDATA[", 9 );
840 writer->state = WRITER_STATE_STARTCDATA;
841 return S_OK;
844 /**************************************************************************
845 * WsWriteEndCData [webservices.@]
847 HRESULT WINAPI WsWriteEndCData( WS_XML_WRITER *handle, WS_ERROR *error )
849 struct writer *writer = (struct writer *)handle;
850 HRESULT hr;
852 TRACE( "%p %p\n", handle, error );
853 if (error) FIXME( "ignoring error parameter\n" );
855 if (!writer) return E_INVALIDARG;
856 if (writer->state != WRITER_STATE_STARTCDATA) return WS_E_INVALID_OPERATION;
858 if ((hr = write_grow_buffer( writer, 3 )) != S_OK) return hr;
859 write_bytes( writer, (const BYTE *)"]]>", 3 );
860 writer->state = WRITER_STATE_ENDCDATA;
861 return S_OK;
864 /* flush current start element if necessary */
865 static HRESULT write_flush( struct writer *writer )
867 if (writer->state == WRITER_STATE_STARTELEMENT) return write_endstartelement( writer );
868 return S_OK;
871 static HRESULT write_add_element_node( struct writer *writer, const WS_XML_STRING *prefix,
872 const WS_XML_STRING *localname, const WS_XML_STRING *ns )
874 struct node *node;
875 WS_XML_ELEMENT_NODE *elem;
876 HRESULT hr;
878 if ((hr = write_flush( writer )) != S_OK) return hr;
880 if (!prefix && node_type( writer->current ) == WS_XML_NODE_TYPE_ELEMENT)
881 prefix = writer->current->hdr.prefix;
883 if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
884 elem = &node->hdr;
886 if (prefix && !(elem->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
888 free_node( node );
889 return E_OUTOFMEMORY;
891 if (!(elem->localName = alloc_xml_string( localname->bytes, localname->length )))
893 free_node( node );
894 return E_OUTOFMEMORY;
896 if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length )))
898 free_node( node );
899 return E_OUTOFMEMORY;
901 write_insert_node( writer, node );
902 writer->state = WRITER_STATE_STARTELEMENT;
903 return S_OK;
906 /**************************************************************************
907 * WsWriteStartElement [webservices.@]
909 HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
910 const WS_XML_STRING *localname, const WS_XML_STRING *ns,
911 WS_ERROR *error )
913 struct writer *writer = (struct writer *)handle;
915 TRACE( "%p %s %s %s %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
916 debugstr_xmlstr(ns), error );
917 if (error) FIXME( "ignoring error parameter\n" );
919 if (!writer || !localname || !ns) return E_INVALIDARG;
921 return write_add_element_node( writer, prefix, localname, ns );
924 static inline void write_set_attribute_value( struct writer *writer, WS_XML_TEXT *text )
926 WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
927 elem->attributes[elem->attributeCount - 1]->value = text;
930 /**************************************************************************
931 * WsWriteText [webservices.@]
933 HRESULT WINAPI WsWriteText( WS_XML_WRITER *handle, const WS_XML_TEXT *text, WS_ERROR *error )
935 struct writer *writer = (struct writer *)handle;
936 WS_XML_UTF8_TEXT *dst, *src = (WS_XML_UTF8_TEXT *)text;
937 HRESULT hr;
939 TRACE( "%p %p %p\n", handle, text, error );
941 if (!writer || !text) return E_INVALIDARG;
943 if (text->textType != WS_XML_TEXT_TYPE_UTF8)
945 FIXME( "text type %u not supported\n", text->textType );
946 return E_NOTIMPL;
949 if (writer->state == WRITER_STATE_STARTATTRIBUTE)
951 if (!(dst = alloc_utf8_text( src->value.bytes, src->value.length )))
952 return E_OUTOFMEMORY;
954 write_set_attribute_value( writer, &dst->text );
956 else
958 if ((hr = write_flush( writer )) != S_OK) return hr;
959 if ((hr = write_grow_buffer( writer, src->value.length )) != S_OK) return hr;
960 write_bytes( writer, src->value.bytes, src->value.length );
963 return S_OK;
966 static WS_XML_TEXT *widechar_to_xmltext( const WCHAR *src, WS_XML_TEXT_TYPE type )
968 switch (type)
970 case WS_XML_TEXT_TYPE_UTF8:
972 WS_XML_UTF8_TEXT *text;
973 int len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL ) - 1;
974 if (!(text = alloc_utf8_text( NULL, len ))) return NULL;
975 WideCharToMultiByte( CP_UTF8, 0, src, -1, (char *)text->value.bytes, text->value.length, NULL, NULL );
976 return &text->text;
978 default:
979 FIXME( "unhandled type %u\n", type );
980 return NULL;
984 static WS_XML_UTF8_TEXT *format_bool( const BOOL *ptr )
986 static const unsigned char bool_true[] = {'t','r','u','e'}, bool_false[] = {'f','a','l','s','e'};
987 if (*ptr) return alloc_utf8_text( bool_true, sizeof(bool_true) );
988 else return alloc_utf8_text( bool_false, sizeof(bool_false) );
991 static WS_XML_UTF8_TEXT *format_int8( const INT8 *ptr )
993 char buf[5]; /* "-128" */
994 int len = wsprintfA( buf, "%d", *ptr );
995 return alloc_utf8_text( (const unsigned char *)buf, len );
998 static WS_XML_UTF8_TEXT *format_int16( const INT16 *ptr )
1000 char buf[7]; /* "-32768" */
1001 int len = wsprintfA( buf, "%d", *ptr );
1002 return alloc_utf8_text( (const unsigned char *)buf, len );
1005 static WS_XML_UTF8_TEXT *format_int32( const INT32 *ptr )
1007 char buf[12]; /* "-2147483648" */
1008 int len = wsprintfA( buf, "%d", *ptr );
1009 return alloc_utf8_text( (const unsigned char *)buf, len );
1012 static WS_XML_UTF8_TEXT *format_int64( const INT64 *ptr )
1014 char buf[21]; /* "-9223372036854775808" */
1015 int len = wsprintfA( buf, "%I64d", *ptr );
1016 return alloc_utf8_text( (const unsigned char *)buf, len );
1019 static WS_XML_UTF8_TEXT *format_uint8( const UINT8 *ptr )
1021 char buf[4]; /* "255" */
1022 int len = wsprintfA( buf, "%u", *ptr );
1023 return alloc_utf8_text( (const unsigned char *)buf, len );
1026 static WS_XML_UTF8_TEXT *format_uint16( const UINT16 *ptr )
1028 char buf[6]; /* "65535" */
1029 int len = wsprintfA( buf, "%u", *ptr );
1030 return alloc_utf8_text( (const unsigned char *)buf, len );
1033 static WS_XML_UTF8_TEXT *format_uint32( const UINT32 *ptr )
1035 char buf[11]; /* "4294967295" */
1036 int len = wsprintfA( buf, "%u", *ptr );
1037 return alloc_utf8_text( (const unsigned char *)buf, len );
1040 static WS_XML_UTF8_TEXT *format_uint64( const UINT64 *ptr )
1042 char buf[21]; /* "18446744073709551615" */
1043 int len = wsprintfA( buf, "%I64u", *ptr );
1044 return alloc_utf8_text( (const unsigned char *)buf, len );
1047 static HRESULT write_add_text_node( struct writer *writer, WS_XML_TEXT *value )
1049 struct node *node;
1050 WS_XML_TEXT_NODE *text;
1052 if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
1053 text = (WS_XML_TEXT_NODE *)node;
1054 text->text = value;
1056 write_insert_node( writer, node );
1057 writer->state = WRITER_STATE_TEXT;
1058 return S_OK;
1061 static HRESULT write_text_node( struct writer *writer )
1063 HRESULT hr;
1064 WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)writer->current;
1065 WS_XML_UTF8_TEXT *text = (WS_XML_UTF8_TEXT *)node->text;
1067 if ((hr = write_grow_buffer( writer, text->value.length )) != S_OK) return hr;
1068 write_bytes( writer, text->value.bytes, text->value.length );
1069 return S_OK;
1072 static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping,
1073 WS_XML_TEXT *text )
1075 HRESULT hr;
1077 switch (mapping)
1079 case WS_ELEMENT_TYPE_MAPPING:
1080 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1081 if ((hr = write_endstartelement( writer )) != S_OK) return hr;
1082 if ((hr = write_add_text_node( writer, text )) != S_OK) return hr;
1083 return write_text_node( writer );
1085 case WS_ATTRIBUTE_TYPE_MAPPING:
1086 write_set_attribute_value( writer, text );
1087 return S_OK;
1089 case WS_ANY_ELEMENT_TYPE_MAPPING:
1090 switch (writer->state)
1092 case WRITER_STATE_STARTATTRIBUTE:
1093 write_set_attribute_value( writer, text );
1094 return S_OK;
1096 case WRITER_STATE_STARTELEMENT:
1097 if ((hr = write_endstartelement( writer )) != S_OK) return hr;
1098 if ((hr = write_add_text_node( writer, text )) != S_OK) return hr;
1099 return write_text_node( writer );
1101 default:
1102 FIXME( "writer state %u not handled\n", writer->state );
1103 return E_NOTIMPL;
1106 default:
1107 FIXME( "mapping %u not implemented\n", mapping );
1108 return E_NOTIMPL;
1112 static HRESULT write_type_bool( struct writer *writer, WS_TYPE_MAPPING mapping,
1113 const WS_BOOL_DESCRIPTION *desc, const BOOL *value )
1115 WS_XML_UTF8_TEXT *text;
1116 HRESULT hr;
1118 if (desc)
1120 FIXME( "description not supported\n" );
1121 return E_NOTIMPL;
1123 if (!(text = format_bool( value ))) return E_OUTOFMEMORY;
1124 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1125 heap_free( text );
1126 return hr;
1129 static HRESULT write_type_int8( struct writer *writer, WS_TYPE_MAPPING mapping,
1130 const WS_INT8_DESCRIPTION *desc, const INT8 *value )
1132 WS_XML_UTF8_TEXT *text;
1133 HRESULT hr;
1135 if (desc)
1137 FIXME( "description not supported\n" );
1138 return E_NOTIMPL;
1140 if (!(text = format_int8( value ))) return E_OUTOFMEMORY;
1141 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1142 heap_free( text );
1143 return hr;
1146 static HRESULT write_type_int16( struct writer *writer, WS_TYPE_MAPPING mapping,
1147 const WS_INT16_DESCRIPTION *desc, const INT16 *value )
1149 WS_XML_UTF8_TEXT *text;
1150 HRESULT hr;
1152 if (desc)
1154 FIXME( "description not supported\n" );
1155 return E_NOTIMPL;
1157 if (!(text = format_int16( value ))) return E_OUTOFMEMORY;
1158 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1159 heap_free( text );
1160 return hr;
1163 static HRESULT write_type_int32( struct writer *writer, WS_TYPE_MAPPING mapping,
1164 const WS_INT32_DESCRIPTION *desc, const INT32 *value )
1166 WS_XML_UTF8_TEXT *text;
1167 HRESULT hr;
1169 if (desc)
1171 FIXME( "description not supported\n" );
1172 return E_NOTIMPL;
1174 if (!(text = format_int32( value ))) return E_OUTOFMEMORY;
1175 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1176 heap_free( text );
1177 return hr;
1180 static HRESULT write_type_int64( struct writer *writer, WS_TYPE_MAPPING mapping,
1181 const WS_INT64_DESCRIPTION *desc, const INT64 *value )
1183 WS_XML_UTF8_TEXT *text;
1184 HRESULT hr;
1186 if (desc)
1188 FIXME( "description not supported\n" );
1189 return E_NOTIMPL;
1191 if (!(text = format_int64( value ))) return E_OUTOFMEMORY;
1192 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1193 heap_free( text );
1194 return hr;
1197 static HRESULT write_type_uint8( struct writer *writer, WS_TYPE_MAPPING mapping,
1198 const WS_UINT8_DESCRIPTION *desc, const UINT8 *value )
1200 WS_XML_UTF8_TEXT *text;
1201 HRESULT hr;
1203 if (desc)
1205 FIXME( "description not supported\n" );
1206 return E_NOTIMPL;
1208 if (!(text = format_uint8( value ))) return E_OUTOFMEMORY;
1209 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1210 heap_free( text );
1211 return hr;
1214 static HRESULT write_type_uint16( struct writer *writer, WS_TYPE_MAPPING mapping,
1215 const WS_UINT16_DESCRIPTION *desc, const UINT16 *value )
1217 WS_XML_UTF8_TEXT *text;
1218 HRESULT hr;
1220 if (desc)
1222 FIXME( "description not supported\n" );
1223 return E_NOTIMPL;
1225 if (!(text = format_uint16( value ))) return E_OUTOFMEMORY;
1226 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1227 heap_free( text );
1228 return hr;
1231 static HRESULT write_type_uint32( struct writer *writer, WS_TYPE_MAPPING mapping,
1232 const WS_UINT32_DESCRIPTION *desc, const UINT32 *value )
1234 WS_XML_UTF8_TEXT *text;
1235 HRESULT hr;
1237 if (desc)
1239 FIXME( "description not supported\n" );
1240 return E_NOTIMPL;
1242 if (!(text = format_uint32( value ))) return E_OUTOFMEMORY;
1243 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1244 heap_free( text );
1245 return hr;
1248 static HRESULT write_type_uint64( struct writer *writer, WS_TYPE_MAPPING mapping,
1249 const WS_UINT64_DESCRIPTION *desc, const UINT64 *value )
1251 WS_XML_UTF8_TEXT *text;
1252 HRESULT hr;
1254 if (desc)
1256 FIXME( "description not supported\n" );
1257 return E_NOTIMPL;
1259 if (!(text = format_uint64( value ))) return E_OUTOFMEMORY;
1260 if ((hr = write_type_text( writer, mapping, &text->text )) == S_OK) return S_OK;
1261 heap_free( text );
1262 return hr;
1265 static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
1266 const WS_WSZ_DESCRIPTION *desc, const WCHAR *value )
1268 WS_XML_TEXT *text;
1269 HRESULT hr;
1271 if (desc)
1273 FIXME( "description not supported\n" );
1274 return E_NOTIMPL;
1276 if (!(text = widechar_to_xmltext( value, WS_XML_TEXT_TYPE_UTF8 ))) return E_OUTOFMEMORY;
1277 if ((hr = write_type_text( writer, mapping, text )) == S_OK) return S_OK;
1278 heap_free( text );
1279 return hr;
1282 static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION,
1283 const void *, ULONG );
1285 static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DESCRIPTION *desc,
1286 const void *value, ULONG size )
1288 HRESULT hr;
1289 WS_TYPE_MAPPING mapping;
1290 WS_WRITE_OPTION option;
1292 if (!desc->options || desc->options == WS_FIELD_OPTIONAL) option = 0;
1293 else if (desc->options == WS_FIELD_POINTER) option = WS_WRITE_REQUIRED_POINTER;
1294 else
1296 FIXME( "options 0x%x not supported\n", desc->options );
1297 return E_NOTIMPL;
1300 switch (desc->mapping)
1302 case WS_ATTRIBUTE_FIELD_MAPPING:
1303 if (!desc->localName || !desc->ns) return E_INVALIDARG;
1304 if ((hr = write_add_attribute( writer, NULL, desc->localName, desc->ns, FALSE )) != S_OK)
1305 return hr;
1307 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
1308 break;
1310 case WS_ELEMENT_FIELD_MAPPING:
1311 if ((hr = write_add_element_node( writer, NULL, desc->localName, desc->ns )) != S_OK)
1312 return hr;
1314 mapping = WS_ELEMENT_TYPE_MAPPING;
1315 break;
1317 case WS_TEXT_FIELD_MAPPING:
1318 switch (writer->state)
1320 case WRITER_STATE_STARTELEMENT:
1321 mapping = WS_ELEMENT_CONTENT_TYPE_MAPPING;
1322 break;
1324 case WRITER_STATE_STARTATTRIBUTE:
1325 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
1326 break;
1328 default:
1329 FIXME( "unhandled writer state %u\n", writer->state );
1330 return E_NOTIMPL;
1332 break;
1334 default:
1335 FIXME( "field mapping %u not supported\n", desc->mapping );
1336 return E_NOTIMPL;
1339 if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, value, size )) != S_OK)
1340 return hr;
1342 switch (mapping)
1344 case WS_ATTRIBUTE_TYPE_MAPPING:
1345 writer->state = WRITER_STATE_STARTELEMENT;
1346 break;
1348 case WS_ELEMENT_TYPE_MAPPING:
1349 if ((hr = write_close_element( writer )) != S_OK) return hr;
1350 break;
1352 default: break;
1355 return S_OK;
1358 static ULONG get_field_size( const WS_STRUCT_DESCRIPTION *desc, ULONG index )
1360 if (index < desc->fieldCount - 1) return desc->fields[index + 1]->offset - desc->fields[index]->offset;
1361 return desc->size - desc->fields[index]->offset;
1364 static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping,
1365 const WS_STRUCT_DESCRIPTION *desc, const void *value )
1367 ULONG i, size;
1368 HRESULT hr;
1369 const char *ptr;
1371 if (!desc) return E_INVALIDARG;
1373 if (desc->structOptions)
1375 FIXME( "struct options 0x%x not supported\n", desc->structOptions );
1376 return E_NOTIMPL;
1379 for (i = 0; i < desc->fieldCount; i++)
1381 ptr = (const char *)value + desc->fields[i]->offset;
1382 size = get_field_size( desc, i );
1383 if ((hr = write_type_struct_field( writer, desc->fields[i], ptr, size )) != S_OK)
1384 return hr;
1387 return S_OK;
1390 static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TYPE type,
1391 const void *desc, WS_WRITE_OPTION option, const void *value,
1392 ULONG size )
1394 switch (type)
1396 case WS_STRUCT_TYPE:
1398 const void * const *ptr = value;
1400 if (!desc || (option && option != WS_WRITE_REQUIRED_POINTER) || size != sizeof(*ptr))
1401 return E_INVALIDARG;
1403 return write_type_struct( writer, mapping, desc, *ptr );
1405 case WS_BOOL_TYPE:
1407 const BOOL *ptr = value;
1408 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1409 return write_type_bool( writer, mapping, desc, ptr );
1411 case WS_INT8_TYPE:
1413 const INT8 *ptr = value;
1414 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1415 return write_type_int8( writer, mapping, desc, ptr );
1417 case WS_INT16_TYPE:
1419 const INT16 *ptr = value;
1420 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1421 return write_type_int16( writer, mapping, desc, ptr );
1423 case WS_INT32_TYPE:
1425 const INT32 *ptr = value;
1426 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1427 return write_type_int32( writer, mapping, desc, ptr );
1429 case WS_INT64_TYPE:
1431 const INT64 *ptr = value;
1432 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1433 return write_type_int64( writer, mapping, desc, ptr );
1435 case WS_UINT8_TYPE:
1437 const UINT8 *ptr = value;
1438 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1439 return write_type_uint8( writer, mapping, desc, ptr );
1441 case WS_UINT16_TYPE:
1443 const UINT16 *ptr = value;
1444 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1445 return write_type_uint16( writer, mapping, desc, ptr );
1447 case WS_UINT32_TYPE:
1449 const UINT32 *ptr = value;
1450 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1451 return write_type_uint32( writer, mapping, desc, ptr );
1453 case WS_UINT64_TYPE:
1455 const UINT64 *ptr = value;
1456 if (option != WS_WRITE_REQUIRED_VALUE || size != sizeof(*ptr)) return E_INVALIDARG;
1457 return write_type_uint64( writer, mapping, desc, ptr );
1459 case WS_WSZ_TYPE:
1461 const WCHAR * const *ptr = value;
1462 if ((option && option != WS_WRITE_REQUIRED_POINTER) || size != sizeof(*ptr)) return E_INVALIDARG;
1463 return write_type_wsz( writer, mapping, desc, *ptr );
1465 default:
1466 FIXME( "type %u not supported\n", type );
1467 return E_NOTIMPL;
1471 /**************************************************************************
1472 * WsWriteAttribute [webservices.@]
1474 HRESULT WINAPI WsWriteAttribute( WS_XML_WRITER *handle, const WS_ATTRIBUTE_DESCRIPTION *desc,
1475 WS_WRITE_OPTION option, const void *value, ULONG size,
1476 WS_ERROR *error )
1478 struct writer *writer = (struct writer *)handle;
1479 HRESULT hr;
1481 TRACE( "%p %p %u %p %u %p\n", handle, desc, option, value, size, error );
1482 if (error) FIXME( "ignoring error parameter\n" );
1484 if (!writer || !desc || !desc->attributeLocalName || !desc->attributeNs || !value)
1485 return E_INVALIDARG;
1487 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
1489 if ((hr = write_add_attribute( writer, NULL, desc->attributeLocalName, desc->attributeNs,
1490 FALSE )) != S_OK) return hr;
1492 return write_type( writer, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->typeDescription,
1493 option, value, size );
1496 /**************************************************************************
1497 * WsWriteElement [webservices.@]
1499 HRESULT WINAPI WsWriteElement( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTION *desc,
1500 WS_WRITE_OPTION option, const void *value, ULONG size,
1501 WS_ERROR *error )
1503 struct writer *writer = (struct writer *)handle;
1504 HRESULT hr;
1506 TRACE( "%p %p %u %p %u %p\n", handle, desc, option, value, size, error );
1507 if (error) FIXME( "ignoring error parameter\n" );
1509 if (!writer || !desc || !desc->elementLocalName || !desc->elementNs || !value)
1510 return E_INVALIDARG;
1512 if ((hr = write_add_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK)
1513 return hr;
1515 if ((hr = write_type( writer, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription,
1516 option, value, size )) != S_OK) return hr;
1518 return write_close_element( writer );
1521 /**************************************************************************
1522 * WsWriteType [webservices.@]
1524 HRESULT WINAPI WsWriteType( WS_XML_WRITER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
1525 const void *desc, WS_WRITE_OPTION option, const void *value,
1526 ULONG size, WS_ERROR *error )
1528 struct writer *writer = (struct writer *)handle;
1529 HRESULT hr;
1531 TRACE( "%p %u %u %p %u %p %u %p\n", handle, mapping, type, desc, option, value,
1532 size, error );
1533 if (error) FIXME( "ignoring error parameter\n" );
1535 if (!writer || !value) return E_INVALIDARG;
1537 switch (mapping)
1539 case WS_ATTRIBUTE_TYPE_MAPPING:
1540 if (writer->state != WRITER_STATE_STARTATTRIBUTE) return WS_E_INVALID_FORMAT;
1541 hr = write_type( writer, mapping, type, desc, option, value, size );
1542 break;
1544 case WS_ELEMENT_TYPE_MAPPING:
1545 case WS_ELEMENT_CONTENT_TYPE_MAPPING:
1546 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_FORMAT;
1547 hr = write_type( writer, mapping, type, desc, option, value, size );
1548 break;
1550 case WS_ANY_ELEMENT_TYPE_MAPPING:
1551 hr = write_type( writer, mapping, type, desc, option, value, size );
1552 break;
1554 default:
1555 FIXME( "mapping %u not implemented\n", mapping );
1556 return E_NOTIMPL;
1559 return hr;
1562 WS_TYPE map_value_type( WS_VALUE_TYPE type )
1564 switch (type)
1566 case WS_BOOL_VALUE_TYPE: return WS_BOOL_TYPE;
1567 case WS_INT8_VALUE_TYPE: return WS_INT8_TYPE;
1568 case WS_INT16_VALUE_TYPE: return WS_INT16_TYPE;
1569 case WS_INT32_VALUE_TYPE: return WS_INT32_TYPE;
1570 case WS_INT64_VALUE_TYPE: return WS_INT64_TYPE;
1571 case WS_UINT8_VALUE_TYPE: return WS_UINT8_TYPE;
1572 case WS_UINT16_VALUE_TYPE: return WS_UINT16_TYPE;
1573 case WS_UINT32_VALUE_TYPE: return WS_UINT32_TYPE;
1574 case WS_UINT64_VALUE_TYPE: return WS_UINT64_TYPE;
1575 case WS_FLOAT_VALUE_TYPE: return WS_FLOAT_TYPE;
1576 case WS_DOUBLE_VALUE_TYPE: return WS_DOUBLE_TYPE;
1577 case WS_DECIMAL_VALUE_TYPE: return WS_DECIMAL_TYPE;
1578 case WS_DATETIME_VALUE_TYPE: return WS_DATETIME_TYPE;
1579 case WS_TIMESPAN_VALUE_TYPE: return WS_TIMESPAN_TYPE;
1580 case WS_GUID_VALUE_TYPE: return WS_GUID_TYPE;
1581 default:
1582 FIXME( "unhandled type %u\n", type );
1583 return ~0u;
1587 /**************************************************************************
1588 * WsWriteValue [webservices.@]
1590 HRESULT WINAPI WsWriteValue( WS_XML_WRITER *handle, WS_VALUE_TYPE value_type, const void *value,
1591 ULONG size, WS_ERROR *error )
1593 struct writer *writer = (struct writer *)handle;
1594 WS_TYPE_MAPPING mapping;
1595 WS_TYPE type;
1597 TRACE( "%p %u %p %u %p\n", handle, value_type, value, size, error );
1598 if (error) FIXME( "ignoring error parameter\n" );
1600 if (!writer || !value || (type = map_value_type( value_type )) == ~0u) return E_INVALIDARG;
1602 switch (writer->state)
1604 case WRITER_STATE_STARTATTRIBUTE:
1605 mapping = WS_ATTRIBUTE_TYPE_MAPPING;
1606 break;
1608 case WRITER_STATE_STARTELEMENT:
1609 mapping = WS_ELEMENT_TYPE_MAPPING;
1610 break;
1612 default:
1613 return WS_E_INVALID_FORMAT;
1616 return write_type( writer, mapping, type, NULL, WS_WRITE_REQUIRED_VALUE, value, size );
1619 /**************************************************************************
1620 * WsWriteXmlBuffer [webservices.@]
1622 HRESULT WINAPI WsWriteXmlBuffer( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer, WS_ERROR *error )
1624 struct writer *writer = (struct writer *)handle;
1625 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
1626 HRESULT hr;
1628 TRACE( "%p %p %p\n", handle, buffer, error );
1629 if (error) FIXME( "ignoring error parameter\n" );
1631 if (!writer || !xmlbuf) return E_INVALIDARG;
1633 if ((hr = write_grow_buffer( writer, xmlbuf->size )) != S_OK) return hr;
1634 write_bytes( writer, xmlbuf->ptr, xmlbuf->size );
1635 return S_OK;
1638 /**************************************************************************
1639 * WsWriteXmlBufferToBytes [webservices.@]
1641 HRESULT WINAPI WsWriteXmlBufferToBytes( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer,
1642 const WS_XML_WRITER_ENCODING *encoding,
1643 const WS_XML_WRITER_PROPERTY *properties, ULONG count,
1644 WS_HEAP *heap, void **bytes, ULONG *size, WS_ERROR *error )
1646 struct writer *writer = (struct writer *)handle;
1647 struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
1648 HRESULT hr;
1649 char *buf;
1650 ULONG i;
1652 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle, buffer, encoding, properties, count, heap,
1653 bytes, size, error );
1654 if (error) FIXME( "ignoring error parameter\n" );
1656 if (!writer || !xmlbuf || !heap || !bytes) return E_INVALIDARG;
1658 if (encoding && encoding->encodingType != WS_XML_WRITER_ENCODING_TYPE_TEXT)
1660 FIXME( "encoding type %u not supported\n", encoding->encodingType );
1661 return E_NOTIMPL;
1664 for (i = 0; i < count; i++)
1666 hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value,
1667 properties[i].valueSize );
1668 if (hr != S_OK) return hr;
1671 if (!(buf = ws_alloc( heap, xmlbuf->size ))) return WS_E_QUOTA_EXCEEDED;
1672 memcpy( buf, xmlbuf->ptr, xmlbuf->size );
1673 *bytes = buf;
1674 return S_OK;
1677 /**************************************************************************
1678 * WsWriteXmlnsAttribute [webservices.@]
1680 HRESULT WINAPI WsWriteXmlnsAttribute( WS_XML_WRITER *handle, const WS_XML_STRING *prefix,
1681 const WS_XML_STRING *ns, BOOL single, WS_ERROR *error )
1683 struct writer *writer = (struct writer *)handle;
1685 TRACE( "%p %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(ns),
1686 single, error );
1687 if (error) FIXME( "ignoring error parameter\n" );
1689 if (!writer || !ns) return E_INVALIDARG;
1690 if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
1692 if (find_namespace_attribute( &writer->current->hdr, prefix, ns )) return S_OK;
1693 return write_add_namespace_attribute( writer, prefix, ns, single );