From: Shaun Ren sren@codeweavers.com
Signed-off-by: Shaun Ren sren@codeweavers.com --- dlls/webservices/tests/proxy.c | 104 +++++++++++++++++++++++++++++++++ dlls/webservices/writer.c | 21 +++++-- 2 files changed, 121 insertions(+), 4 deletions(-)
diff --git a/dlls/webservices/tests/proxy.c b/dlls/webservices/tests/proxy.c index 9d6292be4c9..f03ae7b9844 100644 --- a/dlls/webservices/tests/proxy.c +++ b/dlls/webservices/tests/proxy.c @@ -694,6 +694,108 @@ static void test_empty_response( int port ) WsFreeHeap( heap ); }
+static const char req_test4[] = + "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/%5C%22%3E<s:Body>" + "<req_test4 xmlns="ns"><str>test4</str><val>1</val><val>2</val><val>3</val></req_test4>" + "</s:Body></s:Envelope>"; + +static const char resp_test4[] = + "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/%5C%22%3E<s:Body>" + "<resp_test4 xmlns="ns"><str>out4</str><val>4</val><val>5</val></resp_test4>" + "</s:Body></s:Envelope>"; + +static void test_inout_params( int port ) +{ + WS_XML_STRING str = {3, (BYTE *)"str"}; + WS_XML_STRING req = {3, (BYTE *)"req"}; + WS_XML_STRING resp = {4, (BYTE *)"resp"}; + WS_XML_STRING req_elem = {9, (BYTE *)"req_test4"}; + WS_XML_STRING resp_elem = {10, (BYTE *)"resp_test4"}; + WS_XML_STRING req_action = {9, (BYTE *)"req_test4"}; + WS_XML_STRING resp_action = {10, (BYTE *)"resp_test4"}; + WS_XML_STRING val = {3, (BYTE *)"val"}; + WS_XML_STRING ns = {2, (BYTE *)"ns"}; + HRESULT hr; + WS_SERVICE_PROXY *proxy; + WS_OPERATION_DESCRIPTION op; + WS_MESSAGE_DESCRIPTION input_msg, output_msg; + WS_ELEMENT_DESCRIPTION input_elem, output_elem; + WS_STRUCT_DESCRIPTION input_struct, output_struct; + WS_FIELD_DESCRIPTION f, f2, *fields[2]; + WS_PARAMETER_DESCRIPTION param[3]; + const void *args[3]; + WS_HEAP *heap; + INT32 val_array[] = {1, 2, 3}; + WCHAR **str_ptr; + INT32 **val_ptr; + ULONG *count_ptr; + struct data + { + WCHAR *str; + ULONG count; + INT32 *val; + } data; + + hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + hr = WsCall( NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL ); + ok( hr == E_INVALIDARG, "got %#lx\n", hr ); + + hr = create_proxy( port, &proxy ); + ok( hr == S_OK, "got %#lx\n", hr ); + + hr = WsCall( proxy, NULL, NULL, NULL, NULL, 0, NULL, NULL ); + ok( hr == E_INVALIDARG, "got %#lx\n", hr ); + + set_field_desc( &f, WS_ELEMENT_FIELD_MAPPING, &str, &ns, WS_WSZ_TYPE, NULL, + FIELD_OFFSET(struct data, str), 0, 0, NULL, NULL ); + set_field_desc( &f2, WS_REPEATING_ELEMENT_FIELD_MAPPING, NULL, NULL, WS_INT32_TYPE, NULL, + FIELD_OFFSET(struct data, val), 0, FIELD_OFFSET(struct data, count), &val, &ns ); + + fields[0] = &f; + fields[1] = &f2; + + set_struct_desc( &input_struct, sizeof(struct data), TYPE_ALIGNMENT(struct data), fields, 2, &req, &ns, 0 ); + set_elem_desc( &input_elem, &req_elem, &ns, WS_STRUCT_TYPE, &input_struct ); + set_msg_desc( &input_msg, &req_action, &input_elem ); + + set_struct_desc( &output_struct, sizeof(struct data), TYPE_ALIGNMENT(struct data), fields, 2, &resp, &ns, 0 ); + set_elem_desc( &output_elem, &resp_elem, &ns, WS_STRUCT_TYPE, &output_struct ); + set_msg_desc( &output_msg, &resp_action, &output_elem ); + + set_param_desc( ¶m[0], WS_PARAMETER_TYPE_NORMAL, 0, 0 ); + set_param_desc( ¶m[1], WS_PARAMETER_TYPE_ARRAY, 1, 1 ); + set_param_desc( ¶m[2], WS_PARAMETER_TYPE_ARRAY_COUNT, 1, 1 ); + + set_op_desc( &op, &input_msg, &output_msg, 3, param ); + + data.str = (WCHAR *) L"test4"; + data.count = ARRAY_SIZE(val_array); + data.val = val_array; + + str_ptr = &data.str; + val_ptr = &data.val; + count_ptr = &data.count; + + args[0] = &str_ptr; + args[1] = &val_ptr; + args[2] = &count_ptr; + + hr = WsCall( proxy, &op, args, heap, NULL, 0, NULL, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + ok( !wcscmp( data.str, L"out4" ), "wrong str\n" ); + ok( data.count == 2, "got %lu\n", data.count ); + ok( data.val[0] == 4, "got %u\n", data.val[0] ); + ok( data.val[1] == 5, "got %u\n", data.val[1] ); + + hr = WsCloseServiceProxy( proxy, NULL, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + WsFreeServiceProxy( proxy ); + WsFreeHeap( heap ); +} + static const char status_200[] = "HTTP/1.1 200 OK\r\n";
static const struct @@ -710,6 +812,7 @@ tests[] = { "req_test1", req_test1, sizeof(req_test1)-1, status_200, resp_test1, sizeof(resp_test1)-1 }, { "req_test2", req_test2, sizeof(req_test2)-1, status_200, resp_test2, sizeof(resp_test2)-1 }, { "req_test3", req_test3, sizeof(req_test3)-1, status_200, resp_test3, sizeof(resp_test3)-1 }, + { "req_test4", req_test4, sizeof(req_test4)-1, status_200, resp_test4, sizeof(resp_test4)-1 }, };
static void send_response( int c, const char *status, const char *data, unsigned int len ) @@ -843,6 +946,7 @@ START_TEST(proxy) test_WsReceiveMessage( info.port ); test_WsCall( info.port ); test_empty_response( info.port ); + test_inout_params( info.port );
test_WsSendMessage( info.port, &quit ); WaitForSingleObject( thread, 3000 ); diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c index cd40b8ad8f6..a4cfc94f08e 100644 --- a/dlls/webservices/writer.c +++ b/dlls/webservices/writer.c @@ -4904,7 +4904,10 @@ static ULONG get_array_len( const WS_PARAMETER_DESCRIPTION *params, ULONG count, { if (params[i].inputMessageIndex != index || params[i].parameterType != WS_PARAMETER_TYPE_ARRAY_COUNT) continue; - if (args[i]) ret = *(const ULONG *)args[i]; + if (params[i].outputMessageIndex != INVALID_PARAMETER_INDEX) + ret = **(const ULONG **)args[i]; + else + ret = *(const ULONG *)args[i]; break; } return ret; @@ -4949,12 +4952,22 @@ HRESULT write_input_params( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTION if ((hr = get_param_desc( desc_struct, params[i].inputMessageIndex, &desc_field )) != S_OK) goto done; if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL) { - if ((hr = write_param( writer, desc_field, args[i] )) != S_OK) goto done; + const void *ptr; + if (params[i].outputMessageIndex != INVALID_PARAMETER_INDEX) + ptr = *(const void **)args[i]; + else + ptr = args[i]; + if ((hr = write_param( writer, desc_field, ptr )) != S_OK) goto done; } else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY) { - const void *ptr = *(const void **)args[i]; - ULONG len = get_array_len( params, count, params[i].inputMessageIndex, args ); + const void *ptr; + ULONG len; + if (params[i].outputMessageIndex != INVALID_PARAMETER_INDEX) + ptr = **(const void ***)args[i]; + else + ptr = *(const void **)args[i]; + len = get_array_len( params, count, params[i].inputMessageIndex, args ); if ((hr = write_param_array( writer, desc_field, ptr, len )) != S_OK) goto done; } }