diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index a05d98e84a7..b562c004a7a 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -3561,7 +3561,7 @@ static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_ return WS_E_INVALID_FORMAT; } -static ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc ) +ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc ) { switch (type) { diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c index ebe72fe5644..80b9f43d98f 100644 --- a/dlls/webservices/tests/writer.c +++ b/dlls/webservices/tests/writer.c @@ -2223,6 +2223,92 @@ static void test_WsWriteText(void) WsFreeWriter( writer ); } +static void test_WsWriteArray(void) +{ + static const WS_XML_STRING localname = {4, (BYTE *)"item"}, localname2 = {5, (BYTE *)"array"}; + static const WS_XML_STRING ns = {0, NULL}; + WS_XML_WRITER *writer; + BOOL array_bool[2]; + HRESULT hr; + + hr = WsCreateWriter( NULL, 0, &writer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL ); + ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr ); + + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteArray( writer, NULL, NULL, 0, NULL, 0, 0, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteArray( writer, &localname, NULL, 0, NULL, 0, 0, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteArray( writer, &localname, &ns, 0, NULL, 0, 0, 0, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output( writer, "", __LINE__ ); + + hr = WsWriteArray( writer, &localname, &ns, ~0u, NULL, 0, 0, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, 0, 0, 0, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output( writer, "", __LINE__ ); + + array_bool[0] = FALSE; + hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, 0, 0, 0, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output( writer, "", __LINE__ ); + + hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 0, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output( writer, "", __LINE__ ); + + hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 0, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output( writer, "", __LINE__ ); + + hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, NULL, sizeof(array_bool), 0, 1, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 1, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output( writer, "false", __LINE__ ); + + hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool) - 1, 0, 2, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 3, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + array_bool[1] = TRUE; + hr = WsWriteArray( writer, &localname, &ns, WS_BOOL_VALUE_TYPE, array_bool, sizeof(array_bool), 0, 2, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsWriteEndElement( writer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output( writer, "falsetrue", __LINE__ ); + + WsFreeWriter( writer ); +} + START_TEST(writer) { test_WsCreateWriter(); @@ -2251,4 +2337,5 @@ START_TEST(writer) test_double(); test_field_flags(); test_WsWriteText(); + test_WsWriteArray(); } diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec index cda787df6c3..819686cd7e9 100644 --- a/dlls/webservices/webservices.spec +++ b/dlls/webservices/webservices.spec @@ -164,7 +164,7 @@ @ stub WsStartWriterCanonicalization @ stub WsTrimXmlWhitespace @ stub WsVerifyXmlNCName -@ stub WsWriteArray +@ stdcall WsWriteArray(ptr ptr ptr long ptr long long long ptr) @ stdcall WsWriteAttribute(ptr ptr long ptr long ptr) @ stdcall WsWriteBody(ptr ptr long ptr long ptr) @ stub WsWriteBytes diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index fee00158d8a..a4d08f4bbeb 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -35,6 +35,7 @@ void free_attribute( WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN; WS_TYPE map_value_type( WS_VALUE_TYPE ) DECLSPEC_HIDDEN; BOOL set_fp_rounding( unsigned short * ) DECLSPEC_HIDDEN; void restore_fp_rounding( unsigned short ) DECLSPEC_HIDDEN; +ULONG get_type_size( WS_TYPE, const WS_STRUCT_DESCRIPTION * ) DECLSPEC_HIDDEN; struct node { diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c index 7f732f08856..8fe764ebac1 100644 --- a/dlls/webservices/writer.c +++ b/dlls/webservices/writer.c @@ -1996,6 +1996,41 @@ HRESULT WINAPI WsWriteValue( WS_XML_WRITER *handle, WS_VALUE_TYPE value_type, co return write_type( writer, mapping, type, NULL, WS_WRITE_REQUIRED_VALUE, value, size ); } +/************************************************************************** + * WsWriteArray [webservices.@] + */ +HRESULT WINAPI WsWriteArray( WS_XML_WRITER *handle, const WS_XML_STRING *localname, const WS_XML_STRING *ns, + WS_VALUE_TYPE value_type, const void *array, ULONG size, ULONG offset, + ULONG count, WS_ERROR *error ) +{ + struct writer *writer = (struct writer *)handle; + WS_TYPE type; + ULONG type_size, i; + HRESULT hr; + + TRACE( "%p %s %s %u %p %u %u %u %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), + value_type, array, size, offset, count, error ); + if (error) FIXME( "ignoring error parameter\n" ); + + if (!writer) return E_INVALIDARG; + if (!writer->output_type) return WS_E_INVALID_OPERATION; + if (!localname || !ns || (type = map_value_type( value_type )) == ~0u) return E_INVALIDARG; + + type_size = get_type_size( type, NULL ); + if (size % type_size || (offset + count) * type_size > size || (count && !array)) return E_INVALIDARG; + + for (i = offset; i < count; i++) + { + const char *ptr = (const char *)array + (offset + i) * type_size; + if ((hr = write_element_node( writer, NULL, localname, ns )) != S_OK) return hr; + if ((hr = write_type( writer, WS_ELEMENT_TYPE_MAPPING, type, NULL, WS_WRITE_REQUIRED_POINTER, + &ptr, sizeof(ptr) )) != S_OK) return hr; + if ((hr = write_endelement_node( writer )) != S_OK) return hr; + } + + return S_OK; +} + /************************************************************************** * WsWriteXmlBuffer [webservices.@] */ diff --git a/include/webservices.h b/include/webservices.h index 5decf686a1a..0a58641755a 100644 --- a/include/webservices.h +++ b/include/webservices.h @@ -1493,6 +1493,8 @@ HRESULT WINAPI WsSetOutputToBuffer(WS_XML_WRITER*, WS_XML_BUFFER*, const WS_XML_ HRESULT WINAPI WsSetReaderPosition(WS_XML_READER*, const WS_XML_NODE_POSITION*, WS_ERROR*); HRESULT WINAPI WsSetWriterPosition(WS_XML_WRITER*, const WS_XML_NODE_POSITION*, WS_ERROR*); HRESULT WINAPI WsSkipNode(WS_XML_READER*, WS_ERROR*); +HRESULT WINAPI WsWriteArray(WS_XML_WRITER*, const WS_XML_STRING*, const WS_XML_STRING*, WS_VALUE_TYPE, + const void*, ULONG, ULONG, ULONG, WS_ERROR*); HRESULT WINAPI WsWriteAttribute(WS_XML_WRITER*, const WS_ATTRIBUTE_DESCRIPTION*, WS_WRITE_OPTION, const void*, ULONG, WS_ERROR*); HRESULT WINAPI WsWriteBody(WS_MESSAGE*, const WS_ELEMENT_DESCRIPTION*, WS_WRITE_OPTION, const void*,