diff --git a/dlls/msxml3/tests/xmldoc.c b/dlls/msxml3/tests/xmldoc.c index 7cc6cd53201..aadf0882183 100644 --- a/dlls/msxml3/tests/xmldoc.c +++ b/dlls/msxml3/tests/xmldoc.c @@ -141,6 +141,13 @@ static void test_xmldoc(void) ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(element != NULL, "Expected non-NULL element\n"); + /* ::root() returns new instance each time */ + hr = IXMLDocument_get_root(doc, &child); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(child != NULL, "Expected non-NULL element\n"); + ok(child != element, "Expected new element instance\n"); + IXMLElement_Release(child); + hr = IXMLElement_get_type(element, &type); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type); diff --git a/dlls/msxml3/tests/xmlelem.c b/dlls/msxml3/tests/xmlelem.c index 1738b2ce50b..38b621f781e 100644 --- a/dlls/msxml3/tests/xmlelem.c +++ b/dlls/msxml3/tests/xmlelem.c @@ -53,11 +53,7 @@ static void test_xmlelem(void) hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDocument, (LPVOID*)&doc); - if (FAILED(hr)) - { - skip("Failed to create XMLDocument instance\n"); - return; - } + ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr); V_VT(&vType) = VT_I4; V_I4(&vType) = XMLELEMTYPE_ELEMENT; @@ -265,11 +261,7 @@ static void test_xmlelem_collection(void) hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDocument, (LPVOID*)&doc); - if (FAILED(hr)) - { - skip("Failed to create XMLDocument instance\n"); - return; - } + ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr); create_xml_file(szBankXML); GetFullPathNameA(szBankXML, MAX_PATH, pathA, NULL); @@ -438,6 +430,123 @@ cleanup: DeleteFileA("bank.xml"); } +static void test_xmlelem_children(void) +{ + IXMLDocument *doc = NULL; + IXMLElement *element = NULL, *child = NULL, *child2 = NULL; + IXMLElementCollection *collection = NULL; + VARIANT vType, vName, vIndex; + LONG length; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, + &IID_IXMLDocument, (LPVOID*)&doc); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + V_VT(&vType) = VT_I4; + V_I4(&vType) = XMLELEMTYPE_ELEMENT; + V_VT(&vName) = VT_NULL; + hr = IXMLDocument_createElement(doc, vType, vName, &element); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(element != NULL, "Expected non-NULL element\n"); + + V_VT(&vType) = VT_I4; + V_I4(&vType) = XMLELEMTYPE_TEXT; + V_VT(&vName) = VT_NULL; + hr = IXMLDocument_createElement(doc, vType, vName, &child); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(child != NULL, "Expected non-NULL child\n"); + + V_VT(&vType) = VT_I4; + V_I4(&vType) = XMLELEMTYPE_TEXT; + V_VT(&vName) = VT_NULL; + hr = IXMLDocument_createElement(doc, vType, vName, &child2); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(child2 != NULL, "Expected non-NULL child\n"); + + hr = IXMLElement_addChild(element, child, 0, -1); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXMLElement_get_children(element, &collection); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(collection != NULL, "Expected non-NULL collection\n"); + + length = 0; + hr = IXMLElementCollection_get_length(collection, &length); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(length == 1, "Expected 1, got %08x\n", length); + + /* remove/add child and check what happens with collection */ + hr = IXMLElement_removeChild(element, child); + todo_wine ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + length = -1; + hr = IXMLElementCollection_get_length(collection, &length); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + todo_wine ok(length == 0, "Expected 0, got %08x\n", length); + IXMLElementCollection_Release(collection); + + hr = IXMLElement_AddRef(child); + ok(hr == 2, "Expected 2, got %08x\n", hr); + IXMLElement_Release(child); + hr = IXMLElement_addChild(element, child, 0, -1); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + hr = IXMLElement_AddRef(child); + ok(hr == 2, "Expected 2, got %08x\n", hr); + IXMLElement_Release(child); + hr = IXMLElement_addChild(element, child2, 0, -1); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXMLElement_get_children(element, &collection); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(collection != NULL, "Expected non-NULL collection\n"); + + hr = IXMLElement_AddRef(child); + ok(hr == 2, "Expected 2, got %08x\n", hr); + IXMLElement_Release(child); + + length = 0; + hr = IXMLElementCollection_get_length(collection, &length); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(length == 2, "Expected 2, got %08x\n", length); + + IXMLElement_Release(child2); + + length = 0; + hr = IXMLElementCollection_get_length(collection, &length); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(length == 2, "Expected 2, got %08x\n", length); + + V_VT(&vIndex) = VT_I4; + V_I4(&vIndex) = 1; + hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child2); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(child2 != NULL, "Expected not NULL child\n"); + + IXMLElement_Release(element); + IXMLElement_Release(child); + IXMLElementCollection_Release(collection); + IXMLDocument_Release(doc); +} + + +static BOOL test_try_xmldoc(void) +{ + IXMLDocument *doc = NULL; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, + &IID_IXMLDocument, (LPVOID*)&doc); + if (FAILED(hr)) + { + skip("Failed to create XMLDocument instance\n"); + return FALSE; + } + + IXMLDocument_Release(doc); + return TRUE; +} + START_TEST(xmlelem) { HRESULT hr; @@ -445,8 +554,15 @@ START_TEST(xmlelem) hr = CoInitialize(NULL); ok(hr == S_OK, "failed to init com\n"); + if (!test_try_xmldoc()) + { + CoUninitialize(); + return; + } + test_xmlelem(); test_xmlelem_collection(); + test_xmlelem_children(); CoUninitialize(); } diff --git a/dlls/msxml3/xmldoc.c b/dlls/msxml3/xmldoc.c index cf39cc5d983..af67d4e048b 100644 --- a/dlls/msxml3/xmldoc.c +++ b/dlls/msxml3/xmldoc.c @@ -54,7 +54,6 @@ typedef struct _xmldoc HRESULT error; /* IXMLDocument */ - IXMLElement *root; xmlDocPtr xmldoc; /* IPersistStream */ @@ -198,17 +197,19 @@ static HRESULT WINAPI xmldoc_Invoke(IXMLDocument *iface, DISPID dispIdMember, static HRESULT WINAPI xmldoc_get_root(IXMLDocument *iface, IXMLElement **p) { xmldoc *This = impl_from_IXMLDocument(iface); + xmlNodePtr root; TRACE("(%p, %p)\n", iface, p); if (!p) return E_INVALIDARG; - *p = This->root; - if (!*p) + *p = NULL; + + if (!(root = xmlDocGetRootElement(This->xmldoc))) return E_FAIL; - return S_OK; + return XMLElement_create((IUnknown *)This, root, (LPVOID *)p); } static HRESULT WINAPI xmldoc_get_fileSize(IXMLDocument *iface, BSTR *p) @@ -604,7 +605,6 @@ static HRESULT WINAPI xmldoc_IPersistStreamInit_Load( IPersistStreamInit *iface, LPSTREAM pStm) { xmldoc *This = impl_from_IPersistStreamInit(iface); - xmlNodePtr xmlnode; HRESULT hr; HGLOBAL hglobal; DWORD read, written, len; @@ -653,9 +653,7 @@ static HRESULT WINAPI xmldoc_IPersistStreamInit_Load( return E_FAIL; } - if (This->root) IXMLElement_Release(This->root); - xmlnode = xmlDocGetRootElement(This->xmldoc); - return XMLElement_create((IUnknown *)This, xmlnode, (LPVOID *)&This->root); + return S_OK; } static HRESULT WINAPI xmldoc_IPersistStreamInit_Save( @@ -708,7 +706,6 @@ HRESULT XMLDocument_create(IUnknown *pUnkOuter, LPVOID *ppObj) doc->lpvtblIPersistStreamInit = &xmldoc_IPersistStreamInit_VTable; doc->ref = 1; doc->error = S_OK; - doc->root = NULL; doc->xmldoc = NULL; doc->stream = NULL;