Shaun Ren : webservices: Handle in/out parameters properly in WsCall.
Alexandre Julliard
julliard at winehq.org
Tue Aug 2 14:55:42 CDT 2022
Module: wine
Branch: master
Commit: 86895f07a0810ca32d15ebbafddb9c8b102ad626
URL: https://gitlab.winehq.org/wine/wine/-/commit/86895f07a0810ca32d15ebbafddb9c8b102ad626
Author: Shaun Ren <sren at codeweavers.com>
Date: Fri Jul 22 20:52:09 2022 -0400
webservices: Handle in/out parameters properly in WsCall.
Signed-off-by: Shaun Ren <sren at 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/\"><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/\"><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;
}
}
More information about the wine-cvs
mailing list