ntdll: Validate blocks in the heap pending free request list.
[wine.git] / dlls / webservices / tests / proxy.c
blob59d571fb5c3a30ccc95596fe5fe5914b041eb46c
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 <stdio.h>
20 #include "windows.h"
21 #include "winsock2.h"
22 #include "webservices.h"
23 #include "wine/test.h"
25 static inline void set_field_desc( WS_FIELD_DESCRIPTION *desc, WS_FIELD_MAPPING mapping,
26 WS_XML_STRING *localname, WS_XML_STRING *ns, WS_TYPE type,
27 void *type_desc, ULONG offset, ULONG options, ULONG count_offset,
28 WS_XML_STRING *item_localname, WS_XML_STRING *item_ns )
30 memset( desc, 0, sizeof(*desc) );
31 desc->mapping = mapping;
32 desc->localName = localname;
33 desc->ns = ns;
34 desc->type = type;
35 desc->typeDescription = type_desc;
36 desc->offset = offset;
37 desc->options = options;
38 desc->countOffset = count_offset;
39 desc->itemLocalName = item_localname;
40 desc->itemNs = item_ns;
43 static inline void set_struct_desc( WS_STRUCT_DESCRIPTION *desc, ULONG size, ULONG alignment,
44 WS_FIELD_DESCRIPTION **fields, ULONG count, WS_XML_STRING *localname,
45 WS_XML_STRING *ns, ULONG options )
47 memset( desc, 0, sizeof(*desc) );
48 desc->size = size;
49 desc->alignment = alignment;
50 desc->fields = fields;
51 desc->fieldCount = count;
52 desc->typeLocalName = localname;
53 desc->typeNs = ns;
54 desc->structOptions = options;
57 static inline void set_elem_desc( WS_ELEMENT_DESCRIPTION *desc, WS_XML_STRING *localname, WS_XML_STRING *ns,
58 WS_TYPE type, void *type_desc )
60 desc->elementLocalName = localname;
61 desc->elementNs = ns;
62 desc->type = type;
63 desc->typeDescription = type_desc;
66 static inline void set_msg_desc( WS_MESSAGE_DESCRIPTION *desc, WS_XML_STRING *action,
67 WS_ELEMENT_DESCRIPTION *elem_desc )
69 desc->action = action;
70 desc->bodyElementDescription = elem_desc;
73 static inline void set_param_desc( WS_PARAMETER_DESCRIPTION *desc, WS_PARAMETER_TYPE type,
74 USHORT input_index, USHORT output_index )
76 desc->parameterType = type;
77 desc->inputMessageIndex = input_index;
78 desc->outputMessageIndex = output_index;
81 static inline void set_op_desc( WS_OPERATION_DESCRIPTION *desc, WS_MESSAGE_DESCRIPTION *input_msg,
82 WS_MESSAGE_DESCRIPTION *output_msg, ULONG count,
83 WS_PARAMETER_DESCRIPTION *param_desc )
85 memset( desc, 0, sizeof(*desc) );
86 desc->versionInfo = 1;
87 desc->inputMessageDescription = input_msg;
88 desc->outputMessageDescription = output_msg;
89 desc->parameterCount = count;
90 desc->parameterDescription = param_desc;
93 static void test_WsCreateServiceProxy(void)
95 HRESULT hr;
96 WS_SERVICE_PROXY *proxy;
97 WS_SERVICE_PROXY_STATE state;
98 ULONG value;
100 hr = WsCreateServiceProxy( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, NULL, NULL,
101 0, NULL, 0, NULL, NULL );
102 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
104 proxy = NULL;
105 hr = WsCreateServiceProxy( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, NULL, NULL,
106 0, NULL, 0, &proxy, NULL );
107 ok( hr == S_OK, "got %#lx\n", hr );
108 ok( proxy != NULL, "proxy not set\n" );
110 /* write-only property */
111 value = 0xdeadbeef;
112 hr = WsGetServiceProxyProperty( proxy, WS_PROXY_PROPERTY_CALL_TIMEOUT, &value, sizeof(value), NULL );
113 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
115 state = 0xdeadbeef;
116 hr = WsGetServiceProxyProperty( proxy, WS_PROXY_PROPERTY_STATE, &state, sizeof(state), NULL );
117 ok( hr == S_OK, "got %#lx\n", hr );
118 ok( state == WS_SERVICE_PROXY_STATE_CREATED, "got %u\n", state );
120 WsFreeServiceProxy( proxy );
123 static void test_WsCreateServiceProxyFromTemplate(void)
125 HRESULT hr;
126 WS_SERVICE_PROXY *proxy;
127 WS_HTTP_POLICY_DESCRIPTION policy;
129 hr = WsCreateServiceProxyFromTemplate( WS_CHANNEL_TYPE_REQUEST, NULL, 0, WS_HTTP_BINDING_TEMPLATE_TYPE,
130 NULL, 0, NULL, 0, NULL, NULL );
131 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
133 hr = WsCreateServiceProxyFromTemplate( WS_CHANNEL_TYPE_REQUEST, NULL, 0, WS_HTTP_BINDING_TEMPLATE_TYPE,
134 NULL, 0, NULL, 0, &proxy, NULL );
135 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
137 memset( &policy, 0, sizeof(policy) );
138 proxy = NULL;
139 hr = WsCreateServiceProxyFromTemplate( WS_CHANNEL_TYPE_REQUEST, NULL, 0, WS_HTTP_BINDING_TEMPLATE_TYPE,
140 NULL, 0, &policy, sizeof(policy), &proxy, NULL );
141 ok( hr == S_OK, "got %#lx\n", hr );
142 ok( proxy != NULL, "proxy not set\n" );
144 WsFreeServiceProxy( proxy );
147 static void test_WsOpenServiceProxy(void)
149 HRESULT hr;
150 WS_SERVICE_PROXY *proxy;
151 WS_SERVICE_PROXY_STATE state;
152 WS_HTTP_POLICY_DESCRIPTION policy;
153 WS_ENDPOINT_ADDRESS addr;
155 memset( &policy, 0, sizeof(policy) );
156 hr = WsCreateServiceProxyFromTemplate( WS_CHANNEL_TYPE_REQUEST, NULL, 0, WS_HTTP_BINDING_TEMPLATE_TYPE,
157 NULL, 0, &policy, sizeof(policy), &proxy, NULL );
158 ok( hr == S_OK, "got %#lx\n", hr );
160 state = 0xdeadbeef;
161 hr = WsGetServiceProxyProperty( proxy, WS_PROXY_PROPERTY_STATE, &state, sizeof(state), NULL );
162 ok( hr == S_OK, "got %#lx\n", hr );
163 ok( state == WS_SERVICE_PROXY_STATE_CREATED, "got %u\n", state );
165 memset( &addr, 0, sizeof(addr) );
166 addr.url.length = ARRAY_SIZE( L"http://localhost/" ) - 1;
167 addr.url.chars = (WCHAR *)L"http://localhost/";
168 hr = WsOpenServiceProxy( proxy, &addr, NULL, NULL );
169 ok( hr == S_OK, "got %#lx\n", hr );
171 state = 0xdeadbeef;
172 hr = WsGetServiceProxyProperty( proxy, WS_PROXY_PROPERTY_STATE, &state, sizeof(state), NULL );
173 ok( hr == S_OK, "got %#lx\n", hr );
174 ok( state == WS_SERVICE_PROXY_STATE_OPEN, "got %u\n", state );
176 hr = WsCloseServiceProxy( proxy , NULL, NULL );
177 ok( hr == S_OK, "got %#lx\n", hr );
179 state = 0xdeadbeef;
180 hr = WsGetServiceProxyProperty( proxy, WS_PROXY_PROPERTY_STATE, &state, sizeof(state), NULL );
181 ok( hr == S_OK, "got %#lx\n", hr );
182 ok( state == WS_SERVICE_PROXY_STATE_CLOSED, "got %u\n", state );
184 WsFreeServiceProxy( proxy );
187 static void test_WsResetServiceProxy(void)
189 HRESULT hr;
190 WS_SERVICE_PROXY *proxy;
191 WS_ENDPOINT_ADDRESS addr;
192 WS_SERVICE_PROXY_STATE state;
194 hr = WsCreateServiceProxy( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, NULL, NULL,
195 0, NULL, 0, &proxy, NULL );
196 ok( hr == S_OK, "got %#lx\n", hr );
198 hr = WsResetServiceProxy( proxy, NULL );
199 ok( hr == S_OK, "got %#lx\n", hr );
201 state = 0xdeadbeef;
202 hr = WsGetServiceProxyProperty( proxy, WS_PROXY_PROPERTY_STATE, &state, sizeof(state), NULL );
203 ok( hr == S_OK, "got %#lx\n", hr );
204 ok( state == WS_SERVICE_PROXY_STATE_CREATED, "got %u\n", state );
206 memset( &addr, 0, sizeof(addr) );
207 addr.url.length = ARRAY_SIZE( L"http://localhost/" ) - 1;
208 addr.url.chars = (WCHAR *)L"http://localhost/";
209 hr = WsOpenServiceProxy( proxy, &addr, NULL, NULL );
210 ok( hr == S_OK, "got %#lx\n", hr );
212 hr = WsResetServiceProxy( proxy, NULL );
213 ok( hr == WS_E_INVALID_OPERATION, "got %#lx\n", hr );
215 hr = WsCloseServiceProxy( proxy , NULL, NULL );
216 ok( hr == S_OK, "got %#lx\n", hr );
218 hr = WsResetServiceProxy( proxy, NULL );
219 ok( hr == S_OK, "got %#lx\n", hr );
221 state = 0xdeadbeef;
222 hr = WsGetServiceProxyProperty( proxy, WS_PROXY_PROPERTY_STATE, &state, sizeof(state), NULL );
223 ok( hr == S_OK, "got %#lx\n", hr );
224 ok( state == WS_SERVICE_PROXY_STATE_CREATED, "got %u\n", state );
226 WsFreeServiceProxy( proxy );
229 static HRESULT create_channel( int port, WS_CHANNEL **ret )
231 WS_CHANNEL_PROPERTY prop[2];
232 WS_ENVELOPE_VERSION env_version = WS_ENVELOPE_VERSION_SOAP_1_1;
233 WS_ADDRESSING_VERSION addr_version = WS_ADDRESSING_VERSION_TRANSPORT;
234 WS_CHANNEL *channel;
235 WS_ENDPOINT_ADDRESS addr;
236 WCHAR buf[64];
237 HRESULT hr;
239 prop[0].id = WS_CHANNEL_PROPERTY_ENVELOPE_VERSION;
240 prop[0].value = &env_version;
241 prop[0].valueSize = sizeof(env_version);
243 prop[1].id = WS_CHANNEL_PROPERTY_ADDRESSING_VERSION;
244 prop[1].value = &addr_version;
245 prop[1].valueSize = sizeof(addr_version);
247 *ret = NULL;
248 hr = WsCreateChannel( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, prop, 2, NULL, &channel, NULL );
249 if (hr != S_OK) return hr;
251 memset( &addr, 0, sizeof(addr) );
252 addr.url.length = wsprintfW( buf, L"http://127.0.0.1:%u", port );
253 addr.url.chars = buf;
254 hr = WsOpenChannel( channel, &addr, NULL, NULL );
255 if (hr == S_OK) *ret = channel;
256 else WsFreeChannel( channel );
257 return hr;
260 static const char req_test1[] =
261 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
262 "<req_test1 xmlns=\"ns\">-1</req_test1>"
263 "</s:Body></s:Envelope>";
265 static const char resp_test1[] =
266 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
267 "<resp_test1 xmlns=\"ns\">-2</resp_test1>"
268 "</s:Body></s:Envelope>";
270 static void test_WsSendMessage( int port, WS_XML_STRING *action )
272 WS_XML_STRING req = {9, (BYTE *)"req_test1"}, ns = {2, (BYTE *)"ns"};
273 WS_CHANNEL *channel;
274 WS_MESSAGE *msg;
275 WS_ELEMENT_DESCRIPTION body;
276 WS_MESSAGE_DESCRIPTION desc;
277 INT32 val = -1;
278 HRESULT hr;
280 hr = create_channel( port, &channel );
281 ok( hr == S_OK, "got %#lx\n", hr );
283 hr = WsCreateMessageForChannel( channel, NULL, 0, &msg, NULL );
284 ok( hr == S_OK, "got %#lx\n", hr );
286 set_elem_desc( &body, &req, &ns, WS_INT32_TYPE, NULL );
287 set_msg_desc( &desc, action, &body );
288 hr = WsSendMessage( NULL, msg, &desc, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL );
289 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
291 hr = WsSendMessage( channel, NULL, &desc, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL );
292 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
294 hr = WsSendMessage( channel, msg, NULL, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL );
295 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
297 hr = WsSendMessage( channel, msg, &desc, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL );
298 ok( hr == S_OK, "got %#lx\n", hr );
300 hr = WsCloseChannel( channel, NULL, NULL );
301 ok( hr == S_OK, "got %#lx\n", hr );
303 WsFreeChannel( channel );
304 WsFreeMessage( msg );
307 static void test_WsReceiveMessage( int port )
309 WS_XML_STRING req = {9, (BYTE *)"req_test1"}, resp = {10, (BYTE *)"resp_test1"}, ns = {2, (BYTE *)"ns"};
310 WS_CHANNEL *channel;
311 WS_MESSAGE *msg;
312 WS_ELEMENT_DESCRIPTION body;
313 WS_MESSAGE_DESCRIPTION desc_req, desc_resp;
314 const WS_MESSAGE_DESCRIPTION *desc[1];
315 INT32 val = -1;
316 HRESULT hr;
318 hr = create_channel( port, &channel );
319 ok( hr == S_OK, "got %#lx\n", hr );
321 hr = WsCreateMessageForChannel( channel, NULL, 0, &msg, NULL );
322 ok( hr == S_OK, "got %#lx\n", hr );
324 set_elem_desc( &body, &req, &ns, WS_INT32_TYPE, NULL );
325 set_msg_desc( &desc_req, &req, &body );
326 hr = WsSendMessage( channel, msg, &desc_req, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL );
327 ok( hr == S_OK, "got %#lx\n", hr );
328 WsFreeMessage( msg );
330 hr = WsCreateMessageForChannel( channel, NULL, 0, &msg, NULL );
331 ok( hr == S_OK, "got %#lx\n", hr );
333 set_elem_desc( &body, &resp, &ns, WS_INT32_TYPE, NULL );
334 set_msg_desc( &desc_resp, &resp, &body );
335 desc[0] = &desc_resp;
336 hr = WsReceiveMessage( NULL, msg, desc, 1, WS_RECEIVE_REQUIRED_MESSAGE, WS_READ_REQUIRED_VALUE,
337 NULL, &val, sizeof(val), NULL, NULL, NULL );
338 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
340 hr = WsReceiveMessage( channel, NULL, desc, 1, WS_RECEIVE_REQUIRED_MESSAGE, WS_READ_REQUIRED_VALUE,
341 NULL, &val, sizeof(val), NULL, NULL, NULL );
342 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
344 hr = WsReceiveMessage( channel, msg, NULL, 1, WS_RECEIVE_REQUIRED_MESSAGE, WS_READ_REQUIRED_VALUE,
345 NULL, &val, sizeof(val), NULL, NULL, NULL );
346 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
348 hr = WsReceiveMessage( channel, msg, desc, 1, WS_RECEIVE_REQUIRED_MESSAGE, WS_READ_REQUIRED_VALUE,
349 NULL, &val, sizeof(val), NULL, NULL, NULL );
350 ok( hr == S_OK, "got %#lx\n", hr );
351 ok( val == -2, "got %d\n", val );
353 hr = WsCloseChannel( channel, NULL, NULL );
354 ok( hr == S_OK, "got %#lx\n", hr );
356 WsFreeChannel( channel );
357 WsFreeMessage( msg );
360 static WS_HTTP_HEADER_MAPPING mapped_request_header =
362 {19, (BYTE *)"MappedRequestHeader"}
365 static WS_HTTP_HEADER_MAPPING *request_header_mappings[] =
367 &mapped_request_header
370 static WS_HTTP_HEADER_MAPPING mapped_response_header =
372 {20, (BYTE *)"MappedResponseHeader"}
375 static WS_HTTP_HEADER_MAPPING *response_header_mappings[] =
377 &mapped_response_header
380 static HRESULT create_proxy( int port, WS_SERVICE_PROXY **ret )
382 WS_ENVELOPE_VERSION env_version;
383 WS_ADDRESSING_VERSION addr_version;
384 WS_HTTP_MESSAGE_MAPPING mapping;
385 WS_CHANNEL_PROPERTY prop[3];
386 WS_ENDPOINT_ADDRESS addr;
387 WS_SERVICE_PROXY *proxy;
388 WCHAR url[64];
389 HRESULT hr;
391 env_version = WS_ENVELOPE_VERSION_SOAP_1_1;
392 prop[0].id = WS_CHANNEL_PROPERTY_ENVELOPE_VERSION;
393 prop[0].value = &env_version;
394 prop[0].valueSize = sizeof(env_version);
396 addr_version = WS_ADDRESSING_VERSION_TRANSPORT;
397 prop[1].id = WS_CHANNEL_PROPERTY_ADDRESSING_VERSION;
398 prop[1].value = &addr_version;
399 prop[1].valueSize = sizeof(addr_version);
401 mapping.requestMappingOptions = 0;
402 mapping.responseMappingOptions = 0;
403 mapping.requestHeaderMappings = request_header_mappings;
404 mapping.requestHeaderMappingCount = ARRAY_SIZE(request_header_mappings);
405 mapping.responseHeaderMappings = response_header_mappings;
406 mapping.responseHeaderMappingCount = ARRAY_SIZE(response_header_mappings);
408 prop[2].id = WS_CHANNEL_PROPERTY_HTTP_MESSAGE_MAPPING;
409 prop[2].value = &mapping;
410 prop[2].valueSize = sizeof(mapping);
412 *ret = NULL;
413 hr = WsCreateServiceProxy( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, NULL, NULL,
414 0, prop, ARRAY_SIZE( prop ), &proxy, NULL );
415 if (hr != S_OK) return hr;
417 memset( &addr, 0, sizeof(addr) );
418 addr.url.length = wsprintfW( url, L"http://127.0.0.1:%u", port );
419 addr.url.chars = url;
420 hr = WsOpenServiceProxy( proxy, &addr, NULL, NULL );
421 if (hr == S_OK) *ret = proxy;
422 else WsFreeServiceProxy( proxy );
423 return hr;
426 static HRESULT set_output( WS_XML_WRITER *writer )
428 WS_XML_WRITER_TEXT_ENCODING text = {{ WS_XML_WRITER_ENCODING_TYPE_TEXT }, WS_CHARSET_UTF8 };
429 WS_XML_WRITER_BUFFER_OUTPUT buf = {{ WS_XML_WRITER_OUTPUT_TYPE_BUFFER }};
430 return WsSetOutput( writer, &text.encoding, &buf.output, NULL, 0, NULL );
433 static void check_output_headers( WS_MESSAGE *msg )
435 WS_XML_WRITER *writer;
436 WS_XML_BUFFER *buf;
437 WS_BYTES bytes;
438 HRESULT hr;
440 hr = WsCreateWriter( NULL, 0, &writer, NULL );
441 ok( hr == S_OK, "got %#lx\n", hr );
443 hr = set_output( writer );
444 ok( hr == S_OK, "got %#lx\n", hr );
446 hr = WsGetMessageProperty( msg, WS_MESSAGE_PROPERTY_HEADER_BUFFER, &buf, sizeof(buf), NULL );
447 ok( hr == S_OK, "got %#lx\n", hr );
449 hr = WsWriteXmlBuffer( writer, buf, NULL );
450 ok( hr == S_OK, "got %#lx\n", hr );
452 memset( &bytes, 0, sizeof(bytes) );
453 hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, sizeof(bytes), NULL );
454 ok( hr == S_OK, "got %#lx\n", hr );
455 WsFreeWriter( writer );
458 static const char req_test2[] =
459 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
460 "<req_test2 xmlns=\"ns\"><val>1</val><str>test</str><str>test2</str></req_test2>"
461 "</s:Body></s:Envelope>";
463 static const char resp_test2[] =
464 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
465 "<resp_test2 xmlns=\"ns\"><str>test</str><val>1</val><val>2</val></resp_test2>"
466 "</s:Body></s:Envelope>";
468 static HRESULT CALLBACK send_callback( WS_MESSAGE *msg, WS_HEAP *heap, void *state, WS_ERROR *error )
470 static const WS_XML_STRING header = {19, (BYTE *)"MappedRequestHeader"}, value = {5, (BYTE *)"value"};
471 HRESULT hr;
473 hr = WsAddMappedHeader( msg, &header, WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &value, sizeof(value), NULL );
474 ok( hr == S_OK, "got %#lx\n", hr );
475 check_output_headers( msg );
476 return S_OK;
479 static HRESULT CALLBACK recv_callback( WS_MESSAGE *msg, WS_HEAP *heap, void *state, WS_ERROR *error )
481 static const WS_XML_STRING header = {20, (BYTE *)"MappedResponseHeader"};
482 WCHAR *str;
483 HRESULT hr;
485 check_output_headers( msg );
486 hr = WsGetMappedHeader( msg, &header, WS_SINGLETON_HEADER, 0, WS_WSZ_TYPE, WS_READ_OPTIONAL_POINTER, heap,
487 &str, sizeof(str), NULL );
488 ok( hr == S_OK, "got %#lx\n", hr );
489 ok( !wcscmp(str, L"value"), "wrong value %s\n", wine_dbgstr_w(str) );
490 return S_OK;
493 static void test_WsCall( int port )
495 WS_XML_STRING str = {3, (BYTE *)"str"};
496 WS_XML_STRING req = {3, (BYTE *)"req"};
497 WS_XML_STRING resp = {4, (BYTE *)"resp"};
498 WS_XML_STRING req_elem = {9, (BYTE *)"req_test2"};
499 WS_XML_STRING resp_elem = {10, (BYTE *)"resp_test2"};
500 WS_XML_STRING req_action = {9, (BYTE *)"req_test2"};
501 WS_XML_STRING resp_action = {10, (BYTE *)"resp_test2"};
502 WS_XML_STRING val = {3, (BYTE *)"val"};
503 WS_XML_STRING ns = {2, (BYTE *)"ns"};
504 HRESULT hr;
505 WS_SERVICE_PROXY *proxy;
506 WS_PROXY_MESSAGE_CALLBACK_CONTEXT ctx_send;
507 WS_PROXY_MESSAGE_CALLBACK_CONTEXT ctx_recv;
508 WS_CALL_PROPERTY prop[2];
509 WS_OPERATION_DESCRIPTION op;
510 WS_MESSAGE_DESCRIPTION input_msg, output_msg;
511 WS_ELEMENT_DESCRIPTION input_elem, output_elem;
512 WS_STRUCT_DESCRIPTION input_struct, output_struct;
513 WS_FIELD_DESCRIPTION f, f2, f3, f4, *fields[2], *fields2[2];
514 WS_PARAMETER_DESCRIPTION param[6];
515 const void *args[6];
516 WS_HEAP *heap;
517 INT32 **val_ptr;
518 WCHAR **str_ptr;
519 ULONG *count_ptr;
520 const WCHAR *str_array[2];
521 struct input
523 INT32 val;
524 ULONG count;
525 const WCHAR **str;
526 } in;
527 struct output
529 WCHAR *str;
530 ULONG count;
531 INT32 *val;
532 } out;
534 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
535 ok( hr == S_OK, "got %#lx\n", hr );
537 hr = WsCall( NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL );
538 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
540 hr = create_proxy( port, &proxy );
541 ok( hr == S_OK, "got %#lx\n", hr );
543 hr = WsCall( proxy, NULL, NULL, NULL, NULL, 0, NULL, NULL );
544 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
546 set_field_desc( &f, WS_ELEMENT_FIELD_MAPPING, &val, &ns, WS_INT32_TYPE, NULL, 0, 0, 0, NULL, NULL );
547 set_field_desc( &f4, WS_REPEATING_ELEMENT_FIELD_MAPPING, NULL, NULL, WS_WSZ_TYPE, NULL,
548 FIELD_OFFSET(struct input, str), 0, FIELD_OFFSET(struct input, count), &str, &ns );
549 fields[0] = &f;
550 fields[1] = &f4;
552 set_struct_desc( &input_struct, sizeof(struct input), TYPE_ALIGNMENT(struct input), fields, 2, &req, &ns, 0 );
553 set_elem_desc( &input_elem, &req_elem, &ns, WS_STRUCT_TYPE, &input_struct );
554 set_msg_desc( &input_msg, &req_action, &input_elem );
556 set_field_desc( &f2, WS_ELEMENT_FIELD_MAPPING, &str, &ns, WS_WSZ_TYPE, NULL, FIELD_OFFSET(struct output, str),
557 0, 0, NULL, NULL );
558 set_field_desc( &f3, WS_REPEATING_ELEMENT_FIELD_MAPPING, NULL, NULL, WS_INT32_TYPE, NULL,
559 FIELD_OFFSET(struct output, val), 0, FIELD_OFFSET(struct output, count), &val, &ns );
560 fields2[0] = &f2;
561 fields2[1] = &f3;
563 set_struct_desc( &output_struct, sizeof(struct output), TYPE_ALIGNMENT(struct output), fields2, 2, &resp, &ns, 0 );
564 set_elem_desc( &output_elem, &resp_elem, &ns, WS_STRUCT_TYPE, &output_struct );
565 set_msg_desc( &output_msg, &resp_action, &output_elem );
567 set_param_desc( &param[0], WS_PARAMETER_TYPE_NORMAL, 0, 0xffff );
568 set_param_desc( &param[1], WS_PARAMETER_TYPE_ARRAY, 1, 0xffff );
569 set_param_desc( &param[2], WS_PARAMETER_TYPE_ARRAY_COUNT, 1, 0xffff );
570 set_param_desc( &param[3], WS_PARAMETER_TYPE_NORMAL, 0xffff, 0 );
571 set_param_desc( &param[4], WS_PARAMETER_TYPE_ARRAY, 0xffff, 1 );
572 set_param_desc( &param[5], WS_PARAMETER_TYPE_ARRAY_COUNT, 0xffff, 1 );
574 set_op_desc( &op, &input_msg, &output_msg, 6, param );
575 hr = WsCall( proxy, &op, NULL, NULL, NULL, 0, NULL, NULL );
576 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
578 in.val = 1;
579 str_array[0] = L"test";
580 str_array[1] = L"test2";
581 in.str = str_array;
582 in.count = 2;
584 args[0] = &in.val;
585 args[1] = &in.str;
586 args[2] = &in.count;
588 out.str = NULL;
589 out.count = 0;
590 out.val = NULL;
591 str_ptr = &out.str;
592 val_ptr = &out.val;
593 count_ptr = &out.count;
595 args[3] = &str_ptr;
596 args[4] = &val_ptr;
597 args[5] = &count_ptr;
599 ctx_send.callback = send_callback;
600 ctx_send.state = NULL;
602 prop[0].id = WS_CALL_PROPERTY_SEND_MESSAGE_CONTEXT;
603 prop[0].value = &ctx_send;
604 prop[0].valueSize = sizeof(ctx_send);
606 ctx_recv.callback = recv_callback;
607 ctx_recv.state = NULL;
609 prop[1].id = WS_CALL_PROPERTY_RECEIVE_MESSAGE_CONTEXT;
610 prop[1].value = &ctx_recv;
611 prop[1].valueSize = sizeof(ctx_recv);
613 hr = WsCall( proxy, &op, args, heap, prop, ARRAY_SIZE(prop), NULL, NULL );
614 ok( hr == S_OK, "got %#lx\n", hr );
615 ok( !wcscmp( out.str, L"test" ), "wrong data\n" );
616 ok( out.count == 2, "got %lu\n", out.count );
617 ok( out.val[0] == 1, "got %u\n", out.val[0] );
618 ok( out.val[1] == 2, "got %u\n", out.val[1] );
620 hr = WsCloseServiceProxy( proxy, NULL, NULL );
621 ok( hr == S_OK, "got %#lx\n", hr );
623 WsFreeServiceProxy( proxy );
624 WsFreeHeap( heap );
627 static const char req_test3[] =
628 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
629 "<req_test3 xmlns=\"ns\"><val>1</val></req_test3>"
630 "</s:Body></s:Envelope>";
632 static const char resp_test3[] =
633 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body/></s:Envelope>";
635 static void test_empty_response( int port )
637 WS_XML_STRING req = {3, (BYTE *)"req"};
638 WS_XML_STRING resp = {4, (BYTE *)"resp"};
639 WS_XML_STRING req_action = {9, (BYTE *)"req_test3"};
640 WS_XML_STRING resp_action = {10, (BYTE *)"resp_test3"};
641 WS_XML_STRING req_elem = {9, (BYTE *)"req_test3"};
642 WS_XML_STRING resp_elem = {10, (BYTE *)"resp_test3"};
643 WS_XML_STRING ns = {2, (BYTE *)"ns"};
644 WS_XML_STRING ns2 = {0, (BYTE *)""};
645 WS_XML_STRING val = {3, (BYTE *)"val"};
646 HRESULT hr;
647 WS_SERVICE_PROXY *proxy;
648 WS_FIELD_DESCRIPTION f, *fields[1];
649 WS_STRUCT_DESCRIPTION input_struct, output_struct;
650 WS_ELEMENT_DESCRIPTION input_elem, output_elem;
651 WS_MESSAGE_DESCRIPTION input_msg, output_msg;
652 WS_PARAMETER_DESCRIPTION param[1];
653 WS_OPERATION_DESCRIPTION op;
654 const void *args[1];
655 WS_HEAP *heap;
656 struct input
658 INT32 val;
659 } in;
661 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
662 ok( hr == S_OK, "got %#lx\n", hr );
664 hr = create_proxy( port, &proxy );
665 ok( hr == S_OK, "got %#lx\n", hr );
667 set_field_desc( &f, WS_ELEMENT_FIELD_MAPPING, &val, &ns, WS_INT32_TYPE, NULL, 0, 0, 0, NULL, NULL );
668 fields[0] = &f;
670 set_struct_desc( &input_struct, sizeof(struct input), TYPE_ALIGNMENT(struct input), fields, 1, &req, &ns, 0 );
671 set_elem_desc( &input_elem, &req_elem, &ns, WS_STRUCT_TYPE, &input_struct );
672 set_msg_desc( &input_msg, &req_action, &input_elem );
674 set_struct_desc( &output_struct, 0, 1, NULL, 0, &resp, &ns2, 0x6 );
675 set_elem_desc( &output_elem, &resp_elem, &ns, WS_STRUCT_TYPE, NULL );
676 set_msg_desc( &output_msg, &resp_action, &output_elem );
678 set_param_desc( param, WS_PARAMETER_TYPE_NORMAL, 0, 0xffff );
679 set_op_desc( &op, &input_msg, &output_msg, 1, param );
681 in.val = 1;
682 args[0] = &in.val;
683 hr = WsCall( proxy, &op, args, heap, NULL, 0, NULL, NULL );
684 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
686 set_elem_desc( &output_elem, &resp_elem, &ns, WS_STRUCT_TYPE, &output_struct );
687 hr = WsCall( proxy, &op, args, heap, NULL, 0, NULL, NULL );
688 ok( hr == WS_E_INVALID_FORMAT, "got %#lx\n", hr );
690 hr = WsCloseServiceProxy( proxy, NULL, NULL );
691 ok( hr == S_OK, "got %#lx\n", hr );
693 WsFreeServiceProxy( proxy );
694 WsFreeHeap( heap );
697 static const char req_test4[] =
698 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
699 "<req_test4 xmlns=\"ns\"><str>test4</str><val>1</val><val>2</val><val>3</val></req_test4>"
700 "</s:Body></s:Envelope>";
702 static const char resp_test4[] =
703 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
704 "<resp_test4 xmlns=\"ns\"><str>out4</str><val>4</val><val>5</val></resp_test4>"
705 "</s:Body></s:Envelope>";
707 static void test_inout_params( int port )
709 WS_XML_STRING str = {3, (BYTE *)"str"};
710 WS_XML_STRING req = {3, (BYTE *)"req"};
711 WS_XML_STRING resp = {4, (BYTE *)"resp"};
712 WS_XML_STRING req_elem = {9, (BYTE *)"req_test4"};
713 WS_XML_STRING resp_elem = {10, (BYTE *)"resp_test4"};
714 WS_XML_STRING req_action = {9, (BYTE *)"req_test4"};
715 WS_XML_STRING resp_action = {10, (BYTE *)"resp_test4"};
716 WS_XML_STRING val = {3, (BYTE *)"val"};
717 WS_XML_STRING ns = {2, (BYTE *)"ns"};
718 HRESULT hr;
719 WS_SERVICE_PROXY *proxy;
720 WS_OPERATION_DESCRIPTION op;
721 WS_MESSAGE_DESCRIPTION input_msg, output_msg;
722 WS_ELEMENT_DESCRIPTION input_elem, output_elem;
723 WS_STRUCT_DESCRIPTION input_struct, output_struct;
724 WS_FIELD_DESCRIPTION f, f2, *fields[2];
725 WS_PARAMETER_DESCRIPTION param[3];
726 const void *args[3];
727 WS_HEAP *heap;
728 INT32 val_array[] = {1, 2, 3};
729 WCHAR **str_ptr;
730 INT32 **val_ptr;
731 ULONG *count_ptr;
732 struct data
734 WCHAR *str;
735 ULONG count;
736 INT32 *val;
737 } data;
739 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
740 ok( hr == S_OK, "got %#lx\n", hr );
742 hr = WsCall( NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL );
743 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
745 hr = create_proxy( port, &proxy );
746 ok( hr == S_OK, "got %#lx\n", hr );
748 hr = WsCall( proxy, NULL, NULL, NULL, NULL, 0, NULL, NULL );
749 ok( hr == E_INVALIDARG, "got %#lx\n", hr );
751 set_field_desc( &f, WS_ELEMENT_FIELD_MAPPING, &str, &ns, WS_WSZ_TYPE, NULL,
752 FIELD_OFFSET(struct data, str), 0, 0, NULL, NULL );
753 set_field_desc( &f2, WS_REPEATING_ELEMENT_FIELD_MAPPING, NULL, NULL, WS_INT32_TYPE, NULL,
754 FIELD_OFFSET(struct data, val), 0, FIELD_OFFSET(struct data, count), &val, &ns );
756 fields[0] = &f;
757 fields[1] = &f2;
759 set_struct_desc( &input_struct, sizeof(struct data), TYPE_ALIGNMENT(struct data), fields, 2, &req, &ns, 0 );
760 set_elem_desc( &input_elem, &req_elem, &ns, WS_STRUCT_TYPE, &input_struct );
761 set_msg_desc( &input_msg, &req_action, &input_elem );
763 set_struct_desc( &output_struct, sizeof(struct data), TYPE_ALIGNMENT(struct data), fields, 2, &resp, &ns, 0 );
764 set_elem_desc( &output_elem, &resp_elem, &ns, WS_STRUCT_TYPE, &output_struct );
765 set_msg_desc( &output_msg, &resp_action, &output_elem );
767 set_param_desc( &param[0], WS_PARAMETER_TYPE_NORMAL, 0, 0 );
768 set_param_desc( &param[1], WS_PARAMETER_TYPE_ARRAY, 1, 1 );
769 set_param_desc( &param[2], WS_PARAMETER_TYPE_ARRAY_COUNT, 1, 1 );
771 set_op_desc( &op, &input_msg, &output_msg, 3, param );
773 data.str = (WCHAR *) L"test4";
774 data.count = ARRAY_SIZE(val_array);
775 data.val = val_array;
777 str_ptr = &data.str;
778 val_ptr = &data.val;
779 count_ptr = &data.count;
781 args[0] = &str_ptr;
782 args[1] = &val_ptr;
783 args[2] = &count_ptr;
785 hr = WsCall( proxy, &op, args, heap, NULL, 0, NULL, NULL );
786 ok( hr == S_OK, "got %#lx\n", hr );
787 ok( !wcscmp( data.str, L"out4" ), "wrong str\n" );
788 ok( data.count == 2, "got %lu\n", data.count );
789 ok( data.val[0] == 4, "got %u\n", data.val[0] );
790 ok( data.val[1] == 5, "got %u\n", data.val[1] );
792 hr = WsCloseServiceProxy( proxy, NULL, NULL );
793 ok( hr == S_OK, "got %#lx\n", hr );
795 WsFreeServiceProxy( proxy );
796 WsFreeHeap( heap );
799 static const char req_test5[] =
800 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
801 "<req_test5 xmlns=\"ns\"><val>1</val></req_test5>"
802 "</s:Body></s:Envelope>";
804 static const char resp_test5[] =
805 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>"
806 "<s:Fault><faultcode>s:Client</faultcode><faultstring>OLS Exception</faultstring><detail>"
807 "<ServerFault xmlns=\"http://schemas.microsoft.com/office/licensingservice/API/2012/01/ClientApi\" "
808 "xmlns:a=\"http://schemas.datacontract.org/2004/07/Microsoft.Office.LicensingService\" "
809 "xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><a:ErrorCode>1030</a:ErrorCode><a:Message/>"
810 "<a:Url>https://portal.office.com/Account/#installs</a:Url></ServerFault></detail>"
811 "</s:Fault></s:Body></s:Envelope>";
813 static void test_fault_response( int port )
815 WS_XML_STRING faultcode = {6, (BYTE *)"Client"};
816 WS_STRING faultstring = {13, (WCHAR *)L"OLS Exception"};
817 WS_XML_STRING req = {3, (BYTE *)"req"};
818 WS_XML_STRING resp = {4, (BYTE *)"resp"};
819 WS_XML_STRING req_action = {9, (BYTE *)"req_test5"};
820 WS_XML_STRING resp_action = {10, (BYTE *)"resp_test5"};
821 WS_XML_STRING req_elem = {9, (BYTE *)"req_test5"};
822 WS_XML_STRING resp_elem = {10, (BYTE *)"resp_test5"};
823 WS_XML_STRING ns = {2, (BYTE *)"ns"};
824 WS_XML_STRING ns2 = {0, (BYTE *)""};
825 WS_XML_STRING val = {3, (BYTE *)"val"};
826 HRESULT hr;
827 WS_SERVICE_PROXY *proxy;
828 WS_FIELD_DESCRIPTION f, *fields[1];
829 WS_STRUCT_DESCRIPTION input_struct, output_struct;
830 WS_ELEMENT_DESCRIPTION input_elem, output_elem;
831 WS_MESSAGE_DESCRIPTION input_msg, output_msg;
832 WS_PARAMETER_DESCRIPTION param[1];
833 WS_OPERATION_DESCRIPTION op;
834 const void *args[1];
835 WS_HEAP *heap;
836 struct input
838 INT32 val;
839 } in;
840 WS_ERROR *error;
841 WS_FAULT *fault;
843 hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
844 ok( hr == S_OK, "got %#lx\n", hr );
846 hr = create_proxy( port, &proxy );
847 ok( hr == S_OK, "got %#lx\n", hr );
849 set_field_desc( &f, WS_ELEMENT_FIELD_MAPPING, &val, &ns, WS_INT32_TYPE, NULL, 0, 0, 0, NULL, NULL );
850 fields[0] = &f;
852 set_struct_desc( &input_struct, sizeof(struct input), TYPE_ALIGNMENT(struct input), fields, 1, &req, &ns, 0 );
853 set_elem_desc( &input_elem, &req_elem, &ns, WS_STRUCT_TYPE, &input_struct );
854 set_msg_desc( &input_msg, &req_action, &input_elem );
856 set_struct_desc( &output_struct, 0, 1, NULL, 0, &resp, &ns2, 0x6 );
857 set_elem_desc( &output_elem, &resp_elem, &ns, WS_STRUCT_TYPE, &output_struct );
858 set_msg_desc( &output_msg, &resp_action, &output_elem );
860 set_param_desc( param, WS_PARAMETER_TYPE_NORMAL, 0, 0xffff );
861 set_op_desc( &op, &input_msg, &output_msg, 1, param );
863 in.val = 1;
864 args[0] = &in.val;
866 hr = WsCreateError( NULL, 0, &error );
867 ok( hr == S_OK, "got %#lx\n", hr );
869 hr = WsCall( proxy, &op, args, heap, NULL, 0, NULL, error );
870 ok( hr == WS_E_ENDPOINT_FAULT_RECEIVED, "got %#lx\n", hr );
872 hr = WsGetFaultErrorProperty( error, WS_FAULT_ERROR_PROPERTY_FAULT, &fault, sizeof(fault) );
873 ok( hr == S_OK, "got %#lx\n", hr );
874 ok( fault != NULL, "fault not set\n" );
875 ok( fault->code->value.localName.length == faultcode.length, "got %lu\n", fault->code->value.localName.length );
876 ok( !memcmp( fault->code->value.localName.bytes, faultcode.bytes, faultcode.length ), "wrong fault code\n" );
877 ok( !fault->code->subCode, "subcode is not NULL\n" );
878 ok( fault->reasonCount == 1, "got %lu\n", fault->reasonCount );
879 ok( fault->reasons[0].text.length == faultstring.length, "got %lu\n", fault->reasons[0].text.length );
880 ok( !memcmp( fault->reasons[0].text.chars, faultstring.chars, faultstring.length * sizeof(WCHAR) ),
881 "wrong fault string\n" );
882 ok( fault->detail != NULL, "fault detail not set\n" );
884 hr = WsCloseServiceProxy( proxy, NULL, NULL );
885 ok( hr == S_OK, "got %#lx\n", hr );
887 WsFreeError( error );
888 WsFreeServiceProxy( proxy );
889 WsFreeHeap( heap );
892 static const char status_200[] = "HTTP/1.1 200 OK\r\n";
893 static const char status_500[] = "HTTP/1.1 500 Internal Server Error\r\n";
895 static const struct
897 const char *req_action;
898 const char *req_data;
899 unsigned int req_len;
900 const char *resp_status;
901 const char *resp_data;
902 unsigned int resp_len;
904 tests[] =
906 { "req_test1", req_test1, sizeof(req_test1)-1, status_200, resp_test1, sizeof(resp_test1)-1 },
907 { "req_test2", req_test2, sizeof(req_test2)-1, status_200, resp_test2, sizeof(resp_test2)-1 },
908 { "req_test3", req_test3, sizeof(req_test3)-1, status_200, resp_test3, sizeof(resp_test3)-1 },
909 { "req_test4", req_test4, sizeof(req_test4)-1, status_200, resp_test4, sizeof(resp_test4)-1 },
910 { "req_test5", req_test5, sizeof(req_test5)-1, status_500, resp_test5, sizeof(resp_test5)-1 },
913 static void send_response( int c, const char *status, const char *data, unsigned int len )
915 static const char headers[] =
916 "Content-Type: text/xml; charset=utf-8\r\nConnection: close\r\nMappedResponseHeader: value\r\n";
917 static const char fmt[] =
918 "Content-Length: %u\r\n\r\n";
919 char buf[128];
921 send( c, status, strlen(status), 0 );
922 send( c, headers, sizeof(headers) - 1, 0 );
923 sprintf( buf, fmt, len );
924 send( c, buf, strlen(buf), 0 );
925 send( c, data, len, 0 );
928 struct server_info
930 HANDLE event;
931 int port;
934 static DWORD CALLBACK server_proc( void *arg )
936 struct server_info *info = arg;
937 int len, res, c = -1, i, j, on = 1, quit;
938 WSADATA wsa;
939 SOCKET s;
940 struct sockaddr_in sa;
941 char buf[1024];
942 const char *p;
944 WSAStartup( MAKEWORD(1,1), &wsa );
945 if ((s = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET) return 1;
946 setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on) );
948 memset( &sa, 0, sizeof(sa) );
949 sa.sin_family = AF_INET;
950 sa.sin_port = htons( info->port );
951 sa.sin_addr.S_un.S_addr = inet_addr( "127.0.0.1" );
952 if (bind( s, (struct sockaddr *)&sa, sizeof(sa) ) < 0) return 1;
954 listen( s, 0 );
955 SetEvent( info->event );
956 for (;;)
958 c = accept( s, NULL, NULL );
960 buf[0] = 0;
961 for (i = 0; i < sizeof(buf) - 1; i++)
963 if ((res = recv( c, &buf[i], 1, 0 )) != 1) break;
964 if (i < 4) continue;
965 if (buf[i - 2] == '\n' && buf[i] == '\n' && buf[i - 3] == '\r' && buf[i - 1] == '\r')
966 break;
968 buf[i] = 0;
969 quit = strstr( buf, "SOAPAction: \"quit\"" ) != NULL;
971 len = 0;
972 if ((p = strstr( buf, "Content-Length: " )))
974 p += strlen( "Content-Length: " );
975 while (isdigit( *p ))
977 len *= 10;
978 len += *p++ - '0';
981 for (i = 0; i < len; i++)
983 if ((res = recv( c, &buf[i], 1, 0 )) != 1) break;
985 buf[i] = 0;
987 for (j = 0; j < ARRAY_SIZE( tests ); j++)
989 if (strstr( buf, tests[j].req_action ))
991 if (tests[j].req_data)
993 int data_len = strlen( buf );
994 ok( tests[j].req_len == data_len, "%u: got data length %u expected %u\n",
995 j, data_len, tests[j].req_len );
996 if (tests[j].req_len == data_len)
997 ok( !memcmp( tests[j].req_data, buf, tests[j].req_len ),
998 "%u: got data '%s' expected '%s'\n", j, buf, tests[j].req_data );
1000 send_response( c, tests[j].resp_status, tests[j].resp_data, tests[j].resp_len );
1001 break;
1005 shutdown( c, 2 );
1006 closesocket( c );
1007 if (quit) break;
1009 closesocket( s );
1011 return 0;
1014 START_TEST(proxy)
1016 WS_XML_STRING test1 = {9, (BYTE *)"req_test1"};
1017 WS_XML_STRING quit = {4, (BYTE *)"quit"};
1018 struct server_info info;
1019 HANDLE thread;
1020 DWORD ret;
1022 test_WsCreateServiceProxy();
1023 test_WsCreateServiceProxyFromTemplate();
1024 test_WsOpenServiceProxy();
1025 test_WsResetServiceProxy();
1027 info.port = 7533;
1028 info.event = CreateEventW( NULL, 0, 0, NULL );
1029 thread = CreateThread( NULL, 0, server_proc, &info, 0, NULL );
1030 ok( thread != NULL, "failed to create server thread %lu\n", GetLastError() );
1032 ret = WaitForSingleObject( info.event, 3000 );
1033 ok(ret == WAIT_OBJECT_0, "failed to start test server %lu\n", GetLastError());
1034 if (ret != WAIT_OBJECT_0)
1036 CloseHandle(thread);
1037 return;
1040 test_WsSendMessage( info.port, &test1 );
1041 test_WsReceiveMessage( info.port );
1042 test_WsCall( info.port );
1043 test_empty_response( info.port );
1044 test_inout_params( info.port );
1045 test_fault_response( info.port );
1047 test_WsSendMessage( info.port, &quit );
1048 WaitForSingleObject( thread, 3000 );
1049 CloseHandle(thread);