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