webservices: Implement WS_ADDRESSING_VERSION_TRANSPORT.
[wine.git] / dlls / webservices / msg.c
blob9a196222513dda9560e35570539ad1844f919c9a
1 /*
2 * Copyright 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winuser.h"
24 #include "rpc.h"
25 #include "webservices.h"
27 #include "wine/debug.h"
28 #include "wine/list.h"
29 #include "webservices_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
33 static const char ns_env_1_1[] = "http://schemas.xmlsoap.org/soap/envelope/";
34 static const char ns_env_1_2[] = "http://www.w3.org/2003/05/soap-envelope";
35 static const char ns_addr_0_9[] = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
36 static const char ns_addr_1_0[] = "http://www.w3.org/2005/08/addressing";
38 static const struct prop_desc msg_props[] =
40 { sizeof(WS_MESSAGE_STATE), TRUE }, /* WS_MESSAGE_PROPERTY_STATE */
41 { sizeof(WS_HEAP *), TRUE }, /* WS_MESSAGE_PROPERTY_HEAP */
42 { sizeof(WS_ENVELOPE_VERSION), TRUE }, /* WS_MESSAGE_PROPERTY_ENVELOPE_VERSION */
43 { sizeof(WS_ADDRESSING_VERSION), TRUE }, /* WS_MESSAGE_PROPERTY_ADDRESSING_VERSION */
44 { sizeof(WS_XML_BUFFER *), TRUE }, /* WS_MESSAGE_PROPERTY_HEADER_BUFFER */
45 { sizeof(WS_XML_NODE_POSITION *), TRUE }, /* WS_MESSAGE_PROPERTY_HEADER_POSITION */
46 { sizeof(WS_XML_READER *), TRUE }, /* WS_MESSAGE_PROPERTY_BODY_READER */
47 { sizeof(WS_XML_WRITER *), TRUE }, /* WS_MESSAGE_PROPERTY_BODY_WRITER */
48 { sizeof(BOOL), TRUE }, /* WS_MESSAGE_PROPERTY_IS_ADDRESSED */
51 struct header
53 WS_HEADER_TYPE type;
54 WS_XML_UTF8_TEXT text;
57 struct msg
59 WS_MESSAGE_INITIALIZATION init;
60 WS_MESSAGE_STATE state;
61 GUID id;
62 WS_ENVELOPE_VERSION version_env;
63 WS_ADDRESSING_VERSION version_addr;
64 BOOL is_addressed;
65 WS_STRING addr;
66 WS_HEAP *heap;
67 WS_XML_BUFFER *buf;
68 WS_XML_WRITER *writer;
69 WS_XML_WRITER *writer_body;
70 ULONG header_count;
71 ULONG header_size;
72 struct header **header;
73 ULONG prop_count;
74 struct prop prop[sizeof(msg_props)/sizeof(msg_props[0])];
77 #define HEADER_ARRAY_SIZE 2
78 static struct msg *alloc_msg(void)
80 static const ULONG count = sizeof(msg_props)/sizeof(msg_props[0]);
81 struct msg *ret;
82 ULONG size = sizeof(*ret) + prop_size( msg_props, count );
84 if (!(ret = heap_alloc_zero( size ))) return NULL;
85 if (!(ret->header = heap_alloc( HEADER_ARRAY_SIZE * sizeof(struct header *) )))
87 heap_free( ret );
88 return NULL;
90 ret->state = WS_MESSAGE_STATE_EMPTY;
91 ret->header_size = HEADER_ARRAY_SIZE;
92 prop_init( msg_props, count, ret->prop, &ret[1] );
93 ret->prop_count = count;
94 return ret;
97 static void free_headers( struct header **header, ULONG count )
99 ULONG i;
100 for (i = 0; i < count; i++) heap_free( header[i] );
103 static void free_msg( struct msg *msg )
105 if (!msg) return;
106 WsFreeWriter( msg->writer );
107 WsFreeHeap( msg->heap );
108 heap_free( msg->addr.chars );
109 free_headers( msg->header, msg->header_count );
110 heap_free( msg->header );
111 heap_free( msg );
114 #define HEAP_MAX_SIZE (1 << 16)
115 static HRESULT create_msg( WS_ENVELOPE_VERSION env_version, WS_ADDRESSING_VERSION addr_version,
116 const WS_MESSAGE_PROPERTY *properties, ULONG count, WS_MESSAGE **handle )
118 struct msg *msg;
119 HRESULT hr;
120 ULONG i;
122 if (!(msg = alloc_msg())) return E_OUTOFMEMORY;
124 for (i = 0; i < count; i++)
126 if (properties[i].id == WS_MESSAGE_PROPERTY_ENVELOPE_VERSION ||
127 properties[i].id == WS_MESSAGE_PROPERTY_ADDRESSING_VERSION)
129 free_msg( msg );
130 return E_INVALIDARG;
132 hr = prop_set( msg->prop, msg->prop_count, properties[i].id, properties[i].value,
133 properties[i].valueSize );
134 if (hr != S_OK)
136 free_msg( msg );
137 return hr;
141 if ((hr = WsCreateHeap( HEAP_MAX_SIZE, 0, NULL, 0, &msg->heap, NULL )) != S_OK)
143 free_msg( msg );
144 return hr;
146 if ((hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &msg->buf, NULL )) != S_OK)
148 free_msg( msg );
149 return hr;
152 UuidCreate( &msg->id );
153 msg->version_env = env_version;
154 msg->version_addr = addr_version;
156 *handle = (WS_MESSAGE *)msg;
157 return S_OK;
160 /**************************************************************************
161 * WsCreateMessage [webservices.@]
163 HRESULT WINAPI WsCreateMessage( WS_ENVELOPE_VERSION env_version, WS_ADDRESSING_VERSION addr_version,
164 const WS_MESSAGE_PROPERTY *properties, ULONG count, WS_MESSAGE **handle,
165 WS_ERROR *error )
167 TRACE( "%u %u %p %u %p %p\n", env_version, addr_version, properties, count, handle, error );
168 if (error) FIXME( "ignoring error parameter\n" );
170 if (!handle || !env_version || !addr_version) return E_INVALIDARG;
171 return create_msg( env_version, addr_version, properties, count, handle );
174 /**************************************************************************
175 * WsCreateMessageForChannel [webservices.@]
177 HRESULT WINAPI WsCreateMessageForChannel( WS_CHANNEL *channel_handle, const WS_MESSAGE_PROPERTY *properties,
178 ULONG count, WS_MESSAGE **handle, WS_ERROR *error )
180 WS_ENVELOPE_VERSION version_env;
181 WS_ADDRESSING_VERSION version_addr;
182 HRESULT hr;
184 TRACE( "%p %p %u %p %p\n", channel_handle, properties, count, handle, error );
185 if (error) FIXME( "ignoring error parameter\n" );
187 if (!channel_handle || !handle) return E_INVALIDARG;
189 if ((hr = WsGetChannelProperty( channel_handle, WS_CHANNEL_PROPERTY_ENVELOPE_VERSION, &version_env,
190 sizeof(version_env), NULL )) != S_OK || !version_env)
191 version_env = WS_ENVELOPE_VERSION_SOAP_1_2;
193 if ((hr = WsGetChannelProperty( channel_handle, WS_CHANNEL_PROPERTY_ADDRESSING_VERSION, &version_addr,
194 sizeof(version_addr), NULL )) != S_OK || !version_addr)
195 version_addr = WS_ADDRESSING_VERSION_1_0;
197 return create_msg( version_env, version_addr, properties, count, handle );
200 /**************************************************************************
201 * WsFreeMessage [webservices.@]
203 void WINAPI WsFreeMessage( WS_MESSAGE *handle )
205 struct msg *msg = (struct msg *)handle;
207 TRACE( "%p\n", handle );
208 free_msg( msg );
211 /**************************************************************************
212 * WsGetMessageProperty [webservices.@]
214 HRESULT WINAPI WsGetMessageProperty( WS_MESSAGE *handle, WS_MESSAGE_PROPERTY_ID id, void *buf,
215 ULONG size, WS_ERROR *error )
217 struct msg *msg = (struct msg *)handle;
219 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
220 if (error) FIXME( "ignoring error parameter\n" );
222 if (!handle) return E_INVALIDARG;
224 switch (id)
226 case WS_MESSAGE_PROPERTY_STATE:
227 if (!buf || size != sizeof(msg->state)) return E_INVALIDARG;
228 *(WS_MESSAGE_STATE *)buf = msg->state;
229 return S_OK;
231 case WS_MESSAGE_PROPERTY_HEAP:
232 if (!buf || size != sizeof(msg->heap)) return E_INVALIDARG;
233 *(WS_HEAP **)buf = msg->heap;
234 return S_OK;
236 case WS_MESSAGE_PROPERTY_ENVELOPE_VERSION:
237 if (!buf || size != sizeof(msg->version_env)) return E_INVALIDARG;
238 *(WS_ENVELOPE_VERSION *)buf = msg->version_env;
239 return S_OK;
241 case WS_MESSAGE_PROPERTY_ADDRESSING_VERSION:
242 if (!buf || size != sizeof(msg->version_addr)) return E_INVALIDARG;
243 *(WS_ADDRESSING_VERSION *)buf = msg->version_addr;
244 return S_OK;
246 case WS_MESSAGE_PROPERTY_HEADER_BUFFER:
247 if (!buf || size != sizeof(msg->buf)) return E_INVALIDARG;
248 *(WS_XML_BUFFER **)buf = msg->buf;
249 return S_OK;
251 case WS_MESSAGE_PROPERTY_IS_ADDRESSED:
252 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
253 *(BOOL *)buf = msg->is_addressed;
254 return S_OK;
256 default:
257 return prop_get( msg->prop, msg->prop_count, id, buf, size );
261 /**************************************************************************
262 * WsSetMessageProperty [webservices.@]
264 HRESULT WINAPI WsSetMessageProperty( WS_MESSAGE *handle, WS_MESSAGE_PROPERTY_ID id, const void *value,
265 ULONG size, WS_ERROR *error )
267 struct msg *msg = (struct msg *)handle;
269 TRACE( "%p %u %p %u\n", handle, id, value, size );
270 if (error) FIXME( "ignoring error parameter\n" );
272 if (!handle) return E_INVALIDARG;
274 switch (id)
276 case WS_MESSAGE_PROPERTY_STATE:
277 case WS_MESSAGE_PROPERTY_ENVELOPE_VERSION:
278 case WS_MESSAGE_PROPERTY_ADDRESSING_VERSION:
279 case WS_MESSAGE_PROPERTY_IS_ADDRESSED:
280 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
281 return E_INVALIDARG;
283 default:
284 break;
286 return prop_set( msg->prop, msg->prop_count, id, value, size );
289 /**************************************************************************
290 * WsAddressMessage [webservices.@]
292 HRESULT WINAPI WsAddressMessage( WS_MESSAGE *handle, const WS_ENDPOINT_ADDRESS *addr, WS_ERROR *error )
294 struct msg *msg = (struct msg *)handle;
296 TRACE( "%p %p %p\n", handle, addr, error );
297 if (error) FIXME( "ignoring error parameter\n" );
298 if (addr && (addr->headers || addr->extensions || addr->identity))
300 FIXME( "headers, extensions or identity not supported\n" );
301 return E_NOTIMPL;
304 if (!handle) return E_INVALIDARG;
305 if (msg->state < WS_MESSAGE_STATE_INITIALIZED || msg->is_addressed) return WS_E_INVALID_OPERATION;
307 if (addr && addr->url.length)
309 if (!(msg->addr.chars = heap_alloc( addr->url.length * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
310 memcpy( msg->addr.chars, addr->url.chars, addr->url.length * sizeof(WCHAR) );
311 msg->addr.length = addr->url.length;
314 msg->is_addressed = TRUE;
315 return S_OK;
318 static HRESULT get_env_namespace( WS_ENVELOPE_VERSION ver, WS_XML_STRING *str )
320 switch (ver)
322 case WS_ENVELOPE_VERSION_SOAP_1_1:
323 str->bytes = (BYTE *)ns_env_1_1;
324 str->length = sizeof(ns_env_1_1)/sizeof(ns_env_1_1[0]) - 1;
325 return S_OK;
327 case WS_ENVELOPE_VERSION_SOAP_1_2:
328 str->bytes = (BYTE *)ns_env_1_2;
329 str->length = sizeof(ns_env_1_2)/sizeof(ns_env_1_2[0]) - 1;
330 return S_OK;
332 default:
333 ERR( "unhandled envelope version %u\n", ver );
334 return E_NOTIMPL;
338 static HRESULT get_addr_namespace( WS_ADDRESSING_VERSION ver, WS_XML_STRING *str )
340 switch (ver)
342 case WS_ADDRESSING_VERSION_0_9:
343 str->bytes = (BYTE *)ns_addr_0_9;
344 str->length = sizeof(ns_addr_0_9)/sizeof(ns_addr_0_9[0]) - 1;
345 return S_OK;
347 case WS_ADDRESSING_VERSION_1_0:
348 str->bytes = (BYTE *)ns_addr_1_0;
349 str->length = sizeof(ns_addr_1_0)/sizeof(ns_addr_1_0[0]) - 1;
350 return S_OK;
352 case WS_ADDRESSING_VERSION_TRANSPORT:
353 str->bytes = NULL;
354 str->length = 0;
355 return S_OK;
357 default:
358 ERR( "unhandled addressing version %u\n", ver );
359 return E_NOTIMPL;
363 static const WS_XML_STRING *get_header_name( WS_HEADER_TYPE type )
365 static const WS_XML_STRING action = {6, (BYTE *)"Action"}, to = {2, (BYTE *)"To"};
366 static const WS_XML_STRING msgid = {9, (BYTE *)"MessageID"}, relto = {9, (BYTE *)"RelatesTo"};
367 static const WS_XML_STRING from = {4, (BYTE *)"From"}, replyto = {7, (BYTE *)"ReplyTo"};
368 static const WS_XML_STRING faultto = {7, (BYTE *)"FaultTo"};
370 switch (type)
372 case WS_ACTION_HEADER: return &action;
373 case WS_TO_HEADER: return &to;
374 case WS_MESSAGE_ID_HEADER: return &msgid;
375 case WS_RELATES_TO_HEADER: return &relto;
376 case WS_FROM_HEADER: return &from;
377 case WS_REPLY_TO_HEADER: return &replyto;
378 case WS_FAULT_TO_HEADER: return &faultto;
379 default:
380 ERR( "unknown type %u\n", type );
381 return NULL;
385 static HRESULT write_header( WS_XML_WRITER *writer, const struct header *header )
387 static const WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"};
388 static const WS_XML_STRING understand = {14, (BYTE *)"mustUnderstand"}, ns = {0, NULL};
389 const WS_XML_STRING *localname = get_header_name( header->type );
390 WS_XML_INT32_TEXT one = {{WS_XML_TEXT_TYPE_INT32}, 1};
391 HRESULT hr;
393 if ((hr = WsWriteStartElement( writer, &prefix_a, localname, &ns, NULL )) != S_OK) return hr;
394 if ((hr = WsWriteStartAttribute( writer, &prefix_s, &understand, &ns, FALSE, NULL )) != S_OK) return hr;
395 if ((hr = WsWriteText( writer, &one.text, NULL )) != S_OK) return hr;
396 if ((hr = WsWriteEndAttribute( writer, NULL )) != S_OK) return hr;
397 if ((hr = WsWriteText( writer, &header->text.text, NULL )) != S_OK) return hr;
398 return WsWriteEndElement( writer, NULL );
401 static HRESULT write_envelope_start( struct msg *msg, WS_XML_WRITER *writer )
403 static const char anonymous[] = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
404 static const WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"};
405 static const WS_XML_STRING envelope = {8, (BYTE *)"Envelope"}, header = {6, (BYTE *)"Header"};
406 static const WS_XML_STRING msgid = {9, (BYTE *)"MessageID"}, replyto = {7, (BYTE *)"ReplyTo"};
407 static const WS_XML_STRING address = {7, (BYTE *)"Address"}, body = {4, (BYTE *)"Body"};
408 WS_XML_STRING ns_env, ns_addr;
409 WS_XML_UTF8_TEXT urn, addr;
410 HRESULT hr;
411 ULONG i;
413 if ((hr = get_env_namespace( msg->version_env, &ns_env )) != S_OK) return hr;
414 if ((hr = get_addr_namespace( msg->version_addr, &ns_addr )) != S_OK) return hr;
416 if ((hr = WsWriteStartElement( writer, &prefix_s, &envelope, &ns_env, NULL )) != S_OK) return hr;
417 if (msg->version_addr < WS_ADDRESSING_VERSION_TRANSPORT &&
418 (hr = WsWriteXmlnsAttribute( writer, &prefix_a, &ns_addr, FALSE, NULL )) != S_OK) return hr;
419 if ((hr = WsWriteStartElement( writer, &prefix_s, &header, &ns_env, NULL )) != S_OK) return hr;
421 if (msg->version_addr < WS_ADDRESSING_VERSION_TRANSPORT)
423 if ((hr = WsWriteStartElement( writer, &prefix_a, &msgid, &ns_addr, NULL )) != S_OK) return hr;
424 urn.text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID;
425 memcpy( &urn.value, &msg->id, sizeof(msg->id) );
426 if ((hr = WsWriteText( writer, &urn.text, NULL )) != S_OK) return hr;
427 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:MessageID> */
430 for (i = 0; i < msg->header_count; i++)
432 if ((hr = write_header( writer, msg->header[i] )) != S_OK) return hr;
435 if (msg->version_addr == WS_ADDRESSING_VERSION_0_9)
437 if ((hr = WsWriteStartElement( writer, &prefix_a, &replyto, &ns_addr, NULL )) != S_OK) return hr;
438 if ((hr = WsWriteStartElement( writer, &prefix_a, &address, &ns_addr, NULL )) != S_OK) return hr;
440 addr.text.textType = WS_XML_TEXT_TYPE_UTF8;
441 addr.value.bytes = (BYTE *)anonymous;
442 addr.value.length = sizeof(anonymous) - 1;
443 if ((hr = WsWriteText( writer, &addr.text, NULL )) != S_OK) return hr;
444 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:Address> */
445 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:ReplyTo> */
448 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </s:Header> */
449 return WsWriteStartElement( writer, &prefix_s, &body, &ns_env, NULL ); /* <s:Body> */
452 static HRESULT write_envelope_end( struct msg *msg, WS_XML_WRITER *writer )
454 HRESULT hr;
455 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </s:Body> */
456 return WsWriteEndElement( writer, NULL ); /* </s:Envelope> */
459 static HRESULT write_envelope( struct msg *msg )
461 HRESULT hr;
462 if (!msg->writer && (hr = WsCreateWriter( NULL, 0, &msg->writer, NULL )) != S_OK) return hr;
463 if (!msg->buf && (hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &msg->buf, NULL )) != S_OK) return hr;
464 if ((hr = WsSetOutputToBuffer( msg->writer, msg->buf, NULL, 0, NULL )) != S_OK) return hr;
465 if ((hr = write_envelope_start( msg, msg->writer )) != S_OK) return hr;
466 return write_envelope_end( msg, msg->writer );
469 /**************************************************************************
470 * WsWriteEnvelopeStart [webservices.@]
472 HRESULT WINAPI WsWriteEnvelopeStart( WS_MESSAGE *handle, WS_XML_WRITER *writer,
473 WS_MESSAGE_DONE_CALLBACK cb, void *state, WS_ERROR *error )
475 struct msg *msg = (struct msg *)handle;
476 HRESULT hr;
478 TRACE( "%p %p %p %p %p\n", handle, writer, cb, state, error );
479 if (error) FIXME( "ignoring error parameter\n" );
480 if (cb)
482 FIXME( "callback not supported\n" );
483 return E_NOTIMPL;
486 if (!handle || !writer) return E_INVALIDARG;
487 if (msg->state != WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
489 if ((hr = write_envelope( msg )) != S_OK) return hr;
490 if ((hr = write_envelope_start( msg, writer )) != S_OK) return hr;
492 msg->writer_body = writer;
493 msg->state = WS_MESSAGE_STATE_WRITING;
494 return S_OK;
497 /**************************************************************************
498 * WsWriteEnvelopeEnd [webservices.@]
500 HRESULT WINAPI WsWriteEnvelopeEnd( WS_MESSAGE *handle, WS_ERROR *error )
502 struct msg *msg = (struct msg *)handle;
503 HRESULT hr;
505 TRACE( "%p %p\n", handle, error );
506 if (error) FIXME( "ignoring error parameter\n" );
508 if (!handle) return E_INVALIDARG;
509 if (msg->state != WS_MESSAGE_STATE_WRITING) return WS_E_INVALID_OPERATION;
511 if ((hr = write_envelope_end( msg, msg->writer_body )) != S_OK) return hr;
513 msg->state = WS_MESSAGE_STATE_DONE;
514 return S_OK;
517 /**************************************************************************
518 * WsWriteBody [webservices.@]
520 HRESULT WINAPI WsWriteBody( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *desc, WS_WRITE_OPTION option,
521 const void *value, ULONG size, WS_ERROR *error )
523 struct msg *msg = (struct msg *)handle;
524 HRESULT hr;
526 TRACE( "%p %p %08x %p %u %p\n", handle, desc, option, value, size, error );
527 if (error) FIXME( "ignoring error parameter\n" );
529 if (!handle || !desc) return E_INVALIDARG;
530 if (msg->state != WS_MESSAGE_STATE_WRITING) return WS_E_INVALID_OPERATION;
532 if (desc->elementLocalName &&
533 (hr = WsWriteStartElement( msg->writer_body, NULL, desc->elementLocalName, desc->elementNs,
534 NULL )) != S_OK) return hr;
536 if ((hr = WsWriteType( msg->writer_body, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription,
537 option, value, size, NULL )) != S_OK) return hr;
539 if (desc->elementLocalName) hr = WsWriteEndElement( msg->writer_body, NULL );
540 return hr;
543 /**************************************************************************
544 * WsInitializeMessage [webservices.@]
546 HRESULT WINAPI WsInitializeMessage( WS_MESSAGE *handle, WS_MESSAGE_INITIALIZATION init,
547 WS_MESSAGE *src_handle, WS_ERROR *error )
549 struct msg *msg = (struct msg *)handle;
551 TRACE( "%p %u %p %p\n", handle, init, src_handle, error );
552 if (error) FIXME( "ignoring error parameter\n" );
553 if (src_handle)
555 FIXME( "src message not supported\n" );
556 return E_NOTIMPL;
559 if (!handle || init > WS_FAULT_MESSAGE) return E_INVALIDARG;
560 if (msg->state >= WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
562 msg->init = init;
563 msg->state = WS_MESSAGE_STATE_INITIALIZED;
564 return write_envelope( msg );
567 static inline void set_utf8_text( WS_XML_UTF8_TEXT *text, BYTE *bytes, ULONG len )
569 text->text.textType = WS_XML_TEXT_TYPE_UTF8;
570 text->value.bytes = bytes;
571 text->value.length = len;
574 static HRESULT alloc_header( WS_HEADER_TYPE type, WS_TYPE value_type, WS_WRITE_OPTION option,
575 const void *value, ULONG size, struct header **ret )
577 struct header *header;
579 switch (value_type)
581 case WS_WSZ_TYPE:
583 int len;
584 const WCHAR *src;
586 if (option != WS_WRITE_REQUIRED_POINTER || size != sizeof(WCHAR *)) return E_INVALIDARG;
588 src = *(const WCHAR **)value;
589 len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL ) - 1;
590 if (!(header = heap_alloc( sizeof(*header) + len ))) return E_OUTOFMEMORY;
591 set_utf8_text( &header->text, (BYTE *)(header + 1), len );
592 WideCharToMultiByte( CP_UTF8, 0, src, -1, (char *)header->text.value.bytes, len, NULL, NULL );
593 break;
595 case WS_XML_STRING_TYPE:
597 const WS_XML_STRING *str = value;
599 if (option != WS_WRITE_REQUIRED_VALUE)
601 FIXME( "unhandled write option %u\n", option );
602 return E_NOTIMPL;
604 if (size != sizeof(*str)) return E_INVALIDARG;
605 if (!(header = heap_alloc( sizeof(*header) + str->length ))) return E_OUTOFMEMORY;
606 set_utf8_text( &header->text, (BYTE *)(header + 1), str->length );
607 memcpy( header->text.value.bytes, str->bytes, str->length );
608 break;
610 case WS_STRING_TYPE:
612 int len;
613 const WS_STRING *str = value;
615 if (option != WS_WRITE_REQUIRED_VALUE)
617 FIXME( "unhandled write option %u\n", option );
618 return E_NOTIMPL;
620 if (size != sizeof(*str)) return E_INVALIDARG;
621 len = WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, NULL, 0, NULL, NULL );
622 if (!(header = heap_alloc( sizeof(*header) + len ))) return E_OUTOFMEMORY;
623 set_utf8_text( &header->text, (BYTE *)(header + 1), len );
624 WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, (char *)header->text.value.bytes,
625 len, NULL, NULL );
626 break;
628 default:
629 FIXME( "unhandled type %u\n", value_type );
630 return E_NOTIMPL;
633 header->type = type;
634 *ret = header;
635 return S_OK;
638 /**************************************************************************
639 * WsSetHeader [webservices.@]
641 HRESULT WINAPI WsSetHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_TYPE value_type,
642 WS_WRITE_OPTION option, const void *value, ULONG size, WS_ERROR *error )
644 struct msg *msg = (struct msg *)handle;
645 struct header *header;
646 BOOL found = FALSE;
647 HRESULT hr;
648 ULONG i;
650 TRACE( "%p %u %u %08x %p %u %p\n", handle, type, value_type, option, value, size, error );
651 if (error) FIXME( "ignoring error parameter\n" );
653 if (!handle || type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) return E_INVALIDARG;
654 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
656 for (i = 0; i < msg->header_count; i++)
658 if (msg->header[i]->type == type)
660 found = TRUE;
661 break;
665 if (found) heap_free( msg->header[i] );
666 else
668 if (msg->header_count == msg->header_size)
670 struct header **tmp;
671 if (!(tmp = heap_realloc( msg->header, 2 * msg->header_size * sizeof(struct header *) )))
672 return E_OUTOFMEMORY;
673 msg->header = tmp;
674 msg->header_size *= 2;
676 i = msg->header_count++;
679 if ((hr = alloc_header( type, value_type, option, value, size, &header )) != S_OK) return hr;
680 msg->header[i] = header;
681 return write_envelope( msg );
684 /**************************************************************************
685 * WsRemoveHeader [webservices.@]
687 HRESULT WINAPI WsRemoveHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_ERROR *error )
689 struct msg *msg = (struct msg *)handle;
690 BOOL removed = FALSE;
691 ULONG i;
693 TRACE( "%p %u %p\n", handle, type, error );
694 if (error) FIXME( "ignoring error parameter\n" );
696 if (!handle) return E_INVALIDARG;
697 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
698 if (type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) return E_INVALIDARG;
700 for (i = 0; i < msg->header_count; i++)
702 if (msg->header[i]->type == type)
704 heap_free( msg->header[i] );
705 memmove( &msg->header[i], &msg->header[i + 1], (msg->header_count - i) * sizeof(struct header *) );
706 msg->header_count--;
707 removed = TRUE;
708 break;
712 if (removed) return write_envelope( msg );
713 return S_OK;