dxgi: Add stub implementation for DXGI_PRESENT_TEST.
[wine.git] / dlls / webservices / msg.c
blobf4d167f64ed95f0f3ca52d737c579ff723ab78fb
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 struct prop_desc msg_props[] =
36 { sizeof(WS_MESSAGE_STATE), TRUE }, /* WS_MESSAGE_PROPERTY_STATE */
37 { sizeof(WS_HEAP *), TRUE }, /* WS_MESSAGE_PROPERTY_HEAP */
38 { sizeof(WS_ENVELOPE_VERSION), TRUE }, /* WS_MESSAGE_PROPERTY_ENVELOPE_VERSION */
39 { sizeof(WS_ADDRESSING_VERSION), TRUE }, /* WS_MESSAGE_PROPERTY_ADDRESSING_VERSION */
40 { sizeof(WS_XML_BUFFER *), TRUE }, /* WS_MESSAGE_PROPERTY_HEADER_BUFFER */
41 { sizeof(WS_XML_NODE_POSITION *), TRUE }, /* WS_MESSAGE_PROPERTY_HEADER_POSITION */
42 { sizeof(WS_XML_READER *), TRUE }, /* WS_MESSAGE_PROPERTY_BODY_READER */
43 { sizeof(WS_XML_WRITER *), TRUE }, /* WS_MESSAGE_PROPERTY_BODY_WRITER */
44 { sizeof(BOOL), TRUE }, /* WS_MESSAGE_PROPERTY_IS_ADDRESSED */
47 struct header
49 WS_HEADER_TYPE type;
50 BOOL mapped;
51 WS_XML_STRING name;
52 WS_XML_STRING ns;
53 union
55 WS_XML_BUFFER *buf;
56 WS_XML_STRING *text;
57 } u;
60 struct msg
62 ULONG magic;
63 CRITICAL_SECTION cs;
64 WS_MESSAGE_INITIALIZATION init;
65 WS_MESSAGE_STATE state;
66 GUID id;
67 GUID id_req;
68 WS_ENVELOPE_VERSION version_env;
69 WS_ADDRESSING_VERSION version_addr;
70 BOOL is_addressed;
71 WS_STRING addr;
72 WS_XML_STRING *action;
73 WS_HEAP *heap;
74 WS_XML_BUFFER *buf;
75 WS_XML_WRITER *writer;
76 WS_XML_WRITER *writer_body;
77 WS_XML_READER *reader;
78 WS_XML_READER *reader_body;
79 ULONG header_count;
80 ULONG header_size;
81 struct header **header;
82 WS_PROXY_MESSAGE_CALLBACK_CONTEXT ctx_send;
83 WS_PROXY_MESSAGE_CALLBACK_CONTEXT ctx_receive;
84 ULONG prop_count;
85 struct prop prop[sizeof(msg_props)/sizeof(msg_props[0])];
88 #define MSG_MAGIC (('M' << 24) | ('E' << 16) | ('S' << 8) | 'S')
89 #define HEADER_ARRAY_SIZE 2
91 static struct msg *alloc_msg(void)
93 static const ULONG count = sizeof(msg_props)/sizeof(msg_props[0]);
94 struct msg *ret;
95 ULONG size = sizeof(*ret) + prop_size( msg_props, count );
97 if (!(ret = heap_alloc_zero( size ))) return NULL;
98 if (!(ret->header = heap_alloc( HEADER_ARRAY_SIZE * sizeof(struct header *) )))
100 heap_free( ret );
101 return NULL;
103 ret->magic = MSG_MAGIC;
104 ret->state = WS_MESSAGE_STATE_EMPTY;
105 ret->header_size = HEADER_ARRAY_SIZE;
107 InitializeCriticalSection( &ret->cs );
108 ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": msg.cs");
110 prop_init( msg_props, count, ret->prop, &ret[1] );
111 ret->prop_count = count;
112 return ret;
115 static void free_header( struct header *header )
117 heap_free( header->name.bytes );
118 heap_free( header->ns.bytes );
119 if (header->mapped) free_xml_string( header->u.text );
120 heap_free( header );
123 static void reset_msg( struct msg *msg )
125 ULONG i;
127 msg->state = WS_MESSAGE_STATE_EMPTY;
128 msg->init = 0;
129 UuidCreate( &msg->id );
130 memset( &msg->id_req, 0, sizeof(msg->id_req) );
131 msg->is_addressed = FALSE;
132 heap_free( msg->addr.chars );
133 msg->addr.chars = NULL;
134 msg->addr.length = 0;
136 free_xml_string( msg->action );
137 msg->action = NULL;
139 WsResetHeap( msg->heap, NULL );
140 msg->buf = NULL; /* allocated on msg->heap */
141 msg->writer_body = NULL; /* owned by caller */
142 msg->reader_body = NULL; /* owned by caller */
144 for (i = 0; i < msg->header_count; i++)
146 free_header( msg->header[i] );
147 msg->header[i] = NULL;
149 msg->header_count = 0;
151 memset( &msg->ctx_send, 0, sizeof(msg->ctx_send) );
152 memset( &msg->ctx_receive, 0, sizeof(msg->ctx_receive) );
155 static void free_msg( struct msg *msg )
157 reset_msg( msg );
159 WsFreeWriter( msg->writer );
160 WsFreeReader( msg->reader );
161 WsFreeHeap( msg->heap );
162 heap_free( msg->header );
164 msg->cs.DebugInfo->Spare[0] = 0;
165 DeleteCriticalSection( &msg->cs );
166 heap_free( msg );
169 #define HEAP_MAX_SIZE (1 << 16)
170 static HRESULT create_msg( WS_ENVELOPE_VERSION env_version, WS_ADDRESSING_VERSION addr_version,
171 const WS_MESSAGE_PROPERTY *properties, ULONG count, WS_MESSAGE **handle )
173 struct msg *msg;
174 HRESULT hr;
175 ULONG i;
177 if (!(msg = alloc_msg())) return E_OUTOFMEMORY;
179 for (i = 0; i < count; i++)
181 if (properties[i].id == WS_MESSAGE_PROPERTY_ENVELOPE_VERSION ||
182 properties[i].id == WS_MESSAGE_PROPERTY_ADDRESSING_VERSION)
184 free_msg( msg );
185 return E_INVALIDARG;
187 hr = prop_set( msg->prop, msg->prop_count, properties[i].id, properties[i].value,
188 properties[i].valueSize );
189 if (hr != S_OK)
191 free_msg( msg );
192 return hr;
196 if ((hr = WsCreateHeap( HEAP_MAX_SIZE, 0, NULL, 0, &msg->heap, NULL )) != S_OK)
198 free_msg( msg );
199 return hr;
202 UuidCreate( &msg->id );
203 msg->version_env = env_version;
204 msg->version_addr = addr_version;
206 *handle = (WS_MESSAGE *)msg;
207 return S_OK;
210 /**************************************************************************
211 * WsCreateMessage [webservices.@]
213 HRESULT WINAPI WsCreateMessage( WS_ENVELOPE_VERSION env_version, WS_ADDRESSING_VERSION addr_version,
214 const WS_MESSAGE_PROPERTY *properties, ULONG count, WS_MESSAGE **handle,
215 WS_ERROR *error )
217 HRESULT hr;
219 TRACE( "%u %u %p %u %p %p\n", env_version, addr_version, properties, count, handle, error );
220 if (error) FIXME( "ignoring error parameter\n" );
222 if (!handle || !env_version || !addr_version ||
223 (env_version == WS_ENVELOPE_VERSION_NONE && addr_version != WS_ADDRESSING_VERSION_TRANSPORT))
225 return E_INVALIDARG;
228 if ((hr = create_msg( env_version, addr_version, properties, count, handle )) != S_OK) return hr;
229 TRACE( "created %p\n", *handle );
230 return S_OK;
233 /**************************************************************************
234 * WsCreateMessageForChannel [webservices.@]
236 HRESULT WINAPI WsCreateMessageForChannel( WS_CHANNEL *channel_handle, const WS_MESSAGE_PROPERTY *properties,
237 ULONG count, WS_MESSAGE **handle, WS_ERROR *error )
239 WS_ENVELOPE_VERSION version_env;
240 WS_ADDRESSING_VERSION version_addr;
241 HRESULT hr;
243 TRACE( "%p %p %u %p %p\n", channel_handle, properties, count, handle, error );
244 if (error) FIXME( "ignoring error parameter\n" );
246 if (!channel_handle || !handle) return E_INVALIDARG;
248 if ((hr = WsGetChannelProperty( channel_handle, WS_CHANNEL_PROPERTY_ENVELOPE_VERSION, &version_env,
249 sizeof(version_env), NULL )) != S_OK || !version_env)
250 version_env = WS_ENVELOPE_VERSION_SOAP_1_2;
252 if ((hr = WsGetChannelProperty( channel_handle, WS_CHANNEL_PROPERTY_ADDRESSING_VERSION, &version_addr,
253 sizeof(version_addr), NULL )) != S_OK || !version_addr)
254 version_addr = WS_ADDRESSING_VERSION_1_0;
256 if ((hr = create_msg( version_env, version_addr, properties, count, handle )) != S_OK) return hr;
257 TRACE( "created %p\n", *handle );
258 return S_OK;
261 /**************************************************************************
262 * WsFreeMessage [webservices.@]
264 void WINAPI WsFreeMessage( WS_MESSAGE *handle )
266 struct msg *msg = (struct msg *)handle;
268 TRACE( "%p\n", handle );
270 if (!msg) return;
272 EnterCriticalSection( &msg->cs );
274 if (msg->magic != MSG_MAGIC)
276 LeaveCriticalSection( &msg->cs );
277 return;
280 msg->magic = 0;
282 LeaveCriticalSection( &msg->cs );
283 free_msg( msg );
286 /**************************************************************************
287 * WsResetMessage [webservices.@]
289 HRESULT WINAPI WsResetMessage( WS_MESSAGE *handle, WS_ERROR *error )
291 struct msg *msg = (struct msg *)handle;
293 TRACE( "%p %p\n", handle, error );
294 if (error) FIXME( "ignoring error parameter\n" );
296 if (!msg) return E_INVALIDARG;
298 EnterCriticalSection( &msg->cs );
300 if (msg->magic != MSG_MAGIC)
302 LeaveCriticalSection( &msg->cs );
303 return E_INVALIDARG;
306 reset_msg( msg );
308 LeaveCriticalSection( &msg->cs );
309 return S_OK;
312 /**************************************************************************
313 * WsGetMessageProperty [webservices.@]
315 HRESULT WINAPI WsGetMessageProperty( WS_MESSAGE *handle, WS_MESSAGE_PROPERTY_ID id, void *buf,
316 ULONG size, WS_ERROR *error )
318 struct msg *msg = (struct msg *)handle;
319 HRESULT hr = S_OK;
321 TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
322 if (error) FIXME( "ignoring error parameter\n" );
324 if (!msg) return E_INVALIDARG;
326 EnterCriticalSection( &msg->cs );
328 if (msg->magic != MSG_MAGIC)
330 LeaveCriticalSection( &msg->cs );
331 return E_INVALIDARG;
334 switch (id)
336 case WS_MESSAGE_PROPERTY_STATE:
337 if (!buf || size != sizeof(msg->state)) hr = E_INVALIDARG;
338 else *(WS_MESSAGE_STATE *)buf = msg->state;
339 break;
341 case WS_MESSAGE_PROPERTY_HEAP:
342 if (!buf || size != sizeof(msg->heap)) hr = E_INVALIDARG;
343 else *(WS_HEAP **)buf = msg->heap;
344 break;
346 case WS_MESSAGE_PROPERTY_ENVELOPE_VERSION:
347 if (!buf || size != sizeof(msg->version_env)) hr = E_INVALIDARG;
348 else *(WS_ENVELOPE_VERSION *)buf = msg->version_env;
349 break;
351 case WS_MESSAGE_PROPERTY_ADDRESSING_VERSION:
352 if (!buf || size != sizeof(msg->version_addr)) hr = E_INVALIDARG;
353 else *(WS_ADDRESSING_VERSION *)buf = msg->version_addr;
354 break;
356 case WS_MESSAGE_PROPERTY_HEADER_BUFFER:
357 if (!buf || size != sizeof(msg->buf)) hr = E_INVALIDARG;
358 else *(WS_XML_BUFFER **)buf = msg->buf;
359 break;
361 case WS_MESSAGE_PROPERTY_BODY_READER:
362 if (!buf || size != sizeof(msg->reader_body)) hr = E_INVALIDARG;
363 else *(WS_XML_READER **)buf = msg->reader_body;
364 break;
366 case WS_MESSAGE_PROPERTY_BODY_WRITER:
367 if (!buf || size != sizeof(msg->writer_body)) hr = E_INVALIDARG;
368 else *(WS_XML_WRITER **)buf = msg->writer_body;
369 break;
371 case WS_MESSAGE_PROPERTY_IS_ADDRESSED:
372 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) hr = WS_E_INVALID_OPERATION;
373 else *(BOOL *)buf = msg->is_addressed;
374 break;
376 default:
377 hr = prop_get( msg->prop, msg->prop_count, id, buf, size );
380 LeaveCriticalSection( &msg->cs );
381 return hr;
384 /**************************************************************************
385 * WsSetMessageProperty [webservices.@]
387 HRESULT WINAPI WsSetMessageProperty( WS_MESSAGE *handle, WS_MESSAGE_PROPERTY_ID id, const void *value,
388 ULONG size, WS_ERROR *error )
390 struct msg *msg = (struct msg *)handle;
391 HRESULT hr;
393 TRACE( "%p %u %p %u\n", handle, id, value, size );
394 if (error) FIXME( "ignoring error parameter\n" );
396 if (!msg) return E_INVALIDARG;
398 EnterCriticalSection( &msg->cs );
400 if (msg->magic != MSG_MAGIC)
402 LeaveCriticalSection( &msg->cs );
403 return E_INVALIDARG;
406 switch (id)
408 case WS_MESSAGE_PROPERTY_STATE:
409 case WS_MESSAGE_PROPERTY_ENVELOPE_VERSION:
410 case WS_MESSAGE_PROPERTY_ADDRESSING_VERSION:
411 case WS_MESSAGE_PROPERTY_IS_ADDRESSED:
412 if (msg->state < WS_MESSAGE_STATE_INITIALIZED) hr = WS_E_INVALID_OPERATION;
413 else hr = E_INVALIDARG;
414 break;
416 default:
417 hr = prop_set( msg->prop, msg->prop_count, id, value, size );
420 LeaveCriticalSection( &msg->cs );
421 return hr;
424 /**************************************************************************
425 * WsAddressMessage [webservices.@]
427 HRESULT WINAPI WsAddressMessage( WS_MESSAGE *handle, const WS_ENDPOINT_ADDRESS *addr, WS_ERROR *error )
429 struct msg *msg = (struct msg *)handle;
430 HRESULT hr = S_OK;
432 TRACE( "%p %p %p\n", handle, addr, error );
433 if (error) FIXME( "ignoring error parameter\n" );
434 if (addr && (addr->headers || addr->extensions || addr->identity))
436 FIXME( "headers, extensions or identity not supported\n" );
437 return E_NOTIMPL;
440 if (!msg) return E_INVALIDARG;
442 EnterCriticalSection( &msg->cs );
444 if (msg->magic != MSG_MAGIC)
446 LeaveCriticalSection( &msg->cs );
447 return E_INVALIDARG;
450 if (msg->state < WS_MESSAGE_STATE_INITIALIZED || msg->is_addressed)
452 LeaveCriticalSection( &msg->cs );
453 return WS_E_INVALID_OPERATION;
456 if (addr && addr->url.length)
458 if (!(msg->addr.chars = heap_alloc( addr->url.length * sizeof(WCHAR) ))) hr = E_OUTOFMEMORY;
459 else
461 memcpy( msg->addr.chars, addr->url.chars, addr->url.length * sizeof(WCHAR) );
462 msg->addr.length = addr->url.length;
466 if (hr == S_OK) msg->is_addressed = TRUE;
468 LeaveCriticalSection( &msg->cs );
469 return hr;
472 static const WS_XML_STRING *get_env_namespace( WS_ENVELOPE_VERSION version )
474 static const WS_XML_STRING namespaces[] =
476 {41, (BYTE *)"http://schemas.xmlsoap.org/soap/envelope/"},
477 {39, (BYTE *)"http://www.w3.org/2003/05/soap-envelope"},
478 {0, NULL},
481 if (version < WS_ENVELOPE_VERSION_SOAP_1_1 || version > WS_ENVELOPE_VERSION_NONE)
483 ERR( "unknown version %u\n", version );
484 return NULL;
487 return &namespaces[version - 1];
490 static const WS_XML_STRING *get_addr_namespace( WS_ADDRESSING_VERSION version )
492 static const WS_XML_STRING namespaces[] =
494 {48, (BYTE *)"http://schemas.xmlsoap.org/ws/2004/08/addressing"},
495 {36, (BYTE *)"http://www.w3.org/2005/08/addressing"},
496 {55, (BYTE *)"http://schemas.microsoft.com/ws/2005/05/addressing/none"},
499 if (version < WS_ADDRESSING_VERSION_0_9 || version > WS_ADDRESSING_VERSION_TRANSPORT)
501 ERR( "unknown version %u\n", version );
502 return NULL;
505 return &namespaces[version - 1];
508 static const WS_XML_STRING *get_header_name( WS_HEADER_TYPE type )
510 static const WS_XML_STRING headers[] =
512 {6, (BYTE *)"Action"},
513 {2, (BYTE *)"To"},
514 {9, (BYTE *)"MessageID"},
515 {9, (BYTE *)"RelatesTo"},
516 {4, (BYTE *)"From"},
517 {7, (BYTE *)"ReplyTo"},
518 {7, (BYTE *)"FaultTo"},
521 if (type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER)
523 ERR( "unknown type %u\n", type );
524 return NULL;
527 return &headers[type - 1];
530 static HRESULT write_must_understand( WS_XML_WRITER *writer, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
532 static const WS_XML_STRING understand = {14, (BYTE *)"mustUnderstand"};
533 WS_XML_INT32_TEXT one = {{WS_XML_TEXT_TYPE_INT32}, 1};
534 HRESULT hr;
536 if ((hr = WsWriteStartAttribute( writer, prefix, &understand, ns, FALSE, NULL )) != S_OK) return hr;
537 if ((hr = WsWriteText( writer, &one.text, NULL )) != S_OK) return hr;
538 return WsWriteEndAttribute( writer, NULL );
541 static HRESULT write_action_header( WS_XML_WRITER *writer, const WS_XML_STRING *prefix_env,
542 const WS_XML_STRING *ns_env, const WS_XML_STRING *prefix_addr,
543 const WS_XML_STRING *ns_addr, const WS_XML_STRING *text )
545 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}};
546 const WS_XML_STRING *action = get_header_name( WS_ACTION_HEADER );
547 HRESULT hr;
549 if (!text || !text->length) return S_OK;
550 utf8.value.length = text->length;
551 utf8.value.bytes = text->bytes;
553 if ((hr = WsWriteStartElement( writer, prefix_addr, action, ns_addr, NULL )) != S_OK) return hr;
554 if ((hr = write_must_understand( writer, prefix_env, ns_env )) != S_OK) return hr;
555 if ((hr = WsWriteText( writer, &utf8.text, NULL )) != S_OK) return hr;
556 return WsWriteEndElement( writer, NULL ); /* </a:Action> */
559 static HRESULT write_to_header( WS_XML_WRITER *writer, const WS_XML_STRING *prefix_env,
560 const WS_XML_STRING *ns_env, const WS_XML_STRING *prefix_addr,
561 const WS_XML_STRING *ns_addr, const WS_STRING *addr )
563 WS_XML_UTF16_TEXT utf16 = {{WS_XML_TEXT_TYPE_UTF16}, (BYTE *)addr->chars, addr->length * sizeof(WCHAR)};
564 const WS_XML_STRING *to = get_header_name( WS_TO_HEADER );
565 HRESULT hr;
567 if ((hr = WsWriteStartElement( writer, prefix_addr, to, ns_addr, NULL )) != S_OK) return hr;
568 if ((hr = write_must_understand( writer, prefix_env, ns_env )) != S_OK) return hr;
569 if ((hr = WsWriteText( writer, &utf16.text, NULL )) != S_OK) return hr;
570 return WsWriteEndElement( writer, NULL ); /* </a:To> */
573 static HRESULT write_replyto_header( WS_XML_WRITER *writer, const WS_XML_STRING *prefix_env,
574 const WS_XML_STRING *ns_env, const WS_XML_STRING *prefix_addr,
575 const WS_XML_STRING *ns_addr )
577 static const char anonymous[] = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
578 WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}, {sizeof(anonymous) - 1, (BYTE *)anonymous}};
579 const WS_XML_STRING address = {7, (BYTE *)"Address"}, *replyto = get_header_name( WS_REPLY_TO_HEADER );
580 HRESULT hr;
582 if ((hr = WsWriteStartElement( writer, prefix_addr, replyto, ns_addr, NULL )) != S_OK) return hr;
583 if ((hr = WsWriteStartElement( writer, prefix_addr, &address, ns_addr, NULL )) != S_OK) return hr;
584 if ((hr = WsWriteText( writer, &utf8.text, NULL )) != S_OK) return hr;
585 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </a:Address> */
586 return WsWriteEndElement( writer, NULL ); /* </a:ReplyTo> */
589 static HRESULT write_msgid_header( WS_XML_WRITER *writer, const WS_XML_STRING *prefix_env,
590 const WS_XML_STRING *ns_env, const WS_XML_STRING *prefix_addr,
591 const WS_XML_STRING *ns_addr, const GUID *guid )
593 WS_XML_UNIQUE_ID_TEXT id = {{WS_XML_TEXT_TYPE_UNIQUE_ID}, *guid};
594 const WS_XML_STRING *msgid = get_header_name( WS_MESSAGE_ID_HEADER );
595 HRESULT hr;
597 if ((hr = WsWriteStartElement( writer, prefix_addr, msgid, ns_addr, NULL )) != S_OK) return hr;
598 if ((hr = WsWriteText( writer, &id.text, NULL )) != S_OK) return hr;
599 return WsWriteEndElement( writer, NULL ); /* </a:MessageID> */
602 static HRESULT write_relatesto_header( WS_XML_WRITER *writer, const WS_XML_STRING *prefix_env,
603 const WS_XML_STRING *ns_env, const WS_XML_STRING *prefix_addr,
604 const WS_XML_STRING *ns_addr, const GUID *guid )
606 WS_XML_UNIQUE_ID_TEXT id = {{WS_XML_TEXT_TYPE_UNIQUE_ID}, *guid};
607 const WS_XML_STRING *relatesto = get_header_name( WS_RELATES_TO_HEADER );
608 HRESULT hr;
610 if ((hr = WsWriteStartElement( writer, prefix_addr, relatesto, ns_addr, NULL )) != S_OK) return hr;
611 if ((hr = WsWriteText( writer, &id.text, NULL )) != S_OK) return hr;
612 return WsWriteEndElement( writer, NULL ); /* </a:RelatesTo> */
615 static HRESULT write_headers( struct msg *msg, WS_XML_WRITER *writer, const WS_XML_STRING *prefix_env,
616 const WS_XML_STRING *ns_env, const WS_XML_STRING *prefix_addr,
617 const WS_XML_STRING *ns_addr )
619 static const WS_XML_STRING header = {6, (BYTE *)"Header"};
620 HRESULT hr;
621 ULONG i;
623 if ((hr = WsWriteXmlnsAttribute( writer, prefix_addr, ns_addr, FALSE, NULL )) != S_OK) return hr;
624 if ((hr = WsWriteStartElement( writer, prefix_env, &header, ns_env, NULL )) != S_OK) return hr;
626 if ((hr = write_action_header( writer, prefix_env, ns_env, prefix_addr, ns_addr, msg->action )) != S_OK)
627 return hr;
629 if (msg->init == WS_REPLY_MESSAGE)
631 if ((hr = write_relatesto_header( writer, prefix_env, ns_env, prefix_addr, ns_addr, &msg->id_req )) != S_OK)
632 return hr;
634 else if (msg->addr.length)
636 if ((hr = write_to_header( writer, prefix_env, ns_env, prefix_addr, ns_addr, &msg->addr )) != S_OK)
637 return hr;
639 else
641 if ((hr = write_msgid_header( writer, prefix_env, ns_env, prefix_addr, ns_addr, &msg->id )) != S_OK)
642 return hr;
643 if (msg->version_addr == WS_ADDRESSING_VERSION_0_9 &&
644 (hr = write_replyto_header( writer, prefix_env, ns_env, prefix_addr, ns_addr )) != S_OK) return hr;
647 for (i = 0; i < msg->header_count; i++)
649 if (msg->header[i]->mapped) continue;
650 if ((hr = WsWriteXmlBuffer( writer, msg->header[i]->u.buf, NULL )) != S_OK) return hr;
653 return WsWriteEndElement( writer, NULL ); /* </s:Header> */
656 static HRESULT write_headers_transport( struct msg *msg, WS_XML_WRITER *writer, const WS_XML_STRING *prefix,
657 const WS_XML_STRING *ns )
659 static const WS_XML_STRING header = {6, (BYTE *)"Header"};
660 HRESULT hr = S_OK;
661 ULONG i;
663 if ((msg->header_count || !msg->action) &&
664 (hr = WsWriteStartElement( writer, prefix, &header, ns, NULL )) != S_OK) return hr;
666 for (i = 0; i < msg->header_count; i++)
668 if (msg->header[i]->mapped) continue;
669 if ((hr = WsWriteXmlBuffer( writer, msg->header[i]->u.buf, NULL )) != S_OK) return hr;
672 if (msg->header_count || !msg->action) hr = WsWriteEndElement( writer, NULL ); /* </s:Header> */
673 return hr;
676 static HRESULT write_envelope_start( struct msg *msg, WS_XML_WRITER *writer )
678 static const WS_XML_STRING envelope = {8, (BYTE *)"Envelope"}, body = {4, (BYTE *)"Body"};
679 static const WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"};
680 const WS_XML_STRING *prefix_env = (msg->version_env == WS_ENVELOPE_VERSION_NONE) ? NULL : &prefix_s;
681 const WS_XML_STRING *prefix_addr = (msg->version_addr == WS_ADDRESSING_VERSION_TRANSPORT) ? NULL : &prefix_a;
682 const WS_XML_STRING *ns_env = get_env_namespace( msg->version_env );
683 const WS_XML_STRING *ns_addr = get_addr_namespace( msg->version_addr );
684 HRESULT hr;
686 if ((hr = WsWriteStartElement( writer, prefix_env, &envelope, ns_env, NULL )) != S_OK) return hr;
688 if (msg->version_addr == WS_ADDRESSING_VERSION_TRANSPORT)
689 hr = write_headers_transport( msg, writer, prefix_env, ns_env );
690 else
691 hr = write_headers( msg, writer, prefix_env, ns_env, prefix_addr, ns_addr );
692 if (hr != S_OK) return hr;
694 return WsWriteStartElement( writer, prefix_env, &body, ns_env, NULL ); /* <s:Body> */
697 static HRESULT write_envelope_end( WS_XML_WRITER *writer )
699 HRESULT hr;
700 if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </s:Body> */
701 return WsWriteEndElement( writer, NULL ); /* </s:Envelope> */
704 static HRESULT write_envelope( struct msg *msg )
706 HRESULT hr;
707 if (!msg->writer && (hr = WsCreateWriter( NULL, 0, &msg->writer, NULL )) != S_OK) return hr;
708 if (!msg->buf && (hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &msg->buf, NULL )) != S_OK) return hr;
709 if ((hr = WsSetOutputToBuffer( msg->writer, msg->buf, NULL, 0, NULL )) != S_OK) return hr;
710 if ((hr = write_envelope_start( msg, msg->writer )) != S_OK) return hr;
711 return write_envelope_end( msg->writer );
714 /**************************************************************************
715 * WsWriteEnvelopeStart [webservices.@]
717 HRESULT WINAPI WsWriteEnvelopeStart( WS_MESSAGE *handle, WS_XML_WRITER *writer,
718 WS_MESSAGE_DONE_CALLBACK cb, void *state, WS_ERROR *error )
720 struct msg *msg = (struct msg *)handle;
721 HRESULT hr;
723 TRACE( "%p %p %p %p %p\n", handle, writer, cb, state, error );
724 if (error) FIXME( "ignoring error parameter\n" );
725 if (cb)
727 FIXME( "callback not supported\n" );
728 return E_NOTIMPL;
731 if (!msg || !writer) return E_INVALIDARG;
733 EnterCriticalSection( &msg->cs );
735 if (msg->magic != MSG_MAGIC)
737 LeaveCriticalSection( &msg->cs );
738 return E_INVALIDARG;
741 if (msg->state != WS_MESSAGE_STATE_INITIALIZED)
743 LeaveCriticalSection( &msg->cs );
744 return WS_E_INVALID_OPERATION;
747 if ((hr = write_envelope( msg )) != S_OK) goto done;
748 if ((hr = write_envelope_start( msg, writer )) != S_OK) goto done;
750 msg->writer_body = writer;
751 msg->state = WS_MESSAGE_STATE_WRITING;
753 done:
754 LeaveCriticalSection( &msg->cs );
755 return hr;
758 /**************************************************************************
759 * WsWriteEnvelopeEnd [webservices.@]
761 HRESULT WINAPI WsWriteEnvelopeEnd( WS_MESSAGE *handle, WS_ERROR *error )
763 struct msg *msg = (struct msg *)handle;
764 HRESULT hr;
766 TRACE( "%p %p\n", handle, error );
767 if (error) FIXME( "ignoring error parameter\n" );
769 if (!msg) return E_INVALIDARG;
771 EnterCriticalSection( &msg->cs );
773 if (msg->magic != MSG_MAGIC)
775 LeaveCriticalSection( &msg->cs );
776 return E_INVALIDARG;
779 if (msg->state != WS_MESSAGE_STATE_WRITING)
781 LeaveCriticalSection( &msg->cs );
782 return WS_E_INVALID_OPERATION;
785 if ((hr = write_envelope_end( msg->writer_body )) == S_OK) msg->state = WS_MESSAGE_STATE_DONE;
787 LeaveCriticalSection( &msg->cs );
788 return hr;
791 /**************************************************************************
792 * WsWriteBody [webservices.@]
794 HRESULT WINAPI WsWriteBody( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *desc, WS_WRITE_OPTION option,
795 const void *value, ULONG size, WS_ERROR *error )
797 struct msg *msg = (struct msg *)handle;
798 HRESULT hr;
800 TRACE( "%p %p %08x %p %u %p\n", handle, desc, option, value, size, error );
801 if (error) FIXME( "ignoring error parameter\n" );
803 if (!msg || !desc) return E_INVALIDARG;
805 EnterCriticalSection( &msg->cs );
807 if (msg->magic != MSG_MAGIC)
809 LeaveCriticalSection( &msg->cs );
810 return E_INVALIDARG;
813 if (msg->state != WS_MESSAGE_STATE_WRITING)
815 LeaveCriticalSection( &msg->cs );
816 return WS_E_INVALID_OPERATION;
819 if (desc->elementLocalName &&
820 (hr = WsWriteStartElement( msg->writer_body, NULL, desc->elementLocalName, desc->elementNs,
821 NULL )) != S_OK) goto done;
823 if ((hr = WsWriteType( msg->writer_body, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription,
824 option, value, size, NULL )) != S_OK) goto done;
826 if (desc->elementLocalName) hr = WsWriteEndElement( msg->writer_body, NULL );
828 done:
829 LeaveCriticalSection( &msg->cs );
830 return hr;
833 static BOOL match_current_element( WS_XML_READER *reader, const WS_XML_STRING *localname )
835 const WS_XML_NODE *node;
836 const WS_XML_ELEMENT_NODE *elem;
838 if (WsGetReaderNode( reader, &node, NULL ) != S_OK) return FALSE;
839 if (node->nodeType != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
840 elem = (const WS_XML_ELEMENT_NODE *)node;
841 return WsXmlStringEquals( elem->localName, localname, NULL ) == S_OK;
844 static HRESULT read_message_id( WS_XML_READER *reader, GUID *ret )
846 const WS_XML_NODE *node;
847 const WS_XML_TEXT_NODE *text;
848 const WS_XML_UNIQUE_ID_TEXT *id;
849 HRESULT hr;
851 if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr;
852 if ((hr = WsGetReaderNode( reader, &node, NULL )) != S_OK) return hr;
853 if (node->nodeType != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
854 text = (const WS_XML_TEXT_NODE *)node;
855 if (text->text->textType != WS_XML_TEXT_TYPE_UNIQUE_ID)
857 FIXME( "unhandled text type %u\n", text->text->textType );
858 return E_NOTIMPL;
860 id = (const WS_XML_UNIQUE_ID_TEXT *)text->text;
861 *ret = id->value;
862 return S_OK;
865 static HRESULT read_envelope_start( struct msg *msg, WS_XML_READER *reader )
867 static const WS_XML_STRING envelope = {8, (BYTE *)"Envelope"}, body = {4, (BYTE *)"Body"};
868 static const WS_XML_STRING header = {6, (BYTE *)"Header"}, msgid = {9, (BYTE *)"MessageID"};
869 HRESULT hr;
871 if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr;
872 if (!match_current_element( reader, &envelope )) return WS_E_INVALID_FORMAT;
873 if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr;
874 if (match_current_element( reader, &header ))
876 for (;;)
878 if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr;
879 if (match_current_element( reader, &msgid ) && (hr = read_message_id( reader, &msg->id_req )) != S_OK)
880 return hr;
881 if (match_current_element( reader, &body )) break;
884 if (!match_current_element( reader, &body )) return WS_E_INVALID_FORMAT;
885 return WsReadNode( reader, NULL );
888 /**************************************************************************
889 * WsReadEnvelopeStart [webservices.@]
891 HRESULT WINAPI WsReadEnvelopeStart( WS_MESSAGE *handle, WS_XML_READER *reader, WS_MESSAGE_DONE_CALLBACK cb,
892 void *state, WS_ERROR *error )
894 struct msg *msg = (struct msg *)handle;
895 HRESULT hr;
897 TRACE( "%p %p %p %p %p\n", handle, reader, cb, state, error );
898 if (error) FIXME( "ignoring error parameter\n" );
899 if (cb)
901 FIXME( "callback not supported\n" );
902 return E_NOTIMPL;
905 if (!msg || !reader) return E_INVALIDARG;
907 EnterCriticalSection( &msg->cs );
909 if (msg->magic != MSG_MAGIC)
911 LeaveCriticalSection( &msg->cs );
912 return E_INVALIDARG;
915 if (msg->state != WS_MESSAGE_STATE_EMPTY)
917 LeaveCriticalSection( &msg->cs );
918 return WS_E_INVALID_OPERATION;
921 if ((hr = read_envelope_start( msg, reader )) == S_OK &&
922 (hr = create_header_buffer( reader, msg->heap, &msg->buf )) == S_OK)
924 msg->reader_body = reader;
925 msg->state = WS_MESSAGE_STATE_READING;
928 LeaveCriticalSection( &msg->cs );
929 return hr;
932 static HRESULT read_envelope_end( WS_XML_READER *reader )
934 HRESULT hr;
935 if ((hr = WsReadEndElement( reader, NULL )) != S_OK) return hr; /* </s:Body> */
936 return WsReadEndElement( reader, NULL ); /* </s:Envelope> */
939 /**************************************************************************
940 * WsReadEnvelopeEnd [webservices.@]
942 HRESULT WINAPI WsReadEnvelopeEnd( WS_MESSAGE *handle, WS_ERROR *error )
944 struct msg *msg = (struct msg *)handle;
945 HRESULT hr;
947 TRACE( "%p %p\n", handle, error );
948 if (error) FIXME( "ignoring error parameter\n" );
950 if (!msg) return E_INVALIDARG;
952 EnterCriticalSection( &msg->cs );
954 if (msg->magic != MSG_MAGIC)
956 LeaveCriticalSection( &msg->cs );
957 return E_INVALIDARG;
960 if (msg->state != WS_MESSAGE_STATE_READING)
962 LeaveCriticalSection( &msg->cs );
963 return WS_E_INVALID_OPERATION;
966 if ((hr = read_envelope_end( msg->reader_body )) == S_OK) msg->state = WS_MESSAGE_STATE_DONE;
968 LeaveCriticalSection( &msg->cs );
969 return hr;
972 /**************************************************************************
973 * WsReadBody [webservices.@]
975 HRESULT WINAPI WsReadBody( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *desc, WS_READ_OPTION option,
976 WS_HEAP *heap, void *value, ULONG size, WS_ERROR *error )
978 struct msg *msg = (struct msg *)handle;
979 HRESULT hr;
981 TRACE( "%p %p %08x %p %p %u %p\n", handle, desc, option, heap, value, size, error );
982 if (error) FIXME( "ignoring error parameter\n" );
984 if (!msg || !desc) return E_INVALIDARG;
986 EnterCriticalSection( &msg->cs );
988 if (msg->magic != MSG_MAGIC)
990 LeaveCriticalSection( &msg->cs );
991 return E_INVALIDARG;
994 if (msg->state != WS_MESSAGE_STATE_READING)
996 LeaveCriticalSection( &msg->cs );
997 return WS_E_INVALID_OPERATION;
1000 hr = WsReadElement( msg->reader_body, desc, option, heap, value, size, NULL );
1002 LeaveCriticalSection( &msg->cs );
1003 return hr;
1006 /**************************************************************************
1007 * WsInitializeMessage [webservices.@]
1009 HRESULT WINAPI WsInitializeMessage( WS_MESSAGE *handle, WS_MESSAGE_INITIALIZATION init,
1010 WS_MESSAGE *src_handle, WS_ERROR *error )
1012 struct msg *msg = (struct msg *)handle;
1013 HRESULT hr;
1015 TRACE( "%p %u %p %p\n", handle, init, src_handle, error );
1016 if (error) FIXME( "ignoring error parameter\n" );
1017 if (src_handle)
1019 FIXME( "src message not supported\n" );
1020 return E_NOTIMPL;
1023 if (!msg || init > WS_FAULT_MESSAGE) return E_INVALIDARG;
1025 EnterCriticalSection( &msg->cs );
1027 if (msg->magic != MSG_MAGIC)
1029 LeaveCriticalSection( &msg->cs );
1030 return E_INVALIDARG;
1033 if (msg->state >= WS_MESSAGE_STATE_INITIALIZED)
1035 LeaveCriticalSection( &msg->cs );
1036 return WS_E_INVALID_OPERATION;
1039 if ((hr = write_envelope( msg )) == S_OK)
1041 msg->init = init;
1042 msg->state = WS_MESSAGE_STATE_INITIALIZED;
1045 LeaveCriticalSection( &msg->cs );
1046 return hr;
1049 static HRESULT grow_header_array( struct msg *msg, ULONG size )
1051 struct header **tmp;
1052 if (size <= msg->header_size) return S_OK;
1053 if (!(tmp = heap_realloc( msg->header, 2 * msg->header_size * sizeof(struct header *) )))
1054 return E_OUTOFMEMORY;
1055 msg->header = tmp;
1056 msg->header_size *= 2;
1057 return S_OK;
1060 static struct header *alloc_header( WS_HEADER_TYPE type, BOOL mapped, const WS_XML_STRING *name,
1061 const WS_XML_STRING *ns )
1063 struct header *ret;
1064 if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
1065 if (name && name->length)
1067 if (!(ret->name.bytes = heap_alloc( name->length )))
1069 free_header( ret );
1070 return NULL;
1072 memcpy( ret->name.bytes, name->bytes, name->length );
1073 ret->name.length = name->length;
1075 if (ns && ns->length)
1077 if (!(ret->ns.bytes = heap_alloc( ns->length )))
1079 free_header( ret );
1080 return NULL;
1082 memcpy( ret->ns.bytes, ns->bytes, ns->length );
1083 ret->ns.length = ns->length;
1085 ret->type = type;
1086 ret->mapped = mapped;
1087 return ret;
1090 static HRESULT write_standard_header( struct msg *msg, WS_HEADER_TYPE type, WS_TYPE value_type,
1091 WS_WRITE_OPTION option, const void *value, ULONG size )
1093 static const WS_XML_STRING ns = {0, NULL};
1094 static const WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"};
1095 const WS_XML_STRING *prefix_env = (msg->version_env == WS_ENVELOPE_VERSION_NONE) ? NULL : &prefix_s;
1096 const WS_XML_STRING *prefix_addr = (msg->version_addr == WS_ADDRESSING_VERSION_TRANSPORT) ? NULL : &prefix_a;
1097 const WS_XML_STRING *localname = get_header_name( type );
1098 HRESULT hr;
1100 if ((hr = WsWriteStartElement( msg->writer, prefix_addr, localname, &ns, NULL )) != S_OK) return hr;
1101 if ((hr = write_must_understand( msg->writer, prefix_env, &ns )) != S_OK) return hr;
1102 if (msg->version_addr == WS_ADDRESSING_VERSION_TRANSPORT)
1104 const WS_XML_STRING *ns_addr = get_addr_namespace( WS_ADDRESSING_VERSION_TRANSPORT );
1105 if ((hr = WsWriteXmlnsAttribute( msg->writer, NULL, ns_addr, FALSE, NULL )) != S_OK) return hr;
1107 if ((hr = WsWriteType( msg->writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, value_type, NULL, option, value, size,
1108 NULL )) != S_OK) return hr;
1109 return WsWriteEndElement( msg->writer, NULL );
1112 static HRESULT build_standard_header( struct msg *msg, WS_HEADER_TYPE type, WS_TYPE value_type,
1113 WS_WRITE_OPTION option, const void *value, ULONG size,
1114 struct header **ret )
1116 struct header *header;
1117 WS_XML_BUFFER *buf;
1118 HRESULT hr;
1120 if (!(header = alloc_header( type, FALSE, get_header_name(type), NULL ))) return E_OUTOFMEMORY;
1122 if (!msg->writer && (hr = WsCreateWriter( NULL, 0, &msg->writer, NULL )) != S_OK) goto done;
1123 if ((hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &buf, NULL )) != S_OK) goto done;
1124 if ((hr = WsSetOutputToBuffer( msg->writer, buf, NULL, 0, NULL )) != S_OK) goto done;
1125 if ((hr = write_standard_header( msg, type, value_type, option, value, size )) != S_OK) goto done;
1127 header->u.buf = buf;
1129 done:
1130 if (hr != S_OK) free_header( header );
1131 else *ret = header;
1132 return hr;
1135 /**************************************************************************
1136 * WsSetHeader [webservices.@]
1138 HRESULT WINAPI WsSetHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_TYPE value_type,
1139 WS_WRITE_OPTION option, const void *value, ULONG size, WS_ERROR *error )
1141 struct msg *msg = (struct msg *)handle;
1142 struct header *header;
1143 BOOL found = FALSE;
1144 HRESULT hr;
1145 ULONG i;
1147 TRACE( "%p %u %u %08x %p %u %p\n", handle, type, value_type, option, value, size, error );
1148 if (error) FIXME( "ignoring error parameter\n" );
1150 if (!msg || type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) return E_INVALIDARG;
1152 EnterCriticalSection( &msg->cs );
1154 if (msg->magic != MSG_MAGIC)
1156 LeaveCriticalSection( &msg->cs );
1157 return E_INVALIDARG;
1160 if (msg->state < WS_MESSAGE_STATE_INITIALIZED)
1162 LeaveCriticalSection( &msg->cs );
1163 return WS_E_INVALID_OPERATION;
1166 for (i = 0; i < msg->header_count; i++)
1168 if (msg->header[i]->type == type)
1170 found = TRUE;
1171 break;
1175 if (!found)
1177 if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) goto done;
1178 i = msg->header_count;
1181 if ((hr = build_standard_header( msg, type, value_type, option, value, size, &header )) != S_OK)
1182 goto done;
1184 if (!found) msg->header_count++;
1185 else free_header( msg->header[i] );
1187 msg->header[i] = header;
1188 hr = write_envelope( msg );
1190 done:
1191 LeaveCriticalSection( &msg->cs );
1192 return hr;
1195 static HRESULT find_header( WS_XML_READER *reader, const WS_XML_STRING *localname, const WS_XML_STRING *ns )
1197 const WS_XML_NODE *node;
1198 const WS_XML_ELEMENT_NODE *elem;
1199 HRESULT hr;
1201 for (;;)
1203 if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr;
1204 if ((hr = WsGetReaderNode( reader, &node, NULL )) != S_OK) return hr;
1205 if (node->nodeType == WS_XML_NODE_TYPE_EOF) return WS_E_INVALID_FORMAT;
1206 if (node->nodeType != WS_XML_NODE_TYPE_ELEMENT) continue;
1208 elem = (const WS_XML_ELEMENT_NODE *)node;
1209 if (WsXmlStringEquals( elem->localName, localname, NULL ) == S_OK &&
1210 WsXmlStringEquals( elem->ns, ns, NULL ) == S_OK) break;
1213 return S_OK;
1216 static HRESULT get_standard_header( struct msg *msg, WS_HEADER_TYPE type, WS_TYPE value_type,
1217 WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size )
1219 const WS_XML_STRING *localname = get_header_name( type );
1220 const WS_XML_STRING *ns = get_addr_namespace( msg->version_addr );
1221 HRESULT hr;
1223 if (!heap) heap = msg->heap;
1224 if (!msg->reader && (hr = WsCreateReader( NULL, 0, &msg->reader, NULL )) != S_OK) return hr;
1225 if ((hr = WsSetInputToBuffer( msg->reader, msg->buf, NULL, 0, NULL )) != S_OK) return hr;
1227 if ((hr = find_header( msg->reader, localname, ns )) != S_OK) return hr;
1228 return read_header( msg->reader, localname, ns, value_type, NULL, option, heap, value, size );
1231 /**************************************************************************
1232 * WsGetHeader [webservices.@]
1234 HRESULT WINAPI WsGetHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_TYPE value_type, WS_READ_OPTION option,
1235 WS_HEAP *heap, void *value, ULONG size, WS_ERROR *error )
1237 struct msg *msg = (struct msg *)handle;
1238 HRESULT hr;
1240 TRACE( "%p %u %u %08x %p %p %u %p\n", handle, type, value_type, option, heap, value, size, error );
1241 if (error) FIXME( "ignoring error parameter\n" );
1243 if (!msg || type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER || option < WS_READ_REQUIRED_VALUE ||
1244 option > WS_READ_OPTIONAL_POINTER) return E_INVALIDARG;
1246 EnterCriticalSection( &msg->cs );
1248 if (msg->magic != MSG_MAGIC)
1250 LeaveCriticalSection( &msg->cs );
1251 return E_INVALIDARG;
1254 if (msg->state < WS_MESSAGE_STATE_INITIALIZED)
1256 LeaveCriticalSection( &msg->cs );
1257 return WS_E_INVALID_OPERATION;
1260 hr = get_standard_header( msg, type, value_type, option, heap, value, size );
1262 LeaveCriticalSection( &msg->cs );
1263 return hr;
1266 static void remove_header( struct msg *msg, ULONG i )
1268 free_header( msg->header[i] );
1269 memmove( &msg->header[i], &msg->header[i + 1], (msg->header_count - i - 1) * sizeof(struct header *) );
1270 msg->header_count--;
1273 /**************************************************************************
1274 * WsRemoveHeader [webservices.@]
1276 HRESULT WINAPI WsRemoveHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_ERROR *error )
1278 struct msg *msg = (struct msg *)handle;
1279 BOOL removed = FALSE;
1280 HRESULT hr = S_OK;
1281 ULONG i;
1283 TRACE( "%p %u %p\n", handle, type, error );
1284 if (error) FIXME( "ignoring error parameter\n" );
1286 if (!msg) return E_INVALIDARG;
1288 EnterCriticalSection( &msg->cs );
1290 if (msg->magic != MSG_MAGIC)
1292 LeaveCriticalSection( &msg->cs );
1293 return E_INVALIDARG;
1296 if (msg->state < WS_MESSAGE_STATE_INITIALIZED)
1298 LeaveCriticalSection( &msg->cs );
1299 return WS_E_INVALID_OPERATION;
1302 if (type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER)
1304 LeaveCriticalSection( &msg->cs );
1305 return E_INVALIDARG;
1308 for (i = 0; i < msg->header_count; i++)
1310 if (msg->header[i]->type == type)
1312 remove_header( msg, i );
1313 removed = TRUE;
1314 break;
1318 if (removed) hr = write_envelope( msg );
1320 LeaveCriticalSection( &msg->cs );
1321 return hr;
1324 static HRESULT build_mapped_header( const WS_XML_STRING *name, WS_TYPE type, WS_WRITE_OPTION option,
1325 const void *value, ULONG size, struct header **ret )
1327 struct header *header;
1329 if (!(header = alloc_header( 0, TRUE, name, NULL ))) return E_OUTOFMEMORY;
1330 switch (type)
1332 case WS_WSZ_TYPE:
1334 int len;
1335 const WCHAR *src;
1337 if (option != WS_WRITE_REQUIRED_POINTER || size != sizeof(WCHAR *))
1339 free_header( header );
1340 return E_INVALIDARG;
1342 src = *(const WCHAR **)value;
1343 len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL ) - 1;
1344 if (!(header->u.text = alloc_xml_string( NULL, len )))
1346 free_header( header );
1347 return E_OUTOFMEMORY;
1349 WideCharToMultiByte( CP_UTF8, 0, src, -1, (char *)header->u.text->bytes, len, NULL, NULL );
1350 break;
1352 case WS_XML_STRING_TYPE:
1354 const WS_XML_STRING *str = value;
1356 if (option != WS_WRITE_REQUIRED_VALUE)
1358 FIXME( "unhandled write option %u\n", option );
1359 free_header( header );
1360 return E_NOTIMPL;
1362 if (size != sizeof(*str))
1364 free_header( header );
1365 return E_INVALIDARG;
1367 if (!(header->u.text = alloc_xml_string( NULL, str->length )))
1369 free_header( header );
1370 return E_OUTOFMEMORY;
1372 memcpy( header->u.text->bytes, str->bytes, str->length );
1373 break;
1375 case WS_STRING_TYPE:
1377 int len;
1378 const WS_STRING *str = value;
1380 if (option != WS_WRITE_REQUIRED_VALUE)
1382 FIXME( "unhandled write option %u\n", option );
1383 free_header( header );
1384 return E_NOTIMPL;
1386 if (size != sizeof(*str))
1388 free_header( header );
1389 return E_INVALIDARG;
1391 len = WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, NULL, 0, NULL, NULL );
1392 if (!(header->u.text = alloc_xml_string( NULL, len )))
1394 free_header( header );
1395 return E_OUTOFMEMORY;
1397 WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, (char *)header->u.text->bytes,
1398 len, NULL, NULL );
1399 break;
1401 default:
1402 FIXME( "unhandled type %u\n", type );
1403 free_header( header );
1404 return E_NOTIMPL;
1407 *ret = header;
1408 return S_OK;
1411 /**************************************************************************
1412 * WsAddMappedHeader [webservices.@]
1414 HRESULT WINAPI WsAddMappedHeader( WS_MESSAGE *handle, const WS_XML_STRING *name, WS_TYPE type,
1415 WS_WRITE_OPTION option, const void *value, ULONG size, WS_ERROR *error )
1417 struct msg *msg = (struct msg *)handle;
1418 struct header *header;
1419 BOOL found = FALSE;
1420 HRESULT hr;
1421 ULONG i;
1423 TRACE( "%p %s %u %08x %p %u %p\n", handle, debugstr_xmlstr(name), type, option, value, size, error );
1424 if (error) FIXME( "ignoring error parameter\n" );
1426 if (!msg || !name) return E_INVALIDARG;
1428 EnterCriticalSection( &msg->cs );
1430 if (msg->magic != MSG_MAGIC)
1432 LeaveCriticalSection( &msg->cs );
1433 return E_INVALIDARG;
1436 if (msg->state < WS_MESSAGE_STATE_INITIALIZED)
1438 LeaveCriticalSection( &msg->cs );
1439 return WS_E_INVALID_OPERATION;
1442 for (i = 0; i < msg->header_count; i++)
1444 if (msg->header[i]->type || !msg->header[i]->mapped) continue;
1445 if (WsXmlStringEquals( name, &msg->header[i]->name, NULL ) == S_OK)
1447 found = TRUE;
1448 break;
1452 if (!found)
1454 if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) goto done;
1455 i = msg->header_count;
1458 if ((hr = build_mapped_header( name, type, option, value, size, &header )) != S_OK) goto done;
1460 if (!found) msg->header_count++;
1461 else free_header( msg->header[i] );
1463 msg->header[i] = header;
1465 done:
1466 LeaveCriticalSection( &msg->cs );
1467 return hr;
1470 /**************************************************************************
1471 * WsRemoveMappedHeader [webservices.@]
1473 HRESULT WINAPI WsRemoveMappedHeader( WS_MESSAGE *handle, const WS_XML_STRING *name, WS_ERROR *error )
1475 struct msg *msg = (struct msg *)handle;
1476 ULONG i;
1478 TRACE( "%p %s %p\n", handle, debugstr_xmlstr(name), error );
1479 if (error) FIXME( "ignoring error parameter\n" );
1481 if (!msg || !name) return E_INVALIDARG;
1483 EnterCriticalSection( &msg->cs );
1485 if (msg->magic != MSG_MAGIC)
1487 LeaveCriticalSection( &msg->cs );
1488 return E_INVALIDARG;
1491 if (msg->state < WS_MESSAGE_STATE_INITIALIZED)
1493 LeaveCriticalSection( &msg->cs );
1494 return WS_E_INVALID_OPERATION;
1497 for (i = 0; i < msg->header_count; i++)
1499 if (msg->header[i]->type || !msg->header[i]->mapped) continue;
1500 if (WsXmlStringEquals( name, &msg->header[i]->name, NULL ) == S_OK)
1502 remove_header( msg, i );
1503 break;
1507 LeaveCriticalSection( &msg->cs );
1508 return S_OK;
1511 static HRESULT write_custom_header( WS_XML_WRITER *writer, const WS_XML_STRING *name, const WS_XML_STRING *ns,
1512 WS_TYPE type, const void *desc, WS_WRITE_OPTION option, const void *value,
1513 ULONG size )
1515 HRESULT hr;
1516 if ((hr = WsWriteStartElement( writer, NULL, name, ns, NULL )) != S_OK) return hr;
1517 if ((hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, desc, option, value, size,
1518 NULL )) != S_OK) return hr;
1519 return WsWriteEndElement( writer, NULL );
1522 static HRESULT build_custom_header( struct msg *msg, const WS_XML_STRING *name, const WS_XML_STRING *ns,
1523 WS_TYPE type, const void *desc, WS_WRITE_OPTION option, const void *value,
1524 ULONG size, struct header **ret )
1526 struct header *header;
1527 WS_XML_BUFFER *buf;
1528 HRESULT hr;
1530 if (!(header = alloc_header( 0, FALSE, name, ns ))) return E_OUTOFMEMORY;
1532 if (!msg->writer && (hr = WsCreateWriter( NULL, 0, &msg->writer, NULL )) != S_OK) goto done;
1533 if ((hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &buf, NULL )) != S_OK) goto done;
1534 if ((hr = WsSetOutputToBuffer( msg->writer, buf, NULL, 0, NULL )) != S_OK) goto done;
1535 if ((hr = write_custom_header( msg->writer, name, ns, type, desc, option, value, size )) != S_OK) goto done;
1537 header->u.buf = buf;
1539 done:
1540 if (hr != S_OK) free_header( header );
1541 else *ret = header;
1542 return hr;
1545 /**************************************************************************
1546 * WsAddCustomHeader [webservices.@]
1548 HRESULT WINAPI WsAddCustomHeader( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *desc, WS_WRITE_OPTION option,
1549 const void *value, ULONG size, ULONG attrs, WS_ERROR *error )
1551 struct msg *msg = (struct msg *)handle;
1552 struct header *header;
1553 HRESULT hr;
1555 TRACE( "%p %p %08x %p %u %08x %p\n", handle, desc, option, value, size, attrs, error );
1556 if (error) FIXME( "ignoring error parameter\n" );
1558 if (!msg || !desc) return E_INVALIDARG;
1560 EnterCriticalSection( &msg->cs );
1562 if (msg->magic != MSG_MAGIC)
1564 LeaveCriticalSection( &msg->cs );
1565 return E_INVALIDARG;
1568 if (msg->state < WS_MESSAGE_STATE_INITIALIZED)
1570 LeaveCriticalSection( &msg->cs );
1571 return WS_E_INVALID_OPERATION;
1574 if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) goto done;
1575 if ((hr = build_custom_header( msg, desc->elementLocalName, desc->elementNs, desc->type,
1576 desc->typeDescription, option, value, size, &header )) != S_OK) goto done;
1577 msg->header[msg->header_count++] = header;
1578 hr = write_envelope( msg );
1580 done:
1581 LeaveCriticalSection( &msg->cs );
1582 return hr;
1585 static HRESULT get_custom_header( struct msg *msg, const WS_ELEMENT_DESCRIPTION *desc, WS_READ_OPTION option,
1586 WS_HEAP *heap, void *value, ULONG size )
1588 HRESULT hr;
1589 if (!heap) heap = msg->heap;
1590 if (!msg->reader && (hr = WsCreateReader( NULL, 0, &msg->reader, NULL )) != S_OK) return hr;
1591 if ((hr = WsSetInputToBuffer( msg->reader, msg->buf, NULL, 0, NULL )) != S_OK) return hr;
1593 if ((hr = find_header( msg->reader, desc->elementLocalName, desc->elementNs )) != S_OK) return hr;
1594 return read_header( msg->reader, desc->elementLocalName, desc->elementNs, desc->type, desc->typeDescription,
1595 option, heap, value, size );
1598 /**************************************************************************
1599 * WsGetCustomHeader [webservices.@]
1601 HRESULT WINAPI WsGetCustomHeader( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *desc,
1602 WS_REPEATING_HEADER_OPTION repeat_option, ULONG index, WS_READ_OPTION option,
1603 WS_HEAP *heap, void *value, ULONG size, ULONG *attrs, WS_ERROR *error )
1605 struct msg *msg = (struct msg *)handle;
1606 HRESULT hr;
1608 TRACE( "%p %p %08x %u %08x %p %p %u %p %p\n", handle, desc, repeat_option, index, option, heap, value,
1609 size, attrs, error );
1610 if (error) FIXME( "ignoring error parameter\n" );
1612 if (!msg || !desc || repeat_option < WS_REPEATING_HEADER || repeat_option > WS_SINGLETON_HEADER ||
1613 (repeat_option == WS_SINGLETON_HEADER && index)) return E_INVALIDARG;
1615 if (repeat_option == WS_REPEATING_HEADER)
1617 FIXME( "repeating header not supported\n" );
1618 return E_NOTIMPL;
1620 if (attrs)
1622 FIXME( "attributes not supported\n" );
1623 return E_NOTIMPL;
1626 EnterCriticalSection( &msg->cs );
1628 if (msg->magic != MSG_MAGIC)
1630 LeaveCriticalSection( &msg->cs );
1631 return E_INVALIDARG;
1634 if (msg->state < WS_MESSAGE_STATE_INITIALIZED)
1636 LeaveCriticalSection( &msg->cs );
1637 return WS_E_INVALID_OPERATION;
1640 hr = get_custom_header( msg, desc, option, heap, value, size );
1642 LeaveCriticalSection( &msg->cs );
1643 return hr;
1646 /**************************************************************************
1647 * WsRemoveCustomHeader [webservices.@]
1649 HRESULT WINAPI WsRemoveCustomHeader( WS_MESSAGE *handle, const WS_XML_STRING *name, const WS_XML_STRING *ns,
1650 WS_ERROR *error )
1652 struct msg *msg = (struct msg *)handle;
1653 BOOL removed = FALSE;
1654 HRESULT hr = S_OK;
1655 ULONG i;
1657 TRACE( "%p %s %s %p\n", handle, debugstr_xmlstr(name), debugstr_xmlstr(ns), error );
1658 if (error) FIXME( "ignoring error parameter\n" );
1660 if (!msg || !name || !ns) return E_INVALIDARG;
1662 EnterCriticalSection( &msg->cs );
1664 if (msg->magic != MSG_MAGIC)
1666 LeaveCriticalSection( &msg->cs );
1667 return E_INVALIDARG;
1670 if (msg->state < WS_MESSAGE_STATE_INITIALIZED)
1672 LeaveCriticalSection( &msg->cs );
1673 return WS_E_INVALID_OPERATION;
1676 for (i = 0; i < msg->header_count; i++)
1678 if (msg->header[i]->type || msg->header[i]->mapped) continue;
1679 if (WsXmlStringEquals( name, &msg->header[i]->name, NULL ) == S_OK &&
1680 WsXmlStringEquals( ns, &msg->header[i]->ns, NULL ) == S_OK)
1682 remove_header( msg, i );
1683 removed = TRUE;
1684 i--;
1688 if (removed) hr = write_envelope( msg );
1690 LeaveCriticalSection( &msg->cs );
1691 return hr;
1694 static WCHAR *build_http_header( const WCHAR *name, const WCHAR *value, ULONG *ret_len )
1696 int len_name = strlenW( name ), len_value = strlenW( value );
1697 WCHAR *ret = heap_alloc( (len_name + len_value) * sizeof(WCHAR) );
1699 if (!ret) return NULL;
1700 memcpy( ret, name, len_name * sizeof(WCHAR) );
1701 memcpy( ret + len_name, value, len_value * sizeof(WCHAR) );
1702 *ret_len = len_name + len_value;
1703 return ret;
1706 static inline HRESULT insert_http_header( HINTERNET req, const WCHAR *header, ULONG len, ULONG flags )
1708 if (WinHttpAddRequestHeaders( req, header, len, flags )) return S_OK;
1709 return HRESULT_FROM_WIN32( GetLastError() );
1712 HRESULT message_insert_http_headers( WS_MESSAGE *handle, HINTERNET req )
1714 static const WCHAR contenttypeW[] =
1715 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',0};
1716 static const WCHAR soapxmlW[] =
1717 {'a','p','p','l','i','c','a','t','i','o','n','/','s','o','a','p','+','x','m','l',0};
1718 static const WCHAR textxmlW[] =
1719 {'t','e','x','t','/','x','m','l',0};
1720 static const WCHAR charsetW[] =
1721 {'c','h','a','r','s','e','t','=','u','t','f','-','8',0};
1722 struct msg *msg = (struct msg *)handle;
1723 HRESULT hr = E_OUTOFMEMORY;
1724 WCHAR *header = NULL, *buf;
1725 ULONG len;
1727 EnterCriticalSection( &msg->cs );
1729 if (msg->magic != MSG_MAGIC)
1731 LeaveCriticalSection( &msg->cs );
1732 return E_INVALIDARG;
1735 switch (msg->version_env)
1737 case WS_ENVELOPE_VERSION_SOAP_1_1:
1738 header = build_http_header( contenttypeW, textxmlW, &len );
1739 break;
1741 case WS_ENVELOPE_VERSION_SOAP_1_2:
1742 header = build_http_header( contenttypeW, soapxmlW, &len );
1743 break;
1745 default:
1746 FIXME( "unhandled envelope version %u\n", msg->version_env );
1747 hr = E_NOTIMPL;
1749 if (!header) goto done;
1751 if ((hr = insert_http_header( req, header, len, WINHTTP_ADDREQ_FLAG_ADD )) != S_OK) goto done;
1752 heap_free( header );
1754 hr = E_OUTOFMEMORY;
1755 if (!(header = build_http_header( contenttypeW, charsetW, &len ))) goto done;
1756 if ((hr = insert_http_header( req, header, len, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON )) != S_OK)
1757 goto done;
1758 heap_free( header );
1759 header = NULL;
1761 switch (msg->version_env)
1763 case WS_ENVELOPE_VERSION_SOAP_1_1:
1765 static const WCHAR soapactionW[] = {'S','O','A','P','A','c','t','i','o','n',':',' ',0};
1767 if (!(len = MultiByteToWideChar( CP_UTF8, 0, (char *)msg->action->bytes, msg->action->length, NULL, 0 )))
1768 break;
1770 hr = E_OUTOFMEMORY;
1771 if (!(buf = heap_alloc( (len + 3) * sizeof(WCHAR) ))) goto done;
1772 buf[0] = '"';
1773 MultiByteToWideChar( CP_UTF8, 0, (char *)msg->action->bytes, msg->action->length, buf + 1, len );
1774 buf[len + 1] = '"';
1775 buf[len + 2] = 0;
1777 header = build_http_header( soapactionW, buf, &len );
1778 heap_free( buf );
1779 if (!header) goto done;
1781 hr = insert_http_header( req, header, len, WINHTTP_ADDREQ_FLAG_ADD );
1782 break;
1784 case WS_ENVELOPE_VERSION_SOAP_1_2:
1786 static const WCHAR actionW[] = {'a','c','t','i','o','n','=','"'};
1787 ULONG len_action = sizeof(actionW)/sizeof(actionW[0]);
1789 if (!(len = MultiByteToWideChar( CP_UTF8, 0, (char *)msg->action->bytes, msg->action->length, NULL, 0 )))
1790 break;
1792 hr = E_OUTOFMEMORY;
1793 if (!(buf = heap_alloc( (len + len_action + 2) * sizeof(WCHAR) ))) goto done;
1794 memcpy( buf, actionW, len_action * sizeof(WCHAR) );
1795 MultiByteToWideChar( CP_UTF8, 0, (char *)msg->action->bytes, msg->action->length, buf + len_action, len );
1796 len += len_action;
1797 buf[len++] = '"';
1798 buf[len] = 0;
1800 header = build_http_header( contenttypeW, buf, &len );
1801 heap_free( buf );
1802 if (!header) goto done;
1804 hr = insert_http_header( req, header, len, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON );
1805 break;
1807 default:
1808 FIXME( "unhandled envelope version %u\n", msg->version_env );
1809 hr = E_NOTIMPL;
1812 done:
1813 heap_free( header );
1814 LeaveCriticalSection( &msg->cs );
1815 return hr;
1818 void message_set_send_context( WS_MESSAGE *handle, const WS_PROXY_MESSAGE_CALLBACK_CONTEXT *ctx )
1820 struct msg *msg = (struct msg *)handle;
1822 EnterCriticalSection( &msg->cs );
1824 if (msg->magic != MSG_MAGIC)
1826 LeaveCriticalSection( &msg->cs );
1827 return;
1830 msg->ctx_send.callback = ctx->callback;
1831 msg->ctx_send.state = ctx->state;
1833 LeaveCriticalSection( &msg->cs );
1836 void message_set_receive_context( WS_MESSAGE *handle, const WS_PROXY_MESSAGE_CALLBACK_CONTEXT *ctx )
1838 struct msg *msg = (struct msg *)handle;
1840 EnterCriticalSection( &msg->cs );
1842 if (msg->magic != MSG_MAGIC)
1844 LeaveCriticalSection( &msg->cs );
1845 return;
1848 msg->ctx_receive.callback = ctx->callback;
1849 msg->ctx_receive.state = ctx->state;
1851 LeaveCriticalSection( &msg->cs );
1854 void message_do_send_callback( WS_MESSAGE *handle )
1856 struct msg *msg = (struct msg *)handle;
1858 EnterCriticalSection( &msg->cs );
1860 if (msg->magic != MSG_MAGIC)
1862 LeaveCriticalSection( &msg->cs );
1863 return;
1866 if (msg->ctx_send.callback)
1868 HRESULT hr;
1869 TRACE( "executing callback %p\n", msg->ctx_send.callback );
1870 hr = msg->ctx_send.callback( handle, msg->heap, msg->ctx_send.state, NULL );
1871 TRACE( "callback %p returned %08x\n", msg->ctx_send.callback, hr );
1874 LeaveCriticalSection( &msg->cs );
1877 void message_do_receive_callback( WS_MESSAGE *handle )
1879 struct msg *msg = (struct msg *)handle;
1881 EnterCriticalSection( &msg->cs );
1883 if (msg->magic != MSG_MAGIC)
1885 LeaveCriticalSection( &msg->cs );
1886 return;
1889 if (msg->ctx_receive.callback)
1891 HRESULT hr;
1892 TRACE( "executing callback %p\n", msg->ctx_receive.callback );
1893 hr = msg->ctx_receive.callback( handle, msg->heap, msg->ctx_receive.state, NULL );
1894 TRACE( "callback %p returned %08x\n", msg->ctx_receive.callback, hr );
1897 LeaveCriticalSection( &msg->cs );
1900 HRESULT message_set_action( WS_MESSAGE *handle, const WS_XML_STRING *action )
1902 struct msg *msg = (struct msg *)handle;
1903 HRESULT hr = S_OK;
1905 EnterCriticalSection( &msg->cs );
1907 if (msg->magic != MSG_MAGIC)
1909 LeaveCriticalSection( &msg->cs );
1910 return E_INVALIDARG;
1913 if (!action || !action->length)
1915 free_xml_string( msg->action );
1916 msg->action = NULL;
1918 else
1920 WS_XML_STRING *str;
1921 if (!(str = dup_xml_string( action, FALSE ))) hr = E_OUTOFMEMORY;
1922 else
1924 free_xml_string( msg->action );
1925 msg->action = str;
1929 LeaveCriticalSection( &msg->cs );
1930 return hr;
1933 HRESULT message_get_id( WS_MESSAGE *handle, GUID *id )
1935 struct msg *msg = (struct msg *)handle;
1936 HRESULT hr = S_OK;
1938 EnterCriticalSection( &msg->cs );
1940 if (msg->magic != MSG_MAGIC)
1942 LeaveCriticalSection( &msg->cs );
1943 return E_INVALIDARG;
1946 *id = msg->id_req;
1948 LeaveCriticalSection( &msg->cs );
1949 return hr;
1952 HRESULT message_set_request_id( WS_MESSAGE *handle, const GUID *id )
1954 struct msg *msg = (struct msg *)handle;
1955 HRESULT hr = S_OK;
1957 EnterCriticalSection( &msg->cs );
1959 if (msg->magic != MSG_MAGIC)
1961 LeaveCriticalSection( &msg->cs );
1962 return E_INVALIDARG;
1965 msg->id_req = *id;
1967 LeaveCriticalSection( &msg->cs );
1968 return hr;