[MSXML3_WINETEST]
[reactos.git] / rostests / winetests / msxml3 / domdoc.c
index c70e6ed..5f06d93 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "windows.h"
 #include "ole2.h"
+#include "objsafe.h"
 #include "xmldom.h"
 #include "msxml2.h"
 #include "msxml2did.h"
 
 #include "wine/test.h"
 
+#include "initguid.h"
+
+DEFINE_GUID(IID_IObjectSafety, 0xcb5bdc81, 0x93c1, 0x11cf, 0x8f,0x20, 0x00,0x80,0x5f,0x2c,0xd0,0x64);
+
 static const WCHAR szEmpty[] = { 0 };
 static const WCHAR szIncomplete[] = {
     '<','?','x','m','l',' ',
@@ -147,12 +152,71 @@ static  const CHAR szTransformOutput[] =
 "</h1></body></html>";
 
 static const CHAR szTypeValueXML[] =
-"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
-"<string>Wine</string>";
+"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+"<root xmlns:dt=\"urn:schemas-microsoft-com:datatypes\">\n"
+"   <string>Wine</string>\n"
+"   <string2 dt:dt=\"string\">String</string2>\n"
+"   <number dt:dt=\"number\">12.44</number>\n"
+"   <number2 dt:dt=\"NUMbEr\">-3.71e3</number2>\n"
+"   <int dt:dt=\"int\">-13</int>\n"
+"   <fixed dt:dt=\"fixed.14.4\">7322.9371</fixed>\n"
+"   <bool dt:dt=\"boolean\">1</bool>\n"
+"   <datetime dt:dt=\"datetime\">2009-11-18T03:21:33.12</datetime>\n"
+"   <datetimetz dt:dt=\"datetime.tz\">2003-07-11T11:13:57+03:00</datetimetz>\n"
+"   <date dt:dt=\"date\">3721-11-01</date>\n"
+"   <time dt:dt=\"time\">13:57:12.31321</time>\n"
+"   <timetz dt:dt=\"time.tz\">23:21:01.13+03:21</timetz>\n"
+"   <i1 dt:dt=\"i1\">-13</i1>\n"
+"   <i2 dt:dt=\"i2\">31915</i2>\n"
+"   <i4 dt:dt=\"i4\">-312232</i4>\n"
+"   <ui1 dt:dt=\"ui1\">123</ui1>\n"
+"   <ui2 dt:dt=\"ui2\">48282</ui2>\n"
+"   <ui4 dt:dt=\"ui4\">949281</ui4>\n"
+"   <r4 dt:dt=\"r4\">213124.0</r4>\n"
+"   <r8 dt:dt=\"r8\">0.412</r8>\n"
+"   <float dt:dt=\"float\">41221.421</float>\n"
+"   <uuid dt:dt=\"uuid\">333C7BC4-460F-11D0-BC04-0080C7055a83</uuid>\n"
+"   <binhex dt:dt=\"bin.hex\">fffca012003c</binhex>\n"
+"   <binbase64 dt:dt=\"bin.base64\">YmFzZTY0IHRlc3Q=</binbase64>\n"
+"</root>";
+
+static const CHAR szBasicTransformSSXMLPart1[] =
+"<?xml version=\"1.0\"?>"
+"<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
+"<xsl:output method=\"html\"/>\n"
+"<xsl:template match=\"/\">"
+"<HTML><BODY><TABLE>"
+"        <xsl:apply-templates select='document(\"";
+
+static const CHAR szBasicTransformSSXMLPart2[] =
+"\")/bottle/wine'>"
+"           <xsl:sort select=\"cost\"/><xsl:sort select=\"name\"/>"
+"        </xsl:apply-templates>"
+"</TABLE></BODY></HTML>"
+"</xsl:template>"
+"<xsl:template match=\"bottle\">"
+"   <TR><xsl:apply-templates select=\"name\" /><xsl:apply-templates select=\"cost\" /></TR>"
+"</xsl:template>"
+"<xsl:template match=\"name\">"
+"   <TD><xsl:apply-templates /></TD>"
+"</xsl:template>"
+"<xsl:template match=\"cost\">"
+"   <TD><xsl:apply-templates /></TD>"
+"</xsl:template>"
+"</xsl:stylesheet>";
+
+static const CHAR szBasicTransformXML[] =
+"<?xml version=\"1.0\"?><bottle><wine><name>Wine</name><cost>$25.00</cost></wine></bottle>";
+
+static const CHAR szBasicTransformOutput[] =
+"<HTML><BODY><TABLE><TD>Wine</TD><TD>$25.00</TD></TABLE></BODY></HTML>";
 
 static const WCHAR szNonExistentFile[] = {
     'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0
 };
+static const WCHAR szNonExistentAttribute[] = {
+    'n','o','n','E','x','i','s','i','t','i','n','g','A','t','t','r','i','b','u','t','e',0
+};
 static const WCHAR szDocument[] = {
     '#', 'd', 'o', 'c', 'u', 'm', 'e', 'n', 't', 0
 };
@@ -213,6 +277,8 @@ static WCHAR szStrangeChars[] = {'&','x',' ',0x2103, 0};
     ok(r == (expect), #expr " returned %x, expected %x\n", r, expect); \
 }
 
+#define double_eq(x, y) ok((x)-(y)<=1e-14*(x) && (x)-(y)>=-1e-14*(x), "expected %.16g, got %.16g\n", x, y)
+
 static BSTR alloc_str_from_narrow(const char *str)
 {
     int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
@@ -292,6 +358,55 @@ static void get_str_for_type(DOMNodeType type, char *buf)
     }
 }
 
