mshtml: Added hack to allow pass post data to IPersistMoniker::Load.
[wine] / dlls / msxml3 / tests / domdoc.c
1 /*
2  * XML test
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21
22 #define COBJMACROS
23
24 #include "windows.h"
25 #include "ole2.h"
26 #include "msxml2.h"
27 #include <stdio.h>
28
29 #include "wine/test.h"
30
31 static const WCHAR szEmpty[] = { 0 };
32 static const WCHAR szIncomplete[] = {
33     '<','?','x','m','l',' ',
34     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',0
35 };
36 static const WCHAR szComplete1[] = {
37     '<','?','x','m','l',' ',
38     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
39     '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
40 };
41 static const WCHAR szComplete2[] = {
42     '<','?','x','m','l',' ',
43     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
44     '<','o','>','<','/','o','>','\n',0
45 };
46 static const WCHAR szComplete3[] = {
47     '<','?','x','m','l',' ',
48     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
49     '<','a','>','<','/','a','>','\n',0
50 };
51 static const WCHAR szComplete4[] = {
52     '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
53     '<','l','c',' ','d','l','=','\'','s','t','r','1','\'','>','\n',
54         '<','b','s',' ','v','r','=','\'','s','t','r','2','\'',' ','s','z','=','\'','1','2','3','4','\'','>',
55             'f','n','1','.','t','x','t','\n',
56         '<','/','b','s','>','\n',
57         '<','p','r',' ','i','d','=','\'','s','t','r','3','\'',' ','v','r','=','\'','1','.','2','.','3','\'',' ',
58                     'p','n','=','\'','w','i','n','e',' ','2','0','0','5','0','8','0','4','\'','>','\n',
59             'f','n','2','.','t','x','t','\n',
60         '<','/','p','r','>','\n',
61     '<','/','l','c','>','\n',0
62 };
63 static const WCHAR szNonExistentFile[] = {
64     'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0
65 };
66 static const WCHAR szDocument[] = {
67     '#', 'd', 'o', 'c', 'u', 'm', 'e', 'n', 't', 0
68 };
69
70 static const WCHAR szOpen[] = { 'o','p','e','n',0 };
71 static const WCHAR szdl[] = { 'd','l',0 };
72 static const WCHAR szlc[] = { 'l','c',0 };
73 static const WCHAR szbs[] = { 'b','s',0 };
74 static const WCHAR szstr1[] = { 's','t','r','1',0 };
75 static const WCHAR szstr2[] = { 's','t','r','2',0 };
76 static const WCHAR szstar[] = { '*',0 };
77
78 void test_domdoc( void )
79 {
80     HRESULT r;
81     IXMLDOMDocument *doc = NULL;
82     IXMLDOMParseError *error;
83     IXMLDOMElement *element = NULL;
84     VARIANT_BOOL b;
85     VARIANT var;
86     BSTR str;
87     long code;
88
89     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
90         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
91     if( r != S_OK )
92         return;
93
94     /* try some stupid things */
95     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
96     ok( r == S_FALSE, "loadXML failed\n");
97
98     b = VARIANT_TRUE;
99     r = IXMLDOMDocument_loadXML( doc, NULL, &b );
100     ok( r == S_FALSE, "loadXML failed\n");
101     ok( b == VARIANT_FALSE, "failed to load XML string\n");
102
103     /* try to load a document from a nonexistent file */
104     b = VARIANT_TRUE;
105     str = SysAllocString( szNonExistentFile );
106     VariantInit(&var);
107     V_VT(&var) = VT_BSTR;
108     V_BSTR(&var) = str;
109
110     r = IXMLDOMDocument_load( doc, var, &b);
111     ok( r == S_FALSE, "load (from file) failed\n");
112     ok( b == VARIANT_FALSE, "failed to load XML file\n");
113     SysFreeString( str );
114
115     /* try load an empty document */
116     b = VARIANT_TRUE;
117     str = SysAllocString( szEmpty );
118     r = IXMLDOMDocument_loadXML( doc, str, &b );
119     ok( r == S_FALSE, "loadXML failed\n");
120     ok( b == VARIANT_FALSE, "failed to load XML string\n");
121     SysFreeString( str );
122
123     /* check that there's no document element */
124     element = NULL;
125     r = IXMLDOMDocument_get_documentElement( doc, &element );
126     ok( r == S_FALSE, "should be no document element\n");
127
128     b = VARIANT_TRUE;
129     str = SysAllocString( szIncomplete );
130     r = IXMLDOMDocument_loadXML( doc, str, &b );
131     ok( r == S_FALSE, "loadXML failed\n");
132     ok( b == VARIANT_FALSE, "failed to load XML string\n");
133     SysFreeString( str );
134
135     /* check that there's no document element */
136     element = (IXMLDOMElement*)1;
137     r = IXMLDOMDocument_get_documentElement( doc, &element );
138     ok( r == S_FALSE, "should be no document element\n");
139     ok( element == NULL, "Element should be NULL\n");
140
141     /* try to load something valid */
142     b = VARIANT_FALSE;
143     str = SysAllocString( szComplete1 );
144     r = IXMLDOMDocument_loadXML( doc, str, &b );
145     ok( r == S_OK, "loadXML failed\n");
146     ok( b == VARIANT_TRUE, "failed to load XML string\n");
147     SysFreeString( str );
148
149     /* try with a null out pointer - crashes */
150     if (0)
151     {
152         r = IXMLDOMDocument_get_documentElement( doc, NULL );
153         ok( r == S_OK, "should be no document element\n");
154     }
155
156     /* check if nodename is correct */
157     r = IXMLDOMDocument_get_nodeName( doc, NULL );
158     ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
159
160     /* content doesn't matter here */
161     str = SysAllocString( szNonExistentFile );
162     r = IXMLDOMDocument_get_nodeName( doc, &str );
163     ok ( r == S_OK, "get_nodeName wrong code\n");
164     ok ( str != NULL, "str is null\n");
165     ok( !lstrcmpW( str, szDocument ), "incorrect nodeName\n");
166     SysFreeString( str );
167
168
169     /* check that there's a document element */
170     element = NULL;
171     r = IXMLDOMDocument_get_documentElement( doc, &element );
172     ok( r == S_OK, "should be a document element\n");
173     if( element )
174     {
175         BSTR tag = NULL;
176
177         /* check if the tag is correct */
178         r = IXMLDOMElement_get_tagName( element, &tag );
179         ok( r == S_OK, "couldn't get tag name\n");
180         ok( tag != NULL, "tag was null\n");
181         ok( !lstrcmpW( tag, szOpen ), "incorrect tag name\n");
182         SysFreeString( tag );
183
184         /* figure out what happens if we try to reload the document */
185         str = SysAllocString( szComplete2 );
186         r = IXMLDOMDocument_loadXML( doc, str, &b );
187         ok( r == S_OK, "loadXML failed\n");
188         ok( b == VARIANT_TRUE, "failed to load XML string\n");
189         SysFreeString( str );
190
191         /* check if the tag is still correct */
192         tag = NULL;
193         r = IXMLDOMElement_get_tagName( element, &tag );
194         ok( r == S_OK, "couldn't get tag name\n");
195         ok( tag != NULL, "tag was null\n");
196         ok( !lstrcmpW( tag, szOpen ), "incorrect tag name\n");
197         SysFreeString( tag );
198
199         IXMLDOMElement_Release( element );
200         element = NULL;
201     }
202
203     /* as soon as we call loadXML again, the document element will disappear */
204     b = 2;
205     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
206     ok( r == S_FALSE, "loadXML failed\n");
207     ok( b == 2, "variant modified\n");
208     r = IXMLDOMDocument_get_documentElement( doc, &element );
209     ok( r == S_FALSE, "should be no document element\n");
210
211     /* try to load something else simple and valid */
212     b = VARIANT_FALSE;
213     str = SysAllocString( szComplete3 );
214     r = IXMLDOMDocument_loadXML( doc, str, &b );
215     ok( r == S_OK, "loadXML failed\n");
216     ok( b == VARIANT_TRUE, "failed to load XML string\n");
217     SysFreeString( str );
218
219     /* try something a little more complicated */
220     b = FALSE;
221     str = SysAllocString( szComplete4 );
222     r = IXMLDOMDocument_loadXML( doc, str, &b );
223     ok( r == S_OK, "loadXML failed\n");
224     ok( b == VARIANT_TRUE, "failed to load XML string\n");
225     SysFreeString( str );
226
227     r = IXMLDOMDocument_get_parseError( doc, &error );
228     ok( r == S_OK, "returns %08lx\n", r );
229
230     r = IXMLDOMParseError_get_errorCode( error, &code );
231     ok( r == S_FALSE, "returns %08lx\n", r );
232     ok( code == 0, "code %ld\n", code );
233     IXMLDOMParseError_Release( error );
234
235     r = IXMLDOMDocument_Release( doc );
236     ok( r == 0, "document ref count incorrect\n");
237
238 }
239
240 void test_domnode( void )
241 {
242     HRESULT r;
243     IXMLDOMDocument *doc = NULL, *owner = NULL;
244     IXMLDOMElement *element = NULL;
245     IXMLDOMNamedNodeMap *map = NULL;
246     IXMLDOMNode *node = NULL, *next = NULL;
247     IXMLDOMNodeList *list = NULL;
248     DOMNodeType type = NODE_INVALID;
249     VARIANT_BOOL b;
250     BSTR str;
251     VARIANT var;
252     long count;
253
254     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
255         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
256     if( r != S_OK )
257         return;
258
259     b = FALSE;
260     str = SysAllocString( szComplete4 );
261     r = IXMLDOMDocument_loadXML( doc, str, &b );
262     ok( r == S_OK, "loadXML failed\n");
263     ok( b == VARIANT_TRUE, "failed to load XML string\n");
264     SysFreeString( str );
265
266     if (doc)
267     {
268         b = 1;
269         r = IXMLDOMNode_hasChildNodes( doc, &b );
270         ok( r == S_OK, "hasChildNoes bad return\n");
271         ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
272
273         r = IXMLDOMDocument_get_documentElement( doc, &element );
274         ok( r == S_OK, "should be a document element\n");
275         ok( element != NULL, "should be an element\n");
276     }
277     else
278         ok( FALSE, "no document\n");
279
280     VariantInit(&var);
281     ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
282     r = IXMLDOMNode_get_nodeValue( doc, &var );
283     ok( r == S_FALSE, "nextNode returned wrong code\n");
284     ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
285     ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
286
287     if (element)
288     {
289         owner = NULL;
290         r = IXMLDOMNode_get_ownerDocument( element, &owner );
291         todo_wine {
292         ok( r == S_OK, "get_ownerDocument return code\n");
293         }
294         ok( owner != doc, "get_ownerDocument return\n");
295
296         type = NODE_INVALID;
297         r = IXMLDOMNode_get_nodeType( element, &type);
298         ok( r == S_OK, "getNamedItem returned wrong code\n");
299         ok( type == NODE_ELEMENT, "node not an element\n");
300
301         str = NULL;
302         r = IXMLDOMNode_get_baseName( element, &str );
303         ok( r == S_OK, "get_baseName returned wrong code\n");
304         ok( lstrcmpW(str,szlc) == 0, "basename was wrong\n");
305
306         /* check if nodename is correct */
307         r = IXMLDOMElement_get_nodeName( element, NULL );
308         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
309     
310         /* content doesn't matter here */
311         str = SysAllocString( szNonExistentFile );
312         r = IXMLDOMElement_get_nodeName( element, &str );
313         ok ( r == S_OK, "get_nodeName wrong code\n");
314         ok ( str != NULL, "str is null\n");
315         ok( !lstrcmpW( str, szlc ), "incorrect nodeName\n");
316         SysFreeString( str );
317
318         str = SysAllocString( szNonExistentFile );      
319         V_VT(&var) = VT_I4;
320         V_I4(&var) = 0x1234;
321         r = IXMLDOMElement_getAttribute( element, str, &var );
322         ok( r == E_FAIL, "getAttribute ret %08lx\n", r );
323         ok( V_VT(&var) == VT_EMPTY, "vt = %x\n", V_VT(&var));
324         VariantClear(&var);
325         SysFreeString( str );
326
327         str = SysAllocString( szdl );   
328         V_VT(&var) = VT_I4;
329         V_I4(&var) = 0x1234;
330         r = IXMLDOMElement_getAttribute( element, str, &var );
331         ok( r == S_OK, "getAttribute ret %08lx\n", r );
332         ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
333         ok( !lstrcmpW(V_BSTR(&var), szstr1), "wrong attr value\n");
334         VariantClear( &var );
335         SysFreeString( str );
336
337         r = IXMLDOMElement_get_attributes( element, &map );
338         ok( r == S_OK, "get_attributes returned wrong code\n");
339         ok( map != NULL, "should be attributes\n");
340
341         b = 1;
342         r = IXMLDOMNode_hasChildNodes( element, &b );
343         ok( r == S_OK, "hasChildNoes bad return\n");
344         ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
345     }
346     else
347         ok( FALSE, "no element\n");
348
349     if (map)
350     {
351         ISupportErrorInfo *support_error;
352         r = IXMLDOMNamedNodeMap_QueryInterface( map, &IID_ISupportErrorInfo, (LPVOID*)&support_error );
353         ok( r == S_OK, "ret %08lx\n", r );
354
355         r = ISupportErrorInfo_InterfaceSupportsErrorInfo( support_error, &IID_IXMLDOMNamedNodeMap );
356 todo_wine
357 {
358         ok( r == S_OK, "ret %08lx\n", r );
359 }
360         ISupportErrorInfo_Release( support_error );
361
362         str = SysAllocString( szdl );
363         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
364         ok( r == S_OK, "getNamedItem returned wrong code\n");
365         ok( node != NULL, "should be attributes\n");
366         IXMLDOMNode_Release(node);
367         SysFreeString( str );
368
369         /* test indexed access of attributes */
370         r = IXMLDOMNamedNodeMap_get_length( map, &count );
371         ok ( r == S_OK, "get_length wrong code\n");
372         ok ( count == 1, "get_length != 1\n");
373
374         node = NULL;
375         r = IXMLDOMNamedNodeMap_get_item( map, -1, &node);
376         ok ( r == S_FALSE, "get_item (-1) wrong code\n");
377         ok ( node == NULL, "there is no node\n");
378
379         node = NULL;
380         r = IXMLDOMNamedNodeMap_get_item( map, 1, &node);
381         ok ( r == S_FALSE, "get_item (1) wrong code\n");
382         ok ( node == NULL, "there is no attribute\n");
383
384         node = NULL;
385         r = IXMLDOMNamedNodeMap_get_item( map, 0, &node);
386         ok ( r == S_OK, "get_item (0) wrong code\n");
387         ok ( node != NULL, "should be attribute\n");
388
389         r = IXMLDOMNode_get_nodeName( node, NULL );
390         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
391
392         /* content doesn't matter here */
393         str = SysAllocString( szNonExistentFile );
394         r = IXMLDOMNode_get_nodeName( node, &str );
395         ok ( r == S_OK, "get_nodeName wrong code\n");
396         ok ( str != NULL, "str is null\n");
397         ok( !lstrcmpW( str, szdl ), "incorrect node name\n");
398         SysFreeString( str );
399     }
400     else
401         ok( FALSE, "no map\n");
402
403     if (node)
404     {
405         type = NODE_INVALID;
406         r = IXMLDOMNode_get_nodeType( node, &type);
407         ok( r == S_OK, "getNamedItem returned wrong code\n");
408         ok( type == NODE_ATTRIBUTE, "node not an attribute\n");
409
410         str = NULL;
411         r = IXMLDOMNode_get_baseName( node, NULL );
412         ok( r == E_INVALIDARG, "get_baseName returned wrong code\n");
413
414         str = NULL;
415         r = IXMLDOMNode_get_baseName( node, &str );
416         ok( r == S_OK, "get_baseName returned wrong code\n");
417         ok( lstrcmpW(str,szdl) == 0, "basename was wrong\n");
418
419         r = IXMLDOMNode_get_nodeValue( node, &var );
420         ok( r == S_OK, "returns %08lx\n", r );
421         ok( V_VT(&var) == VT_BSTR, "vt %x\n", V_VT(&var));
422         ok( !lstrcmpW(V_BSTR(&var), szstr1), "nodeValue incorrect\n");
423         VariantClear(&var);
424
425         r = IXMLDOMNode_get_childNodes( node, NULL );
426         ok( r == E_INVALIDARG, "get_childNodes returned wrong code\n");
427
428         r = IXMLDOMNode_get_childNodes( node, &list );
429         ok( r == S_OK, "get_childNodes returned wrong code\n");
430
431         if (list)
432         {
433             r = IXMLDOMNodeList_nextNode( list, &next );
434             ok( r == S_OK, "nextNode returned wrong code\n");
435         }
436         else
437             ok( FALSE, "no childlist\n");
438
439         if (next)
440         {
441             b = 1;
442             r = IXMLDOMNode_hasChildNodes( next, &b );
443             ok( r == S_FALSE, "hasChildNoes bad return\n");
444             ok( b == VARIANT_FALSE, "hasChildNoes wrong result\n");
445
446             type = NODE_INVALID;
447             r = IXMLDOMNode_get_nodeType( next, &type);
448             ok( r == S_OK, "getNamedItem returned wrong code\n");
449             ok( type == NODE_TEXT, "node not text\n");
450
451             str = (BSTR) 1;
452             r = IXMLDOMNode_get_baseName( next, &str );
453             ok( r == S_FALSE, "get_baseName returned wrong code\n");
454             ok( str == NULL, "basename was wrong\n");
455         }
456         else
457             ok( FALSE, "no next\n");
458
459         if (next)
460             IXMLDOMNode_Release( next );
461         next = NULL;
462         if (list)
463             IXMLDOMNodeList_Release( list );
464         list = NULL;
465         if (node)
466             IXMLDOMNode_Release( node );
467     }
468     else
469         ok( FALSE, "no node\n");
470     node = NULL;
471
472     if (map)
473         IXMLDOMNamedNodeMap_Release( map );
474
475     /* now traverse the tree from the root node */
476     if (element)
477     {
478         r = IXMLDOMNode_get_childNodes( element, &list );
479         ok( r == S_OK, "get_childNodes returned wrong code\n");
480     }
481     else
482         ok( FALSE, "no element\n");
483
484     r = IXMLDOMNode_selectSingleNode( element, (BSTR)szdl, &node );
485     ok( r == S_FALSE, "ret %08lx\n", r );
486     r = IXMLDOMNode_selectSingleNode( element, (BSTR)szbs, &node );
487     ok( r == S_OK, "ret %08lx\n", r );
488     r = IXMLDOMNode_Release( node );
489     ok( r == 0, "ret %08lx\n", r );
490
491     if (list)
492     {
493         r = IXMLDOMNodeList_get_length( list, &count );
494         ok( r == S_OK, "get_length returns %08lx\n", r );
495         ok( count == 2, "get_length got %ld\n", count );
496
497         r = IXMLDOMNodeList_nextNode( list, &node );
498         ok( r == S_OK, "nextNode returned wrong code\n");
499     }
500     else
501         ok( FALSE, "no list\n");
502
503     if (node)
504     {
505         type = NODE_INVALID;
506         r = IXMLDOMNode_get_nodeType( node, &type);
507         ok( r == S_OK, "getNamedItem returned wrong code\n");
508         ok( type == NODE_ELEMENT, "node not text\n");
509
510         VariantInit(&var);
511         ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
512         r = IXMLDOMNode_get_nodeValue( node, &var );
513         ok( r == S_FALSE, "nextNode returned wrong code\n");
514         ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
515         ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
516
517         r = IXMLDOMNode_hasChildNodes( node, NULL );
518         ok( r == E_INVALIDARG, "hasChildNoes bad return\n");
519
520         b = 1;
521         r = IXMLDOMNode_hasChildNodes( node, &b );
522         ok( r == S_OK, "hasChildNoes bad return\n");
523         ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
524
525         str = NULL;
526         r = IXMLDOMNode_get_baseName( node, &str );
527         ok( r == S_OK, "get_baseName returned wrong code\n");
528         ok( lstrcmpW(str,szbs) == 0, "basename was wrong\n");
529     }
530     else
531         ok( FALSE, "no node\n");
532
533     if (node)
534         IXMLDOMNode_Release( node );
535     if (list)
536         IXMLDOMNodeList_Release( list );
537     if (element)
538         IXMLDOMElement_Release( element );
539     if (doc)
540         IXMLDOMDocument_Release( doc );
541 }
542
543 static void test_refs(void)
544 {
545     HRESULT r;
546     BSTR str;
547     VARIANT_BOOL b;
548     IXMLDOMDocument *doc = NULL;
549     IXMLDOMElement *element = NULL;
550     IXMLDOMNode *node = NULL, *node2;
551     IXMLDOMNodeList *node_list = NULL;
552     LONG ref;
553     IUnknown *unk, *unk2;
554
555     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
556         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
557     if( r != S_OK )
558         return;
559     ref = IXMLDOMDocument_Release(doc);
560     ok( ref == 0, "ref %ld\n", ref);
561
562     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
563         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
564     if( r != S_OK )
565         return;
566
567     str = SysAllocString( szComplete4 );
568     r = IXMLDOMDocument_loadXML( doc, str, &b );
569     ok( r == S_OK, "loadXML failed\n");
570     ok( b == VARIANT_TRUE, "failed to load XML string\n");
571     SysFreeString( str );
572
573     ref = IXMLDOMDocument_AddRef( doc );
574     ok( ref == 2, "ref %ld\n", ref );
575     ref = IXMLDOMDocument_AddRef( doc );
576     ok( ref == 3, "ref %ld\n", ref );
577     IXMLDOMDocument_Release( doc );
578     IXMLDOMDocument_Release( doc );
579
580     r = IXMLDOMDocument_get_documentElement( doc, &element );
581     ok( r == S_OK, "should be a document element\n");
582     ok( element != NULL, "should be an element\n");
583
584     ref = IXMLDOMDocument_AddRef( doc );
585     ok( ref == 2, "ref %ld\n", ref );
586     IXMLDOMDocument_Release( doc );
587
588     r = IXMLDOMElement_get_childNodes( element, &node_list );
589     ok( r == S_OK, "rets %08lx\n", r);
590     ref = IXMLDOMNodeList_AddRef( node_list );
591     ok( ref == 2, "ref %ld\n", ref );
592     IXMLDOMNodeList_Release( node_list );
593
594     IXMLDOMNodeList_get_item( node_list, 0, &node );
595     ok( r == S_OK, "rets %08lx\n", r);
596
597     IXMLDOMNodeList_get_item( node_list, 0, &node2 );
598     ok( r == S_OK, "rets %08lx\n", r);
599
600     ref = IXMLDOMNode_AddRef( node );
601     ok( ref == 2, "ref %ld\n", ref );
602     IXMLDOMNode_Release( node );
603
604     ref = IXMLDOMNode_Release( node );
605     ok( ref == 0, "ref %ld\n", ref );
606     ref = IXMLDOMNode_Release( node2 );
607     ok( ref == 0, "ref %ld\n", ref );
608
609     ref = IXMLDOMNodeList_Release( node_list );
610     ok( ref == 0, "ref %ld\n", ref );
611
612     ok( node != node2, "node %p node2 %p\n", node, node2 );
613
614     ref = IXMLDOMDocument_Release( doc );
615     ok( ref == 0, "ref %ld\n", ref );
616
617     ref = IXMLDOMElement_AddRef( element );
618     todo_wine {
619     ok( ref == 3, "ref %ld\n", ref );
620     }
621     IXMLDOMElement_Release( element );
622
623     /* IUnknown must be unique however we obtain it */
624     r = IXMLDOMElement_QueryInterface( element, &IID_IUnknown, (LPVOID*)&unk );
625     ok( r == S_OK, "rets %08lx\n", r );
626     r = IXMLDOMElement_QueryInterface( element, &IID_IXMLDOMNode, (LPVOID*)&node );
627     ok( r == S_OK, "rets %08lx\n", r );
628     r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (LPVOID*)&unk2 );
629     ok( r == S_OK, "rets %08lx\n", r );
630     ok( unk == unk2, "unk %p unk2 %p\n", unk, unk2 );
631
632     IUnknown_Release( unk2 );
633     IUnknown_Release( unk );
634     IXMLDOMNode_Release( node );
635
636     IXMLDOMElement_Release( element );
637
638 }
639
640 static void test_create(void)
641 {
642     HRESULT r;
643     VARIANT var;
644     BSTR str, name;
645     IXMLDOMDocument *doc;
646     IXMLDOMElement *element;
647     IXMLDOMNode *root, *node, *child;
648     IXMLDOMNamedNodeMap *attr_map;
649     IUnknown *unk;
650     LONG ref, num;
651
652     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
653         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
654     if( r != S_OK )
655         return;
656
657     V_VT(&var) = VT_I4;
658     V_I4(&var) = NODE_ELEMENT;
659     str = SysAllocString( szlc );
660     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
661     ok( r == S_OK, "returns %08lx\n", r );
662     r = IXMLDOMDocument_appendChild( doc, node, &root );
663     ok( r == S_OK, "returns %08lx\n", r );
664     ok( node == root, "%p %p\n", node, root );
665
666     ref = IXMLDOMNode_AddRef( node );
667     ok(ref == 3, "ref %ld\n", ref);
668     IXMLDOMNode_Release( node );
669
670     ref = IXMLDOMNode_Release( node );
671     ok(ref == 1, "ref %ld\n", ref);
672     SysFreeString( str );
673
674     V_VT(&var) = VT_I4;
675     V_I4(&var) = NODE_ELEMENT;
676     str = SysAllocString( szbs );
677     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
678     ok( r == S_OK, "returns %08lx\n", r );
679
680     ref = IXMLDOMNode_AddRef( node );
681     ok(ref == 2, "ref = %ld\n", ref);
682     IXMLDOMNode_Release( node );
683
684     r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (LPVOID*)&unk );
685     ok( r == S_OK, "returns %08lx\n", r );
686
687     ref = IXMLDOMNode_AddRef( unk );
688     ok(ref == 3, "ref = %ld\n", ref);
689     IXMLDOMNode_Release( unk );
690
691     V_VT(&var) = VT_EMPTY;
692     r = IXMLDOMNode_insertBefore( root, (IXMLDOMNode*)unk, var, &child );
693     ok( r == S_OK, "returns %08lx\n", r );
694     ok( unk == (IUnknown*)child, "%p %p\n", unk, child );
695     IXMLDOMNode_Release( child );
696     IUnknown_Release( unk );
697
698
699     V_VT(&var) = VT_NULL;
700     V_DISPATCH(&var) = (IDispatch*)node;
701     r = IXMLDOMNode_insertBefore( root, node, var, &child );
702     ok( r == S_OK, "returns %08lx\n", r );
703     ok( node == child, "%p %p\n", node, child );
704     IXMLDOMNode_Release( child );
705     IXMLDOMNode_Release( node );
706
707
708     r = IXMLDOMNode_QueryInterface( root, &IID_IXMLDOMElement, (LPVOID*)&element );
709     ok( r == S_OK, "returns %08lx\n", r );
710
711     r = IXMLDOMElement_get_attributes( element, &attr_map );
712     ok( r == S_OK, "returns %08lx\n", r );
713     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
714     ok( r == S_OK, "returns %08lx\n", r );
715     ok( num == 0, "num %ld\n", num );
716     IXMLDOMNamedNodeMap_Release( attr_map );
717
718     V_VT(&var) = VT_BSTR;
719     V_BSTR(&var) = SysAllocString( szstr1 );
720     name = SysAllocString( szdl );
721     r = IXMLDOMElement_setAttribute( element, name, var );
722     ok( r == S_OK, "returns %08lx\n", r );
723     r = IXMLDOMElement_get_attributes( element, &attr_map );
724     ok( r == S_OK, "returns %08lx\n", r );
725     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
726     ok( r == S_OK, "returns %08lx\n", r );
727     ok( num == 1, "num %ld\n", num );
728     IXMLDOMNamedNodeMap_Release( attr_map );
729     VariantClear(&var);
730
731     V_VT(&var) = VT_BSTR;
732     V_BSTR(&var) = SysAllocString( szstr2 );
733     r = IXMLDOMElement_setAttribute( element, name, var );
734     ok( r == S_OK, "returns %08lx\n", r );
735     r = IXMLDOMElement_get_attributes( element, &attr_map );
736     ok( r == S_OK, "returns %08lx\n", r );
737     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
738     ok( r == S_OK, "returns %08lx\n", r );
739     ok( num == 1, "num %ld\n", num );
740     IXMLDOMNamedNodeMap_Release( attr_map );
741     VariantClear(&var);
742     r = IXMLDOMElement_getAttribute( element, name, &var );
743     ok( r == S_OK, "returns %08lx\n", r );
744     ok( !lstrcmpW(V_BSTR(&var), szstr2), "wrong attr value\n");
745     VariantClear(&var);
746     SysFreeString(name);
747
748     V_VT(&var) = VT_BSTR;
749     V_BSTR(&var) = SysAllocString( szstr1 );
750     name = SysAllocString( szlc );
751     r = IXMLDOMElement_setAttribute( element, name, var );
752     ok( r == S_OK, "returns %08lx\n", r );
753     r = IXMLDOMElement_get_attributes( element, &attr_map );
754     ok( r == S_OK, "returns %08lx\n", r );
755     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
756     ok( r == S_OK, "returns %08lx\n", r );
757     ok( num == 2, "num %ld\n", num );
758     IXMLDOMNamedNodeMap_Release( attr_map );
759     VariantClear(&var);
760     SysFreeString(name);
761
762     V_VT(&var) = VT_I4;
763     V_I4(&var) = 10;
764     name = SysAllocString( szbs );
765     r = IXMLDOMElement_setAttribute( element, name, var );
766     ok( r == S_OK, "returns %08lx\n", r );
767     VariantClear(&var);
768     r = IXMLDOMElement_getAttribute( element, name, &var );
769     ok( r == S_OK, "returns %08lx\n", r );
770     ok( V_VT(&var) == VT_BSTR, "variant type %x\n", V_VT(&var));
771     VariantClear(&var);
772     SysFreeString(name);
773
774     IXMLDOMElement_Release( element );
775     IXMLDOMNode_Release( root );
776     IXMLDOMDocument_Release( doc );
777 }
778
779 static void test_getElementsByTagName(void)
780 {
781     HRESULT r;
782     BSTR str;
783     VARIANT_BOOL b;
784     IXMLDOMDocument *doc;
785     IXMLDOMNodeList *node_list;
786     LONG len;
787
788     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
789         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
790     if( r != S_OK )
791         return;
792
793     str = SysAllocString( szComplete4 );
794     r = IXMLDOMDocument_loadXML( doc, str, &b );
795     ok( r == S_OK, "loadXML failed\n");
796     ok( b == VARIANT_TRUE, "failed to load XML string\n");
797     SysFreeString( str );
798
799     str = SysAllocString( szstar );
800     r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
801     ok( r == S_OK, "ret %08lx\n", r );
802     r = IXMLDOMNodeList_get_length( node_list, &len );
803     ok( r == S_OK, "ret %08lx\n", r );
804     ok( len == 3, "len %ld\n", len );
805     IXMLDOMNodeList_Release( node_list );
806     SysFreeString( str );
807
808     str = SysAllocString( szbs );
809     r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
810     ok( r == S_OK, "ret %08lx\n", r );
811     r = IXMLDOMNodeList_get_length( node_list, &len );
812     ok( r == S_OK, "ret %08lx\n", r );
813     ok( len == 1, "len %ld\n", len );
814     IXMLDOMNodeList_Release( node_list );
815     SysFreeString( str );
816
817     str = SysAllocString( szdl );
818     r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
819     ok( r == S_OK, "ret %08lx\n", r );
820     r = IXMLDOMNodeList_get_length( node_list, &len );
821     ok( r == S_OK, "ret %08lx\n", r );
822     ok( len == 0, "len %ld\n", len );
823     IXMLDOMNodeList_Release( node_list );
824     SysFreeString( str );
825
826     str = SysAllocString( szstr1 );
827     r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
828     ok( r == S_OK, "ret %08lx\n", r );
829     r = IXMLDOMNodeList_get_length( node_list, &len );
830     ok( r == S_OK, "ret %08lx\n", r );
831     ok( len == 0, "len %ld\n", len );
832     IXMLDOMNodeList_Release( node_list );
833     SysFreeString( str );
834
835     IXMLDOMDocument_Release( doc );
836 }
837
838 START_TEST(domdoc)
839 {
840     HRESULT r;
841
842     r = CoInitialize( NULL );
843     ok( r == S_OK, "failed to init com\n");
844
845     test_domdoc();
846     test_domnode();
847     test_refs();
848     test_create();
849     test_getElementsByTagName();
850
851     CoUninitialize();
852 }