[1/6] webservices: Add support for optional values in WsReadType.
Hans Leidekker
hans at codeweavers.com
Wed Mar 30 07:12:14 CDT 2016
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/reader.c | 816 +++++++++++++++++++++++----------
dlls/webservices/webservices_private.h | 1 +
dlls/webservices/writer.c | 2 +-
3 files changed, 568 insertions(+), 251 deletions(-)
diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 20b284f..7adc283 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -1987,21 +1987,35 @@ HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *loca
static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- WS_XML_UTF8_TEXT **ret )
+ WS_XML_UTF8_TEXT **ret, BOOL *found )
{
switch (mapping)
{
case WS_ATTRIBUTE_TYPE_MAPPING:
{
ULONG index;
- if (!find_attribute( reader, localname, ns, &index )) return WS_E_INVALID_FORMAT;
+ if (!(*found = find_attribute( reader, localname, ns, &index ))) return S_OK;
return read_get_attribute_text( reader, index, ret );
}
case WS_ELEMENT_TYPE_MAPPING:
case WS_ELEMENT_CONTENT_TYPE_MAPPING:
- /* FIXME: verify localname and ns */
- return read_get_node_text( reader, ret );
+ {
+ HRESULT hr;
+ *found = TRUE;
+ if (localname)
+ {
+ const WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
+ if (WsXmlStringEquals( localname, elem->localName, NULL ) != S_OK ||
+ WsXmlStringEquals( ns, elem->ns, NULL ) != S_OK)
+ {
+ *found = FALSE;
+ return S_OK;
+ }
+ if ((hr = read_startelement( reader )) != S_OK) return hr;
+ }
+ return read_get_node_text( reader, ret );
+ }
default:
FIXME( "mapping %u not supported\n", mapping );
return E_NOTIMPL;
@@ -2010,318 +2024,596 @@ static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping,
static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_BOOL_DESCRIPTION *desc, BOOL *ret )
+ const WS_BOOL_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
- ULONG len;
+ BOOL found, val = FALSE;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
- len = utf8->value.length;
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found)
+ {
+ ULONG len = utf8->value.length;
+ if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) val = TRUE;
+ else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) val = TRUE;
+ else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) val = FALSE;
+ else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) val = FALSE;
+ else return WS_E_INVALID_FORMAT;
+ }
- if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) *ret = TRUE;
- else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) *ret = TRUE;
- else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) *ret = FALSE;
- else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) *ret = FALSE;
- else return WS_E_INVALID_FORMAT;
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ if (size != sizeof(BOOL)) return E_INVALIDARG;
+ *(BOOL *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ {
+ BOOL *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(BOOL **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
return S_OK;
}
static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_INT8_DESCRIPTION *desc, INT8 *ret )
+ const WS_INT8_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
INT64 val;
+ BOOL found;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
-
- if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
return hr;
- *ret = val;
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ if (size != sizeof(INT8)) return E_INVALIDARG;
+ *(INT8 *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ {
+ INT8 *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(INT8 **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
+
return S_OK;
}
static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_INT16_DESCRIPTION *desc, INT16 *ret )
+ const WS_INT16_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
INT64 val;
+ BOOL found;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
-
- if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
return hr;
- *ret = val;
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ if (size != sizeof(INT16)) return E_INVALIDARG;
+ *(INT16 *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ {
+ INT16 *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(INT16 **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
+
return S_OK;
}
static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_INT32_DESCRIPTION *desc, INT32 *ret )
+ const WS_INT32_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
INT64 val;
+ BOOL found;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
-
- if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
return hr;
- *ret = val;
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ if (size != sizeof(INT32)) return E_INVALIDARG;
+ *(INT32 *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ {
+ INT32 *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(INT32 **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
+
return S_OK;
}
static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_INT64_DESCRIPTION *desc, INT64 *ret )
+ const WS_INT64_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
INT64 val;
+ BOOL found;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
-
- if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
return hr;
- *ret = val;
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ if (size != sizeof(INT64)) return E_INVALIDARG;
+ *(INT64 *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ {
+ INT64 *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(INT64 **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
+
return S_OK;
}
static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_UINT8_DESCRIPTION *desc, UINT8 *ret )
+ const WS_UINT8_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
UINT64 val;
+ BOOL found;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
-
- if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
return hr;
- *ret = val;
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ if (size != sizeof(UINT8)) return E_INVALIDARG;
+ *(UINT8 *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ {
+ UINT8 *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(UINT8 **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
+
return S_OK;
}
static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_UINT16_DESCRIPTION *desc, UINT16 *ret )
+ const WS_UINT16_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
UINT64 val;
+ BOOL found;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
-
- if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
return hr;
- *ret = val;
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ if (size != sizeof(UINT16)) return E_INVALIDARG;
+ *(UINT16 *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ {
+ UINT16 *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(UINT16 **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
+
return S_OK;
}
static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_UINT32_DESCRIPTION *desc, UINT32 *ret )
+ const WS_UINT32_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
UINT64 val;
+ BOOL found;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
-
- if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
return hr;
- *ret = val;
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ if (size != sizeof(UINT32)) return E_INVALIDARG;
+ *(UINT32 *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ {
+ UINT32 *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(UINT32 **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
+
return S_OK;
}
static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_UINT64_DESCRIPTION *desc, UINT64 *ret )
+ const WS_UINT64_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
UINT64 val;
+ BOOL found;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
-
- if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
return hr;
- *ret = val;
- return S_OK;
-}
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ if (size != sizeof(UINT64)) return E_INVALIDARG;
+ *(UINT64 *)ret = val;
+ break;
-static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
- const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_WSZ_DESCRIPTION *desc, WS_HEAP *heap, WCHAR **ret )
-{
- WS_XML_UTF8_TEXT *utf8;
- HRESULT hr;
- WCHAR *str;
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
- if (desc)
+ case WS_READ_OPTIONAL_POINTER:
{
- FIXME( "description not supported\n" );
+ UINT64 *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(UINT64 **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
return E_NOTIMPL;
}
- if ((hr = read_get_text( reader, mapping, localname, ns, &utf8 )) != S_OK) return hr;
- if (!(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
- *ret = str;
return S_OK;
}
-static HRESULT read_type_struct( struct reader *, WS_TYPE_MAPPING, const WS_XML_STRING *localname,
- const WS_XML_STRING *ns, const WS_STRUCT_DESCRIPTION *, WS_HEAP *,
- void ** );
-
-static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
- WS_HEAP *heap, char *buf )
+static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
+ const WS_XML_STRING *localname, const WS_XML_STRING *ns,
+ const WS_WSZ_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, WCHAR **ret, ULONG size )
{
- char *ptr = buf + desc->offset;
- WS_TYPE_MAPPING mapping;
+ WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
+ WCHAR *str = NULL;
+ BOOL found;
- if (desc->options && desc->options != WS_FIELD_POINTER &&
- desc->options != WS_FIELD_OPTIONAL &&
- desc->options != (WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
+ if (desc)
{
- FIXME( "options 0x%x not supported\n", desc->options );
+ FIXME( "description not supported\n" );
return E_NOTIMPL;
}
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && !(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
- switch (desc->mapping)
+ switch (option)
{
- case WS_ATTRIBUTE_FIELD_MAPPING:
- mapping = WS_ATTRIBUTE_TYPE_MAPPING;
- break;
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
- case WS_ELEMENT_FIELD_MAPPING:
- mapping = WS_ELEMENT_TYPE_MAPPING;
+ case WS_READ_OPTIONAL_POINTER:
+ if (size != sizeof(str)) return E_INVALIDARG;
+ *ret = str;
break;
default:
- FIXME( "unhandled field mapping %u\n", desc->mapping );
+ FIXME( "read option %u not supported\n", option );
return E_NOTIMPL;
}
- switch (desc->type)
+ return S_OK;
+}
+
+static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
+ const WS_XML_STRING *, const void *, WS_READ_OPTION, WS_HEAP *,
+ void *, ULONG );
+
+static WS_READ_OPTION map_field_options( WS_TYPE type, ULONG options )
+{
+ if (options & !(WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
{
- case WS_STRUCT_TYPE:
- hr = read_type_struct( reader, mapping, desc->localName, desc->ns, desc->typeDescription, heap, (void **)ptr );
- break;
+ FIXME( "options %08x not supported\n", options );
+ return 0;
+ }
+ switch (type)
+ {
case WS_BOOL_TYPE:
- hr = read_type_bool( reader, mapping, desc->localName, desc->ns, desc->typeDescription, (BOOL *)ptr );
- break;
-
case WS_INT8_TYPE:
- hr = read_type_int8( reader, mapping, desc->localName, desc->ns, desc->typeDescription, (INT8 *)ptr );
- break;
-
case WS_INT16_TYPE:
- hr = read_type_int16( reader, mapping, desc->localName, desc->ns, desc->typeDescription, (INT16 *)ptr );
- break;
-
case WS_INT32_TYPE:
- hr = read_type_int32( reader, mapping, desc->localName, desc->ns, desc->typeDescription, (INT32 *)ptr );
- break;
-
case WS_INT64_TYPE:
- hr = read_type_int64( reader, mapping, desc->localName, desc->ns, desc->typeDescription, (INT64 *)ptr );
- break;
-
case WS_UINT8_TYPE:
- hr = read_type_uint8( reader, mapping, desc->localName, desc->ns, desc->typeDescription, (UINT8 *)ptr );
- break;
-
case WS_UINT16_TYPE:
- hr = read_type_uint16( reader, mapping, desc->localName, desc->ns, desc->typeDescription, (UINT16 *)ptr );
- break;
-
case WS_UINT32_TYPE:
- hr = read_type_uint32( reader, mapping, desc->localName, desc->ns, desc->typeDescription, (UINT32 *)ptr );
- break;
-
case WS_UINT64_TYPE:
- hr = read_type_uint64( reader, mapping, desc->localName, desc->ns, desc->typeDescription, (UINT64 *)ptr );
- break;
+ return WS_READ_REQUIRED_VALUE;
case WS_WSZ_TYPE:
- hr = read_type_wsz( reader, mapping, desc->localName, desc->ns, desc->typeDescription, heap, (WCHAR **)ptr );
+ case WS_STRUCT_TYPE:
+ return WS_READ_REQUIRED_POINTER;
+
+ default:
+ FIXME( "unhandled type %u\n", type );
+ return 0;
+ }
+}
+
+static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
+ WS_HEAP *heap, char *buf, ULONG size )
+{
+ char *ptr = buf + desc->offset;
+ WS_READ_OPTION option;
+ HRESULT hr;
+
+ if (!(option = map_field_options( desc->type, desc->options ))) return E_INVALIDARG;
+
+ switch (desc->mapping)
+ {
+ case WS_ATTRIBUTE_FIELD_MAPPING:
+ hr = read_type( reader, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
+ desc->typeDescription, option, heap, ptr, size );
+ break;
+
+ case WS_ELEMENT_FIELD_MAPPING:
+ hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->localName, desc->ns,
+ desc->typeDescription, option, heap, ptr, size );
break;
default:
- FIXME( "type %u not implemented\n", desc->type );
+ FIXME( "unhandled field mapping %u\n", desc->mapping );
return E_NOTIMPL;
}
+
+ if (hr == WS_E_INVALID_FORMAT && desc->options & WS_FIELD_OPTIONAL)
+ {
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (desc->defaultValue) memcpy( ptr, desc->defaultValue->value, desc->defaultValue->valueSize );
+ else memset( ptr, 0, size );
+ return S_OK;
+
+ case WS_READ_REQUIRED_POINTER:
+ *(void **)ptr = NULL;
+ return S_OK;
+
+ default:
+ ERR( "unhandled option %u\n", option );
+ return E_NOTIMPL;
+ }
+ }
+
return hr;
}
static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
- const WS_STRUCT_DESCRIPTION *desc, WS_HEAP *heap, void **ret )
+ const WS_STRUCT_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
{
- ULONG i;
+ ULONG i, field_size;
HRESULT hr;
char *buf;
@@ -2329,185 +2621,203 @@ static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
if (desc->structOptions)
{
- FIXME( "struct options 0x%x not supported\n", desc->structOptions );
+ FIXME( "struct options %08x not supported\n", desc->structOptions );
return E_NOTIMPL;
}
- switch (mapping)
+ switch (option)
{
- case WS_ELEMENT_TYPE_MAPPING:
- if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
+ case WS_READ_REQUIRED_POINTER:
+ case WS_READ_OPTIONAL_POINTER:
+ if (size < sizeof(void *)) return E_INVALIDARG;
+ if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
break;
- case WS_ELEMENT_CONTENT_TYPE_MAPPING:
- if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
- if ((hr = read_startelement( reader )) != S_OK) return hr;
+ case WS_READ_REQUIRED_VALUE:
+ if (size != desc->size) return E_INVALIDARG;
+ buf = ret;
break;
default:
- FIXME( "unhandled mapping %u\n", mapping );
+ FIXME( "unhandled read option %u\n", option );
return E_NOTIMPL;
}
- if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
-
for (i = 0; i < desc->fieldCount; i++)
{
- if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
+ field_size = get_field_size( desc, i );
+ if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf, field_size )) != S_OK)
+ break;
+ }
+
+ switch (option)
+ {
+ case WS_READ_REQUIRED_POINTER:
+ if (hr != S_OK)
{
ws_free( heap, buf );
return hr;
}
+ *(char **)ret = buf;
+ return S_OK;
+
+ case WS_READ_OPTIONAL_POINTER:
+ if (hr != S_OK)
+ {
+ ws_free( heap, buf );
+ buf = NULL;
+ }
+ *(char **)ret = buf;
+ return S_OK;
+
+ case WS_READ_REQUIRED_VALUE:
+ return hr;
+
+ default:
+ ERR( "unhandled read option %u\n", option );
+ return E_NOTIMPL;
}
+}
- switch (mapping)
+static BOOL is_empty_text_node( const struct node *node )
+{
+ const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
+ const WS_XML_UTF8_TEXT *utf8;
+ ULONG i;
+
+ if (node->hdr.node.nodeType != WS_XML_NODE_TYPE_TEXT) return FALSE;
+ if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
{
- case WS_ELEMENT_TYPE_MAPPING:
- if ((hr = read_startelement( reader )) != S_OK) return hr;
- if ((hr = read_node( reader )) != S_OK) return hr;
- break;
+ ERR( "unhandled text type %u\n", text->text->textType );
+ return FALSE;
+ }
+ utf8 = (const WS_XML_UTF8_TEXT *)text->text;
+ for (i = 0; i < utf8->value.length; i++) if (!read_isspace( utf8->value.bytes[i] )) return FALSE;
+ return TRUE;
+}
- case WS_ELEMENT_CONTENT_TYPE_MAPPING:
- if ((hr = read_endelement( reader )) != S_OK) return hr;
- if ((hr = read_node( reader )) != S_OK) return hr;
- if (reader->state != READER_STATE_EOF) return WS_E_INVALID_FORMAT;
- break;
+static HRESULT read_type_next_node( struct reader *reader, const WS_XML_STRING *localname,
+ const WS_XML_STRING *ns )
+{
+ const WS_XML_ELEMENT_NODE *elem;
+ WS_XML_NODE_TYPE type;
+ HRESULT hr;
+ BOOL found;
+
+ if (!localname) return S_OK; /* assume reader is already correctly positioned */
+ if ((hr = read_to_startelement( reader, &found ) != S_OK)) return hr;
+ if (!found) return WS_E_INVALID_FORMAT;
- default: break;
+ elem = &reader->current->hdr;
+ if (WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK &&
+ WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK) return S_OK;
+
+ for (;;)
+ {
+ if ((hr = read_node( reader ) != S_OK)) return hr;
+ type = reader->current->hdr.node.nodeType;
+ if (type == WS_XML_NODE_TYPE_COMMENT ||
+ (type == WS_XML_NODE_TYPE_TEXT && is_empty_text_node( reader->current ))) continue;
+ break;
}
- *ret = buf;
return S_OK;
}
static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
+ const WS_XML_STRING *localname, const WS_XML_STRING *ns,
const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
void *value, ULONG size )
{
+ HRESULT hr;
+
+ switch (mapping)
+ {
+ case WS_ELEMENT_TYPE_MAPPING:
+ case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+ if ((hr = read_type_next_node( reader, localname, ns )) != S_OK) return hr;
+ break;
+
+ case WS_ATTRIBUTE_TYPE_MAPPING:
+ break;
+
+ default:
+ FIXME( "unhandled mapping %u\n", mapping );
+ return E_NOTIMPL;
+ }
+
switch (type)
{
case WS_STRUCT_TYPE:
- {
- void **ptr = value;
- if (option != WS_READ_REQUIRED_POINTER || size != sizeof(*ptr))
- return E_INVALIDARG;
+ if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
- return read_type_struct( reader, mapping, NULL, NULL, desc, heap, ptr );
- }
case WS_BOOL_TYPE:
- {
- BOOL *ptr = value;
- if (option != WS_READ_REQUIRED_VALUE)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_bool( reader, mapping, NULL, NULL, desc, ptr );
- }
+ if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_INT8_TYPE:
- {
- INT8 *ptr = value;
- if (option != WS_READ_REQUIRED_VALUE)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_int8( reader, mapping, NULL, NULL, desc, ptr );
- }
+ if ((hr = read_type_int8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_INT16_TYPE:
- {
- INT16 *ptr = value;
- if (option != WS_READ_REQUIRED_VALUE)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_int16( reader, mapping, NULL, NULL, desc, ptr );
- }
+ if ((hr = read_type_int16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_INT32_TYPE:
- {
- INT32 *ptr = value;
- if (option != WS_READ_REQUIRED_VALUE)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_int32( reader, mapping, NULL, NULL, desc, ptr );
- }
+ if ((hr = read_type_int32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_INT64_TYPE:
- {
- INT64 *ptr = value;
- if (option != WS_READ_REQUIRED_VALUE)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_int64( reader, mapping, NULL, NULL, desc, ptr );
- }
+ if ((hr = read_type_int64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_UINT8_TYPE:
- {
- UINT8 *ptr = value;
- if (option != WS_READ_REQUIRED_VALUE)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_uint8( reader, mapping, NULL, NULL, desc, ptr );
- }
+ if ((hr = read_type_uint8( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_UINT16_TYPE:
- {
- UINT16 *ptr = value;
- if (option != WS_READ_REQUIRED_VALUE)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_uint16( reader, mapping, NULL, NULL, desc, ptr );
- }
+ if ((hr = read_type_uint16( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_UINT32_TYPE:
- {
- UINT32 *ptr = value;
- if (option != WS_READ_REQUIRED_VALUE)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_uint32( reader, mapping, NULL, NULL, desc, ptr );
- }
+ if ((hr = read_type_uint32( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_UINT64_TYPE:
- {
- UINT64 *ptr = value;
- if (option != WS_READ_REQUIRED_VALUE)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_uint64( reader, mapping, NULL, NULL, desc, ptr );
- }
+ if ((hr = read_type_uint64( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_WSZ_TYPE:
- {
- WCHAR **ptr = value;
- if (option != WS_READ_REQUIRED_POINTER)
- {
- FIXME( "read option %u not supported\n", option );
- return E_NOTIMPL;
- }
- if (size != sizeof(*ptr)) return E_INVALIDARG;
- return read_type_wsz( reader, mapping, NULL, NULL, desc, heap, ptr );
- }
+ if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
default:
FIXME( "type %u not supported\n", type );
return E_NOTIMPL;
}
+
+ switch (mapping)
+ {
+ case WS_ELEMENT_TYPE_MAPPING:
+ case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+ return read_node( reader );
+
+ case WS_ATTRIBUTE_TYPE_MAPPING:
+ default:
+ return S_OK;
+ }
}
/**************************************************************************
@@ -2518,6 +2828,7 @@ HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TY
ULONG size, WS_ERROR *error )
{
struct reader *reader = (struct reader *)handle;
+ HRESULT hr;
TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
size, error );
@@ -2525,7 +2836,12 @@ HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TY
if (!reader || !value) return E_INVALIDARG;
- return read_type( reader, mapping, type, desc, option, heap, value, size );
+ if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK)
+ return hr;
+
+ if ((hr = read_node( reader )) != S_OK) return hr;
+ if (!read_end_of_data( reader )) return WS_E_INVALID_FORMAT;
+ return S_OK;
}
/**************************************************************************
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index 780c5c4..aa14416 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -32,6 +32,7 @@ WS_XML_STRING *alloc_xml_string( const unsigned char *, ULONG ) DECLSPEC_HIDDEN;
WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *, ULONG ) DECLSPEC_HIDDEN;
HRESULT append_attribute( WS_XML_ELEMENT_NODE *, WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
void free_attribute( WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
+ULONG get_field_size( const WS_STRUCT_DESCRIPTION *, ULONG ) DECLSPEC_HIDDEN;
struct node
{
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 858c9d0..0c5f3cf5 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -1378,7 +1378,7 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
return S_OK;
}
-static ULONG get_field_size( const WS_STRUCT_DESCRIPTION *desc, ULONG index )
+ULONG get_field_size( const WS_STRUCT_DESCRIPTION *desc, ULONG index )
{
if (index < desc->fieldCount - 1) return desc->fields[index + 1]->offset - desc->fields[index]->offset;
return desc->size - desc->fields[index]->offset;
--
2.8.0.rc3
More information about the wine-patches
mailing list