webservices: Implement WsCopyNode.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e74502b837
commit
46821e27ab
|
@ -378,6 +378,161 @@ void destroy_nodes( struct node *node )
|
||||||
free_node( node );
|
free_node( node );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WS_XML_ATTRIBUTE *dup_attribute( const WS_XML_ATTRIBUTE *src )
|
||||||
|
{
|
||||||
|
WS_XML_ATTRIBUTE *dst;
|
||||||
|
const WS_XML_STRING *prefix = (src->prefix && src->prefix->length) ? src->prefix : NULL;
|
||||||
|
const WS_XML_STRING *localname = src->localName;
|
||||||
|
const WS_XML_STRING *ns = src->localName;
|
||||||
|
|
||||||
|
if (!(dst = heap_alloc( sizeof(*dst) ))) return NULL;
|
||||||
|
dst->singleQuote = src->singleQuote;
|
||||||
|
dst->isXmlNs = src->isXmlNs;
|
||||||
|
if (prefix && !(dst->prefix = alloc_xml_string( prefix->bytes, prefix->length ))) goto error;
|
||||||
|
if (localname && !(dst->localName = alloc_xml_string( localname->bytes, localname->length ))) goto error;
|
||||||
|
if (ns && !(dst->ns = alloc_xml_string( ns->bytes, ns->length ))) goto error;
|
||||||
|
return dst;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free_attribute( dst );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WS_XML_ATTRIBUTE **dup_attributes( WS_XML_ATTRIBUTE * const *src, ULONG count )
|
||||||
|
{
|
||||||
|
WS_XML_ATTRIBUTE **dst;
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
if (!(dst = heap_alloc( sizeof(*dst) * count ))) return NULL;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (!(dst[i] = dup_attribute( src[i] )))
|
||||||
|
{
|
||||||
|
for (; i > 0; i--) free_attribute( dst[i - 1] );
|
||||||
|
heap_free( dst );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct node *dup_element_node( const WS_XML_ELEMENT_NODE *src )
|
||||||
|
{
|
||||||
|
struct node *node;
|
||||||
|
WS_XML_ELEMENT_NODE *dst;
|
||||||
|
ULONG count = src->attributeCount;
|
||||||
|
WS_XML_ATTRIBUTE **attrs = src->attributes;
|
||||||
|
const WS_XML_STRING *prefix = (src->prefix && src->prefix->length) ? src->prefix : NULL;
|
||||||
|
const WS_XML_STRING *localname = src->localName;
|
||||||
|
const WS_XML_STRING *ns = src->ns;
|
||||||
|
|
||||||
|
if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return NULL;
|
||||||
|
dst = &node->hdr;
|
||||||
|
|
||||||
|
if (count && !(dst->attributes = dup_attributes( attrs, count ))) goto error;
|
||||||
|
dst->attributeCount = count;
|
||||||
|
|
||||||
|
if (prefix && !(dst->prefix = alloc_xml_string( prefix->bytes, prefix->length ))) goto error;
|
||||||
|
if (localname && !(dst->localName = alloc_xml_string( localname->bytes, localname->length ))) goto error;
|
||||||
|
if (ns && !(dst->ns = alloc_xml_string( ns->bytes, ns->length ))) goto error;
|
||||||
|
return node;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free_node( node );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct node *dup_text_node( const WS_XML_TEXT_NODE *src )
|
||||||
|
{
|
||||||
|
struct node *node;
|
||||||
|
WS_XML_TEXT_NODE *dst;
|
||||||
|
|
||||||
|
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
|
||||||
|
dst = (WS_XML_TEXT_NODE *)node;
|
||||||
|
|
||||||
|
if (src->text)
|
||||||
|
{
|
||||||
|
WS_XML_UTF8_TEXT *utf8;
|
||||||
|
const WS_XML_UTF8_TEXT *utf8_src = (WS_XML_UTF8_TEXT *)src->text;
|
||||||
|
if (!(utf8 = alloc_utf8_text( utf8_src->value.bytes, utf8_src->value.length )))
|
||||||
|
{
|
||||||
|
free_node( node );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dst->text = &utf8->text;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct node *dup_comment_node( const WS_XML_COMMENT_NODE *src )
|
||||||
|
{
|
||||||
|
struct node *node;
|
||||||
|
WS_XML_COMMENT_NODE *dst;
|
||||||
|
|
||||||
|
if (!(node = alloc_node( WS_XML_NODE_TYPE_COMMENT ))) return NULL;
|
||||||
|
dst = (WS_XML_COMMENT_NODE *)node;
|
||||||
|
|
||||||
|
if (src->value.length && !(dst->value.bytes = heap_alloc( src->value.length )))
|
||||||
|
{
|
||||||
|
free_node( node );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy( dst->value.bytes, src->value.bytes, src->value.length );
|
||||||
|
dst->value.length = src->value.length;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct node *dup_node( const struct node *src )
|
||||||
|
{
|
||||||
|
switch (node_type( src ))
|
||||||
|
{
|
||||||
|
case WS_XML_NODE_TYPE_ELEMENT:
|
||||||
|
return dup_element_node( &src->hdr );
|
||||||
|
|
||||||
|
case WS_XML_NODE_TYPE_TEXT:
|
||||||
|
return dup_text_node( (const WS_XML_TEXT_NODE *)src );
|
||||||
|
|
||||||
|
case WS_XML_NODE_TYPE_COMMENT:
|
||||||
|
return dup_comment_node( (const WS_XML_COMMENT_NODE *)src );
|
||||||
|
|
||||||
|
case WS_XML_NODE_TYPE_CDATA:
|
||||||
|
case WS_XML_NODE_TYPE_END_CDATA:
|
||||||
|
case WS_XML_NODE_TYPE_END_ELEMENT:
|
||||||
|
case WS_XML_NODE_TYPE_EOF:
|
||||||
|
case WS_XML_NODE_TYPE_BOF:
|
||||||
|
return alloc_node( node_type( src ) );
|
||||||
|
|
||||||
|
default:
|
||||||
|
ERR( "unhandled type %u\n", node_type( src ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT dup_tree( struct node **dst, const struct node *src )
|
||||||
|
{
|
||||||
|
struct node *parent;
|
||||||
|
const struct node *child;
|
||||||
|
|
||||||
|
if (!*dst && !(*dst = dup_node( src ))) return E_OUTOFMEMORY;
|
||||||
|
parent = *dst;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY( child, &src->children, struct node, entry )
|
||||||
|
{
|
||||||
|
HRESULT hr = E_OUTOFMEMORY;
|
||||||
|
struct node *new_child;
|
||||||
|
|
||||||
|
if (!(new_child = dup_node( child )) || (hr = dup_tree( &new_child, child )) != S_OK)
|
||||||
|
{
|
||||||
|
destroy_nodes( *dst );
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
new_child->parent = parent;
|
||||||
|
list_add_tail( &parent->children, &new_child->entry );
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct prop_desc reader_props[] =
|
static const struct prop_desc reader_props[] =
|
||||||
{
|
{
|
||||||
{ sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
|
{ sizeof(ULONG), FALSE }, /* WS_XML_READER_PROPERTY_MAX_DEPTH */
|
||||||
|
@ -482,6 +637,12 @@ static void free_reader( struct reader *reader )
|
||||||
heap_free( reader );
|
heap_free( reader );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT copy_node( WS_XML_READER *handle, struct node **node )
|
||||||
|
{
|
||||||
|
struct reader *reader = (struct reader *)handle;
|
||||||
|
return dup_tree( node, reader->current );
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
|
static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
|
||||||
{
|
{
|
||||||
if (str)
|
if (str)
|
||||||
|
@ -1871,7 +2032,7 @@ BOOL move_to_child_node( struct node **current )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL move_to_parent_node( struct node **current )
|
BOOL move_to_parent_node( struct node **current )
|
||||||
{
|
{
|
||||||
struct node *parent = (*current)->parent;
|
struct node *parent = (*current)->parent;
|
||||||
if (!parent) return FALSE;
|
if (!parent) return FALSE;
|
||||||
|
|
|
@ -1733,6 +1733,88 @@ static void test_WsWriteNode(void)
|
||||||
WsFreeHeap( heap );
|
WsFreeHeap( heap );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT set_input( WS_XML_READER *reader, const char *data, ULONG size )
|
||||||
|
{
|
||||||
|
WS_XML_READER_TEXT_ENCODING enc;
|
||||||
|
WS_XML_READER_BUFFER_INPUT input;
|
||||||
|
|
||||||
|
enc.encoding.encodingType = WS_XML_READER_ENCODING_TYPE_TEXT;
|
||||||
|
enc.charSet = WS_CHARSET_AUTO;
|
||||||
|
|
||||||
|
input.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
|
||||||
|
input.encodedData = (void *)data;
|
||||||
|
input.encodedDataSize = size;
|
||||||
|
|
||||||
|
return WsSetInput( reader, &enc.encoding, &input.input, NULL, 0, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_WsCopyNode(void)
|
||||||
|
{
|
||||||
|
WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"}, ns = {0, NULL};
|
||||||
|
WS_XML_NODE_POSITION pos, pos2;
|
||||||
|
WS_XML_WRITER *writer;
|
||||||
|
WS_XML_READER *reader;
|
||||||
|
WS_XML_BUFFER *buffer;
|
||||||
|
WS_HEAP *heap;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", 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 = WsGetWriterPosition( writer, &pos, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
hr = WsWriteEndElement( writer, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
check_output_buffer( buffer, "<t><u/></t>", __LINE__ );
|
||||||
|
|
||||||
|
hr = WsCreateReader( NULL, 0, &reader, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
hr = set_input( reader, "<v/>", sizeof("<v/>") - 1 );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
hr = WsFillReader( reader, sizeof("<v/>") - 1, NULL, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
hr = WsSetWriterPosition( writer, &pos, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
hr = WsCopyNode( writer, reader, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
check_output_buffer( buffer, "<t><u/><v/></t>", __LINE__ );
|
||||||
|
|
||||||
|
hr = WsGetWriterPosition( writer, &pos2, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
ok( pos2.buffer == pos.buffer, "wrong buffer\n" );
|
||||||
|
ok( pos2.node == pos.node, "wrong node\n" );
|
||||||
|
|
||||||
|
WsFreeReader( reader );
|
||||||
|
WsFreeWriter( writer );
|
||||||
|
WsFreeHeap( heap );
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(writer)
|
START_TEST(writer)
|
||||||
{
|
{
|
||||||
test_WsCreateWriter();
|
test_WsCreateWriter();
|
||||||
|
@ -1756,4 +1838,5 @@ START_TEST(writer)
|
||||||
test_WsSetWriterPosition();
|
test_WsSetWriterPosition();
|
||||||
test_WsWriteXmlBuffer();
|
test_WsWriteXmlBuffer();
|
||||||
test_WsWriteNode();
|
test_WsWriteNode();
|
||||||
|
test_WsCopyNode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
@ stdcall WsCloseServiceProxy(ptr ptr ptr)
|
@ stdcall WsCloseServiceProxy(ptr ptr ptr)
|
||||||
@ stub WsCombineUrl
|
@ stub WsCombineUrl
|
||||||
@ stub WsCopyError
|
@ stub WsCopyError
|
||||||
@ stub WsCopyNode
|
@ stdcall WsCopyNode(ptr ptr ptr)
|
||||||
@ stdcall WsCreateChannel(long long ptr long ptr ptr ptr)
|
@ stdcall WsCreateChannel(long long ptr long ptr ptr ptr)
|
||||||
@ stub WsCreateChannelForListener
|
@ stub WsCreateChannelForListener
|
||||||
@ stdcall WsCreateError(ptr long ptr)
|
@ stdcall WsCreateError(ptr long ptr)
|
||||||
|
|
|
@ -46,6 +46,7 @@ struct node *alloc_node( WS_XML_NODE_TYPE ) DECLSPEC_HIDDEN;
|
||||||
void free_node( struct node * ) DECLSPEC_HIDDEN;
|
void free_node( struct node * ) DECLSPEC_HIDDEN;
|
||||||
void destroy_nodes( struct node * ) DECLSPEC_HIDDEN;
|
void destroy_nodes( struct node * ) DECLSPEC_HIDDEN;
|
||||||
struct node *find_parent( struct node * ) DECLSPEC_HIDDEN;
|
struct node *find_parent( struct node * ) DECLSPEC_HIDDEN;
|
||||||
|
HRESULT copy_node( WS_XML_READER *, struct node ** ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
static inline WS_XML_NODE_TYPE node_type( const struct node *node )
|
static inline WS_XML_NODE_TYPE node_type( const struct node *node )
|
||||||
{
|
{
|
||||||
|
@ -64,6 +65,7 @@ BOOL move_to_prev_node( struct node ** ) DECLSPEC_HIDDEN;
|
||||||
BOOL move_to_bof( struct node *, struct node ** ) DECLSPEC_HIDDEN;
|
BOOL move_to_bof( struct node *, struct node ** ) DECLSPEC_HIDDEN;
|
||||||
BOOL move_to_eof( struct node *, struct node ** ) DECLSPEC_HIDDEN;
|
BOOL move_to_eof( struct node *, struct node ** ) DECLSPEC_HIDDEN;
|
||||||
BOOL move_to_child_node( struct node ** ) DECLSPEC_HIDDEN;
|
BOOL move_to_child_node( struct node ** ) DECLSPEC_HIDDEN;
|
||||||
|
BOOL move_to_parent_node( struct node ** ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
struct prop_desc
|
struct prop_desc
|
||||||
{
|
{
|
||||||
|
|
|
@ -1988,3 +1988,117 @@ HRESULT WINAPI WsWriteNode( WS_XML_WRITER *handle, const WS_XML_NODE *node, WS_E
|
||||||
|
|
||||||
return write_node( writer, node );
|
return write_node( writer, node );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT write_tree_node( struct writer *writer )
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
switch (node_type( writer->current ))
|
||||||
|
{
|
||||||
|
case WS_XML_NODE_TYPE_ELEMENT:
|
||||||
|
if (writer->state == WRITER_STATE_STARTELEMENT && (hr = write_endstartelement( writer )) != S_OK)
|
||||||
|
return hr;
|
||||||
|
if ((hr = write_startelement( writer )) != S_OK) return hr;
|
||||||
|
writer->state = WRITER_STATE_STARTELEMENT;
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
case WS_XML_NODE_TYPE_TEXT:
|
||||||
|
if (writer->state == WRITER_STATE_STARTELEMENT && (hr = write_endstartelement( writer )) != S_OK)
|
||||||
|
return hr;
|
||||||
|
if ((hr = write_text( writer )) != S_OK) return hr;
|
||||||
|
writer->state = WRITER_STATE_TEXT;
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
case WS_XML_NODE_TYPE_END_ELEMENT:
|
||||||
|
if ((hr = write_close_element( writer, writer->current->parent )) != S_OK) return hr;
|
||||||
|
writer->state = WRITER_STATE_ENDELEMENT;
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
case WS_XML_NODE_TYPE_COMMENT:
|
||||||
|
if (writer->state == WRITER_STATE_STARTELEMENT && (hr = write_endstartelement( writer )) != S_OK)
|
||||||
|
return hr;
|
||||||
|
if ((hr = write_comment( writer )) != S_OK) return hr;
|
||||||
|
writer->state = WRITER_STATE_COMMENT;
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
case WS_XML_NODE_TYPE_CDATA:
|
||||||
|
if (writer->state == WRITER_STATE_STARTELEMENT && (hr = write_endstartelement( writer )) != S_OK)
|
||||||
|
return hr;
|
||||||
|
if ((hr = write_cdata( writer )) != S_OK) return hr;
|
||||||
|
writer->state = WRITER_STATE_STARTCDATA;
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
case WS_XML_NODE_TYPE_END_CDATA:
|
||||||
|
if ((hr = write_endcdata( writer )) != S_OK) return hr;
|
||||||
|
writer->state = WRITER_STATE_ENDCDATA;
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
case WS_XML_NODE_TYPE_EOF:
|
||||||
|
case WS_XML_NODE_TYPE_BOF:
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ERR( "unknown node type %u\n", node_type(writer->current) );
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT write_tree( struct writer *writer )
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if ((hr = write_tree_node( writer )) != S_OK) return hr;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (node_type( writer->current ) == WS_XML_NODE_TYPE_EOF) break;
|
||||||
|
if (move_to_child_node( &writer->current ))
|
||||||
|
{
|
||||||
|
if ((hr = write_tree_node( writer )) != S_OK) return hr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (move_to_next_node( &writer->current ))
|
||||||
|
{
|
||||||
|
if ((hr = write_tree_node( writer )) != S_OK) return hr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!move_to_parent_node( &writer->current ) || !move_to_next_node( &writer->current ))
|
||||||
|
{
|
||||||
|
ERR( "invalid tree\n" );
|
||||||
|
return WS_E_INVALID_FORMAT;
|
||||||
|
}
|
||||||
|
if ((hr = write_tree_node( writer )) != S_OK) return hr;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_rewind( struct writer *writer )
|
||||||
|
{
|
||||||
|
writer->write_pos = 0;
|
||||||
|
writer->current = writer->root;
|
||||||
|
writer->state = WRITER_STATE_INITIAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* WsCopyNode [webservices.@]
|
||||||
|
*/
|
||||||
|
HRESULT WINAPI WsCopyNode( WS_XML_WRITER *handle, WS_XML_READER *reader, WS_ERROR *error )
|
||||||
|
{
|
||||||
|
struct writer *writer = (struct writer *)handle;
|
||||||
|
struct node *parent, *current = writer->current, *node = NULL;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE( "%p %p %p\n", handle, reader, error );
|
||||||
|
if (error) FIXME( "ignoring error parameter\n" );
|
||||||
|
|
||||||
|
if (!writer) return E_INVALIDARG;
|
||||||
|
if (!(parent = find_parent( writer->current ))) return WS_E_INVALID_FORMAT;
|
||||||
|
|
||||||
|
if ((hr = copy_node( reader, &node )) != S_OK) return hr;
|
||||||
|
write_insert_node( writer, parent, node );
|
||||||
|
|
||||||
|
write_rewind( writer );
|
||||||
|
if ((hr = write_tree( writer )) != S_OK) return hr;
|
||||||
|
|
||||||
|
writer->current = current;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue