2 * Copyright 2015, 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/list.h"
28 #include "wine/unicode.h"
29 #include "webservices_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
33 static const struct prop_desc writer_props
[] =
35 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_DEPTH */
36 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT */
37 { sizeof(ULONG
), FALSE
}, /* WS_XML_READER_PROPERTY_MAX_ATTRIBUTES */
38 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_WRITE_DECLARATION */
39 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INDENT */
40 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE */
41 { sizeof(WS_CHARSET
), FALSE
}, /* WS_XML_WRITER_PROPERTY_CHARSET */
42 { sizeof(WS_BUFFERS
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFERS */
43 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE */
44 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_BYTES */
45 { sizeof(BOOL
), TRUE
}, /* WS_XML_WRITER_PROPERTY_IN_ATTRIBUTE */
46 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE */
47 { sizeof(WS_BYTES
), FALSE
}, /* WS_XML_WRITER_PROPERTY_INITIAL_BUFFER */
48 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_ALLOW_INVALID_CHARACTER_REFERENCES */
49 { sizeof(ULONG
), FALSE
}, /* WS_XML_WRITER_PROPERTY_MAX_NAMESPACES */
50 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_WRITTEN */
51 { sizeof(ULONG
), TRUE
}, /* WS_XML_WRITER_PROPERTY_BYTES_TO_CLOSE */
52 { sizeof(BOOL
), FALSE
}, /* WS_XML_WRITER_PROPERTY_COMPRESS_EMPTY_ELEMENTS */
53 { sizeof(BOOL
), FALSE
} /* WS_XML_WRITER_PROPERTY_EMIT_UNCOMPRESSED_EMPTY_ELEMENTS */
59 WRITER_STATE_STARTELEMENT
,
60 WRITER_STATE_STARTENDELEMENT
,
61 WRITER_STATE_STARTATTRIBUTE
,
62 WRITER_STATE_STARTCDATA
,
63 WRITER_STATE_ENDSTARTELEMENT
,
65 WRITER_STATE_ENDELEMENT
,
72 unsigned char *write_bufptr
;
73 enum writer_state state
;
76 WS_XML_STRING
*current_ns
;
77 WS_XML_WRITER_OUTPUT_TYPE output_type
;
78 struct xmlbuf
*output_buf
;
81 struct prop prop
[sizeof(writer_props
)/sizeof(writer_props
[0])];
84 static struct writer
*alloc_writer(void)
86 static const ULONG count
= sizeof(writer_props
)/sizeof(writer_props
[0]);
88 ULONG size
= sizeof(*ret
) + prop_size( writer_props
, count
);
90 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
91 prop_init( writer_props
, count
, ret
->prop
, &ret
[1] );
92 ret
->prop_count
= count
;
96 static void free_writer( struct writer
*writer
)
98 destroy_nodes( writer
->root
);
99 heap_free( writer
->current_ns
);
100 WsFreeHeap( writer
->output_heap
);
104 static void write_insert_eof( struct writer
*writer
, struct node
*eof
)
106 if (!writer
->root
) writer
->root
= eof
;
109 eof
->parent
= writer
->root
;
110 list_add_tail( &writer
->root
->children
, &eof
->entry
);
112 writer
->current
= eof
;
115 static void write_insert_bof( struct writer
*writer
, struct node
*bof
)
117 writer
->root
->parent
= bof
;
118 list_add_tail( &bof
->children
, &writer
->root
->entry
);
119 writer
->current
= writer
->root
= bof
;
122 static void write_insert_node( struct writer
*writer
, struct node
*node
)
124 node
->parent
= writer
->current
;
125 if (writer
->current
== writer
->root
)
127 struct list
*eof
= list_tail( &writer
->root
->children
);
128 list_add_before( eof
, &node
->entry
);
130 else list_add_tail( &writer
->current
->children
, &node
->entry
);
131 writer
->current
= node
;
134 static HRESULT
write_init_state( struct writer
*writer
)
138 heap_free( writer
->current_ns
);
139 writer
->current_ns
= NULL
;
140 destroy_nodes( writer
->root
);
143 if (!(node
= alloc_node( WS_XML_NODE_TYPE_EOF
))) return E_OUTOFMEMORY
;
144 write_insert_eof( writer
, node
);
145 writer
->state
= WRITER_STATE_INITIAL
;
149 /**************************************************************************
150 * WsCreateWriter [webservices.@]
152 HRESULT WINAPI
WsCreateWriter( const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
153 WS_XML_WRITER
**handle
, WS_ERROR
*error
)
155 struct writer
*writer
;
156 ULONG i
, max_depth
= 32, max_attrs
= 128, trim_size
= 4096, max_size
= 65536, max_ns
= 32;
157 WS_CHARSET charset
= WS_CHARSET_UTF8
;
160 TRACE( "%p %u %p %p\n", properties
, count
, handle
, error
);
161 if (error
) FIXME( "ignoring error parameter\n" );
163 if (!handle
) return E_INVALIDARG
;
164 if (!(writer
= alloc_writer())) return E_OUTOFMEMORY
;
166 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_DEPTH
, &max_depth
, sizeof(max_depth
) );
167 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_ATTRIBUTES
, &max_attrs
, sizeof(max_attrs
) );
168 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
169 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_CHARSET
, &charset
, sizeof(charset
) );
170 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
, &max_size
, sizeof(max_size
) );
171 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_MIME_PARTS_BUFFER_SIZE
, &max_size
, sizeof(max_size
) );
172 prop_set( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_MAX_NAMESPACES
, &max_ns
, sizeof(max_ns
) );
174 for (i
= 0; i
< count
; i
++)
176 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
177 properties
[i
].valueSize
);
180 free_writer( writer
);
185 hr
= prop_get( writer
->prop
, writer
->prop_count
, WS_XML_WRITER_PROPERTY_BUFFER_MAX_SIZE
,
186 &max_size
, sizeof(max_size
) );
189 free_writer( writer
);
193 hr
= WsCreateHeap( max_size
, 0, NULL
, 0, &writer
->output_heap
, NULL
);
196 free_writer( writer
);
200 hr
= write_init_state( writer
);
203 free_writer( writer
);
207 *handle
= (WS_XML_WRITER
*)writer
;
211 /**************************************************************************
212 * WsFreeWriter [webservices.@]
214 void WINAPI
WsFreeWriter( WS_XML_WRITER
*handle
)
216 struct writer
*writer
= (struct writer
*)handle
;
218 TRACE( "%p\n", handle
);
219 free_writer( writer
);
222 #define XML_BUFFER_INITIAL_ALLOCATED_SIZE 256
223 static struct xmlbuf
*alloc_xmlbuf( WS_HEAP
*heap
)
227 if (!(ret
= ws_alloc( heap
, sizeof(*ret
) ))) return NULL
;
228 if (!(ret
->ptr
= ws_alloc( heap
, XML_BUFFER_INITIAL_ALLOCATED_SIZE
)))
230 ws_free( heap
, ret
);
234 ret
->size_allocated
= XML_BUFFER_INITIAL_ALLOCATED_SIZE
;
239 static void free_xmlbuf( struct xmlbuf
*xmlbuf
)
242 ws_free( xmlbuf
->heap
, xmlbuf
->ptr
);
243 ws_free( xmlbuf
->heap
, xmlbuf
);
246 /**************************************************************************
247 * WsCreateXmlBuffer [webservices.@]
249 HRESULT WINAPI
WsCreateXmlBuffer( WS_HEAP
*heap
, const WS_XML_BUFFER_PROPERTY
*properties
,
250 ULONG count
, WS_XML_BUFFER
**handle
, WS_ERROR
*error
)
252 struct xmlbuf
*xmlbuf
;
254 if (!heap
|| !handle
) return E_INVALIDARG
;
255 if (count
) FIXME( "properties not implemented\n" );
257 if (!(xmlbuf
= alloc_xmlbuf( heap
))) return E_OUTOFMEMORY
;
259 *handle
= (WS_XML_BUFFER
*)xmlbuf
;
263 /**************************************************************************
264 * WsGetWriterProperty [webservices.@]
266 HRESULT WINAPI
WsGetWriterProperty( WS_XML_WRITER
*handle
, WS_XML_WRITER_PROPERTY_ID id
,
267 void *buf
, ULONG size
, WS_ERROR
*error
)
269 struct writer
*writer
= (struct writer
*)handle
;
271 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
272 if (error
) FIXME( "ignoring error parameter\n" );
274 if (!writer
->output_type
) return WS_E_INVALID_OPERATION
;
278 case WS_XML_WRITER_PROPERTY_BYTES
:
280 WS_BYTES
*bytes
= buf
;
281 if (size
!= sizeof(*bytes
)) return E_INVALIDARG
;
282 bytes
->bytes
= writer
->output_buf
->ptr
;
283 bytes
->length
= writer
->output_buf
->size
;
287 return prop_get( writer
->prop
, writer
->prop_count
, id
, buf
, size
);
291 static void set_output_buffer( struct writer
*writer
, struct xmlbuf
*xmlbuf
)
293 /* free current buffer if it's ours */
294 if (writer
->output_buf
&& writer
->output_buf
->heap
== writer
->output_heap
)
296 free_xmlbuf( writer
->output_buf
);
298 writer
->output_buf
= xmlbuf
;
299 writer
->output_type
= WS_XML_WRITER_OUTPUT_TYPE_BUFFER
;
300 writer
->write_bufptr
= xmlbuf
->ptr
;
301 writer
->write_pos
= 0;
304 /**************************************************************************
305 * WsSetOutput [webservices.@]
307 HRESULT WINAPI
WsSetOutput( WS_XML_WRITER
*handle
, const WS_XML_WRITER_ENCODING
*encoding
,
308 const WS_XML_WRITER_OUTPUT
*output
, const WS_XML_WRITER_PROPERTY
*properties
,
309 ULONG count
, WS_ERROR
*error
)
311 struct writer
*writer
= (struct writer
*)handle
;
316 TRACE( "%p %p %p %p %u %p\n", handle
, encoding
, output
, properties
, count
, error
);
317 if (error
) FIXME( "ignoring error parameter\n" );
319 if (!writer
) return E_INVALIDARG
;
321 for (i
= 0; i
< count
; i
++)
323 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
324 properties
[i
].valueSize
);
325 if (hr
!= S_OK
) return hr
;
328 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
330 switch (encoding
->encodingType
)
332 case WS_XML_WRITER_ENCODING_TYPE_TEXT
:
334 WS_XML_WRITER_TEXT_ENCODING
*text
= (WS_XML_WRITER_TEXT_ENCODING
*)encoding
;
335 if (text
->charSet
!= WS_CHARSET_UTF8
)
337 FIXME( "charset %u not supported\n", text
->charSet
);
343 FIXME( "encoding type %u not supported\n", encoding
->encodingType
);
346 switch (output
->outputType
)
348 case WS_XML_WRITER_OUTPUT_TYPE_BUFFER
:
350 struct xmlbuf
*xmlbuf
;
352 if (!(xmlbuf
= alloc_xmlbuf( writer
->output_heap
))) return E_OUTOFMEMORY
;
353 set_output_buffer( writer
, xmlbuf
);
357 FIXME( "output type %u not supported\n", output
->outputType
);
361 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
362 write_insert_bof( writer
, node
);
366 /**************************************************************************
367 * WsSetOutputToBuffer [webservices.@]
369 HRESULT WINAPI
WsSetOutputToBuffer( WS_XML_WRITER
*handle
, WS_XML_BUFFER
*buffer
,
370 const WS_XML_WRITER_PROPERTY
*properties
, ULONG count
,
373 struct writer
*writer
= (struct writer
*)handle
;
374 struct xmlbuf
*xmlbuf
= (struct xmlbuf
*)buffer
;
379 TRACE( "%p %p %p %u %p\n", handle
, buffer
, properties
, count
, error
);
380 if (error
) FIXME( "ignoring error parameter\n" );
382 if (!writer
|| !xmlbuf
) return E_INVALIDARG
;
384 for (i
= 0; i
< count
; i
++)
386 hr
= prop_set( writer
->prop
, writer
->prop_count
, properties
[i
].id
, properties
[i
].value
,
387 properties
[i
].valueSize
);
388 if (hr
!= S_OK
) return hr
;
391 if ((hr
= write_init_state( writer
)) != S_OK
) return hr
;
392 set_output_buffer( writer
, xmlbuf
);
394 if (!(node
= alloc_node( WS_XML_NODE_TYPE_BOF
))) return E_OUTOFMEMORY
;
395 write_insert_bof( writer
, node
);
399 static HRESULT
write_grow_buffer( struct writer
*writer
, ULONG size
)
401 struct xmlbuf
*buf
= writer
->output_buf
;
405 if (buf
->size_allocated
>= writer
->write_pos
+ size
)
407 buf
->size
= writer
->write_pos
+ size
;
410 new_size
= max( buf
->size_allocated
* 2, writer
->write_pos
+ size
);
411 if (!(tmp
= ws_realloc( buf
->heap
, buf
->ptr
, new_size
))) return E_OUTOFMEMORY
;
412 writer
->write_bufptr
= buf
->ptr
= tmp
;
413 buf
->size_allocated
= new_size
;
414 buf
->size
= writer
->write_pos
+ size
;
418 static inline void write_char( struct writer
*writer
, unsigned char ch
)
420 writer
->write_bufptr
[writer
->write_pos
++] = ch
;
423 static inline void write_bytes( struct writer
*writer
, const BYTE
*bytes
, ULONG len
)
425 memcpy( writer
->write_bufptr
+ writer
->write_pos
, bytes
, len
);
426 writer
->write_pos
+= len
;
429 static HRESULT
write_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
431 WS_XML_UTF8_TEXT
*text
= (WS_XML_UTF8_TEXT
*)attr
->value
;
432 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
433 const WS_XML_STRING
*prefix
;
437 if (attr
->prefix
) prefix
= attr
->prefix
;
438 else prefix
= writer
->current
->hdr
.prefix
;
440 /* ' prefix:attr="value"' */
442 size
= attr
->localName
->length
+ 4 /* ' =""' */;
443 if (prefix
) size
+= prefix
->length
+ 1 /* ':' */;
444 if (text
) size
+= text
->value
.length
;
445 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
447 write_char( writer
, ' ' );
450 write_bytes( writer
, prefix
->bytes
, prefix
->length
);
451 write_char( writer
, ':' );
453 write_bytes( writer
, attr
->localName
->bytes
, attr
->localName
->length
);
454 write_char( writer
, '=' );
455 write_char( writer
, quote
);
456 if (text
) write_bytes( writer
, text
->value
.bytes
, text
->value
.length
);
457 write_char( writer
, quote
);
462 static inline BOOL
is_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
464 return (WsXmlStringEquals( writer
->current_ns
, ns
, NULL
) == S_OK
);
467 /**************************************************************************
468 * WsGetPrefixFromNamespace [webservices.@]
470 HRESULT WINAPI
WsGetPrefixFromNamespace( WS_XML_WRITER
*handle
, const WS_XML_STRING
*ns
,
471 BOOL required
, const WS_XML_STRING
**prefix
,
474 struct writer
*writer
= (struct writer
*)handle
;
475 WS_XML_ELEMENT_NODE
*elem
;
478 TRACE( "%p %s %d %p %p\n", handle
, debugstr_xmlstr(ns
), required
, prefix
, error
);
479 if (error
) FIXME( "ignoring error parameter\n" );
481 if (!writer
|| !ns
|| !prefix
) return E_INVALIDARG
;
483 elem
= &writer
->current
->hdr
;
484 if (elem
->prefix
&& is_current_namespace( writer
, ns
))
486 *prefix
= elem
->prefix
;
491 if (required
) return WS_E_INVALID_FORMAT
;
498 static HRESULT
set_current_namespace( struct writer
*writer
, const WS_XML_STRING
*ns
)
501 if (!(str
= alloc_xml_string( ns
->bytes
, ns
->length
))) return E_OUTOFMEMORY
;
502 heap_free( writer
->current_ns
);
503 writer
->current_ns
= str
;
507 static HRESULT
write_namespace_attribute( struct writer
*writer
, WS_XML_ATTRIBUTE
*attr
)
509 unsigned char quote
= attr
->singleQuote
? '\'' : '"';
513 /* ' xmlns:prefix="namespace"' */
515 size
= attr
->ns
->length
+ 9 /* ' xmlns=""' */;
516 if (attr
->prefix
) size
+= attr
->prefix
->length
+ 1 /* ':' */;
517 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
519 write_bytes( writer
, (const BYTE
*)" xmlns", 6 );
522 write_char( writer
, ':' );
523 write_bytes( writer
, attr
->prefix
->bytes
, attr
->prefix
->length
);
525 write_char( writer
, '=' );
526 write_char( writer
, quote
);
527 write_bytes( writer
, attr
->ns
->bytes
, attr
->ns
->length
);
528 write_char( writer
, quote
);
533 static HRESULT
write_startelement( struct writer
*writer
)
535 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
539 /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
541 size
= elem
->localName
->length
+ 1 /* '<' */;
542 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
543 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
545 write_char( writer
, '<' );
548 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
549 write_char( writer
, ':' );
551 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
552 for (i
= 0; i
< elem
->attributeCount
; i
++)
554 if (elem
->attributes
[i
]->isXmlNs
) continue;
555 if ((hr
= write_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
557 for (i
= 0; i
< elem
->attributeCount
; i
++)
559 if (!elem
->attributes
[i
]->isXmlNs
|| !elem
->attributes
[i
]->prefix
) continue;
560 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
562 for (i
= 0; i
< elem
->attributeCount
; i
++)
564 if (!elem
->attributes
[i
]->isXmlNs
|| elem
->attributes
[i
]->prefix
) continue;
565 if ((hr
= write_namespace_attribute( writer
, elem
->attributes
[i
] )) != S_OK
) return hr
;
571 static struct node
*write_find_parent_element( struct writer
*writer
)
573 struct node
*node
= writer
->current
;
575 if (node_type( node
) == WS_XML_NODE_TYPE_ELEMENT
) return node
;
576 if (node_type( node
->parent
) == WS_XML_NODE_TYPE_ELEMENT
) return node
->parent
;
580 static HRESULT
write_endelement( struct writer
*writer
)
582 struct node
*node
= write_find_parent_element( writer
);
583 WS_XML_ELEMENT_NODE
*elem
= &node
->hdr
;
587 if (!elem
) return WS_E_INVALID_FORMAT
;
589 /* '</prefix:localname>' */
591 size
= elem
->localName
->length
+ 3 /* '</>' */;
592 if (elem
->prefix
) size
+= elem
->prefix
->length
+ 1 /* ':' */;
593 if ((hr
= write_grow_buffer( writer
, size
)) != S_OK
) return hr
;
595 write_char( writer
, '<' );
596 write_char( writer
, '/' );
599 write_bytes( writer
, elem
->prefix
->bytes
, elem
->prefix
->length
);
600 write_char( writer
, ':' );
602 write_bytes( writer
, elem
->localName
->bytes
, elem
->localName
->length
);
603 write_char( writer
, '>' );
607 static HRESULT
write_add_namespace_attribute( struct writer
*writer
, const WS_XML_STRING
*prefix
,
608 const WS_XML_STRING
*ns
, BOOL single
)
610 WS_XML_ATTRIBUTE
*attr
;
611 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
614 if (!(attr
= heap_alloc_zero( sizeof(*attr
) ))) return E_OUTOFMEMORY
;
616 attr
->singleQuote
= !!single
;
618 if (prefix
&& !(attr
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
620 free_attribute( attr
);
621 return E_OUTOFMEMORY
;
623 if (!(attr
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
625 free_attribute( attr
);
626 return E_OUTOFMEMORY
;
628 if ((hr
= append_attribute( elem
, attr
)) != S_OK
)
630 free_attribute( attr
);
636 static 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
)
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
];
653 static HRESULT
write_set_element_namespace( struct writer
*writer
)
655 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
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
)
664 return set_current_namespace( writer
, elem
->ns
);
667 static HRESULT
write_endstartelement( struct writer
*writer
)
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
, '>' );
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
;
693 static HRESULT
write_close_element( struct writer
*writer
)
697 if (writer
->state
== WRITER_STATE_STARTELEMENT
)
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
;
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
)
722 write_insert_node( writer
, node
);
723 writer
->current
= node
->parent
;
724 writer
->state
= WRITER_STATE_ENDELEMENT
;
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
;
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
;
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
,
768 WS_XML_ATTRIBUTE
*attr
;
769 WS_XML_ELEMENT_NODE
*elem
= &writer
->current
->hdr
;
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
);
797 writer
->state
= WRITER_STATE_STARTATTRIBUTE
;
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
;
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
))
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
;
844 /**************************************************************************
845 * WsWriteEndCData [webservices.@]
847 HRESULT WINAPI
WsWriteEndCData( WS_XML_WRITER
*handle
, WS_ERROR
*error
)
849 struct writer
*writer
= (struct writer
*)handle
;
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
;
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
);
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
)
875 WS_XML_ELEMENT_NODE
*elem
;
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
;
886 if (prefix
&& !(elem
->prefix
= alloc_xml_string( prefix
->bytes
, prefix
->length
)))
889 return E_OUTOFMEMORY
;
891 if (!(elem
->localName
= alloc_xml_string( localname
->bytes
, localname
->length
)))
894 return E_OUTOFMEMORY
;
896 if (!(elem
->ns
= alloc_xml_string( ns
->bytes
, ns
->length
)))
899 return E_OUTOFMEMORY
;
901 write_insert_node( writer
, node
);
902 writer
->state
= WRITER_STATE_STARTELEMENT
;
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
,
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
;
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
);
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
);
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
);
966 static WS_XML_TEXT
*widechar_to_xmltext( const WCHAR
*src
, WS_XML_TEXT_TYPE 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
);
979 FIXME( "unhandled type %u\n", type
);
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
)
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
;
1056 write_insert_node( writer
, node
);
1057 writer
->state
= WRITER_STATE_TEXT
;
1061 static HRESULT
write_text_node( struct writer
*writer
)
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
);
1072 static HRESULT
write_type_text( struct writer
*writer
, WS_TYPE_MAPPING 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
);
1089 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1090 switch (writer
->state
)
1092 case WRITER_STATE_STARTATTRIBUTE
:
1093 write_set_attribute_value( writer
, text
);
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
);
1102 FIXME( "writer state %u not handled\n", writer
->state
);
1107 FIXME( "mapping %u not implemented\n", mapping
);
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
;
1120 FIXME( "description not supported\n" );
1123 if (!(text
= format_bool( value
))) return E_OUTOFMEMORY
;
1124 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
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
;
1137 FIXME( "description not supported\n" );
1140 if (!(text
= format_int8( value
))) return E_OUTOFMEMORY
;
1141 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
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
;
1154 FIXME( "description not supported\n" );
1157 if (!(text
= format_int16( value
))) return E_OUTOFMEMORY
;
1158 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
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
;
1171 FIXME( "description not supported\n" );
1174 if (!(text
= format_int32( value
))) return E_OUTOFMEMORY
;
1175 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
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
;
1188 FIXME( "description not supported\n" );
1191 if (!(text
= format_int64( value
))) return E_OUTOFMEMORY
;
1192 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
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
;
1205 FIXME( "description not supported\n" );
1208 if (!(text
= format_uint8( value
))) return E_OUTOFMEMORY
;
1209 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
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
;
1222 FIXME( "description not supported\n" );
1225 if (!(text
= format_uint16( value
))) return E_OUTOFMEMORY
;
1226 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
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
;
1239 FIXME( "description not supported\n" );
1242 if (!(text
= format_uint32( value
))) return E_OUTOFMEMORY
;
1243 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
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
;
1256 FIXME( "description not supported\n" );
1259 if (!(text
= format_uint64( value
))) return E_OUTOFMEMORY
;
1260 if ((hr
= write_type_text( writer
, mapping
, &text
->text
)) == S_OK
) return S_OK
;
1265 static HRESULT
write_type_wsz( struct writer
*writer
, WS_TYPE_MAPPING mapping
,
1266 const WS_WSZ_DESCRIPTION
*desc
, const WCHAR
*value
)
1273 FIXME( "description not supported\n" );
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
;
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
)
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
;
1296 FIXME( "options 0x%x not supported\n", desc
->options
);
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
)
1307 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1310 case WS_ELEMENT_FIELD_MAPPING
:
1311 if ((hr
= write_add_element_node( writer
, NULL
, desc
->localName
, desc
->ns
)) != S_OK
)
1314 mapping
= WS_ELEMENT_TYPE_MAPPING
;
1317 case WS_TEXT_FIELD_MAPPING
:
1318 switch (writer
->state
)
1320 case WRITER_STATE_STARTELEMENT
:
1321 mapping
= WS_ELEMENT_CONTENT_TYPE_MAPPING
;
1324 case WRITER_STATE_STARTATTRIBUTE
:
1325 mapping
= WS_ATTRIBUTE_TYPE_MAPPING
;
1329 FIXME( "unhandled writer state %u\n", writer
->state
);
1335 FIXME( "field mapping %u not supported\n", desc
->mapping
);
1339 if ((hr
= write_type( writer
, mapping
, desc
->type
, desc
->typeDescription
, option
, value
, size
)) != S_OK
)
1344 case WS_ATTRIBUTE_TYPE_MAPPING
:
1345 writer
->state
= WRITER_STATE_STARTELEMENT
;
1348 case WS_ELEMENT_TYPE_MAPPING
:
1349 if ((hr
= write_close_element( writer
)) != S_OK
) return hr
;
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
)
1371 if (!desc
) return E_INVALIDARG
;
1373 if (desc
->structOptions
)
1375 FIXME( "struct options 0x%x not supported\n", desc
->structOptions
);
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
)
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
,
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
1466 FIXME( "type %u not supported\n", type
);
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
,
1478 struct writer
*writer
= (struct writer
*)handle
;
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
,
1503 struct writer
*writer
= (struct writer
*)handle
;
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
)
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
;
1531 TRACE( "%p %u %u %p %u %p %u %p\n", handle
, mapping
, type
, desc
, option
, value
,
1533 if (error
) FIXME( "ignoring error parameter\n" );
1535 if (!writer
|| !value
) return E_INVALIDARG
;
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
);
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
);
1550 case WS_ANY_ELEMENT_TYPE_MAPPING
:
1551 hr
= write_type( writer
, mapping
, type
, desc
, option
, value
, size
);
1555 FIXME( "mapping %u not implemented\n", mapping
);
1562 WS_TYPE
map_value_type( WS_VALUE_TYPE 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
;
1582 FIXME( "unhandled type %u\n", type
);
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
;
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
;
1608 case WRITER_STATE_STARTELEMENT
:
1609 mapping
= WS_ELEMENT_TYPE_MAPPING
;
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
;
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
);
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
;
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
);
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
);
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
),
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
);