[2/5] msxml3: Basic implementation of IXMLDOMNode::replaceChild
Michael Karcher
wine at mkarcher.dialup.fu-berlin.de
Mon Oct 6 17:48:21 CDT 2008
---
dlls/msxml3/node.c | 39 +++++++++++++++++++++++++++++++++++++--
dlls/msxml3/tests/domdoc.c | 22 +++++++++++++---------
2 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c
index b82ef55..467505e 100644
--- a/dlls/msxml3/node.c
+++ b/dlls/msxml3/node.c
@@ -610,6 +610,9 @@ static HRESULT WINAPI xmlnode_replaceChild(
IXMLDOMNode** outOldChild)
{
xmlnode *This = impl_from_IXMLDOMNode( iface );
+ xmlNode *old_child_ptr, *new_child_ptr;
+ xmlDocPtr leaving_doc;
+ xmlNode *my_ancestor;
TRACE("%p->(%p,%p,%p)\n",This,newChild,oldChild,outOldChild);
@@ -617,9 +620,41 @@ static HRESULT WINAPI xmlnode_replaceChild(
means removal. It does certainly *not* apply to msxml3! */
if(!newChild || !oldChild)
return E_INVALIDARG;
+
+ if(outOldChild)
+ *outOldChild = NULL;
- FIXME("not implemented\n");
- return E_NOTIMPL;
+ old_child_ptr = impl_from_IXMLDOMNode(oldChild)->node;
+ if(old_child_ptr->parent != This->node)
+ {
+ WARN("childNode %p is not a child of %p\n", oldChild, iface);
+ return E_INVALIDARG;
+ }
+
+ new_child_ptr = impl_from_IXMLDOMNode(newChild)->node;
+ my_ancestor = This->node;
+ while(my_ancestor)
+ {
+ if(my_ancestor == new_child_ptr)
+ {
+ WARN("tried to create loop\n");
+ return E_FAIL;
+ }
+ my_ancestor = my_ancestor->parent;
+ }
+
+ leaving_doc = new_child_ptr->doc;
+ xmldoc_add_ref(old_child_ptr->doc);
+ xmlReplaceNode(old_child_ptr, new_child_ptr);
+ xmldoc_release(leaving_doc);
+
+ if(outOldChild)
+ {
+ IXMLDOMNode_AddRef(oldChild);
+ *outOldChild = oldChild;
+ }
+
+ return S_OK;
}
static HRESULT WINAPI xmlnode_removeChild(
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 0703f3d..5ccc7af 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -1843,7 +1843,7 @@ static void test_replaceChild(void)
VARIANT_BOOL b;
IXMLDOMDocument *doc;
IXMLDOMElement *element;
- IXMLDOMNode *fo_node, *ba_node, *removed_node, *temp_node;
+ IXMLDOMNode *fo_node, *ba_node, *lc_node, *removed_node, *temp_node;
IXMLDOMNodeList *root_list, *fo_list;
IUnknown * unk1, *unk2;
long len;
@@ -1865,6 +1865,9 @@ static void test_replaceChild(void)
r = IXMLDOMElement_get_childNodes( element, &root_list );
ok( r == S_OK, "ret %08x\n", r);
+ r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
+ ok( r == S_OK, "ret %08x\n", r);
+
r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
ok( r == S_OK, "ret %08x\n", r);
@@ -1890,13 +1893,14 @@ static void test_replaceChild(void)
/* invalid parameter: OldNode is not a child */
removed_node = (void*)0xdeadbeef;
- r = IXMLDOMElement_replaceChild( element, ba_node, ba_node, &removed_node );
- todo_wine ok( r == E_INVALIDARG, "ret %08x\n", r );
- if( r == E_NOTIMPL)
- {
- skip("replaceChild not implemented\n");
- return;
- }
+ r = IXMLDOMElement_replaceChild( element, lc_node, ba_node, &removed_node );
+ ok( r == E_INVALIDARG, "ret %08x\n", r );
+ ok( removed_node == NULL, "%p\n", removed_node );
+
+ /* invalid parameter: would create loop */
+ removed_node = (void*)0xdeadbeef;
+ r = IXMLDOMNode_replaceChild( fo_node, fo_node, ba_node, &removed_node );
+ ok( r == E_FAIL, "ret %08x\n", r );
ok( removed_node == NULL, "%p\n", removed_node );
r = IXMLDOMElement_replaceChild( element, ba_node, fo_node, NULL );
@@ -1912,7 +1916,7 @@ static void test_replaceChild(void)
ok( r == S_OK, "ret %08x\n", r );
r = IXMLDOMNode_QueryInterface( ba_node, &IID_IUnknown, (void**)&unk2);
ok( r == S_OK, "ret %08x\n", r );
- ok( unk1 == unk2, "unk1 %p unk2 %p\n", unk1, unk2);
+ todo_wine ok( unk1 == unk2, "unk1 %p unk2 %p\n", unk1, unk2);
IUnknown_Release( unk1 );
IUnknown_Release( unk2 );
--
1.5.6.5
More information about the wine-patches
mailing list