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