diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c index 156060d50de..6d61aa066a8 100644 --- a/dlls/webservices/msg.c +++ b/dlls/webservices/msg.c @@ -1081,6 +1081,69 @@ done: return hr; } +static HRESULT get_standard_header( struct msg *msg, WS_HEADER_TYPE type, WS_TYPE value_type, + WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size ) +{ + const WS_XML_STRING *localname = get_header_name( type ); + const WS_XML_STRING *ns = get_addr_namespace( msg->version_addr ); + const WS_XML_ELEMENT_NODE *elem; + const WS_XML_NODE *node; + HRESULT hr; + + if (!heap) heap = msg->heap; + if (!msg->reader && (hr = WsCreateReader( NULL, 0, &msg->reader, NULL )) != S_OK) return hr; + if ((hr = WsSetInputToBuffer( msg->reader, msg->buf, NULL, 0, NULL )) != S_OK) return hr; + + for (;;) + { + if ((hr = WsReadNode( msg->reader, NULL )) != S_OK) return hr; + if ((hr = WsGetReaderNode( msg->reader, &node, NULL )) != S_OK) return hr; + if (node->nodeType == WS_XML_NODE_TYPE_EOF) return WS_E_INVALID_FORMAT; + if (node->nodeType != WS_XML_NODE_TYPE_ELEMENT) continue; + + elem = (const WS_XML_ELEMENT_NODE *)node; + if (WsXmlStringEquals( elem->localName, localname, NULL ) == S_OK && + WsXmlStringEquals( elem->ns, ns, NULL ) == S_OK) break; + } + + return read_header( msg->reader, localname, ns, value_type, NULL, option, heap, value, size ); +} + +/************************************************************************** + * WsGetHeader [webservices.@] + */ +HRESULT WINAPI WsGetHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_TYPE value_type, WS_READ_OPTION option, + WS_HEAP *heap, void *value, ULONG size, WS_ERROR *error ) +{ + struct msg *msg = (struct msg *)handle; + HRESULT hr; + + TRACE( "%p %u %u %08x %p %p %u %p\n", handle, type, value_type, option, heap, value, size, error ); + if (error) FIXME( "ignoring error parameter\n" ); + + if (!msg || type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER || option < WS_READ_REQUIRED_VALUE || + option > WS_READ_OPTIONAL_POINTER) return E_INVALIDARG; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) + { + LeaveCriticalSection( &msg->cs ); + return WS_E_INVALID_OPERATION; + } + + hr = get_standard_header( msg, type, value_type, option, heap, value, size ); + + LeaveCriticalSection( &msg->cs ); + return hr; +} + static void remove_header( struct msg *msg, ULONG i ) { free_header( msg->header[i] ); diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index d59de3bad0d..7c0a2eb3fa4 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -5242,6 +5242,28 @@ HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TY return hr; } +HRESULT read_header( WS_XML_READER *handle, const WS_XML_STRING *localname, const WS_XML_STRING *ns, + WS_TYPE type, const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value, + ULONG size ) +{ + struct reader *reader = (struct reader *)handle; + HRESULT hr; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_type( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, type, localname, ns, desc, option, heap, + value, size ); + + LeaveCriticalSection( &reader->cs ); + return hr; +} + /************************************************************************** * WsReadElement [webservices.@] */ diff --git a/dlls/webservices/tests/msg.c b/dlls/webservices/tests/msg.c index 4d252659300..4b33b55163e 100644 --- a/dlls/webservices/tests/msg.c +++ b/dlls/webservices/tests/msg.c @@ -1164,6 +1164,110 @@ static void test_WsResetMessage(void) WsFreeMessage( msg ); } +static void test_WsGetHeader(void) +{ + static char expected[] = + "" + "urn:uuid:00000000-0000-0000-0000-000000000000" + "action"; + static char expected2[] = + "
action" + "
"; + static char expected3[] = + "" + "action" + ""; + static WCHAR action[] = {'a','c','t','i','o','n',0}; + WS_MESSAGE *msg; + WCHAR *ptr; + HRESULT hr; + + hr = WsGetHeader( NULL, 0, 0, 0, NULL, NULL, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsCreateMessage( WS_ENVELOPE_VERSION_SOAP_1_2, WS_ADDRESSING_VERSION_1_0, NULL, 0, &msg, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsGetHeader( msg, 0, 0, 0, NULL, NULL, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsInitializeMessage( msg, WS_REQUEST_MESSAGE, NULL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsGetHeader( msg, 0, 0, 0, NULL, NULL, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsGetHeader( msg, WS_ACTION_HEADER, 0, 0, NULL, NULL, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsGetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, 0, NULL, NULL, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsGetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_READ_NILLABLE_POINTER, NULL, NULL, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = WsGetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_READ_REQUIRED_POINTER, NULL, NULL, 0, NULL ); + ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr ); + + ptr = action; + hr = WsSetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + check_output_header( msg, expected, -1, strstr(expected, "urn:uuid:") - expected, 46, __LINE__ ); + + hr = WsGetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_READ_REQUIRED_POINTER, NULL, NULL, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + ptr = NULL; + hr = WsGetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_READ_REQUIRED_POINTER, NULL, &ptr, 0, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + ptr = NULL; + hr = WsGetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_READ_REQUIRED_POINTER, NULL, &ptr, sizeof(ptr), NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( ptr != NULL, "ptr not set\n" ); + ok( !memcmp( ptr, action, sizeof(action) ), "wrong data\n" ); + WsFreeMessage( msg ); + + hr = WsCreateMessage( WS_ENVELOPE_VERSION_NONE, WS_ADDRESSING_VERSION_TRANSPORT, NULL, 0, &msg, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsInitializeMessage( msg, WS_REQUEST_MESSAGE, NULL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + ptr = action; + hr = WsSetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + if (hr == S_OK) check_output_header( msg, expected2, -1, 0, 0, __LINE__ ); + + ptr = NULL; + hr = WsGetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_READ_REQUIRED_POINTER, NULL, &ptr, sizeof(ptr), NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( ptr != NULL, "ptr not set\n" ); + ok( !memcmp( ptr, action, sizeof(action) ), "wrong data\n" ); + WsFreeMessage( msg ); + + hr = WsCreateMessage( WS_ENVELOPE_VERSION_SOAP_1_2, WS_ADDRESSING_VERSION_TRANSPORT, NULL, 0, &msg, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsInitializeMessage( msg, WS_REQUEST_MESSAGE, NULL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + ptr = action; + hr = WsSetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + if (hr == S_OK) check_output_header( msg, expected3, -1, 0, 0, __LINE__ ); + + ptr = NULL; + hr = WsGetHeader( msg, WS_ACTION_HEADER, WS_WSZ_TYPE, WS_READ_REQUIRED_POINTER, NULL, &ptr, sizeof(ptr), NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( ptr != NULL, "ptr not set\n" ); + ok( !memcmp( ptr, action, sizeof(action) ), "wrong data\n" ); + WsFreeMessage( msg ); +} + START_TEST(msg) { test_WsCreateMessage(); @@ -1183,4 +1287,5 @@ START_TEST(msg) test_WsReadEnvelopeEnd(); test_WsReadBody(); test_WsResetMessage(); + test_WsGetHeader(); } diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec index c88935aa75c..b6f246c417c 100644 --- a/dlls/webservices/webservices.spec +++ b/dlls/webservices/webservices.spec @@ -66,7 +66,7 @@ @ stdcall WsGetErrorString(ptr long ptr) @ stub WsGetFaultErrorDetail @ stub WsGetFaultErrorProperty -@ stub WsGetHeader +@ stdcall WsGetHeader(ptr long long long ptr ptr long ptr) @ stub WsGetHeaderAttributes @ stdcall WsGetHeapProperty(ptr long ptr long ptr) @ stdcall WsGetListenerProperty(ptr long ptr long ptr) diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index db839b447a5..30bce24d6bb 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -45,6 +45,8 @@ BOOL set_fpword( unsigned short, unsigned short * ) DECLSPEC_HIDDEN; void restore_fpword( unsigned short ) DECLSPEC_HIDDEN; HRESULT set_output( WS_XML_WRITER * ) DECLSPEC_HIDDEN; ULONG get_type_size( WS_TYPE, const WS_STRUCT_DESCRIPTION * ) DECLSPEC_HIDDEN; +HRESULT read_header( WS_XML_READER *, const WS_XML_STRING *, const WS_XML_STRING *, WS_TYPE, + const void *, WS_READ_OPTION, WS_HEAP *, void *, ULONG ) DECLSPEC_HIDDEN; #define INVALID_PARAMETER_INDEX 0xffff HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *, USHORT, const WS_FIELD_DESCRIPTION ** ) DECLSPEC_HIDDEN;