mshtml: Implement IHTMLDOMNode replaceChild.
[wine] / dlls / mshtml / tests / dom.c
1 /*
2  * Copyright 2007-2011 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #define COBJMACROS
20 #define CONST_VTABLE
21
22 #include <wine/test.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "ole2.h"
29 #include "mshtml.h"
30 #include "mshtmcid.h"
31 #include "mshtmhst.h"
32 #include "docobj.h"
33 #include "dispex.h"
34 #include "mshtml_test.h"
35 #include "objsafe.h"
36
37 static INT (WINAPI *pLCIDToLocaleName)(LCID,LPWSTR,INT,DWORD);
38 static LANGID (WINAPI *pGetUserDefaultUILanguage)(void);
39
40 static const char doc_blank[] = "<html></html>";
41 static const char doc_str1[] = "<html><body>test</body></html>";
42 static const char range_test_str[] =
43     "<html><body>test \na<font size=\"2\">bc\t123<br /> it's\r\n  \t</font>text<br /></body></html>";
44 static const char range_test2_str[] =
45     "<html><body>abc<hr />123<br /><hr />def</body></html>";
46 static const char elem_test_str[] =
47     "<html><head><title>test</title><style id=\"styleid\">.body { margin-right: 0px; }</style>"
48     "<body onload=\"Testing()\">text test<!-- a comment -->"
49     "<a id=\"a\" href=\"http://test\" name=\"x\">link</a>"
50     "<input id=\"in\" class=\"testclass\" tabIndex=\"2\" title=\"test title\" />"
51     "<select id=\"s\"><option id=\"x\" value=\"val1\">opt1</option><option id=\"y\">opt2</option></select>"
52     "<textarea id=\"X\">text text</textarea>"
53     "<table id=\"tbl\"><tbody><tr></tr><tr id=\"row2\"><td>td1 text</td><td>td2 text</td></tr></tbody></table>"
54     "<script id=\"sc\" type=\"text/javascript\"><!--\nfunction Testing() {}\n// -->\n</script>"
55     "<test /><object id=\"objid\" vspace=100></object><embed />"
56     "<img id=\"imgid\" name=\"WineImg\"/>"
57     "<iframe src=\"about:blank\" id=\"ifr\"></iframe>"
58     "<form id=\"frm\"></form>"
59     "<div id=\"attr\" attr1=\"attr1\" attr2 attr3=\"attr3\"></div>"
60     "</body></html>";
61 static const char elem_test2_str[] =
62     "<html><head><title>test</title><style>.body { margin-right: 0px; }</style>"
63     "<body><div id=\"divid\" emptyattr=\"\" onclick=\"parseInt();\"></div></body>"
64     "</html>";
65
66 static const char indent_test_str[] =
67     "<html><head><title>test</title></head><body>abc<br /><a href=\"about:blank\">123</a></body></html>";
68 static const char cond_comment_str[] =
69     "<html><head><title>test</title></head><body>"
70     "<!--[if gte IE 4]> <br> <![endif]-->"
71     "</body></html>";
72 static const char frameset_str[] =
73     "<html><head><title>frameset test</title></head><frameset rows=\"25, 25, *\">"
74     "<frame src=\"about:blank\" name=\"nm1\" id=\"fr1\"><frame src=\"about:blank\" name=\"nm2\" id=\"fr2\">"
75     "<frame src=\"about:blank\" id=\"fr3\">"
76     "</frameset></html>";
77 static const char emptydiv_str[] =
78     "<html><head><title>emptydiv test</title></head>"
79     "<body><div id=\"divid\"></div></body></html>";
80
81 static WCHAR characterW[] = {'c','h','a','r','a','c','t','e','r',0};
82 static WCHAR texteditW[] = {'t','e','x','t','e','d','i','t',0};
83 static WCHAR wordW[] = {'w','o','r','d',0};
84
85 typedef enum {
86     ET_NONE,
87     ET_HTML,
88     ET_HEAD,
89     ET_TITLE,
90     ET_BODY,
91     ET_A,
92     ET_INPUT,
93     ET_SELECT,
94     ET_TEXTAREA,
95     ET_OPTION,
96     ET_STYLE,
97     ET_BLOCKQUOTE,
98     ET_P,
99     ET_BR,
100     ET_TABLE,
101     ET_TBODY,
102     ET_SCRIPT,
103     ET_TEST,
104     ET_TESTG,
105     ET_COMMENT,
106     ET_IMG,
107     ET_TR,
108     ET_TD,
109     ET_IFRAME,
110     ET_FORM,
111     ET_FRAME,
112     ET_OBJECT,
113     ET_EMBED,
114     ET_DIV
115 } elem_type_t;
116
117 static const IID * const none_iids[] = {
118     &IID_IUnknown,
119     NULL
120 };
121
122 static const IID * const doc_node_iids[] = {
123     &IID_IHTMLDOMNode,
124     &IID_IHTMLDOMNode2,
125     &IID_IHTMLDocument,
126     &IID_IHTMLDocument2,
127     &IID_IHTMLDocument3,
128     &IID_IHTMLDocument4,
129     &IID_IHTMLDocument5,
130     &IID_IDispatchEx,
131     &IID_IConnectionPointContainer,
132     &IID_IInternetHostSecurityManager,
133     &IID_IOleContainer,
134     &IID_IObjectSafety,
135     &IID_IProvideClassInfo,
136     NULL
137 };
138
139 static const IID * const doc_obj_iids[] = {
140     &IID_IHTMLDocument,
141     &IID_IHTMLDocument2,
142     &IID_IHTMLDocument3,
143     &IID_IHTMLDocument4,
144     &IID_IHTMLDocument5,
145     &IID_IDispatchEx,
146     &IID_IConnectionPointContainer,
147     &IID_ICustomDoc,
148     &IID_IOleContainer,
149     &IID_IObjectSafety,
150     &IID_IProvideClassInfo,
151     NULL
152 };
153
154 #define ELEM_IFACES \
155     &IID_IHTMLDOMNode,  \
156     &IID_IHTMLDOMNode2, \
157     &IID_IHTMLElement,  \
158     &IID_IHTMLElement2, \
159     &IID_IHTMLElement3, \
160     &IID_IHTMLElement4, \
161     &IID_IDispatchEx
162
163 static const IID * const elem_iids[] = {
164     ELEM_IFACES,
165     &IID_IConnectionPointContainer,
166     NULL
167 };
168
169 static const IID * const body_iids[] = {
170     ELEM_IFACES,
171     &IID_IHTMLTextContainer,
172     &IID_IHTMLBodyElement,
173     &IID_IConnectionPointContainer,
174     NULL
175 };
176
177 static const IID * const anchor_iids[] = {
178     ELEM_IFACES,
179     &IID_IHTMLAnchorElement,
180     &IID_IConnectionPointContainer,
181     NULL
182 };
183
184 static const IID * const input_iids[] = {
185     ELEM_IFACES,
186     &IID_IHTMLInputElement,
187     &IID_IHTMLInputTextElement,
188     &IID_IConnectionPointContainer,
189     NULL
190 };
191
192 static const IID * const select_iids[] = {
193     ELEM_IFACES,
194     &IID_IHTMLSelectElement,
195     &IID_IConnectionPointContainer,
196     NULL
197 };
198
199 static const IID * const textarea_iids[] = {
200     ELEM_IFACES,
201     &IID_IHTMLTextAreaElement,
202     &IID_IConnectionPointContainer,
203     NULL
204 };
205
206 static const IID * const option_iids[] = {
207     ELEM_IFACES,
208     &IID_IHTMLOptionElement,
209     &IID_IConnectionPointContainer,
210     NULL
211 };
212
213 static const IID * const table_iids[] = {
214     ELEM_IFACES,
215     &IID_IHTMLTable,
216     &IID_IHTMLTable2,
217     &IID_IHTMLTable3,
218     &IID_IConnectionPointContainer,
219     NULL
220 };
221
222 static const IID * const script_iids[] = {
223     ELEM_IFACES,
224     &IID_IHTMLScriptElement,
225     &IID_IConnectionPointContainer,
226     NULL
227 };
228
229 static const IID * const text_iids[] = {
230     &IID_IHTMLDOMNode,
231     &IID_IHTMLDOMNode2,
232     &IID_IHTMLDOMTextNode,
233     NULL
234 };
235
236 static const IID * const attr_iids[] = {
237     &IID_IHTMLDOMAttribute,
238     &IID_IDispatchEx,
239     NULL
240 };
241
242 static const IID * const location_iids[] = {
243     &IID_IDispatch,
244     &IID_IHTMLLocation,
245     NULL
246 };
247
248 static const IID * const window_iids[] = {
249     &IID_IDispatch,
250     &IID_IHTMLWindow2,
251     &IID_IHTMLWindow3,
252     &IID_IDispatchEx,
253     &IID_IServiceProvider,
254     NULL
255 };
256
257 static const IID * const comment_iids[] = {
258     ELEM_IFACES,
259     &IID_IHTMLCommentElement,
260     &IID_IConnectionPointContainer,
261     NULL
262 };
263
264 static const IID * const img_iids[] = {
265     ELEM_IFACES,
266     &IID_IHTMLImgElement,
267     &IID_IConnectionPointContainer,
268     NULL
269 };
270
271 static const IID * const tr_iids[] = {
272     ELEM_IFACES,
273     &IID_IHTMLTableRow,
274     &IID_IConnectionPointContainer,
275     NULL
276 };
277
278 static const IID * const td_iids[] = {
279     ELEM_IFACES,
280     &IID_IConnectionPointContainer,
281     NULL
282 };
283
284 static const IID * const frame_iids[] = {
285     ELEM_IFACES,
286     &IID_IHTMLFrameBase,
287     &IID_IHTMLFrameBase2,
288     &IID_IConnectionPointContainer,
289     NULL
290 };
291
292 static const IID * const head_iids[] = {
293     ELEM_IFACES,
294     &IID_IHTMLHeadElement,
295     &IID_IConnectionPointContainer,
296     NULL
297 };
298
299 static const IID * const title_iids[] = {
300     ELEM_IFACES,
301     &IID_IHTMLTitleElement,
302     &IID_IConnectionPointContainer,
303     NULL
304 };
305
306 static const IID * const object_iids[] = {
307     ELEM_IFACES,
308     &IID_IHTMLObjectElement,
309     /* FIXME: No IConnectionPointContainer */
310     NULL
311 };
312
313 static const IID * const embed_iids[] = {
314     ELEM_IFACES,
315     &IID_IHTMLEmbedElement,
316     /* FIXME: No IConnectionPointContainer */
317     NULL
318 };
319
320 static const IID * const iframe_iids[] = {
321     ELEM_IFACES,
322     &IID_IHTMLFrameBase,
323     &IID_IHTMLFrameBase2,
324     &IID_IHTMLIFrameElement,
325     &IID_IConnectionPointContainer,
326     NULL
327 };
328
329 static const IID * const form_iids[] = {
330     ELEM_IFACES,
331     &IID_IHTMLFormElement,
332     &IID_IConnectionPointContainer,
333     NULL
334 };
335
336 static const IID * const styleelem_iids[] = {
337     ELEM_IFACES,
338     &IID_IHTMLStyleElement,
339     &IID_IConnectionPointContainer,
340     NULL
341 };
342
343 static const IID * const generic_iids[] = {
344     ELEM_IFACES,
345     &IID_IHTMLGenericElement,
346     &IID_IConnectionPointContainer,
347     NULL
348 };
349
350 static const IID * const style_iids[] = {
351     &IID_IUnknown,
352     &IID_IDispatch,
353     &IID_IDispatchEx,
354     &IID_IHTMLStyle,
355     &IID_IHTMLStyle2,
356     &IID_IHTMLStyle3,
357     &IID_IHTMLStyle4,
358     NULL
359 };
360
361 static const IID * const cstyle_iids[] = {
362     &IID_IUnknown,
363     &IID_IDispatch,
364     &IID_IDispatchEx,
365     &IID_IHTMLCurrentStyle,
366     &IID_IHTMLCurrentStyle2,
367     &IID_IHTMLCurrentStyle3,
368     NULL
369 };
370
371 static const IID * const img_factory_iids[] = {
372     &IID_IUnknown,
373     &IID_IDispatch,
374     &IID_IDispatchEx,
375     &IID_IHTMLImageElementFactory,
376     NULL
377 };
378
379 typedef struct {
380     const char *tag;
381     REFIID *iids;
382     const IID *dispiid;
383 } elem_type_info_t;
384
385 static const elem_type_info_t elem_type_infos[] = {
386     {"",          none_iids,        NULL},
387     {"HTML",      elem_iids,        NULL},
388     {"HEAD",      head_iids,        &DIID_DispHTMLHeadElement},
389     {"TITLE",     title_iids,       &DIID_DispHTMLTitleElement},
390     {"BODY",      body_iids,        &DIID_DispHTMLBody},
391     {"A",         anchor_iids,      &DIID_DispHTMLAnchorElement},
392     {"INPUT",     input_iids,       &DIID_DispHTMLInputElement},
393     {"SELECT",    select_iids,      &DIID_DispHTMLSelectElement},
394     {"TEXTAREA",  textarea_iids,    &DIID_DispHTMLTextAreaElement},
395     {"OPTION",    option_iids,      &DIID_DispHTMLOptionElement},
396     {"STYLE",     styleelem_iids,   &DIID_DispHTMLStyleElement},
397     {"BLOCKQUOTE",elem_iids,        NULL},
398     {"P",         elem_iids,        NULL},
399     {"BR",        elem_iids,        NULL},
400     {"TABLE",     table_iids,       &DIID_DispHTMLTable},
401     {"TBODY",     elem_iids,        NULL},
402     {"SCRIPT",    script_iids,      &DIID_DispHTMLScriptElement},
403     {"TEST",      elem_iids,        &DIID_DispHTMLUnknownElement},
404     {"TEST",      generic_iids,     &DIID_DispHTMLGenericElement},
405     {"!",         comment_iids,     &DIID_DispHTMLCommentElement},
406     {"IMG",       img_iids,         &DIID_DispHTMLImg},
407     {"TR",        tr_iids,          &DIID_DispHTMLTableRow},
408     {"TD",        td_iids,          NULL},
409     {"IFRAME",    iframe_iids,      &DIID_DispHTMLIFrame},
410     {"FORM",      form_iids,        &DIID_DispHTMLFormElement},
411     {"FRAME",     frame_iids,       &DIID_DispHTMLFrameElement},
412     {"OBJECT",    object_iids,      &DIID_DispHTMLObjectElement},
413     {"EMBED",     embed_iids,       &DIID_DispHTMLEmbed},
414     {"DIV",       elem_iids,        NULL}
415 };
416
417 static const char *dbgstr_guid(REFIID riid)
418 {
419     static char buf[50];
420
421     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
422             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
423             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
424             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
425
426     return buf;
427 }
428
429 static int strcmp_wa(LPCWSTR strw, const char *stra)
430 {
431     CHAR buf[512];
432     WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
433     return lstrcmpA(stra, buf);
434 }
435
436 static BSTR a2bstr(const char *str)
437 {
438     BSTR ret;
439     int len;
440
441     if(!str)
442         return NULL;
443
444     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
445     ret = SysAllocStringLen(NULL, len);
446     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
447
448     return ret;
449 }
450
451 static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
452 {
453     IUnknown *unk1, *unk2;
454
455     if(iface1 == iface2)
456         return TRUE;
457
458     IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
459     IUnknown_Release(unk1);
460     IUnknown_QueryInterface(iface2, &IID_IUnknown, (void**)&unk2);
461     IUnknown_Release(unk2);
462
463     return unk1 == unk2;
464 }
465
466 static IHTMLDocument2 *create_document(void)
467 {
468     IHTMLDocument2 *doc;
469     IHTMLDocument5 *doc5;
470     HRESULT hres;
471
472     hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
473             &IID_IHTMLDocument2, (void**)&doc);
474     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
475     if(FAILED(hres))
476         return NULL;
477
478     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5);
479     if(FAILED(hres)) {
480         win_skip("Could not get IHTMLDocument5, probably too old IE\n");
481         IHTMLDocument2_Release(doc);
482         return NULL;
483     }
484
485     IHTMLDocument5_Release(doc5);
486     return doc;
487 }
488
489 #define get_dispex_iface(u) _get_dispex_iface(__LINE__,u)
490 static IDispatchEx *_get_dispex_iface(unsigned line, IUnknown *unk)
491 {
492     IDispatchEx *dispex;
493     HRESULT hres;
494
495     hres = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex);
496     ok_(__FILE__,line) (hres == S_OK, "Could not get IDispatchEx: %08x\n", hres);
497     return dispex;
498 }
499
500 #define test_ifaces(i,ids) _test_ifaces(__LINE__,i,ids)
501 static void _test_ifaces(unsigned line, IUnknown *iface, REFIID *iids)
502 {
503     const IID * const *piid;
504     IUnknown *unk;
505     HRESULT hres;
506
507      for(piid = iids; *piid; piid++) {
508         hres = IDispatch_QueryInterface(iface, *piid, (void**)&unk);
509         ok_(__FILE__,line) (hres == S_OK, "Could not get %s interface: %08x\n", dbgstr_guid(*piid), hres);
510         if(SUCCEEDED(hres))
511             IUnknown_Release(unk);
512     }
513 }
514
515 #define test_no_iface(a,b) _test_no_iface(__LINE__,a,b)
516 static void _test_no_iface(unsigned line, IUnknown *iface, REFIID iid)
517 {
518     IUnknown *unk;
519     HRESULT hres;
520
521     unk = (void*)0xdeadbeef;
522     hres = IUnknown_QueryInterface(iface, iid, (void**)&unk);
523     ok_(__FILE__,line)(hres == E_NOINTERFACE, "hres = %08x, expected E_NOINTERFACE\n", hres);
524     ok_(__FILE__,line)(!unk, "unk = %p\n", unk);
525 }
526
527 #define test_get_dispid(u,id) _test_get_dispid(__LINE__,u,id)
528 static BOOL _test_get_dispid(unsigned line, IUnknown *unk, IID *iid)
529 {
530     IDispatchEx *dispex = _get_dispex_iface(line, unk);
531     ITypeInfo *typeinfo;
532     BOOL ret = FALSE;
533     UINT ticnt;
534     HRESULT hres;
535
536     ticnt = 0xdeadbeef;
537     hres = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
538     ok_(__FILE__,line) (hres == S_OK, "GetTypeInfoCount failed: %08x\n", hres);
539     ok_(__FILE__,line) (ticnt == 1, "ticnt=%u\n", ticnt);
540
541     hres = IDispatchEx_GetTypeInfo(dispex, 0, 0, &typeinfo);
542     ok_(__FILE__,line) (hres == S_OK, "GetTypeInfo failed: %08x\n", hres);
543
544     if(SUCCEEDED(hres)) {
545         TYPEATTR *type_attr;
546
547         hres = ITypeInfo_GetTypeAttr(typeinfo, &type_attr);
548         ok_(__FILE__,line) (hres == S_OK, "GetTypeAttr failed: %08x\n", hres);
549         if(hres == S_OK) {
550             *iid = type_attr->guid;
551             ret = TRUE;
552         }
553
554         ITypeInfo_ReleaseTypeAttr(typeinfo, type_attr);
555         ITypeInfo_Release(typeinfo);
556     }
557
558     IDispatchEx_Release(dispex);
559     return ret;
560 }
561
562 #define test_disp_value(u) _test_disp_value(__LINE__,u,v)
563 static void _test_disp_value(unsigned line, IUnknown *unk, const char *val)
564 {
565     IDispatchEx *dispex = _get_dispex_iface(line, unk);
566     DISPPARAMS dp  = {NULL,NULL,0,0};
567     EXCEPINFO ei;
568     VARIANT var;
569     HRESULT hres;
570
571     hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, 0, DISPATCH_PROPERTYGET, &dp, &var, &ei, NULL);
572     IDispatchEx_Release(dispex);
573     ok_(__FILE__,line)(hres == S_OK, "InvokeEx(DISPID_VALUE) returned: %08x\n", hres);
574
575     ok_(__FILE__,line)(V_VT(&var) == VT_BSTR, "V_VT(value) = %d\n", V_VT(&var));
576     ok_(__FILE__,line)(!strcmp_wa(V_BSTR(&var), val), "value = %s, expected %s\n", wine_dbgstr_w(V_BSTR(&var)), val);
577     VariantClear(&var);
578 }
579
580 #define test_disp(u,id,v) _test_disp(__LINE__,u,id,v)
581 static void _test_disp(unsigned line, IUnknown *unk, const IID *diid, const char *val)
582 {
583     IID iid;
584
585     if(_test_get_dispid(line, unk, &iid))
586         ok_(__FILE__,line) (IsEqualGUID(&iid, diid), "unexpected guid %s\n", dbgstr_guid(&iid));
587
588     if(val)
589         _test_disp_value(line, unk, val);
590 }
591
592 #define test_disp2(u,id,id2,v) _test_disp2(__LINE__,u,id,id2,v)
593 static void _test_disp2(unsigned line, IUnknown *unk, const IID *diid, const IID *diid2, const char *val)
594 {
595     IID iid;
596
597     if(_test_get_dispid(line, unk, &iid))
598         ok_(__FILE__,line) (IsEqualGUID(&iid, diid) || broken(IsEqualGUID(&iid, diid2)),
599                 "unexpected guid %s\n", dbgstr_guid(&iid));
600
601     if(val)
602         _test_disp_value(line, unk, val);
603 }
604
605 #define test_class_info(u) _test_class_info(__LINE__,u)
606 static void _test_class_info(unsigned line, IUnknown *unk)
607 {
608     IProvideClassInfo *classinfo;
609     ITypeInfo *typeinfo;
610     TYPEATTR *type_attr;
611     HRESULT hres;
612
613     hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo, (void**)&classinfo);
614     ok_(__FILE__,line)(hres == S_OK, "Could not get IProvideClassInfo interface: %08x\n", hres);
615     if(FAILED(hres))
616         return;
617
618     hres = IProvideClassInfo_GetClassInfo(classinfo, &typeinfo);
619     ok_(__FILE__,line)(hres == S_OK, "Could not get ITypeInfo interface: %08x\n", hres);
620     if(FAILED(hres))
621     {
622         IProvideClassInfo_Release(classinfo);
623         return;
624     }
625
626     hres = ITypeInfo_GetTypeAttr(typeinfo, &type_attr);
627     ok_(__FILE__,line)(hres == S_OK, "GetTypeAttr failed: %08x\n", hres);
628     if(SUCCEEDED(hres))
629     {
630         ok_(__FILE__,line)(IsEqualGUID(&type_attr->guid, &CLSID_HTMLDocument),
631                 "unexpected guid %s\n", dbgstr_guid(&type_attr->guid));
632         ok_(__FILE__,line)(type_attr->typekind == TKIND_COCLASS,
633                 "unexpected typekind %d\n", type_attr->typekind);
634         ITypeInfo_ReleaseTypeAttr(typeinfo, type_attr);
635     }
636
637     ITypeInfo_Release(typeinfo);
638     IProvideClassInfo_Release(classinfo);
639 }
640
641 #define set_dispex_value(a,b,c) _set_dispex_value(__LINE__,a,b,c)
642 static void _set_dispex_value(unsigned line, IUnknown *unk, const char *name, VARIANT *val)
643 {
644     IDispatchEx *dispex = _get_dispex_iface(line, unk);
645     DISPPARAMS dp = {val, NULL, 1, 0};
646     EXCEPINFO ei;
647     DISPID id;
648     BSTR str;
649     HRESULT hres;
650
651     str = a2bstr(name);
652     hres = IDispatchEx_GetDispID(dispex, str, fdexNameEnsure|fdexNameCaseInsensitive, &id);
653     SysFreeString(str);
654     ok_(__FILE__,line)(hres == S_OK, "GetDispID failed: %08x\n", hres);
655
656     memset(&ei, 0, sizeof(ei));
657     hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, INVOKE_PROPERTYPUT, &dp, NULL, &ei, NULL);
658     ok_(__FILE__,line)(hres == S_OK, "InvokeEx failed: %08x\n", hres);
659
660 }
661
662 #define get_elem_iface(u) _get_elem_iface(__LINE__,u)
663 static IHTMLElement *_get_elem_iface(unsigned line, IUnknown *unk)
664 {
665     IHTMLElement *elem;
666     HRESULT hres;
667
668     hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement, (void**)&elem);
669     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement: %08x\n", hres);
670     return elem;
671 }
672
673 #define get_elem2_iface(u) _get_elem2_iface(__LINE__,u)
674 static IHTMLElement2 *_get_elem2_iface(unsigned line, IUnknown *unk)
675 {
676     IHTMLElement2 *elem;
677     HRESULT hres;
678
679     hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement2, (void**)&elem);
680     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement2: %08x\n", hres);
681     return elem;
682 }
683
684 #define get_elem3_iface(u) _get_elem3_iface(__LINE__,u)
685 static IHTMLElement3 *_get_elem3_iface(unsigned line, IUnknown *unk)
686 {
687     IHTMLElement3 *elem;
688     HRESULT hres;
689
690     hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement3, (void**)&elem);
691     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement3: %08x\n", hres);
692     return elem;
693 }
694
695 #define get_elem4_iface(u) _get_elem4_iface(__LINE__,u)
696 static IHTMLElement4 *_get_elem4_iface(unsigned line, IUnknown *unk)
697 {
698     IHTMLElement4 *elem;
699     HRESULT hres;
700
701     hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement4, (void**)&elem);
702     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement4: %08x\n", hres);
703     return elem;
704 }
705
706 #define get_node_iface(u) _get_node_iface(__LINE__,u)
707 static IHTMLDOMNode *_get_node_iface(unsigned line, IUnknown *unk)
708 {
709     IHTMLDOMNode *node;
710     HRESULT hres;
711
712     hres = IUnknown_QueryInterface(unk, &IID_IHTMLDOMNode, (void**)&node);
713     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDOMNode: %08x\n", hres);
714     return node;
715 }
716
717 #define get_node2_iface(u) _get_node2_iface(__LINE__,u)
718 static IHTMLDOMNode2 *_get_node2_iface(unsigned line, IUnknown *unk)
719 {
720     IHTMLDOMNode2 *node;
721     HRESULT hres;
722
723     hres = IUnknown_QueryInterface(unk, &IID_IHTMLDOMNode2, (void**)&node);
724     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDOMNode2: %08x\n", hres);
725     return node;
726 }
727
728 #define get_img_iface(u) _get_img_iface(__LINE__,u)
729 static IHTMLImgElement *_get_img_iface(unsigned line, IUnknown *unk)
730 {
731     IHTMLImgElement *img;
732     HRESULT hres;
733
734     hres = IUnknown_QueryInterface(unk, &IID_IHTMLImgElement, (void**)&img);
735     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLImgElement: %08x\n", hres);
736     return img;
737 }
738
739 #define get_anchor_iface(u) _get_anchor_iface(__LINE__,u)
740 static IHTMLAnchorElement *_get_anchor_iface(unsigned line, IUnknown *unk)
741 {
742     IHTMLAnchorElement *anchor;
743     HRESULT hres;
744
745     hres = IUnknown_QueryInterface(unk, &IID_IHTMLAnchorElement, (void**)&anchor);
746     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLAnchorElement: %08x\n", hres);
747     return anchor;
748 }
749
750 #define get_textarea_iface(u) _get_textarea_iface(__LINE__,u)
751 static IHTMLTextAreaElement *_get_textarea_iface(unsigned line, IUnknown *unk)
752 {
753     IHTMLTextAreaElement *textarea;
754     HRESULT hres;
755
756     hres = IUnknown_QueryInterface(unk, &IID_IHTMLTextAreaElement, (void**)&textarea);
757     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLTextAreaElement: %08x\n", hres);
758     return textarea;
759 }
760
761 #define get_select_iface(u) _get_select_iface(__LINE__,u)
762 static IHTMLSelectElement *_get_select_iface(unsigned line, IUnknown *unk)
763 {
764     IHTMLSelectElement *select;
765     HRESULT hres;
766
767     hres = IUnknown_QueryInterface(unk, &IID_IHTMLSelectElement, (void**)&select);
768     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLSelectElement: %08x\n", hres);
769     return select;
770 }
771
772 #define get_form_iface(u) _get_form_iface(__LINE__,u)
773 static IHTMLFormElement *_get_form_iface(unsigned line, IUnknown *unk)
774 {
775     IHTMLFormElement *form;
776     HRESULT hres;
777
778     hres = IUnknown_QueryInterface(unk, &IID_IHTMLFormElement, (void**)&form);
779     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLFormElement: %08x\n", hres);
780     return form;
781 }
782
783 #define get_text_iface(u) _get_text_iface(__LINE__,u)
784 static IHTMLDOMTextNode *_get_text_iface(unsigned line, IUnknown *unk)
785 {
786     IHTMLDOMTextNode *text;
787     HRESULT hres;
788
789     hres = IUnknown_QueryInterface(unk, &IID_IHTMLDOMTextNode, (void**)&text);
790     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDOMTextNode: %08x\n", hres);
791     return text;
792 }
793
794 #define get_comment_iface(u) _get_comment_iface(__LINE__,u)
795 static IHTMLCommentElement *_get_comment_iface(unsigned line, IUnknown *unk)
796 {
797     IHTMLCommentElement *comment;
798     HRESULT hres;
799
800     hres = IUnknown_QueryInterface(unk, &IID_IHTMLCommentElement, (void**)&comment);
801     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLCommentElement: %08x\n", hres);
802     return comment;
803 }
804
805 #define get_object_iface(u) _get_object_iface(__LINE__,u)
806 static IHTMLObjectElement *_get_object_iface(unsigned line, IUnknown *unk)
807 {
808     IHTMLObjectElement *obj;
809     HRESULT hres;
810
811     hres = IUnknown_QueryInterface(unk, &IID_IHTMLObjectElement, (void**)&obj);
812     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLObjectElement: %08x\n", hres);
813     return obj;
814 }
815
816 #define get_style_iface(u) _get_style_iface(__LINE__,u)
817 static IHTMLStyleElement *_get_style_iface(unsigned line, IUnknown *unk)
818 {
819     IHTMLStyleElement *obj;
820     HRESULT hres;
821
822     hres = IUnknown_QueryInterface(unk, &IID_IHTMLStyleElement, (void**)&obj);
823     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLStyleElement: %08x\n", hres);
824     return obj;
825 }
826
827 #define test_node_name(u,n) _test_node_name(__LINE__,u,n)
828 static void _test_node_name(unsigned line, IUnknown *unk, const char *exname)
829 {
830     IHTMLDOMNode *node = _get_node_iface(line, unk);
831     BSTR name;
832     HRESULT hres;
833
834     hres = IHTMLDOMNode_get_nodeName(node, &name);
835     IHTMLDOMNode_Release(node);
836     ok_(__FILE__, line) (hres == S_OK, "get_nodeName failed: %08x\n", hres);
837     ok_(__FILE__, line) (!strcmp_wa(name, exname), "got name: %s, expected %s\n", wine_dbgstr_w(name), exname);
838
839     SysFreeString(name);
840 }
841
842 #define get_owner_doc(u) _get_owner_doc(__LINE__,u)
843 static IHTMLDocument2 *_get_owner_doc(unsigned line, IUnknown *unk)
844 {
845     IHTMLDOMNode2 *node = _get_node2_iface(line, unk);
846     IDispatch *disp = (void*)0xdeadbeef;
847     IHTMLDocument2 *doc = NULL;
848     HRESULT hres;
849
850     hres = IHTMLDOMNode2_get_ownerDocument(node, &disp);
851     IHTMLDOMNode2_Release(node);
852     ok_(__FILE__,line)(hres == S_OK, "get_ownerDocument failed: %08x\n", hres);
853
854     if(disp) {
855         hres = IDispatch_QueryInterface(disp, &IID_IHTMLDocument2, (void**)&doc);
856         IDispatch_Release(disp);
857         ok_(__FILE__,line)(hres == S_OK, "Could not get IHTMLDocument2 iface: %08x\n", hres);
858     }
859
860     return doc;
861 }
862
863 #define get_doc_window(d) _get_doc_window(__LINE__,d)
864 static IHTMLWindow2 *_get_doc_window(unsigned line, IHTMLDocument2 *doc)
865 {
866     IHTMLWindow2 *window;
867     HRESULT hres;
868
869     window = NULL;
870     hres = IHTMLDocument2_get_parentWindow(doc, &window);
871     ok_(__FILE__,line)(hres == S_OK, "get_parentWindow failed: %08x\n", hres);
872     ok_(__FILE__,line)(window != NULL, "window == NULL\n");
873
874     return window;
875 }
876
877 #define clone_node(n,d) _clone_node(__LINE__,n,d)
878 static IHTMLDOMNode *_clone_node(unsigned line, IUnknown *unk, VARIANT_BOOL deep)
879 {
880     IHTMLDOMNode *node = _get_node_iface(line, unk);
881     IHTMLDOMNode *ret = NULL;
882     HRESULT hres;
883
884     hres = IHTMLDOMNode_cloneNode(node, deep, &ret);
885     IHTMLDOMNode_Release(node);
886     ok_(__FILE__,line)(hres == S_OK, "cloneNode failed: %08x\n", hres);
887     ok_(__FILE__,line)(ret != NULL, "ret == NULL\n");
888
889     return ret;
890
891 }
892
893 #define test_elem_tag(u,n) _test_elem_tag(__LINE__,u,n)
894 static void _test_elem_tag(unsigned line, IUnknown *unk, const char *extag)
895 {
896     IHTMLElement *elem = _get_elem_iface(line, unk);
897     BSTR tag;
898     HRESULT hres;
899
900     hres = IHTMLElement_get_tagName(elem, &tag);
901     IHTMLElement_Release(elem);
902     ok_(__FILE__, line) (hres == S_OK, "get_tagName failed: %08x\n", hres);
903     ok_(__FILE__, line) (!strcmp_wa(tag, extag), "got tag: %s, expected %s\n", wine_dbgstr_w(tag), extag);
904
905     SysFreeString(tag);
906 }
907
908 #define test_elem_type(ifc,t) _test_elem_type(__LINE__,ifc,t)
909 static void _test_elem_type(unsigned line, IUnknown *unk, elem_type_t type)
910 {
911     _test_elem_tag(line, unk, elem_type_infos[type].tag);
912     _test_ifaces(line, unk, elem_type_infos[type].iids);
913
914     if(elem_type_infos[type].dispiid && type != ET_A)
915         _test_disp(line, unk, elem_type_infos[type].dispiid, "[object]");
916 }
917
918 #define get_node_type(n) _get_node_type(__LINE__,n)
919 static LONG _get_node_type(unsigned line, IUnknown *unk)
920 {
921     IHTMLDOMNode *node = _get_node_iface(line, unk);
922     LONG type = -1;
923     HRESULT hres;
924
925     hres = IHTMLDOMNode_get_nodeType(node, &type);
926     ok(hres == S_OK, "get_nodeType failed: %08x\n", hres);
927
928     IHTMLDOMNode_Release(node);
929
930     return type;
931 }
932
933 #define get_child_nodes(u) _get_child_nodes(__LINE__,u)
934 static IHTMLDOMChildrenCollection *_get_child_nodes(unsigned line, IUnknown *unk)
935 {
936     IHTMLDOMNode *node = _get_node_iface(line, unk);
937     IHTMLDOMChildrenCollection *col = NULL;
938     IDispatch *disp;
939     HRESULT hres;
940
941     hres = IHTMLDOMNode_get_childNodes(node, &disp);
942     IHTMLDOMNode_Release(node);
943     ok_(__FILE__,line) (hres == S_OK, "get_childNodes failed: %08x\n", hres);
944     if(FAILED(hres))
945         return NULL;
946
947     hres = IDispatch_QueryInterface(disp, &IID_IHTMLDOMChildrenCollection, (void**)&col);
948     IDispatch_Release(disp);
949     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDOMChildrenCollection: %08x\n", hres);
950
951     return col;
952 }
953
954 #define get_child_item(c,i) _get_child_item(__LINE__,c,i)
955 static IHTMLDOMNode *_get_child_item(unsigned line, IHTMLDOMChildrenCollection *col, LONG idx)
956 {
957     IHTMLDOMNode *node = NULL;
958     IDispatch *disp;
959     HRESULT hres;
960
961     hres = IHTMLDOMChildrenCollection_item(col, idx, &disp);
962     ok(hres == S_OK, "item failed: %08x\n", hres);
963
964     node = _get_node_iface(line, (IUnknown*)disp);
965     IDispatch_Release(disp);
966
967     return node;
968 }
969
970 #define test_elem_attr(e,n,v) _test_elem_attr(__LINE__,e,n,v)
971 static void _test_elem_attr(unsigned line, IHTMLElement *elem, const char *name, const char *exval)
972 {
973     VARIANT value;
974     BSTR tmp;
975     HRESULT hres;
976
977     VariantInit(&value);
978
979     tmp = a2bstr(name);
980     hres = IHTMLElement_getAttribute(elem, tmp, 0, &value);
981     SysFreeString(tmp);
982     ok_(__FILE__,line) (hres == S_OK, "getAttribute failed: %08x\n", hres);
983
984     if(exval) {
985         ok_(__FILE__,line) (V_VT(&value) == VT_BSTR, "vt=%d\n", V_VT(&value));
986         ok_(__FILE__,line) (!strcmp_wa(V_BSTR(&value), exval), "unexpected value %s\n", wine_dbgstr_w(V_BSTR(&value)));
987     }else {
988         ok_(__FILE__,line) (V_VT(&value) == VT_NULL, "vt=%d\n", V_VT(&value));
989     }
990
991     VariantClear(&value);
992 }
993
994 #define test_elem_offset(a,b) _test_elem_offset(__LINE__,a,b)
995 static void _test_elem_offset(unsigned line, IUnknown *unk, const char *parent_tag)
996 {
997     IHTMLElement *elem = _get_elem_iface(line, unk);
998     IHTMLElement *off_parent;
999     LONG l;
1000     HRESULT hres;
1001
1002     hres = IHTMLElement_get_offsetTop(elem, &l);
1003     ok_(__FILE__,line) (hres == S_OK, "get_offsetTop failed: %08x\n", hres);
1004
1005     hres = IHTMLElement_get_offsetHeight(elem, &l);
1006     ok_(__FILE__,line) (hres == S_OK, "get_offsetHeight failed: %08x\n", hres);
1007
1008     hres = IHTMLElement_get_offsetWidth(elem, &l);
1009     ok_(__FILE__,line) (hres == S_OK, "get_offsetWidth failed: %08x\n", hres);
1010
1011     hres = IHTMLElement_get_offsetLeft(elem, &l);
1012     ok_(__FILE__,line) (hres == S_OK, "get_offsetLeft failed: %08x\n", hres);
1013
1014     hres = IHTMLElement_get_offsetParent(elem, &off_parent);
1015     ok_(__FILE__,line) (hres == S_OK, "get_offsetParent failed: %08x\n", hres);
1016
1017     _test_elem_tag(line, (IUnknown*)off_parent, parent_tag);
1018     IHTMLElement_Release(off_parent);
1019
1020     IHTMLElement_Release(elem);
1021 }
1022
1023 #define get_doc_node(d) _get_doc_node(__LINE__,d)
1024 static IHTMLDocument2 *_get_doc_node(unsigned line, IHTMLDocument2 *doc)
1025 {
1026     IHTMLWindow2 *window;
1027     IHTMLDocument2 *ret;
1028     HRESULT hres;
1029
1030     hres = IHTMLDocument2_get_parentWindow(doc, &window);
1031     ok_(__FILE__,line)(hres == S_OK, "get_parentWindow failed: %08x\n", hres);
1032
1033     hres = IHTMLWindow2_get_document(window, &ret);
1034     ok_(__FILE__,line)(hres == S_OK, "get_document failed: %08x\n", hres);
1035     ok_(__FILE__,line)(ret != NULL, "document = NULL\n");
1036
1037     return ret;
1038 }
1039
1040 #define test_window_name(d,e) _test_window_name(__LINE__,d,e)
1041 static void _test_window_name(unsigned line, IHTMLWindow2 *window, const char *exname)
1042 {
1043     BSTR name;
1044     HRESULT hres;
1045
1046     hres = IHTMLWindow2_get_name(window, &name);
1047     ok_(__FILE__,line)(hres == S_OK, "get_name failed: %08x\n", hres);
1048     if(exname)
1049         ok_(__FILE__,line)(!strcmp_wa(name, exname), "name = %s\n", wine_dbgstr_w(name));
1050     else
1051         ok_(__FILE__,line)(!name, "name = %s\n", wine_dbgstr_w(name));
1052     SysFreeString(name);
1053 }
1054
1055 #define set_window_name(w,n) _set_window_name(__LINE__,w,n)
1056 static void _set_window_name(unsigned line, IHTMLWindow2 *window, const char *name)
1057 {
1058     BSTR str;
1059     HRESULT hres;
1060
1061     str = a2bstr(name);
1062     hres = IHTMLWindow2_put_name(window, str);
1063     SysFreeString(str);
1064     ok_(__FILE__,line)(hres == S_OK, "put_name failed: %08x\n", hres);
1065
1066     _test_window_name(line, window, name);
1067 }
1068
1069 #define test_window_status(d) _test_window_status(__LINE__,d)
1070 static void _test_window_status(unsigned line, IHTMLWindow2 *window)
1071 {
1072     BSTR status;
1073     HRESULT hres;
1074
1075     status = (void*)0xdeadbeef;
1076     hres = IHTMLWindow2_get_status(window, &status);
1077     ok_(__FILE__,line)(hres == S_OK, "get_status failed: %08x\n", hres);
1078     ok_(__FILE__,line)(!status, "status = %s\n", wine_dbgstr_w(status));
1079     SysFreeString(status);
1080 }
1081
1082 #define set_window_status(w,n) _set_window_status(__LINE__,w,n)
1083 static void _set_window_status(unsigned line, IHTMLWindow2 *window, const char *status)
1084 {
1085     BSTR str;
1086     HRESULT hres;
1087
1088     str = a2bstr(status);
1089     hres = IHTMLWindow2_put_status(window, str);
1090     SysFreeString(str);
1091     ok_(__FILE__,line)(hres == S_OK, "put_status failed: %08x\n", hres);
1092 }
1093
1094 #define test_window_length(w,l) _test_window_length(__LINE__,w,l)
1095 static void _test_window_length(unsigned line, IHTMLWindow2 *window, LONG exlen)
1096 {
1097     LONG length = -1;
1098     HRESULT hres;
1099
1100     hres = IHTMLWindow2_get_length(window, &length);
1101     ok_(__FILE__,line)(hres == S_OK, "get_length failed: %08x\n", hres);
1102     ok_(__FILE__,line)(length == exlen, "length = %d, expected %d\n", length, exlen);
1103 }
1104
1105 #define get_frame_content_window(e) _get_frame_content_window(__LINE__,e)
1106 static IHTMLWindow2 *_get_frame_content_window(unsigned line, IUnknown *elem)
1107 {
1108     IHTMLFrameBase2 *base2;
1109     IHTMLWindow2 *window;
1110     HRESULT hres;
1111
1112     hres = IUnknown_QueryInterface(elem, &IID_IHTMLFrameBase2, (void**)&base2);
1113     ok(hres == S_OK, "Could not get IHTMFrameBase2 iface: %08x\n", hres);
1114
1115     window = NULL;
1116     hres = IHTMLFrameBase2_get_contentWindow(base2, &window);
1117     IHTMLFrameBase2_Release(base2);
1118     ok(hres == S_OK, "get_contentWindow failed: %08x\n", hres);
1119     ok(window != NULL, "contentWindow = NULL\n");
1120
1121     return window;
1122 }
1123
1124 static void test_get_set_attr(IHTMLDocument2 *doc)
1125 {
1126     IHTMLElement *elem;
1127     IHTMLDocument3 *doc3;
1128     HRESULT hres;
1129     BSTR bstr;
1130     VARIANT val;
1131
1132     /* grab an element to test with */
1133     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
1134     ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08x\n", hres);
1135
1136     hres = IHTMLDocument3_get_documentElement(doc3, &elem);
1137     IHTMLDocument3_Release(doc3);
1138     ok(hres == S_OK, "get_documentElement failed: %08x\n", hres);
1139
1140     /* get a non-present attribute */
1141     bstr = a2bstr("notAnAttribute");
1142     hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
1143     ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
1144     ok(V_VT(&val) == VT_NULL, "variant type should have been VT_NULL (0x%x), was: 0x%x\n", VT_NULL, V_VT(&val));
1145     VariantClear(&val);
1146     SysFreeString(bstr);
1147
1148     /* get a present attribute */
1149     bstr = a2bstr("scrollHeight");
1150     hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
1151     ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
1152     ok(V_VT(&val) == VT_I4, "variant type should have been VT_I4 (0x%x), was: 0x%x\n", VT_I4, V_VT(&val));
1153     VariantClear(&val);
1154     SysFreeString(bstr);
1155
1156     /* create a new BSTR attribute */
1157     bstr = a2bstr("newAttribute");
1158
1159     V_VT(&val) = VT_BSTR;
1160     V_BSTR(&val) = a2bstr("the value");
1161     hres = IHTMLElement_setAttribute(elem, bstr, val, 0);
1162     ok(hres == S_OK, "setAttribute failed: %08x\n", hres);
1163     VariantClear(&val);
1164
1165     hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
1166     ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
1167     ok(V_VT(&val) == VT_BSTR, "variant type should have been VT_BSTR (0x%x), was: 0x%x\n", VT_BSTR, V_VT(&val));
1168     ok(strcmp_wa(V_BSTR(&val), "the value") == 0, "variant value should have been L\"the value\", was %s\n", wine_dbgstr_w(V_BSTR(&val)));
1169     VariantClear(&val);
1170
1171     /* overwrite the attribute with a BOOL */
1172     V_VT(&val) = VT_BOOL;
1173     V_BOOL(&val) = VARIANT_TRUE;
1174     hres = IHTMLElement_setAttribute(elem, bstr, val, 0);
1175     ok(hres == S_OK, "setAttribute failed: %08x\n", hres);
1176     VariantClear(&val);
1177
1178     hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
1179     ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
1180     ok(V_VT(&val) == VT_BOOL, "variant type should have been VT_BOOL (0x%x), was: 0x%x\n", VT_BOOL, V_VT(&val));
1181     ok(V_BOOL(&val) == VARIANT_TRUE, "variant value should have been VARIANT_TRUE (0x%x), was %d\n", VARIANT_TRUE, V_BOOL(&val));
1182     VariantClear(&val);
1183
1184     SysFreeString(bstr);
1185
1186     /* case-insensitive */
1187     bstr = a2bstr("newattribute");
1188     hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
1189     ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
1190     ok(V_VT(&val) == VT_BOOL, "variant type should have been VT_BOOL (0x%x), was: 0x%x\n", VT_BOOL, V_VT(&val));
1191     ok(V_BOOL(&val) == VARIANT_TRUE, "variant value should have been VARIANT_TRUE (0x%x), was %d\n", VARIANT_TRUE, V_BOOL(&val));
1192     VariantClear(&val);
1193     SysFreeString(bstr);
1194
1195     IHTMLElement_Release(elem);
1196 }
1197
1198 #define get_doc_elem(d) _get_doc_elem(__LINE__,d)
1199 static IHTMLElement *_get_doc_elem(unsigned line, IHTMLDocument2 *doc)
1200 {
1201     IHTMLElement *elem;
1202     IHTMLDocument3 *doc3;
1203     HRESULT hres;
1204
1205     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
1206     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDocument3 interface: %08x\n", hres);
1207     hres = IHTMLDocument3_get_documentElement(doc3, &elem);
1208     ok_(__FILE__,line) (hres == S_OK, "get_documentElement failed: %08x\n", hres);
1209     IHTMLDocument3_Release(doc3);
1210
1211     return elem;
1212 }
1213
1214 #define test_anchor_href(a,h) _test_anchor_href(__LINE__,a,h)
1215 static void _test_anchor_href(unsigned line, IUnknown *unk, const char *exhref)
1216 {
1217     IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk);
1218     BSTR str;
1219     HRESULT hres;
1220
1221     hres = IHTMLAnchorElement_get_href(anchor, &str);
1222     ok_(__FILE__,line)(hres == S_OK, "get_href failed: %08x\n", hres);
1223     ok_(__FILE__,line)(!strcmp_wa(str, exhref), "href = %s, expected %s\n", wine_dbgstr_w(str), exhref);
1224     SysFreeString(str);
1225
1226     _test_disp_value(line, unk, exhref);
1227 }
1228
1229 #define test_anchor_put_href(a,h) _test_anchor_put_href(__LINE__,a,h)
1230 static void _test_anchor_put_href(unsigned line, IUnknown *unk, const char *exhref)
1231 {
1232     IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk);
1233     BSTR str;
1234     HRESULT hres;
1235
1236     str = a2bstr(exhref);
1237     hres = IHTMLAnchorElement_put_href(anchor, str);
1238     ok_(__FILE__,line)(hres == S_OK, "get_href failed: %08x\n", hres);
1239     SysFreeString(str);
1240
1241     _test_disp_value(line, unk, exhref);
1242 }
1243
1244 #define test_anchor_get_target(a,h) _test_anchor_get_target(__LINE__,a,h)
1245 static void _test_anchor_get_target(unsigned line, IUnknown *unk, const char *target)
1246 {
1247     IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk);
1248     BSTR str;
1249     HRESULT hres;
1250
1251     hres = IHTMLAnchorElement_get_target(anchor, &str);
1252     ok_(__FILE__,line)(hres == S_OK, "get_target failed: %08x\n", hres);
1253     if(target)
1254         ok_(__FILE__,line)(!strcmp_wa(str, target), "target = %s, expected %s\n", wine_dbgstr_w(str), target);
1255     else
1256         ok_(__FILE__,line)(str == NULL, "target = %s, expected NULL\n", wine_dbgstr_w(str));
1257     SysFreeString(str);
1258 }
1259
1260 #define test_anchor_put_target(a,h) _test_anchor_put_target(__LINE__,a,h)
1261 static void _test_anchor_put_target(unsigned line, IUnknown *unk, const char *target)
1262 {
1263     IHTMLAnchorElement *anchor = _get_anchor_iface(line, unk);
1264     BSTR str;
1265     HRESULT hres;
1266
1267     str = target ? a2bstr(target) : NULL;
1268     hres = IHTMLAnchorElement_put_target(anchor, str);
1269     ok_(__FILE__,line)(hres == S_OK, "put_target failed: %08x\n", hres);
1270     SysFreeString(str);
1271 }
1272
1273
1274 #define test_option_text(o,t) _test_option_text(__LINE__,o,t)
1275 static void _test_option_text(unsigned line, IHTMLOptionElement *option, const char *text)
1276 {
1277     BSTR bstr;
1278     HRESULT hres;
1279
1280     hres = IHTMLOptionElement_get_text(option, &bstr);
1281     ok_(__FILE__,line) (hres == S_OK, "get_text failed: %08x\n", hres);
1282     ok_(__FILE__,line) (!strcmp_wa(bstr, text), "text=%s\n", wine_dbgstr_w(bstr));
1283     SysFreeString(bstr);
1284 }
1285
1286 #define test_option_put_text(o,t) _test_option_put_text(__LINE__,o,t)
1287 static void _test_option_put_text(unsigned line, IHTMLOptionElement *option, const char *text)
1288 {
1289     BSTR bstr;
1290     HRESULT hres;
1291
1292     bstr = a2bstr(text);
1293     hres = IHTMLOptionElement_put_text(option, bstr);
1294     SysFreeString(bstr);
1295     ok(hres == S_OK, "put_text failed: %08x\n", hres);
1296
1297     _test_option_text(line, option, text);
1298 }
1299
1300 #define test_option_value(o,t) _test_option_value(__LINE__,o,t)
1301 static void _test_option_value(unsigned line, IHTMLOptionElement *option, const char *value)
1302 {
1303     BSTR bstr;
1304     HRESULT hres;
1305
1306     hres = IHTMLOptionElement_get_value(option, &bstr);
1307     ok_(__FILE__,line) (hres == S_OK, "get_value failed: %08x\n", hres);
1308     ok_(__FILE__,line) (!strcmp_wa(bstr, value), "value=%s\n", wine_dbgstr_w(bstr));
1309     SysFreeString(bstr);
1310 }
1311
1312 #define test_option_put_value(o,t) _test_option_put_value(__LINE__,o,t)
1313 static void _test_option_put_value(unsigned line, IHTMLOptionElement *option, const char *value)
1314 {
1315     BSTR bstr;
1316     HRESULT hres;
1317
1318     bstr = a2bstr(value);
1319     hres = IHTMLOptionElement_put_value(option, bstr);
1320     SysFreeString(bstr);
1321     ok(hres == S_OK, "put_value failed: %08x\n", hres);
1322
1323     _test_option_value(line, option, value);
1324 }
1325
1326 #define test_option_selected(o,s) _test_option_selected(__LINE__,o,s)
1327 static void _test_option_selected(unsigned line, IHTMLOptionElement *option, VARIANT_BOOL ex)
1328 {
1329     VARIANT_BOOL b = 0x100;
1330     HRESULT hres;
1331
1332     hres = IHTMLOptionElement_get_selected(option, &b);
1333     ok_(__FILE__,line)(hres == S_OK, "get_selected failed: %08x\n", hres);
1334     ok_(__FILE__,line)(b == ex, "selected = %x, expected %x\n", b, ex);
1335 }
1336
1337 #define test_option_put_selected(o,s) _test_option_put_selected(__LINE__,o,s)
1338 static void _test_option_put_selected(unsigned line, IHTMLOptionElement *option, VARIANT_BOOL b)
1339 {
1340     HRESULT hres;
1341
1342     hres = IHTMLOptionElement_put_selected(option, b);
1343     ok_(__FILE__,line)(hres == S_OK, "put_selected failed: %08x\n", hres);
1344     _test_option_selected(line, option, b);
1345 }
1346
1347 #define test_textarea_value(t,v) _test_textarea_value(__LINE__,t,v)
1348 static void _test_textarea_value(unsigned line, IUnknown *unk, const char *exval)
1349 {
1350     IHTMLTextAreaElement *textarea = _get_textarea_iface(line, unk);
1351     BSTR value = (void*)0xdeadbeef;
1352     HRESULT hres;
1353
1354     hres = IHTMLTextAreaElement_get_value(textarea, &value);
1355     IHTMLTextAreaElement_Release(textarea);
1356     ok_(__FILE__,line)(hres == S_OK, "get_value failed: %08x\n", hres);
1357     if(exval)
1358         ok_(__FILE__,line)(!strcmp_wa(value, exval), "value = %s, expected %s\n", wine_dbgstr_w(value), exval);
1359     else
1360         ok_(__FILE__,line)(!value, "value = %p\n", value);
1361     SysFreeString(value);
1362 }
1363
1364 #define test_textarea_put_value(t,v) _test_textarea_put_value(__LINE__,t,v)
1365 static void _test_textarea_put_value(unsigned line, IUnknown *unk, const char *value)
1366 {
1367     IHTMLTextAreaElement *textarea = _get_textarea_iface(line, unk);
1368     BSTR tmp = a2bstr(value);
1369     HRESULT hres;
1370
1371     hres = IHTMLTextAreaElement_put_value(textarea, tmp);
1372     IHTMLTextAreaElement_Release(textarea);
1373     ok_(__FILE__,line)(hres == S_OK, "put_value failed: %08x\n", hres);
1374     SysFreeString(tmp);
1375
1376     _test_textarea_value(line, unk, value);
1377 }
1378
1379 #define test_textarea_readonly(t,v) _test_textarea_readonly(__LINE__,t,v)
1380 static void _test_textarea_readonly(unsigned line, IUnknown *unk, VARIANT_BOOL ex)
1381 {
1382     IHTMLTextAreaElement *textarea = _get_textarea_iface(line, unk);
1383     VARIANT_BOOL b = 0x100;
1384     HRESULT hres;
1385
1386     hres = IHTMLTextAreaElement_get_readOnly(textarea, &b);
1387     IHTMLTextAreaElement_Release(textarea);
1388     ok_(__FILE__,line)(hres == S_OK, "get_readOnly failed: %08x\n", hres);
1389     ok_(__FILE__,line)(b == ex, "readOnly = %x, expected %x\n", b, ex);
1390 }
1391
1392 #define test_textarea_put_readonly(t,v) _test_textarea_put_readonly(__LINE__,t,v)
1393 static void _test_textarea_put_readonly(unsigned line, IUnknown *unk, VARIANT_BOOL b)
1394 {
1395     IHTMLTextAreaElement *textarea = _get_textarea_iface(line, unk);
1396     HRESULT hres;
1397
1398     hres = IHTMLTextAreaElement_put_readOnly(textarea, b);
1399     IHTMLTextAreaElement_Release(textarea);
1400     ok_(__FILE__,line)(hres == S_OK, "put_readOnly failed: %08x\n", hres);
1401
1402     _test_textarea_readonly(line, unk, b);
1403 }
1404
1405 #define test_textarea_type(t) _test_textarea_type(__LINE__,t)
1406 static void _test_textarea_type(unsigned line, IUnknown *unk)
1407 {
1408     IHTMLTextAreaElement *textarea = _get_textarea_iface(line, unk);
1409     BSTR type = (void*)0xdeadbeef;
1410     HRESULT hres;
1411
1412     hres = IHTMLTextAreaElement_get_type(textarea, &type);
1413     IHTMLTextAreaElement_Release(textarea);
1414     ok_(__FILE__,line)(hres == S_OK, "get_type failed: %08x\n", hres);
1415     ok_(__FILE__,line)(!strcmp_wa(type, "textarea"), "type = %s, expected textarea\n", wine_dbgstr_w(type));
1416     SysFreeString(type);
1417 }
1418
1419 #define test_comment_text(c,t) _test_comment_text(__LINE__,c,t)
1420 static void _test_comment_text(unsigned line, IUnknown *unk, const char *extext)
1421 {
1422     IHTMLCommentElement *comment = _get_comment_iface(__LINE__,unk);
1423     BSTR text;
1424     HRESULT hres;
1425
1426     text = a2bstr(extext);
1427     hres = IHTMLCommentElement_get_text(comment, &text);
1428     ok_(__FILE__,line)(hres == S_OK, "get_text failed: %08x\n", hres);
1429     ok_(__FILE__,line)(!strcmp_wa(text, extext), "text = \"%s\", expected \"%s\"\n", wine_dbgstr_w(text), extext);
1430
1431     IHTMLCommentElement_Release(comment);
1432     SysFreeString(text);
1433 }
1434
1435 #define test_comment_attrs(c) _test_comment_attrs(__LINE__,c)
1436 static void _test_comment_attrs(unsigned line, IUnknown *unk)
1437 {
1438     IHTMLCommentElement *comment = _get_comment_iface(__LINE__,unk);
1439     IHTMLElement *elem = _get_elem_iface(__LINE__,unk);
1440     IHTMLElement4 *elem4 = _get_elem4_iface(__LINE__,unk);
1441     IHTMLDOMAttribute *attr;
1442     BSTR name = a2bstr("test");
1443     VARIANT val;
1444     HRESULT hres;
1445
1446     hres = IHTMLElement4_getAttributeNode(elem4, name, &attr);
1447     ok(hres == S_OK, "getAttributeNode failed: %08x\n", hres);
1448     ok(attr == NULL, "attr != NULL\n");
1449
1450     V_VT(&val) = VT_I4;
1451     V_I4(&val) = 1234;
1452     hres = IHTMLElement_setAttribute(elem, name, val, 0);
1453     ok(hres == S_OK, "setAttribute failed: %08x\n", hres);
1454
1455     hres = IHTMLElement4_getAttributeNode(elem4, name, &attr);
1456     ok(hres == S_OK, "getAttributeNode failed: %08x\n", hres);
1457     ok(attr != NULL, "attr == NULL\n");
1458
1459     IHTMLDOMAttribute_Release(attr);
1460     IHTMLCommentElement_Release(comment);
1461     IHTMLElement_Release(elem);
1462     IHTMLElement4_Release(elem);
1463     SysFreeString(name);
1464 }
1465
1466 #define test_object_vspace(u,s) _test_object_vspace(__LINE__,u,s)
1467 static void _test_object_vspace(unsigned line, IUnknown *unk, LONG exl)
1468 {
1469     IHTMLObjectElement *object = _get_object_iface(line, unk);
1470     LONG l;
1471     HRESULT hres;
1472
1473     l = 0xdeadbeef;
1474     hres = IHTMLObjectElement_get_vspace(object, &l);
1475     ok_(__FILE__,line)(hres == S_OK, "get_vspace failed: %08x\n", hres);
1476     ok_(__FILE__,line)(l == exl, "vspace=%d, expected %d\n", l, exl);
1477     IHTMLObjectElement_Release(object);
1478 }
1479
1480 #define create_option_elem(d,t,v) _create_option_elem(__LINE__,d,t,v)
1481 static IHTMLOptionElement *_create_option_elem(unsigned line, IHTMLDocument2 *doc,
1482         const char *txt, const char *val)
1483 {
1484     IHTMLOptionElementFactory *factory;
1485     IHTMLOptionElement *option;
1486     IHTMLWindow2 *window;
1487     VARIANT text, value, empty;
1488     HRESULT hres;
1489
1490     hres = IHTMLDocument2_get_parentWindow(doc, &window);
1491     ok_(__FILE__,line) (hres == S_OK, "get_parentElement failed: %08x\n", hres);
1492
1493     hres = IHTMLWindow2_get_Option(window, &factory);
1494     IHTMLWindow2_Release(window);
1495     ok_(__FILE__,line) (hres == S_OK, "get_Option failed: %08x\n", hres);
1496
1497     V_VT(&text) = VT_BSTR;
1498     V_BSTR(&text) = a2bstr(txt);
1499     V_VT(&value) = VT_BSTR;
1500     V_BSTR(&value) = a2bstr(val);
1501     V_VT(&empty) = VT_EMPTY;
1502
1503     hres = IHTMLOptionElementFactory_create(factory, text, value, empty, empty, &option);
1504     ok_(__FILE__,line) (hres == S_OK, "create failed: %08x\n", hres);
1505
1506     IHTMLOptionElementFactory_Release(factory);
1507     VariantClear(&text);
1508     VariantClear(&value);
1509
1510     _test_option_text(line, option, txt);
1511     _test_option_value(line, option, val);
1512     _test_option_selected(line, option, VARIANT_FALSE);
1513
1514     return option;
1515 }
1516
1517 #define test_img_width(o,w) _test_img_width(__LINE__,o,w)
1518 static void _test_img_width(unsigned line, IHTMLImgElement *img, const LONG exp)
1519 {
1520     LONG found = -1;
1521     HRESULT hres;
1522
1523     hres = IHTMLImgElement_get_width(img, &found);
1524     ok_(__FILE__,line) (hres == S_OK, "get_width failed: %08x\n", hres);
1525     ok_(__FILE__,line) (found == exp, "width=%d\n", found);
1526 }
1527
1528 #define test_img_put_width(o,w) _test_img_put_width(__LINE__,o,w)
1529 static void _test_img_put_width(unsigned line, IHTMLImgElement *img, const LONG width)
1530 {
1531     HRESULT hres;
1532
1533     hres = IHTMLImgElement_put_width(img, width);
1534     ok(hres == S_OK, "put_width failed: %08x\n", hres);
1535
1536     _test_img_width(line, img, width);
1537 }
1538
1539 #define test_img_height(o,h) _test_img_height(__LINE__,o,h)
1540 static void _test_img_height(unsigned line, IHTMLImgElement *img, const LONG exp)
1541 {
1542     LONG found = -1;
1543     HRESULT hres;
1544
1545     hres = IHTMLImgElement_get_height(img, &found);
1546     ok_(__FILE__,line) (hres == S_OK, "get_height failed: %08x\n", hres);
1547     ok_(__FILE__,line) (found == exp, "height=%d\n", found);
1548 }
1549
1550 #define test_img_put_height(o,w) _test_img_put_height(__LINE__,o,w)
1551 static void _test_img_put_height(unsigned line, IHTMLImgElement *img, const LONG height)
1552 {
1553     HRESULT hres;
1554
1555     hres = IHTMLImgElement_put_height(img, height);
1556     ok(hres == S_OK, "put_height failed: %08x\n", hres);
1557
1558     _test_img_height(line, img, height);
1559 }
1560
1561 #define create_img_elem(d,t,v) _create_img_elem(__LINE__,d,t,v)
1562 static IHTMLImgElement *_create_img_elem(unsigned line, IHTMLDocument2 *doc,
1563         LONG wdth, LONG hght)
1564 {
1565     IHTMLImageElementFactory *factory;
1566     IHTMLImgElement *img;
1567     IHTMLWindow2 *window;
1568     VARIANT width, height;
1569     char buf[16];
1570     HRESULT hres;
1571
1572     hres = IHTMLDocument2_get_parentWindow(doc, &window);
1573     ok_(__FILE__,line) (hres == S_OK, "get_parentElement failed: %08x\n", hres);
1574
1575     hres = IHTMLWindow2_get_Image(window, &factory);
1576     IHTMLWindow2_Release(window);
1577     ok_(__FILE__,line) (hres == S_OK, "get_Image failed: %08x\n", hres);
1578
1579     test_ifaces((IUnknown*)factory, img_factory_iids);
1580     test_disp((IUnknown*)factory, &IID_IHTMLImageElementFactory, "[object]");
1581
1582     if(wdth >= 0){
1583         snprintf(buf, 16, "%d", wdth);
1584         V_VT(&width) = VT_BSTR;
1585         V_BSTR(&width) = a2bstr(buf);
1586     }else{
1587         V_VT(&width) = VT_EMPTY;
1588         wdth = 0;
1589     }
1590
1591     if(hght >= 0){
1592         snprintf(buf, 16, "%d", hght);
1593         V_VT(&height) = VT_BSTR;
1594         V_BSTR(&height) = a2bstr(buf);
1595     }else{
1596         V_VT(&height) = VT_EMPTY;
1597         hght = 0;
1598     }
1599
1600     hres = IHTMLImageElementFactory_create(factory, width, height, &img);
1601     ok_(__FILE__,line) (hres == S_OK, "create failed: %08x\n", hres);
1602
1603     IHTMLImageElementFactory_Release(factory);
1604     VariantClear(&width);
1605     VariantClear(&height);
1606
1607     if(SUCCEEDED(hres)) {
1608         _test_img_width(line, img, wdth);
1609         _test_img_height(line, img, hght);
1610         return img;
1611     }
1612
1613     return NULL;
1614 }
1615
1616 #define test_select_length(s,l) _test_select_length(__LINE__,s,l)
1617 static void _test_select_length(unsigned line, IHTMLSelectElement *select, LONG length)
1618 {
1619     LONG len = 0xdeadbeef;
1620     HRESULT hres;
1621
1622     hres = IHTMLSelectElement_get_length(select, &len);
1623     ok_(__FILE__,line) (hres == S_OK, "get_length failed: %08x\n", hres);
1624     ok_(__FILE__,line) (len == length, "len=%d, expected %d\n", len, length);
1625 }
1626
1627 #define test_select_put_length(s,l) _test_select_put_length(__LINE__,s,l)
1628 static void _test_select_put_length(unsigned line, IUnknown *unk, LONG length)
1629 {
1630     IHTMLSelectElement *select = _get_select_iface(line, unk);
1631     HRESULT hres;
1632
1633     hres = IHTMLSelectElement_put_length(select, length);
1634     ok_(__FILE__,line) (hres == S_OK, "put_length failed: %08x\n", hres);
1635     _test_select_length(line, select, length);
1636     IHTMLSelectElement_Release(select);
1637 }
1638
1639 #define test_select_selidx(s,i) _test_select_selidx(__LINE__,s,i)
1640 static void _test_select_selidx(unsigned line, IHTMLSelectElement *select, LONG index)
1641 {
1642     LONG idx = 0xdeadbeef;
1643     HRESULT hres;
1644
1645     hres = IHTMLSelectElement_get_selectedIndex(select, &idx);
1646     ok_(__FILE__,line) (hres == S_OK, "get_selectedIndex failed: %08x\n", hres);
1647     ok_(__FILE__,line) (idx == index, "idx=%d, expected %d\n", idx, index);
1648 }
1649
1650 #define test_select_put_selidx(s,i) _test_select_put_selidx(__LINE__,s,i)
1651 static void _test_select_put_selidx(unsigned line, IHTMLSelectElement *select, LONG index)
1652 {
1653     HRESULT hres;
1654
1655     hres = IHTMLSelectElement_put_selectedIndex(select, index);
1656     ok_(__FILE__,line) (hres == S_OK, "get_selectedIndex failed: %08x\n", hres);
1657     _test_select_selidx(line, select, index);
1658 }
1659
1660 #define test_select_value(s,v) _test_select_value(__LINE__,s,v)
1661 static void _test_select_value(unsigned line, IHTMLSelectElement *select, const char *exval)
1662 {
1663     BSTR val;
1664     HRESULT hres;
1665
1666     hres = IHTMLSelectElement_get_value(select, &val);
1667     ok_(__FILE__,line) (hres == S_OK, "get_value failed: %08x\n", hres);
1668     if(exval)
1669         ok_(__FILE__,line) (!strcmp_wa(val, exval), "unexpected value %s\n", wine_dbgstr_w(val));
1670     else
1671         ok_(__FILE__,line) (val == NULL, "val=%s, expected NULL\n", wine_dbgstr_w(val));
1672     SysFreeString(val);
1673 }
1674
1675 #define test_select_set_value(s,v) _test_select_set_value(__LINE__,s,v)
1676 static void _test_select_set_value(unsigned line, IHTMLSelectElement *select, const char *val)
1677 {
1678     BSTR bstr;
1679     HRESULT hres;
1680
1681     bstr = a2bstr(val);
1682     hres = IHTMLSelectElement_put_value(select, bstr);
1683     SysFreeString(bstr);
1684     ok_(__FILE__,line) (hres == S_OK, "put_value failed: %08x\n", hres);
1685 }
1686
1687 #define test_select_type(s,t) _test_select_type(__LINE__,s,t)
1688 static void _test_select_type(unsigned line, IHTMLSelectElement *select, const char *extype)
1689 {
1690     BSTR type;
1691     HRESULT hres;
1692
1693     hres = IHTMLSelectElement_get_type(select, &type);
1694     ok_(__FILE__,line) (hres == S_OK, "get_type failed: %08x\n", hres);
1695     ok_(__FILE__,line) (!strcmp_wa(type, extype), "type=%s, expected %s\n", wine_dbgstr_w(type), extype);
1696     SysFreeString(type);
1697 }
1698
1699 #define test_range_text(r,t) _test_range_text(__LINE__,r,t)
1700 static void _test_range_text(unsigned line, IHTMLTxtRange *range, const char *extext)
1701 {
1702     BSTR text;
1703     HRESULT hres;
1704
1705     hres = IHTMLTxtRange_get_text(range, &text);
1706     ok_(__FILE__, line) (hres == S_OK, "get_text failed: %08x\n", hres);
1707
1708     if(extext) {
1709         ok_(__FILE__, line) (text != NULL, "text == NULL\n");
1710         ok_(__FILE__, line) (!strcmp_wa(text, extext), "text=%s, expected %s\n", wine_dbgstr_w(text), extext);
1711     }else {
1712         ok_(__FILE__, line) (text == NULL, "text=%s, expected NULL\n", wine_dbgstr_w(text));
1713     }
1714
1715     SysFreeString(text);
1716
1717 }
1718
1719 #define test_range_collapse(r,b) _test_range_collapse(__LINE__,r,b)
1720 static void _test_range_collapse(unsigned line, IHTMLTxtRange *range, BOOL b)
1721 {
1722     HRESULT hres;
1723
1724     hres = IHTMLTxtRange_collapse(range, b);
1725     ok_(__FILE__, line) (hres == S_OK, "collapse failed: %08x\n", hres);
1726     _test_range_text(line, range, NULL);
1727 }
1728
1729 #define test_range_expand(r,u,b,t) _test_range_expand(__LINE__,r,u,b,t)
1730 static void _test_range_expand(unsigned line, IHTMLTxtRange *range, LPWSTR unit,
1731         VARIANT_BOOL exb, const char *extext)
1732 {
1733     VARIANT_BOOL b = 0xe0e0;
1734     HRESULT hres;
1735
1736     hres = IHTMLTxtRange_expand(range, unit, &b);
1737     ok_(__FILE__,line) (hres == S_OK, "expand failed: %08x\n", hres);
1738     ok_(__FILE__,line) (b == exb, "b=%x, expected %x\n", b, exb);
1739     _test_range_text(line, range, extext);
1740 }
1741
1742 #define test_range_move(r,u,c,e) _test_range_move(__LINE__,r,u,c,e)
1743 static void _test_range_move(unsigned line, IHTMLTxtRange *range, LPWSTR unit, LONG cnt, LONG excnt)
1744 {
1745     LONG c = 0xdeadbeef;
1746     HRESULT hres;
1747
1748     hres = IHTMLTxtRange_move(range, unit, cnt, &c);
1749     ok_(__FILE__,line) (hres == S_OK, "move failed: %08x\n", hres);
1750     ok_(__FILE__,line) (c == excnt, "count=%d, expected %d\n", c, excnt);
1751     _test_range_text(line, range, NULL);
1752 }
1753
1754 #define test_range_movestart(r,u,c,e) _test_range_movestart(__LINE__,r,u,c,e)
1755 static void _test_range_movestart(unsigned line, IHTMLTxtRange *range,
1756         LPWSTR unit, LONG cnt, LONG excnt)
1757 {
1758     LONG c = 0xdeadbeef;
1759     HRESULT hres;
1760
1761     hres = IHTMLTxtRange_moveStart(range, unit, cnt, &c);
1762     ok_(__FILE__,line) (hres == S_OK, "move failed: %08x\n", hres);
1763     ok_(__FILE__,line) (c == excnt, "count=%d, expected %d\n", c, excnt);
1764 }
1765
1766 #define test_range_moveend(r,u,c,e) _test_range_moveend(__LINE__,r,u,c,e)
1767 static void _test_range_moveend(unsigned line, IHTMLTxtRange *range, LPWSTR unit, LONG cnt, LONG excnt)
1768 {
1769     LONG c = 0xdeadbeef;
1770     HRESULT hres;
1771
1772     hres = IHTMLTxtRange_moveEnd(range, unit, cnt, &c);
1773     ok_(__FILE__,line) (hres == S_OK, "move failed: %08x\n", hres);
1774     ok_(__FILE__,line) (c == excnt, "count=%d, expected %d\n", c, excnt);
1775 }
1776
1777 #define test_range_put_text(r,t) _test_range_put_text(__LINE__,r,t)
1778 static void _test_range_put_text(unsigned line, IHTMLTxtRange *range, const char *text)
1779 {
1780     HRESULT hres;
1781     BSTR bstr = a2bstr(text);
1782
1783     hres = IHTMLTxtRange_put_text(range, bstr);
1784     ok_(__FILE__,line) (hres == S_OK, "put_text failed: %08x\n", hres);
1785     SysFreeString(bstr);
1786     _test_range_text(line, range, NULL);
1787 }
1788
1789 #define test_range_inrange(r1,r2,b) _test_range_inrange(__LINE__,r1,r2,b)
1790 static void _test_range_inrange(unsigned line, IHTMLTxtRange *range1, IHTMLTxtRange *range2, VARIANT_BOOL exb)
1791 {
1792     VARIANT_BOOL b;
1793     HRESULT hres;
1794
1795     b = 0xe0e0;
1796     hres = IHTMLTxtRange_inRange(range1, range2, &b);
1797     ok_(__FILE__,line) (hres == S_OK, "(1->2) isEqual failed: %08x\n", hres);
1798     ok_(__FILE__,line) (b == exb, "(1->2) b=%x, expected %x\n", b, exb);
1799 }
1800
1801 #define test_range_isequal(r1,r2,b) _test_range_isequal(__LINE__,r1,r2,b)
1802 static void _test_range_isequal(unsigned line, IHTMLTxtRange *range1, IHTMLTxtRange *range2, VARIANT_BOOL exb)
1803 {
1804     VARIANT_BOOL b;
1805     HRESULT hres;
1806
1807     b = 0xe0e0;
1808     hres = IHTMLTxtRange_isEqual(range1, range2, &b);
1809     ok_(__FILE__,line) (hres == S_OK, "(1->2) isEqual failed: %08x\n", hres);
1810     ok_(__FILE__,line) (b == exb, "(1->2) b=%x, expected %x\n", b, exb);
1811
1812     b = 0xe0e0;
1813     hres = IHTMLTxtRange_isEqual(range2, range1, &b);
1814     ok_(__FILE__,line) (hres == S_OK, "(2->1) isEqual failed: %08x\n", hres);
1815     ok_(__FILE__,line) (b == exb, "(2->1) b=%x, expected %x\n", b, exb);
1816
1817     if(exb) {
1818         test_range_inrange(range1, range2, VARIANT_TRUE);
1819         test_range_inrange(range2, range1, VARIANT_TRUE);
1820     }
1821 }
1822
1823 #define test_range_parent(r,t) _test_range_parent(__LINE__,r,t)
1824 static void _test_range_parent(unsigned line, IHTMLTxtRange *range, elem_type_t type)
1825 {
1826     IHTMLElement *elem;
1827     HRESULT hres;
1828
1829     hres = IHTMLTxtRange_parentElement(range, &elem);
1830     ok_(__FILE__,line) (hres == S_OK, "parentElement failed: %08x\n", hres);
1831
1832     _test_elem_type(line, (IUnknown*)elem, type);
1833
1834     IHTMLElement_Release(elem);
1835 }
1836
1837 #define test_elem_collection(c,t,l) _test_elem_collection(__LINE__,c,t,l)
1838 static void _test_elem_collection(unsigned line, IUnknown *unk,
1839         const elem_type_t *elem_types, LONG exlen)
1840 {
1841     IHTMLElementCollection *col;
1842     LONG len;
1843     DWORD i;
1844     VARIANT name, index;
1845     IDispatch *disp, *disp2;
1846     HRESULT hres;
1847
1848     hres = IUnknown_QueryInterface(unk, &IID_IHTMLElementCollection, (void**)&col);
1849     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElementCollection: %08x\n", hres);
1850
1851     test_disp((IUnknown*)col, &DIID_DispHTMLElementCollection, "[object]");
1852
1853     hres = IHTMLElementCollection_get_length(col, &len);
1854     ok_(__FILE__,line) (hres == S_OK, "get_length failed: %08x\n", hres);
1855     ok_(__FILE__,line) (len == exlen, "len=%d, expected %d\n", len, exlen);
1856
1857     if(len > exlen)
1858         len = exlen;
1859
1860     V_VT(&index) = VT_EMPTY;
1861
1862     for(i=0; i<len; i++) {
1863         V_VT(&name) = VT_I4;
1864         V_I4(&name) = i;
1865         disp = (void*)0xdeadbeef;
1866         hres = IHTMLElementCollection_item(col, name, index, &disp);
1867         ok_(__FILE__,line) (hres == S_OK, "item(%d) failed: %08x\n", i, hres);
1868         ok_(__FILE__,line) (disp != NULL, "item returned NULL\n");
1869         if(FAILED(hres) || !disp)
1870             continue;
1871
1872         _test_elem_type(line, (IUnknown*)disp, elem_types[i]);
1873
1874         if(!i) {
1875             V_VT(&name) = VT_UINT;
1876             V_I4(&name) = 0;
1877             disp2 = (void*)0xdeadbeef;
1878             hres = IHTMLElementCollection_item(col, name, index, &disp2);
1879             ok_(__FILE__,line) (hres == S_OK, "item(%d) failed: %08x\n", i, hres);
1880             ok_(__FILE__,line) (iface_cmp((IUnknown*)disp, (IUnknown*)disp2), "disp != disp2\n");
1881             if(disp2)
1882                 IDispatch_Release(disp2);
1883         }
1884
1885         IDispatch_Release(disp);
1886     }
1887
1888     V_VT(&name) = VT_I4;
1889     V_I4(&name) = len;
1890     disp = (void*)0xdeadbeef;
1891     hres = IHTMLElementCollection_item(col, name, index, &disp);
1892     ok_(__FILE__,line) (hres == S_OK, "item failed: %08x\n", hres);
1893     ok_(__FILE__,line) (disp == NULL, "disp != NULL\n");
1894
1895     V_VT(&name) = VT_I4;
1896     V_I4(&name) = -1;
1897     disp = (void*)0xdeadbeef;
1898     hres = IHTMLElementCollection_item(col, name, index, &disp);
1899     ok_(__FILE__,line) (hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
1900     ok_(__FILE__,line) (disp == NULL, "disp != NULL\n");
1901
1902     IHTMLElementCollection_Release(col);
1903 }
1904
1905 #define test_elem_all(c,t,l) _test_elem_all(__LINE__,c,t,l)
1906 static void _test_elem_all(unsigned line, IUnknown *unk, const elem_type_t *elem_types, LONG exlen)
1907 {
1908     IHTMLElement *elem = _get_elem_iface(line, unk);
1909     IDispatch *disp;
1910     HRESULT hres;
1911
1912     hres = IHTMLElement_get_all(elem, &disp);
1913     IHTMLElement_Release(elem);
1914     ok_(__FILE__,line)(hres == S_OK, "get_all failed: %08x\n", hres);
1915
1916     _test_elem_collection(line, (IUnknown*)disp, elem_types, exlen);
1917     IDispatch_Release(disp);
1918 }
1919
1920 #define test_elem_getelembytag(u,t,l) _test_elem_getelembytag(__LINE__,u,t,l)
1921 static void _test_elem_getelembytag(unsigned line, IUnknown *unk, elem_type_t type, LONG exlen)
1922 {
1923     IHTMLElement2 *elem = _get_elem2_iface(line, unk);
1924     IHTMLElementCollection *col = NULL;
1925     elem_type_t *types = NULL;
1926     BSTR tmp;
1927     int i;
1928     HRESULT hres;
1929
1930     tmp = a2bstr(elem_type_infos[type].tag);
1931     hres = IHTMLElement2_getElementsByTagName(elem, tmp, &col);
1932     SysFreeString(tmp);
1933     IHTMLElement2_Release(elem);
1934     ok_(__FILE__,line) (hres == S_OK, "getElementByTagName failed: %08x\n", hres);
1935     ok_(__FILE__,line) (col != NULL, "col == NULL\n");
1936
1937     if(exlen) {
1938         types = HeapAlloc(GetProcessHeap(), 0, exlen*sizeof(elem_type_t));
1939         for(i=0; i<exlen; i++)
1940             types[i] = type;
1941     }
1942
1943     _test_elem_collection(line, (IUnknown*)col, types, exlen);
1944
1945     HeapFree(GetProcessHeap(), 0, types);
1946 }
1947
1948 #define test_elem_innertext(e,t) _test_elem_innertext(__LINE__,e,t)
1949 static void _test_elem_innertext(unsigned line, IHTMLElement *elem, const char *extext)
1950 {
1951     BSTR text = NULL;
1952     HRESULT hres;
1953
1954     hres = IHTMLElement_get_innerText(elem, &text);
1955     ok_(__FILE__,line) (hres == S_OK, "get_innerText failed: %08x\n", hres);
1956     ok_(__FILE__,line) (!strcmp_wa(text, extext), "get_innerText returned %s expected %s\n",
1957                         wine_dbgstr_w(text), extext);
1958     SysFreeString(text);
1959 }
1960
1961 #define test_elem_set_innertext(e,t) _test_elem_set_innertext(__LINE__,e,t)
1962 static void _test_elem_set_innertext(unsigned line, IHTMLElement *elem, const char *text)
1963 {
1964     IHTMLDOMChildrenCollection *col;
1965     BSTR str;
1966     HRESULT hres;
1967
1968     str = a2bstr(text);
1969     hres = IHTMLElement_put_innerText(elem, str);
1970     ok_(__FILE__,line) (hres == S_OK, "put_innerText failed: %08x\n", hres);
1971     SysFreeString(str);
1972
1973     _test_elem_innertext(line, elem, text);
1974
1975
1976     col = _get_child_nodes(line, (IUnknown*)elem);
1977     ok(col != NULL, "col == NULL\n");
1978     if(col) {
1979         LONG length = 0, type;
1980         IHTMLDOMNode *node;
1981
1982         hres = IHTMLDOMChildrenCollection_get_length(col, &length);
1983         ok(hres == S_OK, "get_length failed: %08x\n", hres);
1984         ok(length == 1, "length = %d\n", length);
1985
1986         node = _get_child_item(line, col, 0);
1987         ok(node != NULL, "node == NULL\n");
1988         if(node) {
1989             type = _get_node_type(line, (IUnknown*)node);
1990             ok(type == 3, "type=%d\n", type);
1991             IHTMLDOMNode_Release(node);
1992         }
1993
1994         IHTMLDOMChildrenCollection_Release(col);
1995     }
1996
1997 }
1998
1999 #define test_elem_innerhtml(e,t) _test_elem_innerhtml(__LINE__,e,t)
2000 static void _test_elem_innerhtml(unsigned line, IUnknown *unk, const char *inner_html)
2001 {
2002     IHTMLElement *elem = _get_elem_iface(line, unk);
2003     BSTR html;
2004     HRESULT hres;
2005
2006     hres = IHTMLElement_get_innerHTML(elem, &html);
2007     ok_(__FILE__,line)(hres == S_OK, "get_innerHTML failed: %08x\n", hres);
2008     if(inner_html)
2009         ok_(__FILE__,line)(!strcmp_wa(html, inner_html), "unexpected innerHTML: %s\n", wine_dbgstr_w(html));
2010     else
2011         ok_(__FILE__,line)(!html, "innerHTML = %s\n", wine_dbgstr_w(html));
2012
2013     IHTMLElement_Release(elem);
2014     SysFreeString(html);
2015 }
2016
2017 #define test_elem_set_innerhtml(e,t) _test_elem_set_innerhtml(__LINE__,e,t)
2018 static void _test_elem_set_innerhtml(unsigned line, IUnknown *unk, const char *inner_html)
2019 {
2020     IHTMLElement *elem = _get_elem_iface(line, unk);
2021     BSTR html;
2022     HRESULT hres;
2023
2024     html = a2bstr(inner_html);
2025     hres = IHTMLElement_put_innerHTML(elem, html);
2026     ok_(__FILE__,line)(hres == S_OK, "put_innerHTML failed: %08x\n", hres);
2027
2028     IHTMLElement_Release(elem);
2029     SysFreeString(html);
2030 }
2031
2032 #define test_elem_set_outerhtml(e,t) _test_elem_set_outerhtml(__LINE__,e,t)
2033 static void _test_elem_set_outerhtml(unsigned line, IUnknown *unk, const char *outer_html)
2034 {
2035     IHTMLElement *elem = _get_elem_iface(line, unk);
2036     BSTR html;
2037     HRESULT hres;
2038
2039     html = a2bstr(outer_html);
2040     hres = IHTMLElement_put_outerHTML(elem, html);
2041     ok_(__FILE__,line)(hres == S_OK, "put_outerHTML failed: %08x\n", hres);
2042
2043     IHTMLElement_Release(elem);
2044     SysFreeString(html);
2045 }
2046
2047 #define test_elem_outerhtml(e,t) _test_elem_outerhtml(__LINE__,e,t)
2048 static void _test_elem_outerhtml(unsigned line, IUnknown *unk, const char *outer_html)
2049 {
2050     IHTMLElement *elem = _get_elem_iface(line, unk);
2051     BSTR html;
2052     HRESULT hres;
2053
2054     hres = IHTMLElement_get_outerHTML(elem, &html);
2055     ok_(__FILE__,line)(hres == S_OK, "get_outerHTML failed: %08x\n", hres);
2056     ok_(__FILE__,line)(!strcmp_wa(html, outer_html), "outerHTML = '%s', expected '%s'\n", wine_dbgstr_w(html), outer_html);
2057
2058     IHTMLElement_Release(elem);
2059     SysFreeString(html);
2060 }
2061
2062 #define get_first_child(n) _get_first_child(__LINE__,n)
2063 static IHTMLDOMNode *_get_first_child(unsigned line, IUnknown *unk)
2064 {
2065     IHTMLDOMNode *node = _get_node_iface(line, unk);
2066     IHTMLDOMNode *child = NULL;
2067     HRESULT hres;
2068
2069     hres = IHTMLDOMNode_get_firstChild(node, &child);
2070     IHTMLDOMNode_Release(node);
2071     ok_(__FILE__,line) (hres == S_OK, "get_firstChild failed: %08x\n", hres);
2072
2073     return child;
2074 }
2075
2076 #define test_node_has_child(u,b) _test_node_has_child(__LINE__,u,b)
2077 static void _test_node_has_child(unsigned line, IUnknown *unk, VARIANT_BOOL exb)
2078 {
2079     IHTMLDOMNode *node = _get_node_iface(line, unk);
2080     VARIANT_BOOL b = 0xdead;
2081     HRESULT hres;
2082
2083     hres = IHTMLDOMNode_hasChildNodes(node, &b);
2084     ok_(__FILE__,line) (hres == S_OK, "hasChildNodes failed: %08x\n", hres);
2085     ok_(__FILE__,line) (b == exb, "hasChildNodes=%x, expected %x\n", b, exb);
2086
2087     IHTMLDOMNode_Release(node);
2088 }
2089
2090 #define test_node_get_parent(u) _test_node_get_parent(__LINE__,u)
2091 static IHTMLDOMNode *_test_node_get_parent(unsigned line, IUnknown *unk)
2092 {
2093     IHTMLDOMNode *node = _get_node_iface(line, unk);
2094     IHTMLDOMNode *parent;
2095     HRESULT hres;
2096
2097     hres = IHTMLDOMNode_get_parentNode(node, &parent);
2098     IHTMLDOMNode_Release(node);
2099     ok_(__FILE__,line) (hres == S_OK, "get_parentNode failed: %08x\n", hres);
2100
2101     return parent;
2102 }
2103
2104 #define node_get_next(u) _node_get_next(__LINE__,u)
2105 static IHTMLDOMNode *_node_get_next(unsigned line, IUnknown *unk)
2106 {
2107     IHTMLDOMNode *node = _get_node_iface(line, unk);
2108     IHTMLDOMNode *next;
2109     HRESULT hres;
2110
2111     hres = IHTMLDOMNode_get_nextSibling(node, &next);
2112     IHTMLDOMNode_Release(node);
2113     ok_(__FILE__,line) (hres == S_OK, "get_nextSiblibg failed: %08x\n", hres);
2114
2115     return next;
2116 }
2117
2118 #define node_get_prev(u) _node_get_prev(__LINE__,u)
2119 static IHTMLDOMNode *_node_get_prev(unsigned line, IUnknown *unk)
2120 {
2121     IHTMLDOMNode *node = _get_node_iface(line, unk);
2122     IHTMLDOMNode *prev;
2123     HRESULT hres;
2124
2125     hres = IHTMLDOMNode_get_previousSibling(node, &prev);
2126     IHTMLDOMNode_Release(node);
2127     ok_(__FILE__,line) (hres == S_OK, "get_previousSibling failed: %08x\n", hres);
2128
2129     return prev;
2130 }
2131
2132 #define test_elem_get_parent(u) _test_elem_get_parent(__LINE__,u)
2133 static IHTMLElement *_test_elem_get_parent(unsigned line, IUnknown *unk)
2134 {
2135     IHTMLElement *elem = _get_elem_iface(line, unk);
2136     IHTMLElement *parent;
2137     HRESULT hres;
2138
2139     hres = IHTMLElement_get_parentElement(elem, &parent);
2140     IHTMLElement_Release(elem);
2141     ok_(__FILE__,line) (hres == S_OK, "get_parentElement failed: %08x\n", hres);
2142
2143     return parent;
2144 }
2145
2146 #define test_elem3_get_disabled(i,b) _test_elem3_get_disabled(__LINE__,i,b)
2147 static void _test_elem3_get_disabled(unsigned line, IUnknown *unk, VARIANT_BOOL exb)
2148 {
2149     IHTMLElement3 *elem3 = _get_elem3_iface(line, unk);
2150     VARIANT_BOOL disabled = 100;
2151     HRESULT hres;
2152
2153     if (!elem3) return;
2154     hres = IHTMLElement3_get_disabled(elem3, &disabled);
2155     ok_(__FILE__,line) (hres == S_OK, "get_disabled failed: %08x\n", hres);
2156     ok_(__FILE__,line) (disabled == exb, "disabled=%x, expected %x\n", disabled, exb);
2157     IHTMLElement3_Release(elem3);
2158 }
2159
2160 #define test_elem3_set_disabled(i,b) _test_elem3_set_disabled(__LINE__,i,b)
2161 static void _test_elem3_set_disabled(unsigned line, IUnknown *unk, VARIANT_BOOL b)
2162 {
2163     IHTMLElement3 *elem3 = _get_elem3_iface(line, unk);
2164     HRESULT hres;
2165
2166     if (!elem3) return;
2167     hres = IHTMLElement3_put_disabled(elem3, b);
2168     ok_(__FILE__,line) (hres == S_OK, "get_disabled failed: %08x\n", hres);
2169
2170     IHTMLElement3_Release(elem3);
2171     _test_elem3_get_disabled(line, unk, b);
2172 }
2173
2174 #define test_select_get_disabled(i,b) _test_select_get_disabled(__LINE__,i,b)
2175 static void _test_select_get_disabled(unsigned line, IHTMLSelectElement *select, VARIANT_BOOL exb)
2176 {
2177     VARIANT_BOOL disabled = 100;
2178     HRESULT hres;
2179
2180     hres = IHTMLSelectElement_get_disabled(select, &disabled);
2181     ok_(__FILE__,line) (hres == S_OK, "get_disabled failed: %08x\n", hres);
2182     ok_(__FILE__,line) (disabled == exb, "disabled=%x, expected %x\n", disabled, exb);
2183
2184     _test_elem3_get_disabled(line, (IUnknown*)select, exb);
2185 }
2186
2187 #define test_text_length(u,l) _test_text_length(__LINE__,u,l)
2188 static void _test_text_length(unsigned line, IUnknown *unk, LONG l)
2189 {
2190     IHTMLDOMTextNode *text = _get_text_iface(line, unk);
2191     LONG length;
2192     HRESULT hres;
2193
2194     hres = IHTMLDOMTextNode_get_length(text, &length);
2195     ok_(__FILE__,line)(hres == S_OK, "get_length failed: %08x\n", hres);
2196     ok_(__FILE__,line)(length == l, "length = %d, expected %d\n", length, l);
2197     IHTMLDOMTextNode_Release(text);
2198 }
2199
2200 #define test_select_set_disabled(i,b) _test_select_set_disabled(__LINE__,i,b)
2201 static void _test_select_set_disabled(unsigned line, IHTMLSelectElement *select, VARIANT_BOOL b)
2202 {
2203     HRESULT hres;
2204
2205     hres = IHTMLSelectElement_put_disabled(select, b);
2206     ok_(__FILE__,line) (hres == S_OK, "get_disabled failed: %08x\n", hres);
2207
2208     _test_select_get_disabled(line, select, b);
2209 }
2210
2211 #define elem_get_scroll_height(u) _elem_get_scroll_height(__LINE__,u)
2212 static LONG _elem_get_scroll_height(unsigned line, IUnknown *unk)
2213 {
2214     IHTMLElement2 *elem = _get_elem2_iface(line, unk);
2215     IHTMLTextContainer *txtcont;
2216     LONG l = -1, l2 = -1;
2217     HRESULT hres;
2218
2219     hres = IHTMLElement2_get_scrollHeight(elem, &l);
2220     ok_(__FILE__,line) (hres == S_OK, "get_scrollHeight failed: %08x\n", hres);
2221     IHTMLElement2_Release(elem);
2222
2223     hres = IUnknown_QueryInterface(unk, &IID_IHTMLTextContainer, (void**)&txtcont);
2224     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLTextContainer: %08x\n", hres);
2225
2226     hres = IHTMLTextContainer_get_scrollHeight(txtcont, &l2);
2227     IHTMLTextContainer_Release(txtcont);
2228     ok_(__FILE__,line) (hres == S_OK, "IHTMLTextContainer::get_scrollHeight failed: %d\n", l2);
2229     ok_(__FILE__,line) (l == l2, "unexpected height %d, expected %d\n", l2, l);
2230
2231     return l;
2232 }
2233
2234 #define elem_get_scroll_width(u) _elem_get_scroll_width(__LINE__,u)
2235 static LONG _elem_get_scroll_width(unsigned line, IUnknown *unk)
2236 {
2237     IHTMLElement2 *elem = _get_elem2_iface(line, unk);
2238     IHTMLTextContainer *txtcont;
2239     LONG l = -1, l2 = -1;
2240     HRESULT hres;
2241
2242     hres = IHTMLElement2_get_scrollWidth(elem, &l);
2243     ok_(__FILE__,line) (hres == S_OK, "get_scrollWidth failed: %08x\n", hres);
2244     IHTMLElement2_Release(elem);
2245
2246     hres = IUnknown_QueryInterface(unk, &IID_IHTMLTextContainer, (void**)&txtcont);
2247     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLTextContainer: %08x\n", hres);
2248
2249     hres = IHTMLTextContainer_get_scrollWidth(txtcont, &l2);
2250     IHTMLTextContainer_Release(txtcont);
2251     ok_(__FILE__,line) (hres == S_OK, "IHTMLTextContainer::get_scrollWidth failed: %d\n", l2);
2252     ok_(__FILE__,line) (l == l2, "unexpected width %d, expected %d\n", l2, l);
2253
2254     return l;
2255 }
2256
2257 #define elem_get_scroll_top(u) _elem_get_scroll_top(__LINE__,u)
2258 static LONG _elem_get_scroll_top(unsigned line, IUnknown *unk)
2259 {
2260     IHTMLElement2 *elem = _get_elem2_iface(line, unk);
2261     IHTMLTextContainer *txtcont;
2262     LONG l = -1, l2 = -1;
2263     HRESULT hres;
2264
2265     hres = IHTMLElement2_get_scrollTop(elem, &l);
2266     ok_(__FILE__,line) (hres == S_OK, "get_scrollTop failed: %08x\n", hres);
2267     IHTMLElement2_Release(elem);
2268
2269     hres = IUnknown_QueryInterface(unk, &IID_IHTMLTextContainer, (void**)&txtcont);
2270     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLTextContainer: %08x\n", hres);
2271
2272     hres = IHTMLTextContainer_get_scrollTop(txtcont, &l2);
2273     IHTMLTextContainer_Release(txtcont);
2274     ok_(__FILE__,line) (hres == S_OK, "IHTMLTextContainer::get_scrollTop failed: %d\n", l2);
2275     ok_(__FILE__,line) (l == l2, "unexpected top %d, expected %d\n", l2, l);
2276
2277     return l;
2278 }
2279
2280 #define elem_get_scroll_left(u) _elem_get_scroll_left(__LINE__,u)
2281 static void _elem_get_scroll_left(unsigned line, IUnknown *unk)
2282 {
2283     IHTMLElement2 *elem = _get_elem2_iface(line, unk);
2284     IHTMLTextContainer *txtcont;
2285     LONG l = -1, l2 = -1;
2286     HRESULT hres;
2287
2288     hres = IHTMLElement2_get_scrollLeft(elem, NULL);
2289     ok(hres == E_INVALIDARG, "expect E_INVALIDARG got 0x%08x\n", hres);
2290
2291     hres = IHTMLElement2_get_scrollLeft(elem, &l);
2292     ok(hres == S_OK, "get_scrollTop failed: %08x\n", hres);
2293     IHTMLElement2_Release(elem);
2294
2295     hres = IUnknown_QueryInterface(unk, &IID_IHTMLTextContainer, (void**)&txtcont);
2296     ok(hres == S_OK, "Could not get IHTMLTextContainer: %08x\n", hres);
2297
2298     hres = IHTMLTextContainer_get_scrollLeft(txtcont, &l2);
2299     IHTMLTextContainer_Release(txtcont);
2300     ok(hres == S_OK, "IHTMLTextContainer::get_scrollLeft failed: %d\n", l2);
2301     ok(l == l2, "unexpected left %d, expected %d\n", l2, l);
2302 }
2303
2304 #define test_img_src(a,b,c) _test_img_src(__LINE__,a,b,c)
2305 static void _test_img_src(unsigned line, IUnknown *unk, const char *exsrc, const char *broken_src)
2306 {
2307     IHTMLImgElement *img = _get_img_iface(line, unk);
2308     BSTR src;
2309     HRESULT hres;
2310
2311     hres = IHTMLImgElement_get_src(img, &src);
2312     IHTMLImgElement_Release(img);
2313     ok_(__FILE__,line) (hres == S_OK, "get_src failed: %08x\n", hres);
2314     ok_(__FILE__,line) (!strcmp_wa(src, exsrc) || (broken_src && broken(!strcmp_wa(src, broken_src))),
2315         "get_src returned %s expected %s\n", wine_dbgstr_w(src), exsrc);
2316     SysFreeString(src);
2317 }
2318
2319 #define test_img_set_src(u,s) _test_img_set_src(__LINE__,u,s)
2320 static void _test_img_set_src(unsigned line, IUnknown *unk, const char *src)
2321 {
2322     IHTMLImgElement *img = _get_img_iface(line, unk);
2323     BSTR tmp;
2324     HRESULT hres;
2325
2326     tmp = a2bstr(src);
2327     hres = IHTMLImgElement_put_src(img, tmp);
2328     IHTMLImgElement_Release(img);
2329     SysFreeString(tmp);
2330     ok_(__FILE__,line) (hres == S_OK, "put_src failed: %08x\n", hres);
2331 }
2332
2333 #define test_img_alt(u,a) _test_img_alt(__LINE__,u,a)
2334 static void _test_img_alt(unsigned line, IUnknown *unk, const char *exalt)
2335 {
2336     IHTMLImgElement *img = _get_img_iface(line, unk);
2337     BSTR alt;
2338     HRESULT hres;
2339
2340     hres = IHTMLImgElement_get_alt(img, &alt);
2341     ok_(__FILE__,line) (hres == S_OK, "get_alt failed: %08x\n", hres);
2342     if(exalt)
2343         ok_(__FILE__,line) (!strcmp_wa(alt, exalt), "inexopected alt %s\n", wine_dbgstr_w(alt));
2344     else
2345         ok_(__FILE__,line) (!alt, "alt != NULL\n");
2346     SysFreeString(alt);
2347 }
2348
2349 #define test_img_set_alt(u,a) _test_img_set_alt(__LINE__,u,a)
2350 static void _test_img_set_alt(unsigned line, IUnknown *unk, const char *alt)
2351 {
2352     IHTMLImgElement *img = _get_img_iface(line, unk);
2353     BSTR tmp;
2354     HRESULT hres;
2355
2356     tmp = a2bstr(alt);
2357     hres = IHTMLImgElement_put_alt(img, tmp);
2358     ok_(__FILE__,line) (hres == S_OK, "get_alt failed: %08x\n", hres);
2359     SysFreeString(tmp);
2360
2361     _test_img_alt(line, unk, alt);
2362 }
2363
2364 #define test_img_name(u, c) _test_img_name(__LINE__,u, c)
2365 static void _test_img_name(unsigned line, IUnknown *unk, const char *pValue)
2366 {
2367     IHTMLImgElement *img = _get_img_iface(line, unk);
2368     BSTR sName;
2369     HRESULT hres;
2370
2371     hres = IHTMLImgElement_get_name(img, &sName);
2372     ok_(__FILE__,line) (hres == S_OK, "get_Name failed: %08x\n", hres);
2373     ok_(__FILE__,line) (!strcmp_wa (sName, pValue), "expected '%s' got '%s'\n", pValue, wine_dbgstr_w(sName));
2374     IHTMLImgElement_Release(img);
2375     SysFreeString(sName);
2376 }
2377
2378 static void test_dynamic_properties(IHTMLElement *elem)
2379 {
2380     static const WCHAR attr1W[] = {'a','t','t','r','1',0};
2381     IDispatchEx *dispex;
2382     BSTR name, attr1 = SysAllocString(attr1W);
2383     VARIANT_BOOL succ;
2384     VARIANT val;
2385     int checked_no = 0;
2386     DISPID id = DISPID_STARTENUM;
2387     HRESULT hres;
2388
2389     hres = IHTMLElement_QueryInterface(elem, &IID_IDispatchEx, (void**)&dispex);
2390     ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
2391
2392     hres = IHTMLElement_removeAttribute(elem, attr1, 0, &succ);
2393     ok(hres == S_OK, "removeAttribute failed: %08x\n", hres);
2394     ok(succ, "removeAttribute set succ to FALSE\n");
2395
2396     while(1) {
2397         hres = IDispatchEx_GetNextDispID(dispex, fdexEnumAll, id, &id);
2398         ok(hres==S_OK || hres==S_FALSE, "GetNextDispID failed: %08x\n", hres);
2399         if(hres != S_OK)
2400             break;
2401
2402         hres = IDispatchEx_GetMemberName(dispex, id, &name);
2403         ok(hres == S_OK, "GetMemberName failed: %08x\n", hres);
2404
2405         if(!strcmp_wa(name, "attr1"))
2406             ok(0, "attr1 should be removed\n");
2407         else if(!strcmp_wa(name, "attr2") || !strcmp_wa(name, "attr3"))
2408             checked_no++;
2409         SysFreeString(name);
2410     }
2411     ok(checked_no == 2, "checked_no=%d, expected 2\n", checked_no);
2412     IDispatchEx_Release(dispex);
2413
2414     V_VT(&val) = VT_BSTR;
2415     V_BSTR(&val) = attr1;
2416     hres = IHTMLElement_setAttribute(elem, attr1, val, 0);
2417     ok(hres == S_OK, "setAttribute failed: %08x\n", hres);
2418     SysFreeString(attr1);
2419 }
2420
2421 static void test_attr_collection_disp(IDispatch *disp)
2422 {
2423     IDispatchEx *dispex;
2424     IHTMLDOMAttribute *attr;
2425     DISPPARAMS dp = {NULL, NULL, 0, 0};
2426     VARIANT var;
2427     EXCEPINFO ei;
2428     DISPID id;
2429     BSTR bstr;
2430     HRESULT hres;
2431
2432     hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
2433     ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
2434
2435     bstr = a2bstr("0");
2436     hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id);
2437     ok(hres == S_OK, "GetDispID failed: %08x\n", hres);
2438     SysFreeString(bstr);
2439
2440     VariantInit(&var);
2441     hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL);
2442     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
2443     ok(V_VT(&var) == VT_DISPATCH, "V_VT(var)=%d\n", V_VT(&var));
2444     ok(V_DISPATCH(&var) != NULL, "V_DISPATCH(var) == NULL\n");
2445     VariantClear(&var);
2446
2447     bstr = a2bstr("attr1");
2448     hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id);
2449     ok(hres == S_OK, "GetDispID failed: %08x\n", hres);
2450     SysFreeString(bstr);
2451
2452     VariantInit(&var);
2453     hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL);
2454     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
2455     ok(V_VT(&var) == VT_DISPATCH, "V_VT(var)=%d\n", V_VT(&var));
2456     ok(V_DISPATCH(&var) != NULL, "V_DISPATCH(var) == NULL\n");
2457     hres = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IHTMLDOMAttribute, (void**)&attr);
2458     ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
2459     hres = IHTMLDOMAttribute_get_nodeName(attr, &bstr);
2460     ok(hres == S_OK, "get_nodeName failed: %08x\n", hres);
2461     ok(!strcmp_wa(bstr, "attr1"), "node name is %s, expected attr1\n", wine_dbgstr_w(bstr));
2462     SysFreeString(bstr);
2463     IHTMLDOMAttribute_Release(attr);
2464     VariantClear(&var);
2465
2466     IDispatchEx_Release(dispex);
2467 }
2468
2469 static void test_attr_collection(IHTMLElement *elem)
2470 {
2471     static const WCHAR testW[] = {'t','e','s','t',0};
2472
2473     IHTMLDOMNode *node;
2474     IDispatch *disp, *attr;
2475     IHTMLDOMAttribute *dom_attr;
2476     IHTMLAttributeCollection *attr_col;
2477     BSTR name = SysAllocString(testW);
2478     VARIANT id, val;
2479     LONG i, len, checked;
2480     HRESULT hres;
2481
2482     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLDOMNode, (void**)&node);
2483     ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
2484
2485     hres = IHTMLDOMNode_get_attributes(node, &disp);
2486     ok(hres == S_OK, "get_attributes failed: %08x\n", hres);
2487
2488     hres = IHTMLDOMNode_get_attributes(node, &attr);
2489     ok(hres == S_OK, "get_attributes failed: %08x\n", hres);
2490     ok(iface_cmp((IUnknown*)disp, (IUnknown*)attr), "disp != attr\n");
2491     IDispatch_Release(attr);
2492     IHTMLDOMNode_Release(node);
2493
2494     hres = IDispatch_QueryInterface(disp, &IID_IHTMLAttributeCollection, (void**)&attr_col);
2495     ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
2496
2497     hres = IHTMLAttributeCollection_get_length(attr_col, &i);
2498     ok(hres == S_OK, "get_length failed: %08x\n", hres);
2499
2500     V_VT(&val) = VT_I4;
2501     V_I4(&val) = 1;
2502     hres = IHTMLElement_setAttribute(elem, name, val, 0);
2503     ok(hres == S_OK, "setAttribute failed: %08x\n", hres);
2504     SysFreeString(name);
2505
2506     hres = IHTMLAttributeCollection_get_length(attr_col, &len);
2507     ok(hres == S_OK, "get_length failed: %08x\n", hres);
2508     ok(len == i+1, "get_length returned %d, expected %d\n", len, i+1);
2509
2510     checked = 0;
2511     for(i=0; i<len; i++) {
2512         V_VT(&id) = VT_I4;
2513         V_I4(&id) = i;
2514         hres = IHTMLAttributeCollection_item(attr_col, &id, &attr);
2515         ok(hres == S_OK, "%d) item failed: %08x\n", i, hres);
2516
2517         hres = IDispatch_QueryInterface(attr, &IID_IHTMLDOMAttribute, (void**)&dom_attr);
2518         ok(hres == S_OK, "%d) QueryInterface failed: %08x\n", i, hres);
2519         IDispatch_Release(attr);
2520
2521         hres = IHTMLDOMAttribute_get_nodeName(dom_attr, &name);
2522         ok(hres == S_OK, "%d) get_nodeName failed: %08x\n", i, hres);
2523
2524         if(!strcmp_wa(name, "id")) {
2525             checked++;
2526             hres = IHTMLDOMAttribute_get_nodeValue(dom_attr, &val);
2527             ok(hres == S_OK, "%d) get_nodeValue failed: %08x\n", i, hres);
2528             ok(V_VT(&val) == VT_BSTR, "id: V_VT(&val) = %d\n", V_VT(&val));
2529             ok(!strcmp_wa(V_BSTR(&val), "attr"), "id: V_BSTR(&val) = %s\n", wine_dbgstr_w(V_BSTR(&val)));
2530         } else if(!strcmp_wa(name, "attr1")) {
2531             checked++;
2532             hres = IHTMLDOMAttribute_get_nodeValue(dom_attr, &val);
2533             ok(hres == S_OK, "%d) get_nodeValue failed: %08x\n", i, hres);
2534             ok(V_VT(&val) == VT_BSTR, "attr1: V_VT(&val) = %d\n", V_VT(&val));
2535             ok(!strcmp_wa(V_BSTR(&val), "attr1"), "attr1: V_BSTR(&val) = %s\n", wine_dbgstr_w(V_BSTR(&val)));
2536         } else if(!strcmp_wa(name, "attr2")) {
2537             checked++;
2538             hres = IHTMLDOMAttribute_get_nodeValue(dom_attr, &val);
2539             ok(hres == S_OK, "%d) get_nodeValue failed: %08x\n", i, hres);
2540             ok(V_VT(&val) == VT_BSTR, "attr2: V_VT(&val) = %d\n", V_VT(&val));
2541             ok(!V_BSTR(&val), "attr2: V_BSTR(&val) != NULL\n");
2542         } else if(!strcmp_wa(name, "attr3")) {
2543             checked++;
2544             hres = IHTMLDOMAttribute_get_nodeValue(dom_attr, &val);
2545             ok(hres == S_OK, "%d) get_nodeValue failed: %08x\n", i, hres);
2546             ok(V_VT(&val) == VT_BSTR, "attr3: V_VT(&val) = %d\n", V_VT(&val));
2547             ok(!strcmp_wa(V_BSTR(&val), "attr3"), "attr3: V_BSTR(&val) = %s\n", wine_dbgstr_w(V_BSTR(&val)));
2548         } else if(!strcmp_wa(name, "test")) {
2549             checked++;
2550             hres = IHTMLDOMAttribute_get_nodeValue(dom_attr, &val);
2551             ok(hres == S_OK, "%d) get_nodeValue failed: %08x\n", i, hres);
2552             ok(V_VT(&val) == VT_I4, "test: V_VT(&val) = %d\n", V_VT(&val));
2553             ok(V_I4(&val) == 1, "test: V_I4(&val) = %d\n", V_I4(&val));
2554         }
2555
2556         IHTMLDOMAttribute_Release(dom_attr);
2557         SysFreeString(name);
2558         VariantClear(&val);
2559     }
2560     ok(checked==5, "invalid number of specified attributes (%d)\n", checked);
2561
2562     V_I4(&id) = len;
2563     hres = IHTMLAttributeCollection_item(attr_col, &id, &attr);
2564     ok(hres == E_INVALIDARG, "item failed: %08x\n", hres);
2565
2566     V_VT(&id) = VT_BSTR;
2567     V_BSTR(&id) = a2bstr("nonexisting");
2568     hres = IHTMLAttributeCollection_item(attr_col, &id, &attr);
2569     ok(hres == E_INVALIDARG, "item failed: %08x\n", hres);
2570     VariantClear(&id);
2571
2572     test_attr_collection_disp(disp);
2573
2574     IDispatch_Release(disp);
2575     IHTMLAttributeCollection_Release(attr_col);
2576 }
2577
2578 #define test_input_type(i,t) _test_input_type(__LINE__,i,t)
2579 static void _test_input_type(unsigned line, IHTMLInputElement *input, const char *extype)
2580 {
2581     BSTR type;
2582     HRESULT hres;
2583
2584     hres = IHTMLInputElement_get_type(input, &type);
2585     ok_(__FILE__,line) (hres == S_OK, "get_type failed: %08x\n", hres);
2586     ok_(__FILE__,line) (!strcmp_wa(type, extype), "type=%s, expected %s\n", wine_dbgstr_w(type), extype);
2587     SysFreeString(type);
2588 }
2589
2590 #define test_input_name(u, c) _test_input_name(__LINE__,u, c)
2591 static void _test_input_name(unsigned line, IHTMLInputElement *input, const char *exname)
2592 {
2593     BSTR name = (BSTR)0xdeadbeef;
2594     HRESULT hres;
2595
2596     hres = IHTMLInputElement_get_name(input, &name);
2597     ok_(__FILE__,line) (hres == S_OK, "get_name failed: %08x\n", hres);
2598     if(exname)
2599         ok_(__FILE__,line) (!strcmp_wa (name, exname), "name=%s, expected %s\n", wine_dbgstr_w(name), exname);
2600     else
2601         ok_(__FILE__,line) (!name, "name=%p, expected NULL\n", name);
2602     SysFreeString(name);
2603 }
2604
2605 #define test_input_set_name(u, c) _test_input_set_name(__LINE__,u, c)
2606 static void _test_input_set_name(unsigned line, IHTMLInputElement *input, const char *name)
2607 {
2608     BSTR tmp = a2bstr(name);
2609     HRESULT hres;
2610
2611     hres = IHTMLInputElement_put_name(input, tmp);
2612     ok_(__FILE__,line) (hres == S_OK, "put_name failed: %08x\n", hres);
2613     SysFreeString(tmp);
2614
2615     _test_input_name(line, input, name);
2616 }
2617
2618 #define test_input_get_disabled(i,b) _test_input_get_disabled(__LINE__,i,b)
2619 static void _test_input_get_disabled(unsigned line, IHTMLInputElement *input, VARIANT_BOOL exb)
2620 {
2621     VARIANT_BOOL disabled = 100;
2622     HRESULT hres;
2623
2624     hres = IHTMLInputElement_get_disabled(input, &disabled);
2625     ok_(__FILE__,line) (hres == S_OK, "get_disabled failed: %08x\n", hres);
2626     ok_(__FILE__,line) (disabled == exb, "disabled=%x, expected %x\n", disabled, exb);
2627
2628     _test_elem3_get_disabled(line, (IUnknown*)input, exb);
2629 }
2630
2631 #define test_input_set_disabled(i,b) _test_input_set_disabled(__LINE__,i,b)
2632 static void _test_input_set_disabled(unsigned line, IHTMLInputElement *input, VARIANT_BOOL b)
2633 {
2634     HRESULT hres;
2635
2636     hres = IHTMLInputElement_put_disabled(input, b);
2637     ok_(__FILE__,line) (hres == S_OK, "get_disabled failed: %08x\n", hres);
2638
2639     _test_input_get_disabled(line, input, b);
2640 }
2641
2642 #define test_input_get_defaultchecked(i,b) _test_input_get_defaultchecked(__LINE__,i,b)
2643 static void _test_input_get_defaultchecked(unsigned line, IHTMLInputElement *input, VARIANT_BOOL exb)
2644 {
2645     VARIANT_BOOL checked = 100;
2646     HRESULT hres;
2647
2648     hres = IHTMLInputElement_get_defaultChecked(input, &checked);
2649     ok_(__FILE__,line) (hres == S_OK, "get_defaultChecked failed: %08x\n", hres);
2650     ok_(__FILE__,line) (checked == exb, "checked=%x, expected %x\n", checked, exb);
2651 }
2652
2653 #define test_input_set_defaultchecked(i,b) _test_input_set_defaultchecked(__LINE__,i,b)
2654 static void _test_input_set_defaultchecked(unsigned line, IHTMLInputElement *input, VARIANT_BOOL b)
2655 {
2656     HRESULT hres;
2657
2658     hres = IHTMLInputElement_put_defaultChecked(input, b);
2659     ok_(__FILE__,line) (hres == S_OK, "get_defaultChecked failed: %08x\n", hres);
2660
2661     _test_input_get_defaultchecked(line, input, b);
2662 }
2663
2664 #define test_input_get_checked(i,b) _test_input_get_checked(__LINE__,i,b)
2665 static void _test_input_get_checked(unsigned line, IHTMLInputElement *input, VARIANT_BOOL exb)
2666 {
2667     VARIANT_BOOL checked = 100;
2668     HRESULT hres;
2669
2670     hres = IHTMLInputElement_get_checked(input, &checked);
2671     ok_(__FILE__,line) (hres == S_OK, "get_checked failed: %08x\n", hres);
2672     ok_(__FILE__,line) (checked == exb, "checked=%x, expected %x\n", checked, exb);
2673 }
2674
2675 #define test_input_set_checked(i,b) _test_input_set_checked(__LINE__,i,b)
2676 static void _test_input_set_checked(unsigned line, IHTMLInputElement *input, VARIANT_BOOL b)
2677 {
2678     HRESULT hres;
2679
2680     hres = IHTMLInputElement_put_checked(input, b);
2681     ok_(__FILE__,line) (hres == S_OK, "get_checked failed: %08x\n", hres);
2682
2683     _test_input_get_checked(line, input, b);
2684 }
2685
2686 #define test_input_value(o,t) _test_input_value(__LINE__,o,t)
2687 static void _test_input_value(unsigned line, IUnknown *unk, const char *exval)
2688 {
2689     IHTMLInputElement *input;
2690     BSTR bstr;
2691     HRESULT hres;
2692
2693     hres = IUnknown_QueryInterface(unk, &IID_IHTMLInputElement, (void**)&input);
2694     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLInputElement: %08x\n", hres);
2695     if(FAILED(hres))
2696         return;
2697
2698     hres = IHTMLInputElement_get_value(input, &bstr);
2699     ok_(__FILE__,line) (hres == S_OK, "get_value failed: %08x\n", hres);
2700     if(exval)
2701         ok_(__FILE__,line) (!strcmp_wa(bstr, exval), "value=%s\n", wine_dbgstr_w(bstr));
2702     else
2703         ok_(__FILE__,line) (!bstr, "exval != NULL\n");
2704     SysFreeString(bstr);
2705     IHTMLInputElement_Release(input);
2706 }
2707
2708 #define test_input_put_value(o,v) _test_input_put_value(__LINE__,o,v)
2709 static void _test_input_put_value(unsigned line, IUnknown *unk, const char *val)
2710 {
2711     IHTMLInputElement *input;
2712     BSTR bstr;
2713     HRESULT hres;
2714
2715     hres = IUnknown_QueryInterface(unk, &IID_IHTMLInputElement, (void**)&input);
2716     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLInputElement: %08x\n", hres);
2717     if(FAILED(hres))
2718         return;
2719
2720     bstr = a2bstr(val);
2721     hres = IHTMLInputElement_put_value(input, bstr);
2722     ok_(__FILE__,line) (hres == S_OK, "get_value failed: %08x\n", hres);
2723     SysFreeString(bstr);
2724     IHTMLInputElement_Release(input);
2725
2726     _test_input_value(line, unk, val);
2727 }
2728
2729 #define test_input_src(i,s) _test_input_src(__LINE__,i,s)
2730 static void _test_input_src(unsigned line, IHTMLInputElement *input, const char *exsrc)
2731 {
2732     BSTR src;
2733     HRESULT hres;
2734
2735     hres = IHTMLInputElement_get_src(input, &src);
2736     ok_(__FILE__,line) (hres == S_OK, "get_src failed: %08x\n", hres);
2737     if(exsrc)
2738         ok_(__FILE__,line) (!strcmp_wa(src, exsrc), "get_src returned %s expected %s\n", wine_dbgstr_w(src), exsrc);
2739     else
2740         ok_(__FILE__,line) (!src, "get_src returned %s expected NULL\n", wine_dbgstr_w(src));
2741     SysFreeString(src);
2742 }
2743
2744 #define test_input_set_src(u,s) _test_input_set_src(__LINE__,u,s)
2745 static void _test_input_set_src(unsigned line, IHTMLInputElement *input, const char *src)
2746 {
2747     BSTR tmp;
2748     HRESULT hres;
2749
2750     tmp = a2bstr(src);
2751     hres = IHTMLInputElement_put_src(input, tmp);
2752     SysFreeString(tmp);
2753     ok_(__FILE__,line) (hres == S_OK, "put_src failed: %08x\n", hres);
2754
2755     _test_input_src(line, input, src);
2756 }
2757
2758 #define test_elem_class(u,c) _test_elem_class(__LINE__,u,c)
2759 static void _test_elem_class(unsigned line, IUnknown *unk, const char *exclass)
2760 {
2761     IHTMLElement *elem = _get_elem_iface(line, unk);
2762     BSTR class = (void*)0xdeadbeef;
2763     HRESULT hres;
2764
2765     hres = IHTMLElement_get_className(elem, &class);
2766     IHTMLElement_Release(elem);
2767     ok_(__FILE__,line) (hres == S_OK, "get_className failed: %08x\n", hres);
2768     if(exclass)
2769         ok_(__FILE__,line) (!strcmp_wa(class, exclass), "unexpected className %s\n", wine_dbgstr_w(class));
2770     else
2771         ok_(__FILE__,line) (!class, "class != NULL\n");
2772     SysFreeString(class);
2773 }
2774
2775 #define test_elem_tabindex(u,i) _test_elem_tabindex(__LINE__,u,i)
2776 static void _test_elem_tabindex(unsigned line, IUnknown *unk, short exindex)
2777 {
2778     IHTMLElement2 *elem2 = _get_elem2_iface(line, unk);
2779     short index = -3;
2780     HRESULT hres;
2781
2782     hres = IHTMLElement2_get_tabIndex(elem2, &index);
2783     IHTMLElement2_Release(elem2);
2784     ok_(__FILE__,line) (hres == S_OK, "get_tabIndex failed: %08x\n", hres);
2785     ok_(__FILE__,line) (index == exindex, "unexpected index %d\n", index);
2786 }
2787
2788 #define test_elem_set_tabindex(u,i) _test_elem_set_tabindex(__LINE__,u,i)
2789 static void _test_elem_set_tabindex(unsigned line, IUnknown *unk, short index)
2790 {
2791     IHTMLElement2 *elem2 = _get_elem2_iface(line, unk);
2792     HRESULT hres;
2793
2794     hres = IHTMLElement2_put_tabIndex(elem2, index);
2795     IHTMLElement2_Release(elem2);
2796     ok_(__FILE__,line) (hres == S_OK, "get_tabIndex failed: %08x\n", hres);
2797
2798     _test_elem_tabindex(line, unk, index);
2799 }
2800
2801 #define test_style_media(s,m) _test_style_media(__LINE__,s,m)
2802 static void _test_style_media(unsigned line, IUnknown *unk, const char *exmedia)
2803 {
2804     IHTMLStyleElement *style = _get_style_iface(line, unk);
2805     BSTR media;
2806     HRESULT hres;
2807
2808     hres = IHTMLStyleElement_get_media(style, &media);
2809     ok_(__FILE__,line)(hres == S_OK, "get_media failed: %08x\n", hres);
2810     if(exmedia)
2811         ok_(__FILE__,line)(!strcmp_wa(media, exmedia), "media = %s, expected %s\n", wine_dbgstr_w(media), exmedia);
2812     else
2813         ok_(__FILE__,line)(!media, "media = %s, expected NULL\n", wine_dbgstr_w(media));
2814
2815     IHTMLStyleElement_Release(style);
2816     SysFreeString(media);
2817 }
2818
2819 #define test_style_put_media(s,m) _test_style_put_media(__LINE__,s,m)
2820 static void _test_style_put_media(unsigned line, IUnknown *unk, const char *media)
2821 {
2822     IHTMLStyleElement *style = _get_style_iface(line, unk);
2823     BSTR str;
2824     HRESULT hres;
2825
2826     str = a2bstr(media);
2827     hres = IHTMLStyleElement_put_media(style, str);
2828     ok_(__FILE__,line)(hres == S_OK, "put_media failed: %08x\n", hres);
2829     IHTMLStyleElement_Release(style);
2830     SysFreeString(str);
2831
2832     _test_style_media(line, unk, media);
2833 }
2834
2835 #define test_style_type(s,m) _test_style_type(__LINE__,s,m)
2836 static void _test_style_type(unsigned line, IUnknown *unk, const char *extype)
2837 {
2838     IHTMLStyleElement *style = _get_style_iface(line, unk);
2839     BSTR type;
2840     HRESULT hres;
2841
2842     hres = IHTMLStyleElement_get_type(style, &type);
2843     ok_(__FILE__,line)(hres == S_OK, "get_type failed: %08x\n", hres);
2844     if(extype)
2845         ok_(__FILE__,line)(!strcmp_wa(type, extype), "type = %s, expected %s\n", wine_dbgstr_w(type), extype);
2846     else
2847         ok_(__FILE__,line)(!type, "type = %s, expected NULL\n", wine_dbgstr_w(type));
2848
2849     IHTMLStyleElement_Release(style);
2850     SysFreeString(type);
2851 }
2852
2853 #define test_style_put_type(s,m) _test_style_put_type(__LINE__,s,m)
2854 static void _test_style_put_type(unsigned line, IUnknown *unk, const char *type)
2855 {
2856     IHTMLStyleElement *style = _get_style_iface(line, unk);
2857     BSTR str;
2858     HRESULT hres;
2859
2860     str = a2bstr(type);
2861     hres = IHTMLStyleElement_put_type(style, str);
2862     ok_(__FILE__,line)(hres == S_OK, "put_type failed: %08x\n", hres);
2863     IHTMLStyleElement_Release(style);
2864     SysFreeString(str);
2865
2866     _test_style_type(line, unk, type);
2867 }
2868
2869 #define test_elem_filters(u) _test_elem_filters(__LINE__,u)
2870 static void _test_elem_filters(unsigned line, IUnknown *unk)
2871 {
2872     IHTMLElement *elem = _get_elem_iface(line, unk);
2873     HRESULT hres;
2874     IHTMLFiltersCollection *filters;
2875
2876     hres = IHTMLElement_get_filters(elem, &filters);
2877     ok_(__FILE__,line) (hres == S_OK || broken(hres == REGDB_E_CLASSNOTREG) /* NT4 */,
2878                         "get_filters failed: %08x\n", hres);
2879     if(hres == S_OK)
2880     {
2881         LONG len;
2882         IDispatchEx *dispex;
2883
2884         hres = IHTMLFiltersCollection_get_length(filters, &len);
2885         ok_(__FILE__,line) (hres == S_OK, "get_length failed: %08x\n", hres);
2886         ok_(__FILE__,line) (len == 0, "expect 0 got %d\n", len);
2887
2888         hres = IHTMLFiltersCollection_QueryInterface(filters, &IID_IDispatchEx, (void**)&dispex);
2889         ok_(__FILE__,line) (hres == S_OK || broken(hres == E_NOINTERFACE),
2890                             "Could not get IDispatchEx interface: %08x\n", hres);
2891         if(SUCCEEDED(hres)) {
2892             test_disp((IUnknown*)filters, &IID_IHTMLFiltersCollection, "[object]");
2893             IDispatchEx_Release(dispex);
2894         }
2895
2896         IHTMLFiltersCollection_Release(filters);
2897     }
2898
2899     IHTMLElement_Release(elem);
2900 }
2901
2902 #define test_elem_set_class(u,c) _test_elem_set_class(__LINE__,u,c)
2903 static void _test_elem_set_class(unsigned line, IUnknown *unk, const char *class)
2904 {
2905     IHTMLElement *elem = _get_elem_iface(line, unk);
2906     BSTR tmp;
2907     HRESULT hres;
2908
2909     tmp = class ? a2bstr(class) : NULL;
2910     hres = IHTMLElement_put_className(elem, tmp);
2911     IHTMLElement_Release(elem);
2912     ok_(__FILE__,line) (hres == S_OK, "put_className failed: %08x\n", hres);
2913     SysFreeString(tmp);
2914
2915     _test_elem_class(line, unk, class);
2916 }
2917
2918 #define test_elem_id(e,i) _test_elem_id(__LINE__,e,i)
2919 static void _test_elem_id(unsigned line, IUnknown *unk, const char *exid)
2920 {
2921     IHTMLElement *elem = _get_elem_iface(line, unk);
2922     BSTR id = (void*)0xdeadbeef;
2923     HRESULT hres;
2924
2925     hres = IHTMLElement_get_id(elem, &id);
2926     IHTMLElement_Release(elem);
2927     ok_(__FILE__,line) (hres == S_OK, "get_id failed: %08x\n", hres);
2928
2929     if(exid)
2930         ok_(__FILE__,line) (!strcmp_wa(id, exid), "unexpected id %s\n", wine_dbgstr_w(id));
2931     else
2932         ok_(__FILE__,line) (!id, "id=%s\n", wine_dbgstr_w(id));
2933
2934     SysFreeString(id);
2935 }
2936
2937 #define test_elem_put_id(u,i) _test_elem_put_id(__LINE__,u,i)
2938 static void _test_elem_put_id(unsigned line, IUnknown *unk, const char *new_id)
2939 {
2940     IHTMLElement *elem = _get_elem_iface(line, unk);
2941     BSTR tmp = a2bstr(new_id);
2942     HRESULT hres;
2943
2944     hres = IHTMLElement_put_id(elem, tmp);
2945     IHTMLElement_Release(elem);
2946     SysFreeString(tmp);
2947     ok_(__FILE__,line) (hres == S_OK, "put_id failed: %08x\n", hres);
2948
2949     _test_elem_id(line, unk, new_id);
2950 }
2951
2952 #define test_elem_title(u,t) _test_elem_title(__LINE__,u,t)
2953 static void _test_elem_title(unsigned line, IUnknown *unk, const char *extitle)
2954 {
2955     IHTMLElement *elem = _get_elem_iface(line, unk);
2956     BSTR title;
2957     HRESULT hres;
2958
2959     hres = IHTMLElement_get_title(elem, &title);
2960     IHTMLElement_Release(elem);
2961     ok_(__FILE__,line) (hres == S_OK, "get_title failed: %08x\n", hres);
2962     if(extitle)
2963         ok_(__FILE__,line) (!strcmp_wa(title, extitle), "unexpected title %s\n", wine_dbgstr_w(title));
2964     else
2965         ok_(__FILE__,line) (!title, "title=%s, expected NULL\n", wine_dbgstr_w(title));
2966
2967     SysFreeString(title);
2968 }
2969
2970 #define test_elem_set_title(u,t) _test_elem_set_title(__LINE__,u,t)
2971 static void _test_elem_set_title(unsigned line, IUnknown *unk, const char *title)
2972 {
2973     IHTMLElement *elem = _get_elem_iface(line, unk);
2974     BSTR tmp;
2975     HRESULT hres;
2976
2977     tmp = a2bstr(title);
2978     hres = IHTMLElement_put_title(elem, tmp);
2979     ok_(__FILE__,line) (hres == S_OK, "get_title failed: %08x\n", hres);
2980
2981     IHTMLElement_Release(elem);
2982     SysFreeString(tmp);
2983 }
2984
2985 #define test_node_get_value_str(u,e) _test_node_get_value_str(__LINE__,u,e)
2986 static void _test_node_get_value_str(unsigned line, IUnknown *unk, const char *exval)
2987 {
2988     IHTMLDOMNode *node = _get_node_iface(line, unk);
2989     VARIANT var;
2990     HRESULT hres;
2991
2992     hres = IHTMLDOMNode_get_nodeValue(node, &var);
2993     IHTMLDOMNode_Release(node);
2994     ok_(__FILE__,line) (hres == S_OK, "get_nodeValue failed: %08x, expected VT_BSTR\n", hres);
2995
2996     if(exval) {
2997         ok_(__FILE__,line) (V_VT(&var) == VT_BSTR, "vt=%d\n", V_VT(&var));
2998         ok_(__FILE__,line) (!strcmp_wa(V_BSTR(&var), exval), "unexpected value %s\n", wine_dbgstr_w(V_BSTR(&var)));
2999     }else {
3000         ok_(__FILE__,line) (V_VT(&var) == VT_NULL, "vt=%d, expected VT_NULL\n", V_VT(&var));
3001     }
3002
3003     VariantClear(&var);
3004 }
3005
3006 #define test_node_put_value_str(u,v) _test_node_put_value_str(__LINE__,u,v)
3007 static void _test_node_put_value_str(unsigned line, IUnknown *unk, const char *val)
3008 {
3009     IHTMLDOMNode *node = _get_node_iface(line, unk);
3010     VARIANT var;
3011     HRESULT hres;
3012
3013     V_VT(&var) = VT_BSTR;
3014     V_BSTR(&var) = a2bstr(val);
3015
3016     hres = IHTMLDOMNode_put_nodeValue(node, var);
3017     ok_(__FILE__,line) (hres == S_OK, "get_nodeValue failed: %08x, expected VT_BSTR\n", hres);
3018     IHTMLDOMNode_Release(node);
3019     VariantClear(&var);
3020 }
3021
3022 #define test_elem_client_size(u) _test_elem_client_size(__LINE__,u)
3023 static void _test_elem_client_size(unsigned line, IUnknown *unk)
3024 {
3025     IHTMLElement2 *elem = _get_elem2_iface(line, unk);
3026     LONG l;
3027     HRESULT hres;
3028
3029     hres = IHTMLElement2_get_clientWidth(elem, &l);
3030     ok_(__FILE__,line) (hres == S_OK, "get_clientWidth failed: %08x\n", hres);
3031     hres = IHTMLElement2_get_clientHeight(elem, &l);
3032     ok_(__FILE__,line) (hres == S_OK, "get_clientHeight failed: %08x\n", hres);
3033
3034     IHTMLElement2_Release(elem);
3035 }
3036
3037 #define test_elem_client_rect(u) _test_elem_client_rect(__LINE__,u)
3038 static void _test_elem_client_rect(unsigned line, IUnknown *unk)
3039 {
3040     IHTMLElement2 *elem = _get_elem2_iface(line, unk);
3041     LONG l;
3042     HRESULT hres;
3043
3044     hres = IHTMLElement2_get_clientLeft(elem, &l);
3045     ok_(__FILE__,line) (hres == S_OK, "get_clientLeft failed: %08x\n", hres);
3046     ok_(__FILE__,line) (!l, "clientLeft = %d\n", l);
3047
3048     hres = IHTMLElement2_get_clientTop(elem, &l);
3049     ok_(__FILE__,line) (hres == S_OK, "get_clientTop failed: %08x\n", hres);
3050     ok_(__FILE__,line) (!l, "clientTop = %d\n", l);
3051
3052     IHTMLElement2_Release(elem);
3053 }
3054
3055 #define test_form_length(e,l) _test_form_length(__LINE__,e,l)
3056 static void _test_form_length(unsigned line, IUnknown *unk, LONG exlen)
3057 {
3058     IHTMLFormElement *form = _get_form_iface(line, unk);
3059     LONG len = 0xdeadbeef;
3060     HRESULT hres;
3061
3062     hres = IHTMLFormElement_get_length(form, &len);
3063     ok_(__FILE__,line)(hres == S_OK, "get_length failed: %08x\n", hres);
3064     ok_(__FILE__,line)(len == exlen, "length=%d, expected %d\n", len, exlen);
3065
3066     IHTMLFormElement_Release(form);
3067 }
3068
3069 #define test_form_action(f,a) _test_form_action(__LINE__,f,a)
3070 static void _test_form_action(unsigned line, IUnknown *unk, const char *ex)
3071 {
3072     IHTMLFormElement *form = _get_form_iface(line, unk);
3073     BSTR action = (void*)0xdeadbeef;
3074     HRESULT hres;
3075
3076     hres = IHTMLFormElement_get_action(form, &action);
3077     ok_(__FILE__,line)(hres == S_OK, "get_action failed: %08x\n", hres);
3078     if(ex)
3079         ok_(__FILE__,line)(!strcmp_wa(action, ex), "action=%s, expected %s\n", wine_dbgstr_w(action), ex);
3080     else
3081         ok_(__FILE__,line)(!action, "action=%p\n", action);
3082
3083     SysFreeString(action);
3084     IHTMLFormElement_Release(form);
3085 }
3086
3087 #define test_form_put_action(f,a) _test_form_put_action(__LINE__,f,a)
3088 static void _test_form_put_action(unsigned line, IUnknown *unk, const char *action)
3089 {
3090     IHTMLFormElement *form = _get_form_iface(line, unk);
3091     BSTR tmp = a2bstr(action);
3092     HRESULT hres;
3093
3094     hres = IHTMLFormElement_put_action(form, tmp);
3095     ok_(__FILE__,line)(hres == S_OK, "put_action failed: %08x\n", hres);
3096     SysFreeString(tmp);
3097     IHTMLFormElement_Release(form);
3098
3099     _test_form_action(line, unk, action);
3100 }
3101
3102 #define test_form_method(f,a) _test_form_method(__LINE__,f,a)
3103 static void _test_form_method(unsigned line, IUnknown *unk, const char *ex)
3104 {
3105     IHTMLFormElement *form = _get_form_iface(line, unk);
3106     BSTR method = (void*)0xdeadbeef;
3107     HRESULT hres;
3108
3109     hres = IHTMLFormElement_get_method(form, &method);
3110     ok_(__FILE__,line)(hres == S_OK, "get_method failed: %08x\n", hres);
3111     if(ex)
3112         ok_(__FILE__,line)(!strcmp_wa(method, ex), "method=%s, expected %s\n", wine_dbgstr_w(method), ex);
3113     else
3114         ok_(__FILE__,line)(!method, "method=%p\n", method);
3115
3116     SysFreeString(method);
3117     IHTMLFormElement_Release(form);
3118 }
3119
3120 #define test_form_put_method(f,r,a) _test_form_put_method(__LINE__,f,r,a)
3121 static void _test_form_put_method(unsigned line, IUnknown *unk, HRESULT exp_hres, const char *method)
3122 {
3123     IHTMLFormElement *form = _get_form_iface(line, unk);
3124     BSTR tmp = a2bstr(method);
3125     HRESULT hres;
3126
3127     hres = IHTMLFormElement_put_method(form, tmp);
3128     ok_(__FILE__,line)(hres == exp_hres, "put_method returned: %08x, expected %08x\n", hres, exp_hres);
3129     SysFreeString(tmp);
3130     IHTMLFormElement_Release(form);
3131
3132     if(exp_hres == S_OK)
3133         _test_form_method(line, unk, method);
3134 }
3135
3136 #define test_form_name(f,a) _test_form_name(__LINE__,f,a)
3137 static void _test_form_name(unsigned line, IUnknown *unk, const char *ex)
3138 {
3139     IHTMLFormElement *form = _get_form_iface(line, unk);
3140     BSTR name = (void*)0xdeadbeef;
3141     HRESULT hres;
3142
3143     hres = IHTMLFormElement_get_name(form, &name);
3144     ok_(__FILE__,line)(hres == S_OK, "get_name failed: %08x\n", hres);
3145     if(ex)
3146         ok_(__FILE__,line)(!strcmp_wa(name, ex), "name=%s, expected %s\n", wine_dbgstr_w(name), ex);
3147     else
3148         ok_(__FILE__,line)(!name, "name=%p\n", name);
3149
3150     SysFreeString(name);
3151     IHTMLFormElement_Release(form);
3152 }
3153
3154 #define test_form_put_name(f,a) _test_form_put_name(__LINE__,f,a)
3155 static void _test_form_put_name(unsigned line, IUnknown *unk, const char *name)
3156 {
3157     IHTMLFormElement *form = _get_form_iface(line, unk);
3158     BSTR tmp = a2bstr(name);
3159     HRESULT hres;
3160
3161     hres = IHTMLFormElement_put_name(form, tmp);
3162     ok_(__FILE__,line)(hres == S_OK, "put_name failed: %08x\n", hres);
3163     SysFreeString(tmp);
3164     IHTMLFormElement_Release(form);
3165
3166     _test_form_name(line, unk, name);
3167 }
3168
3169 #define test_form_encoding(f,a) _test_form_encoding(__LINE__,f,a)
3170 static void _test_form_encoding(unsigned line, IUnknown *unk, const char *ex)
3171 {
3172     IHTMLFormElement *form = _get_form_iface(line, unk);
3173     BSTR encoding = (void*)0xdeadbeef;
3174     HRESULT hres;
3175
3176     hres = IHTMLFormElement_get_encoding(form, &encoding);
3177     ok_(__FILE__,line)(hres == S_OK, "get_encoding failed: %08x\n", hres);
3178     if(ex)
3179         ok_(__FILE__,line)(!strcmp_wa(encoding, ex), "encoding=%s, expected %s\n", wine_dbgstr_w(encoding), ex);
3180     else
3181         ok_(__FILE__,line)(!encoding, "encoding=%p\n", encoding);
3182
3183     SysFreeString(encoding);
3184     IHTMLFormElement_Release(form);
3185 }
3186
3187 #define test_form_put_encoding(f,r,a) _test_form_put_encoding(__LINE__,f,r,a)
3188 static void _test_form_put_encoding(unsigned line, IUnknown *unk, HRESULT exp_hres, const char *encoding)
3189 {
3190     IHTMLFormElement *form = _get_form_iface(line, unk);
3191     BSTR tmp = a2bstr(encoding);
3192     HRESULT hres;
3193
3194     hres = IHTMLFormElement_put_encoding(form, tmp);
3195     ok_(__FILE__,line)(hres == exp_hres, "put_encoding returned: %08x, expected %08x\n", hres, exp_hres);
3196     SysFreeString(tmp);
3197     IHTMLFormElement_Release(form);
3198
3199     if(exp_hres == S_OK)
3200         _test_form_encoding(line, unk, encoding);
3201 }
3202
3203 #define test_form_elements(a) _test_form_elements(__LINE__,a)
3204 static void _test_form_elements(unsigned line, IUnknown *unk)
3205 {
3206     IHTMLFormElement *form = _get_form_iface(line, unk);
3207     IDispatch *disp;
3208     HRESULT hres;
3209
3210     disp = NULL;
3211     hres = IHTMLFormElement_get_elements(form, &disp);
3212     ok_(__FILE__,line)(hres == S_OK, "get_elements failed: %08x\n", hres);
3213     ok_(__FILE__,line)(disp != NULL, "disp = NULL\n");
3214     ok_(__FILE__,line)(iface_cmp((IUnknown*)form, (IUnknown*)disp), "disp != form\n");
3215
3216     IDispatch_Release(disp);
3217     IHTMLFormElement_Release(form);
3218 }
3219
3220 #define get_elem_doc(e) _get_elem_doc(__LINE__,e)
3221 static IHTMLDocument2 *_get_elem_doc(unsigned line, IUnknown *unk)
3222 {
3223     IHTMLElement *elem = _get_elem_iface(line, unk);
3224     IHTMLDocument2 *doc;
3225     IDispatch *disp;
3226     HRESULT hres;
3227
3228     disp = NULL;
3229     hres = IHTMLElement_get_document(elem, &disp);
3230     ok(hres == S_OK, "get_document failed: %08x\n", hres);
3231     ok(disp != NULL, "disp == NULL\n");
3232
3233     hres = IDispatch_QueryInterface(disp, &IID_IHTMLDocument2, (void**)&doc);
3234     IDispatch_Release(disp);
3235     ok(hres == S_OK, "Could not get IHTMLDocument2 iface: %08x\n", hres);
3236
3237     return doc;
3238 }
3239
3240 #define get_elem_attr_node(a,b,c) _get_elem_attr_node(__LINE__,a,b,c)
3241 static IHTMLDOMAttribute *_get_elem_attr_node(unsigned line, IUnknown *unk, const char *attr_name, BOOL expect_success)
3242 {
3243     IHTMLElement4 *elem = _get_elem4_iface(line, unk);
3244     BSTR str = a2bstr(attr_name);
3245     IHTMLDOMAttribute *attr;
3246     HRESULT hres;
3247
3248     attr = (void*)0xdeadbeef;
3249     hres = IHTMLElement4_getAttributeNode(elem, str, &attr);
3250     ok_(__FILE__,line)(hres == S_OK, "getAttributeNode failed: %08x\n", hres);
3251     if(expect_success)
3252         ok_(__FILE__,line)(attr != NULL, "attr = NULL\n");
3253     else
3254         ok_(__FILE__,line)(!attr, "attr = %p\n", attr);
3255
3256     IHTMLElement4_Release(elem);
3257     SysFreeString(str);
3258     return attr;
3259 }
3260
3261 #define get_attr_node_value(a,b,c) _get_attr_node_value(__LINE__,a,b,c)
3262 static void _get_attr_node_value(unsigned line, IHTMLDOMAttribute *attr, VARIANT *v, VARTYPE vt)
3263 {
3264     HRESULT hres;
3265
3266     hres = IHTMLDOMAttribute_get_nodeValue(attr, v);
3267     ok_(__FILE__,line) (hres == S_OK, "get_nodeValue failed: %08x, expected VT_BSTR\n", hres);
3268     ok_(__FILE__,line) (V_VT(v) == vt, "vt=%d, expected %d\n", V_VT(v), vt);
3269 }
3270
3271 #define get_window_doc(e) _get_window_doc(__LINE__,e)
3272 static IHTMLDocument2 *_get_window_doc(unsigned line, IHTMLWindow2 *window)
3273 {
3274     IHTMLDocument2 *doc;
3275     HRESULT hres;
3276
3277     doc = NULL;
3278     hres = IHTMLWindow2_get_document(window, &doc);
3279     ok(hres == S_OK, "get_document failed: %08x\n", hres);
3280     ok(doc != NULL, "disp == NULL\n");
3281
3282     return doc;
3283 }
3284
3285 #define doc_get_body(d) _doc_get_body(__LINE__,d)
3286 static IHTMLElement *_doc_get_body(unsigned line, IHTMLDocument2 *doc)
3287 {
3288     IHTMLElement *elem;
3289     HRESULT hres;
3290
3291     hres = IHTMLDocument2_get_body(doc, &elem);
3292     ok_(__FILE__,line)(hres == S_OK, "get_body failed: %08x\n", hres);
3293     ok_(__FILE__,line)(elem != NULL, "body == NULL\n");
3294
3295     return elem;
3296 }
3297
3298 #define test_create_elem(d,t) _test_create_elem(__LINE__,d,t)
3299 static IHTMLElement *_test_create_elem(unsigned line, IHTMLDocument2 *doc, const char *tag)
3300 {
3301     IHTMLElement *elem = NULL;
3302     BSTR tmp;
3303     HRESULT hres;
3304
3305     tmp = a2bstr(tag);
3306     hres = IHTMLDocument2_createElement(doc, tmp, &elem);
3307     ok_(__FILE__,line) (hres == S_OK, "createElement failed: %08x\n", hres);
3308     ok_(__FILE__,line) (elem != NULL, "elem == NULL\n");
3309     SysFreeString(tmp);
3310
3311     return elem;
3312 }
3313
3314 #define test_create_text(d,t) _test_create_text(__LINE__,d,t)
3315 static IHTMLDOMNode *_test_create_text(unsigned line, IHTMLDocument2 *doc, const char *text)
3316 {
3317     IHTMLDocument3 *doc3;
3318     IHTMLDOMNode *node = NULL;
3319     BSTR tmp;
3320     HRESULT hres;
3321
3322     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
3323     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDocument3: %08x\n", hres);
3324
3325     tmp = a2bstr(text);
3326     hres = IHTMLDocument3_createTextNode(doc3, tmp, &node);
3327     IHTMLDocument3_Release(doc3);
3328     SysFreeString(tmp);
3329     ok_(__FILE__,line) (hres == S_OK, "createElement failed: %08x\n", hres);
3330     ok_(__FILE__,line) (node != NULL, "node == NULL\n");
3331
3332     return node;
3333 }
3334
3335 #define test_node_append_child(n,c) _test_node_append_child(__LINE__,n,c)
3336 static IHTMLDOMNode *_test_node_append_child(unsigned line, IUnknown *node_unk, IUnknown *child_unk)
3337 {
3338     IHTMLDOMNode *node = _get_node_iface(line, node_unk);
3339     IHTMLDOMNode *child = _get_node_iface(line, child_unk);
3340     IHTMLDOMNode *new_child = NULL;
3341     HRESULT hres;
3342
3343     hres = IHTMLDOMNode_appendChild(node, child, &new_child);
3344     ok_(__FILE__,line) (hres == S_OK, "appendChild failed: %08x\n", hres);
3345     ok_(__FILE__,line) (new_child != NULL, "new_child == NULL\n");
3346     /* TODO  ok_(__FILE__,line) (new_child != child, "new_child == child\n"); */
3347
3348     IHTMLDOMNode_Release(node);
3349     IHTMLDOMNode_Release(child);
3350
3351     return new_child;
3352 }
3353
3354 #define test_node_insertbefore(n,c,v) _test_node_insertbefore(__LINE__,n,c,v)
3355 static IHTMLDOMNode *_test_node_insertbefore(unsigned line, IUnknown *node_unk, IHTMLDOMNode *child, VARIANT *var)
3356 {
3357     IHTMLDOMNode *node = _get_node_iface(line, node_unk);
3358     IHTMLDOMNode *new_child = NULL;
3359     HRESULT hres;
3360
3361     hres = IHTMLDOMNode_insertBefore(node, child, *var, &new_child);
3362     ok_(__FILE__,line) (hres == S_OK, "insertBefore failed: %08x\n", hres);
3363     ok_(__FILE__,line) (new_child != NULL, "new_child == NULL\n");
3364     /* TODO  ok_(__FILE__,line) (new_child != child, "new_child == child\n"); */
3365
3366     IHTMLDOMNode_Release(node);
3367
3368     return new_child;
3369 }
3370
3371 #define test_node_remove_child(n,c) _test_node_remove_child(__LINE__,n,c)
3372 static void _test_node_remove_child(unsigned line, IUnknown *unk, IHTMLDOMNode *child)
3373 {
3374     IHTMLDOMNode *node = _get_node_iface(line, unk);
3375     IHTMLDOMNode *new_node = NULL;
3376     HRESULT hres;
3377
3378     hres = IHTMLDOMNode_removeChild(node, child, &new_node);
3379     ok_(__FILE__,line) (hres == S_OK, "removeChild failed: %08x\n", hres);
3380     ok_(__FILE__,line) (new_node != NULL, "new_node == NULL\n");
3381     /* TODO ok_(__FILE__,line) (new_node != child, "new_node == child\n"); */
3382
3383     IHTMLDOMNode_Release(node);
3384     IHTMLDOMNode_Release(new_node);
3385 }
3386
3387 #define test_doc_title(d,t) _test_doc_title(__LINE__,d,t)
3388 static void _test_doc_title(unsigned line, IHTMLDocument2 *doc, const char *extitle)
3389 {
3390     BSTR title = NULL;
3391     HRESULT hres;
3392
3393     hres = IHTMLDocument2_get_title(doc, &title);
3394     ok_(__FILE__,line) (hres == S_OK, "get_title failed: %08x\n", hres);
3395     ok_(__FILE__,line) (!strcmp_wa(title, extitle), "unexpected title %s\n", wine_dbgstr_w(title));
3396     SysFreeString(title);
3397 }
3398
3399 #define test_doc_set_title(d,t) _test_doc_set_title(__LINE__,d,t)
3400 static void _test_doc_set_title(unsigned line, IHTMLDocument2 *doc, const char *title)
3401 {
3402     BSTR tmp;
3403     HRESULT hres;
3404
3405     tmp = a2bstr(title);
3406     hres = IHTMLDocument2_put_title(doc, tmp);
3407     ok_(__FILE__,line) (hres == S_OK, "get_title failed: %08x\n", hres);
3408     SysFreeString(tmp);
3409 }
3410
3411 static void test_elem_bounding_client_rect(IUnknown *unk)
3412 {
3413     IHTMLRect *rect, *rect2;
3414     IHTMLElement2 *elem2;
3415     LONG l;
3416     HRESULT hres;
3417
3418     elem2 = get_elem2_iface(unk);
3419     hres = IHTMLElement2_getBoundingClientRect(elem2, &rect);
3420     ok(hres == S_OK, "getBoundingClientRect failed: %08x\n", hres);
3421     hres = IHTMLElement2_getBoundingClientRect(elem2, &rect2);
3422     IHTMLElement2_Release(elem2);
3423     ok(hres == S_OK, "getBoundingClientRect failed: %08x\n", hres);
3424     ok(rect != NULL, "rect == NULL\n");
3425     ok(rect != rect2, "rect == rect2\n");
3426     IHTMLRect_Release(rect2);
3427
3428     test_disp((IUnknown*)rect, &IID_IHTMLRect, "[object]");
3429
3430     l = 0xdeadbeef;
3431     hres = IHTMLRect_get_top(rect, &l);
3432     ok(hres == S_OK, "get_top failed: %08x\n", hres);
3433     ok(l != 0xdeadbeef, "l = 0xdeadbeef\n");
3434
3435     l = 0xdeadbeef;
3436     hres = IHTMLRect_get_left(rect, &l);
3437     ok(hres == S_OK, "get_left failed: %08x\n", hres);
3438     ok(l != 0xdeadbeef, "l = 0xdeadbeef\n");
3439
3440     l = 0xdeadbeef;
3441     hres = IHTMLRect_get_bottom(rect, &l);
3442     ok(hres == S_OK, "get_bottom failed: %08x\n", hres);
3443     ok(l != 0xdeadbeef, "l = 0xdeadbeef\n");
3444
3445     l = 0xdeadbeef;
3446     hres = IHTMLRect_get_right(rect, &l);
3447     ok(hres == S_OK, "get_right failed: %08x\n", hres);
3448     ok(l != 0xdeadbeef, "l = 0xdeadbeef\n");
3449
3450     IHTMLRect_Release(rect);
3451 }
3452
3453 static void test_elem_col_item(IHTMLElementCollection *col, const char *n,
3454         const elem_type_t *elem_types, LONG len)
3455 {
3456     IDispatch *disp;
3457     VARIANT name, index;
3458     DWORD i;
3459     HRESULT hres;
3460
3461     V_VT(&index) = VT_EMPTY;
3462     V_VT(&name) = VT_BSTR;
3463     V_BSTR(&name) = a2bstr(n);
3464
3465     hres = IHTMLElementCollection_item(col, name, index, &disp);
3466     ok(hres == S_OK, "item failed: %08x\n", hres);
3467
3468     test_elem_collection((IUnknown*)disp, elem_types, len);
3469     IDispatch_Release(disp);
3470     ok(hres == S_OK, "Could not get IHTMLElementCollection interface: %08x\n", hres);
3471     if(hres != S_OK)
3472         goto cleanup;
3473
3474     V_VT(&index) = VT_I4;
3475
3476     for(i=0; i<len; i++) {
3477         V_I4(&index) = i;
3478         disp = (void*)0xdeadbeef;
3479         hres = IHTMLElementCollection_item(col, name, index, &disp);
3480         ok(hres == S_OK, "item failed: %08x\n", hres);
3481         ok(disp != NULL, "disp == NULL\n");
3482         if(FAILED(hres) || !disp)
3483             continue;
3484
3485         test_elem_type((IUnknown*)disp, elem_types[i]);
3486
3487         IDispatch_Release(disp);
3488     }
3489
3490     V_I4(&index) = len;
3491     disp = (void*)0xdeadbeef;
3492     hres = IHTMLElementCollection_item(col, name, index, &disp);
3493     ok(hres == S_OK, "item failed: %08x\n", hres);
3494     ok(disp == NULL, "disp != NULL\n");
3495
3496     V_I4(&index) = -1;
3497     disp = (void*)0xdeadbeef;
3498     hres = IHTMLElementCollection_item(col, name, index, &disp);
3499     ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
3500     ok(disp == NULL, "disp != NULL\n");
3501
3502 cleanup:
3503     SysFreeString(V_BSTR(&name));
3504 }
3505
3506 static IHTMLElement *get_elem_by_id(IHTMLDocument2 *doc, const char *id, BOOL expect_success)
3507 {
3508     IHTMLElementCollection *col;
3509     IHTMLElement *elem;
3510     IDispatch *disp = (void*)0xdeadbeef;
3511     VARIANT name, index;
3512     HRESULT hres;
3513
3514     hres = IHTMLDocument2_get_all(doc, &col);
3515     ok(hres == S_OK, "get_all failed: %08x\n", hres);
3516     ok(col != NULL, "col == NULL\n");
3517     if(FAILED(hres) || !col)
3518         return NULL;
3519
3520     V_VT(&index) = VT_EMPTY;
3521     V_VT(&name) = VT_BSTR;
3522     V_BSTR(&name) = a2bstr(id);
3523
3524     hres = IHTMLElementCollection_item(col, name, index, &disp);
3525     IHTMLElementCollection_Release(col);
3526     SysFreeString(V_BSTR(&name));
3527     ok(hres == S_OK, "item failed: %08x\n", hres);
3528     if(!expect_success) {
3529         ok(disp == NULL, "disp != NULL\n");
3530         return NULL;
3531     }
3532
3533     ok(disp != NULL, "disp == NULL\n");
3534     if(!disp)
3535         return NULL;
3536
3537     elem = get_elem_iface((IUnknown*)disp);
3538     IDispatch_Release(disp);
3539
3540     return elem;
3541 }
3542
3543 static IHTMLElement *get_doc_elem_by_id(IHTMLDocument2 *doc, const char *id)
3544 {
3545     IHTMLDocument3 *doc3;
3546     IHTMLElement *elem;
3547     BSTR tmp;
3548     HRESULT hres;
3549
3550     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
3551     ok(hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres);
3552
3553     tmp = a2bstr(id);
3554     hres = IHTMLDocument3_getElementById(doc3, tmp, &elem);
3555     SysFreeString(tmp);
3556     ok(hres == S_OK, "getElementById(%s) failed: %08x\n", id, hres);
3557
3558     IHTMLDocument3_Release(doc3);
3559
3560     return elem;
3561 }
3562
3563 static void test_select_elem(IHTMLSelectElement *select)
3564 {
3565     IDispatch *disp, *disp2;
3566     VARIANT name, index;
3567     HRESULT hres;
3568
3569     test_select_type(select, "select-one");
3570     test_select_length(select, 2);
3571     test_select_selidx(select, 0);
3572     test_select_put_selidx(select, 1);
3573
3574     test_select_set_value(select, "val1");
3575     test_select_value(select, "val1");
3576
3577     test_select_get_disabled(select, VARIANT_FALSE);
3578     test_select_set_disabled(select, VARIANT_TRUE);
3579     test_select_set_disabled(select, VARIANT_FALSE);
3580
3581     disp = NULL;
3582     hres = IHTMLSelectElement_get_options(select, &disp);
3583     ok(hres == S_OK, "get_options failed: %08x\n", hres);
3584     ok(disp != NULL, "options == NULL\n");
3585     ok(iface_cmp((IUnknown*)disp, (IUnknown*)select), "disp != select\n");
3586     IDispatch_Release(disp);
3587
3588     V_VT(&index) = VT_EMPTY;
3589     V_VT(&name) = VT_I4;
3590     V_I4(&name) = -1;
3591     disp = (void*)0xdeadbeef;
3592     hres = IHTMLSelectElement_item(select, name, index, &disp);
3593     ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
3594     ok(!disp, "disp = %p\n", disp);
3595
3596     V_I4(&name) = 2;
3597     disp = (void*)0xdeadbeef;
3598     hres = IHTMLSelectElement_item(select, name, index, &disp);
3599     ok(hres == S_OK, "item failed: %08x\n", hres);
3600     ok(!disp, "disp = %p\n", disp);
3601
3602     V_I4(&name) = 1;
3603     hres = IHTMLSelectElement_item(select, name, index, NULL);
3604     ok(hres == E_POINTER || broken(hres == E_INVALIDARG), "item failed: %08x, expected E_POINTER\n", hres);
3605
3606     disp = NULL;
3607     hres = IHTMLSelectElement_item(select, name, index, &disp);
3608     ok(hres == S_OK, "item failed: %08x\n", hres);
3609     ok(disp != NULL, "disp = NULL\n");
3610     test_disp((IUnknown*)disp, &DIID_DispHTMLOptionElement, NULL);
3611
3612     V_VT(&index) = VT_I4;
3613     V_I4(&index) = 1;
3614     disp2 = NULL;
3615     hres = IHTMLSelectElement_item(select, name, index, &disp2);
3616     ok(hres == S_OK, "item failed: %08x\n", hres);
3617     ok(disp2 != NULL, "disp = NULL\n");
3618     ok(iface_cmp((IUnknown*)disp, (IUnknown*)disp2), "disp != disp2\n");
3619     IDispatch_Release(disp2);
3620     IDispatch_Release(disp);
3621 }
3622
3623 static void test_form_item(IHTMLElement *elem)
3624 {
3625     IHTMLFormElement *form = get_form_iface((IUnknown*)elem);
3626     IDispatch *disp, *disp2;
3627     VARIANT name, index;
3628     HRESULT hres;
3629
3630     V_VT(&index) = VT_EMPTY;
3631     V_VT(&name) = VT_I4;
3632     V_I4(&name) = -1;
3633     disp = (void*)0xdeadbeef;
3634     hres = IHTMLFormElement_item(form, name, index, &disp);
3635     ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
3636     ok(!disp, "disp = %p\n", disp);
3637
3638     V_I4(&name) = 2;
3639     disp = (void*)0xdeadbeef;
3640     hres = IHTMLFormElement_item(form, name, index, &disp);
3641     ok(hres == S_OK, "item failed: %08x\n", hres);
3642     ok(!disp, "disp = %p\n", disp);
3643
3644     V_I4(&name) = 1;
3645     hres = IHTMLFormElement_item(form, name, index, NULL);
3646     ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
3647
3648     disp = NULL;
3649     hres = IHTMLFormElement_item(form, name, index, &disp);
3650     ok(hres == S_OK, "item failed: %08x\n", hres);
3651     ok(disp != NULL, "disp = NULL\n");
3652     test_disp((IUnknown*)disp, &DIID_DispHTMLInputElement, NULL);
3653
3654     V_VT(&index) = VT_I4;
3655     V_I4(&index) = 1;
3656     disp2 = NULL;
3657     hres = IHTMLFormElement_item(form, name, index, &disp2);
3658     ok(hres == S_OK, "item failed: %08x\n", hres);
3659     ok(disp2 != NULL, "disp = NULL\n");
3660     ok(iface_cmp((IUnknown*)disp, (IUnknown*)disp2), "disp != disp2\n");
3661     IDispatch_Release(disp2);
3662     IDispatch_Release(disp);
3663 }
3664
3665 static void test_create_option_elem(IHTMLDocument2 *doc)
3666 {
3667     IHTMLOptionElement *option;
3668
3669     option = create_option_elem(doc, "test text", "test value");
3670
3671     test_option_put_text(option, "new text");
3672     test_option_put_value(option, "new value");
3673     test_option_put_selected(option, VARIANT_TRUE);
3674     test_option_put_selected(option, VARIANT_FALSE);
3675
3676     IHTMLOptionElement_Release(option);
3677 }
3678
3679 static void test_create_img_elem(IHTMLDocument2 *doc)
3680 {
3681     IHTMLImgElement *img;
3682
3683     img = create_img_elem(doc, 10, 15);
3684
3685     if(img){
3686         test_img_put_width(img, 5);
3687         test_img_put_height(img, 20);
3688
3689         IHTMLImgElement_Release(img);
3690         img = NULL;
3691     }
3692
3693     img = create_img_elem(doc, -1, -1);
3694
3695     if(img){
3696         test_img_put_width(img, 5);
3697         test_img_put_height(img, 20);
3698
3699         IHTMLImgElement_Release(img);
3700     }
3701 }
3702
3703 static IHTMLTxtRange *test_create_body_range(IHTMLDocument2 *doc)
3704 {
3705     IHTMLBodyElement *body;
3706     IHTMLTxtRange *range;
3707     IHTMLElement *elem;
3708     HRESULT hres;
3709
3710     elem = doc_get_body(doc);
3711     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLBodyElement, (void**)&body);
3712     ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
3713     IHTMLElement_Release(elem);
3714
3715     hres = IHTMLBodyElement_createTextRange(body, &range);
3716     IHTMLBodyElement_Release(body);
3717     ok(hres == S_OK, "createTextRange failed: %08x\n", hres);
3718
3719     return range;
3720 }
3721
3722 static void test_txtrange(IHTMLDocument2 *doc)
3723 {
3724     IHTMLTxtRange *body_range, *range, *range2;
3725     IHTMLSelectionObject *selection;
3726     IDispatch *disp_range;
3727     HRESULT hres;
3728
3729     body_range = test_create_body_range(doc);
3730
3731     test_range_text(body_range, "test abc 123\r\nit's text");
3732
3733     hres = IHTMLTxtRange_duplicate(body_range, &range);
3734     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
3735
3736     hres = IHTMLTxtRange_duplicate(body_range, &range2);
3737     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
3738     test_range_isequal(range, range2, VARIANT_TRUE);
3739
3740     test_range_text(range, "test abc 123\r\nit's text");
3741     test_range_text(body_range, "test abc 123\r\nit's text");
3742
3743     test_range_collapse(range, TRUE);
3744     test_range_isequal(range, range2, VARIANT_FALSE);
3745     test_range_inrange(range, range2, VARIANT_FALSE);
3746     test_range_inrange(range2, range, VARIANT_TRUE);
3747     IHTMLTxtRange_Release(range2);
3748
3749     test_range_expand(range, wordW, VARIANT_TRUE, "test ");
3750     test_range_expand(range, wordW, VARIANT_FALSE, "test ");
3751     test_range_move(range, characterW, 2, 2);
3752     test_range_expand(range, wordW, VARIANT_TRUE, "test ");
3753
3754     test_range_collapse(range, FALSE);
3755     test_range_expand(range, wordW, VARIANT_TRUE, "abc ");
3756
3757     test_range_collapse(range, FALSE);
3758     test_range_expand(range, wordW, VARIANT_TRUE, "123");
3759     test_range_expand(range, wordW, VARIANT_FALSE, "123");
3760     test_range_move(range, characterW, 2, 2);
3761     test_range_expand(range, wordW, VARIANT_TRUE, "123");
3762     test_range_moveend(range, characterW, -5, -5);
3763     test_range_text(range, NULL);
3764     test_range_moveend(range, characterW, 3, 3);
3765     test_range_text(range, "c 1");
3766     test_range_expand(range, texteditW, VARIANT_TRUE, "test abc 123\r\nit's text");
3767     test_range_collapse(range, TRUE);
3768     test_range_move(range, characterW, 4, 4);
3769     test_range_moveend(range, characterW, 1, 1);
3770     test_range_text(range, " ");
3771     test_range_move(range, wordW, 1, 1);
3772     test_range_moveend(range, characterW, 2, 2);
3773     test_range_text(range, "ab");
3774
3775     IHTMLTxtRange_Release(range);
3776
3777     hres = IHTMLTxtRange_duplicate(body_range, &range);
3778     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
3779
3780     test_range_text(range, "test abc 123\r\nit's text");
3781     test_range_move(range, characterW, 3, 3);
3782     test_range_moveend(range, characterW, 1, 1);
3783     test_range_text(range, "t");
3784     test_range_moveend(range, characterW, 3, 3);
3785     test_range_text(range, "t ab");
3786     test_range_moveend(range, characterW, -2, -2);
3787     test_range_text(range, "t ");
3788     test_range_move(range, characterW, 6, 6);
3789     test_range_moveend(range, characterW, 3, 3);
3790     test_range_text(range, "123");
3791     test_range_moveend(range, characterW, 2, 2);
3792     test_range_text(range, "123\r\ni");
3793
3794     IHTMLTxtRange_Release(range);
3795
3796     hres = IHTMLTxtRange_duplicate(body_range, &range);
3797     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
3798
3799     test_range_move(range, wordW, 1, 1);
3800     test_range_moveend(range, characterW, 2, 2);
3801     test_range_text(range, "ab");
3802
3803     test_range_move(range, characterW, -2, -2);
3804     test_range_moveend(range, characterW, 2, 2);
3805     test_range_text(range, "t ");
3806
3807     test_range_move(range, wordW, 3, 3);
3808     test_range_move(range, wordW, -2, -2);
3809     test_range_moveend(range, characterW, 2, 2);
3810     test_range_text(range, "ab");
3811
3812     test_range_move(range, characterW, -6, -5);
3813     test_range_moveend(range, characterW, -1, 0);
3814     test_range_moveend(range, characterW, -6, 0);
3815     test_range_move(range, characterW, 2, 2);
3816     test_range_moveend(range, characterW, 2, 2);
3817     test_range_text(range, "st");
3818     test_range_moveend(range, characterW, -6, -4);
3819     test_range_moveend(range, characterW, 2, 2);
3820
3821     IHTMLTxtRange_Release(range);
3822
3823     hres = IHTMLTxtRange_duplicate(body_range, &range);
3824     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
3825
3826     test_range_move(range, wordW, 2, 2);
3827     test_range_moveend(range, characterW, 2, 2);
3828     test_range_text(range, "12");
3829
3830     test_range_move(range, characterW, 15, 14);
3831     test_range_move(range, characterW, -2, -2);
3832     test_range_moveend(range, characterW, 3, 2);
3833     test_range_text(range, "t");
3834     test_range_moveend(range, characterW, -1, -1);
3835     test_range_text(range, "t");
3836     test_range_expand(range, wordW, VARIANT_TRUE, "text");
3837     test_range_move(range, characterW, -2, -2);
3838     test_range_moveend(range, characterW, 2, 2);
3839     test_range_text(range, "s ");
3840     test_range_move(range, characterW, 100, 7);
3841     test_range_move(range, wordW, 1, 0);
3842     test_range_move(range, characterW, -2, -2);
3843     test_range_moveend(range, characterW, 3, 2);
3844     test_range_text(range, "t");
3845
3846     IHTMLTxtRange_Release(range);
3847
3848     hres = IHTMLTxtRange_duplicate(body_range, &range);
3849     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
3850
3851     test_range_collapse(range, TRUE);
3852     test_range_expand(range, wordW, VARIANT_TRUE, "test ");
3853     test_range_put_text(range, "word");
3854     test_range_text(body_range, "wordabc 123\r\nit's text");
3855     test_range_text(range, NULL);
3856     test_range_moveend(range, characterW, 3, 3);
3857     test_range_text(range, "abc");
3858     test_range_movestart(range, characterW, -2, -2);
3859     test_range_text(range, "rdabc");
3860     test_range_movestart(range, characterW, 3, 3);
3861     test_range_text(range, "bc");
3862     test_range_movestart(range, characterW, 4, 4);
3863     test_range_text(range, NULL);
3864     test_range_movestart(range, characterW, -3, -3);
3865     test_range_text(range, "c 1");
3866     test_range_movestart(range, characterW, -7, -6);
3867     test_range_text(range, "wordabc 1");
3868     test_range_movestart(range, characterW, 100, 22);
3869     test_range_text(range, NULL);
3870
3871     IHTMLTxtRange_Release(range);
3872     IHTMLTxtRange_Release(body_range);
3873
3874     hres = IHTMLDocument2_get_selection(doc, &selection);
3875     ok(hres == S_OK, "IHTMLDocument2_get_selection failed: %08x\n", hres);
3876
3877     hres = IHTMLSelectionObject_createRange(selection, &disp_range);
3878     ok(hres == S_OK, "IHTMLSelectionObject_createRange failed: %08x\n", hres);
3879     IHTMLSelectionObject_Release(selection);
3880
3881     hres = IDispatch_QueryInterface(disp_range, &IID_IHTMLTxtRange, (void **)&range);
3882     ok(hres == S_OK, "Could not get IID_IHTMLTxtRange interface: 0x%08x\n", hres);
3883     IDispatch_Release(disp_range);
3884
3885     test_range_text(range, NULL);
3886     test_range_moveend(range, characterW, 3, 3);
3887     test_range_text(range, "wor");
3888     test_range_parent(range, ET_BODY);
3889     test_range_expand(range, texteditW, VARIANT_TRUE, "wordabc 123\r\nit's text");
3890     test_range_expand(range, texteditW, VARIANT_TRUE, "wordabc 123\r\nit's text");
3891     test_range_move(range, characterW, 3, 3);
3892     test_range_expand(range, wordW, VARIANT_TRUE, "wordabc ");
3893     test_range_moveend(range, characterW, -4, -4);
3894     test_range_put_text(range, "abc def ");
3895     test_range_expand(range, texteditW, VARIANT_TRUE, "abc def abc 123\r\nit's text");
3896     test_range_move(range, wordW, 1, 1);
3897     test_range_movestart(range, characterW, -1, -1);
3898     test_range_text(range, " ");
3899     test_range_move(range, wordW, 1, 1);
3900     test_range_moveend(range, characterW, 3, 3);
3901     test_range_text(range, "def");
3902     test_range_put_text(range, "xyz");
3903     test_range_moveend(range, characterW, 1, 1);
3904     test_range_move(range, wordW, 1, 1);
3905     test_range_moveend(range, characterW, 2, 2);
3906     test_range_text(range, "ab");
3907
3908     IHTMLTxtRange_Release(range);
3909 }
3910
3911 static void test_txtrange2(IHTMLDocument2 *doc)
3912 {
3913     IHTMLTxtRange *range;
3914
3915     range = test_create_body_range(doc);
3916
3917     test_range_text(range, "abc\r\n\r\n123\r\n\r\n\r\ndef");
3918     test_range_move(range, characterW, 5, 5);
3919     test_range_moveend(range, characterW, 1, 1);
3920     test_range_text(range, "2");
3921     test_range_move(range, characterW, -3, -3);
3922     test_range_moveend(range, characterW, 3, 3);
3923     test_range_text(range, "c\r\n\r\n1");
3924     test_range_collapse(range, VARIANT_FALSE);
3925     test_range_moveend(range, characterW, 4, 4);
3926     test_range_text(range, "23");
3927     test_range_moveend(range, characterW, 1, 1);
3928     test_range_text(range, "23\r\n\r\n\r\nd");
3929     test_range_moveend(range, characterW, -1, -1);
3930     test_range_text(range, "23");
3931     test_range_moveend(range, characterW, -1, -1);
3932     test_range_text(range, "23");
3933     test_range_moveend(range, characterW, -2, -2);
3934     test_range_text(range, "2");
3935
3936     IHTMLTxtRange_Release(range);
3937 }
3938
3939 static void test_compatmode(IHTMLDocument2 *doc)
3940 {
3941     IHTMLDocument5 *doc5;
3942     BSTR mode;
3943     HRESULT hres;
3944
3945     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5);
3946     ok(hres == S_OK, "Could not get IHTMLDocument5 interface: %08x\n", hres);
3947     if(FAILED(hres))
3948         return;
3949
3950     hres = IHTMLDocument5_get_compatMode(doc5, &mode);
3951     IHTMLDocument5_Release(doc5);
3952     ok(hres == S_OK, "get_compatMode failed: %08x\n", hres);
3953     ok(!strcmp_wa(mode, "BackCompat"), "compatMode=%s\n", wine_dbgstr_w(mode));
3954     SysFreeString(mode);
3955 }
3956
3957 static void test_location(IHTMLDocument2 *doc)
3958 {
3959     IHTMLLocation *location, *location2;
3960     IHTMLWindow2 *window;
3961     BSTR str;
3962     ULONG ref;
3963     HRESULT hres;
3964
3965     hres = IHTMLDocument2_get_location(doc, &location);
3966     ok(hres == S_OK, "get_location failed: %08x\n", hres);
3967
3968     hres = IHTMLDocument2_get_location(doc, &location2);
3969     ok(hres == S_OK, "get_location failed: %08x\n", hres);
3970
3971     ok(location == location2, "location != location2\n");
3972     IHTMLLocation_Release(location2);
3973
3974     hres = IHTMLDocument2_get_parentWindow(doc, &window);
3975     ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres);
3976
3977     hres = IHTMLWindow2_get_location(window, &location2);
3978     ok(hres == S_OK, "get_location failed: %08x\n", hres);
3979     ok(location == location2, "location != location2\n");
3980     IHTMLLocation_Release(location2);
3981
3982     test_ifaces((IUnknown*)location, location_iids);
3983     test_disp2((IUnknown*)location, &DIID_DispHTMLLocation, &IID_IHTMLLocation, "about:blank");
3984
3985     hres = IHTMLLocation_get_pathname(location, &str);
3986     ok(hres == S_OK, "get_pathname failed: %08x\n", hres);
3987     ok(!strcmp_wa(str, "blank"), "unexpected pathname %s\n", wine_dbgstr_w(str));
3988     SysFreeString(str);
3989
3990     hres = IHTMLLocation_get_href(location, NULL);
3991     ok(hres == E_POINTER, "get_href passed: %08x\n", hres);
3992
3993     hres = IHTMLLocation_get_href(location, &str);
3994     ok(hres == S_OK, "get_href failed: %08x\n", hres);
3995     ok(!strcmp_wa(str, "about:blank"), "unexpected href %s\n", wine_dbgstr_w(str));
3996     SysFreeString(str);
3997
3998     ref = IHTMLLocation_Release(location);
3999     ok(!ref, "location chould be destroyed here\n");
4000 }
4001
4002 static void test_plugins_col(IHTMLDocument2 *doc)
4003 {
4004     IHTMLPluginsCollection *col, *col2;
4005     IHTMLWindow2 *window;
4006     IOmNavigator *nav;
4007     ULONG ref;
4008     LONG len;
4009     HRESULT hres;
4010
4011     window = get_doc_window(doc);
4012     hres = IHTMLWindow2_get_navigator(window, &nav);
4013     IHTMLWindow2_Release(window);
4014
4015     hres = IOmNavigator_get_plugins(nav, &col);
4016     ok(hres == S_OK, "get_plugins failed: %08x\n", hres);
4017
4018     hres = IOmNavigator_get_plugins(nav, &col2);
4019     ok(hres == S_OK, "get_plugins failed: %08x\n", hres);
4020     ok(iface_cmp((IUnknown*)col, (IUnknown*)col2), "col != col2\n");
4021     IHTMLPluginsCollection_Release(col2);
4022
4023     test_disp2((IUnknown*)col, &DIID_DispCPlugins, &IID_IHTMLPluginsCollection, "[object]");
4024
4025     len = 0xdeadbeef;
4026     hres = IHTMLPluginsCollection_get_length(col, &len);
4027     ok(hres == S_OK, "get_length failed: %08x\n", hres);
4028     ok(!len, "length = %d\n", len);
4029
4030     ref = IHTMLPluginsCollection_Release(col);
4031     ok(!ref, "ref=%d\n", ref);
4032
4033     IOmNavigator_Release(nav);
4034 }
4035
4036 static void test_mime_types_col(IOmNavigator *nav)
4037 {
4038     IHTMLMimeTypesCollection *col, *col2;
4039     LONG length;
4040     ULONG ref;
4041     HRESULT hres;
4042
4043     hres = IOmNavigator_get_mimeTypes(nav, &col);
4044     ok(hres == S_OK, "get_mimeTypes failed: %08x\n", hres);
4045
4046     hres = IOmNavigator_get_mimeTypes(nav, &col2);
4047     ok(hres == S_OK, "get_mimeTypes failed: %08x\n", hres);
4048     ok(iface_cmp((IUnknown*)col, (IUnknown*)col2), "col != col2\n");
4049     IHTMLMimeTypesCollection_Release(col2);
4050
4051     test_disp((IUnknown*)col, &IID_IHTMLMimeTypesCollection, "[object]");
4052
4053     length = 0xdeadbeef;
4054     hres = IHTMLMimeTypesCollection_get_length(col, &length);
4055     ok(hres == S_OK, "get_length failed: %08x\n", hres);
4056     ok(!length, "length = %d\n", length);
4057
4058     ref = IHTMLMimeTypesCollection_Release(col);
4059     ok(!ref, "ref=%d\n", ref);
4060 }
4061
4062 #define test_language_string(a,b) _test_language_string(__LINE__,a,b)
4063 static void _test_language_string(unsigned line, const WCHAR *lang, LCID lcid)
4064 {
4065     WCHAR buf[64];
4066     int res;
4067
4068     if(pLCIDToLocaleName) {
4069         res = pLCIDToLocaleName(lcid, buf, sizeof(buf)/sizeof(WCHAR), 0);
4070         ok_(__FILE__,line)(res, "LCIDToLocaleName failed: %u\n", GetLastError());
4071         ok_(__FILE__,line)(!lstrcmpW(lang, buf), "lang = %s, expected %s\n", wine_dbgstr_w(lang), wine_dbgstr_w(buf));
4072     }else {
4073         win_skip("LCIDToLocaleName not available, unable to test language string\n");
4074         ok_(__FILE__,line)(lang != NULL, "lang == NULL\n");
4075     }
4076 }
4077
4078 static void test_navigator(IHTMLDocument2 *doc)
4079 {
4080     IHTMLWindow2 *window;
4081     IOmNavigator *navigator, *navigator2;
4082     char buf[512];
4083     DWORD size;
4084     ULONG ref;
4085     BSTR bstr;
4086     HRESULT hres;
4087
4088     static const WCHAR v40[] = {'4','.','0'};
4089
4090     hres = IHTMLDocument2_get_parentWindow(doc, &window);
4091     ok(hres == S_OK, "parentWidnow failed: %08x\n", hres);
4092
4093     hres = IHTMLWindow2_get_navigator(window, &navigator);
4094     ok(hres == S_OK, "get_navigator failed: %08x\n", hres);
4095     ok(navigator != NULL, "navigator == NULL\n");
4096     test_disp2((IUnknown*)navigator, &DIID_DispHTMLNavigator, &IID_IOmNavigator, "[object]");
4097
4098     hres = IHTMLWindow2_get_navigator(window, &navigator2);
4099     ok(hres == S_OK, "get_navigator failed: %08x\n", hres);
4100     ok(navigator != navigator2, "navigator2 != navihgator\n");
4101
4102     IHTMLWindow2_Release(window);
4103     IOmNavigator_Release(navigator2);
4104
4105     hres = IOmNavigator_get_appCodeName(navigator, &bstr);
4106     ok(hres == S_OK, "get_appCodeName failed: %08x\n", hres);
4107     ok(!strcmp_wa(bstr, "Mozilla"), "Unexpected appCodeName %s\n", wine_dbgstr_w(bstr));
4108     SysFreeString(bstr);
4109
4110     bstr = NULL;
4111     hres = IOmNavigator_get_appName(navigator, &bstr);
4112     ok(hres == S_OK, "get_appName failed: %08x\n", hres);
4113     ok(!strcmp_wa(bstr, "Microsoft Internet Explorer"), "Unexpected appCodeName %s\n", wine_dbgstr_w(bstr));
4114     SysFreeString(bstr);
4115
4116     bstr = NULL;
4117     hres = IOmNavigator_get_platform(navigator, &bstr);
4118     ok(hres == S_OK, "get_platform failed: %08x\n", hres);
4119     ok(!strcmp_wa(bstr, sizeof(void*) == 8 ? "Win64" : "Win32")
4120        || (sizeof(void*) == 8 && broken(!strcmp_wa(bstr, "Win32") /* IE6 */)), "unexpected platform %s\n", wine_dbgstr_w(bstr));
4121     SysFreeString(bstr);
4122
4123     bstr = NULL;
4124     hres = IOmNavigator_get_cpuClass(navigator, &bstr);
4125     ok(hres == S_OK, "get_cpuClass failed: %08x\n", hres);
4126     ok(!strcmp_wa(bstr, sizeof(void*) == 8 ? "x64" : "x86"), "unexpected cpuClass %s\n", wine_dbgstr_w(bstr));
4127     SysFreeString(bstr);
4128
4129     bstr = NULL;
4130     hres = IOmNavigator_get_appVersion(navigator, &bstr);
4131     ok(hres == S_OK, "get_appVersion failed: %08x\n", hres);
4132     ok(!memcmp(bstr, v40, sizeof(v40)), "appVersion is %s\n", wine_dbgstr_w(bstr));
4133     SysFreeString(bstr);
4134
4135     bstr = NULL;
4136     hres = IOmNavigator_get_systemLanguage(navigator, &bstr);
4137     ok(hres == S_OK, "get_systemLanguage failed: %08x\n", hres);
4138     test_language_string(bstr, LOCALE_SYSTEM_DEFAULT);
4139     SysFreeString(bstr);
4140
4141     if (pGetUserDefaultUILanguage)
4142     {
4143         bstr = NULL;
4144         hres = IOmNavigator_get_browserLanguage(navigator, &bstr);
4145         ok(hres == S_OK, "get_browserLanguage failed: %08x\n", hres);
4146         test_language_string(bstr, pGetUserDefaultUILanguage());
4147         SysFreeString(bstr);
4148     }
4149     else
4150         win_skip("GetUserDefaultUILanguage not available\n");
4151
4152     bstr = NULL;
4153     hres = IOmNavigator_get_userLanguage(navigator, &bstr);
4154     ok(hres == S_OK, "get_userLanguage failed: %08x\n", hres);
4155     test_language_string(bstr, LOCALE_USER_DEFAULT);
4156     SysFreeString(bstr);
4157
4158     hres = IOmNavigator_toString(navigator, NULL);
4159     ok(hres == E_INVALIDARG, "toString failed: %08x\n", hres);
4160
4161     bstr = NULL;
4162     hres = IOmNavigator_toString(navigator, &bstr);
4163     ok(hres == S_OK, "toString failed: %08x\n", hres);
4164     ok(!strcmp_wa(bstr, "[object]"), "toString returned %s\n", wine_dbgstr_w(bstr));
4165     SysFreeString(bstr);
4166
4167     size = sizeof(buf);
4168     hres = ObtainUserAgentString(0, buf, &size);
4169     ok(hres == S_OK, "ObtainUserAgentString failed: %08x\n", hres);
4170
4171     bstr = NULL;
4172     hres = IOmNavigator_get_userAgent(navigator, &bstr);
4173     ok(hres == S_OK, "get_userAgent failed: %08x\n", hres);
4174     ok(!strcmp_wa(bstr, buf), "userAgent returned %s, expected \"%s\"\n", wine_dbgstr_w(bstr), buf);
4175     SysFreeString(bstr);
4176
4177     if(!strncmp(buf, "Mozilla/", 8)) {
4178         bstr = NULL;
4179         hres = IOmNavigator_get_appVersion(navigator, &bstr);
4180         ok(hres == S_OK, "get_appVersion failed: %08x\n", hres);
4181         ok(!strcmp_wa(bstr, buf+8), "appVersion returned %s, expected \"%s\"\n", wine_dbgstr_w(bstr), buf+8);
4182         SysFreeString(bstr);
4183     }else {
4184         skip("nonstandard user agent\n");
4185     }
4186
4187     bstr = NULL;
4188     hres = IOmNavigator_get_appMinorVersion(navigator, &bstr);
4189     ok(hres == S_OK, "get_appMonorVersion failed: %08x\n", hres);
4190     ok(bstr != NULL, "appMinorVersion returned NULL\n");
4191     SysFreeString(bstr);
4192
4193     test_mime_types_col(navigator);
4194
4195     ref = IOmNavigator_Release(navigator);
4196     ok(!ref, "navigator should be destroyed here\n");
4197 }
4198
4199 static void test_screen(IHTMLWindow2 *window)
4200 {
4201     IHTMLScreen *screen, *screen2;
4202     IDispatchEx *dispex;
4203     RECT work_area;
4204     LONG l, exl;
4205     HDC hdc;
4206     HRESULT hres;
4207
4208     screen = NULL;
4209     hres = IHTMLWindow2_get_screen(window, &screen);
4210     ok(hres == S_OK, "get_screen failed: %08x\n", hres);
4211     ok(screen != NULL, "screen == NULL\n");
4212
4213     screen2 = NULL;
4214     hres = IHTMLWindow2_get_screen(window, &screen2);
4215     ok(hres == S_OK, "get_screen failed: %08x\n", hres);
4216     ok(screen2 != NULL, "screen == NULL\n");
4217     ok(iface_cmp((IUnknown*)screen2, (IUnknown*)screen), "screen2 != screen\n");
4218     IHTMLScreen_Release(screen2);
4219
4220     hres = IHTMLScreen_QueryInterface(screen, &IID_IDispatchEx, (void**)&dispex);
4221     ok(hres == S_OK || broken(hres == E_NOINTERFACE), "Could not get IDispatchEx interface: %08x\n", hres);
4222     if(SUCCEEDED(hres)) {
4223         test_disp((IUnknown*)screen, &DIID_DispHTMLScreen, "[object]");
4224         IDispatchEx_Release(dispex);
4225     }
4226
4227     hdc = CreateICA("DISPLAY", NULL, NULL, NULL);
4228
4229     exl = GetDeviceCaps(hdc, HORZRES);
4230     l = 0xdeadbeef;
4231     hres = IHTMLScreen_get_width(screen, &l);
4232     ok(hres == S_OK, "get_width failed: %08x\n", hres);
4233     ok(l == exl, "width = %d, expected %d\n", l, exl);
4234
4235     exl = GetDeviceCaps(hdc, VERTRES);
4236     l = 0xdeadbeef;
4237     hres = IHTMLScreen_get_height(screen, &l);
4238     ok(hres == S_OK, "get_height failed: %08x\n", hres);
4239     ok(l == exl, "height = %d, expected %d\n", l, exl);
4240
4241     exl = GetDeviceCaps(hdc, BITSPIXEL);
4242     l = 0xdeadbeef;
4243     hres = IHTMLScreen_get_colorDepth(screen, &l);
4244     ok(hres == S_OK, "get_height failed: %08x\n", hres);
4245     ok(l == exl, "height = %d, expected %d\n", l, exl);
4246
4247     DeleteObject(hdc);
4248
4249     SystemParametersInfoW(SPI_GETWORKAREA, 0, &work_area, 0);
4250
4251     l = 0xdeadbeef;
4252     hres = IHTMLScreen_get_availHeight(screen, &l);
4253     ok(hres == S_OK, "get_availHeight failed: %08x\n", hres);
4254     ok(l == work_area.bottom-work_area.top, "availHeight = %d, expected %d\n", l, work_area.bottom-work_area.top);
4255
4256     l = 0xdeadbeef;
4257     hres = IHTMLScreen_get_availWidth(screen, &l);
4258     ok(hres == S_OK, "get_availWidth failed: %08x\n", hres);
4259     ok(l == work_area.right-work_area.left, "availWidth = %d, expected %d\n", l, work_area.right-work_area.left);
4260
4261     IHTMLScreen_Release(screen);
4262 }
4263
4264 static void test_default_selection(IHTMLDocument2 *doc)
4265 {
4266     IHTMLSelectionObject *selection;
4267     IHTMLTxtRange *range;
4268     IDispatch *disp;
4269     BSTR str;
4270     HRESULT hres;
4271
4272     hres = IHTMLDocument2_get_selection(doc, &selection);
4273     ok(hres == S_OK, "get_selection failed: %08x\n", hres);
4274
4275     hres = IHTMLSelectionObject_get_type(selection, &str);
4276     ok(hres == S_OK, "get_type failed: %08x\n", hres);
4277     ok(!strcmp_wa(str, "None"), "type = %s\n", wine_dbgstr_w(str));
4278     SysFreeString(str);
4279
4280     hres = IHTMLSelectionObject_createRange(selection, &disp);
4281     IHTMLSelectionObject_Release(selection);
4282     ok(hres == S_OK, "createRange failed: %08x\n", hres);
4283
4284     hres = IDispatch_QueryInterface(disp, &IID_IHTMLTxtRange, (void**)&range);
4285     IDispatch_Release(disp);
4286     ok(hres == S_OK, "Could not get IHTMLTxtRange interface: %08x\n", hres);
4287
4288     test_range_text(range, NULL);
4289     IHTMLTxtRange_Release(range);
4290 }
4291
4292 static void test_doc_elem(IHTMLDocument2 *doc)
4293 {
4294     IHTMLDocument2 *doc_node, *owner_doc;
4295     IHTMLElement *elem;
4296     IHTMLDocument3 *doc3;
4297     HRESULT hres;
4298
4299     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
4300     ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08x\n", hres);
4301
4302     hres = IHTMLDocument3_get_documentElement(doc3, &elem);
4303     IHTMLDocument3_Release(doc3);
4304     ok(hres == S_OK, "get_documentElement failed: %08x\n", hres);
4305
4306     test_node_name((IUnknown*)elem, "HTML");
4307     test_elem_tag((IUnknown*)elem, "HTML");
4308
4309     doc_node = get_doc_node(doc);
4310     owner_doc = get_owner_doc((IUnknown*)elem);
4311     ok(iface_cmp((IUnknown *)doc_node, (IUnknown *)owner_doc), "doc_node != owner_doc\n");
4312     IHTMLDocument2_Release(owner_doc);
4313
4314     owner_doc = get_owner_doc((IUnknown*)doc_node);
4315     ok(!owner_doc, "owner_doc = %p\n", owner_doc);
4316     IHTMLDocument2_Release(doc_node);
4317
4318     test_elem_client_rect((IUnknown*)elem);
4319
4320     IHTMLElement_Release(elem);
4321 }
4322
4323 static void test_default_body(IHTMLBodyElement *body)
4324 {
4325     LONG l;
4326     BSTR bstr;
4327     HRESULT hres;
4328     VARIANT v;
4329
4330     bstr = (void*)0xdeadbeef;
4331     hres = IHTMLBodyElement_get_background(body, &bstr);
4332     ok(hres == S_OK, "get_background failed: %08x\n", hres);
4333     ok(bstr == NULL, "bstr != NULL\n");
4334
4335     l = elem_get_scroll_height((IUnknown*)body);
4336     ok(l != -1, "scrollHeight == -1\n");
4337     l = elem_get_scroll_width((IUnknown*)body);
4338     ok(l != -1, "scrollWidth == -1\n");
4339     l = elem_get_scroll_top((IUnknown*)body);
4340     ok(!l, "scrollTop = %d\n", l);
4341     elem_get_scroll_left((IUnknown*)body);
4342
4343     /* get_text tests */
4344     hres = IHTMLBodyElement_get_text(body, &v);
4345     ok(hres == S_OK, "expect S_OK got 0x%08d\n", hres);
4346     ok(V_VT(&v) == VT_BSTR, "Expected VT_BSTR got %d\n", V_VT(&v));
4347     ok(bstr == NULL, "bstr != NULL\n");
4348
4349     /* get_text - Invalid Text */
4350     V_VT(&v) = VT_BSTR;
4351     V_BSTR(&v) = a2bstr("Invalid");
4352     hres = IHTMLBodyElement_put_text(body, v);
4353     ok(hres == S_OK, "expect S_OK got 0x%08d\n", hres);
4354     VariantClear(&v);
4355
4356     V_VT(&v) = VT_NULL;
4357     hres = IHTMLBodyElement_get_text(body, &v);
4358     ok(hres == S_OK, "expect S_OK got 0x%08d\n", hres);
4359     ok(V_VT(&v) == VT_BSTR, "Expected VT_BSTR got %d\n", V_VT(&v));
4360     ok(!strcmp_wa(V_BSTR(&v), "#00a0d0"), "v = %s, expected '#00a0d0'\n", wine_dbgstr_w(V_BSTR(&v)));
4361     VariantClear(&v);
4362
4363     /* get_text - Valid Text */
4364     V_VT(&v) = VT_BSTR;
4365     V_BSTR(&v) = a2bstr("#FF0000");
4366     hres = IHTMLBodyElement_put_text(body, v);
4367     ok(hres == S_OK, "expect S_OK got 0x%08d\n", hres);
4368     VariantClear(&v);
4369
4370     V_VT(&v) = VT_NULL;
4371     hres = IHTMLBodyElement_get_text(body, &v);
4372     ok(hres == S_OK, "expect S_OK got 0x%08d\n", hres);
4373     ok(V_VT(&v) == VT_BSTR, "Expected VT_BSTR got %d\n", V_VT(&v));
4374     ok(!strcmp_wa(V_BSTR(&v), "#ff0000"), "v = %s, expected '#ff0000'\n", wine_dbgstr_w(V_BSTR(&v)));
4375     VariantClear(&v);
4376 }
4377
4378 static void test_body_funs(IHTMLBodyElement *body)
4379 {
4380     VARIANT vbg, vDefaultbg;
4381     HRESULT hres;
4382
4383     hres = IHTMLBodyElement_get_bgColor(body, &vDefaultbg);
4384     ok(hres == S_OK, "get_bgColor failed: %08x\n", hres);
4385     ok(V_VT(&vDefaultbg) == VT_BSTR, "bstr != NULL\n");
4386     ok(!V_BSTR(&vDefaultbg), "V_BSTR(bgColor) = %s\n", wine_dbgstr_w(V_BSTR(&vDefaultbg)));
4387
4388     V_VT(&vbg) = VT_BSTR;
4389     V_BSTR(&vbg) = a2bstr("red");
4390     hres = IHTMLBodyElement_put_bgColor(body, vbg);
4391     ok(hres == S_OK, "put_bgColor failed: %08x\n", hres);
4392     VariantClear(&vbg);
4393
4394     hres = IHTMLBodyElement_get_bgColor(body, &vbg);
4395     ok(hres == S_OK, "get_bgColor failed: %08x\n", hres);
4396     ok(V_VT(&vDefaultbg) == VT_BSTR, "V_VT(&vDefaultbg) != VT_BSTR\n");
4397     ok(!strcmp_wa(V_BSTR(&vbg), "#ff0000"), "Unexpected bgcolor %s\n", wine_dbgstr_w(V_BSTR(&vbg)));
4398     VariantClear(&vbg);
4399
4400     /* Restore Originial */
4401     hres = IHTMLBodyElement_put_bgColor(body, vDefaultbg);
4402     ok(hres == S_OK, "put_bgColor failed: %08x\n", hres);
4403     VariantClear(&vDefaultbg);
4404 }
4405
4406 static void test_window(IHTMLDocument2 *doc)
4407 {
4408     IHTMLWindow2 *window, *window2, *self;
4409     IHTMLDocument2 *doc2 = NULL;
4410     IDispatch *disp;
4411     IUnknown *unk;
4412     BSTR str;
4413     HRESULT hres;
4414
4415     hres = IHTMLDocument2_get_parentWindow(doc, &window);
4416     ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres);
4417     test_ifaces((IUnknown*)window, window_iids);
4418     test_disp((IUnknown*)window, &DIID_DispHTMLWindow2, "[object]");
4419
4420     hres = IHTMLWindow2_get_document(window, &doc2);
4421     ok(hres == S_OK, "get_document failed: %08x\n", hres);
4422     ok(doc2 != NULL, "doc2 == NULL\n");
4423
4424     test_ifaces((IUnknown*)doc2, doc_node_iids);
4425     test_disp((IUnknown*)doc2, &DIID_DispHTMLDocument, "[object]");
4426     test_class_info((IUnknown*)doc2);
4427
4428     test_ifaces((IUnknown*)doc, doc_obj_iids);
4429     test_disp((IUnknown*)doc, &DIID_DispHTMLDocument, "[object]");
4430     test_class_info((IUnknown*)doc);
4431
4432     unk = (void*)0xdeadbeef;
4433     hres = IHTMLDocument2_QueryInterface(doc2, &IID_ICustomDoc, (void**)&unk);
4434     ok(hres == E_NOINTERFACE, "QueryInterface(IID_ICustomDoc) returned: %08x\n", hres);
4435     ok(!unk, "unk = %p\n", unk);
4436
4437     IHTMLDocument_Release(doc2);
4438
4439     hres = IHTMLWindow2_get_window(window, &window2);
4440     ok(hres == S_OK, "get_window failed: %08x\n", hres);
4441     ok(window2 != NULL, "window2 == NULL\n");
4442
4443     hres = IHTMLWindow2_get_self(window, &self);
4444     ok(hres == S_OK, "get_self failed: %08x\n", hres);
4445     ok(window2 != NULL, "self == NULL\n");
4446
4447     ok(self == window2, "self != window2\n");
4448
4449     IHTMLWindow2_Release(window2);
4450     IHTMLWindow2_Release(self);
4451
4452     disp = NULL;
4453     hres = IHTMLDocument2_get_Script(doc, &disp);
4454     ok(hres == S_OK, "get_Script failed: %08x\n", hres);
4455     ok(disp == (void*)window, "disp != window\n");
4456     IDispatch_Release(disp);
4457
4458     hres = IHTMLWindow2_toString(window, NULL);
4459     ok(hres == E_INVALIDARG, "toString failed: %08x\n", hres);
4460
4461     str = NULL;
4462     hres = IHTMLWindow2_toString(window, &str);
4463     ok(hres == S_OK, "toString failed: %08x\n", hres);
4464     ok(!strcmp_wa(str, "[object]") ||
4465        !strcmp_wa(str, "[object Window]") /* win7 ie9 */, "toString returned %s\n", wine_dbgstr_w(str));
4466     SysFreeString(str);
4467
4468     test_window_name(window, NULL);
4469     set_window_name(window, "test");
4470     test_window_length(window, 0);
4471     test_screen(window);
4472     test_window_status(window);
4473     set_window_status(window, "Test!");
4474
4475     IHTMLWindow2_Release(window);
4476 }
4477
4478 static void test_defaults(IHTMLDocument2 *doc)
4479 {
4480     IHTMLStyleSheetsCollection *stylesheetcol;
4481     IHTMLCurrentStyle *cstyle;
4482     IHTMLBodyElement *body;
4483     IHTMLElement2 *elem2;
4484     IHTMLElement *elem;
4485     IHTMLStyle *style;
4486     LONG l;
4487     HRESULT hres;
4488     IHTMLElementCollection *collection;
4489
4490     elem = doc_get_body(doc);
4491
4492     hres = IHTMLDocument2_get_images(doc, NULL);
4493     ok(hres == E_INVALIDARG, "hres %08x\n", hres);
4494
4495     hres = IHTMLDocument2_get_images(doc, &collection);
4496     ok(hres == S_OK, "get_images failed: %08x\n", hres);
4497     if(hres == S_OK)
4498     {
4499         test_elem_collection((IUnknown*)collection, NULL, 0);
4500         IHTMLElementCollection_Release(collection);
4501     }
4502
4503     hres = IHTMLDocument2_get_applets(doc, NULL);
4504     ok(hres == E_INVALIDARG, "hres %08x\n", hres);
4505
4506     hres = IHTMLDocument2_get_applets(doc, &collection);
4507     ok(hres == S_OK, "get_applets failed: %08x\n", hres);
4508     if(hres == S_OK)
4509     {
4510         test_elem_collection((IUnknown*)collection, NULL, 0);
4511         IHTMLElementCollection_Release(collection);
4512     }
4513
4514     hres = IHTMLDocument2_get_links(doc, NULL);
4515     ok(hres == E_INVALIDARG, "hres %08x\n", hres);
4516
4517     hres = IHTMLDocument2_get_links(doc, &collection);
4518     ok(hres == S_OK, "get_links failed: %08x\n", hres);
4519     if(hres == S_OK)
4520     {
4521         test_elem_collection((IUnknown*)collection, NULL, 0);
4522         IHTMLElementCollection_Release(collection);
4523     }
4524
4525     hres = IHTMLDocument2_get_forms(doc, NULL);
4526     ok(hres == E_INVALIDARG, "hres %08x\n", hres);
4527
4528     hres = IHTMLDocument2_get_forms(doc, &collection);
4529     ok(hres == S_OK, "get_forms failed: %08x\n", hres);
4530     if(hres == S_OK)
4531     {
4532         test_elem_collection((IUnknown*)collection, NULL, 0);
4533         IHTMLElementCollection_Release(collection);
4534     }
4535
4536     hres = IHTMLDocument2_get_anchors(doc, NULL);
4537     ok(hres == E_INVALIDARG, "hres %08x\n", hres);
4538
4539     hres = IHTMLDocument2_get_anchors(doc, &collection);
4540     ok(hres == S_OK, "get_anchors failed: %08x\n", hres);
4541     if(hres == S_OK)
4542     {
4543         test_elem_collection((IUnknown*)collection, NULL, 0);
4544         IHTMLElementCollection_Release(collection);
4545     }
4546
4547     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLBodyElement, (void**)&body);
4548     ok(hres == S_OK, "Could not get IHTMBodyElement: %08x\n", hres);
4549     test_default_body(body);
4550     test_body_funs(body);
4551     IHTMLBodyElement_Release(body);
4552
4553     hres = IHTMLElement_get_style(elem, &style);
4554     ok(hres == S_OK, "get_style failed: %08x\n", hres);
4555
4556     test_disp((IUnknown*)style, &DIID_DispHTMLStyle, "[object]");
4557     test_ifaces((IUnknown*)style, style_iids);
4558     IHTMLStyle_Release(style);
4559
4560     test_window(doc);
4561     test_compatmode(doc);
4562     test_location(doc);
4563     test_navigator(doc);
4564     test_plugins_col(doc);
4565
4566     elem2 = get_elem2_iface((IUnknown*)elem);
4567     hres = IHTMLElement2_get_currentStyle(elem2, &cstyle);
4568     ok(hres == S_OK, "get_currentStyle failed: %08x\n", hres);
4569     if(SUCCEEDED(hres)) {
4570         IUnknown *unk;
4571
4572         test_disp((IUnknown*)cstyle, &DIID_DispHTMLCurrentStyle, "[object]");
4573         test_ifaces((IUnknown*)cstyle, cstyle_iids);
4574
4575         hres = IHTMLCurrentStyle_QueryInterface(cstyle, &IID_IHTMLCurrentStyle4, (void**)&unk);
4576         if(SUCCEEDED(hres))
4577             IUnknown_Release(unk);
4578         else
4579         {
4580            /*IE6 doesn't have interface */
4581            win_skip("IID_IHTMLCurrentStyle4 not supported\n");
4582         }
4583
4584         IHTMLCurrentStyle_Release(cstyle);
4585     }
4586     IHTMLElement2_Release(elem2);
4587
4588     IHTMLElement_Release(elem);
4589
4590     hres = IHTMLDocument2_get_styleSheets(doc, &stylesheetcol);
4591     ok(hres == S_OK, "get_styleSheets failed: %08x\n", hres);
4592
4593     l = 0xdeadbeef;
4594     hres = IHTMLStyleSheetsCollection_get_length(stylesheetcol, &l);
4595     ok(hres == S_OK, "get_length failed: %08x\n", hres);
4596     ok(l == 0, "length = %d\n", l);
4597
4598     IHTMLStyleSheetsCollection_Release(stylesheetcol);
4599
4600     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFiltersCollection, (void**)&body);
4601     ok(hres == E_NOINTERFACE, "got interface IHTMLFiltersCollection\n");
4602
4603     test_default_selection(doc);
4604     test_doc_title(doc, "");
4605 }
4606
4607 static void test_tr_elem(IHTMLElement *elem)
4608 {
4609     IHTMLElementCollection *col;
4610     IHTMLTableRow *row;
4611     HRESULT hres;
4612
4613     static const elem_type_t cell_types[] = {ET_TD,ET_TD};
4614
4615     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLTableRow, (void**)&row);
4616     ok(hres == S_OK, "Could not get IHTMLTableRow iface: %08x\n", hres);
4617     if(FAILED(hres))
4618         return;
4619
4620     col = NULL;
4621     hres = IHTMLTableRow_get_cells(row, &col);
4622     ok(hres == S_OK, "get_cells failed: %08x\n", hres);
4623     ok(col != NULL, "get_cells returned NULL\n");
4624
4625     test_elem_collection((IUnknown*)col, cell_types, sizeof(cell_types)/sizeof(*cell_types));
4626     IHTMLElementCollection_Release(col);
4627
4628     IHTMLTable_Release(row);
4629 }
4630
4631 static void test_table_elem(IHTMLElement *elem)
4632 {
4633     IHTMLElementCollection *col;
4634     IHTMLTable *table;
4635     IHTMLDOMNode *node;
4636     HRESULT hres;
4637
4638     static const elem_type_t row_types[] = {ET_TR,ET_TR};
4639     static const elem_type_t all_types[] = {ET_TBODY,ET_TR,ET_TR,ET_TD,ET_TD};
4640
4641     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLTable, (void**)&table);
4642     ok(hres == S_OK, "Could not get IHTMLTable iface: %08x\n", hres);
4643     if(FAILED(hres))
4644         return;
4645
4646     col = NULL;
4647     hres = IHTMLTable_get_rows(table, &col);
4648     ok(hres == S_OK, "get_rows failed: %08x\n", hres);
4649     ok(col != NULL, "get_ros returned NULL\n");
4650
4651     test_elem_collection((IUnknown*)col, row_types, sizeof(row_types)/sizeof(*row_types));
4652     IHTMLElementCollection_Release(col);
4653
4654     test_elem_all((IUnknown*)table, all_types, sizeof(all_types)/sizeof(*all_types));
4655
4656     node = clone_node((IUnknown*)table, VARIANT_TRUE);
4657     test_elem_tag((IUnknown*)node, "TABLE");
4658     test_elem_all((IUnknown*)node, all_types, sizeof(all_types)/sizeof(*all_types));
4659     IHTMLDOMNode_Release(node);
4660
4661     node = clone_node((IUnknown*)table, VARIANT_FALSE);
4662     test_elem_tag((IUnknown*)node, "TABLE");
4663     test_elem_all((IUnknown*)node, NULL, 0);
4664     IHTMLDOMNode_Release(node);
4665
4666     IHTMLTable_Release(table);
4667 }
4668
4669 static void doc_write(IHTMLDocument2 *doc, BOOL ln, const char *text)
4670 {
4671     SAFEARRAYBOUND dim;
4672     SAFEARRAY *sa;
4673     VARIANT *var;
4674     HRESULT hres;
4675
4676     dim.lLbound = 0;
4677     dim.cElements = 1;
4678     sa = SafeArrayCreate(VT_VARIANT, 1, &dim);
4679     SafeArrayAccessData(sa, (void**)&var);
4680     V_VT(var) = VT_BSTR;
4681     V_BSTR(var) = a2bstr(text);
4682     SafeArrayUnaccessData(sa);
4683
4684     if(ln)
4685         hres = IHTMLDocument2_writeln(doc, sa);
4686     else
4687         hres = IHTMLDocument2_write(doc, sa);
4688     ok(hres == S_OK, "write failed: %08x\n", hres);
4689
4690     SafeArrayDestroy(sa);
4691 }
4692
4693 static void test_frame_doc(IUnknown *frame_elem, BOOL iframe)
4694 {
4695     IHTMLDocument2 *window_doc, *elem_doc;
4696     IHTMLFrameElement3 *frame_elem3;
4697     IHTMLWindow2 *content_window;
4698     HRESULT hres;
4699
4700     content_window = get_frame_content_window(frame_elem);
4701     window_doc = get_window_doc(content_window);
4702     IHTMLWindow2_Release(content_window);
4703
4704     elem_doc = get_elem_doc(frame_elem);
4705     ok(iface_cmp((IUnknown*)window_doc, (IUnknown*)elem_doc), "content_doc != elem_doc\n");
4706
4707     if(!iframe) {
4708         hres = IUnknown_QueryInterface(frame_elem, &IID_IHTMLFrameElement3, (void**)&frame_elem3);
4709         if(SUCCEEDED(hres)) {
4710             IDispatch *disp = NULL;
4711
4712             hres = IHTMLFrameElement3_get_contentDocument(frame_elem3, &disp);
4713             ok(hres == S_OK, "get_contentDocument failed: %08x\n", hres);
4714             ok(disp != NULL, "contentDocument == NULL\n");
4715             ok(iface_cmp((IUnknown*)disp, (IUnknown*)window_doc), "contentDocument != contentWindow.document\n");
4716
4717             IDispatch_Release(disp);
4718             IHTMLFrameElement3_Release(frame_elem3);
4719         }else {
4720             win_skip("IHTMLFrameElement3 not supported\n");
4721         }
4722     }
4723
4724     IHTMLDocument2_Release(elem_doc);
4725     IHTMLDocument2_Release(window_doc);
4726 }
4727
4728 static void test_iframe_elem(IHTMLElement *elem)
4729 {
4730     IHTMLDocument2 *content_doc, *owner_doc;
4731     IHTMLElementCollection *col;
4732     IHTMLWindow2 *content_window;
4733     IDispatch *disp;
4734     VARIANT errv;
4735     BSTR str;
4736     HRESULT hres;
4737
4738     static const elem_type_t all_types[] = {
4739         ET_HTML,
4740         ET_HEAD,
4741         ET_TITLE,
4742         ET_BODY,
4743         ET_BR
4744     };
4745
4746     test_frame_doc((IUnknown*)elem, TRUE);
4747
4748     content_window = get_frame_content_window((IUnknown*)elem);
4749     test_window_length(content_window, 0);
4750
4751     content_doc = get_window_doc(content_window);
4752     IHTMLWindow2_Release(content_window);
4753
4754     str = a2bstr("text/html");
4755     V_VT(&errv) = VT_ERROR;
4756     disp = NULL;
4757     hres = IHTMLDocument2_open(content_doc, str, errv, errv, errv, &disp);
4758     SysFreeString(str);
4759     ok(hres == S_OK, "open failed: %08x\n", hres);
4760     ok(disp != NULL, "disp == NULL\n");
4761     ok(iface_cmp((IUnknown*)disp, (IUnknown*)content_window), "disp != content_window\n");
4762     IDispatch_Release(disp);
4763
4764     doc_write(content_doc, FALSE, "<html><head><title>test</title></head><body><br /></body>");
4765     doc_write(content_doc, TRUE, "</html>");
4766
4767     hres = IHTMLDocument2_get_all(content_doc, &col);
4768     ok(hres == S_OK, "get_all failed: %08x\n", hres);
4769     test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
4770     IHTMLElementCollection_Release(col);
4771
4772     hres = IHTMLDocument2_close(content_doc);
4773     ok(hres == S_OK, "close failed: %08x\n", hres);
4774
4775     owner_doc = get_owner_doc((IUnknown*)content_doc);
4776     ok(!owner_doc, "owner_doc = %p\n", owner_doc);
4777
4778     IHTMLDocument2_Release(content_doc);
4779 }
4780
4781 static void test_stylesheet(IDispatch *disp)
4782 {
4783     IHTMLStyleSheetRulesCollection *col = NULL;
4784     IHTMLStyleSheet *stylesheet;
4785     HRESULT hres;
4786
4787     hres = IDispatch_QueryInterface(disp, &IID_IHTMLStyleSheet, (void**)&stylesheet);
4788     ok(hres == S_OK, "Could not get IHTMLStyleSheet: %08x\n", hres);
4789
4790     hres = IHTMLStyleSheet_get_rules(stylesheet, &col);
4791     ok(hres == S_OK, "get_rules failed: %08x\n", hres);
4792     ok(col != NULL, "col == NULL\n");
4793
4794     IHTMLStyleSheetRulesCollection_Release(col);
4795     IHTMLStyleSheet_Release(stylesheet);
4796 }
4797
4798 static void test_stylesheets(IHTMLDocument2 *doc)
4799 {
4800     IHTMLStyleSheetsCollection *col = NULL;
4801     VARIANT idx, res;
4802     LONG len = 0;
4803     HRESULT hres;
4804
4805     hres = IHTMLDocument2_get_styleSheets(doc, &col);
4806     ok(hres == S_OK, "get_styleSheets failed: %08x\n", hres);
4807     ok(col != NULL, "col == NULL\n");
4808
4809     test_disp2((IUnknown*)col, &DIID_DispHTMLStyleSheetsCollection, &IID_IHTMLStyleSheetsCollection, "[object]");
4810
4811     hres = IHTMLStyleSheetsCollection_get_length(col, &len);
4812     ok(hres == S_OK, "get_length failed: %08x\n", hres);
4813     ok(len == 1, "len=%d\n", len);
4814
4815     VariantInit(&res);
4816     V_VT(&idx) = VT_I4;
4817     V_I4(&idx) = 0;
4818
4819     hres = IHTMLStyleSheetsCollection_item(col, &idx, &res);
4820     ok(hres == S_OK, "item failed: %08x\n", hres);
4821     ok(V_VT(&res) == VT_DISPATCH, "V_VT(res) = %d\n", V_VT(&res));
4822     ok(V_DISPATCH(&res) != NULL, "V_DISPATCH(&res) == NULL\n");
4823     test_stylesheet(V_DISPATCH(&res));
4824     VariantClear(&res);
4825
4826     V_VT(&res) = VT_I4;
4827     V_VT(&idx) = VT_I4;
4828     V_I4(&idx) = 1;
4829
4830     hres = IHTMLStyleSheetsCollection_item(col, &idx, &res);
4831     ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
4832     ok(V_VT(&res) == VT_EMPTY, "V_VT(res) = %d\n", V_VT(&res));
4833     ok(V_DISPATCH(&res) != NULL, "V_DISPATCH(&res) == NULL\n");
4834     VariantClear(&res);
4835
4836     IHTMLStyleSheetsCollection_Release(col);
4837 }
4838
4839 static void test_child_col_disp(IHTMLDOMChildrenCollection *col)
4840 {
4841     IDispatchEx *dispex;
4842     IHTMLDOMNode *node;
4843     DISPPARAMS dp = {NULL, NULL, 0, 0};
4844     VARIANT var;
4845     EXCEPINFO ei;
4846     LONG type;
4847     DISPID id;
4848     BSTR bstr;
4849     HRESULT hres;
4850
4851     static const WCHAR w0[] = {'0',0};
4852     static const WCHAR w100[] = {'1','0','0',0};
4853
4854     hres = IHTMLDOMChildrenCollection_QueryInterface(col, &IID_IDispatchEx, (void**)&dispex);
4855     ok(hres == S_OK, "Could not get IDispatchEx: %08x\n", hres);
4856
4857     bstr = SysAllocString(w0);
4858     hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id);
4859     ok(hres == S_OK, "GetDispID failed: %08x\n", hres);
4860     SysFreeString(bstr);
4861
4862     VariantInit(&var);
4863     hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, INVOKE_PROPERTYGET, &dp, &var, &ei, NULL);
4864     ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
4865     ok(V_VT(&var) == VT_DISPATCH, "V_VT(var)=%d\n", V_VT(&var));
4866     ok(V_DISPATCH(&var) != NULL, "V_DISPATCH(var) == NULL\n");
4867     node = get_node_iface((IUnknown*)V_DISPATCH(&var));
4868     type = get_node_type((IUnknown*)node);
4869     ok(type == 3, "type=%d\n", type);
4870     IHTMLDOMNode_Release(node);
4871     VariantClear(&var);
4872
4873     bstr = SysAllocString(w100);
4874     hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameCaseSensitive, &id);
4875     ok(hres == DISP_E_UNKNOWNNAME, "GetDispID failed: %08x, expected DISP_E_UNKNOWNNAME\n", hres);
4876     SysFreeString(bstr);
4877
4878     IDispatchEx_Release(dispex);
4879 }
4880
4881
4882
4883 static void test_elems(IHTMLDocument2 *doc)
4884 {
4885     IHTMLElementCollection *col;
4886     IHTMLDOMChildrenCollection *child_col;
4887     IHTMLElement *elem, *elem2, *elem3;
4888     IHTMLDOMNode *node, *node2;
4889     IHTMLWindow2 *window;
4890     IDispatch *disp;
4891     LONG type;
4892     HRESULT hres;
4893     IHTMLElementCollection *collection;
4894     IHTMLDocument3 *doc3;
4895     BSTR str;
4896
4897     static const elem_type_t all_types[] = {
4898         ET_HTML,
4899         ET_HEAD,
4900         ET_TITLE,
4901         ET_STYLE,
4902         ET_BODY,
4903         ET_COMMENT,
4904         ET_A,
4905         ET_INPUT,
4906         ET_SELECT,
4907         ET_OPTION,
4908         ET_OPTION,
4909         ET_TEXTAREA,
4910         ET_TABLE,
4911         ET_TBODY,
4912         ET_TR,
4913         ET_TR,
4914         ET_TD,
4915         ET_TD,
4916         ET_SCRIPT,
4917         ET_TEST,
4918         ET_OBJECT,
4919         ET_EMBED,
4920         ET_IMG,
4921         ET_IFRAME,
4922         ET_FORM,
4923         ET_DIV
4924     };
4925
4926     static const elem_type_t item_types[] = {
4927         ET_A,
4928         ET_OPTION,
4929         ET_TEXTAREA
4930     };
4931
4932     hres = IHTMLDocument2_get_all(doc, &col);
4933     ok(hres == S_OK, "get_all failed: %08x\n", hres);
4934     test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
4935     test_elem_col_item(col, "x", item_types, sizeof(item_types)/sizeof(item_types[0]));
4936     IHTMLElementCollection_Release(col);
4937
4938     hres = IHTMLDocument2_get_images(doc, &collection);
4939     ok(hres == S_OK, "get_images failed: %08x\n", hres);
4940     if(hres == S_OK)
4941     {
4942         static const elem_type_t images_types[] = {ET_IMG};
4943         test_elem_collection((IUnknown*)collection, images_types, 1);
4944
4945         IHTMLElementCollection_Release(collection);
4946     }
4947
4948     hres = IHTMLDocument2_get_links(doc, &collection);
4949     ok(hres == S_OK, "get_links failed: %08x\n", hres);
4950     if(hres == S_OK)
4951     {
4952         static const elem_type_t images_types[] = {ET_A};
4953         test_elem_collection((IUnknown*)collection, images_types, 1);
4954
4955         IHTMLElementCollection_Release(collection);
4956     }
4957
4958     hres = IHTMLDocument2_get_anchors(doc, &collection);
4959     ok(hres == S_OK, "get_anchors failed: %08x\n", hres);
4960     if(hres == S_OK)
4961     {
4962         static const elem_type_t anchor_types[] = {ET_A};
4963         test_elem_collection((IUnknown*)collection, anchor_types, 1);
4964
4965         IHTMLElementCollection_Release(collection);
4966     }
4967
4968     test_plugins_col(doc);
4969
4970     elem = get_doc_elem(doc);
4971     test_elem_all((IUnknown*)elem, all_types+1, sizeof(all_types)/sizeof(all_types[0])-1);
4972     IHTMLElement_Release(elem);
4973
4974     get_elem_by_id(doc, "xxx", FALSE);
4975     elem = get_doc_elem_by_id(doc, "xxx");
4976     ok(!elem, "elem != NULL\n");
4977
4978     elem = get_doc_elem_by_id(doc, "s");
4979     ok(elem != NULL, "elem == NULL\n");
4980     if(elem) {
4981         test_elem_type((IUnknown*)elem, ET_SELECT);
4982         test_elem_attr(elem, "xxx", NULL);
4983         test_elem_attr(elem, "id", "s");
4984         test_elem_class((IUnknown*)elem, NULL);
4985         test_elem_set_class((IUnknown*)elem, "cl");
4986         test_elem_set_class((IUnknown*)elem, NULL);
4987         test_elem_tabindex((IUnknown*)elem, 0);
4988         test_elem_set_tabindex((IUnknown*)elem, 1);
4989         test_elem_filters((IUnknown*)elem);
4990
4991         node = test_node_get_parent((IUnknown*)elem);
4992         ok(node != NULL, "node == NULL\n");
4993         test_node_name((IUnknown*)node, "BODY");
4994         node2 = test_node_get_parent((IUnknown*)node);
4995         IHTMLDOMNode_Release(node);
4996         ok(node2 != NULL, "node == NULL\n");
4997         test_node_name((IUnknown*)node2, "HTML");
4998         node = test_node_get_parent((IUnknown*)node2);
4999         IHTMLDOMNode_Release(node2);
5000         ok(node != NULL, "node == NULL\n");
5001         if (node)
5002         {
5003             test_node_name((IUnknown*)node, "#document");
5004             type = get_node_type((IUnknown*)node);
5005             ok(type == 9, "type=%d, expected 9\n", type);
5006             node2 = test_node_get_parent((IUnknown*)node);
5007             IHTMLDOMNode_Release(node);
5008             ok(node2 == NULL, "node != NULL\n");
5009         }
5010
5011         elem2 = test_elem_get_parent((IUnknown*)elem);
5012         ok(elem2 != NULL, "elem2 == NULL\n");
5013         test_node_name((IUnknown*)elem2, "BODY");
5014         elem3 = test_elem_get_parent((IUnknown*)elem2);
5015         IHTMLElement_Release(elem2);
5016         ok(elem3 != NULL, "elem3 == NULL\n");
5017         test_node_name((IUnknown*)elem3, "HTML");
5018         elem2 = test_elem_get_parent((IUnknown*)elem3);
5019         IHTMLElement_Release(elem3);
5020         ok(elem2 == NULL, "elem2 != NULL\n");
5021
5022         test_elem_getelembytag((IUnknown*)elem, ET_OPTION, 2);
5023         test_elem_getelembytag((IUnknown*)elem, ET_SELECT, 0);
5024         test_elem_getelembytag((IUnknown*)elem, ET_HTML, 0);
5025
5026         test_elem_innertext(elem, "opt1opt2");
5027
5028         IHTMLElement_Release(elem);
5029     }
5030
5031     elem = get_elem_by_id(doc, "s", TRUE);
5032     if(elem) {
5033         IHTMLSelectElement *select = get_select_iface((IUnknown*)elem);
5034         IHTMLDocument2 *doc_node, *elem_doc;
5035
5036         test_select_elem(select);
5037
5038         test_elem_title((IUnknown*)select, NULL);
5039         test_elem_set_title((IUnknown*)select, "Title");
5040         test_elem_title((IUnknown*)select, "Title");
5041         test_elem_offset((IUnknown*)select, "BODY");
5042         test_elem_bounding_client_rect((IUnknown*)select);
5043
5044         node = get_first_child((IUnknown*)select);
5045         ok(node != NULL, "node == NULL\n");
5046         if(node) {
5047             test_elem_type((IUnknown*)node, ET_OPTION);
5048             IHTMLDOMNode_Release(node);
5049         }
5050
5051         type = get_node_type((IUnknown*)select);
5052         ok(type == 1, "type=%d\n", type);
5053
5054         IHTMLSelectElement_Release(select);
5055
5056         elem_doc = get_elem_doc((IUnknown*)elem);
5057
5058         doc_node = get_doc_node(doc);
5059         ok(iface_cmp((IUnknown*)elem_doc, (IUnknown*)doc_node), "disp != doc\n");
5060         IHTMLDocument2_Release(doc_node);
5061         IHTMLDocument2_Release(elem_doc);
5062
5063         IHTMLElement_Release(elem);
5064     }
5065
5066     elem = get_elem_by_id(doc, "sc", TRUE);
5067     if(elem) {
5068         IHTMLScriptElement *script;
5069         BSTR type;
5070
5071         hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLScriptElement, (void**)&script);
5072         ok(hres == S_OK, "Could not get IHTMLScriptElement interface: %08x\n", hres);
5073
5074         if(hres == S_OK)
5075         {
5076             VARIANT_BOOL vb;
5077
5078             hres = IHTMLScriptElement_put_type (script, NULL);
5079             ok(hres == S_OK, "put_type failed: %08x\n", hres);
5080             hres = IHTMLScriptElement_get_type(script, &type);
5081             ok(hres == S_OK, "get_type failed: %08x\n", hres);
5082             ok(type == NULL, "Unexpected type %s\n", wine_dbgstr_w(type));
5083
5084             hres = IHTMLScriptElement_put_type (script, a2bstr ("text/javascript"));
5085             ok(hres == S_OK, "put_type failed: %08x\n", hres);
5086             hres = IHTMLScriptElement_get_type(script, &type);
5087             ok(hres == S_OK, "get_type failed: %08x\n", hres);
5088             ok(!strcmp_wa(type, "text/javascript"), "Unexpected type %s\n", wine_dbgstr_w(type));
5089
5090             SysFreeString(type);
5091
5092             /* test defer */
5093             hres = IHTMLScriptElement_put_defer(script, VARIANT_TRUE);
5094             ok(hres == S_OK, "put_defer failed: %08x\n", hres);
5095
5096             hres = IHTMLScriptElement_get_defer(script, &vb);
5097             ok(hres == S_OK, "get_defer failed: %08x\n", hres);
5098             ok(vb == VARIANT_TRUE, "get_defer result is %08x\n", hres);
5099
5100             hres = IHTMLScriptElement_put_defer(script, VARIANT_FALSE);
5101             ok(hres == S_OK, "put_defer failed: %08x\n", hres);
5102
5103             str = (BSTR)0xdeadbeef;
5104             hres = IHTMLScriptElement_get_src(script, &str);
5105             ok(hres == S_OK, "get_src failed: %08x\n", hres);
5106             ok(!str, "src = %s\n", wine_dbgstr_w(str));
5107         }
5108
5109         IHTMLScriptElement_Release(script);
5110     }
5111
5112     elem = get_elem_by_id(doc, "in", TRUE);
5113     if(elem) {
5114         IHTMLInputElement *input;
5115
5116         hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLInputElement, (void**)&input);
5117         ok(hres == S_OK, "Could not get IHTMLInputElement: %08x\n", hres);
5118
5119         test_elem_id((IUnknown*)elem, "in");
5120         test_elem_put_id((IUnknown*)elem, "newin");
5121         test_input_get_disabled(input, VARIANT_FALSE);
5122         test_input_set_disabled(input, VARIANT_TRUE);
5123         test_input_set_disabled(input, VARIANT_FALSE);
5124         test_elem3_set_disabled((IUnknown*)input, VARIANT_TRUE);
5125         test_input_get_disabled(input, VARIANT_TRUE);
5126         test_elem3_set_disabled((IUnknown*)input, VARIANT_FALSE);
5127         test_input_get_disabled(input, VARIANT_FALSE);
5128         test_elem_client_size((IUnknown*)elem);
5129         test_input_type(input, "text");
5130
5131         test_node_get_value_str((IUnknown*)elem, NULL);
5132         test_node_put_value_str((IUnknown*)elem, "test");
5133         test_node_get_value_str((IUnknown*)elem, NULL);
5134         test_input_value((IUnknown*)elem, NULL);
5135         test_input_put_value((IUnknown*)elem, "test");
5136         test_elem_class((IUnknown*)elem, "testclass");
5137         test_elem_tabindex((IUnknown*)elem, 2);
5138         test_elem_set_tabindex((IUnknown*)elem, 3);
5139         test_elem_title((IUnknown*)elem, "test title");
5140
5141         test_input_get_defaultchecked(input, VARIANT_FALSE);
5142         test_input_set_defaultchecked(input, VARIANT_TRUE);
5143         test_input_set_defaultchecked(input, VARIANT_FALSE);
5144
5145         test_input_get_checked(input, VARIANT_FALSE);
5146         test_input_set_checked(input, VARIANT_TRUE);
5147         test_input_set_checked(input, VARIANT_FALSE);
5148
5149         test_input_name(input, NULL);
5150         test_input_set_name(input, "test");
5151
5152         test_input_src(input, NULL);
5153         test_input_set_src(input, "about:blank");
5154
5155         IHTMLInputElement_Release(input);
5156         IHTMLElement_Release(elem);
5157     }
5158
5159     elem = get_elem_by_id(doc, "imgid", TRUE);
5160     if(elem) {
5161         test_img_src((IUnknown*)elem, "", NULL);
5162         test_img_set_src((IUnknown*)elem, "about:blank");
5163         test_img_src((IUnknown*)elem, "about:blank", NULL);
5164         test_img_alt((IUnknown*)elem, NULL);
5165         test_img_set_alt((IUnknown*)elem, "alt test");
5166         test_img_name((IUnknown*)elem, "WineImg");
5167         IHTMLElement_Release(elem);
5168     }
5169
5170     elem = get_elem_by_id(doc, "attr", TRUE);
5171     if(elem) {
5172         test_dynamic_properties(elem);
5173         test_attr_collection(elem);
5174         IHTMLElement_Release(elem);
5175     }
5176
5177     elem = get_elem_by_id(doc, "styleid", TRUE);
5178     if(elem) {
5179         test_style_media((IUnknown*)elem, NULL);
5180         test_style_put_media((IUnknown*)elem, "screen");
5181         test_style_type((IUnknown*)elem, NULL);
5182         test_style_put_type((IUnknown*)elem, "text/css");
5183         IHTMLElement_Release(elem);
5184     }
5185
5186     elem = get_doc_elem_by_id(doc, "tbl");
5187     ok(elem != NULL, "elem == NULL\n");
5188     if(elem) {
5189         test_table_elem(elem);
5190         IHTMLElement_Release(elem);
5191     }
5192
5193     elem = get_doc_elem_by_id(doc, "row2");
5194     ok(elem != NULL, "elem == NULL\n");
5195     if(elem) {
5196         test_tr_elem(elem);
5197         IHTMLElement_Release(elem);
5198     }
5199
5200     elem = get_doc_elem_by_id(doc, "ifr");
5201     ok(elem != NULL, "elem == NULL\n");
5202     if(elem) {
5203         test_iframe_elem(elem);
5204         IHTMLElement_Release(elem);
5205     }
5206
5207     elem = get_doc_elem_by_id(doc, "objid");
5208     ok(elem != NULL, "elem == NULL\n");
5209     if(elem) {
5210         test_object_vspace((IUnknown*)elem, 100);
5211         IHTMLElement_Release(elem);
5212     }
5213
5214     elem = get_elem_by_id(doc, "a", TRUE);
5215     if(elem) {
5216         test_anchor_href((IUnknown*)elem, "http://test/");
5217
5218         /* Change the href */
5219         test_anchor_put_href((IUnknown*)elem, "http://test1/");
5220         test_anchor_href((IUnknown*)elem, "http://test1/");
5221
5222         /* Restore the href */
5223         test_anchor_put_href((IUnknown*)elem, "http://test/");
5224         test_anchor_href((IUnknown*)elem, "http://test/");
5225
5226         /* target */
5227         test_anchor_get_target((IUnknown*)elem, NULL);
5228
5229         /* Change the target */
5230         test_anchor_put_target((IUnknown*)elem, "wine");
5231         test_anchor_get_target((IUnknown*)elem, "wine");
5232
5233         /* Restore the target */
5234         test_anchor_put_target((IUnknown*)elem, NULL);
5235         test_anchor_get_target((IUnknown*)elem, NULL);
5236
5237         IHTMLElement_Release(elem);
5238     }
5239
5240     elem = doc_get_body(doc);
5241
5242     node = get_first_child((IUnknown*)elem);
5243     ok(node != NULL, "node == NULL\n");
5244     if(node) {
5245         test_ifaces((IUnknown*)node, text_iids);
5246         test_disp((IUnknown*)node, &DIID_DispHTMLDOMTextNode, "[object]");
5247
5248         node2 = get_first_child((IUnknown*)node);
5249         ok(!node2, "node2 != NULL\n");
5250
5251         type = get_node_type((IUnknown*)node);
5252         ok(type == 3, "type=%d\n", type);
5253
5254         test_node_get_value_str((IUnknown*)node, "text test");
5255         test_node_put_value_str((IUnknown*)elem, "test text");
5256         test_node_get_value_str((IUnknown*)node, "text test");
5257
5258         hres = IHTMLDOMNode_get_attributes(node, &disp);
5259         ok(hres == S_OK, "get_attributes failed: %08x\n", hres);
5260         ok(!disp, "disp != NULL\n");
5261
5262         IHTMLDOMNode_Release(node);
5263     }
5264
5265     child_col = get_child_nodes((IUnknown*)elem);
5266     ok(child_col != NULL, "child_coll == NULL\n");
5267     if(child_col) {
5268         LONG length = 0;
5269
5270         test_disp((IUnknown*)child_col, &DIID_DispDOMChildrenCollection, "[object]");
5271
5272         hres = IHTMLDOMChildrenCollection_get_length(child_col, &length);
5273         ok(hres == S_OK, "get_length failed: %08x\n", hres);
5274         ok(length, "length=0\n");
5275
5276         node2 = NULL;
5277         node = get_child_item(child_col, 0);
5278         ok(node != NULL, "node == NULL\n");
5279         if(node) {
5280             IHTMLDOMNode *prev;
5281
5282             type = get_node_type((IUnknown*)node);
5283             ok(type == 3, "type=%d\n", type);
5284             node2 = node_get_next((IUnknown*)node);
5285
5286             prev = node_get_prev((IUnknown*)node2);
5287             ok(iface_cmp((IUnknown*)node, (IUnknown*)prev), "node != prev\n");
5288             IHTMLDOMNode_Release(prev);
5289
5290             IHTMLDOMNode_Release(node);
5291         }
5292
5293         node = get_child_item(child_col, 1);
5294         ok(node != NULL, "node == NULL\n");
5295         if(node) {
5296             type = get_node_type((IUnknown*)node);
5297             ok(type == 8, "type=%d\n", type);
5298
5299             test_elem_id((IUnknown*)node, NULL);
5300             ok(iface_cmp((IUnknown*)node2, (IUnknown*)node), "node2 != node\n");
5301             IHTMLDOMNode_Release(node2);
5302             IHTMLDOMNode_Release(node);
5303         }
5304
5305         hres = IHTMLDOMChildrenCollection_item(child_col, length - 1, NULL);
5306         ok(hres == E_POINTER, "item failed: %08x, expected E_POINTER\n", hres);
5307
5308         hres = IHTMLDOMChildrenCollection_item(child_col, length, NULL);
5309         ok(hres == E_POINTER, "item failed: %08x, expected E_POINTER\n", hres);
5310
5311         hres = IHTMLDOMChildrenCollection_item(child_col, 6000, &disp);
5312         ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
5313
5314         hres = IHTMLDOMChildrenCollection_item(child_col, length, &disp);
5315         ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
5316
5317         test_child_col_disp(child_col);
5318
5319         IHTMLDOMChildrenCollection_Release(child_col);
5320     }
5321
5322     test_elem3_get_disabled((IUnknown*)elem, VARIANT_FALSE);
5323     test_elem3_set_disabled((IUnknown*)elem, VARIANT_TRUE);
5324     test_elem3_set_disabled((IUnknown*)elem, VARIANT_FALSE);
5325
5326     IHTMLElement_Release(elem);
5327
5328     elem = get_doc_elem_by_id(doc, "frm");
5329     ok(elem != NULL, "elem == NULL\n");
5330     if(elem) {
5331         test_form_length((IUnknown*)elem, 0);
5332         test_form_elements((IUnknown*)elem);
5333         IHTMLElement_Release(elem);
5334     }
5335
5336     test_stylesheets(doc);
5337     test_create_option_elem(doc);
5338     test_create_img_elem(doc);
5339
5340     elem = get_doc_elem_by_id(doc, "tbl");
5341     ok(elem != NULL, "elem = NULL\n");
5342     test_elem_set_innertext(elem, "inner text");
5343     IHTMLElement_Release(elem);
5344
5345     test_doc_title(doc, "test");
5346     test_doc_set_title(doc, "test title");
5347     test_doc_title(doc, "test title");
5348
5349     disp = NULL;
5350     hres = IHTMLDocument2_get_Script(doc, &disp);
5351     ok(hres == S_OK, "get_Script failed: %08x\n", hres);
5352     if(hres == S_OK)
5353     {
5354         IDispatchEx *dispex;
5355         hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
5356         ok(hres == S_OK, "IDispatch_QueryInterface failed: %08x\n", hres);
5357         if(hres == S_OK)
5358         {
5359             DISPID pid = -1;
5360             BSTR str = a2bstr("Testing");
5361             hres = IDispatchEx_GetDispID(dispex, str, 1, &pid);
5362             ok(hres == S_OK, "GetDispID failed: %08x\n", hres);
5363             ok(pid != -1, "pid == -1\n");
5364             SysFreeString(str);
5365             IDispatchEx_Release(dispex);
5366         }
5367     }
5368     IDispatch_Release(disp);
5369
5370     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
5371     ok(hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres);
5372
5373     str = a2bstr("img");
5374     hres = IHTMLDocument3_getElementsByTagName(doc3, str, &col);
5375     ok(hres == S_OK, "getElementsByTagName(%s) failed: %08x\n", wine_dbgstr_w(str), hres);
5376     SysFreeString(str);
5377     if(hres == S_OK)
5378     {
5379         static const elem_type_t img_types[] = { ET_IMG };
5380
5381         test_elem_collection((IUnknown*)col, img_types, sizeof(img_types)/sizeof(img_types[0]));
5382         IHTMLElementCollection_Release(col);
5383     }
5384
5385     elem = get_doc_elem_by_id(doc, "y");
5386     test_elem_set_innerhtml((IUnknown*)elem, "inner html");
5387     test_elem_innerhtml((IUnknown*)elem, "inner html");
5388     test_elem_set_innerhtml((IUnknown*)elem, "");
5389     test_elem_innerhtml((IUnknown*)elem, NULL);
5390     node = node_get_next((IUnknown*)elem);
5391     ok(!node, "node = %p\n", node);
5392
5393     elem2 = get_doc_elem_by_id(doc, "x");
5394     test_elem_tag((IUnknown*)elem2, "A");
5395     node = node_get_next((IUnknown*)elem2);
5396     IHTMLDOMNode_Release(node);
5397     IHTMLElement_Release(elem2);
5398     IHTMLElement_Release(elem);
5399
5400     IHTMLDocument3_Release(doc3);
5401
5402     elem = get_elem_by_id(doc, "s", TRUE);
5403     if(elem) {
5404         static const elem_type_t select_types[] = { ET_OPTION, ET_OPTION, ET_OPTION };
5405
5406         test_select_put_length((IUnknown*)elem, 3);
5407         test_elem_all((IUnknown*)elem, select_types, sizeof(select_types)/sizeof(*select_types));
5408         test_select_put_length((IUnknown*)elem, 1);
5409         test_elem_all((IUnknown*)elem, select_types, 1);
5410         IHTMLElement_Release(elem);
5411     }
5412
5413     window = get_doc_window(doc);
5414     test_window_name(window, NULL);
5415     set_window_name(window, "test name");
5416     test_window_length(window, 1);
5417     IHTMLWindow2_Release(window);
5418 }
5419
5420 static void test_attr(IHTMLElement *elem)
5421 {
5422     IHTMLDOMAttribute *attr, *attr2;
5423     VARIANT v;
5424
5425     get_elem_attr_node((IUnknown*)elem, "noattr", FALSE);
5426
5427     attr = get_elem_attr_node((IUnknown*)elem, "id", TRUE);
5428
5429     test_disp((IUnknown*)attr, &DIID_DispHTMLDOMAttribute, "[object]");
5430     test_ifaces((IUnknown*)attr, attr_iids);
5431     test_no_iface((IUnknown*)attr, &IID_IHTMLDOMNode);
5432
5433     attr2 = get_elem_attr_node((IUnknown*)elem, "id", TRUE);
5434     ok(iface_cmp((IUnknown*)attr, (IUnknown*)attr2), "attr != attr2\n");
5435     IHTMLDOMAttribute_Release(attr2);
5436
5437     get_attr_node_value(attr, &v, VT_BSTR);
5438     ok(!strcmp_wa(V_BSTR(&v), "divid"), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v)));
5439     VariantClear(&v);
5440
5441     IHTMLDOMAttribute_Release(attr);
5442
5443     attr = get_elem_attr_node((IUnknown*)elem, "emptyattr", TRUE);
5444     get_attr_node_value(attr, &v, VT_BSTR);
5445     ok(!V_BSTR(&v), "V_BSTR(v) = %s\n", wine_dbgstr_w(V_BSTR(&v)));
5446     VariantClear(&v);
5447     IHTMLDOMAttribute_Release(attr);
5448
5449     V_VT(&v) = VT_I4;
5450     V_I4(&v) = 100;
5451     set_dispex_value((IUnknown*)elem, "dispprop", &v);
5452     attr = get_elem_attr_node((IUnknown*)elem, "dispprop", TRUE);
5453     get_attr_node_value(attr, &v, VT_I4);
5454     ok(V_I4(&v) == 100, "V_I4(v) = %d\n", V_I4(&v));
5455     IHTMLDOMAttribute_Release(attr);
5456 }
5457
5458 static void test_blocked(IHTMLDocument2 *doc, IHTMLElement *outer_elem)
5459 {
5460     IHTMLElement *elem;
5461
5462     test_elem_set_innerhtml((IUnknown*)outer_elem,
5463             "<img id=\"imgid\" src=\"BLOCKED::http://www.winehq.org/img.png\" />");
5464     elem = get_elem_by_id(doc, "imgid", TRUE);
5465     if(elem) {
5466         test_img_src((IUnknown*)elem, "BLOCKED::", "blocked::http://www.winehq.org/img.png");
5467         IHTMLElement_Release(elem);
5468     }
5469
5470     test_elem_set_innerhtml((IUnknown*)outer_elem,
5471             "<img id=\"imgid\" src=\"BLOCKE::http://www.winehq.org/img.png\" />");
5472     elem = get_elem_by_id(doc, "imgid", TRUE);
5473     if(elem) {
5474         test_img_src((IUnknown*)elem, "blocke::http://www.winehq.org/img.png", NULL);
5475         test_img_set_src((IUnknown*)elem, "BLOCKED:http://www.winehq.org/img.png");
5476         test_img_src((IUnknown*)elem, "blocked:http://www.winehq.org/img.png", NULL);
5477         test_img_set_src((IUnknown*)elem, "blocked::http://www.winehq.org/img.png");
5478         test_img_src((IUnknown*)elem, "BLOCKED::", "blocked::http://www.winehq.org/img.png");
5479         IHTMLElement_Release(elem);
5480     }
5481 }
5482
5483 static void test_elems2(IHTMLDocument2 *doc)
5484 {
5485     IHTMLElement *elem, *elem2, *div;
5486
5487     static const elem_type_t outer_types[] = {
5488         ET_BR,
5489         ET_A
5490     };
5491
5492     div = get_doc_elem_by_id(doc, "divid");
5493
5494     test_elem_set_innerhtml((IUnknown*)div, "<div id=\"innerid\"></div>");
5495     elem2 = get_doc_elem_by_id(doc, "innerid");
5496     ok(elem2 != NULL, "elem2 == NULL\n");
5497     test_elem_set_outerhtml((IUnknown*)elem2, "<br><a href=\"about:blank\" id=\"aid\">a</a>");
5498     test_elem_all((IUnknown*)div, outer_types, sizeof(outer_types)/sizeof(*outer_types));
5499     IHTMLElement_Release(elem2);
5500
5501     elem2 = get_doc_elem_by_id(doc, "aid");
5502     ok(elem2 != NULL, "elem2 == NULL\n");
5503     test_elem_set_outerhtml((IUnknown*)elem2, "");
5504     test_elem_all((IUnknown*)div, outer_types, 1);
5505     IHTMLElement_Release(elem2);
5506
5507     test_elem_set_innerhtml((IUnknown*)div, "<textarea id=\"ta\"></textarea>");
5508     elem = get_elem_by_id(doc, "ta", TRUE);
5509     if(elem) {
5510         test_textarea_value((IUnknown*)elem, NULL);
5511         test_textarea_put_value((IUnknown*)elem, "test");
5512         test_textarea_readonly((IUnknown*)elem, VARIANT_FALSE);
5513         test_textarea_put_readonly((IUnknown*)elem, VARIANT_TRUE);
5514         test_textarea_put_readonly((IUnknown*)elem, VARIANT_FALSE);
5515         test_textarea_type((IUnknown*)elem);
5516         IHTMLElement_Release(elem);
5517     }
5518
5519     test_elem_set_innerhtml((IUnknown*)div,
5520             "<form id=\"form\"><input type=\"button\" /><div><input type=\"text\" /></div></textarea>");
5521     elem = get_elem_by_id(doc, "form", TRUE);
5522     if(elem) {
5523         test_form_length((IUnknown*)elem, 2);
5524         test_form_item(elem);
5525         test_form_action((IUnknown*)elem, NULL);
5526         test_form_put_action((IUnknown*)elem, "about:blank");
5527         test_form_method((IUnknown*)elem, "get");
5528         test_form_put_method((IUnknown*)elem, S_OK, "post");
5529         test_form_put_method((IUnknown*)elem, E_INVALIDARG, "put");
5530         test_form_method((IUnknown*)elem, "post");
5531         test_form_name((IUnknown*)elem, NULL);
5532         test_form_put_name((IUnknown*)elem, "Name");
5533         test_form_encoding((IUnknown*)elem, "application/x-www-form-urlencoded");
5534         test_form_put_encoding((IUnknown*)elem, S_OK, "text/plain");
5535         test_form_put_encoding((IUnknown*)elem, S_OK, "multipart/form-data");
5536         test_form_put_encoding((IUnknown*)elem, E_INVALIDARG, "image/png");
5537         test_form_encoding((IUnknown*)elem, "multipart/form-data");
5538         test_form_elements((IUnknown*)elem);
5539         IHTMLElement_Release(elem);
5540     }
5541
5542     test_attr(div);
5543     test_blocked(doc, div);
5544
5545     IHTMLElement_Release(div);
5546 }
5547
5548 static void test_create_elems(IHTMLDocument2 *doc)
5549 {
5550     IHTMLElement *elem, *body, *elem2;
5551     IHTMLDOMNode *node, *node2, *node3, *comment;
5552     IHTMLDocument5 *doc5;
5553     IDispatch *disp;
5554     VARIANT var;
5555     LONG type;
5556     HRESULT hres;
5557     BSTR str;
5558
5559     static const elem_type_t types1[] = { ET_TESTG };
5560
5561     elem = test_create_elem(doc, "TEST");
5562     test_elem_tag((IUnknown*)elem, "TEST");
5563     type = get_node_type((IUnknown*)elem);
5564     ok(type == 1, "type=%d\n", type);
5565     test_ifaces((IUnknown*)elem, elem_iids);
5566     test_disp((IUnknown*)elem, &DIID_DispHTMLGenericElement, "[object]");
5567
5568     body = doc_get_body(doc);
5569     test_node_has_child((IUnknown*)body, VARIANT_FALSE);
5570
5571     node = test_node_append_child((IUnknown*)body, (IUnknown*)elem);
5572     test_node_has_child((IUnknown*)body, VARIANT_TRUE);
5573     elem2 = get_elem_iface((IUnknown*)node);
5574     IHTMLElement_Release(elem2);
5575
5576     hres = IHTMLElement_get_all(body, &disp);
5577     ok(hres == S_OK, "get_all failed: %08x\n", hres);
5578     test_elem_collection((IUnknown*)disp, types1, sizeof(types1)/sizeof(types1[0]));
5579     IDispatch_Release(disp);
5580
5581     test_node_remove_child((IUnknown*)body, node);
5582
5583     hres = IHTMLElement_get_all(body, &disp);
5584     ok(hres == S_OK, "get_all failed: %08x\n", hres);
5585     test_elem_collection((IUnknown*)disp, NULL, 0);
5586     IDispatch_Release(disp);
5587     test_node_has_child((IUnknown*)body, VARIANT_FALSE);
5588
5589     IHTMLElement_Release(elem);
5590     IHTMLDOMNode_Release(node);
5591
5592     node = test_create_text(doc, "test");
5593     test_ifaces((IUnknown*)node, text_iids);
5594     test_disp((IUnknown*)node, &DIID_DispHTMLDOMTextNode, "[object]");
5595     test_text_length((IUnknown*)node, 4);
5596
5597     V_VT(&var) = VT_NULL;
5598     node2 = test_node_insertbefore((IUnknown*)body, node, &var);
5599     IHTMLDOMNode_Release(node);
5600
5601     node = test_create_text(doc, "insert ");
5602
5603     V_VT(&var) = VT_DISPATCH;
5604     V_DISPATCH(&var) = (IDispatch*)node2;
5605     node3 = test_node_insertbefore((IUnknown*)body, node, &var);
5606     IHTMLDOMNode_Release(node);
5607     IHTMLDOMNode_Release(node2);
5608     IHTMLDOMNode_Release(node3);
5609
5610     test_elem_innertext(body, "insert test");
5611     test_elem_innerhtml((IUnknown*)body, "insert test");
5612
5613     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5);
5614     if(hres == S_OK)
5615     {
5616         str = a2bstr("testing");
5617         hres = IHTMLDocument5_createComment(doc5, str, &comment);
5618         SysFreeString(str);
5619         ok(hres == S_OK, "createComment failed: %08x\n", hres);
5620         if(hres == S_OK)
5621         {
5622             type = get_node_type((IUnknown*)comment);
5623             ok(type == 8, "type=%d, expected 8\n", type);
5624
5625             test_node_get_value_str((IUnknown*)comment, "testing");
5626             test_elem_title((IUnknown*)comment, NULL);
5627             test_elem_set_title((IUnknown*)comment, "comment title");
5628             test_elem_title((IUnknown*)comment, "comment title");
5629             test_comment_text((IUnknown*)comment, "<!--testing-->");
5630             test_elem_outerhtml((IUnknown*)comment, "<!--testing-->");
5631             test_comment_attrs((IUnknown*)comment);
5632
5633             IHTMLDOMNode_Release(comment);
5634         }
5635
5636         IHTMLDocument5_Release(doc5);
5637     }
5638
5639     IHTMLElement_Release(body);
5640 }
5641
5642 static void test_replacechild_elems(IHTMLDocument2 *doc)
5643 {
5644     IHTMLElement *body;
5645     IHTMLDOMNode *node, *node2, *node3;
5646     IHTMLDOMNode *nodeBody, *nodeNew;
5647     HRESULT hres;
5648     VARIANT var;
5649
5650     body = doc_get_body(doc);
5651
5652     node = test_create_text(doc, "insert");
5653
5654     V_VT(&var) = VT_NULL;
5655     V_DISPATCH(&var) = NULL;
5656     node2 = test_node_insertbefore((IUnknown*)body, node, &var);
5657     IHTMLDOMNode_Release(node);
5658
5659     test_elem_innertext(body, "insert");
5660
5661     node3 = test_create_text(doc, "replaced");
5662
5663     nodeBody = _get_node_iface(__LINE__, (IUnknown *)body);
5664
5665     hres = IHTMLDOMNode_replaceChild(nodeBody, node3, node2, &nodeNew);
5666     ok(hres == S_OK, "Expected S_OK, got 0x%08x\n", hres);
5667
5668     test_elem_innertext(body, "replaced");
5669
5670     IHTMLDOMNode_Release(node2);
5671     IHTMLDOMNode_Release(node3);
5672     IHTMLDOMNode_Release(nodeBody);
5673
5674     IHTMLElement_Release(body);
5675 }
5676
5677 static void test_null_write(IHTMLDocument2 *doc)
5678 {
5679     HRESULT hres;
5680
5681     doc_write(doc, FALSE, NULL);
5682     doc_write(doc, TRUE, NULL);
5683
5684     hres = IHTMLDocument2_write(doc, NULL);
5685     ok(hres == S_OK,
5686        "Expected IHTMLDocument2::write to return S_OK, got 0x%08x\n", hres);
5687
5688     hres = IHTMLDocument2_writeln(doc, NULL);
5689     ok(hres == S_OK,
5690        "Expected IHTMLDocument2::writeln to return S_OK, got 0x%08x\n", hres);
5691 }
5692
5693 static void test_exec(IUnknown *unk, const GUID *grpid, DWORD cmdid, VARIANT *in, VARIANT *out)
5694 {
5695     IOleCommandTarget *cmdtrg;
5696     HRESULT hres;
5697
5698     hres = IHTMLTxtRange_QueryInterface(unk, &IID_IOleCommandTarget, (void**)&cmdtrg);
5699     ok(hres == S_OK, "Could not get IOleCommandTarget interface: %08x\n", hres);
5700
5701     hres = IOleCommandTarget_Exec(cmdtrg, grpid, cmdid, 0, in, out);
5702     ok(hres == S_OK, "Exec failed: %08x\n", hres);
5703
5704     IOleCommandTarget_Release(cmdtrg);
5705 }
5706
5707 static void test_indent(IHTMLDocument2 *doc)
5708 {
5709     IHTMLElementCollection *col;
5710     IHTMLTxtRange *range;
5711     HRESULT hres;
5712
5713     static const elem_type_t all_types[] = {
5714         ET_HTML,
5715         ET_HEAD,
5716         ET_TITLE,
5717         ET_BODY,
5718         ET_BR,
5719         ET_A,
5720     };
5721
5722     static const elem_type_t indent_types[] = {
5723         ET_HTML,
5724         ET_HEAD,
5725         ET_TITLE,
5726         ET_BODY,
5727         ET_BLOCKQUOTE,
5728         ET_P,
5729         ET_BR,
5730         ET_A,
5731     };
5732
5733     hres = IHTMLDocument2_get_all(doc, &col);
5734     ok(hres == S_OK, "get_all failed: %08x\n", hres);
5735     test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
5736     IHTMLElementCollection_Release(col);
5737
5738     range = test_create_body_range(doc);
5739     test_exec((IUnknown*)range, &CGID_MSHTML, IDM_INDENT, NULL, NULL);
5740     IHTMLTxtRange_Release(range);
5741
5742     hres = IHTMLDocument2_get_all(doc, &col);
5743     ok(hres == S_OK, "get_all failed: %08x\n", hres);
5744     test_elem_collection((IUnknown*)col, indent_types, sizeof(indent_types)/sizeof(indent_types[0]));
5745     IHTMLElementCollection_Release(col);
5746 }
5747
5748 static void test_cond_comment(IHTMLDocument2 *doc)
5749 {
5750     IHTMLElementCollection *col;
5751     HRESULT hres;
5752
5753     static const elem_type_t all_types[] = {
5754         ET_HTML,
5755         ET_HEAD,
5756         ET_TITLE,
5757         ET_BODY,
5758         ET_BR
5759     };
5760
5761     hres = IHTMLDocument2_get_all(doc, &col);
5762     ok(hres == S_OK, "get_all failed: %08x\n", hres);
5763     test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
5764     IHTMLElementCollection_Release(col);
5765 }
5766
5767 static void test_frame(IDispatch *disp, const char *exp_id)
5768 {
5769     IHTMLWindow2 *frame2, *parent, *top;
5770     IHTMLDocument2 *parent_doc, *top_doc;
5771     IHTMLWindow4 *frame;
5772     IHTMLFrameBase *frame_elem;
5773     HRESULT hres;
5774
5775     hres = IDispatch_QueryInterface(disp, &IID_IHTMLWindow4, (void**)&frame);
5776     ok(hres == S_OK, "Could not get IHTMLWindow4 interface: 0x%08x\n", hres);
5777     if(FAILED(hres))
5778         return;
5779
5780     hres = IHTMLWindow4_get_frameElement(frame, &frame_elem);
5781     ok(hres == S_OK, "IHTMLWindow4_get_frameElement failed: 0x%08x\n", hres);
5782     IHTMLWindow4_Release(frame);
5783     if(FAILED(hres))
5784         return;
5785
5786     test_elem_type((IUnknown*)frame_elem, ET_FRAME);
5787     test_frame_doc((IUnknown*)frame_elem, FALSE);
5788     test_elem_id((IUnknown*)frame_elem, exp_id);
5789     IHTMLElement_Release(frame_elem);
5790
5791     hres = IDispatch_QueryInterface(disp, &IID_IHTMLWindow2, (void**)&frame2);
5792     ok(hres == S_OK, "Could not get IHTMLWindow2 interface: 0x%08x\n", hres);
5793     if(FAILED(hres))
5794         return;
5795
5796     hres = IHTMLWindow2_get_parent(frame2, &parent);
5797     ok(hres == S_OK, "IHTMLWindow2_get_parent failed: 0x%08x\n", hres);
5798     if(FAILED(hres)){
5799         IHTMLWindow2_Release(frame2);
5800         return;
5801     }
5802
5803     hres = IHTMLWindow2_get_document(parent, &parent_doc);
5804     ok(hres == S_OK, "IHTMLWindow2_get_document failed: 0x%08x\n", hres);
5805     IHTMLWindow2_Release(parent);
5806     if(FAILED(hres)){
5807         IHTMLWindow2_Release(frame2);
5808         return;
5809     }
5810
5811     test_doc_title(parent_doc, "frameset test");
5812     IHTMLDocument2_Release(parent_doc);
5813
5814     /* test get_top */
5815     hres = IHTMLWindow2_get_top(frame2, &top);
5816     ok(hres == S_OK, "IHTMLWindow2_get_top failed: 0x%08x\n", hres);
5817     IHTMLWindow2_Release(frame2);
5818     if(FAILED(hres))
5819         return;
5820
5821     hres = IHTMLWindow2_get_document(top, &top_doc);
5822     ok(hres == S_OK, "IHTMLWindow2_get_document failed: 0x%08x\n", hres);
5823     IHTMLWindow2_Release(top);
5824     if(FAILED(hres))
5825         return;
5826
5827     test_doc_title(top_doc, "frameset test");
5828     IHTMLDocument2_Release(top_doc);
5829 }
5830
5831 static void test_frameset(IHTMLDocument2 *doc)
5832 {
5833     IHTMLWindow2 *window;
5834     IHTMLFramesCollection2 *frames;
5835     IHTMLElement *elem;
5836     IHTMLFrameBase *fbase;
5837     LONG length;
5838     VARIANT index_var, result_var;
5839     BSTR str;
5840     HRESULT hres;
5841
5842     window = get_doc_window(doc);
5843
5844     /* test using IHTMLFramesCollection object */
5845
5846     hres = IHTMLWindow2_get_frames(window, &frames);
5847     ok(hres == S_OK, "IHTMLWindow2_get_frames failed: 0x%08x\n", hres);
5848     IHTMLWindow2_Release(window);
5849     if(FAILED(hres))
5850         return;
5851
5852     /* test result length */
5853     hres = IHTMLFramesCollection2_get_length(frames, &length);
5854     ok(hres == S_OK, "IHTMLFramesCollection2_get_length failed: 0x%08x\n", hres);
5855     ok(length == 3, "IHTMLFramesCollection2_get_length should have been 3, was: %d\n", length);
5856
5857     /* test first frame */
5858     V_VT(&index_var) = VT_I4;
5859     V_I4(&index_var) = 0;
5860     hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var);
5861     ok(hres == S_OK, "IHTMLFramesCollection2_item failed: 0x%08x\n", hres);
5862     if(SUCCEEDED(hres)) {
5863         ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var));
5864         test_frame((IDispatch*)V_DISPATCH(&result_var), "fr1");
5865     }
5866     VariantClear(&result_var);
5867
5868     /* test second frame */
5869     V_I4(&index_var) = 1;
5870     hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var);
5871     ok(hres == S_OK, "IHTMLFramesCollection2_item failed: 0x%08x\n", hres);
5872     if(SUCCEEDED(hres)) {
5873         ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var));
5874         test_frame((IDispatch*)V_DISPATCH(&result_var), "fr2");
5875     }
5876     VariantClear(&result_var);
5877
5878     /* fail on next frame */
5879     V_I4(&index_var) = 3;
5880     hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var);
5881     ok(hres == DISP_E_MEMBERNOTFOUND, "IHTMLFramesCollection2_item should have"
5882            "failed with DISP_E_MEMBERNOTFOUND, instead: 0x%08x\n", hres);
5883     VariantClear(&result_var);
5884
5885     /* string argument (element id lookup) */
5886     V_VT(&index_var) = VT_BSTR;
5887     V_BSTR(&index_var) = a2bstr("fr1");
5888     hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var);
5889     ok(hres == S_OK, "IHTMLFramesCollection2_item failed: 0x%08x\n", hres);
5890     if(SUCCEEDED(hres)) {
5891         ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var));
5892         test_frame(V_DISPATCH(&result_var), "fr1");
5893     }
5894     VariantClear(&result_var);
5895     VariantClear(&index_var);
5896
5897     /* invalid argument */
5898     V_VT(&index_var) = VT_BOOL;
5899     V_BOOL(&index_var) = VARIANT_TRUE;
5900     hres = IHTMLFramesCollection2_item(frames, &index_var, &result_var);
5901     ok(hres == E_INVALIDARG, "IHTMLFramesCollection2_item should have"
5902            "failed with E_INVALIDARG, instead: 0x%08x\n", hres);
5903     VariantClear(&result_var);
5904
5905     IHTMLFramesCollection2_Release(frames);
5906
5907     /* test using IHTMLWindow2 inheritance */
5908
5909     /* test result length */
5910     hres = IHTMLWindow2_get_length(window, &length);
5911     ok(hres == S_OK, "IHTMLWindow2_get_length failed: 0x%08x\n", hres);
5912     ok(length == 3, "IHTMLWindow2_get_length should have been 3, was: %d\n", length);
5913
5914     /* test first frame */
5915     V_VT(&index_var) = VT_I4;
5916     V_I4(&index_var) = 0;
5917     hres = IHTMLWindow2_item(window, &index_var, &result_var);
5918     ok(hres == S_OK, "IHTMLWindow2_item failed: 0x%08x\n", hres);
5919     if(SUCCEEDED(hres)) {
5920         ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var));
5921         test_frame((IDispatch*)V_DISPATCH(&result_var), "fr1");
5922     }
5923     VariantClear(&result_var);
5924
5925     /* test second frame */
5926     V_I4(&index_var) = 1;
5927     hres = IHTMLWindow2_item(window, &index_var, &result_var);
5928     ok(hres == S_OK, "IHTMLWindow2_item failed: 0x%08x\n", hres);
5929     if(SUCCEEDED(hres)) {
5930         ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var));
5931         test_frame((IDispatch*)V_DISPATCH(&result_var), "fr2");
5932     }
5933     VariantClear(&result_var);
5934
5935     /* fail on next frame */
5936     V_I4(&index_var) = 3;
5937     hres = IHTMLWindow2_item(window, &index_var, &result_var);
5938     ok(hres == DISP_E_MEMBERNOTFOUND, "IHTMLWindow2_item should have"
5939            "failed with DISP_E_MEMBERNOTFOUND, instead: 0x%08x\n", hres);
5940     VariantClear(&result_var);
5941
5942     /* string argument (element id lookup) */
5943     V_VT(&index_var) = VT_BSTR;
5944     V_BSTR(&index_var) = a2bstr("fr2");
5945     hres = IHTMLWindow2_item(window, &index_var, &result_var);
5946     ok(hres == S_OK, "IHTMLWindow2_item failed: 0x%08x\n", hres);
5947     if(SUCCEEDED(hres)) {
5948         ok(V_VT(&result_var) == VT_DISPATCH, "result type should have been VT_DISPATCH, was: 0x%x\n", V_VT(&result_var));
5949         test_frame((IDispatch*)V_DISPATCH(&result_var), "fr2");
5950     }
5951     VariantClear(&result_var);
5952     VariantClear(&index_var);
5953
5954     /* invalid argument */
5955     V_VT(&index_var) = VT_BOOL;
5956     V_BOOL(&index_var) = VARIANT_TRUE;
5957     hres = IHTMLWindow2_item(window, &index_var, &result_var);
5958     ok(hres == E_INVALIDARG, "IHTMLWindow2_item should have"
5959            "failed with E_INVALIDARG, instead: 0x%08x\n", hres);
5960     VariantClear(&result_var);
5961
5962     /* getElementById with node name attributes */
5963     elem = get_doc_elem_by_id(doc, "nm1");
5964     test_elem_id((IUnknown*)elem, "fr1");
5965
5966     /* get/put scrolling */
5967     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFrameBase, (void**)&fbase);
5968     ok(hres == S_OK, "Could not get IHTMLFrameBase interface: 0x%08x\n", hres);
5969
5970     hres = IHTMLFrameBase_get_scrolling(fbase, &str);
5971     ok(hres == S_OK, "IHTMLFrameBase_get_scrolling failed: 0x%08x\n", hres);
5972     ok(!strcmp_wa(str, "auto"), "get_scrolling should have given 'auto', gave: %s\n", wine_dbgstr_w(str));
5973     SysFreeString(str);
5974
5975     str = a2bstr("no");
5976     hres = IHTMLFrameBase_put_scrolling(fbase, str);
5977     ok(hres == S_OK, "IHTMLFrameBase_put_scrolling failed: 0x%08x\n", hres);
5978     SysFreeString(str);
5979
5980     hres = IHTMLFrameBase_get_scrolling(fbase, &str);
5981     ok(hres == S_OK, "IHTMLFrameBase_get_scrolling failed: 0x%08x\n", hres);
5982     ok(!strcmp_wa(str, "no"), "get_scrolling should have given 'no', gave: %s\n", wine_dbgstr_w(str));
5983     SysFreeString(str);
5984
5985     str = a2bstr("junk");
5986     hres = IHTMLFrameBase_put_scrolling(fbase, str);
5987     ok(hres == E_INVALIDARG, "IHTMLFrameBase_put_scrolling should have failed "
5988             "with E_INVALIDARG, instead: 0x%08x\n", hres);
5989     SysFreeString(str);
5990
5991     hres = IHTMLFrameBase_get_scrolling(fbase, &str);
5992     ok(hres == S_OK, "IHTMLFrameBase_get_scrolling failed: 0x%08x\n", hres);
5993     ok(!strcmp_wa(str, "no"), "get_scrolling should have given 'no', gave: %s\n", wine_dbgstr_w(str));
5994     SysFreeString(str);
5995
5996     /* get_name */
5997     hres = IHTMLFrameBase_get_name(fbase, &str);
5998     ok(hres == S_OK, "IHTMLFrameBase_get_name failed: 0x%08x\n", hres);
5999     ok(!strcmp_wa(str, "nm1"), "get_name should have given 'nm1', gave: %s\n", wine_dbgstr_w(str));
6000     SysFreeString(str);
6001
6002     IHTMLFrameBase_Release(fbase);
6003     IHTMLElement_Release(elem);
6004
6005     /* get_name with no name attr */
6006     elem = get_doc_elem_by_id(doc, "fr3");
6007     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFrameBase, (void**)&fbase);
6008     ok(hres == S_OK, "Could not get IHTMLFrameBase interface: 0x%08x\n", hres);
6009
6010     hres = IHTMLFrameBase_get_name(fbase, &str);
6011     ok(hres == S_OK, "IHTMLFrameBase_get_name failed: 0x%08x\n", hres);
6012     ok(str == NULL, "get_name should have given 'null', gave: %s\n", wine_dbgstr_w(str));
6013     SysFreeString(str);
6014
6015     IHTMLFrameBase_Release(fbase);
6016     IHTMLElement_Release(elem);
6017 }
6018
6019 static IHTMLDocument2 *create_docfrag(IHTMLDocument2 *doc)
6020 {
6021     IHTMLDocument2 *frag;
6022     IHTMLDocument3 *doc3;
6023     HRESULT hres;
6024
6025     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
6026     ok(hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres);
6027
6028     hres = IHTMLDocument3_createDocumentFragment(doc3, &frag);
6029     IHTMLDocument3_Release(doc3);
6030     ok(hres == S_OK, "createDocumentFragment failed: %08x\n", hres);
6031     ok(frag != NULL, "frag == NULL\n");
6032
6033     return frag;
6034 }
6035
6036 static void test_docfrag(IHTMLDocument2 *doc)
6037 {
6038     IHTMLElement *div, *body, *br;
6039     IHTMLElementCollection *col;
6040     IHTMLLocation *location;
6041     IHTMLDocument2 *frag;
6042     HRESULT hres;
6043
6044     static const elem_type_t all_types[] = {
6045         ET_HTML,
6046         ET_HEAD,
6047         ET_TITLE,
6048         ET_BODY,
6049         ET_DIV,
6050         ET_BR
6051     };
6052
6053     frag = create_docfrag(doc);
6054
6055     test_disp((IUnknown*)frag, &DIID_DispHTMLDocument, "[object]");
6056
6057     body = (void*)0xdeadbeef;
6058     hres = IHTMLDocument2_get_body(frag, &body);
6059     ok(hres == S_OK, "get_body failed: %08x\n", hres);
6060     ok(!body, "body != NULL\n");
6061
6062     location = (void*)0xdeadbeef;
6063     hres = IHTMLDocument2_get_location(frag, &location);
6064     ok(hres == E_UNEXPECTED, "get_location failed: %08x\n", hres);
6065     ok(location == (void*)0xdeadbeef, "location changed\n");
6066
6067     br = test_create_elem(doc, "BR");
6068     test_node_append_child((IUnknown*)frag, (IUnknown*)br);
6069     IHTMLElement_Release(br);
6070
6071     div = get_elem_by_id(doc, "divid", TRUE);
6072     test_node_append_child((IUnknown*)div, (IUnknown*)frag);
6073     IHTMLElement_Release(div);
6074
6075     hres = IHTMLDocument2_get_all(doc, &col);
6076     ok(hres == S_OK, "get_all failed: %08x\n", hres);
6077     test_elem_collection((IUnknown*)col, all_types, sizeof(all_types)/sizeof(all_types[0]));
6078     IHTMLElementCollection_Release(col);
6079
6080     IHTMLDocument2_Release(frag);
6081 }
6082
6083 static IHTMLDocument2 *notif_doc;
6084 static BOOL doc_complete;
6085
6086 static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
6087         REFIID riid, void**ppv)
6088 {
6089     if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
6090         *ppv = iface;
6091         return S_OK;
6092     }
6093
6094     ok(0, "unexpected call\n");
6095     return E_NOINTERFACE;
6096 }
6097
6098 static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface)
6099 {
6100     return 2;
6101 }
6102
6103 static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface)
6104 {
6105     return 1;
6106 }
6107
6108 static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
6109 {
6110     if(dispID == DISPID_READYSTATE){
6111         BSTR state;
6112         HRESULT hres;
6113
6114         hres = IHTMLDocument2_get_readyState(notif_doc, &state);
6115         ok(hres == S_OK, "get_readyState failed: %08x\n", hres);
6116
6117         if(!strcmp_wa(state, "complete"))
6118             doc_complete = TRUE;
6119
6120         SysFreeString(state);
6121     }
6122
6123     return S_OK;
6124 }
6125
6126 static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
6127 {
6128     ok(0, "unexpected call\n");
6129     return E_NOTIMPL;
6130 }
6131
6132 static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
6133     PropertyNotifySink_QueryInterface,
6134     PropertyNotifySink_AddRef,
6135     PropertyNotifySink_Release,
6136     PropertyNotifySink_OnChanged,
6137     PropertyNotifySink_OnRequestEdit
6138 };
6139
6140 static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl };
6141
6142 static IHTMLDocument2 *create_doc_with_string(const char *str)
6143 {
6144     IPersistStreamInit *init;
6145     IStream *stream;
6146     IHTMLDocument2 *doc;
6147     HGLOBAL mem;
6148     SIZE_T len;
6149
6150     notif_doc = doc = create_document();
6151     if(!doc)
6152         return NULL;
6153
6154     doc_complete = FALSE;
6155     len = strlen(str);
6156     mem = GlobalAlloc(0, len);
6157     memcpy(mem, str, len);
6158     CreateStreamOnHGlobal(mem, TRUE, &stream);
6159
6160     IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init);
6161
6162     IPersistStreamInit_Load(init, stream);
6163     IPersistStreamInit_Release(init);
6164     IStream_Release(stream);
6165
6166     return doc;
6167 }
6168
6169 static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise)
6170 {
6171     IConnectionPointContainer *container;
6172     IConnectionPoint *cp;
6173     DWORD cookie;
6174     HRESULT hres;
6175
6176     hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
6177     ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
6178
6179     hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp);
6180     IConnectionPointContainer_Release(container);
6181     ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
6182
6183     hres = IConnectionPoint_Advise(cp, unk_advise, &cookie);
6184     IConnectionPoint_Release(cp);
6185     ok(hres == S_OK, "Advise failed: %08x\n", hres);
6186 }
6187
6188 typedef void (*domtest_t)(IHTMLDocument2*);
6189
6190 static void run_domtest(const char *str, domtest_t test)
6191 {
6192     IHTMLDocument2 *doc;
6193     ULONG ref;
6194     MSG msg;
6195
6196     doc = create_doc_with_string(str);
6197     if(!doc)
6198         return;
6199
6200     do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
6201
6202     while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) {
6203         TranslateMessage(&msg);
6204         DispatchMessage(&msg);
6205     }
6206
6207     test(doc);
6208
6209     ref = IHTMLDocument2_Release(doc);
6210     ok(!ref || broken(ref == 1), /* Vista */
6211        "ref = %d\n", ref);
6212 }
6213
6214 START_TEST(dom)
6215 {
6216     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
6217     pLCIDToLocaleName = (void*)GetProcAddress(hkernel32, "LCIDToLocaleName");
6218     pGetUserDefaultUILanguage = (void*)GetProcAddress(hkernel32, "GetUserDefaultUILanguage");
6219
6220     CoInitialize(NULL);
6221
6222     run_domtest(doc_str1, test_doc_elem);
6223     run_domtest(doc_str1, test_get_set_attr);
6224     run_domtest(range_test_str, test_txtrange);
6225     run_domtest(range_test2_str, test_txtrange2);
6226     if (winetest_interactive || ! is_ie_hardened()) {
6227         run_domtest(elem_test_str, test_elems);
6228         run_domtest(elem_test2_str, test_elems2);
6229     }else {
6230         skip("IE running in Enhanced Security Configuration\n");
6231     }
6232     run_domtest(doc_blank, test_create_elems);
6233     run_domtest(doc_blank, test_defaults);
6234     run_domtest(doc_blank, test_null_write);
6235     run_domtest(indent_test_str, test_indent);
6236     run_domtest(cond_comment_str, test_cond_comment);
6237     run_domtest(frameset_str, test_frameset);
6238     run_domtest(emptydiv_str, test_docfrag);
6239     run_domtest(doc_blank, test_replacechild_elems);
6240
6241     CoUninitialize();
6242 }