d2d1: Use d2d_point_set() in d2d_rectangle_geometry_init().
[wine.git] / dlls / webservices / msg.c
blobe7a7969248365edaca7021a7e44995afe1277f91
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 "wine/unicode.h"
30 #include "webservices_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
34 static const char ns_env_1_1[] = "http://schemas.xmlsoap.org/soap/envelope/";
35 static const char ns_env_1_2[] = "http://www.w3.org/2003/05/soap-envelope";
36 static const char ns_addr_0_9[] = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
37 static const char ns_addr_1_0[] = "http://www.w3.org/2005/08/addressing";
39 static const struct prop_desc msg_props[] =
41 { sizeof(WS_MESSAGE_STATE), TRUE }, /* WS_MESSAGE_PROPERTY_STATE */
42 { sizeof(WS_HEAP *), TRUE }, /* WS_MESSAGE_PROPERTY_HEAP */
43 { sizeof(WS_ENVELOPE_VERSION), TRUE }, /* WS_MESSAGE_PROPERTY_ENVELOPE_VERSION */
44 { sizeof(WS_ADDRESSING_VERSION), TRUE }, /* WS_MESSAGE_PROPERTY_ADDRESSING_VERSION */
45 { sizeof(WS_XML_BUFFER *), TRUE }, /* WS_MESSAGE_PROPERTY_HEADER_BUFFER */
46 { sizeof(WS_XML_NODE_POSITION *), TRUE }, /* WS_MESSAGE_PROPERTY_HEADER_POSITION */
47 { sizeof(WS_XML_READER *), TRUE }, /* WS_MESSAGE_PROPERTY_BODY_READER */
48 { sizeof(WS_XML_WRITER *), TRUE }, /* WS_MESSAGE_PROPERTY_BODY_WRITER */
49 { sizeof(BOOL), TRUE }, /* WS_MESSAGE_PROPERTY_IS_ADDRESSED */
52 struct header
54 WS_HEADER_TYPE type;
55 BOOL mapped;
56 WS_XML_STRING name;
57 WS_XML_STRING ns;
58 union
60 WS_XML_BUFFER *buf;
61 WS_XML_STRING *text;
62 } u;
65 struct msg
67 WS_MESSAGE_INITIALIZATION init;
68 WS_MESSAGE_STATE state;
69 GUID id;
70 WS_ENVELOPE_VERSION version_env;
71 WS_ADDRESSING_VERSION version_addr;
72 BOOL is_addressed;
73 WS_STRING addr;
74 WS_STRING action;
75 WS_HEAP *heap;
76 WS_XML_BUFFER *buf;
77 WS_XML_WRITER *writer;
78 WS_XML_WRITER *writer_body;
79 WS_XML_READER *reader_body;
80 ULONG header_count;
81 ULONG header_size;
82 struct header **header;
83 WS_PROXY_MESSAGE_CALLBACK_CONTEXT ctx_send;
84 WS_PROXY_MESSAGE_CALLBACK_CONTEXT ctx_receive;
85 ULONG prop_count;
86 struct prop prop[sizeof(msg_props)/sizeof(msg_props[0])];
89 #define HEADER_ARRAY_SIZE 2
90 static struct msg *alloc_msg(void)
92 static const ULONG count = sizeof(msg_props)/sizeof(msg_props[0]);
93 struct msg *ret;
94 ULONG size = sizeof(*ret) + prop_size( msg_props, count );
96 if (!(ret = heap_alloc_zero( size ))) return NULL;
97 if (!(ret->header = heap_alloc( HEADER_ARRAY_SIZE * sizeof(struct header *) )))
99 heap_free( ret );
100 return NULL;
102 ret->state = WS_MESSAGE_STATE_EMPTY;
103 ret->header_size = HEADER_ARRAY_SIZE;
104 prop_init( msg_props, count, ret->prop, &ret[1] );
105 ret->prop_count = count;
106 return ret;
109 static void free_header( struct header *header )
111 heap_free( header->name.bytes );
112 heap_free( header->ns.bytes );
113 if (header->mapped) heap_free( header->u.text );
114 heap_free( header );
117 static void free_msg( struct msg *msg )
119 ULONG i;
120 if (!msg) return;
121 WsFreeWriter( msg->writer );
122 WsFreeHeap( msg->heap );
123 heap_free( msg->addr.chars );
124 heap_free( msg->action.chars );
125 for (i = 0; i < msg->header_count; i++) free_header( msg->header[i] );
126 heap_free( msg->header );
127 heap_free( msg );
130 #define HEAP_MAX_SIZE (1 << 16)
131 static HRESULT create_msg( WS_ENVELOPE_VERSION env_version, WS_ADDRESSING_VERSION addr_version,
132 const WS_MESSAGE_PROPERTY *properties, ULONG count, WS_MESSAGE **handle )
134 struct msg *msg;
135 HRESULT hr;
136 ULONG i;
138 if (!(msg = alloc_msg())) return E_OUTOFMEMORY;
140 for (i = 0; i < count; i++)
142 if (properties[i].id == WS_MESSAGE_PROPERTY_ENVELOPE_VERSION ||
143 properties[i].id == WS_MESSAGE_PROPERTY_ADDRESSING_VERSION)
145 free_msg( msg );
146 return E_INVALIDARG;
148 hr = prop_set( msg->prop, msg->prop_count, properties[i].id, properties[i].value,
149 properties[i].valueSize );
150 if (hr != S_OK)
152 free_msg( msg );
153 return hr;
157 if ((hr = WsCreateHeap( HEAP_MAX_SIZE, 0, NULL, 0, &msg->heap, NULL )) != S_OK)
159 free_msg( msg );
160 return hr;
162 if ((hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &msg->buf, NULL )) != S_OK)
164 free_msg( msg );
165 return hr;
168 UuidCreate( &msg->id );
169 msg->version_env = env_version;
170 msg->version_addr = addr_version;
172 *handle = (WS_MESSAGE *)msg;
173 return S_OK;
176 /**************************************************************************
177 * WsCreateMessage [webservices.@]
179 HRESULT WINAPI WsCreateMessage( WS_ENVELOPE_VERSION env_version, WS_ADDRESSING_VERSION addr_version,
180 const WS_MESSAGE_PROPERTY *properties, ULONG count, WS_MESSAGE **handle,
181 WS_ERROR *error )
183 TRACE( "%u %u %p %u %p %p\n", env_version, addr_version, properties, count, handle, error );
184 if (error) FIXME( "ignoring error parameter\n" );
186 if (!handle || !env_version || !addr_version) return E_INVALIDARG;
187 return create_msg( env_version, addr_version, properties, count, handle );
190 /**************************************************************************
191 * WsCreateMessageForChannel [webservices.@]
193 HRESULT WINAPI WsCreateMessageForChannel( WS_CHANNEL *channel_handle, const WS_MESSAGE_PROPERTY *properties,
194 ULONG count, WS_MESSAGE **handle, WS_ERROR *error )
196 WS_ENVELOPE_VERSION version_env;
197 WS_ADDRESSING_VERSION version_addr;
198 HRESULT hr;
200 TRACE( "%p %p %u %p %p\n", channel_handle, properties, count, handle, error );
201 if (error) FIXME( "ignoring error parameter\n" );
203 if (!channel_handle || !handle) return E_INVALIDARG;
205 if ((hr = WsGetChannelProperty( channel_handle, WS_CHANNEL_PROPERTY_ENVELOPE_VERSION, &version_env,
206 sizeof(version_env), NULL )) != S_OK || !version_env)
207 version_env = WS_ENVELOPE_VERSION_SOAP_1_2;
209 if ((hr = WsGetChannelProperty( channel_handle, WS_CHANNEL_PROPERTY_ADDRESSING_VERSION, &version_addr,
210 sizeof(version_addr), NULL )) != S_OK || !version_addr)
211 version_addr = WS_ADDRESSING_VERSION_1_0;
213 return create_msg( version_env, version_addr, properties, count, handle );
216 /**************************************************************************
217 * WsFreeMessage [webservices.@]
219 void WINAPI WsFreeMessage( WS_MESSAGE *handle )
221 struct msg *msg = (struct msg *)handle;
223 TRACE( "%p\n", handle );
224 free_msg( msg );
227 /**************************************************************************
228 * WsGetMessageProperty [webservices.@]
230 HRESULT WINAPI WsGetMessageProperty( WS_MESSAGE *handle, WS_MESSAGE_PROPERTY_ID id, void *buf,
231 ULONG size, WS_ERROR *error )
233 struct msg *msg = (struct msg *)handle;
235 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
236 if (error) FIXME( "ignoring error parameter\n" );
238 if (!handle) return E_INVALIDARG;
240 switch (id)
242 case WS_MESSAGE_PROPERTY_STATE:
243 if (!buf || size != sizeof(msg->state)) return E_INVALIDARG;
244 *(WS_MESSAGE_STATE *)buf = msg->state;
245 return S_OK;
247 case WS_MESSAGE_PROPERTY_HEAP:
248 if (!buf || size != sizeof(msg->heap)) return E_INVALIDARG;
249 *(WS_HEAP **)buf = msg->heap;
250 return S_OK;
252 case WS_MESSAGE_PROPERTY_ENVELOPE_VERSION:
253 if (!buf || size != sizeof(msg->version_env)) return E_INVALIDARG;
254 *(WS_ENVELOPE_VERSION *)buf = msg->version_env;
255 return S_OK;
257 case WS_MESSAGE_PROPERTY_ADDRESSING_VERSION:
258 if (!buf || size != sizeof(msg->version_addr)) return E_INVALIDARG;
259 *(WS_ADDRESSING_VERSION *)buf = msg->version_addr;
260 return S_OK;
262 case WS_MESSAGE_PROPERTY_HEADER_BUFFER:
263 if (!buf || size != sizeof(msg->buf)) return E_INVALIDARG;
264 *(WS_XML_BUFFER **)buf = msg->buf;
265 return S_OK;
267 case WS_MESSAGE_PROPERTY_BODY_READER:
268 if (!buf || size != sizeof(msg->reader_body)) return E_INVALIDARG;
269 *(WS_XML_READER **)buf = msg->reader_body;
270 return S_OK;
272 case WS_MESSAGE_PROPERTY_BODY_WRITER:
273 if (!buf || size != sizeof(msg->writer_body)) return E_INVALIDARG;
274 *(WS_XML_WRITER **)buf = msg->writer_body;
275 return S_OK;
277 case WS_MESSAGE_PROPERTY_IS_ADDRESSED:
278 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
279 *(BOOL *)buf = msg->is_addressed;
280 return S_OK;
282 default:
283 return prop_get( msg->prop, msg->prop_count, id, buf, size );
287 /**************************************************************************
288 * WsSetMessageProperty [webservices.@]
290 HRESULT WINAPI WsSetMessageProperty( WS_MESSAGE *handle, WS_MESSAGE_PROPERTY_ID id, const void *value,
291 ULONG size, WS_ERROR *error )
293 struct msg *msg = (struct msg *)handle;
295 TRACE( "%p %u %p %u\n", handle, id, value, size );
296 if (error) FIXME( "ignoring error parameter\n" );
298 if (!handle) return E_INVALIDARG;
300 switch (id)
302 case WS_MESSAGE_PROPERTY_STATE:
303 case WS_MESSAGE_PROPERTY_ENVELOPE_VERSION:
304 case WS_MESSAGE_PROPERTY_ADDRESSING_VERSION:
305 case WS_MESSAGE_PROPERTY_IS_ADDRESSED:
306 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
307 return E_INVALIDARG;
309 default:
310 break;
312 return prop_set( msg->prop, msg->prop_count, id, value, size );
315 /**************************************************************************
316 * WsAddressMessage [webservices.@]
318 HRESULT WINAPI WsAddressMessage( WS_MESSAGE *handle, const WS_ENDPOINT_ADDRESS *addr, WS_ERROR *error )
320 struct msg *msg = (struct msg *)handle;
322 TRACE( "%p %p %p\n", handle, addr, error );
323 if (error) FIXME( "ignoring error parameter\n" );
324 if (addr && (addr->headers || addr->extensions || addr->identity))
326 FIXME( "headers, extensions or identity not supported\n" );
327 return E_NOTIMPL;
330 if (!handle) return E_INVALIDARG;
331 if (msg->state < WS_MESSAGE_STATE_INITIALIZED || msg->is_addressed) return WS_E_INVALID_OPERATION;
333 if (addr && addr->url.length)
335 if (!(msg->addr.chars = heap_alloc( addr->url.length * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
336 memcpy( msg->addr.chars, addr->url.chars, addr->url.length * sizeof(WCHAR) );
337 msg->addr.length = addr->url.length;
340 msg->is_addressed = TRUE;
341 return S_OK;
344 static HRESULT get_env_namespace( WS_ENVELOPE_VERSION ver, WS_XML_STRING *str )
346 switch (ver)
348 case WS_ENVELOPE_VERSION_SOAP_1_1:
349 str->bytes = (BYTE *)ns_env_1_1;
350 str->length = sizeof(ns_env_1_1)/sizeof(ns_env_1_1[0]) - 1;
351 return S_OK;
353 case WS_ENVELOPE_VERSION_SOAP_1_2:
354 str->bytes = (BYTE *)ns_env_1_2;
355 str->length = sizeof(ns_env_1_2)/sizeof(ns_env_1_2[0]) - 1;
356 return S_OK;
358 default:
359 ERR( "unhandled envelope version %u\n", ver );
360 return E_NOTIMPL;
364 static HRESULT get_addr_namespace( WS_ADDRESSING_VERSION ver, WS_XML_STRING *str )
366 switch (ver)
368 case WS_ADDRESSING_VERSION_0_9:
369 str->bytes = (BYTE *)ns_addr_0_9;
370 str->length = sizeof(ns_addr_0_9)/sizeof(ns_addr_0_9[0]) - 1;
371 return S_OK;
373 case WS_ADDRESSING_VERSION_1_0:
374 str->bytes = (BYTE *)ns_addr_1_0;
375 str->length = sizeof(ns_addr_1_0)/sizeof(ns_addr_1_0[0]) - 1;
376 return S_OK;
378 case WS_ADDRESSING_VERSION_TRANSPORT:
379 str->bytes = NULL;
380 str->length = 0;
381 return S_OK;
383 default:
384 ERR( "unhandled addressing version %u\n", ver );
385 return E_NOTIMPL;
389 static const WS_XML_STRING *get_header_name( WS_HEADER_TYPE type )
391 static const WS_XML_STRING action = {6, (BYTE *)"Action"}, to = {2, (BYTE *)"To"};
392 static const WS_XML_STRING msgid = {9, (BYTE *)"MessageID"}, relto = {9, (BYTE *)"RelatesTo"};
393 static const WS_XML_STRING from = {4, (BYTE *)"From"}, replyto = {7, (BYTE *)"ReplyTo"};
394 static const WS_XML_STRING faultto = {7, (BYTE *)"FaultTo"};
396 switch (type)
398 case WS_ACTION_HEADER: return &action;
399 case WS_TO_HEADER: return &to;
400 case WS_MESSAGE_ID_HEADER: return &msgid;
401 case WS_RELATES_TO_HEADER: return &relto;
402 case WS_FROM_HEADER: return &from;
403 case WS_REPLY_TO_HEADER: return &replyto;
404 case WS_FAULT_TO_HEADER: return &faultto;
405 default:
406 ERR( "unknown type %u\n", type );
407 return NULL;
411 static HRESULT write_headers( struct msg *msg, const WS_XML_STRING *ns_env, const WS_XML_STRING *ns_addr,
412 WS_XML_WRITER *writer )
414 static const char anonymous[] = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
415 static const WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"};
416 static const WS_XML_STRING msgid = {9, (BYTE *)"MessageID"}, replyto = {7, (BYTE *)"ReplyTo"};
417 static const WS_XML_STRING address = {7, (BYTE *)"Address"}, header = {6, (BYTE *)"Header"};
418 WS_XML_UTF8_TEXT urn, addr;
419 HRESULT hr;
420 ULONG i;
422 if ((hr = WsWriteXmlnsAttribute( writer, &prefix_a, ns_addr, FALSE, NULL )) != S_OK) return hr;
423 if ((hr = WsWriteStartElement( writer, &prefix_s, &header, ns_env, NULL )) != S_OK) return hr;
425 if ((hr = WsWriteStartElement( writer, &prefix_a, &msgid, ns_addr, NULL )) != S_OK) return hr;
426 urn.text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID;
427 memcpy( &urn.value, &msg->id, sizeof(msg->id) );
428 if ((hr = WsWriteText( writer, &urn.text, NULL )) != S_OK) return hr;
429 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:MessageID> */
431 if (msg->version_addr == WS_ADDRESSING_VERSION_0_9)
433 if ((hr = WsWriteStartElement( writer, &prefix_a, &replyto, ns_addr, NULL )) != S_OK) return hr;
434 if ((hr = WsWriteStartElement( writer, &prefix_a, &address, ns_addr, NULL )) != S_OK) return hr;
436 addr.text.textType = WS_XML_TEXT_TYPE_UTF8;
437 addr.value.bytes = (BYTE *)anonymous;
438 addr.value.length = sizeof(anonymous) - 1;
439 if ((hr = WsWriteText( writer, &addr.text, NULL )) != S_OK) return hr;
440 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:Address> */
441 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:ReplyTo> */
444 for (i = 0; i < msg->header_count; i++)
446 if (msg->header[i]->mapped) continue;
447 if ((hr = WsWriteXmlBuffer( writer, msg->header[i]->u.buf, NULL )) != S_OK) return hr;
450 return WsWriteEndElement( writer, NULL ); /* </s:Header> */
453 static HRESULT write_headers_transport( struct msg *msg, const WS_XML_STRING *ns_env, WS_XML_WRITER *writer )
455 static const WS_XML_STRING prefix = {1, (BYTE *)"s"}, header = {6, (BYTE *)"Header"};
456 HRESULT hr = S_OK;
457 ULONG i;
459 if ((msg->header_count || !msg->action.length) &&
460 (hr = WsWriteStartElement( writer, &prefix, &header, ns_env, NULL )) != S_OK) return hr;
462 for (i = 0; i < msg->header_count; i++)
464 if (msg->header[i]->mapped) continue;
465 if ((hr = WsWriteXmlBuffer( writer, msg->header[i]->u.buf, NULL )) != S_OK) return hr;
468 if (msg->header_count || !msg->action.length) hr = WsWriteEndElement( writer, NULL ); /* </s:Header> */
469 return hr;
472 static HRESULT write_envelope_start( struct msg *msg, WS_XML_WRITER *writer )
474 static const WS_XML_STRING envelope = {8, (BYTE *)"Envelope"}, body = {4, (BYTE *)"Body"};
475 static const WS_XML_STRING prefix = {1, (BYTE *)"s"};
476 WS_XML_STRING ns_env, ns_addr;
477 HRESULT hr;
479 if ((hr = get_env_namespace( msg->version_env, &ns_env )) != S_OK) return hr;
480 if ((hr = get_addr_namespace( msg->version_addr, &ns_addr )) != S_OK) return hr;
481 if ((hr = WsWriteStartElement( writer, &prefix, &envelope, &ns_env, NULL )) != S_OK) return hr;
483 if (msg->version_addr == WS_ADDRESSING_VERSION_TRANSPORT)
484 hr = write_headers_transport( msg, &ns_env, writer );
485 else
486 hr = write_headers( msg, &ns_env, &ns_addr, writer );
487 if (hr != S_OK) return hr;
489 return WsWriteStartElement( writer, &prefix, &body, &ns_env, NULL ); /* <s:Body> */
492 static HRESULT write_envelope_end( WS_XML_WRITER *writer )
494 HRESULT hr;
495 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </s:Body> */
496 return WsWriteEndElement( writer, NULL ); /* </s:Envelope> */
499 static HRESULT write_envelope( struct msg *msg )
501 HRESULT hr;
502 if (!msg->writer && (hr = WsCreateWriter( NULL, 0, &msg->writer, NULL )) != S_OK) return hr;
503 if (!msg->buf && (hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &msg->buf, NULL )) != S_OK) return hr;
504 if ((hr = WsSetOutputToBuffer( msg->writer, msg->buf, NULL, 0, NULL )) != S_OK) return hr;
505 if ((hr = write_envelope_start( msg, msg->writer )) != S_OK) return hr;
506 return write_envelope_end( msg->writer );
509 /**************************************************************************
510 * WsWriteEnvelopeStart [webservices.@]
512 HRESULT WINAPI WsWriteEnvelopeStart( WS_MESSAGE *handle, WS_XML_WRITER *writer,
513 WS_MESSAGE_DONE_CALLBACK cb, void *state, WS_ERROR *error )
515 struct msg *msg = (struct msg *)handle;
516 HRESULT hr;
518 TRACE( "%p %p %p %p %p\n", handle, writer, cb, state, error );
519 if (error) FIXME( "ignoring error parameter\n" );
520 if (cb)
522 FIXME( "callback not supported\n" );
523 return E_NOTIMPL;
526 if (!handle || !writer) return E_INVALIDARG;
527 if (msg->state != WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
529 if ((hr = write_envelope( msg )) != S_OK) return hr;
530 if ((hr = write_envelope_start( msg, writer )) != S_OK) return hr;
532 msg->writer_body = writer;
533 msg->state = WS_MESSAGE_STATE_WRITING;
534 return S_OK;
537 /**************************************************************************
538 * WsWriteEnvelopeEnd [webservices.@]
540 HRESULT WINAPI WsWriteEnvelopeEnd( WS_MESSAGE *handle, WS_ERROR *error )
542 struct msg *msg = (struct msg *)handle;
543 HRESULT hr;
545 TRACE( "%p %p\n", handle, error );
546 if (error) FIXME( "ignoring error parameter\n" );
548 if (!handle) return E_INVALIDARG;
549 if (msg->state != WS_MESSAGE_STATE_WRITING) return WS_E_INVALID_OPERATION;
551 if ((hr = write_envelope_end( msg->writer_body )) != S_OK) return hr;
553 msg->state = WS_MESSAGE_STATE_DONE;
554 return S_OK;
557 /**************************************************************************
558 * WsWriteBody [webservices.@]
560 HRESULT WINAPI WsWriteBody( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *desc, WS_WRITE_OPTION option,
561 const void *value, ULONG size, WS_ERROR *error )
563 struct msg *msg = (struct msg *)handle;
564 HRESULT hr;
566 TRACE( "%p %p %08x %p %u %p\n", handle, desc, option, value, size, error );
567 if (error) FIXME( "ignoring error parameter\n" );
569 if (!handle || !desc) return E_INVALIDARG;
570 if (msg->state != WS_MESSAGE_STATE_WRITING) return WS_E_INVALID_OPERATION;
572 if (desc->elementLocalName &&
573 (hr = WsWriteStartElement( msg->writer_body, NULL, desc->elementLocalName, desc->elementNs,
574 NULL )) != S_OK) return hr;
576 if ((hr = WsWriteType( msg->writer_body, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription,
577 option, value, size, NULL )) != S_OK) return hr;
579 if (desc->elementLocalName) hr = WsWriteEndElement( msg->writer_body, NULL );
580 return hr;
583 static BOOL match_current_element( WS_XML_READER *reader, const WS_XML_STRING *localname )
585 const WS_XML_NODE *node;
586 const WS_XML_ELEMENT_NODE *elem;
588 if (WsGetReaderNode( reader, &node, NULL ) != S_OK) return FALSE;
589 if (node->nodeType != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
590 elem = (const WS_XML_ELEMENT_NODE *)node;
591 return WsXmlStringEquals( elem->localName, localname, NULL ) == S_OK;
594 static HRESULT read_envelope_start( WS_XML_READER *reader )
596 static const WS_XML_STRING envelope = {8, (BYTE *)"Envelope"}, body = {4, (BYTE *)"Body"};
597 HRESULT hr;
599 if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr;
600 if (!match_current_element( reader, &envelope )) return WS_E_INVALID_FORMAT;
601 /* FIXME: read headers */
602 if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr;
603 if (!match_current_element( reader, &body )) return WS_E_INVALID_FORMAT;
604 return WsReadNode( reader, NULL );
607 /**************************************************************************
608 * WsReadEnvelopeStart [webservices.@]
610 HRESULT WINAPI WsReadEnvelopeStart( WS_MESSAGE *handle, WS_XML_READER *reader, WS_MESSAGE_DONE_CALLBACK cb,
611 void *state, WS_ERROR *error )
613 struct msg *msg = (struct msg *)handle;
614 HRESULT hr;
616 TRACE( "%p %p %p %p %p\n", handle, reader, cb, state, error );
617 if (error) FIXME( "ignoring error parameter\n" );
618 if (cb)
620 FIXME( "callback not supported\n" );
621 return E_NOTIMPL;
624 if (!handle || !reader) return E_INVALIDARG;
625 if (msg->state != WS_MESSAGE_STATE_EMPTY) return WS_E_INVALID_OPERATION;
627 if ((hr = read_envelope_start( reader )) != S_OK) return hr;
629 msg->reader_body = reader;
630 msg->state = WS_MESSAGE_STATE_READING;
631 return S_OK;
634 static HRESULT read_envelope_end( WS_XML_READER *reader )
636 HRESULT hr;
637 if ((hr = WsReadEndElement( reader, NULL )) != S_OK) return hr; /* </s:Body> */
638 return WsReadEndElement( reader, NULL ); /* </s:Envelope> */
641 /**************************************************************************
642 * WsReadEnvelopeEnd [webservices.@]
644 HRESULT WINAPI WsReadEnvelopeEnd( WS_MESSAGE *handle, WS_ERROR *error )
646 struct msg *msg = (struct msg *)handle;
647 HRESULT hr;
649 TRACE( "%p %p\n", handle, error );
650 if (error) FIXME( "ignoring error parameter\n" );
652 if (!handle) return E_INVALIDARG;
653 if (msg->state != WS_MESSAGE_STATE_READING) return WS_E_INVALID_OPERATION;
655 if ((hr = read_envelope_end( msg->reader_body )) != S_OK) return hr;
657 msg->state = WS_MESSAGE_STATE_DONE;
658 return S_OK;
661 /**************************************************************************
662 * WsReadBody [webservices.@]
664 HRESULT WINAPI WsReadBody( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *desc, WS_READ_OPTION option,
665 WS_HEAP *heap, void *value, ULONG size, WS_ERROR *error )
667 struct msg *msg = (struct msg *)handle;
669 TRACE( "%p %p %08x %p %p %u %p\n", handle, desc, option, heap, value, size, error );
670 if (error) FIXME( "ignoring error parameter\n" );
672 if (!handle || !desc) return E_INVALIDARG;
673 if (msg->state != WS_MESSAGE_STATE_READING) return WS_E_INVALID_OPERATION;
675 return WsReadElement( msg->reader_body, desc, option, heap, value, size, NULL );
678 /**************************************************************************
679 * WsInitializeMessage [webservices.@]
681 HRESULT WINAPI WsInitializeMessage( WS_MESSAGE *handle, WS_MESSAGE_INITIALIZATION init,
682 WS_MESSAGE *src_handle, WS_ERROR *error )
684 struct msg *msg = (struct msg *)handle;
686 TRACE( "%p %u %p %p\n", handle, init, src_handle, error );
687 if (error) FIXME( "ignoring error parameter\n" );
688 if (src_handle)
690 FIXME( "src message not supported\n" );
691 return E_NOTIMPL;
694 if (!handle || init > WS_FAULT_MESSAGE) return E_INVALIDARG;
695 if (msg->state >= WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
697 msg->init = init;
698 msg->state = WS_MESSAGE_STATE_INITIALIZED;
699 return write_envelope( msg );
702 static HRESULT grow_header_array( struct msg *msg, ULONG size )
704 struct header **tmp;
705 if (size <= msg->header_size) return S_OK;
706 if (!(tmp = heap_realloc( msg->header, 2 * msg->header_size * sizeof(struct header *) )))
707 return E_OUTOFMEMORY;
708 msg->header = tmp;
709 msg->header_size *= 2;
710 return S_OK;
713 static struct header *alloc_header( WS_HEADER_TYPE type, BOOL mapped, const WS_XML_STRING *name,
714 const WS_XML_STRING *ns )
716 struct header *ret;
717 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
718 if (name && name->length)
720 if (!(ret->name.bytes = heap_alloc( name->length )))
722 free_header( ret );
723 return NULL;
725 memcpy( ret->name.bytes, name->bytes, name->length );
726 ret->name.length = name->length;
728 if (ns && ns->length)
730 if (!(ret->ns.bytes = heap_alloc( ns->length )))
732 free_header( ret );
733 return NULL;
735 memcpy( ret->ns.bytes, ns->bytes, ns->length );
736 ret->ns.length = ns->length;
738 ret->type = type;
739 ret->mapped = mapped;
740 return ret;
743 static HRESULT write_standard_header( WS_XML_WRITER *writer, const WS_XML_STRING *name, WS_TYPE value_type,
744 WS_WRITE_OPTION option, const void *value, ULONG size )
746 static const WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"};
747 static const WS_XML_STRING understand = {14, (BYTE *)"mustUnderstand"}, ns = {0, NULL};
748 WS_XML_INT32_TEXT one = {{WS_XML_TEXT_TYPE_INT32}, 1};
749 HRESULT hr;
751 if ((hr = WsWriteStartElement( writer, &prefix_a, name, &ns, NULL )) != S_OK) return hr;
752 if ((hr = WsWriteStartAttribute( writer, &prefix_s, &understand, &ns, FALSE, NULL )) != S_OK) return hr;
753 if ((hr = WsWriteText( writer, &one.text, NULL )) != S_OK) return hr;
754 if ((hr = WsWriteEndAttribute( writer, NULL )) != S_OK) return hr;
755 if ((hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, value_type, NULL, option, value, size,
756 NULL )) != S_OK) return hr;
757 return WsWriteEndElement( writer, NULL );
760 static HRESULT build_standard_header( WS_HEAP *heap, WS_HEADER_TYPE type, WS_TYPE value_type,
761 WS_WRITE_OPTION option, const void *value, ULONG size,
762 struct header **ret )
764 const WS_XML_STRING *name = get_header_name( type );
765 struct header *header;
766 WS_XML_WRITER *writer;
767 WS_XML_BUFFER *buf;
768 HRESULT hr;
770 if (!(header = alloc_header( type, FALSE, name, NULL ))) return E_OUTOFMEMORY;
772 if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
773 if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buf, NULL )) != S_OK) goto done;
774 if ((hr = WsSetOutputToBuffer( writer, buf, NULL, 0, NULL )) != S_OK) goto done;
775 if ((hr = write_standard_header( writer, name, value_type, option, value, size )) != S_OK)
776 goto done;
778 header->u.buf = buf;
780 done:
781 if (hr != S_OK) free_header( header );
782 else *ret = header;
783 WsFreeWriter( writer );
784 return hr;
787 /**************************************************************************
788 * WsSetHeader [webservices.@]
790 HRESULT WINAPI WsSetHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_TYPE value_type,
791 WS_WRITE_OPTION option, const void *value, ULONG size, WS_ERROR *error )
793 struct msg *msg = (struct msg *)handle;
794 struct header *header;
795 BOOL found = FALSE;
796 HRESULT hr;
797 ULONG i;
799 TRACE( "%p %u %u %08x %p %u %p\n", handle, type, value_type, option, value, size, error );
800 if (error) FIXME( "ignoring error parameter\n" );
802 if (!handle || type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) return E_INVALIDARG;
803 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
805 for (i = 0; i < msg->header_count; i++)
807 if (msg->header[i]->type == type)
809 found = TRUE;
810 break;
814 if (!found)
816 if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) return hr;
817 i = msg->header_count;
820 if ((hr = build_standard_header( msg->heap, type, value_type, option, value, size, &header )) != S_OK)
821 return hr;
823 if (!found) msg->header_count++;
824 else free_header( msg->header[i] );
826 msg->header[i] = header;
827 return write_envelope( msg );
830 static void remove_header( struct msg *msg, ULONG i )
832 free_header( msg->header[i] );
833 memmove( &msg->header[i], &msg->header[i + 1], (msg->header_count - i - 1) * sizeof(struct header *) );
834 msg->header_count--;
837 /**************************************************************************
838 * WsRemoveHeader [webservices.@]
840 HRESULT WINAPI WsRemoveHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_ERROR *error )
842 struct msg *msg = (struct msg *)handle;
843 BOOL removed = FALSE;
844 ULONG i;
846 TRACE( "%p %u %p\n", handle, type, error );
847 if (error) FIXME( "ignoring error parameter\n" );
849 if (!handle) return E_INVALIDARG;
850 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
851 if (type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) return E_INVALIDARG;
853 for (i = 0; i < msg->header_count; i++)
855 if (msg->header[i]->type == type)
857 remove_header( msg, i );
858 removed = TRUE;
859 break;
863 if (removed) return write_envelope( msg );
864 return S_OK;
867 static HRESULT build_mapped_header( const WS_XML_STRING *name, WS_TYPE type, WS_WRITE_OPTION option,
868 const void *value, ULONG size, struct header **ret )
870 struct header *header;
872 if (!(header = alloc_header( 0, TRUE, name, NULL ))) return E_OUTOFMEMORY;
873 switch (type)
875 case WS_WSZ_TYPE:
877 int len;
878 const WCHAR *src;
880 if (option != WS_WRITE_REQUIRED_POINTER || size != sizeof(WCHAR *))
882 free_header( header );
883 return E_INVALIDARG;
885 src = *(const WCHAR **)value;
886 len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL ) - 1;
887 if (!(header->u.text = alloc_xml_string( NULL, len )))
889 free_header( header );
890 return E_OUTOFMEMORY;
892 WideCharToMultiByte( CP_UTF8, 0, src, -1, (char *)header->u.text->bytes, len, NULL, NULL );
893 break;
895 case WS_XML_STRING_TYPE:
897 const WS_XML_STRING *str = value;
899 if (option != WS_WRITE_REQUIRED_VALUE)
901 FIXME( "unhandled write option %u\n", option );
902 free_header( header );
903 return E_NOTIMPL;
905 if (size != sizeof(*str))
907 free_header( header );
908 return E_INVALIDARG;
910 if (!(header->u.text = alloc_xml_string( NULL, str->length )))
912 free_header( header );
913 return E_OUTOFMEMORY;
915 memcpy( header->u.text->bytes, str->bytes, str->length );
916 break;
918 case WS_STRING_TYPE:
920 int len;
921 const WS_STRING *str = value;
923 if (option != WS_WRITE_REQUIRED_VALUE)
925 FIXME( "unhandled write option %u\n", option );
926 free_header( header );
927 return E_NOTIMPL;
929 if (size != sizeof(*str))
931 free_header( header );
932 return E_INVALIDARG;
934 len = WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, NULL, 0, NULL, NULL );
935 if (!(header->u.text = alloc_xml_string( NULL, len )))
937 free_header( header );
938 return E_OUTOFMEMORY;
940 WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, (char *)header->u.text->bytes,
941 len, NULL, NULL );
942 break;
944 default:
945 FIXME( "unhandled type %u\n", type );
946 free_header( header );
947 return E_NOTIMPL;
950 *ret = header;
951 return S_OK;
954 /**************************************************************************
955 * WsAddMappedHeader [webservices.@]
957 HRESULT WINAPI WsAddMappedHeader( WS_MESSAGE *handle, const WS_XML_STRING *name, WS_TYPE type,
958 WS_WRITE_OPTION option, const void *value, ULONG size, WS_ERROR *error )
960 struct msg *msg = (struct msg *)handle;
961 struct header *header;
962 BOOL found = FALSE;
963 HRESULT hr;
964 ULONG i;
966 TRACE( "%p %s %u %08x %p %u %p\n", handle, debugstr_xmlstr(name), type, option, value, size, error );
967 if (error) FIXME( "ignoring error parameter\n" );
969 if (!handle || !name) return E_INVALIDARG;
970 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
972 for (i = 0; i < msg->header_count; i++)
974 if (msg->header[i]->type || !msg->header[i]->mapped) continue;
975 if (WsXmlStringEquals( name, &msg->header[i]->name, NULL ) == S_OK)
977 found = TRUE;
978 break;
982 if (!found)
984 if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) return hr;
985 i = msg->header_count;
988 if ((hr = build_mapped_header( name, type, option, value, size, &header )) != S_OK) return hr;
990 if (!found) msg->header_count++;
991 else free_header( msg->header[i] );
993 msg->header[i] = header;
994 return S_OK;
997 /**************************************************************************
998 * WsRemoveMappedHeader [webservices.@]
1000 HRESULT WINAPI WsRemoveMappedHeader( WS_MESSAGE *handle, const WS_XML_STRING *name, WS_ERROR *error )
1002 struct msg *msg = (struct msg *)handle;
1003 ULONG i;
1005 TRACE( "%p %s %p\n", handle, debugstr_xmlstr(name), error );
1006 if (error) FIXME( "ignoring error parameter\n" );
1008 if (!handle || !name) return E_INVALIDARG;
1009 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
1011 for (i = 0; i < msg->header_count; i++)
1013 if (msg->header[i]->type || !msg->header[i]->mapped) continue;
1014 if (WsXmlStringEquals( name, &msg->header[i]->name, NULL ) == S_OK)
1016 remove_header( msg, i );
1017 break;
1021 return S_OK;
1024 static HRESULT write_custom_header( WS_XML_WRITER *writer, const WS_XML_STRING *name, const WS_XML_STRING *ns,
1025 WS_TYPE type, const void *desc, WS_WRITE_OPTION option, const void *value,
1026 ULONG size )
1028 HRESULT hr;
1029 if ((hr = WsWriteStartElement( writer, NULL, name, ns, NULL )) != S_OK) return hr;
1030 if ((hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, desc, option, value, size,
1031 NULL )) != S_OK) return hr;
1032 return WsWriteEndElement( writer, NULL );
1035 static HRESULT build_custom_header( WS_HEAP *heap, const WS_XML_STRING *name, const WS_XML_STRING *ns,
1036 WS_TYPE type, const void *desc, WS_WRITE_OPTION option, const void *value,
1037 ULONG size, struct header **ret )
1039 struct header *header;
1040 WS_XML_WRITER *writer;
1041 WS_XML_BUFFER *buf;
1042 HRESULT hr;
1044 if (!(header = alloc_header( 0, FALSE, name, ns ))) return E_OUTOFMEMORY;
1046 if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
1047 if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buf, NULL )) != S_OK) goto done;
1048 if ((hr = WsSetOutputToBuffer( writer, buf, NULL, 0, NULL )) != S_OK) goto done;
1049 if ((hr = write_custom_header( writer, name, ns, type, desc, option, value, size )) != S_OK) goto done;
1051 header->u.buf = buf;
1053 done:
1054 if (hr != S_OK) free_header( header );
1055 else *ret = header;
1056 WsFreeWriter( writer );
1057 return hr;
1060 /**************************************************************************
1061 * WsAddCustomHeader [webservices.@]
1063 HRESULT WINAPI WsAddCustomHeader( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *desc, WS_WRITE_OPTION option,
1064 const void *value, ULONG size, ULONG attrs, WS_ERROR *error )
1066 struct msg *msg = (struct msg *)handle;
1067 struct header *header;
1068 HRESULT hr;
1070 TRACE( "%p %p %08x %p %u %08x %p\n", handle, desc, option, value, size, attrs, error );
1071 if (error) FIXME( "ignoring error parameter\n" );
1073 if (!handle || !desc) return E_INVALIDARG;
1074 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
1076 if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) return hr;
1077 if ((hr = build_custom_header( msg->heap, desc->elementLocalName, desc->elementNs, desc->type,
1078 desc->typeDescription, option, value, size, &header )) != S_OK) return hr;
1080 msg->header[msg->header_count++] = header;
1081 return write_envelope( msg );
1084 /**************************************************************************
1085 * WsRemoveCustomHeader [webservices.@]
1087 HRESULT WINAPI WsRemoveCustomHeader( WS_MESSAGE *handle, const WS_XML_STRING *name, const WS_XML_STRING *ns,
1088 WS_ERROR *error )
1090 struct msg *msg = (struct msg *)handle;
1091 BOOL removed = FALSE;
1092 ULONG i;
1094 TRACE( "%p %s %s %p\n", handle, debugstr_xmlstr(name), debugstr_xmlstr(ns), error );
1095 if (error) FIXME( "ignoring error parameter\n" );
1097 if (!handle || !name || !ns) return E_INVALIDARG;
1098 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
1100 for (i = 0; i < msg->header_count; i++)
1102 if (msg->header[i]->type || msg->header[i]->mapped) continue;
1103 if (WsXmlStringEquals( name, &msg->header[i]->name, NULL ) == S_OK &&
1104 WsXmlStringEquals( ns, &msg->header[i]->ns, NULL ) == S_OK)
1106 remove_header( msg, i );
1107 removed = TRUE;
1108 i--;
1112 if (removed) return write_envelope( msg );
1113 return S_OK;
1116 static WCHAR *build_http_header( const WCHAR *name, const WCHAR *value, ULONG *ret_len )
1118 static const WCHAR fmtW[] = {'%','s',':',' ','%','s',0};
1119 WCHAR *ret = heap_alloc( (strlenW(name) + strlenW(value) + 3) * sizeof(WCHAR) );
1120 if (ret) *ret_len = sprintfW( ret, fmtW, name, value );
1121 return ret;
1124 HRESULT message_insert_http_headers( WS_MESSAGE *handle, HINTERNET req )
1126 static const WCHAR contenttypeW[] =
1127 {'C','o','n','t','e','n','t','-','T','y','p','e',0};
1128 static const WCHAR soapxmlW[] =
1129 {'a','p','p','l','i','c','a','t','i','o','n','/','s','o','a','p','+','x','m','l',0};
1130 static const WCHAR textxmlW[] =
1131 {'t','e','x','t','/','x','m','l',0};
1132 static const WCHAR charsetW[] =
1133 {'c','h','a','r','s','e','t','=','u','t','f','-','8',0};
1134 struct msg *msg = (struct msg *)handle;
1135 WCHAR *header, *buf;
1136 ULONG len;
1137 BOOL ret;
1139 switch (msg->version_env)
1141 case WS_ENVELOPE_VERSION_SOAP_1_1:
1142 header = build_http_header( contenttypeW, textxmlW, &len );
1143 break;
1145 case WS_ENVELOPE_VERSION_SOAP_1_2:
1146 header = build_http_header( contenttypeW, soapxmlW, &len );
1147 break;
1149 default:
1150 FIXME( "unhandled envelope version %u\n", msg->version_env );
1151 return E_NOTIMPL;
1153 if (!header) return E_OUTOFMEMORY;
1155 ret = WinHttpAddRequestHeaders( req, header, len, WINHTTP_ADDREQ_FLAG_ADD );
1156 heap_free( header );
1157 if (!ret) return HRESULT_FROM_WIN32( GetLastError() );
1159 if (!(header = build_http_header( contenttypeW, charsetW, &len ))) return E_OUTOFMEMORY;
1160 ret = WinHttpAddRequestHeaders( req, header, len, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON );
1161 heap_free( header );
1162 if (!ret) return HRESULT_FROM_WIN32( GetLastError() );
1164 switch (msg->version_env)
1166 case WS_ENVELOPE_VERSION_SOAP_1_1:
1168 static const WCHAR soapactionW[] = {'S','O','A','P','A','c','t','i','o','n',0};
1170 if (!(len = msg->action.length)) break;
1171 if (!(buf = heap_alloc( (len + 3) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
1172 buf[0] = '"';
1173 memcpy( buf + 1, msg->action.chars, len * sizeof(WCHAR) );
1174 buf[len + 1] = '"';
1175 buf[len + 2] = 0;
1176 header = build_http_header( soapactionW, buf, &len );
1177 heap_free( buf );
1178 if (!header) return E_OUTOFMEMORY;
1180 ret = WinHttpAddRequestHeaders( req, header, len, WINHTTP_ADDREQ_FLAG_ADD );
1181 heap_free( header );
1182 if (!ret) return HRESULT_FROM_WIN32( GetLastError() );
1183 break;
1185 case WS_ENVELOPE_VERSION_SOAP_1_2:
1187 static const WCHAR actionW[] = {'a','c','t','i','o','n','=','"'};
1188 ULONG len_action = sizeof(actionW)/sizeof(actionW[0]);
1190 if (!(len = msg->action.length)) break;
1191 if (!(buf = heap_alloc( (len + len_action + 2) * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
1192 memcpy( buf, actionW, len_action * sizeof(WCHAR) );
1193 memcpy( buf + len_action, msg->action.chars, len * sizeof(WCHAR) );
1194 len += len_action;
1195 buf[len++] = '"';
1196 buf[len] = 0;
1197 header = build_http_header( contenttypeW, buf, &len );
1198 heap_free( buf );
1199 if (!header) return E_OUTOFMEMORY;
1201 ret = WinHttpAddRequestHeaders( req, header, len, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON );
1202 heap_free( header );
1203 if (!ret) return HRESULT_FROM_WIN32( GetLastError() );
1204 break;
1206 default:
1207 FIXME( "unhandled envelope version %u\n", msg->version_env );
1208 return E_NOTIMPL;
1211 return S_OK;
1214 void message_set_send_context( WS_MESSAGE *handle, const WS_PROXY_MESSAGE_CALLBACK_CONTEXT *ctx )
1216 struct msg *msg = (struct msg *)handle;
1217 msg->ctx_send.callback = ctx->callback;
1218 msg->ctx_send.state = ctx->state;
1221 void message_set_receive_context( WS_MESSAGE *handle, const WS_PROXY_MESSAGE_CALLBACK_CONTEXT *ctx )
1223 struct msg *msg = (struct msg *)handle;
1224 msg->ctx_receive.callback = ctx->callback;
1225 msg->ctx_receive.state = ctx->state;
1228 void message_do_send_callback( WS_MESSAGE *handle )
1230 struct msg *msg = (struct msg *)handle;
1231 if (msg->ctx_send.callback)
1233 HRESULT hr;
1234 TRACE( "executing callback %p\n", msg->ctx_send.callback );
1235 hr = msg->ctx_send.callback( handle, msg->heap, msg->ctx_send.state, NULL );
1236 TRACE( "callback %p returned %08x\n", msg->ctx_send.callback, hr );
1240 void message_do_receive_callback( WS_MESSAGE *handle )
1242 struct msg *msg = (struct msg *)handle;
1243 if (msg->ctx_receive.callback)
1245 HRESULT hr;
1246 TRACE( "executing callback %p\n", msg->ctx_receive.callback );
1247 hr = msg->ctx_receive.callback( handle, msg->heap, msg->ctx_receive.state, NULL );
1248 TRACE( "callback %p returned %08x\n", msg->ctx_receive.callback, hr );
1252 HRESULT message_set_action( WS_MESSAGE *handle, const WS_XML_STRING *action )
1254 struct msg *msg = (struct msg *)handle;
1255 WCHAR *chars;
1256 int len;
1258 if (!action || !action->length)
1260 heap_free( msg->action.chars );
1261 msg->action.chars = NULL;
1262 msg->action.length = 0;
1263 return S_OK;
1265 len = MultiByteToWideChar( CP_UTF8, 0, (char *)action->bytes, action->length, NULL, 0 );
1266 if (!(chars = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
1267 MultiByteToWideChar( CP_UTF8, 0, (char *)action->bytes, action->length, chars, len );
1269 heap_free( msg->action.chars );
1270 msg->action.chars = chars;
1271 msg->action.length = len;
1273 return S_OK;