From 83bdbc1e386afe59c026c1156b77e3bc5797bbf7 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Wed, 14 Jun 2017 11:07:30 +0200 Subject: [PATCH] webservices: Implement WsReadXmlBuffer. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/webservices/reader.c | 69 +++++++++++ dlls/webservices/tests/reader.c | 198 ++++++++++++++++++++++++++++++ dlls/webservices/webservices.spec | 2 +- include/webservices.h | 1 + 4 files changed, 269 insertions(+), 1 deletion(-) diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index cb9dd8cea8d..4a427cc47be 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -5968,6 +5968,75 @@ HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_co return S_OK; } +static HRESULT move_to_element( struct reader *reader ) +{ + HRESULT hr; + if (node_type( reader->current ) == WS_XML_NODE_TYPE_BOF && + (hr = read_move_to( reader, WS_MOVE_TO_CHILD_NODE, NULL )) != S_OK) return hr; + if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return E_FAIL; + return S_OK; +} + +static HRESULT copy_tree( struct reader *reader, WS_XML_WRITER *writer ) +{ + const struct node *node, *parent; + BOOL done = FALSE; + HRESULT hr; + + if ((hr = move_to_element( reader )) != S_OK) return hr; + parent = reader->current; + for (;;) + { + node = reader->current; + if ((hr = WsWriteNode( writer, (const WS_XML_NODE *)node, NULL )) != S_OK) break; + if (node_type( node ) == WS_XML_NODE_TYPE_END_ELEMENT && node->parent == parent) done = TRUE; + if ((hr = read_next_node( reader )) != S_OK || done) break; + } + return hr; +} + +/************************************************************************** + * WsReadXmlBuffer [webservices.@] + */ +HRESULT WINAPI WsReadXmlBuffer( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_BUFFER **ret, WS_ERROR *error ) +{ + struct reader *reader = (struct reader *)handle; + WS_XML_WRITER *writer = NULL; + WS_XML_BUFFER *buffer; + HRESULT hr; + + TRACE( "%p %p %p %p\n", handle, heap, ret, error ); + if (error) FIXME( "ignoring error parameter\n" ); + + if (!reader || !heap) return E_INVALIDARG; + if (!ret) return E_FAIL; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } + + if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done; + if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL )) != S_OK) goto done; + if ((hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL )) != S_OK) goto done; + if ((hr = copy_tree( reader, writer )) == S_OK) *ret = buffer; + +done: + if (hr != S_OK) free_xmlbuf( (struct xmlbuf *)buffer ); + WsFreeWriter( writer ); + LeaveCriticalSection( &reader->cs ); + return hr; +} + HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *desc, USHORT index, const WS_FIELD_DESCRIPTION **ret ) { if (index >= desc->fieldCount) return E_INVALIDARG; diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c index c023959990e..466ba78b293 100644 --- a/dlls/webservices/tests/reader.c +++ b/dlls/webservices/tests/reader.c @@ -5212,6 +5212,203 @@ static void test_dictionary(void) WsFreeReader( reader ); } +static HRESULT set_output( WS_XML_WRITER *writer ) +{ + WS_XML_WRITER_TEXT_ENCODING text = {{WS_XML_WRITER_ENCODING_TYPE_TEXT}, WS_CHARSET_UTF8}; + WS_XML_WRITER_BUFFER_OUTPUT buf = {{WS_XML_WRITER_OUTPUT_TYPE_BUFFER}}; + return WsSetOutput( writer, &text.encoding, &buf.output, NULL, 0, NULL ); +} + +static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line ) +{ + WS_XML_WRITER *writer; + WS_BYTES bytes; + ULONG size = sizeof(bytes); + int len = strlen(expected); + HRESULT hr; + + hr = WsCreateWriter( NULL, 0, &writer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = set_output( writer ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsWriteXmlBuffer( writer, buffer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + memset( &bytes, 0, sizeof(bytes) ); + hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL ); + ok( hr == S_OK, "%u: got %08x\n", line, hr ); + ok( bytes.length == len, "%u: got %u expected %u\n", line, bytes.length, len ); + if (bytes.length != len) return; + ok( !memcmp( bytes.bytes, expected, len ), "%u: got %s expected %s\n", line, bytes.bytes, expected ); + + WsFreeWriter( writer ); +} + +static HRESULT prepare_xml_buffer_test( WS_XML_READER *reader, WS_HEAP *heap ) +{ + WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"}, ns = {0, NULL}; + WS_XML_WRITER *writer; + WS_XML_BUFFER *buffer; + HRESULT hr; + + hr = WsCreateWriter( NULL, 0, &writer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteEndElement( writer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsWriteEndElement( writer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsSetInputToBuffer( reader, buffer, NULL, 0, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + WsFreeWriter( writer ); + return S_OK; +} + +static void test_WsReadXmlBuffer(void) +{ + const WS_XML_NODE *node; + WS_XML_READER *reader; + WS_XML_BUFFER *buffer; + WS_HEAP *heap; + HRESULT hr; + + hr = WsReadXmlBuffer( NULL, NULL, NULL, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsCreateReader( NULL, 0, &reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadXmlBuffer( reader, NULL, NULL, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadXmlBuffer( reader, heap, NULL, NULL ); + ok( hr == E_FAIL, "got %08x\n", hr ); + + hr = WsReadXmlBuffer( reader, heap, &buffer, NULL ); + todo_wine ok( hr == E_FAIL, "got %08x\n", hr ); + + hr = set_input( reader, "", sizeof("") - 1 ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadStartElement( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsGetReaderNode( reader, &node, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( node->nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", node->nodeType ); + + /* reader positioned at element */ + buffer = NULL; + hr = WsReadXmlBuffer( reader, heap, &buffer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( buffer != NULL, "buffer not set\n" ); + check_output_buffer( buffer, "", __LINE__ ); + + hr = WsGetReaderNode( reader, &node, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType ); + + /* reader positioned at end element */ + hr = WsReadXmlBuffer( reader, heap, &buffer, NULL ); + ok( hr == E_FAIL, "got %08x\n", hr ); + + hr = set_input( reader, "", sizeof("") - 1 ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsGetReaderNode( reader, &node, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( node->nodeType == WS_XML_NODE_TYPE_BOF, "got %u\n", node->nodeType ); + + /* reader positioned at BOF */ + hr = WsReadXmlBuffer( reader, heap, &buffer, NULL ); + todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr ); + + hr = WsGetReaderNode( reader, &node, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + todo_wine ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType ); + + hr = set_input( reader, "", sizeof("") - 1 ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsGetReaderNode( reader, &node, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( node->nodeType == WS_XML_NODE_TYPE_COMMENT, "got %u\n", node->nodeType ); + + /* reader positioned at non-element */ + hr = WsReadXmlBuffer( reader, heap, &buffer, NULL ); + ok( hr == E_FAIL, "got %08x\n", hr ); + + hr = prepare_xml_buffer_test( reader, heap ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsGetReaderNode( reader, &node, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( node->nodeType == WS_XML_NODE_TYPE_BOF, "got %u\n", node->nodeType ); + + /* reader positioned at BOF, input buffer */ + hr = WsReadXmlBuffer( reader, heap, &buffer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output_buffer( buffer, "", __LINE__ ); + + hr = WsGetReaderNode( reader, &node, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType ); + + /* reader positioned at EOF, input buffer */ + hr = WsReadXmlBuffer( reader, heap, &buffer, NULL ); + ok( hr == E_FAIL, "got %08x\n", hr ); + + hr = prepare_xml_buffer_test( reader, heap ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsGetReaderNode( reader, &node, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( node->nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", node->nodeType ); + + /* reader positioned at element, input buffer */ + hr = WsReadXmlBuffer( reader, heap, &buffer, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output_buffer( buffer, "", __LINE__ ); + + hr = WsGetReaderNode( reader, &node, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType ); + + /* reader positioned at end element, input buffer */ + hr = WsReadXmlBuffer( reader, heap, &buffer, NULL ); + ok( hr == E_FAIL, "got %08x\n", hr ); + + WsFreeReader( reader ); + WsFreeHeap( heap ); +} + START_TEST(reader) { test_WsCreateError(); @@ -5256,4 +5453,5 @@ START_TEST(reader) test_WsSkipNode(); test_binary_encoding(); test_dictionary(); + test_WsReadXmlBuffer(); } diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec index 3e774368282..5f9cce8b6c5 100644 --- a/dlls/webservices/webservices.spec +++ b/dlls/webservices/webservices.spec @@ -123,7 +123,7 @@ @ stdcall WsReadToStartElement(ptr ptr ptr ptr ptr) @ stdcall WsReadType(ptr long long ptr long ptr ptr long ptr) @ stdcall WsReadValue(ptr long ptr long ptr) -@ stub WsReadXmlBuffer +@ stdcall WsReadXmlBuffer(ptr ptr ptr ptr) @ stub WsReadXmlBufferFromBytes @ stdcall WsReceiveMessage(ptr ptr ptr long long long ptr ptr long ptr ptr ptr) @ stub WsRegisterOperationForCancel diff --git a/include/webservices.h b/include/webservices.h index aa5fdf4c2e7..84fa206ab8f 100644 --- a/include/webservices.h +++ b/include/webservices.h @@ -1647,6 +1647,7 @@ HRESULT WINAPI WsReadToStartElement(WS_XML_READER*, const WS_XML_STRING*, const HRESULT WINAPI WsReadType(WS_XML_READER*, WS_TYPE_MAPPING, WS_TYPE, const void*, WS_READ_OPTION, WS_HEAP*, void*, ULONG, WS_ERROR*); HRESULT WINAPI WsReadValue(WS_XML_READER*, WS_VALUE_TYPE, void*, ULONG, WS_ERROR*); +HRESULT WINAPI WsReadXmlBuffer(WS_XML_READER*, WS_HEAP*, WS_XML_BUFFER**, WS_ERROR*); HRESULT WINAPI WsReceiveMessage(WS_CHANNEL*, WS_MESSAGE*, const WS_MESSAGE_DESCRIPTION**, ULONG, WS_RECEIVE_OPTION, WS_READ_OPTION, WS_HEAP*, void*, ULONG, ULONG*, const WS_ASYNC_CONTEXT*, WS_ERROR*);