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
*parent
, struct node
*node
)
124 node
->parent
= parent
;
125 if (node
->parent
== writer
->root
)
127 struct list
*eof
= list_tail( &writer
->root
->children
);
128 list_add_before( eof
, &node
->entry
);
130 else list_add_tail( &parent
->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 HRESULT
write_endelement( struct writer
*writer
, struct node
*parent
)
573 WS_XML_ELEMENT_NODE
*elem
= &parent
->hdr
;
577 if (!elem
) return WS_E_INVALID_FORMAT
;
579 /* '</prefix:localname>' */
581 size
= elem
->localName
->length
+ 3 /* '</>' */;
582 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
583 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
585 write_char( writer
, '<' );
586 write_char( writer
, '/' );
589 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
590 write_char( writer
, ':' );
592 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
593 write_char( writer
, '>' );
597 static HRESULT
write_add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
598 const WS_XML_STRING
*ns
, BOOL single
)
600 WS_XML_ATTRIBUTE
*attr
;
601 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
604 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
606 attr
->singleQuote
= !!single
;
608 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
610 free_attribute( attr
);
611 return E_OUTOFMEMORY
;
613 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
615 free_attribute( attr
);
616 return E_OUTOFMEMORY
;
618 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
620 free_attribute( attr
);
626 static BOOL
namespace_in_scope( const WS_XML_ELEMENT_NODE
*elem
, const WS_XML_STRING
*prefix
,
627 const WS_XML_STRING
*ns
)
630 const struct node
*node
;
632 for (node
= (const struct node
*)elem
; node
; node
= node
->parent
)
634 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) break;
637 for (i
= 0; i
< elem
->attributeCount
; i
++)
639 if (!elem
->attributes
[i
]->isXmlNs
) continue;
640 if (WsXmlStringEquals( elem
->attributes
[i
]->prefix
, prefix
, NULL
) == S_OK
&&
641 WsXmlStringEquals( elem
->attributes
[i
]->ns
, ns
, NULL
) == S_OK
)
650 static HRESULT
write_set_element_namespace( struct writer
*writer
)
652 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
655 if (!elem
->ns
->length
|| is_current_namespace( writer
, elem
->ns
) ||
656 namespace_in_scope( elem
, elem
->prefix
, elem
->ns
)) return S_OK
;
658 if ((hr
= write_add_namespace_attribute( writer
, elem
->prefix
, elem
->ns
, FALSE
)) != S_OK
)
661 return set_current_namespace( writer
, elem
->ns
);
664 static HRESULT
write_endstartelement( struct writer
*writer
)
667 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) return hr
;
668 if ((hr
= write_startelement( writer
)) != S_OK
) return hr
;
669 if ((hr
= write_grow_buffer( writer
, 1 )) != S_OK
) return hr
;
670 write_char( writer
, '>' );
674 /**************************************************************************
675 * WsWriteEndAttribute [webservices.@]
677 HRESULT WINAPI
WsWriteEndAttribute( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
679 struct writer
*writer
= (struct writer
*)handle
;
681 TRACE( "%p %p\n", handle
, error
);
682 if (error
) FIXME( "ignoring error parameter\n" );
684 if (!writer
) return E_INVALIDARG
;
686 writer
->state
= WRITER_STATE_STARTELEMENT
;
690 static struct node
*write_find_start_element( struct writer
*writer
)
692 struct node
*node
= writer
->current
, *child
;
695 for (node
= writer
->current
; node
; node
= node
->parent
)
697 if (node_type( node
) != WS_XML_NODE_TYPE_ELEMENT
) continue;
699 if (!(ptr
= list_tail( &node
->children
))) return node
;
700 child
= LIST_ENTRY( ptr
, struct node
, entry
);
701 if (node_type( child
) != WS_XML_NODE_TYPE_END_ELEMENT
) return node
;
706 static HRESULT
write_close_element( struct writer
*writer
)
708 struct node
*node
, *parent
;
711 if (!(parent
= write_find_start_element( writer
))) return WS_E_INVALID_FORMAT
;
712 if (!(node
= alloc_node( WS_XML_NODE_TYPE_END_ELEMENT
))) return E_OUTOFMEMORY
;
714 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
717 if ((hr
= write_set_element_namespace( writer
)) != S_OK
) goto error
;
718 if ((hr
= write_startelement( writer
)) != S_OK
) goto error
;
719 if ((hr
= write_grow_buffer( writer
, 2 )) != S_OK
) goto error
;
720 write_char( writer
, '/' );
721 write_char( writer
, '>' );
722 writer
->state
= WRITER_STATE_STARTENDELEMENT
;
726 /* '</prefix:localname>' */
727 if ((hr
= write_endelement( writer
, parent
)) != S_OK
) goto error
;
728 writer
->state
= WRITER_STATE_ENDELEMENT
;
731 write_insert_node( writer
, parent
, node
);
739 /**************************************************************************
740 * WsWriteEndElement [webservices.@]
742 HRESULT WINAPI
WsWriteEndElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
744 struct writer
*writer
= (struct writer
*)handle
;
746 TRACE( "%p %p\n", handle
, error
);
747 if (error
) FIXME( "ignoring error parameter\n" );
749 if (!writer
) return E_INVALIDARG
;
751 return write_close_element( writer
);
754 /**************************************************************************
755 * WsWriteEndStartElement [webservices.@]
757 HRESULT WINAPI
WsWriteEndStartElement( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
759 struct writer
*writer
= (struct writer
*)handle
;
762 TRACE( "%p %p\n", handle
, error
);
763 if (error
) FIXME( "ignoring error parameter\n" );
765 if (!writer
) return E_INVALIDARG
;
766 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
768 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
769 writer
->state
= WRITER_STATE_ENDSTARTELEMENT
;
773 static HRESULT
write_add_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
774 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
777 WS_XML_ATTRIBUTE
*attr
;
778 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
781 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
783 if (!prefix
) prefix
= elem
->prefix
;
785 attr
->singleQuote
= !!single
;
786 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
788 free_attribute( attr
);
789 return E_OUTOFMEMORY
;
791 if (!(attr
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
793 free_attribute( attr
);
794 return E_OUTOFMEMORY
;
796 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
798 free_attribute( attr
);
799 return E_OUTOFMEMORY
;
801 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
803 free_attribute( attr
);
806 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
810 /**************************************************************************
811 * WsWriteStartAttribute [webservices.@]
813 HRESULT WINAPI
WsWriteStartAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
814 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
815 BOOL single
, WS_ERROR
*error
)
817 struct writer
*writer
= (struct writer
*)handle
;
819 TRACE( "%p %s %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
820 debugstr_xmlstr(ns
), single
, error
);
821 if (error
) FIXME( "ignoring error parameter\n" );
823 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
825 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
827 return write_add_attribute( writer
, prefix
, localname
, ns
, single
);
830 /**************************************************************************
831 * WsWriteStartCData [webservices.@]
833 HRESULT WINAPI
WsWriteStartCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
835 struct writer
*writer
= (struct writer
*)handle
;
838 TRACE( "%p %p\n", handle
, error
);
839 if (error
) FIXME( "ignoring error parameter\n" );
841 if (!writer
) return E_INVALIDARG
;
843 /* flush current start element if necessary */
844 if (writer
->state
== WRITER_STATE_STARTELEMENT
&& ((hr
= write_endstartelement( writer
)) != S_OK
))
847 if ((hr
= write_grow_buffer( writer
, 9 )) != S_OK
) return hr
;
848 write_bytes( writer
, (const BYTE
*)"<![CDATA[", 9 );
849 writer
->state
= WRITER_STATE_STARTCDATA
;
853 /**************************************************************************
854 * WsWriteEndCData [webservices.@]
856 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
858 struct writer
*writer
= (struct writer
*)handle
;
861 TRACE( "%p %p\n", handle
, error
);
862 if (error
) FIXME( "ignoring error parameter\n" );
864 if (!writer
) return E_INVALIDARG
;
865 if (writer
->state
!= WRITER_STATE_STARTCDATA
) return WS_E_INVALID_OPERATION
;
867 if ((hr
= write_grow_buffer( writer
, 3 )) != S_OK
) return hr
;
868 write_bytes( writer
, (const BYTE
*)"]]>", 3 );
869 writer
->state
= WRITER_STATE_ENDCDATA
;
873 /* flush current start element if necessary */
874 static HRESULT
write_flush( struct writer
*writer
)
876 if (writer
->state
== WRITER_STATE_STARTELEMENT
) return write_endstartelement( writer
);
880 static HRESULT
write_add_element_node( struct writer
*writer
, const WS_XML_STRING
*prefix
,
881 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
)
883 struct node
*node
, *parent
;
884 WS_XML_ELEMENT_NODE
*elem
;
887 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
888 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
890 if (!prefix
&& node_type( writer
->current
) == WS_XML_NODE_TYPE_ELEMENT
)
891 prefix
= writer
->current
->hdr
.prefix
;
893 if (!(node
= alloc_node( WS_XML_NODE_TYPE_ELEMENT
))) return E_OUTOFMEMORY
;
896 if (prefix
&& !(elem
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
899 return E_OUTOFMEMORY
;
901 if (!(elem
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
904 return E_OUTOFMEMORY
;
906 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
909 return E_OUTOFMEMORY
;
911 write_insert_node( writer
, parent
, node
);
912 writer
->state
= WRITER_STATE_STARTELEMENT
;
916 /**************************************************************************
917 * WsWriteStartElement [webservices.@]
919 HRESULT WINAPI
WsWriteStartElement( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
920 const WS_XML_STRING
*localname
, const WS_XML_STRING
*ns
,
923 struct writer
*writer
= (struct writer
*)handle
;
925 TRACE( "%p %s %s %s %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(localname
),
926 debugstr_xmlstr(ns
), error
);
927 if (error
) FIXME( "ignoring error parameter\n" );
929 if (!writer
|| !localname
|| !ns
) return E_INVALIDARG
;
931 return write_add_element_node( writer
, prefix
, localname
, ns
);
934 static inline void write_set_attribute_value( struct writer
*writer
, WS_XML_TEXT
*text
)
936 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
937 elem
->attributes
[elem
->attributeCount
- 1]->value
= text
;
940 static HRESULT
write_add_text_node( struct writer
*writer
, WS_XML_TEXT
*value
)
942 struct node
*node
, *parent
;
943 WS_XML_TEXT_NODE
*text
;
945 if (!(parent
= find_parent( writer
->current
))) return WS_E_INVALID_FORMAT
;
947 if (!(node
= alloc_node( WS_XML_NODE_TYPE_TEXT
))) return E_OUTOFMEMORY
;
948 text
= (WS_XML_TEXT_NODE
*)node
;
951 write_insert_node( writer
, parent
, node
);
952 writer
->state
= WRITER_STATE_TEXT
;
956 /**************************************************************************
957 * WsWriteText [webservices.@]
959 HRESULT WINAPI
WsWriteText( WS_XML_WRITER
*handle
, const WS_XML_TEXT
*text
, WS_ERROR
*error
)
961 struct writer
*writer
= (struct writer
*)handle
;
962 WS_XML_UTF8_TEXT
*dst
, *src
= (WS_XML_UTF8_TEXT
*)text
;
965 TRACE( "%p %p %p\n", handle
, text
, error
);
967 if (!writer
|| !text
) return E_INVALIDARG
;
969 if (text
->textType
!= WS_XML_TEXT_TYPE_UTF8
)
971 FIXME( "text type %u not supported\n", text
->textType
);
975 if (writer
->state
== WRITER_STATE_STARTATTRIBUTE
)
977 if (!(dst
= alloc_utf8_text( src
->value
.bytes
, src
->value
.length
)))
978 return E_OUTOFMEMORY
;
980 write_set_attribute_value( writer
, &dst
->text
);
984 if ((hr
= write_flush( writer
)) != S_OK
) return hr
;
985 if (writer
->state
!= WRITER_STATE_STARTCDATA
)
987 if (!(dst
= alloc_utf8_text( src
->value
.bytes
, src
->value
.length
)))
988 return E_OUTOFMEMORY
;
990 if ((hr
= write_add_text_node( writer
, &dst
->text
)) != S_OK
)
996 if ((hr
= write_grow_buffer( writer
, src
->value
.length
)) != S_OK
) return hr
;
997 write_bytes( writer
, src
->value
.bytes
, src
->value
.length
);
1002 static WS_XML_TEXT
*widechar_to_xmltext( const WCHAR
*src
, WS_XML_TEXT_TYPE type
)
1006 case WS_XML_TEXT_TYPE_UTF8
:
1008 WS_XML_UTF8_TEXT
*text
;
1009 int len
= WideCharToMultiByte( CP_UTF8
, 0, src
, -1, NULL
, 0, NULL
, NULL
) - 1;
1010 if (!(text
= alloc_utf8_text( NULL
, len
))) return NULL
;
1011 WideCharToMultiByte( CP_UTF8
, 0, src
, -1, (char *)text
->value
.bytes
, text
->value
.length
, NULL
, NULL
);
1015 FIXME( "unhandled type %u\n", type
);
1020 static WS_XML_UTF8_TEXT
*format_bool( const BOOL
*ptr
)
1022 static const unsigned char bool_true
[] = {'t','r','u','e'}, bool_false
[] = {'f','a','l','s','e'};
1023 if (*ptr
) return alloc_utf8_text( bool_true
, sizeof(bool_true
) );
1024 else return alloc_utf8_text( bool_false
, sizeof(bool_false
) );
1027 static WS_XML_UTF8_TEXT
*format_int8( const INT8
*ptr
)
1029 char buf
[5]; /* "-128" */
1030 int len
= wsprintfA( buf
, "%d", *ptr
);
1031 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1034 static WS_XML_UTF8_TEXT
*format_int16( const INT16
*ptr
)
1036 char buf
[7]; /* "-32768" */
1037 int len
= wsprintfA( buf
, "%d", *ptr
);
1038 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1041 static WS_XML_UTF8_TEXT
*format_int32( const INT32
*ptr
)
1043 char buf
[12]; /* "-2147483648" */
1044 int len
= wsprintfA( buf
, "%d", *ptr
);
1045 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1048 static WS_XML_UTF8_TEXT
*format_int64( const INT64
*ptr
)
1050 char buf
[21]; /* "-9223372036854775808" */
1051 int len
= wsprintfA( buf
, "%I64d", *ptr
);
1052 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1055 static WS_XML_UTF8_TEXT
*format_uint8( const UINT8
*ptr
)
1057 char buf
[4]; /* "255" */
1058 int len
= wsprintfA( buf
, "%u", *ptr
);
1059 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1062 static WS_XML_UTF8_TEXT
*format_uint16( const UINT16
*ptr
)
1064 char buf
[6]; /* "65535" */
1065 int len
= wsprintfA( buf
, "%u", *ptr
);
1066 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1069 static WS_XML_UTF8_TEXT
*format_uint32( const UINT32
*ptr
)
1071 char buf
[11]; /* "4294967295" */
1072 int len
= wsprintfA( buf
, "%u", *ptr
);
1073 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1076 static WS_XML_UTF8_TEXT
*format_uint64( const UINT64
*ptr
)
1078 char buf
[21]; /* "18446744073709551615" */
1079 int len
= wsprintfA( buf
, "%I64u", *ptr
);
1080 return alloc_utf8_text( (const unsigned char *)buf
, len
);
1083 static HRESULT
write_text_node( struct writer
*writer
)
1086 WS_XML_TEXT_NODE
*node
= (WS_XML_TEXT_NODE
*)writer
->current
;
1087 WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)node
->text
;
1089 if ((hr
= write_grow_buffer( writer
, text
->value
.length
)) != S_OK
) return hr
;
1090 write_bytes( writer
, text
->value
.bytes
, text
->value
.length
);
1094 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1101 case WS_ELEMENT_TYPE_MAPPING
:
1102 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1103 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
1104 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
1105 return write_text_node( writer
);
1107 case WS_ATTRIBUTE_TYPE_MAPPING
:
1108 write_set_attribute_value( writer
, text
);
1111 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1112 switch (writer
->state
)
1114 case WRITER_STATE_STARTATTRIBUTE
:
1115 write_set_attribute_value( writer
, text
);
1118 case WRITER_STATE_STARTELEMENT
:
1119 if ((hr
= write_endstartelement( writer
)) != S_OK
) return hr
;
1120 if ((hr
= write_add_text_node( writer
, text
)) != S_OK
) return hr
;
1121 return write_text_node( writer
);
1124 FIXME( "writer state %u not handled\n", writer
->state
);
1129 FIXME( "mapping %u not implemented\n", mapping
);
1134 static HRESULT
write_type_bool( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1135 const WS_BOOL_DESCRIPTION
*desc
, const BOOL
*value
)
1137 WS_XML_UTF8_TEXT
*text
;
1142 FIXME( "description not supported\n" );
1145 if (!(text
= format_bool( value
))) return E_OUTOFMEMORY
;
1146 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1151 static HRESULT
write_type_int8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1152 const WS_INT8_DESCRIPTION
*desc
, const INT8
*value
)
1154 WS_XML_UTF8_TEXT
*text
;
1159 FIXME( "description not supported\n" );
1162 if (!(text
= format_int8( value
))) return E_OUTOFMEMORY
;
1163 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1168 static HRESULT
write_type_int16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1169 const WS_INT16_DESCRIPTION
*desc
, const INT16
*value
)
1171 WS_XML_UTF8_TEXT
*text
;
1176 FIXME( "description not supported\n" );
1179 if (!(text
= format_int16( value
))) return E_OUTOFMEMORY
;
1180 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1185 static HRESULT
write_type_int32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1186 const WS_INT32_DESCRIPTION
*desc
, const INT32
*value
)
1188 WS_XML_UTF8_TEXT
*text
;
1193 FIXME( "description not supported\n" );
1196 if (!(text
= format_int32( value
))) return E_OUTOFMEMORY
;
1197 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1202 static HRESULT
write_type_int64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1203 const WS_INT64_DESCRIPTION
*desc
, const INT64
*value
)
1205 WS_XML_UTF8_TEXT
*text
;
1210 FIXME( "description not supported\n" );
1213 if (!(text
= format_int64( value
))) return E_OUTOFMEMORY
;
1214 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1219 static HRESULT
write_type_uint8( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1220 const WS_UINT8_DESCRIPTION
*desc
, const UINT8
*value
)
1222 WS_XML_UTF8_TEXT
*text
;
1227 FIXME( "description not supported\n" );
1230 if (!(text
= format_uint8( value
))) return E_OUTOFMEMORY
;
1231 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1236 static HRESULT
write_type_uint16( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1237 const WS_UINT16_DESCRIPTION
*desc
, const UINT16
*value
)
1239 WS_XML_UTF8_TEXT
*text
;
1244 FIXME( "description not supported\n" );
1247 if (!(text
= format_uint16( value
))) return E_OUTOFMEMORY
;
1248 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1253 static HRESULT
write_type_uint32( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1254 const WS_UINT32_DESCRIPTION
*desc
, const UINT32
*value
)
1256 WS_XML_UTF8_TEXT
*text
;
1261 FIXME( "description not supported\n" );
1264 if (!(text
= format_uint32( value
))) return E_OUTOFMEMORY
;
1265 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1270 static HRESULT
write_type_uint64( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1271 const WS_UINT64_DESCRIPTION
*desc
, const UINT64
*value
)
1273 WS_XML_UTF8_TEXT
*text
;
1278 FIXME( "description not supported\n" );
1281 if (!(text
= format_uint64( value
))) return E_OUTOFMEMORY
;
1282 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1287 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1288 const WS_WSZ_DESCRIPTION
*desc
, const WCHAR
*value
)
1295 FIXME( "description not supported\n" );
1298 if (!(text
= widechar_to_xmltext( value
, WS_XML_TEXT_TYPE_UTF8
))) return E_OUTOFMEMORY
;
1299 if ((hr
= write_type_text( writer
, mapping
, text
)) == S_OK
) return S_OK
;
1304 static HRESULT
write_type( struct writer
*, WS_TYPE_MAPPING
, WS_TYPE
, const void *, WS_WRITE_OPTION
,
1305 const void *, ULONG
);
1307 static HRESULT
write_type_struct_field( struct writer
*writer
, const WS_FIELD_DESCRIPTION
*desc
,
1308 const void *value
, ULONG size
)
1311 WS_TYPE_MAPPING mapping
;
1312 WS_WRITE_OPTION option
;
1314 if (!desc
->options
|| desc
->options
== WS_FIELD_OPTIONAL
) option
= 0;
1315 else if (desc
->options
== WS_FIELD_POINTER
) option
= WS_WRITE_REQUIRED_POINTER
;
1318 FIXME( "options 0x%x not supported\n", desc
->options
);
1322 switch (desc
->mapping
)
1324 case WS_ATTRIBUTE_FIELD_MAPPING
:
1325 if (!desc
->localName
|| !desc
->ns
) return E_INVALIDARG
;
1326 if ((hr
= write_add_attribute( writer
, NULL
, desc
->localName
, desc
->ns
, FALSE
)) != S_OK
)
1329 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1332 case WS_ELEMENT_FIELD_MAPPING
:
1333 if ((hr
= write_add_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
)
1336 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1339 case WS_TEXT_FIELD_MAPPING
:
1340 switch (writer
->state
)
1342 case WRITER_STATE_STARTELEMENT
:
1343 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
1346 case WRITER_STATE_STARTATTRIBUTE
:
1347 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1351 FIXME( "unhandled writer state %u\n", writer
->state
);
1357 FIXME( "field mapping %u not supported\n", desc
->mapping
);
1361 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, value
, size
)) != S_OK
)
1366 case WS_ATTRIBUTE_TYPE_MAPPING
:
1367 writer
->state
= WRITER_STATE_STARTELEMENT
;
1370 case WS_ELEMENT_TYPE_MAPPING
:
1371 if ((hr
= write_close_element( writer
)) != S_OK
) return hr
;
1380 static ULONG
get_field_size( const WS_STRUCT_DESCRIPTION
*desc
, ULONG index
)
1382 if (index
< desc
->fieldCount
- 1) return desc
->fields
[index
+ 1]->offset
- desc
->fields
[index
]->offset
;
1383 return desc
->size
- desc
->fields
[index
]->offset
;
1386 static HRESULT
write_type_struct( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1387 const WS_STRUCT_DESCRIPTION
*desc
, const void *value
)
1393 if (!desc
) return E_INVALIDARG
;
1395 if (desc
->structOptions
)
1397 FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
1401 for (i
= 0; i
< desc
->fieldCount
; i
++)
1403 ptr
= (const char *)value
+ desc
->fields
[i
]->offset
;
1404 size
= get_field_size( desc
, i
);
1405 if ((hr
= write_type_struct_field( writer
, desc
->fields
[i
], ptr
, size
)) != S_OK
)
1412 static HRESULT
write_type( struct writer
*writer
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1413 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
1418 case WS_STRUCT_TYPE
:
1420 const void * const *ptr
= value
;
1422 if (!desc
|| (option
&& option
!= WS_WRITE_REQUIRED_POINTER
) || size
!= sizeof(*ptr
))
1423 return E_INVALIDARG
;
1425 return write_type_struct( writer
, mapping
, desc
, *ptr
);
1429 const BOOL
*ptr
= value
;
1430 if ((option
&& option
!= WS_WRITE_REQUIRED_VALUE
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1431 return write_type_bool( writer
, mapping
, desc
, ptr
);
1435 const INT8
*ptr
= value
;
1436 if ((option
&& option
!= WS_WRITE_REQUIRED_VALUE
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1437 return write_type_int8( writer
, mapping
, desc
, ptr
);
1441 const INT16
*ptr
= value
;
1442 if ((option
&& option
!= WS_WRITE_REQUIRED_VALUE
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1443 return write_type_int16( writer
, mapping
, desc
, ptr
);
1447 const INT32
*ptr
= value
;
1448 if ((option
&& option
!= WS_WRITE_REQUIRED_VALUE
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1449 return write_type_int32( writer
, mapping
, desc
, ptr
);
1453 const INT64
*ptr
= value
;
1454 if ((option
&& option
!= WS_WRITE_REQUIRED_VALUE
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1455 return write_type_int64( writer
, mapping
, desc
, ptr
);
1459 const UINT8
*ptr
= value
;
1460 if ((option
&& option
!= WS_WRITE_REQUIRED_VALUE
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1461 return write_type_uint8( writer
, mapping
, desc
, ptr
);
1463 case WS_UINT16_TYPE
:
1465 const UINT16
*ptr
= value
;
1466 if ((option
&& option
!= WS_WRITE_REQUIRED_VALUE
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1467 return write_type_uint16( writer
, mapping
, desc
, ptr
);
1469 case WS_UINT32_TYPE
:
1471 const UINT32
*ptr
= value
;
1472 if ((option
&& option
!= WS_WRITE_REQUIRED_VALUE
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1473 return write_type_uint32( writer
, mapping
, desc
, ptr
);
1475 case WS_UINT64_TYPE
:
1477 const UINT64
*ptr
= value
;
1478 if ((option
&& option
!= WS_WRITE_REQUIRED_VALUE
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1479 return write_type_uint64( writer
, mapping
, desc
, ptr
);
1483 const WCHAR
* const *ptr
= value
;
1484 if ((option
&& option
!= WS_WRITE_REQUIRED_POINTER
) || size
!= sizeof(*ptr
)) return E_INVALIDARG
;
1485 return write_type_wsz( writer
, mapping
, desc
, *ptr
);
1488 FIXME( "type %u not supported\n", type
);
1493 /**************************************************************************
1494 * WsWriteAttribute [webservices.@]
1496 HRESULT WINAPI
WsWriteAttribute( WS_XML_WRITER
*handle
, const WS_ATTRIBUTE_DESCRIPTION
*desc
,
1497 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
1500 struct writer
*writer
= (struct writer
*)handle
;
1503 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
1504 if (error
) FIXME( "ignoring error parameter\n" );
1506 if (!writer
|| !desc
|| !desc
->attributeLocalName
|| !desc
->attributeNs
|| !value
)
1507 return E_INVALIDARG
;
1509 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
1511 if ((hr
= write_add_attribute( writer
, NULL
, desc
->attributeLocalName
, desc
->attributeNs
,
1512 FALSE
)) != S_OK
) return hr
;
1514 return write_type( writer
, WS_ATTRIBUTE_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
1515 option
, value
, size
);
1518 /**************************************************************************
1519 * WsWriteElement [webservices.@]
1521 HRESULT WINAPI
WsWriteElement( WS_XML_WRITER
*handle
, const WS_ELEMENT_DESCRIPTION
*desc
,
1522 WS_WRITE_OPTION option
, const void *value
, ULONG size
,
1525 struct writer
*writer
= (struct writer
*)handle
;
1528 TRACE( "%p %p %u %p %u %p\n", handle
, desc
, option
, value
, size
, error
);
1529 if (error
) FIXME( "ignoring error parameter\n" );
1531 if (!writer
|| !desc
|| !desc
->elementLocalName
|| !desc
->elementNs
|| !value
)
1532 return E_INVALIDARG
;
1534 if ((hr
= write_add_element_node( writer
, NULL
, desc
->elementLocalName
, desc
->elementNs
)) != S_OK
)
1537 if ((hr
= write_type( writer
, WS_ANY_ELEMENT_TYPE_MAPPING
, desc
->type
, desc
->typeDescription
,
1538 option
, value
, size
)) != S_OK
) return hr
;
1540 return write_close_element( writer
);
1543 /**************************************************************************
1544 * WsWriteType [webservices.@]
1546 HRESULT WINAPI
WsWriteType( WS_XML_WRITER
*handle
, WS_TYPE_MAPPING mapping
, WS_TYPE type
,
1547 const void *desc
, WS_WRITE_OPTION option
, const void *value
,
1548 ULONG size
, WS_ERROR
*error
)
1550 struct writer
*writer
= (struct writer
*)handle
;
1553 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
1555 if (error
) FIXME( "ignoring error parameter\n" );
1557 if (!writer
|| !value
) return E_INVALIDARG
;
1561 case WS_ATTRIBUTE_TYPE_MAPPING
:
1562 if (writer
->state
!= WRITER_STATE_STARTATTRIBUTE
) return WS_E_INVALID_FORMAT
;
1563 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1566 case WS_ELEMENT_TYPE_MAPPING
:
1567 case WS_ELEMENT_CONTENT_TYPE_MAPPING
:
1568 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_FORMAT
;
1569 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1572 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1573 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1577 FIXME( "mapping %u not implemented\n", mapping
);
1584 WS_TYPE
map_value_type( WS_VALUE_TYPE type
)
1588 case WS_BOOL_VALUE_TYPE
: return WS_BOOL_TYPE
;
1589 case WS_INT8_VALUE_TYPE
: return WS_INT8_TYPE
;
1590 case WS_INT16_VALUE_TYPE
: return WS_INT16_TYPE
;
1591 case WS_INT32_VALUE_TYPE
: return WS_INT32_TYPE
;
1592 case WS_INT64_VALUE_TYPE
: return WS_INT64_TYPE
;
1593 case WS_UINT8_VALUE_TYPE
: return WS_UINT8_TYPE
;
1594 case WS_UINT16_VALUE_TYPE
: return WS_UINT16_TYPE
;
1595 case WS_UINT32_VALUE_TYPE
: return WS_UINT32_TYPE
;
1596 case WS_UINT64_VALUE_TYPE
: return WS_UINT64_TYPE
;
1597 case WS_FLOAT_VALUE_TYPE
: return WS_FLOAT_TYPE
;
1598 case WS_DOUBLE_VALUE_TYPE
: return WS_DOUBLE_TYPE
;
1599 case WS_DECIMAL_VALUE_TYPE
: return WS_DECIMAL_TYPE
;
1600 case WS_DATETIME_VALUE_TYPE
: return WS_DATETIME_TYPE
;
1601 case WS_TIMESPAN_VALUE_TYPE
: return WS_TIMESPAN_TYPE
;
1602 case WS_GUID_VALUE_TYPE
: return WS_GUID_TYPE
;
1604 FIXME( "unhandled type %u\n", type
);
1609 /**************************************************************************
1610 * WsWriteValue [webservices.@]
1612 HRESULT WINAPI
WsWriteValue( WS_XML_WRITER
*handle
, WS_VALUE_TYPE value_type
, const void *value
,
1613 ULONG size
, WS_ERROR
*error
)
1615 struct writer
*writer
= (struct writer
*)handle
;
1616 WS_TYPE_MAPPING mapping
;
1619 TRACE( "%p %u %p %u %p\n", handle
, value_type
, value
, size
, error
);
1620 if (error
) FIXME( "ignoring error parameter\n" );
1622 if (!writer
|| !value
|| (type
= map_value_type( value_type
)) == ~0u) return E_INVALIDARG
;
1624 switch (writer
->state
)
1626 case WRITER_STATE_STARTATTRIBUTE
:
1627 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1630 case WRITER_STATE_STARTELEMENT
:
1631 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1635 return WS_E_INVALID_FORMAT
;
1638 return write_type( writer
, mapping
, type
, NULL
, WS_WRITE_REQUIRED_VALUE
, value
, size
);
1641 /**************************************************************************
1642 * WsWriteXmlBuffer [webservices.@]
1644 HRESULT WINAPI
WsWriteXmlBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
, WS_ERROR
*error
)
1646 struct writer
*writer
= (struct writer
*)handle
;
1647 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1650 TRACE( "%p %p %p\n", handle
, buffer
, error
);
1651 if (error
) FIXME( "ignoring error parameter\n" );
1653 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
1655 if ((hr
= write_grow_buffer( writer
, xmlbuf
->size
)) != S_OK
) return hr
;
1656 write_bytes( writer
, xmlbuf
->ptr
, xmlbuf
->size
);
1660 /**************************************************************************
1661 * WsWriteXmlBufferToBytes [webservices.@]
1663 HRESULT WINAPI
WsWriteXmlBufferToBytes( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
1664 const WS_XML_WRITER_ENCODING
*encoding
,
1665 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
1666 WS_HEAP
*heap
, void **bytes
, ULONG
*size
, WS_ERROR
*error
)
1668 struct writer
*writer
= (struct writer
*)handle
;
1669 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
1674 TRACE( "%p %p %p %p %u %p %p %p %p\n", handle
, buffer
, encoding
, properties
, count
, heap
,
1675 bytes
, size
, error
);
1676 if (error
) FIXME( "ignoring error parameter\n" );
1678 if (!writer
|| !xmlbuf
|| !heap
|| !bytes
) return E_INVALIDARG
;
1680 if (encoding
&& encoding
->encodingType
!= WS_XML_WRITER_ENCODING_TYPE_TEXT
)
1682 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
1686 for (i
= 0; i
< count
; i
++)
1688 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
1689 properties
[i
].valueSize
);
1690 if (hr
!= S_OK
) return hr
;
1693 if (!(buf
= ws_alloc( heap
, xmlbuf
->size
))) return WS_E_QUOTA_EXCEEDED
;
1694 memcpy( buf
, xmlbuf
->ptr
, xmlbuf
->size
);
1699 /**************************************************************************
1700 * WsWriteXmlnsAttribute [webservices.@]
1702 HRESULT WINAPI
WsWriteXmlnsAttribute( WS_XML_WRITER
*handle
, const WS_XML_STRING
*prefix
,
1703 const WS_XML_STRING
*ns
, BOOL single
, WS_ERROR
*error
)
1705 struct writer
*writer
= (struct writer
*)handle
;
1707 TRACE( "%p %s %s %d %p\n", handle
, debugstr_xmlstr(prefix
), debugstr_xmlstr(ns
),
1709 if (error
) FIXME( "ignoring error parameter\n" );
1711 if (!writer
|| !ns
) return E_INVALIDARG
;
1712 if (writer
->state
!= WRITER_STATE_STARTELEMENT
) return WS_E_INVALID_OPERATION
;
1714 if (namespace_in_scope( &writer
->current
->hdr
, prefix
, ns
)) return S_OK
;
1715 return write_add_namespace_attribute( writer
, prefix
, ns
, single
);
1718 static HRESULT
write_move_to( struct writer
*writer
, WS_MOVE_TO move
, BOOL
*found
)
1720 BOOL success
= FALSE
;
1721 struct node
*node
= writer
->current
;
1725 case WS_MOVE_TO_ROOT_ELEMENT
:
1726 success
= move_to_root_element( writer
->root
, &node
);
1729 case WS_MOVE_TO_NEXT_ELEMENT
:
1730 success
= move_to_next_element( &node
);
1733 case WS_MOVE_TO_PREVIOUS_ELEMENT
:
1734 success
= move_to_prev_element( &node
);
1737 case WS_MOVE_TO_CHILD_ELEMENT
:
1738 success
= move_to_child_element( &node
);
1741 case WS_MOVE_TO_END_ELEMENT
:
1742 success
= move_to_end_element( &node
);
1745 case WS_MOVE_TO_PARENT_ELEMENT
:
1746 success
= move_to_parent_element( &node
);
1749 case WS_MOVE_TO_FIRST_NODE
:
1750 success
= move_to_first_node( &node
);
1753 case WS_MOVE_TO_NEXT_NODE
:
1754 success
= move_to_next_node( &node
);
1757 case WS_MOVE_TO_PREVIOUS_NODE
:
1758 success
= move_to_prev_node( &node
);
1761 case WS_MOVE_TO_CHILD_NODE
:
1762 success
= move_to_child_node( &node
);
1765 case WS_MOVE_TO_BOF
:
1766 success
= move_to_bof( writer
->root
, &node
);
1769 case WS_MOVE_TO_EOF
:
1770 success
= move_to_eof( writer
->root
, &node
);
1774 FIXME( "unhandled move %u\n", move
);
1778 if (success
&& node
== writer
->root
) return E_INVALIDARG
;
1779 writer
->current
= node
;
1786 return success
? S_OK
: WS_E_INVALID_FORMAT
;
1789 /**************************************************************************
1790 * WsMoveWriter [webservices.@]
1792 HRESULT WINAPI
WsMoveWriter( WS_XML_WRITER
*handle
, WS_MOVE_TO move
, BOOL
*found
, WS_ERROR
*error
)
1794 struct writer
*writer
= (struct writer
*)handle
;
1796 TRACE( "%p %u %p %p\n", handle
, move
, found
, error
);
1797 if (error
) FIXME( "ignoring error parameter\n" );
1799 if (!writer
) return E_INVALIDARG
;
1800 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
1802 return write_move_to( writer
, move
, found
);
1805 /**************************************************************************
1806 * WsGetWriterPosition [webservices.@]
1808 HRESULT WINAPI
WsGetWriterPosition( WS_XML_WRITER
*handle
, WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
1810 struct writer
*writer
= (struct writer
*)handle
;
1812 TRACE( "%p %p %p\n", handle
, pos
, error
);
1813 if (error
) FIXME( "ignoring error parameter\n" );
1815 if (!writer
|| !pos
) return E_INVALIDARG
;
1816 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
1818 pos
->buffer
= (WS_XML_BUFFER
*)writer
->output_buf
;
1819 pos
->node
= writer
->current
;
1823 /**************************************************************************
1824 * WsSetWriterPosition [webservices.@]
1826 HRESULT WINAPI
WsSetWriterPosition( WS_XML_WRITER
*handle
, const WS_XML_NODE_POSITION
*pos
, WS_ERROR
*error
)
1828 struct writer
*writer
= (struct writer
*)handle
;
1830 TRACE( "%p %p %p\n", handle
, pos
, error
);
1831 if (error
) FIXME( "ignoring error parameter\n" );
1833 if (!writer
|| !pos
|| (struct xmlbuf
*)pos
->buffer
!= writer
->output_buf
) return E_INVALIDARG
;
1834 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
1836 writer
->current
= pos
->node
;