+#define test_disp(u) _test_disp(__LINE__,u)
+static void _test_disp(unsigned line, IUnknown *unk)
+{
+    DISPID dispid = DISPID_XMLDOM_NODELIST_RESET;
+    IDispatchEx *dispex;
+    DWORD dwProps = 0;
+    BSTR sName;
+    UINT ticnt;
+    IUnknown *pUnk;
+    HRESULT hres;
+
+    hres = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex);
+    ok_(__FILE__,line) (hres == S_OK, "Could not get IDispatch: %08x\n", hres);
+    if(FAILED(hres))
+        return;
+
+    ticnt = 0xdeadbeef;
+    hres = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
+    ok_(__FILE__,line) (hres == S_OK, "GetTypeInfoCount failed: %08x\n", hres);
+    ok_(__FILE__,line) (ticnt == 1, "ticnt=%u\n", ticnt);
+
+    sName = SysAllocString( szstar );
+    hres = IDispatchEx_DeleteMemberByName(dispex, sName, fdexNameCaseSensitive);
+    ok(hres == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", hres);
+    SysFreeString( sName );
+
+    hres = IDispatchEx_DeleteMemberByDispID(dispex, dispid);
+    ok(hres == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", hres);
+
+    hres = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &dwProps);
+    ok(hres == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", hres);
+    ok(dwProps == 0, "expected 0 got %d\n", dwProps);
+
+    hres = IDispatchEx_GetMemberName(dispex, dispid, &sName);
+    ok(hres == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", hres);
+    if(SUCCEEDED(hres))
+        SysFreeString(sName);
+
+    hres = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_XMLDOM_NODELIST_RESET, &dispid);
+    ok(hres == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", hres);
+
+    hres = IDispatchEx_GetNameSpaceParent(dispex, &pUnk);
+    ok(hres == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", hres);
+    if(hres == S_OK && pUnk)
+        IUnknown_Release(pUnk);
+
+    IDispatchEx_Release(dispex);
+}
+
 static int get_node_position(IXMLDOMNode *node)
 {
     HRESULT r;
@@ -376,7 +491,7 @@ static char *list_to_string(IXMLDOMNodeList *list)
 {
     static char buf[4096];
     char *pos = buf;
-    long len = 0;
+    LONG len = 0;
     int i;
 
     if (list == NULL)
@@ -399,8 +514,8 @@ static char *list_to_string(IXMLDOMNodeList *list)
     return buf;
 }
 
-#define expect_node(node, expstr) { char str[4096]; node_to_string(node, str); ok(strcmp(str, expstr)==0, "Invalid node: %s, exptected %s\n", str, expstr); }
-#define expect_list_and_release(list, expstr) { char *str = list_to_string(list); ok(strcmp(str, expstr)==0, "Invalid node list: %s, exptected %s\n", str, expstr); if (list) IXMLDOMNodeList_Release(list); }
+#define expect_node(node, expstr) { char str[4096]; node_to_string(node, str); ok(strcmp(str, expstr)==0, "Invalid node: %s, expected %s\n", str, expstr); }
+#define expect_list_and_release(list, expstr) { char *str = list_to_string(list); ok(strcmp(str, expstr)==0, "Invalid node list: %s, expected %s\n", str, expstr); if (list) IXMLDOMNodeList_Release(list); }
 
 static void test_domdoc( void )
 {
@@ -418,14 +533,16 @@ static void test_domdoc( void )
     VARIANT_BOOL b;
     VARIANT var;
     BSTR str;
-    long code;
-    long nLength = 0;
+    LONG code;
+    LONG nLength = 0;
 
     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
     if( r != S_OK )
         return;
 
+    test_disp((IUnknown*)doc);
+
     /* try some stupid things */
     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
     ok( r == S_FALSE, "loadXML failed\n");
@@ -514,8 +631,17 @@ static void test_domdoc( void )
     ok( r == S_OK, "should be a document element\n");
     if( element )
     {
+        IObjectIdentity *ident;
         BSTR tag = NULL;
 
+        test_disp((IUnknown*)element);
+
+        r = IXMLDOMElement_QueryInterface( element, &IID_IObjectIdentity, (LPVOID*)&ident );
+        ok( r == E_NOINTERFACE, "ret %08x\n", r);
+
+        r = IXMLDOMElement_get_tagName( element, NULL );
+        ok( r == E_INVALIDARG, "ret %08x\n", r);
+
         /* check if the tag is correct */
         r = IXMLDOMElement_get_tagName( element, &tag );
         ok( r == S_OK, "couldn't get tag name\n");
@@ -571,10 +697,14 @@ static void test_domdoc( void )
 
     r = IXMLDOMParseError_get_errorCode( error, &code );
     ok( r == S_FALSE, "returns %08x\n", r );
-    ok( code == 0, "code %ld\n", code );
+    ok( code == 0, "code %d\n", code );
     IXMLDOMParseError_Release( error );
 
-     /* test createTextNode */
+    /* test createTextNode */
+    r = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &nodetext);
+    ok( r == S_OK, "returns %08x\n", r );
+    IXMLDOMText_Release(nodetext);
+
     str = SysAllocString( szOpen );
     r = IXMLDOMDocument_createTextNode(doc, str, NULL);
     ok( r == E_INVALIDARG, "returns %08x\n", r );
@@ -618,7 +748,7 @@ static void test_domdoc( void )
 
         r = IXMLDOMText_get_length(nodetext, &nLength);
         ok(r == S_OK, "ret %08x\n", r );
-        ok(nLength == 4, "expected 4 got %ld\n", nLength);
+        ok(nLength == 4, "expected 4 got %d\n", nLength);
 
         /* test nodeTypeString */
         r = IXMLDOMText_get_nodeTypeString(nodetext, &str);
@@ -750,6 +880,77 @@ static void test_domdoc( void )
         ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string\n");
         SysFreeString(str);
 
+        /* delete data */
+        /* invalid arguments */
+        r = IXMLDOMText_deleteData(nodetext, -1, 1);
+        ok(r == E_INVALIDARG, "ret %08x\n", r );
+
+        r = IXMLDOMText_deleteData(nodetext, 0, 0);
+        ok(r == S_OK, "ret %08x\n", r );
+
+        r = IXMLDOMText_deleteData(nodetext, 0, -1);
+        ok(r == E_INVALIDARG, "ret %08x\n", r );
+
+        r = IXMLDOMText_get_length(nodetext, &nLength);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok(nLength == 43, "expected 43 got %d\n", nLength);
+
+        r = IXMLDOMText_deleteData(nodetext, nLength, 1);
+        ok(r == S_OK, "ret %08x\n", r );
+
+        r = IXMLDOMText_deleteData(nodetext, nLength+1, 1);
+        ok(r == E_INVALIDARG, "ret %08x\n", r );
+
+        /* delete from start */
+        r = IXMLDOMText_deleteData(nodetext, 0, 5);
+        ok(r == S_OK, "ret %08x\n", r );
+
+        r = IXMLDOMText_get_length(nodetext, &nLength);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok(nLength == 38, "expected 38 got %d\n", nLength);
+
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        /* whitespace preserving needs to be handled here */
+        todo_wine ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append End") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        /* delete from end */
+        r = IXMLDOMText_deleteData(nodetext, 35, 3);
+        ok(r == S_OK, "ret %08x\n", r );
+
+        r = IXMLDOMText_get_length(nodetext, &nLength);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok(nLength == 35, "expected 35 got %d\n", nLength);
+
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        todo_wine ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        /* delete from inside */
+        r = IXMLDOMText_deleteData(nodetext, 1, 33);
+        ok(r == S_OK, "ret %08x\n", r );
+
+        r = IXMLDOMText_get_length(nodetext, &nLength);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok(nLength == 2, "expected 2 got %d\n", nLength);
+
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        todo_wine ok( !lstrcmpW( str, _bstr_("") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        /* delete whole data ... */
+        r = IXMLDOMText_get_length(nodetext, &nLength);
+        ok(r == S_OK, "ret %08x\n", r );
+
+        r = IXMLDOMText_deleteData(nodetext, 0, nLength);
+        ok(r == S_OK, "ret %08x\n", r );
+        /* ... and try again with empty string */
+        r = IXMLDOMText_deleteData(nodetext, 0, nLength);
+        ok(r == S_OK, "ret %08x\n", r );
+
         /* test put_data */
         V_VT(&var) = VT_BSTR;
         V_BSTR(&var) = SysAllocString(szstr1);
@@ -774,13 +975,107 @@ static void test_domdoc( void )
         ok( !lstrcmpW( str, _bstr_("99") ), "incorrect get_text string\n");
         SysFreeString(str);
 
+        /* ::replaceData() */
+        V_VT(&var) = VT_BSTR;
+        V_BSTR(&var) = SysAllocString(szstr1);
+        r = IXMLDOMText_put_nodeValue(nodetext, var);
+        ok(r == S_OK, "ret %08x\n", r );
+        VariantClear(&var);
+
+        r = IXMLDOMText_replaceData(nodetext, 6, 0, NULL);
+        ok(r == E_INVALIDARG, "ret %08x\n", r );
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        r = IXMLDOMText_replaceData(nodetext, 0, 0, NULL);
+        ok(r == S_OK, "ret %08x\n", r );
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        /* NULL pointer means delete */
+        r = IXMLDOMText_replaceData(nodetext, 0, 1, NULL);
+        ok(r == S_OK, "ret %08x\n", r );
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        /* empty string means delete */
+        r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_(""));
+        ok(r == S_OK, "ret %08x\n", r );
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        /* zero count means insert */
+        r = IXMLDOMText_replaceData(nodetext, 0, 0, _bstr_("a"));
+        ok(r == S_OK, "ret %08x\n", r );
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        r = IXMLDOMText_replaceData(nodetext, 0, 2, NULL);
+        ok(r == S_OK, "ret %08x\n", r );
+
+        r = IXMLDOMText_insertData(nodetext, 0, _bstr_("m"));
+        ok(r == S_OK, "ret %08x\n", r );
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        /* nonempty string, count greater than its length */
+        r = IXMLDOMText_replaceData(nodetext, 0, 2, _bstr_("a1.2"));
+        ok(r == S_OK, "ret %08x\n", r );
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
+        /* nonempty string, count less than its length */
+        r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_("wine"));
+        ok(r == S_OK, "ret %08x\n", r );
+        r = IXMLDOMText_get_text(nodetext, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string\n");
+        SysFreeString(str);
+
         IXMLDOMText_Release( nodetext );
     }
 
     /* test Create Comment */
     r = IXMLDOMDocument_createComment(doc, NULL, NULL);
     ok( r == E_INVALIDARG, "returns %08x\n", r );
-    r = IXMLDOMDocument_createComment(doc, szComment, &node_comment);
+    node_comment = (IXMLDOMComment*)0x1;
+
+    /* empty comment */
+    r = IXMLDOMDocument_createComment(doc, _bstr_(""), &node_comment);
+    ok( r == S_OK, "returns %08x\n", r );
+    str = (BSTR)0x1;
+    r = IXMLDOMComment_get_data(node_comment, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && SysStringLen(str) == 0, "expected empty string data\n");
+    IXMLDOMComment_Release(node_comment);
+    SysFreeString(str);
+
+    r = IXMLDOMDocument_createComment(doc, NULL, &node_comment);
+    ok( r == S_OK, "returns %08x\n", r );
+    str = (BSTR)0x1;
+    r = IXMLDOMComment_get_data(node_comment, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && (SysStringLen(str) == 0), "expected empty string data\n");
+    IXMLDOMComment_Release(node_comment);
+    SysFreeString(str);
+
+    str = SysAllocString(szComment);
+    r = IXMLDOMDocument_createComment(doc, str, &node_comment);
+    SysFreeString(str);
     ok( r == S_OK, "returns %08x\n", r );
     if(node_comment)
     {
@@ -793,15 +1088,23 @@ static void test_domdoc( void )
         ok(r == S_FALSE, "ret %08x\n", r );
         ok(nodeChild == NULL, "pLastChild not NULL\n");
 
+        /* baseName */
+        str = (BSTR)0xdeadbeef;
+        IXMLDOMComment_get_baseName(node_comment, &str);
+        ok(r == S_FALSE, "ret %08x\n", r );
+        ok(str == NULL, "Expected NULL\n");
+
         IXMLDOMComment_Release( node_comment );
     }
 
     /* test Create Attribute */
+    str = SysAllocString(szAttribute);
     r = IXMLDOMDocument_createAttribute(doc, NULL, NULL);
     ok( r == E_INVALIDARG, "returns %08x\n", r );
-    r = IXMLDOMDocument_createAttribute(doc, szAttribute, &node_attr);
+    r = IXMLDOMDocument_createAttribute(doc, str, &node_attr);
     ok( r == S_OK, "returns %08x\n", r );
     IXMLDOMText_Release( node_attr);
+    SysFreeString(str);
 
     /* test Processing Instruction */
     str = SysAllocStringLen(NULL, 0);
@@ -837,6 +1140,13 @@ static void test_domdoc( void )
         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
         SysFreeString(str);
 
+        /* test baseName */
+        str = (BSTR)0x1;
+        r = IXMLDOMProcessingInstruction_get_baseName(nodePI, &str);
+        ok(r == S_OK, "ret %08x\n", r );
+        ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
+        SysFreeString(str);
+
         /* test Target */
         r = IXMLDOMProcessingInstruction_get_target(nodePI, &str);
         ok(r == S_OK, "ret %08x\n", r );
@@ -909,12 +1219,16 @@ static void test_domnode( void )
     VARIANT_BOOL b;
     BSTR str;
     VARIANT var;
-    long count;
+    LONG count;
 
     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
     if( r != S_OK )
         return;
+    if (!doc) {
+        ok( FALSE, "no document\n");
+        return;
+    }
 
     b = FALSE;
     str = SysAllocString( szComplete4 );
@@ -923,19 +1237,14 @@ static void test_domnode( void )
     ok( b == VARIANT_TRUE, "failed to load XML string\n");
     SysFreeString( str );
 
-    if (doc)
-    {
-        b = 1;
-        r = IXMLDOMNode_hasChildNodes( doc, &b );
-        ok( r == S_OK, "hasChildNoes bad return\n");
-        ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
+    b = 1;
+    r = IXMLDOMNode_hasChildNodes( doc, &b );
+    ok( r == S_OK, "hasChildNoes bad return\n");
+    ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
 
-        r = IXMLDOMDocument_get_documentElement( doc, &element );
-        ok( r == S_OK, "should be a document element\n");
-        ok( element != NULL, "should be an element\n");
-    }
-    else
-        ok( FALSE, "no document\n");
+    r = IXMLDOMDocument_get_documentElement( doc, &element );
+    ok( r == S_OK, "should be a document element\n");
+    ok( element != NULL, "should be an element\n");
 
     VariantInit(&var);
     ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
@@ -954,6 +1263,7 @@ static void test_domnode( void )
         r = IXMLDOMNode_get_ownerDocument( element, &owner );
         ok( r == S_OK, "get_ownerDocument return code\n");
         ok( owner != doc, "get_ownerDocument return\n");
+        IXMLDOMDocument_Release(owner);
 
         type = NODE_INVALID;
         r = IXMLDOMNode_get_nodeType( element, &type);
@@ -996,7 +1306,7 @@ static void test_domnode( void )
         SysFreeString( str );
 
         attr = (IXMLDOMAttribute*)0xdeadbeef;
-        str = _bstr_("nonExisitingAttribute");
+        str = SysAllocString( szNonExistentAttribute );
         r = IXMLDOMElement_getAttributeNode( element, str, &attr);
         ok( r == S_FALSE, "getAttributeNode ret %08x\n", r );
         ok( attr == NULL, "getAttributeNode ret %p, expected NULL\n", attr );
@@ -1021,8 +1331,19 @@ static void test_domnode( void )
         r = IXMLDOMElement_getAttributeNode( element, str, &attr);
         ok( r == S_OK, "GetAttributeNode ret %08x\n", r );
         ok( attr != NULL, "getAttributeNode returned NULL\n" );
-        if(attr)
+        if (attr)
+        {
+            r = IXMLDOMAttribute_get_parentNode( attr, NULL );
+            ok( r == E_INVALIDARG, "Expected E_INVALIDARG, ret %08x\n", r );
+
+            /* attribute doesn't have a parent in msxml interpretation */
+            node = (IXMLDOMNode*)0xdeadbeef;
+            r = IXMLDOMAttribute_get_parentNode( attr, &node );
+            ok( r == S_FALSE, "Expected S_FALSE, ret %08x\n", r );
+            ok( node == NULL, "Expected NULL, got %p\n", node );
+
             IXMLDOMAttribute_Release(attr);
+        }
 
         SysFreeString( str );
 
@@ -1202,7 +1523,6 @@ todo_wine
     /* now traverse the tree from the root element */
     if (element)
     {
-        IXMLDOMNode *node;
         r = IXMLDOMNode_get_childNodes( element, &list );
         ok( r == S_OK, "get_childNodes returned wrong code\n");
 
@@ -1218,19 +1538,24 @@ todo_wine
         IXMLDOMNodeList_AddRef(list);
         expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1");
         ole_check(IXMLDOMNodeList_reset(list));
+
+        node = (void*)0xdeadbeef;
+        str = SysAllocString(szdl);
+        r = IXMLDOMNode_selectSingleNode( element, str, &node );
+        SysFreeString(str);
+        ok( r == S_FALSE, "ret %08x\n", r );
+        ok( node == NULL, "node %p\n", node );
+
+        str = SysAllocString(szbs);
+        r = IXMLDOMNode_selectSingleNode( element, str, &node );
+        SysFreeString(str);
+        ok( r == S_OK, "ret %08x\n", r );
+        r = IXMLDOMNode_Release( node );
+        ok( r == 0, "ret %08x\n", r );
     }
     else
         ok( FALSE, "no element\n");
 
-    node = (void*)0xdeadbeef;
-    r = IXMLDOMNode_selectSingleNode( element, szdl, &node );
-    ok( r == S_FALSE, "ret %08x\n", r );
-    ok( node == NULL, "node %p\n", node );
-    r = IXMLDOMNode_selectSingleNode( element, szbs, &node );
-    ok( r == S_OK, "ret %08x\n", r );
-    r = IXMLDOMNode_Release( node );
-    ok( r == 0, "ret %08x\n", r );
-
     if (list)
     {
         r = IXMLDOMNodeList_QueryInterface(list, &IID_IDispatch, NULL);
@@ -1244,7 +1569,7 @@ todo_wine
 
         r = IXMLDOMNodeList_get_length( list, &count );
         ok( r == S_OK, "get_length returns %08x\n", r );
-        ok( count == 4, "get_length got %ld\n", count );
+        ok( count == 4, "get_length got %d\n", count );
 
         r = IXMLDOMNodeList_nextNode(list, NULL);
         ok(r == E_INVALIDARG, "Exected E_INVALIDARG got %08x\n", r);
@@ -1324,8 +1649,7 @@ todo_wine
 
     if (element)
         IXMLDOMElement_Release( element );
-    if (doc)
-        ok(IXMLDOMDocument_Release( doc ) == 0, "document is not destroyed\n");
+    ok(IXMLDOMDocument_Release( doc ) == 0, "document is not destroyed\n");
 }
 
 static void test_refs(void)
@@ -1435,99 +1759,356 @@ static void test_create(void)
     BSTR str, name;
     IXMLDOMDocument *doc;
     IXMLDOMElement *element;
+    IXMLDOMComment *comment;
+    IXMLDOMText *text;
+    IXMLDOMCDATASection *cdata;
     IXMLDOMNode *root, *node, *child;
     IXMLDOMNamedNodeMap *attr_map;
     IUnknown *unk;
     LONG ref;
-    long num;
+    LONG num;
 
     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
     if( r != S_OK )
         return;
 
+    /* types not supported for creation */
     V_VT(&var) = VT_I1;
-    V_I1(&var) = NODE_ELEMENT;
-    str = SysAllocString( szlc );
-    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
-    ok( r == S_OK, "returns %08x\n", r );
-    if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
+    V_I1(&var) = NODE_DOCUMENT;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
+    ok( r == E_INVALIDARG, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
 
-    V_VT(&var) = VT_R4;
-    V_R4(&var) = NODE_ELEMENT;
-    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
-    ok( r == S_OK, "returns %08x\n", r );
-    if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_DOCUMENT_TYPE;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
+    ok( r == E_INVALIDARG, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
 
-    V_VT(&var) = VT_BSTR;
-    V_BSTR(&var) = SysAllocString( szOne );
-    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
-    ok( r == S_OK, "returns %08x\n", r );
-    if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
-    VariantClear(&var);
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ENTITY;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
+    ok( r == E_INVALIDARG, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
 
-    V_VT(&var) = VT_BSTR;
-    V_BSTR(&var) = SysAllocString( szOneGarbage );
-    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_NOTATION;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
     ok( r == E_INVALIDARG, "returns %08x\n", r );
-    if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
-    VariantClear(&var);
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
 
-    V_VT(&var) = VT_I4;
-    V_I4(&var) = NODE_ELEMENT;
-    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    /* NODE_COMMENT */
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_COMMENT;
+    node = NULL;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
     ok( r == S_OK, "returns %08x\n", r );
-    r = IXMLDOMDocument_appendChild( doc, node, &root );
+    ok( node != NULL, "\n");
+
+    r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
     ok( r == S_OK, "returns %08x\n", r );
-    ok( node == root, "%p %p\n", node, root );
+    IXMLDOMNode_Release(node);
 
-    ref = IXMLDOMNode_AddRef( node );
-    ok(ref == 3, "ref %d\n", ref);
-    IXMLDOMNode_Release( node );
+    str = NULL;
+    r = IXMLDOMComment_get_data(comment, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
+    IXMLDOMComment_Release(comment);
+    SysFreeString(str);
 
-    ref = IXMLDOMNode_Release( node );
-    ok(ref == 1, "ref %d\n", ref);
-    SysFreeString( str );
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
 
-    V_VT(&var) = VT_I4;
-    V_I4(&var) = NODE_ELEMENT;
-    str = SysAllocString( szbs );
-    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
     ok( r == S_OK, "returns %08x\n", r );
-    SysFreeString( str );
+    IXMLDOMNode_Release(node);
 
-    ref = IXMLDOMNode_AddRef( node );
-    ok(ref == 2, "ref = %d\n", ref);
-    IXMLDOMNode_Release( node );
+    str = NULL;
+    r = IXMLDOMComment_get_data(comment, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
+    IXMLDOMComment_Release(comment);
+    SysFreeString(str);
 
-    r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (LPVOID*)&unk );
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
     ok( r == S_OK, "returns %08x\n", r );
 
-    ref = IXMLDOMNode_AddRef( unk );
-    ok(ref == 3, "ref = %d\n", ref);
-    IXMLDOMNode_Release( unk );
+    r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
+    ok( r == S_OK, "returns %08x\n", r );
+    IXMLDOMNode_Release(node);
 
-    V_VT(&var) = VT_EMPTY;
-    r = IXMLDOMNode_insertBefore( root, (IXMLDOMNode*)unk, var, &child );
+    str = NULL;
+    r = IXMLDOMComment_get_data(comment, &str);
     ok( r == S_OK, "returns %08x\n", r );
-    ok( unk == (IUnknown*)child, "%p %p\n", unk, child );
-    IXMLDOMNode_Release( child );
-    IUnknown_Release( unk );
+    ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
+    IXMLDOMComment_Release(comment);
+    SysFreeString(str);
 
+    /* NODE_TEXT */
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_TEXT;
+    node = NULL;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( node != NULL, "\n");
 
-    V_VT(&var) = VT_NULL;
-    V_DISPATCH(&var) = (IDispatch*)node;
-    r = IXMLDOMNode_insertBefore( root, node, var, &child );
+    r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
     ok( r == S_OK, "returns %08x\n", r );
-    ok( node == child, "%p %p\n", node, child );
-    IXMLDOMNode_Release( child );
+    IXMLDOMNode_Release(node);
 
+    str = NULL;
+    r = IXMLDOMText_get_data(text, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
+    IXMLDOMText_Release(text);
+    SysFreeString(str);
 
-    V_VT(&var) = VT_NULL;
-    V_DISPATCH(&var) = (IDispatch*)node;
-    r = IXMLDOMNode_insertBefore( root, node, var, NULL );
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
     ok( r == S_OK, "returns %08x\n", r );
-    IXMLDOMNode_Release( node );
+
+    r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
+    ok( r == S_OK, "returns %08x\n", r );
+    IXMLDOMNode_Release(node);
+
+    str = NULL;
+    r = IXMLDOMText_get_data(text, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
+    IXMLDOMText_Release(text);
+    SysFreeString(str);
+
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+
+    r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
+    ok( r == S_OK, "returns %08x\n", r );
+    IXMLDOMNode_Release(node);
+
+    str = NULL;
+    r = IXMLDOMText_get_data(text, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
+    IXMLDOMText_Release(text);
+    SysFreeString(str);
+
+    /* NODE_CDATA_SECTION */
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_CDATA_SECTION;
+    node = NULL;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( node != NULL, "\n");
+
+    r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
+    ok( r == S_OK, "returns %08x\n", r );
+    IXMLDOMNode_Release(node);
+
+    str = NULL;
+    r = IXMLDOMCDATASection_get_data(cdata, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
+    IXMLDOMCDATASection_Release(cdata);
+    SysFreeString(str);
+
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+
+    r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
+    ok( r == S_OK, "returns %08x\n", r );
+    IXMLDOMNode_Release(node);
+
+    str = NULL;
+    r = IXMLDOMCDATASection_get_data(cdata, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
+    IXMLDOMCDATASection_Release(cdata);
+    SysFreeString(str);
+
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+
+    r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
+    ok( r == S_OK, "returns %08x\n", r );
+    IXMLDOMNode_Release(node);
+
+    str = NULL;
+    r = IXMLDOMCDATASection_get_data(cdata, &str);
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
+    IXMLDOMCDATASection_Release(cdata);
+    SysFreeString(str);
+
+    /* NODE_ATTRIBUTE */
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ATTRIBUTE;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
+    ok( r == E_FAIL, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ATTRIBUTE;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
+    ok( r == E_FAIL, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ATTRIBUTE;
+    str = SysAllocString( szlc );
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+    if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
+    SysFreeString(str);
+
+    /* NODE_PROCESSING_INSTRUCTION */
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
+    ok( r == E_FAIL, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
+    ok( r == E_FAIL, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_("pi"), NULL, NULL );
+    ok( r == E_INVALIDARG, "returns %08x\n", r );
+
+    /* NODE_ENTITY_REFERENCE */
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ENTITY_REFERENCE;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
+    ok( r == E_FAIL, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ENTITY_REFERENCE;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
+    ok( r == E_FAIL, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
+
+    /* NODE_ELEMENT */
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ELEMENT;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
+    ok( r == E_FAIL, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ELEMENT;
+    node = (IXMLDOMNode*)0x1;
+    r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
+    ok( r == E_FAIL, "returns %08x\n", r );
+    ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ELEMENT;
+    str = SysAllocString( szlc );
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+    if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
+
+    V_VT(&var) = VT_I1;
+    V_I1(&var) = NODE_ELEMENT;
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, NULL );
+    ok( r == E_INVALIDARG, "returns %08x\n", r );
+
+    V_VT(&var) = VT_R4;
+    V_R4(&var) = NODE_ELEMENT;
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+    if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
+
+    V_VT(&var) = VT_BSTR;
+    V_BSTR(&var) = SysAllocString( szOne );
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+    if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
+    VariantClear(&var);
+
+    V_VT(&var) = VT_BSTR;
+    V_BSTR(&var) = SysAllocString( szOneGarbage );
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    ok( r == E_INVALIDARG, "returns %08x\n", r );
+    if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
+    VariantClear(&var);
+
+    V_VT(&var) = VT_I4;
+    V_I4(&var) = NODE_ELEMENT;
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+    r = IXMLDOMDocument_appendChild( doc, node, &root );
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( node == root, "%p %p\n", node, root );
+
+    ref = IXMLDOMNode_AddRef( node );
+    ok(ref == 3, "ref %d\n", ref);
+    IXMLDOMNode_Release( node );
+
+    ref = IXMLDOMNode_Release( node );
+    ok(ref == 1, "ref %d\n", ref);
+    SysFreeString( str );
+
+    V_VT(&var) = VT_I4;
+    V_I4(&var) = NODE_ELEMENT;
+    str = SysAllocString( szbs );
+    r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
+    ok( r == S_OK, "returns %08x\n", r );
+    SysFreeString( str );
+
+    ref = IXMLDOMNode_AddRef( node );
+    ok(ref == 2, "ref = %d\n", ref);
+    IXMLDOMNode_Release( node );
+
+    r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (LPVOID*)&unk );
+    ok( r == S_OK, "returns %08x\n", r );
+
+    ref = IXMLDOMNode_AddRef( unk );
+    ok(ref == 3, "ref = %d\n", ref);
+    IXMLDOMNode_Release( unk );
+
+    V_VT(&var) = VT_EMPTY;
+    r = IXMLDOMNode_insertBefore( root, (IXMLDOMNode*)unk, var, &child );
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( unk == (IUnknown*)child, "%p %p\n", unk, child );
+    IXMLDOMNode_Release( child );
+    IUnknown_Release( unk );
+
+
+    V_VT(&var) = VT_NULL;
+    V_DISPATCH(&var) = (IDispatch*)node;
+    r = IXMLDOMNode_insertBefore( root, node, var, &child );
+    ok( r == S_OK, "returns %08x\n", r );
+    ok( node == child, "%p %p\n", node, child );
+    IXMLDOMNode_Release( child );
+
+
+    V_VT(&var) = VT_NULL;
+    V_DISPATCH(&var) = (IDispatch*)node;
+    r = IXMLDOMNode_insertBefore( root, node, var, NULL );
+    ok( r == S_OK, "returns %08x\n", r );
+    IXMLDOMNode_Release( node );
 
     r = IXMLDOMNode_QueryInterface( root, &IID_IXMLDOMElement, (LPVOID*)&element );
     ok( r == S_OK, "returns %08x\n", r );
@@ -1536,7 +2117,7 @@ static void test_create(void)
     ok( r == S_OK, "returns %08x\n", r );
     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
     ok( r == S_OK, "returns %08x\n", r );
-    ok( num == 0, "num %ld\n", num );
+    ok( num == 0, "num %d\n", num );
     IXMLDOMNamedNodeMap_Release( attr_map );
 
     V_VT(&var) = VT_BSTR;
@@ -1548,7 +2129,7 @@ static void test_create(void)
     ok( r == S_OK, "returns %08x\n", r );
     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
     ok( r == S_OK, "returns %08x\n", r );
-    ok( num == 1, "num %ld\n", num );
+    ok( num == 1, "num %d\n", num );
     IXMLDOMNamedNodeMap_Release( attr_map );
     VariantClear(&var);
 
@@ -1560,7 +2141,7 @@ static void test_create(void)
     ok( r == S_OK, "returns %08x\n", r );
     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
     ok( r == S_OK, "returns %08x\n", r );
-    ok( num == 1, "num %ld\n", num );
+    ok( num == 1, "num %d\n", num );
     IXMLDOMNamedNodeMap_Release( attr_map );
     VariantClear(&var);
     r = IXMLDOMElement_getAttribute( element, name, &var );
@@ -1578,7 +2159,7 @@ static void test_create(void)
     ok( r == S_OK, "returns %08x\n", r );
     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
     ok( r == S_OK, "returns %08x\n", r );
-    ok( num == 2, "num %ld\n", num );
+    ok( num == 2, "num %d\n", num );
     IXMLDOMNamedNodeMap_Release( attr_map );
     VariantClear(&var);
     SysFreeString(name);
@@ -1625,8 +2206,7 @@ static void test_getElementsByTagName(void)
     VARIANT_BOOL b;
     IXMLDOMDocument *doc;
     IXMLDOMNodeList *node_list;
-    IDispatchEx *dispex;
-    long len;
+    LONG len;
 
     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
@@ -1644,45 +2224,9 @@ static void test_getElementsByTagName(void)
     ok( r == S_OK, "ret %08x\n", r );
     r = IXMLDOMNodeList_get_length( node_list, &len );
     ok( r == S_OK, "ret %08x\n", r );
-    ok( len == 6, "len %ld\n", len );
-
-    r = IXMLDOMNodeList_QueryInterface( node_list, &IID_IDispatchEx, (void**)&dispex );
-    ok( r == S_OK, "rets %08x\n", r);
-    if( r == S_OK )
-    {
-        DISPID dispid = DISPID_XMLDOM_NODELIST_RESET;
-        DWORD dwProps = 0;
-        BSTR sName;
-        IUnknown *pUnk;
-
-        sName = SysAllocString( szstar );
-        r = IDispatchEx_DeleteMemberByName(dispex, sName, fdexNameCaseSensitive);
-        ok(r == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", r);
-        SysFreeString( sName );
-
-        r = IDispatchEx_DeleteMemberByDispID(dispex, dispid);
-        ok(r == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", r);
-
-        r = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &dwProps);
-        ok(r == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", r);
-        ok(dwProps == 0, "expected 0 got %d\n", dwProps);
-
-        r = IDispatchEx_GetMemberName(dispex, dispid, &sName);
-        ok(r == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", r);
-        if( SUCCEEDED(r) )
-            SysFreeString(sName);
-
-        r = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_XMLDOM_NODELIST_RESET, &dispid);
-        ok(r == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", r);
-
-        r = IDispatchEx_GetNameSpaceParent(dispex, &pUnk);
-        ok(r == E_NOTIMPL, "expected E_NOTIMPL got %08x\n", r);
-        if(r == S_OK)
-            IUnknown_Release(pUnk);
-
-        IDispatchEx_Release( dispex );
-    }
+    ok( len == 6, "len %d\n", len );
 
+    test_disp((IUnknown*)node_list);
 
     IXMLDOMNodeList_Release( node_list );
     SysFreeString( str );
@@ -1692,7 +2236,7 @@ static void test_getElementsByTagName(void)
     ok( r == S_OK, "ret %08x\n", r );
     r = IXMLDOMNodeList_get_length( node_list, &len );
     ok( r == S_OK, "ret %08x\n", r );
-    ok( len == 1, "len %ld\n", len );
+    ok( len == 1, "len %d\n", len );
     IXMLDOMNodeList_Release( node_list );
     SysFreeString( str );
 
@@ -1701,7 +2245,7 @@ static void test_getElementsByTagName(void)
     ok( r == S_OK, "ret %08x\n", r );
     r = IXMLDOMNodeList_get_length( node_list, &len );
     ok( r == S_OK, "ret %08x\n", r );
-    ok( len == 0, "len %ld\n", len );
+    ok( len == 0, "len %d\n", len );
     IXMLDOMNodeList_Release( node_list );
     SysFreeString( str );
 
@@ -1710,7 +2254,7 @@ static void test_getElementsByTagName(void)
     ok( r == S_OK, "ret %08x\n", r );
     r = IXMLDOMNodeList_get_length( node_list, &len );
     ok( r == S_OK, "ret %08x\n", r );
-    ok( len == 0, "len %ld\n", len );
+    ok( len == 0, "len %d\n", len );
     IXMLDOMNodeList_Release( node_list );
     SysFreeString( str );
 
@@ -1727,7 +2271,7 @@ static void test_get_text(void)
     IXMLDOMNode *nodeRoot;
     IXMLDOMNodeList *node_list;
     IXMLDOMNamedNodeMap *node_map;
-    long len;
+    LONG len;
 
     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
@@ -1769,7 +2313,7 @@ static void test_get_text(void)
 
     r = IXMLDOMNodeList_get_length( node_list, &len );
     ok( r == S_OK, "ret %08x\n", r );
-    ok( len == 1, "expect 1 got %ld\n", len );
+    ok( len == 1, "expect 1 got %d\n", len );
 
     r = IXMLDOMNodeList_get_item( node_list, 0, NULL );
     ok( r == E_INVALIDARG, "ret %08x\n", r );
@@ -1828,7 +2372,7 @@ static void test_get_childNodes(void)
     IXMLDOMElement *element;
     IXMLDOMNode *node, *node2;
     IXMLDOMNodeList *node_list, *node_list2;
-    long len;
+    LONG len;
 
     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
@@ -1849,7 +2393,7 @@ static void test_get_childNodes(void)
 
     r = IXMLDOMNodeList_get_length( node_list, &len );
     ok( r == S_OK, "ret %08x\n", r);
-    ok( len == 4, "len %ld\n", len);
+    ok( len == 4, "len %d\n", len);
 
     r = IXMLDOMNodeList_get_item( node_list, 2, &node );
     ok( r == S_OK, "ret %08x\n", r);
@@ -1859,7 +2403,7 @@ static void test_get_childNodes(void)
 
     r = IXMLDOMNodeList_get_length( node_list2, &len );
     ok( r == S_OK, "ret %08x\n", r);
-    ok( len == 0, "len %ld\n", len);
+    ok( len == 0, "len %d\n", len);
 
     r = IXMLDOMNodeList_get_item( node_list2, 0, &node2);
     ok( r == S_FALSE, "ret %08x\n", r);
@@ -1968,7 +2512,7 @@ static void test_replaceChild(void)
     IXMLDOMNode *fo_node, *ba_node, *lc_node, *removed_node, *temp_node;
     IXMLDOMNodeList *root_list, *fo_list;
     IUnknown * unk1, *unk2;
-    long len;
+    LONG len;
 
     r = CoCreateInstance( &CLSID_DOMDocument, NULL,
         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
@@ -2056,7 +2600,7 @@ static void test_replaceChild(void)
 
     r = IXMLDOMNodeList_get_length( fo_list, &len);
     ok( r == S_OK, "ret %08x\n", r );
-    ok( len == 0, "len %ld\n", len);
+    ok( len == 0, "len %d\n", len);
 
     IXMLDOMNodeList_Release( fo_list );
 
@@ -2077,7 +2621,7 @@ static void test_removeNamedItem(void)
     IXMLDOMNamedNodeMap * pr_attrs;
     VARIANT_BOOL b;
     BSTR str;
-    long len;
+    LONG len;
     HRESULT r;
 
     r = CoCreateInstance( &CLSID_DOMDocument, NULL,
@@ -2105,7 +2649,7 @@ static void test_removeNamedItem(void)
 
     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
     ok( r == S_OK, "ret %08x\n", r);
-    ok( len == 3, "length %ld\n", len);
+    ok( len == 3, "length %d\n", len);
 
     removed_node = (void*)0xdeadbeef;
     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, NULL, &removed_node);
@@ -2124,7 +2668,7 @@ static void test_removeNamedItem(void)
 
     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
     ok( r == S_OK, "ret %08x\n", r);
-    ok( len == 2, "length %ld\n", len);
+    ok( len == 2, "length %d\n", len);
 
     r = IXMLDOMNamedNodeMap_setNamedItem( pr_attrs, removed_node, NULL);
     ok ( r == S_OK, "ret %08x\n", r);
@@ -2132,14 +2676,14 @@ static void test_removeNamedItem(void)
 
     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
     ok( r == S_OK, "ret %08x\n", r);
-    ok( len == 3, "length %ld\n", len);
+    ok( len == 3, "length %d\n", len);
 
     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
     ok ( r == S_OK, "ret %08x\n", r);
 
     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
     ok( r == S_OK, "ret %08x\n", r);
-    ok( len == 2, "length %ld\n", len);
+    ok( len == 2, "length %d\n", len);
 
     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
     ok ( r == S_FALSE, "ret %08x\n", r);
@@ -2162,7 +2706,7 @@ static void test_XMLHTTP(void)
         'p','o','s','t','t','e','s','t','.','p','h','p',0};
     static const WCHAR wszExpectedResponse[] = {'F','A','I','L','E','D',0};
     IXMLHttpRequest *pXMLHttpRequest;
-    BSTR bstrResponse;
+    BSTR bstrResponse, str1, str2;
     VARIANT dummy;
     VARIANT varfalse;
     VARIANT varbody;
@@ -2182,8 +2726,12 @@ static void test_XMLHTTP(void)
     V_VT(&varbody) = VT_BSTR;
     V_BSTR(&varbody) = SysAllocString(wszBody);
 
-    hr = IXMLHttpRequest_open(pXMLHttpRequest, wszPOST, wszUrl, varfalse, dummy, dummy);
+    str1 = SysAllocString(wszPOST);
+    str2 = SysAllocString(wszUrl);
+    hr = IXMLHttpRequest_open(pXMLHttpRequest, str1, str2, varfalse, dummy, dummy);
     todo_wine ok(hr == S_OK, "IXMLHttpRequest_open should have succeeded instead of failing with 0x%08x\n", hr);
+    SysFreeString(str1);
+    SysFreeString(str2);
 
     hr = IXMLHttpRequest_send(pXMLHttpRequest, varbody);
     todo_wine ok(hr == S_OK, "IXMLHttpRequest_send should have succeeded instead of failing with 0x%08x\n", hr);
@@ -2400,8 +2948,8 @@ static void test_cloneNode(void )
     VARIANT_BOOL b;
     IXMLDOMNodeList *pList;
     IXMLDOMNamedNodeMap *mapAttr;
-    long nLength = 0, nLength1 = 0;
-    long nAttrCnt = 0, nAttrCnt1 = 0;
+    LONG nLength = 0, nLength1 = 0;
+    LONG nAttrCnt = 0, nAttrCnt1 = 0;
     IXMLDOMNode *node;
     IXMLDOMNode *node_clone;
     IXMLDOMNode *node_first;
@@ -2495,8 +3043,8 @@ static void test_cloneNode(void )
         IXMLDOMNamedNodeMap_Release(mapAttr);
     }
 
-    ok(nLength == nLength1, "wrong Child count (%ld, %ld)\n", nLength, nLength1);
-    ok(nAttrCnt == nAttrCnt1, "wrong Attribute count (%ld, %ld)\n", nAttrCnt, nAttrCnt1);
+    ok(nLength == nLength1, "wrong Child count (%d, %d)\n", nLength, nLength1);
+    ok(nAttrCnt == nAttrCnt1, "wrong Attribute count (%d, %d)\n", nAttrCnt, nAttrCnt1);
     IXMLDOMNode_Release(node_clone);
 
     /* No Children */
@@ -2530,7 +3078,7 @@ static void test_cloneNode(void )
     if (pList)
        {
                IXMLDOMNodeList_get_length(pList, &nLength1);
-        ok( nLength1 == 0, "Length should be 0 (%ld)\n", nLength1);
+        ok( nLength1 == 0, "Length should be 0 (%d)\n", nLength1);
                IXMLDOMNodeList_Release(pList);
        }
 
@@ -2539,12 +3087,12 @@ static void test_cloneNode(void )
     if(mapAttr)
     {
         IXMLDOMNamedNodeMap_get_length(mapAttr, &nAttrCnt1);
-        ok( nAttrCnt1 == 3, "Attribute count should be 3 (%ld)\n", nAttrCnt1);
+        ok( nAttrCnt1 == 3, "Attribute count should be 3 (%d)\n", nAttrCnt1);
         IXMLDOMNamedNodeMap_Release(mapAttr);
     }
 
-    ok(nLength != nLength1, "wrong Child count (%ld, %ld)\n", nLength, nLength1);
-    ok(nAttrCnt == nAttrCnt1, "wrong Attribute count (%ld, %ld)\n", nAttrCnt, nAttrCnt1);
+    ok(nLength != nLength1, "wrong Child count (%d, %d)\n", nLength, nLength1);
+    ok(nAttrCnt == nAttrCnt1, "wrong Attribute count (%d, %d)\n", nAttrCnt, nAttrCnt1);
     IXMLDOMNode_Release(node_clone);
 
 
@@ -2559,7 +3107,7 @@ static void test_xmlTypes(void)
     HRESULT hr;
     IXMLDOMComment *pComment;
     IXMLDOMElement *pElement;
-    IXMLDOMAttribute *pAttrubute;
+    IXMLDOMAttribute *pAttribute;
     IXMLDOMNamedNodeMap *pAttribs;
     IXMLDOMCDATASection *pCDataSec;
     IXMLDOMImplementation *pIXMLDOMImplementation = NULL;
@@ -2568,7 +3116,7 @@ static void test_xmlTypes(void)
     BSTR str;
     IXMLDOMNode *pNextChild = (IXMLDOMNode *)0x1;   /* Used for testing Siblings */
     VARIANT v;
-    long len = 0;
+    LONG len = 0;
 
     hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (LPVOID*)&doc );
     if( hr != S_OK )
@@ -2664,7 +3212,15 @@ static void test_xmlTypes(void)
         IXMLDOMImplementation_Release(pIXMLDOMImplementation);
     }
 
+    pRoot = (IXMLDOMElement*)0x1;
+    hr = IXMLDOMDocument_createElement(doc, NULL, &pRoot);
+    ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+    ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
 
+    pRoot = (IXMLDOMElement*)0x1;
+    hr = IXMLDOMDocument_createElement(doc, _bstr_(""), &pRoot);
+    ok(hr == E_FAIL, "ret %08x\n", hr );
+    ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
 
     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &pRoot);
     ok(hr == S_OK, "ret %08x\n", hr );
@@ -2675,7 +3231,9 @@ static void test_xmlTypes(void)
         if(hr == S_OK)
         {
             /* Comment */
-            hr = IXMLDOMDocument_createComment(doc, szComment, &pComment);
+            str = SysAllocString(szComment);
+            hr = IXMLDOMDocument_createComment(doc, str, &pComment);
+            SysFreeString(str);
             ok(hr == S_OK, "ret %08x\n", hr );
             if(hr == S_OK)
             {
@@ -2744,7 +3302,7 @@ static void test_xmlTypes(void)
                 /* test length property */
                 hr = IXMLDOMComment_get_length(pComment, &len);
                 ok(hr == S_OK, "ret %08x\n", hr );
-                ok(len == 21, "expected 21 got %ld\n", len);
+                ok(len == 21, "expected 21 got %d\n", len);
 
                 /* test substringData */
                 hr = IXMLDOMComment_substringData(pComment, 0, 4, NULL);
@@ -2848,119 +3406,274 @@ static void test_xmlTypes(void)
                 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string\n");
                 SysFreeString(str);
 
-                IXMLDOMComment_Release(pComment);
-            }
+                /* delete data */
+                /* invalid arguments */
+                hr = IXMLDOMComment_deleteData(pComment, -1, 1);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
 
-            /* Element */
-            hr = IXMLDOMDocument_createElement(doc, szElement, &pElement);
-            ok(hr == S_OK, "ret %08x\n", hr );
-            if(hr == S_OK)
-            {
-                hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL);
+                hr = IXMLDOMComment_deleteData(pComment, 0, 0);
                 ok(hr == S_OK, "ret %08x\n", hr );
 
-                /* test nodeTypeString */
-                hr = IXMLDOMDocument_get_nodeTypeString(pElement, &str);
-                ok(hr == S_OK, "ret %08x\n", hr );
-                ok( !lstrcmpW( str, _bstr_("element") ), "incorrect nodeTypeString string\n");
-                SysFreeString(str);
+                hr = IXMLDOMComment_deleteData(pComment, 0, -1);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
 
-                hr = IXMLDOMElement_get_nodeName(pElement, &str);
+                hr = IXMLDOMComment_get_length(pComment, &len);
                 ok(hr == S_OK, "ret %08x\n", hr );
-                ok( !lstrcmpW( str, szElement ), "incorrect element node Name\n");
-                SysFreeString(str);
+                ok(len == 43, "expected 43 got %d\n", len);
 
-                hr = IXMLDOMElement_get_xml(pElement, &str);
+                hr = IXMLDOMComment_deleteData(pComment, len, 1);
                 ok(hr == S_OK, "ret %08x\n", hr );
-                ok( !lstrcmpW( str, szElementXML ), "incorrect element xml\n");
-                SysFreeString(str);
 
-                hr = IXMLDOMElement_get_dataType(pElement, &v);
-                ok(hr == S_FALSE, "ret %08x\n", hr );
-                ok( V_VT(&v) == VT_NULL, "incorrect dataType type\n");
-                VariantClear(&v);
+                hr = IXMLDOMComment_deleteData(pComment, len+1, 1);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
 
-                 /* Attribute */
-                hr = IXMLDOMDocument_createAttribute(doc, szAttribute, &pAttrubute);
+                /* delete from start */
+                hr = IXMLDOMComment_deleteData(pComment, 0, 5);
                 ok(hr == S_OK, "ret %08x\n", hr );
-                if(hr == S_OK)
-                {
-                    IXMLDOMNode *pNewChild = (IXMLDOMNode *)0x1;
 
-                    hr = IXMLDOMAttribute_get_nextSibling(pAttrubute, NULL);
-                    ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_length(pComment, &len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok(len == 38, "expected 38 got %d\n", len);
 
-                    pNextChild = (IXMLDOMNode *)0x1;
-                    hr = IXMLDOMAttribute_get_nextSibling(pAttrubute, &pNextChild);
-                    ok(hr == S_FALSE, "ret %08x\n", hr );
-                    ok(pNextChild == NULL, "pNextChild not NULL\n");
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string\n");
+                SysFreeString(str);
 
-                    /* test Previous Sibling*/
-                    hr = IXMLDOMAttribute_get_previousSibling(pAttrubute, NULL);
-                    ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+                /* delete from end */
+                hr = IXMLDOMComment_deleteData(pComment, 35, 3);
+                ok(hr == S_OK, "ret %08x\n", hr );
 
-                    pNextChild = (IXMLDOMNode *)0x1;
-                    hr = IXMLDOMAttribute_get_previousSibling(pAttrubute, &pNextChild);
-                    ok(hr == S_FALSE, "ret %08x\n", hr );
-                    ok(pNextChild == NULL, "pNextChild not NULL\n");
+                hr = IXMLDOMComment_get_length(pComment, &len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok(len == 35, "expected 35 got %d\n", len);
 
-                    /* test get_attributes */
-                    hr = IXMLDOMAttribute_get_attributes( pAttrubute, NULL );
-                    ok( hr == E_INVALIDARG, "get_attributes returned wrong code\n");
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string\n");
+                SysFreeString(str);
 
-                    pAttribs = (IXMLDOMNamedNodeMap*)0x1;
-                    hr = IXMLDOMAttribute_get_attributes( pAttrubute, &pAttribs);
-                    ok(hr == S_FALSE, "ret %08x\n", hr );
-                    ok( pAttribs == NULL, "pAttribs not NULL\n");
+                /* delete from inside */
+                hr = IXMLDOMComment_deleteData(pComment, 1, 33);
+                ok(hr == S_OK, "ret %08x\n", hr );
 
-                    hr = IXMLDOMElement_appendChild(pElement, (IXMLDOMNode*)pAttrubute, &pNewChild);
-                    ok(hr == E_FAIL, "ret %08x\n", hr );
-                    ok(pNewChild == NULL, "pNewChild not NULL\n");
+                hr = IXMLDOMComment_get_length(pComment, &len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok(len == 2, "expected 2 got %d\n", len);
 
-                    hr = IXMLDOMElement_get_attributes(pElement, &pAttribs);
-                    ok(hr == S_OK, "ret %08x\n", hr );
-                    if ( hr == S_OK )
-                    {
-                        hr = IXMLDOMNamedNodeMap_setNamedItem(pAttribs, (IXMLDOMNode*)pAttrubute, NULL );
-                        ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("  ") ), "incorrect get_text string\n");
+                SysFreeString(str);
 
-                        IXMLDOMNamedNodeMap_Release(pAttribs);
-                    }
+                /* delete whole data ... */
+                hr = IXMLDOMComment_get_length(pComment, &len);
+                ok(hr == S_OK, "ret %08x\n", hr );
 
-                    hr = IXMLDOMAttribute_get_nodeName(pAttrubute, &str);
-                    ok(hr == S_OK, "ret %08x\n", hr );
-                    ok( !lstrcmpW( str, szAttribute ), "incorrect attribute node Name\n");
+                hr = IXMLDOMComment_deleteData(pComment, 0, len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                /* ... and try again with empty string */
+                hr = IXMLDOMComment_deleteData(pComment, 0, len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                /* ::replaceData() */
+                V_VT(&v) = VT_BSTR;
+                V_BSTR(&v) = SysAllocString(szstr1);
+                hr = IXMLDOMComment_put_nodeValue(pComment, v);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                VariantClear(&v);
+
+                hr = IXMLDOMComment_replaceData(pComment, 6, 0, NULL);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                hr = IXMLDOMComment_replaceData(pComment, 0, 0, NULL);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* NULL pointer means delete */
+                hr = IXMLDOMComment_replaceData(pComment, 0, 1, NULL);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* empty string means delete */
+                hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_(""));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* zero count means insert */
+                hr = IXMLDOMComment_replaceData(pComment, 0, 0, _bstr_("a"));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                hr = IXMLDOMComment_replaceData(pComment, 0, 2, NULL);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                hr = IXMLDOMComment_insertData(pComment, 0, _bstr_("m"));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* nonempty string, count greater than its length */
+                hr = IXMLDOMComment_replaceData(pComment, 0, 2, _bstr_("a1.2"));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* nonempty string, count less than its length */
+                hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_("wine"));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMComment_get_text(pComment, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                IXMLDOMComment_Release(pComment);
+            }
+
+            /* Element */
+            str = SysAllocString(szElement);
+            hr = IXMLDOMDocument_createElement(doc, str, &pElement);
+            SysFreeString(str);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            if(hr == S_OK)
+            {
+                hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                /* test nodeTypeString */
+                hr = IXMLDOMDocument_get_nodeTypeString(pElement, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("element") ), "incorrect nodeTypeString string\n");
+                SysFreeString(str);
+
+                hr = IXMLDOMElement_get_nodeName(pElement, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, szElement ), "incorrect element node Name\n");
+                SysFreeString(str);
+
+                hr = IXMLDOMElement_get_xml(pElement, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, szElementXML ), "incorrect element xml\n");
+                SysFreeString(str);
+
+                hr = IXMLDOMElement_get_dataType(pElement, &v);
+                ok(hr == S_FALSE, "ret %08x\n", hr );
+                ok( V_VT(&v) == VT_NULL, "incorrect dataType type\n");
+                VariantClear(&v);
+
+                /* Attribute */
+                pAttribute = (IXMLDOMAttribute*)0x1;
+                hr = IXMLDOMDocument_createAttribute(doc, NULL, &pAttribute);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+                ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
+
+                pAttribute = (IXMLDOMAttribute*)0x1;
+                hr = IXMLDOMDocument_createAttribute(doc, _bstr_(""), &pAttribute);
+                ok(hr == E_FAIL, "ret %08x\n", hr );
+                ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
+
+                str = SysAllocString(szAttribute);
+                hr = IXMLDOMDocument_createAttribute(doc, str, &pAttribute);
+                SysFreeString(str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                if(hr == S_OK)
+                {
+                    IXMLDOMNode *pNewChild = (IXMLDOMNode *)0x1;
+
+                    hr = IXMLDOMAttribute_get_nextSibling(pAttribute, NULL);
+                    ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+
+                    pNextChild = (IXMLDOMNode *)0x1;
+                    hr = IXMLDOMAttribute_get_nextSibling(pAttribute, &pNextChild);
+                    ok(hr == S_FALSE, "ret %08x\n", hr );
+                    ok(pNextChild == NULL, "pNextChild not NULL\n");
+
+                    /* test Previous Sibling*/
+                    hr = IXMLDOMAttribute_get_previousSibling(pAttribute, NULL);
+                    ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+
+                    pNextChild = (IXMLDOMNode *)0x1;
+                    hr = IXMLDOMAttribute_get_previousSibling(pAttribute, &pNextChild);
+                    ok(hr == S_FALSE, "ret %08x\n", hr );
+                    ok(pNextChild == NULL, "pNextChild not NULL\n");
+
+                    /* test get_attributes */
+                    hr = IXMLDOMAttribute_get_attributes( pAttribute, NULL );
+                    ok( hr == E_INVALIDARG, "get_attributes returned wrong code\n");
+
+                    pAttribs = (IXMLDOMNamedNodeMap*)0x1;
+                    hr = IXMLDOMAttribute_get_attributes( pAttribute, &pAttribs);
+                    ok(hr == S_FALSE, "ret %08x\n", hr );
+                    ok( pAttribs == NULL, "pAttribs not NULL\n");
+
+                    hr = IXMLDOMElement_appendChild(pElement, (IXMLDOMNode*)pAttribute, &pNewChild);
+                    ok(hr == E_FAIL, "ret %08x\n", hr );
+                    ok(pNewChild == NULL, "pNewChild not NULL\n");
+
+                    hr = IXMLDOMElement_get_attributes(pElement, &pAttribs);
+                    ok(hr == S_OK, "ret %08x\n", hr );
+                    if ( hr == S_OK )
+                    {
+                        hr = IXMLDOMNamedNodeMap_setNamedItem(pAttribs, (IXMLDOMNode*)pAttribute, NULL );
+                        ok(hr == S_OK, "ret %08x\n", hr );
+
+                        IXMLDOMNamedNodeMap_Release(pAttribs);
+                    }
+
+                    hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
+                    ok(hr == S_OK, "ret %08x\n", hr );
+                    ok( !lstrcmpW( str, szAttribute ), "incorrect attribute node Name\n");
                     SysFreeString(str);
 
                     /* test nodeTypeString */
-                    hr = IXMLDOMAttribute_get_nodeTypeString(pAttrubute, &str);
+                    hr = IXMLDOMAttribute_get_nodeTypeString(pAttribute, &str);
                     ok(hr == S_OK, "ret %08x\n", hr );
                     ok( !lstrcmpW( str, _bstr_("attribute") ), "incorrect nodeTypeString string\n");
                     SysFreeString(str);
 
                     /* test nodeName */
-                    hr = IXMLDOMAttribute_get_nodeName(pAttrubute, &str);
+                    hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
                     ok(hr == S_OK, "ret %08x\n", hr );
                     ok( !lstrcmpW( str, szAttribute ), "incorrect nodeName string\n");
                     SysFreeString(str);
 
                     /* test name property */
-                    hr = IXMLDOMAttribute_get_name(pAttrubute, &str);
+                    hr = IXMLDOMAttribute_get_name(pAttribute, &str);
                     ok(hr == S_OK, "ret %08x\n", hr );
                     ok( !lstrcmpW( str, szAttribute ), "incorrect name string\n");
                     SysFreeString(str);
 
-                    hr = IXMLDOMAttribute_get_xml(pAttrubute, &str);
+                    hr = IXMLDOMAttribute_get_xml(pAttribute, &str);
                     ok(hr == S_OK, "ret %08x\n", hr );
                     ok( !lstrcmpW( str, szAttributeXML ), "incorrect attribute xml\n");
                     SysFreeString(str);
 
-                    hr = IXMLDOMAttribute_get_dataType(pAttrubute, &v);
+                    hr = IXMLDOMAttribute_get_dataType(pAttribute, &v);
                     ok(hr == S_FALSE, "ret %08x\n", hr );
                     ok( V_VT(&v) == VT_NULL, "incorrect dataType type\n");
                     VariantClear(&v);
 
-                    IXMLDOMAttribute_Release(pAttrubute);
+                    IXMLDOMAttribute_Release(pAttribute);
 
                     /* Check Element again with the Add Attribute*/
                     hr = IXMLDOMElement_get_xml(pElement, &str);
@@ -2997,16 +3710,20 @@ static void test_xmlTypes(void)
             }
 
             /* CData Section */
-            hr = IXMLDOMDocument_createCDATASection(doc, szCData, NULL);
+            str = SysAllocString(szCData);
+            hr = IXMLDOMDocument_createCDATASection(doc, str, NULL);
             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
 
-            hr = IXMLDOMDocument_createCDATASection(doc, szCData, &pCDataSec);
+            hr = IXMLDOMDocument_createCDATASection(doc, str, &pCDataSec);
+            SysFreeString(str);
             ok(hr == S_OK, "ret %08x\n", hr );
             if(hr == S_OK)
             {
                 IXMLDOMNode *pNextChild = (IXMLDOMNode *)0x1;
                 VARIANT var;
 
+                VariantInit(&var);
+
                 hr = IXMLDOMCDATASection_QueryInterface(pCDataSec, &IID_IXMLDOMElement, (LPVOID*)&pElement);
                 ok(hr == E_NOINTERFACE, "ret %08x\n", hr);
 
@@ -3072,12 +3789,13 @@ static void test_xmlTypes(void)
                 /* test length property */
                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
                 ok(hr == S_OK, "ret %08x\n", hr );
-                ok(len == 21, "expected 21 got %ld\n", len);
+                ok(len == 21, "expected 21 got %d\n", len);
 
                 /* test get nodeValue */
                 hr = IXMLDOMCDATASection_get_nodeValue(pCDataSec, &var);
                 ok(hr == S_OK, "ret %08x\n", hr );
-                ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
+                ok(V_VT(&var) == VT_BSTR, "got vt %04x\n", V_VT(&var));
+                ok( !lstrcmpW( V_BSTR(&var), _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
                 VariantClear(&var);
 
                 /* test get data */
@@ -3188,6 +3906,148 @@ static void test_xmlTypes(void)
                 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string\n");
                 SysFreeString(str);
 
+                /* delete data */
+                /* invalid arguments */
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, -1, 1);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 0);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, -1);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+
+                hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok(len == 43, "expected 43 got %d\n", len);
+
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, len, 1);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, len+1, 1);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+
+                /* delete from start */
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 5);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok(len == 38, "expected 38 got %d\n", len);
+
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* delete from end */
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, 35, 3);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok(len == 35, "expected 35 got %d\n", len);
+
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* delete from inside */
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, 1, 33);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok(len == 2, "expected 2 got %d\n", len);
+
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("  ") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* delete whole data ... */
+                hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                /* ... and try again with empty string */
+                hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                /* ::replaceData() */
+                V_VT(&v) = VT_BSTR;
+                V_BSTR(&v) = SysAllocString(szstr1);
+                hr = IXMLDOMCDATASection_put_nodeValue(pCDataSec, v);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                VariantClear(&v);
+
+                hr = IXMLDOMCDATASection_replaceData(pCDataSec, 6, 0, NULL);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, NULL);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* NULL pointer means delete */
+                hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, NULL);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* empty string means delete */
+                hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_(""));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* zero count means insert */
+                hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, _bstr_("a"));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, NULL);
+                ok(hr == S_OK, "ret %08x\n", hr );
+
+                hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, _bstr_("m"));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* nonempty string, count greater than its length */
+                hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, _bstr_("a1.2"));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
+                /* nonempty string, count less than its length */
+                hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_("wine"));
+                ok(hr == S_OK, "ret %08x\n", hr );
+                hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string\n");
+                SysFreeString(str);
+
                 IXMLDOMCDATASection_Release(pCDataSec);
             }
 
@@ -3199,7 +4059,15 @@ static void test_xmlTypes(void)
             ok(hr == S_OK, "ret %08x\n", hr );
             if(hr == S_OK)
             {
-                IXMLDOMNode *pNextChild = (IXMLDOMNode *)0x1;
+                IXMLDOMNode *node;
+
+                hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, NULL);
+                ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+
+                node = (IXMLDOMNode *)0x1;
+                hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, &node);
+                ok(hr == S_FALSE, "ret %08x\n", hr );
+                ok(node == NULL, "expected NULL, got %p\n", node);
 
                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pDocFrag, NULL);
                 ok(hr == S_OK, "ret %08x\n", hr );
@@ -3222,19 +4090,19 @@ static void test_xmlTypes(void)
                 hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, NULL);
                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
 
-                pNextChild = (IXMLDOMNode *)0x1;
-                hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, &pNextChild);
+                node = (IXMLDOMNode *)0x1;
+                hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, &node);
                 ok(hr == S_FALSE, "ret %08x\n", hr );
