kernel32: FindFirstChangeNotification needs a static IO_STATUS_BLOCK.
[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
77 void test_domdoc( void )
78 {
79     HRESULT r;
80     IXMLDOMDocument *doc = NULL;
81     IXMLDOMParseError *error;
82     IXMLDOMElement *element = NULL;
83     VARIANT_BOOL b;
84     VARIANT var;
85     BSTR str;
86     long code;
87
88     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
89         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
90     if( r != S_OK )
91         return;
92
93     /* try some stupid things */
94     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
95     ok( r == S_FALSE, "loadXML failed\n");
96
97     b = VARIANT_TRUE;
98     r = IXMLDOMDocument_loadXML( doc, NULL, &b );
99     ok( r == S_FALSE, "loadXML failed\n");
100     ok( b == VARIANT_FALSE, "failed to load XML string\n");
101
102     /* try to load a document from a nonexistent file */
103     b = VARIANT_TRUE;
104     str = SysAllocString( szNonExistentFile );
105     VariantInit(&var);
106     V_VT(&var) = VT_BSTR;
107     V_BSTR(&var) = str;
108
109     r = IXMLDOMDocument_load( doc, var, &b);
110     ok( r == S_FALSE, "load (from file) failed\n");
111     ok( b == VARIANT_FALSE, "failed to load XML file\n");
112     SysFreeString( str );
113
114     /* try load an empty document */
115     b = VARIANT_TRUE;
116     str = SysAllocString( szEmpty );
117     r = IXMLDOMDocument_loadXML( doc, str, &b );
118     ok( r == S_FALSE, "loadXML failed\n");
119     ok( b == VARIANT_FALSE, "failed to load XML string\n");
120     SysFreeString( str );
121
122     /* check that there's no document element */
123     element = NULL;
124     r = IXMLDOMDocument_get_documentElement( doc, &element );
125     ok( r == S_FALSE, "should be no document element\n");
126
127     b = VARIANT_TRUE;
128     str = SysAllocString( szIncomplete );
129     r = IXMLDOMDocument_loadXML( doc, str, &b );
130     ok( r == S_FALSE, "loadXML failed\n");
131     ok( b == VARIANT_FALSE, "failed to load XML string\n");
132     SysFreeString( str );
133
134     /* check that there's no document element */
135     element = (IXMLDOMElement*)1;
136     r = IXMLDOMDocument_get_documentElement( doc, &element );
137     ok( r == S_FALSE, "should be no document element\n");
138     ok( element == NULL, "Element should be NULL\n");
139
140     /* try to load something valid */
141     b = VARIANT_FALSE;
142     str = SysAllocString( szComplete1 );
143     r = IXMLDOMDocument_loadXML( doc, str, &b );
144     ok( r == S_OK, "loadXML failed\n");
145     ok( b == VARIANT_TRUE, "failed to load XML string\n");
146     SysFreeString( str );
147
148     /* try with a null out pointer - crashes */
149     if (0)
150     {
151         r = IXMLDOMDocument_get_documentElement( doc, NULL );
152         ok( r == S_OK, "should be no document element\n");
153     }
154
155     /* check if nodename is correct */
156     r = IXMLDOMDocument_get_nodeName( doc, NULL );
157     ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
158
159     /* content doesn't matter here */
160     str = SysAllocString( szNonExistentFile );
161     r = IXMLDOMDocument_get_nodeName( doc, &str );
162     ok ( r == S_OK, "get_nodeName wrong code\n");
163     ok ( str != NULL, "str is null\n");
164     ok( !lstrcmpW( str, szDocument ), "incorrect nodeName\n");
165     SysFreeString( str );
166
167
168     /* check that there's a document element */
169     element = NULL;
170     r = IXMLDOMDocument_get_documentElement( doc, &element );
171     ok( r == S_OK, "should be a document element\n");
172     if( element )
173     {
174         BSTR tag = NULL;
175
176         /* check if the tag is correct */
177         r = IXMLDOMElement_get_tagName( element, &tag );
178         ok( r == S_OK, "couldn't get tag name\n");
179         ok( tag != NULL, "tag was null\n");
180         ok( !lstrcmpW( tag, szOpen ), "incorrect tag name\n");
181         SysFreeString( tag );
182
183         /* figure out what happens if we try to reload the document */
184         str = SysAllocString( szComplete2 );
185         r = IXMLDOMDocument_loadXML( doc, str, &b );
186         ok( r == S_OK, "loadXML failed\n");
187         ok( b == VARIANT_TRUE, "failed to load XML string\n");
188         SysFreeString( str );
189
190         /* check if the tag is still correct */
191         tag = NULL;
192         r = IXMLDOMElement_get_tagName( element, &tag );
193         ok( r == S_OK, "couldn't get tag name\n");
194         ok( tag != NULL, "tag was null\n");
195         ok( !lstrcmpW( tag, szOpen ), "incorrect tag name\n");
196         SysFreeString( tag );
197
198         IXMLDOMElement_Release( element );
199         element = NULL;
200     }
201
202     /* as soon as we call loadXML again, the document element will disappear */
203     b = 2;
204     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
205     ok( r == S_FALSE, "loadXML failed\n");
206     ok( b == 2, "variant modified\n");
207     r = IXMLDOMDocument_get_documentElement( doc, &element );
208     ok( r == S_FALSE, "should be no document element\n");
209
210     /* try to load something else simple and valid */
211     b = VARIANT_FALSE;
212     str = SysAllocString( szComplete3 );
213     r = IXMLDOMDocument_loadXML( doc, str, &b );
214     ok( r == S_OK, "loadXML failed\n");
215     ok( b == VARIANT_TRUE, "failed to load XML string\n");
216     SysFreeString( str );
217
218     /* try something a little more complicated */
219     b = FALSE;
220     str = SysAllocString( szComplete4 );
221     r = IXMLDOMDocument_loadXML( doc, str, &b );
222     ok( r == S_OK, "loadXML failed\n");
223     ok( b == VARIANT_TRUE, "failed to load XML string\n");
224     SysFreeString( str );
225
226     r = IXMLDOMDocument_get_parseError( doc, &error );
227     ok( r == S_OK, "returns %08lx\n", r );
228
229     r = IXMLDOMParseError_get_errorCode( error, &code );
230     ok( r == S_FALSE, "returns %08lx\n", r );
231     ok( code == 0, "code %ld\n", code );
232     IXMLDOMParseError_Release( error );
233
234     r = IXMLDOMDocument_Release( doc );
235     ok( r == 0, "document ref count incorrect\n");
236
237 }
238
239 void test_domnode( void )
240 {
241     HRESULT r;
242     IXMLDOMDocument *doc = NULL, *owner = NULL;
243     IXMLDOMElement *element = NULL;
244     IXMLDOMNamedNodeMap *map = NULL;
245     IXMLDOMNode *node = NULL, *next = NULL;
246     IXMLDOMNodeList *list = NULL;
247     DOMNodeType type = NODE_INVALID;
248     VARIANT_BOOL b;
249     BSTR str;
250     VARIANT var;
251     long count;
252
253     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
254         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
255     if( r != S_OK )
256         return;
257
258     b = FALSE;
259     str = SysAllocString( szComplete4 );
260     r = IXMLDOMDocument_loadXML( doc, str, &b );
261     ok( r == S_OK, "loadXML failed\n");
262     ok( b == VARIANT_TRUE, "failed to load XML string\n");
263     SysFreeString( str );
264
265     if (doc)
266     {
267         b = 1;
268         r = IXMLDOMNode_hasChildNodes( doc, &b );
269         ok( r == S_OK, "hasChildNoes bad return\n");
270         ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
271
272         r = IXMLDOMDocument_get_documentElement( doc, &element );
273         ok( r == S_OK, "should be a document element\n");
274         ok( element != NULL, "should be an element\n");
275     }
276     else
277         ok( FALSE, "no document\n");
278
279     VariantInit(&var);
280     ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
281     r = IXMLDOMNode_get_nodeValue( doc, &var );
282     ok( r == S_FALSE, "nextNode returned wrong code\n");
283     ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
284     ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
285
286     if (element)
287     {
288         owner = NULL;
289         r = IXMLDOMNode_get_ownerDocument( element, &owner );
290         todo_wine {
291         ok( r == S_OK, "get_ownerDocument return code\n");
292         }
293         ok( owner != doc, "get_ownerDocument return\n");
294
295         type = NODE_INVALID;
296         r = IXMLDOMNode_get_nodeType( element, &type);
297         ok( r == S_OK, "getNamedItem returned wrong code\n");
298         ok( type == NODE_ELEMENT, "node not an element\n");
299
300         str = NULL;
301         r = IXMLDOMNode_get_baseName( element, &str );
302         ok( r == S_OK, "get_baseName returned wrong code\n");
303         ok( lstrcmpW(str,szlc) == 0, "basename was wrong\n");
304
305         /* check if nodename is correct */
306         r = IXMLDOMElement_get_nodeName( element, NULL );
307         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
308     
309         /* content doesn't matter here */
310         str = SysAllocString( szNonExistentFile );
311         r = IXMLDOMElement_get_nodeName( element, &str );
312         ok ( r == S_OK, "get_nodeName wrong code\n");
313         ok ( str != NULL, "str is null\n");
314         ok( !lstrcmpW( str, szlc ), "incorrect nodeName\n");
315         SysFreeString( str );
316
317         str = SysAllocString( szNonExistentFile );      
318         V_VT(&var) = VT_I4;
319         V_I4(&var) = 0x1234;
320         r = IXMLDOMElement_getAttribute( element, str, &var );
321         ok( r == E_FAIL, "getAttribute ret %08lx\n", r );
322         ok( V_VT(&var) == VT_EMPTY, "vt = %x\n", V_VT(&var));
323         VariantClear(&var);
324         SysFreeString( str );
325
326         str = SysAllocString( szdl );   
327         V_VT(&var) = VT_I4;
328         V_I4(&var) = 0x1234;
329         r = IXMLDOMElement_getAttribute( element, str, &var );
330         ok( r == S_OK, "getAttribute ret %08lx\n", r );
331         ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
332         ok( !lstrcmpW(V_BSTR(&var), szstr1), "wrong attr value\n");
333         VariantClear( &var );
334         SysFreeString( str );
335
336         r = IXMLDOMElement_get_attributes( element, &map );
337         ok( r == S_OK, "get_attributes returned wrong code\n");
338         ok( map != NULL, "should be attributes\n");
339
340         b = 1;
341         r = IXMLDOMNode_hasChildNodes( element, &b );
342         ok( r == S_OK, "hasChildNoes bad return\n");
343         ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
344     }
345     else
346         ok( FALSE, "no element\n");
347
348     if (map)
349     {
350         str = SysAllocString( szdl );
351         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
352         ok( r == S_OK, "getNamedItem returned wrong code\n");
353         ok( node != NULL, "should be attributes\n");
354         IXMLDOMNode_Release(node);
355         SysFreeString( str );
356
357         /* test indexed access of attributes */
358         r = IXMLDOMNamedNodeMap_get_length( map, &count );
359         ok ( r == S_OK, "get_length wrong code\n");
360         ok ( count == 1, "get_length != 1\n");
361
362         node = NULL;
363         r = IXMLDOMNamedNodeMap_get_item( map, -1, &node);
364         ok ( r == S_FALSE, "get_item (-1) wrong code\n");
365         ok ( node == NULL, "there is no node\n");
366
367         node = NULL;
368         r = IXMLDOMNamedNodeMap_get_item( map, 1, &node);
369         ok ( r == S_FALSE, "get_item (1) wrong code\n");
370         ok ( node == NULL, "there is no attribute\n");
371
372         node = NULL;
373         r = IXMLDOMNamedNodeMap_get_item( map, 0, &node);
374         ok ( r == S_OK, "get_item (0) wrong code\n");
375         ok ( node != NULL, "should be attribute\n");
376
377         r = IXMLDOMNode_get_nodeName( node, NULL );
378         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
379
380         /* content doesn't matter here */
381         str = SysAllocString( szNonExistentFile );
382         r = IXMLDOMNode_get_nodeName( node, &str );
383         ok ( r == S_OK, "get_nodeName wrong code\n");
384         ok ( str != NULL, "str is null\n");
385         ok( !lstrcmpW( str, szdl ), "incorrect node name\n");
386         SysFreeString( str );
387     }
388     else
389         ok( FALSE, "no map\n");
390
391     if (node)
392     {
393         type = NODE_INVALID;
394         r = IXMLDOMNode_get_nodeType( node, &type);
395         ok( r == S_OK, "getNamedItem returned wrong code\n");
396         ok( type == NODE_ATTRIBUTE, "node not an attribute\n");
397
398         str = NULL;
399         r = IXMLDOMNode_get_baseName( node, NULL );
400         ok( r == E_INVALIDARG, "get_baseName returned wrong code\n");
401
402         str = NULL;
403         r = IXMLDOMNode_get_baseName( node, &str );
404         ok( r == S_OK, "get_baseName returned wrong code\n");
405         ok( lstrcmpW(str,szdl) == 0, "basename was wrong\n");
406
407         r = IXMLDOMNode_get_nodeValue( node, &var );
408         ok( r == S_OK, "returns %08lx\n", r );
409         ok( V_VT(&var) == VT_BSTR, "vt %x\n", V_VT(&var));
410         ok( !lstrcmpW(V_BSTR(&var), szstr1), "nodeValue incorrect\n");
411         VariantClear(&var);
412
413         r = IXMLDOMNode_get_childNodes( node, NULL );
414         ok( r == E_INVALIDARG, "get_childNodes returned wrong code\n");
415
416         r = IXMLDOMNode_get_childNodes( node, &list );
417         ok( r == S_OK, "get_childNodes returned wrong code\n");
418
419         if (list)
420         {
421             r = IXMLDOMNodeList_nextNode( list, &next );
422             ok( r == S_OK, "nextNode returned wrong code\n");
423         }
424         else
425             ok( FALSE, "no childlist\n");
426
427         if (next)
428         {
429             b = 1;
430             r = IXMLDOMNode_hasChildNodes( next, &b );
431             ok( r == S_FALSE, "hasChildNoes bad return\n");
432             ok( b == VARIANT_FALSE, "hasChildNoes wrong result\n");
433
434             type = NODE_INVALID;
435             r = IXMLDOMNode_get_nodeType( next, &type);
436             ok( r == S_OK, "getNamedItem returned wrong code\n");
437             ok( type == NODE_TEXT, "node not text\n");
438
439             str = (BSTR) 1;
440             r = IXMLDOMNode_get_baseName( next, &str );
441             ok( r == S_FALSE, "get_baseName returned wrong code\n");
442             ok( str == NULL, "basename was wrong\n");
443         }
444         else
445             ok( FALSE, "no next\n");
446
447         if (next)
448             IXMLDOMNode_Release( next );
449         next = NULL;
450         if (list)
451             IXMLDOMNodeList_Release( list );
452         list = NULL;
453         if (node)
454             IXMLDOMNode_Release( node );
455     }
456     else
457         ok( FALSE, "no node\n");
458     node = NULL;
459
460     if (map)
461         IXMLDOMNamedNodeMap_Release( map );
462
463     /* now traverse the tree from the root node */
464     if (element)
465     {
466         r = IXMLDOMNode_get_childNodes( element, &list );
467         ok( r == S_OK, "get_childNodes returned wrong code\n");
468     }
469     else
470         ok( FALSE, "no element\n");
471
472     r = IXMLDOMNode_selectSingleNode( element, (BSTR)szdl, &node );
473     ok( r == S_FALSE, "ret %08lx\n", r );
474     r = IXMLDOMNode_selectSingleNode( element, (BSTR)szbs, &node );
475     ok( r == S_OK, "ret %08lx\n", r );
476     r = IXMLDOMNode_Release( node );
477     ok( r == 0, "ret %08lx\n", r );
478
479     if (list)
480     {
481         r = IXMLDOMNodeList_get_length( list, &count );
482         ok( r == S_OK, "get_length returns %08lx\n", r );
483         ok( count == 2, "get_length got %ld\n", count );
484
485         r = IXMLDOMNodeList_nextNode( list, &node );
486         ok( r == S_OK, "nextNode returned wrong code\n");
487     }
488     else
489         ok( FALSE, "no list\n");
490
491     if (node)
492     {
493         type = NODE_INVALID;
494         r = IXMLDOMNode_get_nodeType( node, &type);
495         ok( r == S_OK, "getNamedItem returned wrong code\n");
496         ok( type == NODE_ELEMENT, "node not text\n");
497
498         VariantInit(&var);
499         ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
500         r = IXMLDOMNode_get_nodeValue( node, &var );
501         ok( r == S_FALSE, "nextNode returned wrong code\n");
502         ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
503         ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
504
505         r = IXMLDOMNode_hasChildNodes( node, NULL );
506         ok( r == E_INVALIDARG, "hasChildNoes bad return\n");
507
508         b = 1;
509         r = IXMLDOMNode_hasChildNodes( node, &b );
510         ok( r == S_OK, "hasChildNoes bad return\n");
511         ok( b == VARIANT_TRUE, "hasChildNoes wrong result\n");
512
513         str = NULL;
514         r = IXMLDOMNode_get_baseName( node, &str );
515         ok( r == S_OK, "get_baseName returned wrong code\n");
516         ok( lstrcmpW(str,szbs) == 0, "basename was wrong\n");
517     }
518     else
519         ok( FALSE, "no node\n");
520
521     if (node)
522         IXMLDOMNode_Release( node );
523     if (list)
524         IXMLDOMNodeList_Release( list );
525     if (element)
526         IXMLDOMElement_Release( element );
527     if (doc)
528         IXMLDOMDocument_Release( doc );
529 }
530
531 static void test_refs(void)
532 {
533     HRESULT r;
534     BSTR str;
535     VARIANT_BOOL b;
536     IXMLDOMDocument *doc = NULL;
537     IXMLDOMElement *element = NULL;
538     IXMLDOMNode *node = NULL, *node2;
539     IXMLDOMNodeList *node_list = NULL;
540     LONG ref;
541     IUnknown *unk, *unk2;
542
543     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
544         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
545     if( r != S_OK )
546         return;
547     ref = IXMLDOMDocument_Release(doc);
548     ok( ref == 0, "ref %ld\n", ref);
549
550     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
551         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
552     if( r != S_OK )
553         return;
554
555     str = SysAllocString( szComplete4 );
556     r = IXMLDOMDocument_loadXML( doc, str, &b );
557     ok( r == S_OK, "loadXML failed\n");
558     ok( b == VARIANT_TRUE, "failed to load XML string\n");
559     SysFreeString( str );
560
561     ref = IXMLDOMDocument_AddRef( doc );
562     ok( ref == 2, "ref %ld\n", ref );
563     ref = IXMLDOMDocument_AddRef( doc );
564     ok( ref == 3, "ref %ld\n", ref );
565     IXMLDOMDocument_Release( doc );
566     IXMLDOMDocument_Release( doc );
567
568     r = IXMLDOMDocument_get_documentElement( doc, &element );
569     ok( r == S_OK, "should be a document element\n");
570     ok( element != NULL, "should be an element\n");
571
572     ref = IXMLDOMDocument_AddRef( doc );
573     ok( ref == 2, "ref %ld\n", ref );
574     IXMLDOMDocument_Release( doc );
575
576     r = IXMLDOMElement_get_childNodes( element, &node_list );
577     ok( r == S_OK, "rets %08lx\n", r);
578     ref = IXMLDOMNodeList_AddRef( node_list );
579     ok( ref == 2, "ref %ld\n", ref );
580     IXMLDOMNodeList_Release( node_list );
581
582     IXMLDOMNodeList_get_item( node_list, 0, &node );
583     ok( r == S_OK, "rets %08lx\n", r);
584
585     IXMLDOMNodeList_get_item( node_list, 0, &node2 );
586     ok( r == S_OK, "rets %08lx\n", r);
587
588     ref = IXMLDOMNode_AddRef( node );
589     ok( ref == 2, "ref %ld\n", ref );
590     IXMLDOMNode_Release( node );
591
592     ref = IXMLDOMNode_Release( node );
593     ok( ref == 0, "ref %ld\n", ref );
594     ref = IXMLDOMNode_Release( node2 );
595     ok( ref == 0, "ref %ld\n", ref );
596
597     ref = IXMLDOMNodeList_Release( node_list );
598     ok( ref == 0, "ref %ld\n", ref );
599
600     ok( node != node2, "node %p node2 %p\n", node, node2 );
601
602     ref = IXMLDOMDocument_Release( doc );
603     ok( ref == 0, "ref %ld\n", ref );
604
605     ref = IXMLDOMElement_AddRef( element );
606     todo_wine {
607     ok( ref == 3, "ref %ld\n", ref );
608     }
609     IXMLDOMElement_Release( element );
610
611     /* IUnknown must be unique however we obtain it */
612     r = IXMLDOMElement_QueryInterface( element, &IID_IUnknown, (LPVOID*)&unk );
613     ok( r == S_OK, "rets %08lx\n", r );
614     r = IXMLDOMElement_QueryInterface( element, &IID_IXMLDOMNode, (LPVOID*)&node );
615     ok( r == S_OK, "rets %08lx\n", r );
616     r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (LPVOID*)&unk2 );
617     ok( r == S_OK, "rets %08lx\n", r );
618     ok( unk == unk2, "unk %p unk2 %p\n", unk, unk2 );
619
620     IUnknown_Release( unk2 );
621     IUnknown_Release( unk );
622     IXMLDOMNode_Release( node );
623
624     IXMLDOMElement_Release( element );
625
626 }
627
628 static void test_create(void)
629 {
630     HRESULT r;
631     VARIANT var;
632     BSTR str, name;
633     IXMLDOMDocument *doc;
634     IXMLDOMElement *element;
635     IXMLDOMNode *root, *node, *child;
636     IXMLDOMNamedNodeMap *attr_map;
637     IUnknown *unk;
638     LONG ref, num;
639
640     r = CoCreateInstance( &CLSID_DOMDocument, NULL, 
641         CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (LPVOID*)&doc );
642     if( r != S_OK )
643         return;
644
645     V_VT(&var) = VT_I4;
646     V_I4(&var) = NODE_ELEMENT;
647     str = SysAllocString( szlc );
648     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
649     ok( r == S_OK, "returns %08lx\n", r );
650     r = IXMLDOMDocument_appendChild( doc, node, &root );
651     ok( r == S_OK, "returns %08lx\n", r );
652     ok( node == root, "%p %p\n", node, root );
653
654     ref = IXMLDOMNode_AddRef( node );
655     ok(ref == 3, "ref %ld\n", ref);
656     IXMLDOMNode_Release( node );
657
658     ref = IXMLDOMNode_Release( node );
659     ok(ref == 1, "ref %ld\n", ref);
660     SysFreeString( str );
661
662     V_VT(&var) = VT_I4;
663     V_I4(&var) = NODE_ELEMENT;
664     str = SysAllocString( szbs );
665     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
666     ok( r == S_OK, "returns %08lx\n", r );
667
668     ref = IXMLDOMNode_AddRef( node );
669     ok(ref == 2, "ref = %ld\n", ref);
670     IXMLDOMNode_Release( node );
671
672     r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (LPVOID*)&unk );
673     ok( r == S_OK, "returns %08lx\n", r );
674
675     ref = IXMLDOMNode_AddRef( unk );
676     ok(ref == 3, "ref = %ld\n", ref);
677     IXMLDOMNode_Release( unk );
678
679     V_VT(&var) = VT_EMPTY;
680     r = IXMLDOMNode_insertBefore( root, (IXMLDOMNode*)unk, var, &child );
681     ok( r == S_OK, "returns %08lx\n", r );
682     ok( unk == (IUnknown*)child, "%p %p\n", unk, child );
683     IXMLDOMNode_Release( child );
684     IUnknown_Release( unk );
685
686
687     V_VT(&var) = VT_NULL;
688     V_DISPATCH(&var) = (IDispatch*)node;
689     r = IXMLDOMNode_insertBefore( root, node, var, &child );
690     ok( r == S_OK, "returns %08lx\n", r );
691     ok( node == child, "%p %p\n", node, child );
692     IXMLDOMNode_Release( child );
693     IXMLDOMNode_Release( node );
694
695
696     r = IXMLDOMNode_QueryInterface( root, &IID_IXMLDOMElement, (LPVOID*)&element );
697     ok( r == S_OK, "returns %08lx\n", r );
698
699     r = IXMLDOMElement_get_attributes( element, &attr_map );
700     ok( r == S_OK, "returns %08lx\n", r );
701     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
702     ok( r == S_OK, "returns %08lx\n", r );
703     ok( num == 0, "num %ld\n", num );
704     IXMLDOMNamedNodeMap_Release( attr_map );
705
706     V_VT(&var) = VT_BSTR;
707     V_BSTR(&var) = SysAllocString( szstr1 );
708     name = SysAllocString( szdl );
709     r = IXMLDOMElement_setAttribute( element, name, var );
710     ok( r == S_OK, "returns %08lx\n", r );
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 == 1, "num %ld\n", num );
716     IXMLDOMNamedNodeMap_Release( attr_map );
717     VariantClear(&var);
718
719     V_VT(&var) = VT_BSTR;
720     V_BSTR(&var) = SysAllocString( szstr2 );
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     r = IXMLDOMElement_getAttribute( element, name, &var );
731     ok( r == S_OK, "returns %08lx\n", r );
732     ok( !lstrcmpW(V_BSTR(&var), szstr2), "wrong attr value\n");
733     VariantClear(&var);
734     SysFreeString(name);
735
736     V_VT(&var) = VT_BSTR;
737     V_BSTR(&var) = SysAllocString( szstr1 );
738     name = SysAllocString( szlc );
739     r = IXMLDOMElement_setAttribute( element, name, var );
740     ok( r == S_OK, "returns %08lx\n", r );
741     r = IXMLDOMElement_get_attributes( element, &attr_map );
742     ok( r == S_OK, "returns %08lx\n", r );
743     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
744     ok( r == S_OK, "returns %08lx\n", r );
745     ok( num == 2, "num %ld\n", num );
746     IXMLDOMNamedNodeMap_Release( attr_map );
747     VariantClear(&var);
748     SysFreeString(name);
749
750     V_VT(&var) = VT_I4;
751     V_I4(&var) = 10;
752     name = SysAllocString( szbs );
753     r = IXMLDOMElement_setAttribute( element, name, var );
754     ok( r == S_OK, "returns %08lx\n", r );
755     VariantClear(&var);
756     r = IXMLDOMElement_getAttribute( element, name, &var );
757     ok( r == S_OK, "returns %08lx\n", r );
758     ok( V_VT(&var) == VT_BSTR, "variant type %x\n", V_VT(&var));
759     VariantClear(&var);
760     SysFreeString(name);
761
762     IXMLDOMElement_Release( element );
763     IXMLDOMNode_Release( root );
764     IXMLDOMDocument_Release( doc );
765 }
766
767
768 START_TEST(domdoc)
769 {
770     HRESULT r;
771
772     r = CoInitialize( NULL );
773     ok( r == S_OK, "failed to init com\n");
774
775     test_domdoc();
776     test_domnode();
777     test_refs();
778     test_create();
779
780     CoUninitialize();
781 }