-                ok(pNextChild == NULL, "pNextChild not NULL\n");
+                ok(node == NULL, "next sibling not NULL\n");
 
                 /* test Previous Sibling*/
                 hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, NULL);
                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
 
-                pNextChild = (IXMLDOMNode *)0x1;
-                hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, &pNextChild);
+                node = (IXMLDOMNode *)0x1;
+                hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, &node);
                 ok(hr == S_FALSE, "ret %08x\n", hr );
-                ok(pNextChild == NULL, "pNextChild not NULL\n");
+                ok(node == NULL, "previous sibling not NULL\n");
 
                 /* test get_dataType */
                 hr = IXMLDOMDocumentFragment_get_dataType(pDocFrag, NULL);
@@ -3255,10 +4123,17 @@ static void test_xmlTypes(void)
             }
 
             /* Entity References */
-            hr = IXMLDOMDocument_createEntityReference(doc, szEntityRef, NULL);
+            hr = IXMLDOMDocument_createEntityReference(doc, NULL, &pEntityRef);
+            ok(hr == E_FAIL, "ret %08x\n", hr );
+            hr = IXMLDOMDocument_createEntityReference(doc, _bstr_(""), &pEntityRef);
+            ok(hr == E_FAIL, "ret %08x\n", hr );
+
+            str = SysAllocString(szEntityRef);
+            hr = IXMLDOMDocument_createEntityReference(doc, str, NULL);
             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
 
-            hr = IXMLDOMDocument_createEntityReference(doc, szEntityRef, &pEntityRef);
+            hr = IXMLDOMDocument_createEntityReference(doc, str, &pEntityRef);
+            SysFreeString(str);
             ok(hr == S_OK, "ret %08x\n", hr );
             if(hr == S_OK)
             {
@@ -3315,6 +4190,9 @@ static void test_nodeTypeTests( void )
     if( hr != S_OK )
         return;
 
+    hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), NULL);
+    ok(hr == E_INVALIDARG, "ret %08x\n", hr );
+
     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &pRoot);
     ok(hr == S_OK, "ret %08x\n", hr );
     if(hr == S_OK)
@@ -3921,7 +4799,7 @@ static void test_NodeTypeValue(void)
         hr = IXMLDOMDocument2_get_nodeTypedValue(doc, &v);
         ok(hr == S_FALSE, "ret %08x\n", hr );
 
-        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("string"), &pNode);
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/string"), &pNode);
         ok(hr == S_OK, "ret %08x\n", hr );
         if(hr == S_OK)
         {
@@ -3936,16 +4814,624 @@ static void test_NodeTypeValue(void)
 
             hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
             ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_BSTR, "incorrect type\n");
             ok(!lstrcmpW( V_BSTR(&v), _bstr_("Wine") ), "incorrect value\n");
             VariantClear( &v );
 
             IXMLDOMNode_Release(pNode);
         }
-    }
 
-    IXMLDOMDocument2_Release(doc);
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/string2"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_BSTR, "incorrect type\n");
+            ok(!lstrcmpW( V_BSTR(&v), _bstr_("String") ), "incorrect value\n");
+            VariantClear( &v );
 
-    free_bstrs();
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/number"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_BSTR, "incorrect type\n");
+            ok(!lstrcmpW( V_BSTR(&v), _bstr_("12.44") ), "incorrect value\n");
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/number2"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_BSTR, "incorrect type\n");
+            ok(!lstrcmpW( V_BSTR(&v), _bstr_("-3.71e3") ), "incorrect value\n");
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/int"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_I4, "incorrect type\n");
+            ok(V_I4(&v) == -13, "incorrect value\n");
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/fixed"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_CY, "incorrect type\n");
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/bool"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_BOOL, "incorrect type\n");
+            ok(V_BOOL(&v) == VARIANT_TRUE, "incorrect value\n");
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/datetime"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_DATE, "incorrect type\n");
+            double_eq(40135.13996527778, V_DATE(&v));
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/datetimetz"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_DATE, "incorrect type\n");
+            double_eq(37813.59302083334, V_DATE(&v));
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/date"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_DATE, "incorrect type\n");
+            double_eq(665413.0, V_DATE(&v));
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/time"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_DATE, "incorrect type\n");
+            double_eq(0.5813888888888888, V_DATE(&v));
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/timetz"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_DATE, "incorrect type\n");
+            double_eq(1.112511574074074, V_DATE(&v));
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/i1"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_I1, "incorrect type\n");
+            ok(V_I1(&v) == -13, "incorrect value\n");
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/i2"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_I2, "incorrect type\n");
+            ok(V_I2(&v) == 31915, "incorrect value\n");
+            VariantClear( &v );
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/i4"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_I4, "incorrect type\n");
+            ok(V_I4(&v) == -312232, "incorrect value\n");
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/ui1"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_UI1, "incorrect type\n");
+            ok(V_UI1(&v) == 123, "incorrect value\n");
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/ui2"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_UI2, "incorrect type\n");
+            ok(V_UI2(&v) == 48282, "incorrect value\n");
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/ui4"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_UI4, "incorrect type\n");
+            ok(V_UI4(&v) == 949281, "incorrect value\n");
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/r4"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_R4, "incorrect type\n");
+            double_eq(213124.0, V_R4(&v));
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/r8"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_R8, "incorrect type\n");
+            double_eq(0.412, V_R8(&v));
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/float"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_R8, "incorrect type\n");
+            double_eq(41221.421, V_R8(&v));
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/uuid"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == VT_BSTR, "incorrect type\n");
+            ok(!lstrcmpW(V_BSTR(&v), _bstr_("333C7BC4-460F-11D0-BC04-0080C7055a83")), "incorrect value\n");
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/binhex"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            BYTE bytes[] = {0xff,0xfc,0xa0,0x12,0x00,0x3c};
+
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == (VT_ARRAY|VT_UI1), "incorrect type\n");
+            ok(V_ARRAY(&v)->rgsabound[0].cElements == 6, "incorrect array size\n");
+            if(V_ARRAY(&v)->rgsabound[0].cElements == 6)
+                ok(!memcmp(bytes, V_ARRAY(&v)->pvData, sizeof(bytes)), "incorrect value\n");
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+
+        hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/binbase64"), &pNode);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        if(hr == S_OK)
+        {
+            BYTE bytes[] = {0x62,0x61,0x73,0x65,0x36,0x34,0x20,0x74,0x65,0x73,0x74};
+
+            hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v);
+            ok(hr == S_OK, "ret %08x\n", hr );
+            ok(V_VT(&v) == (VT_ARRAY|VT_UI1), "incorrect type\n");
+            ok(V_ARRAY(&v)->rgsabound[0].cElements == 11, "incorrect array size\n");
+            if(V_ARRAY(&v)->rgsabound[0].cElements == 11)
+                ok(!memcmp(bytes, V_ARRAY(&v)->pvData, sizeof(bytes)), "incorrect value\n");
+            VariantClear(&v);
+
+            IXMLDOMNode_Release(pNode);
+        }
+    }
+
+    IXMLDOMDocument2_Release(doc);
+
+    free_bstrs();
+}
+
+static void test_TransformWithLoadingLocalFile(void)
+{
+    IXMLDOMDocument2 *doc = NULL;
+    IXMLDOMDocument2 *xsl = NULL;
+    IXMLDOMNode *pNode;
+    VARIANT_BOOL bSucc;
+    HRESULT hr;
+    HANDLE file;
+    DWORD dwWritten;
+    char lpPathBuffer[MAX_PATH];
+    int i;
+
+    /* Create a Temp File. */
+    GetTempPathA(MAX_PATH, lpPathBuffer);
+    strcat(lpPathBuffer, "customers.xml" );
+
+    file = CreateFile(lpPathBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
+    ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
+    if(file == INVALID_HANDLE_VALUE)
+        return;
+
+    WriteFile(file, szBasicTransformXML, strlen(szBasicTransformXML), &dwWritten, NULL);
+    CloseHandle(file);
+
+    /* Correct path to not include a escape character. */
+    for(i=0; i < strlen(lpPathBuffer); i++)
+    {
+        if(lpPathBuffer[i] == '\\')
+            lpPathBuffer[i] = '/';
+    }
+
+    hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (LPVOID*)&doc );
+    if( hr != S_OK )
+        return;
+
+    hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (LPVOID*)&xsl );
+    if( hr != S_OK )
+    {
+        IXMLDOMDocument2_Release(doc);
+        return;
+    }
+
+    hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szTypeValueXML), &bSucc);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
+    if(bSucc == VARIANT_TRUE)
+    {
+        BSTR sXSL;
+        BSTR sPart1 = _bstr_(szBasicTransformSSXMLPart1);
+        BSTR sPart2 = _bstr_(szBasicTransformSSXMLPart2);
+        BSTR sFileName = _bstr_(lpPathBuffer);
+        int nLegnth = lstrlenW(sPart1) + lstrlenW(sPart2) + lstrlenW(sFileName) + 1;
+
+        sXSL = SysAllocStringLen(NULL, nLegnth);
+        lstrcpyW(sXSL, sPart1);
+        lstrcatW(sXSL, sFileName);
+        lstrcatW(sXSL, sPart2);
+
+        hr = IXMLDOMDocument2_loadXML(xsl, sXSL, &bSucc);
+        ok(hr == S_OK, "ret %08x\n", hr );
+        ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
+        if(bSucc == VARIANT_TRUE)
+        {
+            BSTR sResult;
+
+            hr = IXMLDOMDocument_QueryInterface(xsl, &IID_IXMLDOMNode, (LPVOID*)&pNode );
+            ok(hr == S_OK, "ret %08x\n", hr );
+            if(hr == S_OK)
+            {
+                /* This will load the temp file via the XSL */
+                hr = IXMLDOMDocument2_transformNode(doc, pNode, &sResult);
+                ok(hr == S_OK, "ret %08x\n", hr );
+                if(hr == S_OK)
+                {
+                    ok( compareIgnoreReturns( sResult, _bstr_(szBasicTransformOutput)), "Stylesheet output not correct\n");
+                    SysFreeString(sResult);
+                }
+
+                IXMLDOMNode_Release(pNode);
+            }
+        }
+
+        SysFreeString(sXSL);
+    }
+
+    IXMLDOMDocument2_Release(doc);
+    IXMLDOMDocument2_Release(xsl);
+
+    DeleteFile(lpPathBuffer);
+    free_bstrs();
+}
+
+static void test_put_nodeValue(void)
+{
+    IXMLDOMDocument *doc;
+    IXMLDOMEntityReference *entityref;
+    IXMLDOMNode *node;
+    HRESULT hr;
+    VARIANT data, type;
+
+    hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
+    if( hr != S_OK )
+        return;
+
+    /* test for unsupported types */
+    /* NODE_DOCUMENT */
+    hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&node);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    V_VT(&data) = VT_BSTR;
+    V_BSTR(&data) = _bstr_("one two three");
+    hr = IXMLDOMNode_put_nodeValue(node, data);
+    ok(hr == E_FAIL, "ret %08x\n", hr );
+    IXMLDOMNode_Release(node);
+
+    /* NODE_DOCUMENT_FRAGMENT */
+    V_VT(&type) = VT_I1;
+    V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
+    hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    V_VT(&data) = VT_BSTR;
+    V_BSTR(&data) = _bstr_("one two three");
+    hr = IXMLDOMNode_put_nodeValue(node, data);
+    ok(hr == E_FAIL, "ret %08x\n", hr );
+    IXMLDOMNode_Release(node);
+
+    /* NODE_ELEMENT */
+    V_VT(&type) = VT_I1;
+    V_I1(&type) = NODE_ELEMENT;
+    hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    V_VT(&data) = VT_BSTR;
+    V_BSTR(&data) = _bstr_("one two three");
+    hr = IXMLDOMNode_put_nodeValue(node, data);
+    ok(hr == E_FAIL, "ret %08x\n", hr );
+    IXMLDOMNode_Release(node);
+
+    /* NODE_ENTITY_REFERENCE */
+    hr = IXMLDOMDocument_createEntityReference(doc, _bstr_("ref"), &entityref);
+    ok(hr == S_OK, "ret %08x\n", hr );
+
+    V_VT(&data) = VT_BSTR;
+    V_BSTR(&data) = _bstr_("one two three");
+    hr = IXMLDOMEntityReference_put_nodeValue(entityref, data);
+    ok(hr == E_FAIL, "ret %08x\n", hr );
+
+    hr = IXMLDOMEntityReference_QueryInterface(entityref, &IID_IXMLDOMNode, (void**)&node);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    V_VT(&data) = VT_BSTR;
+    V_BSTR(&data) = _bstr_("one two three");
+    hr = IXMLDOMNode_put_nodeValue(node, data);
+    ok(hr == E_FAIL, "ret %08x\n", hr );
+    IXMLDOMNode_Release(node);
+    IXMLDOMEntityReference_Release(entityref);
+
+    free_bstrs();
+
+    IXMLDOMDocument_Release(doc);
+}
+
+static void test_IObjectSafety_set(IObjectSafety *safety, HRESULT result, HRESULT result2, DWORD set, DWORD mask, DWORD expected, DWORD expected2)
+{
+    HRESULT hr;
+    DWORD enabled, supported;
+
+    trace("testing IObjectSafety: enable=%08x, mask=%08x\n", set, mask);
+
+    hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL, set, mask);
+    if (result == result2)
+        ok(hr == result, "SetInterfaceSafetyOptions: expected %08x, returned %08x\n", result, hr );
+    else
+        ok(broken(hr == result) || hr == result2,
+           "SetInterfaceSafetyOptions: expected %08x, got %08x\n", result2, hr );
+
+    supported = enabled = 0xCAFECAFE;
+    hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    if (expected == expected2)
+        ok(enabled == expected, "Expected %08x, got %08x\n", expected, enabled);
+    else
+        ok(broken(enabled == expected) || enabled == expected2,
+           "Expected %08x, got %08x\n", expected2, enabled);
+
+    /* reset the safety options */
+
+    hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
+            INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER,
+            0);
+    ok(hr == S_OK, "ret %08x\n", hr );
+
+    hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    ok(enabled == 0, "Expected 0, got %08x\n", enabled);
+}
+
+static void test_document_IObjectSafety(void)
+{
+    IXMLDOMDocument *doc;
+    IObjectSafety *safety;
+    DWORD enabled = 0, supported = 0;
+    HRESULT hr;
+
+    hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
+    if( hr != S_OK )
+        return;
+
+    hr = IXMLDOMDocument_QueryInterface(doc, &IID_IObjectSafety, (void**)&safety);
+    ok(hr == S_OK, "ret %08x\n", hr );
+
+    /* get */
+    hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, NULL, &enabled);
+    ok(hr == E_POINTER, "ret %08x\n", hr );
+    hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, NULL);
+    ok(hr == E_POINTER, "ret %08x\n", hr );
+
+    hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    ok(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
+       supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
+        "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
+             "got %08x\n", supported);
+    ok(enabled == 0, "Expected 0, got %08x\n", enabled);
+
+    /* set -- individual flags */
+
+    test_IObjectSafety_set(safety, S_OK, S_OK,
+        INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER,
+        INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER);
+
+    test_IObjectSafety_set(safety, S_OK, S_OK,
+        INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA,
+        INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA);
+
+    test_IObjectSafety_set(safety, S_OK, S_OK,
+        INTERFACE_USES_SECURITY_MANAGER, INTERFACE_USES_SECURITY_MANAGER,
+        0, INTERFACE_USES_SECURITY_MANAGER /* msxml3 SP8+ */);
+
+    /* set INTERFACE_USES_DISPEX  */
+
+    test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
+        INTERFACE_USES_DISPEX, INTERFACE_USES_DISPEX,
+        0, 0);
+
+    test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
+        INTERFACE_USES_DISPEX, 0,
+        0, 0);
+
+    test_IObjectSafety_set(safety, S_OK, S_OK /* msxml3 SP8+ */,
+        0, INTERFACE_USES_DISPEX,
+        0, 0);
+
+    /* set option masking */
+
+    test_IObjectSafety_set(safety, S_OK, S_OK,
+        INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
+        INTERFACESAFE_FOR_UNTRUSTED_CALLER,
+        INTERFACESAFE_FOR_UNTRUSTED_CALLER,
+        INTERFACESAFE_FOR_UNTRUSTED_CALLER);
+
+    test_IObjectSafety_set(safety, S_OK, S_OK,
+        INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
+        INTERFACESAFE_FOR_UNTRUSTED_DATA,
+        INTERFACESAFE_FOR_UNTRUSTED_DATA,
+        INTERFACESAFE_FOR_UNTRUSTED_DATA);
+
+    test_IObjectSafety_set(safety, S_OK, S_OK,
+        INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
+        INTERFACE_USES_SECURITY_MANAGER,
+        0,
+        0);
+
+    /* set -- inheriting previous settings */
+
+    hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
+                                                         INTERFACESAFE_FOR_UNTRUSTED_CALLER,
+                                                         INTERFACESAFE_FOR_UNTRUSTED_CALLER);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    todo_wine
+    ok(broken(enabled == INTERFACESAFE_FOR_UNTRUSTED_CALLER) ||
+       enabled == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
+         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACE_USES_SECURITY_MANAGER), "
+         "got %08x\n", enabled);
+
+    hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
+                                                         INTERFACESAFE_FOR_UNTRUSTED_DATA,
+                                                         INTERFACESAFE_FOR_UNTRUSTED_DATA);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
+    ok(hr == S_OK, "ret %08x\n", hr );
+    todo_wine
+    ok(broken(enabled == INTERFACESAFE_FOR_UNTRUSTED_DATA) ||
+       enabled == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA) /* msxml3 SP8+ */,
+        "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA), "
+        "got %08x\n", enabled);
+
+    IObjectSafety_Release(safety);
+
+    IXMLDOMDocument_Release(doc);
 }
 
 START_TEST(domdoc)
@@ -3977,6 +5463,9 @@ START_TEST(domdoc)
     test_Namespaces();
     test_FormattingXML();
     test_NodeTypeValue();
+    test_TransformWithLoadingLocalFile();
+    test_put_nodeValue();
+    test_document_IObjectSafety();
 
     CoUninitialize();
 }