comctl32: Monthcal should send notifications when today link gets clicked.
[wine] / dlls / mshtml / tests / dom.c
1 /*
2  * Copyright 2007 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 "docobj.h"
31
32 static const char doc_blank[] = "<html></html>";
33 static const char doc_str1[] = "<html><body>test</body></html>";
34 static const char doc_str2[] =
35     "<html><body>test a<font size=\"2\">bc 123<br />it's </font>text<br /></body></html>";
36 static const char doc_str3[] =
37     "<html><head><title>test</title><body>"
38     "<a href=\"http://test\" name=\"x\">link</a><input />"
39     "<select id=\"s\"><option id=\"x\">opt1</option><option id=\"y\">opt2</option></select>"
40     "<textarea id=\"X\">text text</textarea>"
41     "</body></html>";
42
43 static const WCHAR noneW[] = {'N','o','n','e',0};
44
45 static WCHAR characterW[] = {'c','h','a','r','a','c','t','e','r',0};
46 static WCHAR wordW[] = {'w','o','r','d',0};
47
48 typedef enum {
49     ET_NONE,
50     ET_HTML,
51     ET_HEAD,
52     ET_TITLE,
53     ET_BODY,
54     ET_A,
55     ET_INPUT,
56     ET_SELECT,
57     ET_TEXTAREA,
58     ET_OPTION
59 } elem_type_t;
60
61 static const REFIID none_iids[] = {
62     &IID_IUnknown,
63     NULL
64 };
65
66 static const REFIID html_iids[] = {
67     &IID_IHTMLDOMNode,
68     &IID_IHTMLElement,
69     &IID_IHTMLElement2,
70     NULL
71 };
72
73 static const REFIID head_iids[] = {
74     &IID_IHTMLDOMNode,
75     &IID_IHTMLElement,
76     &IID_IHTMLElement2,
77     NULL
78 };
79
80 static const REFIID title_iids[] = {
81     &IID_IHTMLDOMNode,
82     &IID_IHTMLElement,
83     &IID_IHTMLElement2,
84     NULL
85 };
86
87 static const REFIID body_iids[] = {
88     &IID_IHTMLDOMNode,
89     &IID_IHTMLElement,
90     &IID_IHTMLElement2,
91     &IID_IHTMLTextContainer,
92     &IID_IHTMLBodyElement,
93     NULL
94 };
95
96 static const REFIID anchor_iids[] = {
97     &IID_IHTMLDOMNode,
98     &IID_IHTMLElement,
99     &IID_IHTMLElement2,
100     &IID_IHTMLAnchorElement,
101     NULL
102 };
103
104 static const REFIID input_iids[] = {
105     &IID_IHTMLDOMNode,
106     &IID_IHTMLElement,
107     &IID_IHTMLElement2,
108     &IID_IHTMLInputElement,
109     &IID_IHTMLInputTextElement,
110     NULL
111 };
112
113 static const REFIID select_iids[] = {
114     &IID_IHTMLDOMNode,
115     &IID_IHTMLElement,
116     &IID_IHTMLElement2,
117     &IID_IHTMLSelectElement,
118     NULL
119 };
120
121 static const REFIID textarea_iids[] = {
122     &IID_IHTMLDOMNode,
123     &IID_IHTMLElement,
124     &IID_IHTMLElement2,
125     &IID_IHTMLTextAreaElement,
126     NULL
127 };
128
129 static const REFIID option_iids[] = {
130     &IID_IHTMLDOMNode,
131     &IID_IHTMLElement,
132     &IID_IHTMLElement2,
133     &IID_IHTMLOptionElement,
134     NULL
135 };
136
137 typedef struct {
138     const char *tag;
139     REFIID *iids;
140 } elem_type_info_t;
141
142 static const elem_type_info_t elem_type_infos[] = {
143     {"",          none_iids},
144     {"HTML",      html_iids},
145     {"HEAD",      head_iids},
146     {"TITLE",     title_iids},
147     {"BODY",      body_iids},
148     {"A",         anchor_iids},
149     {"INPUT",     input_iids},
150     {"SELECT",    select_iids},
151     {"TEXTAREA",  textarea_iids},
152     {"OPTION",    option_iids}
153 };
154
155 static const char *dbgstr_w(LPCWSTR str)
156 {
157     static char buf[512];
158     if(!str)
159         return "(null)";
160     WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
161     return buf;
162 }
163
164 static const char *dbgstr_guid(REFIID riid)
165 {
166     static char buf[50];
167
168     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
169             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
170             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
171             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
172
173     return buf;
174 }
175
176 static int strcmp_wa(LPCWSTR strw, const char *stra)
177 {
178     WCHAR buf[512];
179     MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
180     return lstrcmpW(strw, buf);
181 }
182
183 static BSTR a2bstr(const char *str)
184 {
185     BSTR ret;
186     int len;
187
188     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
189     ret = SysAllocStringLen(NULL, len);
190     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
191
192     return ret;
193 }
194
195 static IHTMLDocument2 *create_document(void)
196 {
197     IHTMLDocument2 *doc;
198     HRESULT hres;
199
200     hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
201             &IID_IHTMLDocument2, (void**)&doc);
202     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
203
204     return doc;
205 }
206
207 #define test_ifaces(i,ids) _test_ifaces(__LINE__,i,ids)
208 static void _test_ifaces(unsigned line, IUnknown *iface, REFIID *iids)
209 {
210     const IID * const *piid;
211     IUnknown *unk;
212     HRESULT hres;
213
214      for(piid = iids; *piid; piid++) {
215         hres = IDispatch_QueryInterface(iface, *piid, (void**)&unk);
216         ok_(__FILE__,line) (hres == S_OK, "Could not get %s interface: %08x\n", dbgstr_guid(*piid), hres);
217         if(SUCCEEDED(hres))
218             IUnknown_Release(unk);
219     }
220 }
221
222 #define test_node_name(u,n) _test_node_name(__LINE__,u,n)
223 static void _test_node_name(unsigned line, IUnknown *unk, const char *exname)
224 {
225     IHTMLDOMNode *node;
226     BSTR name;
227     HRESULT hres;
228
229     hres = IUnknown_QueryInterface(unk, &IID_IHTMLDOMNode, (void**)&node);
230     ok_(__FILE__, line) (hres == S_OK, "QueryInterface(IID_IHTMLNode) failed: %08x\n", hres);
231
232     hres = IHTMLDOMNode_get_nodeName(node, &name);
233     IHTMLDOMNode_Release(node);
234     ok_(__FILE__, line) (hres == S_OK, "get_nodeName failed: %08x\n", hres);
235     ok_(__FILE__, line) (!strcmp_wa(name, exname), "got name: %s, expected %s\n", dbgstr_w(name), exname);
236
237     SysFreeString(name);
238 }
239
240 #define test_elem_tag(u,n) _test_elem_tag(__LINE__,u,n)
241 static void _test_elem_tag(unsigned line, IUnknown *unk, const char *extag)
242 {
243     IHTMLElement *elem;
244     BSTR tag;
245     HRESULT hres;
246
247     hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement, (void**)&elem);
248     ok_(__FILE__, line) (hres == S_OK, "QueryInterface(IID_IHTMLElement) failed: %08x\n", hres);
249
250     hres = IHTMLElement_get_tagName(elem, &tag);
251     IHTMLElement_Release(elem);
252     ok_(__FILE__, line) (hres == S_OK, "get_tagName failed: %08x\n", hres);
253     ok_(__FILE__, line) (!strcmp_wa(tag, extag), "got tag: %s, expected %s\n", dbgstr_w(tag), extag);
254
255     SysFreeString(tag);
256 }
257
258 #define test_elem_type(ifc,t) _test_elem_type(__LINE__,ifc,t)
259 static void _test_elem_type(unsigned line, IUnknown *unk, elem_type_t type)
260 {
261     _test_elem_tag(line, unk, elem_type_infos[type].tag);
262     _test_ifaces(line, unk, elem_type_infos[type].iids);
263 }
264
265 static void test_doc_elem(IHTMLDocument2 *doc)
266 {
267     IHTMLElement *elem;
268     IHTMLDocument3 *doc3;
269     HRESULT hres;
270
271     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
272     ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08x\n", hres);
273
274     hres = IHTMLDocument3_get_documentElement(doc3, &elem);
275     IHTMLDocument3_Release(doc3);
276     ok(hres == S_OK, "get_documentElement failed: %08x\n", hres);
277
278     test_node_name((IUnknown*)elem, "HTML");
279     test_elem_tag((IUnknown*)elem, "HTML");
280
281     IHTMLElement_Release(elem);
282 }
283
284 #define get_doc_elem(d) _get_doc_elem(__LINE__,d)
285 static IHTMLElement *_get_doc_elem(unsigned line, IHTMLDocument2 *doc)
286 {
287     IHTMLElement *elem;
288     IHTMLDocument3 *doc3;
289     HRESULT hres;
290
291     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
292     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDocument3 interface: %08x\n", hres);
293     hres = IHTMLDocument3_get_documentElement(doc3, &elem);
294     ok_(__FILE__,line) (hres == S_OK, "get_documentElement failed: %08x\n", hres);
295     IHTMLDocument3_Release(doc3);
296
297     return elem;
298 }
299
300 #define test_option_text(o,t) _test_option_text(__LINE__,o,t)
301 static void _test_option_text(unsigned line, IHTMLOptionElement *option, const char *text)
302 {
303     BSTR bstr;
304     HRESULT hres;
305
306     hres = IHTMLOptionElement_get_text(option, &bstr);
307     ok_(__FILE__,line) (hres == S_OK, "get_text failed: %08x\n", hres);
308     ok_(__FILE__,line) (!strcmp_wa(bstr, text), "text=%s\n", dbgstr_w(bstr));
309     SysFreeString(bstr);
310 }
311
312 #define test_option_put_text(o,t) _test_option_put_text(__LINE__,o,t)
313 static void _test_option_put_text(unsigned line, IHTMLOptionElement *option, const char *text)
314 {
315     BSTR bstr;
316     HRESULT hres;
317
318     bstr = a2bstr(text);
319     hres = IHTMLOptionElement_put_text(option, bstr);
320     SysFreeString(bstr);
321     ok(hres == S_OK, "put_text failed: %08x\n", hres);
322
323     _test_option_text(line, option, text);
324 }
325
326 #define test_option_value(o,t) _test_option_value(__LINE__,o,t)
327 static void _test_option_value(unsigned line, IHTMLOptionElement *option, const char *value)
328 {
329     BSTR bstr;
330     HRESULT hres;
331
332     hres = IHTMLOptionElement_get_value(option, &bstr);
333     ok_(__FILE__,line) (hres == S_OK, "get_value failed: %08x\n", hres);
334     ok_(__FILE__,line) (!strcmp_wa(bstr, value), "value=%s\n", dbgstr_w(bstr));
335     SysFreeString(bstr);
336 }
337
338 #define test_option_put_value(o,t) _test_option_put_value(__LINE__,o,t)
339 static void _test_option_put_value(unsigned line, IHTMLOptionElement *option, const char *value)
340 {
341     BSTR bstr;
342     HRESULT hres;
343
344     bstr = a2bstr(value);
345     hres = IHTMLOptionElement_put_value(option, bstr);
346     SysFreeString(bstr);
347     ok(hres == S_OK, "put_value failed: %08x\n", hres);
348
349     _test_option_value(line, option, value);
350 }
351
352 #define create_option_elem(d,t,v) _create_option_elem(__LINE__,d,t,v)
353 static IHTMLOptionElement *_create_option_elem(unsigned line, IHTMLDocument2 *doc,
354         const char *txt, const char *val)
355 {
356     IHTMLOptionElementFactory *factory;
357     IHTMLOptionElement *option;
358     IHTMLWindow2 *window;
359     VARIANT text, value, empty;
360     HRESULT hres;
361
362     hres = IHTMLDocument2_get_parentWindow(doc, &window);
363     ok_(__FILE__,line) (hres == S_OK, "get_parentElement failed: %08x\n", hres);
364
365     hres = IHTMLWindow2_get_Option(window, &factory);
366     IHTMLWindow2_Release(window);
367     ok_(__FILE__,line) (hres == S_OK, "get_Option failed: %08x\n", hres);
368
369     V_VT(&text) = VT_BSTR;
370     V_BSTR(&text) = a2bstr(txt);
371     V_VT(&value) = VT_BSTR;
372     V_BSTR(&value) = a2bstr(val);
373     V_VT(&empty) = VT_EMPTY;
374
375     hres = IHTMLOptionElementFactory_create(factory, text, value, empty, empty, &option);
376     ok_(__FILE__,line) (hres == S_OK, "create failed: %08x\n", hres);
377
378     IHTMLOptionElementFactory_Release(factory);
379     VariantClear(&text);
380     VariantClear(&value);
381
382     _test_option_text(line, option, txt);
383     _test_option_value(line, option, val);
384
385     return option;
386 }
387
388 #define test_select_length(s,l) _test_select_length(__LINE__,s,l)
389 static void _test_select_length(unsigned line, IHTMLSelectElement *select, long length)
390 {
391     long len = 0xdeadbeef;
392     HRESULT hres;
393
394     hres = IHTMLSelectElement_get_length(select, &len);
395     ok_(__FILE__,line) (hres == S_OK, "get_length failed: %08x\n", hres);
396     ok_(__FILE__,line) (len == length, "len=%ld, expected %ld\n", len, length);
397 }
398
399 #define test_select_selidx(s,i) _test_select_selidx(__LINE__,s,i)
400 static void _test_select_selidx(unsigned line, IHTMLSelectElement *select, long index)
401 {
402     long idx = 0xdeadbeef;
403     HRESULT hres;
404
405     hres = IHTMLSelectElement_get_selectedIndex(select, &idx);
406     ok_(__FILE__,line) (hres == S_OK, "get_selectedIndex failed: %08x\n", hres);
407     ok_(__FILE__,line) (idx == index, "idx=%ld, expected %ld\n", idx, index);
408 }
409
410 #define test_select_put_selidx(s,i) _test_select_put_selidx(__LINE__,s,i)
411 static void _test_select_put_selidx(unsigned line, IHTMLSelectElement *select, long index)
412 {
413     HRESULT hres;
414
415     hres = IHTMLSelectElement_put_selectedIndex(select, index);
416     ok_(__FILE__,line) (hres == S_OK, "get_selectedIndex failed: %08x\n", hres);
417     _test_select_selidx(line, select, index);
418 }
419
420 #define test_range_text(r,t) _test_range_text(__LINE__,r,t)
421 static void _test_range_text(unsigned line, IHTMLTxtRange *range, const char *extext)
422 {
423     BSTR text;
424     HRESULT hres;
425
426     hres = IHTMLTxtRange_get_text(range, &text);
427     ok_(__FILE__, line) (hres == S_OK, "get_text failed: %08x\n", hres);
428
429     if(extext) {
430         ok_(__FILE__, line) (text != NULL, "text == NULL\n");
431         ok_(__FILE__, line) (!strcmp_wa(text, extext), "text=\"%s\", expected \"%s\"\n", dbgstr_w(text), extext);
432     }else {
433         ok_(__FILE__, line) (text == NULL, "text=\"%s\", expected NULL\n", dbgstr_w(text));
434     }
435
436     SysFreeString(text);
437
438 }
439
440 #define test_range_collapse(r,b) _test_range_collapse(__LINE__,r,b)
441 static void _test_range_collapse(unsigned line, IHTMLTxtRange *range, BOOL b)
442 {
443     HRESULT hres;
444
445     hres = IHTMLTxtRange_collapse(range, b);
446     ok_(__FILE__, line) (hres == S_OK, "collapse failed: %08x\n", hres);
447     _test_range_text(line, range, NULL);
448 }
449
450 #define test_range_expand(r,u,b,t) _test_range_expand(__LINE__,r,u,b,t)
451 static void _test_range_expand(unsigned line, IHTMLTxtRange *range, LPWSTR unit,
452         VARIANT_BOOL exb, const char *extext)
453 {
454     VARIANT_BOOL b = 0xe0e0;
455     HRESULT hres;
456
457     hres = IHTMLTxtRange_expand(range, unit, &b);
458     ok_(__FILE__,line) (hres == S_OK, "expand failed: %08x\n", hres);
459     ok_(__FILE__,line) (b == exb, "b=%x, expected %x\n", b, exb);
460     _test_range_text(line, range, extext);
461 }
462
463 #define test_range_move(r,u,c,e) _test_range_move(__LINE__,r,u,c,e)
464 static void _test_range_move(unsigned line, IHTMLTxtRange *range, LPWSTR unit, long cnt, long excnt)
465 {
466     long c = 0xdeadbeef;
467     HRESULT hres;
468
469     hres = IHTMLTxtRange_move(range, unit, cnt, &c);
470     ok_(__FILE__,line) (hres == S_OK, "move failed: %08x\n", hres);
471     ok_(__FILE__,line) (c == excnt, "count=%ld, expected %ld\n", c, excnt);
472     _test_range_text(line, range, NULL);
473 }
474
475 #define test_range_movestart(r,u,c,e) _test_range_movestart(__LINE__,r,u,c,e)
476 static void _test_range_movestart(unsigned line, IHTMLTxtRange *range,
477         LPWSTR unit, long cnt, long excnt)
478 {
479     long c = 0xdeadbeef;
480     HRESULT hres;
481
482     hres = IHTMLTxtRange_moveStart(range, unit, cnt, &c);
483     ok_(__FILE__,line) (hres == S_OK, "move failed: %08x\n", hres);
484     ok_(__FILE__,line) (c == excnt, "count=%ld, expected %ld\n", c, excnt);
485 }
486
487 #define test_range_moveend(r,u,c,e) _test_range_moveend(__LINE__,r,u,c,e)
488 static void _test_range_moveend(unsigned line, IHTMLTxtRange *range, LPWSTR unit, long cnt, long excnt)
489 {
490     long c = 0xdeadbeef;
491     HRESULT hres;
492
493     hres = IHTMLTxtRange_moveEnd(range, unit, cnt, &c);
494     ok_(__FILE__,line) (hres == S_OK, "move failed: %08x\n", hres);
495     ok_(__FILE__,line) (c == excnt, "count=%ld, expected %ld\n", c, excnt);
496 }
497
498 #define test_range_put_text(r,t) _test_range_put_text(__LINE__,r,t)
499 static void _test_range_put_text(unsigned line, IHTMLTxtRange *range, LPCWSTR text)
500 {
501     HRESULT hres;
502
503     hres = IHTMLTxtRange_put_text(range, (BSTR)text);
504     ok_(__FILE__,line) (hres == S_OK, "put_text failed: %08x\n", hres);
505     _test_range_text(line, range, NULL);
506 }
507
508 #define test_range_inrange(r1,r2,b) _test_range_inrange(__LINE__,r1,r2,b)
509 static void _test_range_inrange(unsigned line, IHTMLTxtRange *range1, IHTMLTxtRange *range2, VARIANT_BOOL exb)
510 {
511     VARIANT_BOOL b;
512     HRESULT hres;
513
514     b = 0xe0e0;
515     hres = IHTMLTxtRange_inRange(range1, range2, &b);
516     ok_(__FILE__,line) (hres == S_OK, "(1->2) isEqual failed: %08x\n", hres);
517     ok_(__FILE__,line) (b == exb, "(1->2) b=%x, expected %x\n", b, exb);
518 }
519
520 #define test_range_isequal(r1,r2,b) _test_range_isequal(__LINE__,r1,r2,b)
521 static void _test_range_isequal(unsigned line, IHTMLTxtRange *range1, IHTMLTxtRange *range2, VARIANT_BOOL exb)
522 {
523     VARIANT_BOOL b;
524     HRESULT hres;
525
526     b = 0xe0e0;
527     hres = IHTMLTxtRange_isEqual(range1, range2, &b);
528     ok_(__FILE__,line) (hres == S_OK, "(1->2) isEqual failed: %08x\n", hres);
529     ok_(__FILE__,line) (b == exb, "(1->2) b=%x, expected %x\n", b, exb);
530
531     b = 0xe0e0;
532     hres = IHTMLTxtRange_isEqual(range2, range1, &b);
533     ok_(__FILE__,line) (hres == S_OK, "(2->1) isEqual failed: %08x\n", hres);
534     ok_(__FILE__,line) (b == exb, "(2->1) b=%x, expected %x\n", b, exb);
535
536     if(exb) {
537         test_range_inrange(range1, range2, VARIANT_TRUE);
538         test_range_inrange(range2, range1, VARIANT_TRUE);
539     }
540 }
541
542 static void test_elem_collection(IHTMLElementCollection *col, const elem_type_t *elem_types, long exlen)
543 {
544     long len;
545     DWORD i;
546     VARIANT name, index;
547     IDispatch *disp;
548     HRESULT hres;
549
550     hres = IHTMLElementCollection_get_length(col, &len);
551     ok(hres == S_OK, "get_length failed: %08x\n", hres);
552     ok(len == exlen, "len=%ld, expected %ld\n", len, exlen);
553
554     V_VT(&index) = VT_EMPTY;
555     V_VT(&name) = VT_I4;
556
557     for(i=0; i<len; i++) {
558         V_I4(&name) = i;
559         disp = (void*)0xdeadbeef;
560         hres = IHTMLElementCollection_item(col, name, index, &disp);
561         ok(hres == S_OK, "item(%d) failed: %08x\n", i, hres);
562         ok(disp != NULL, "item returned NULL\n");
563         if(FAILED(hres) || !disp)
564             continue;
565
566         test_elem_type((IUnknown*)disp, elem_types[i]);
567         IDispatch_Release(disp);
568     }
569
570     V_I4(&name) = len;
571     disp = (void*)0xdeadbeef;
572     hres = IHTMLElementCollection_item(col, name, index, &disp);
573     ok(hres == S_OK, "item failed: %08x\n", hres);
574     ok(disp == NULL, "disp != NULL\n");
575
576     V_I4(&name) = -1;
577     disp = (void*)0xdeadbeef;
578     hres = IHTMLElementCollection_item(col, name, index, &disp);
579     ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
580     ok(disp == NULL, "disp != NULL\n");
581 }
582
583 static void test_elem_col_item(IHTMLElementCollection *col, LPCWSTR n,
584         const elem_type_t *elem_types, long len)
585 {
586     IHTMLElementCollection *elcol;
587     IDispatch *disp;
588     VARIANT name, index;
589     DWORD i;
590     HRESULT hres;
591
592     V_VT(&index) = VT_EMPTY;
593     V_VT(&name) = VT_BSTR;
594     V_BSTR(&name) = SysAllocString(n);
595
596     hres = IHTMLElementCollection_item(col, name, index, &disp);
597     ok(hres == S_OK, "item failed: %08x\n", hres);
598
599     hres = IDispatch_QueryInterface(disp, &IID_IHTMLElementCollection, (void**)&elcol);
600     IDispatch_Release(disp);
601     ok(hres == S_OK, "Could not get IHTMLElementCollection interface: %08x\n", hres);
602     test_elem_collection(elcol, elem_types, len);
603     IHTMLElementCollection_Release(elcol);
604
605     V_VT(&index) = VT_I4;
606
607     for(i=0; i<len; i++) {
608         V_I4(&index) = i;
609         disp = (void*)0xdeadbeef;
610         hres = IHTMLElementCollection_item(col, name, index, &disp);
611         ok(hres == S_OK, "item failed: %08x\n", hres);
612         ok(disp != NULL, "disp == NULL\n");
613         if(FAILED(hres) || !disp)
614             continue;
615
616         test_elem_type((IUnknown*)disp, elem_types[i]);
617
618         IDispatch_Release(disp);
619     }
620
621     V_I4(&index) = len;
622     disp = (void*)0xdeadbeef;
623     hres = IHTMLElementCollection_item(col, name, index, &disp);
624     ok(hres == S_OK, "item failed: %08x\n", hres);
625     ok(disp == NULL, "disp != NULL\n");
626
627     V_I4(&index) = -1;
628     disp = (void*)0xdeadbeef;
629     hres = IHTMLElementCollection_item(col, name, index, &disp);
630     ok(hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres);
631     ok(disp == NULL, "disp != NULL\n");
632
633     SysFreeString(V_BSTR(&name));
634 }
635
636 static IHTMLElement *get_elem_by_id(IHTMLDocument2 *doc, LPCWSTR id, BOOL expect_success)
637 {
638     IHTMLElementCollection *col;
639     IHTMLElement *elem;
640     IDispatch *disp = (void*)0xdeadbeef;
641     VARIANT name, index;
642     HRESULT hres;
643
644     hres = IHTMLDocument2_get_all(doc, &col);
645     ok(hres == S_OK, "get_all failed: %08x\n", hres);
646     ok(col != NULL, "col == NULL\n");
647     if(FAILED(hres) || !col)
648         return NULL;
649
650     V_VT(&index) = VT_EMPTY;
651     V_VT(&name) = VT_BSTR;
652     V_BSTR(&name) = SysAllocString(id);
653
654     hres = IHTMLElementCollection_item(col, name, index, &disp);
655     IHTMLElementCollection_Release(col);
656     SysFreeString(V_BSTR(&name));
657     ok(hres == S_OK, "item failed: %08x\n", hres);
658     if(!expect_success) {
659         ok(disp == NULL, "disp != NULL\n");
660         return NULL;
661     }
662
663     ok(disp != NULL, "disp == NULL\n");
664     if(!disp)
665         return NULL;
666
667     hres = IDispatch_QueryInterface(disp, &IID_IHTMLElement, (void**)&elem);
668     IDispatch_Release(disp);
669     ok(hres == S_OK, "Could not get IHTMLElement interface: %08x\n", hres);
670
671     return elem;
672 }
673
674 static void test_select_elem(IHTMLSelectElement *select)
675 {
676     test_select_length(select, 2);
677     test_select_selidx(select, 0);
678     test_select_put_selidx(select, 1);
679 }
680
681 static void test_create_option_elem(IHTMLDocument2 *doc)
682 {
683     IHTMLOptionElement *option;
684
685     option = create_option_elem(doc, "test text", "test value");
686
687     test_option_put_text(option, "new text");
688     test_option_put_value(option, "new value");
689
690     IHTMLOptionElement_Release(option);
691 }
692
693 static void test_txtrange(IHTMLDocument2 *doc)
694 {
695     IHTMLElement *elem;
696     IHTMLBodyElement *body;
697     IHTMLTxtRange *body_range, *range, *range2;
698     HRESULT hres;
699
700     hres = IHTMLDocument2_get_body(doc, &elem);
701     ok(hres == S_OK, "get_body failed: %08x\n", hres);
702
703     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLBodyElement, (void**)&body);
704     IHTMLElement_Release(elem);
705
706     hres = IHTMLBodyElement_createTextRange(body, &body_range);
707     IHTMLBodyElement_Release(body);
708     ok(hres == S_OK, "createTextRange failed: %08x\n", hres);
709
710     test_range_text(body_range, "test abc 123\r\nit's text");
711
712     hres = IHTMLTxtRange_duplicate(body_range, &range);
713     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
714
715     hres = IHTMLTxtRange_duplicate(body_range, &range2);
716     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
717     test_range_isequal(range, range2, VARIANT_TRUE);
718
719     test_range_text(range, "test abc 123\r\nit's text");
720     test_range_text(body_range, "test abc 123\r\nit's text");
721
722     test_range_collapse(range, TRUE);
723     test_range_isequal(range, range2, VARIANT_FALSE);
724     test_range_inrange(range, range2, VARIANT_FALSE);
725     test_range_inrange(range2, range, VARIANT_TRUE);
726     IHTMLTxtRange_Release(range2);
727
728     test_range_expand(range, wordW, VARIANT_TRUE, "test ");
729     test_range_expand(range, wordW, VARIANT_FALSE, "test ");
730     test_range_move(range, characterW, 2, 2);
731     test_range_expand(range, wordW, VARIANT_TRUE, "test ");
732
733     test_range_collapse(range, FALSE);
734     test_range_expand(range, wordW, VARIANT_TRUE, "abc ");
735
736     test_range_collapse(range, FALSE);
737     test_range_expand(range, wordW, VARIANT_TRUE, "123");
738     test_range_expand(range, wordW, VARIANT_FALSE, "123");
739     test_range_move(range, characterW, 2, 2);
740     test_range_expand(range, wordW, VARIANT_TRUE, "123");
741     test_range_moveend(range, characterW, -5, -5);
742     test_range_text(range, NULL);
743     test_range_moveend(range, characterW, 3, 3);
744     test_range_text(range, "c 1");
745
746     IHTMLTxtRange_Release(range);
747
748     hres = IHTMLTxtRange_duplicate(body_range, &range);
749     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
750
751     test_range_text(range, "test abc 123\r\nit's text");
752     test_range_move(range, characterW, 3, 3);
753     test_range_moveend(range, characterW, 1, 1);
754     test_range_text(range, "t");
755     test_range_moveend(range, characterW, 3, 3);
756     test_range_text(range, "t ab");
757     test_range_moveend(range, characterW, -2, -2);
758     test_range_text(range, "t ");
759     test_range_move(range, characterW, 6, 6);
760     test_range_moveend(range, characterW, 3, 3);
761     test_range_text(range, "123");
762     test_range_moveend(range, characterW, 2, 2);
763     test_range_text(range, "123\r\ni");
764
765     IHTMLTxtRange_Release(range);
766
767     hres = IHTMLTxtRange_duplicate(body_range, &range);
768     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
769
770     test_range_move(range, wordW, 1, 1);
771     test_range_moveend(range, characterW, 2, 2);
772     test_range_text(range, "ab");
773
774     test_range_move(range, characterW, -2, -2);
775     test_range_moveend(range, characterW, 2, 2);
776     test_range_text(range, "t ");
777
778     test_range_move(range, wordW, 3, 3);
779     test_range_move(range, wordW, -2, -2);
780     test_range_moveend(range, characterW, 2, 2);
781     test_range_text(range, "ab");
782
783     test_range_move(range, characterW, -6, -5);
784     test_range_moveend(range, characterW, -1, 0);
785     test_range_moveend(range, characterW, -6, 0);
786     test_range_move(range, characterW, 2, 2);
787     test_range_moveend(range, characterW, 2, 2);
788     test_range_text(range, "st");
789     test_range_moveend(range, characterW, -6, -4);
790     test_range_moveend(range, characterW, 2, 2);
791
792     IHTMLTxtRange_Release(range);
793
794     hres = IHTMLTxtRange_duplicate(body_range, &range);
795     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
796
797     test_range_move(range, wordW, 2, 2);
798     test_range_moveend(range, characterW, 2, 2);
799     test_range_text(range, "12");
800
801     test_range_move(range, characterW, 15, 14);
802     test_range_move(range, characterW, -2, -2);
803     test_range_moveend(range, characterW, 3, 2);
804     test_range_text(range, "t");
805     test_range_moveend(range, characterW, -1, -1);
806     test_range_text(range, "t");
807     test_range_expand(range, wordW, VARIANT_TRUE, "text");
808     test_range_move(range, characterW, -2, -2);
809     test_range_moveend(range, characterW, 2, 2);
810     test_range_text(range, "s ");
811     test_range_move(range, characterW, 100, 7);
812     test_range_move(range, wordW, 1, 0);
813     test_range_move(range, characterW, -2, -2);
814     test_range_moveend(range, characterW, 3, 2);
815     test_range_text(range, "t");
816
817     IHTMLTxtRange_Release(range);
818
819     hres = IHTMLTxtRange_duplicate(body_range, &range);
820     ok(hres == S_OK, "duplicate failed: %08x\n", hres);
821
822     test_range_collapse(range, TRUE);
823     test_range_expand(range, wordW, VARIANT_TRUE, "test ");
824     test_range_put_text(range, wordW);
825     test_range_text(body_range, "wordabc 123\r\nit's text");
826     test_range_text(range, NULL);
827     test_range_moveend(range, characterW, 3, 3);
828     test_range_text(range, "abc");
829     test_range_movestart(range, characterW, -2, -2);
830     test_range_text(range, "rdabc");
831     test_range_movestart(range, characterW, 3, 3);
832     test_range_text(range, "bc");
833     test_range_movestart(range, characterW, 4, 4);
834     test_range_text(range, NULL);
835     test_range_movestart(range, characterW, -3, -3);
836     test_range_text(range, "c 1");
837     test_range_movestart(range, characterW, -7, -6);
838     test_range_text(range, "wordabc 1");
839     test_range_movestart(range, characterW, 100, 22);
840     test_range_text(range, NULL);
841
842     IHTMLTxtRange_Release(range);
843     IHTMLTxtRange_Release(body_range);
844 }
845
846 static void test_compatmode(IHTMLDocument2 *doc)
847 {
848     IHTMLDocument5 *doc5;
849     BSTR mode;
850     HRESULT hres;
851
852     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5);
853     ok(hres == S_OK, "Could not get IHTMLDocument5 interface: %08x\n", hres);
854     if(FAILED(hres))
855         return;
856
857     hres = IHTMLDocument5_get_compatMode(doc5, &mode);
858     IHTMLDocument5_Release(doc5);
859     ok(hres == S_OK, "get_compatMode failed: %08x\n", hres);
860     ok(!strcmp_wa(mode, "BackCompat"), "compatMode=%s\n", dbgstr_w(mode));
861     SysFreeString(mode);
862 }
863
864 static void test_default_style(IHTMLStyle *style)
865 {
866     VARIANT_BOOL b;
867     VARIANT v;
868     BSTR str;
869     HRESULT hres;
870
871     str = (void*)0xdeadbeef;
872     hres = IHTMLStyle_get_fontFamily(style, &str);
873     ok(hres == S_OK, "get_fontFamily failed: %08x\n", hres);
874     ok(!str, "fontFamily = %s\n", dbgstr_w(str));
875
876     str = (void*)0xdeadbeef;
877     hres = IHTMLStyle_get_fontWeight(style, &str);
878     ok(hres == S_OK, "get_fontWeight failed: %08x\n", hres);
879     ok(!str, "fontWeight = %s\n", dbgstr_w(str));
880
881     str = (void*)0xdeadbeef;
882     hres = IHTMLStyle_get_display(style, &str);
883     ok(hres == S_OK, "get_display failed: %08x\n", hres);
884     ok(!str, "display = %s\n", dbgstr_w(str));
885
886     str = (void*)0xdeadbeef;
887     hres = IHTMLStyle_get_visibility(style, &str);
888     ok(hres == S_OK, "get_visibility failed: %08x\n", hres);
889     ok(!str, "visibility = %s\n", dbgstr_w(str));
890
891     V_VT(&v) = VT_NULL;
892     hres = IHTMLStyle_get_fontSize(style, &v);
893     ok(hres == S_OK, "get_fontSize failed: %08x\n", hres);
894     ok(V_VT(&v) == VT_BSTR, "V_VT(fontSize) = %d\n", V_VT(&v));
895     ok(!V_BSTR(&v), "V_BSTR(fontSize) = %s\n", dbgstr_w(V_BSTR(&v)));
896
897     V_VT(&v) = VT_NULL;
898     hres = IHTMLStyle_get_color(style, &v);
899     ok(hres == S_OK, "get_color failed: %08x\n", hres);
900     ok(V_VT(&v) == VT_BSTR, "V_VT(color) = %d\n", V_VT(&v));
901     ok(!V_BSTR(&v), "V_BSTR(color) = %s\n", dbgstr_w(V_BSTR(&v)));
902
903     b = 0xfefe;
904     hres = IHTMLStyle_get_textDecorationUnderline(style, &b);
905     ok(hres == S_OK, "get_textDecorationUnderline failed: %08x\n", hres);
906     ok(b == VARIANT_FALSE, "textDecorationUnderline = %x\n", b);
907
908     b = 0xfefe;
909     hres = IHTMLStyle_get_textDecorationLineThrough(style, &b);
910     ok(hres == S_OK, "get_textDecorationLineThrough failed: %08x\n", hres);
911     ok(b == VARIANT_FALSE, "textDecorationLineThrough = %x\n", b);
912 }
913
914 static void test_default_selection(IHTMLDocument2 *doc)
915 {
916     IHTMLSelectionObject *selection;
917     IHTMLTxtRange *range;
918     IDispatch *disp;
919     BSTR str;
920     HRESULT hres;
921
922     hres = IHTMLDocument2_get_selection(doc, &selection);
923     ok(hres == S_OK, "get_selection failed: %08x\n", hres);
924
925     hres = IHTMLSelectionObject_get_type(selection, &str);
926     ok(hres == S_OK, "get_type failed: %08x\n", hres);
927     ok(!lstrcmpW(str, noneW), "type = %s\n", dbgstr_w(str));
928     SysFreeString(str);
929
930     hres = IHTMLSelectionObject_createRange(selection, &disp);
931     IHTMLSelectionObject_Release(selection);
932     ok(hres == S_OK, "createRange failed: %08x\n", hres);
933
934     hres = IDispatch_QueryInterface(disp, &IID_IHTMLTxtRange, (void**)&range);
935     IDispatch_Release(disp);
936     ok(hres == S_OK, "Could not get IHTMLTxtRange interface: %08x\n", hres);
937
938     test_range_text(range, NULL);
939     IHTMLTxtRange_Release(range);
940 }
941
942 static void test_defaults(IHTMLDocument2 *doc)
943 {
944     IHTMLStyleSheetsCollection *stylesheetcol;
945     IHTMLElement *elem;
946     IHTMLStyle *style;
947     long l;
948     HRESULT hres;
949
950     hres = IHTMLDocument2_get_body(doc, &elem);
951     ok(hres == S_OK, "get_body failed: %08x\n", hres);
952
953     hres = IHTMLElement_get_style(elem, &style);
954     IHTMLElement_Release(elem);
955     ok(hres == S_OK, "get_style failed: %08x\n", hres);
956
957     test_default_style(style);
958     test_compatmode(doc);
959
960     IHTMLStyle_Release(style);
961
962     hres = IHTMLDocument2_get_styleSheets(doc, &stylesheetcol);
963     ok(hres == S_OK, "get_styleSheets failed: %08x\n", hres);
964
965     l = 0xdeadbeef;
966     hres = IHTMLStyleSheetsCollection_get_length(stylesheetcol, &l);
967     ok(hres == S_OK, "get_length failed: %08x\n", hres);
968     ok(l == 0, "length = %ld\n", l);
969
970     IHTMLStyleSheetsCollection_Release(stylesheetcol);
971
972     test_default_selection(doc);
973 }
974
975 static void test_elems(IHTMLDocument2 *doc)
976 {
977     IHTMLElementCollection *col;
978     IHTMLElement *elem;
979     IDispatch *disp;
980     HRESULT hres;
981
982     static const WCHAR xW[] = {'x',0};
983     static const WCHAR sW[] = {'s',0};
984     static const WCHAR xxxW[] = {'x','x','x',0};
985
986     static const elem_type_t all_types[] = {
987         ET_HTML,
988         ET_HEAD,
989         ET_TITLE,
990         ET_BODY,
991         ET_A,
992         ET_INPUT,
993         ET_SELECT,
994         ET_OPTION,
995         ET_OPTION,
996         ET_TEXTAREA
997     };
998
999     static const elem_type_t item_types[] = {
1000         ET_A,
1001         ET_OPTION,
1002         ET_TEXTAREA
1003     };
1004
1005     hres = IHTMLDocument2_get_all(doc, &col);
1006     ok(hres == S_OK, "get_all failed: %08x\n", hres);
1007     test_elem_collection(col, all_types, sizeof(all_types)/sizeof(all_types[0]));
1008     test_elem_col_item(col, xW, item_types, sizeof(item_types)/sizeof(item_types[0]));
1009     IHTMLElementCollection_Release(col);
1010
1011     elem = get_doc_elem(doc);
1012     ok(hres == S_OK, "get_documentElement failed: %08x\n", hres);
1013     hres = IHTMLElement_get_all(elem, &disp);
1014     IHTMLElement_Release(elem);
1015     ok(hres == S_OK, "get_all failed: %08x\n", hres);
1016
1017     hres = IDispatch_QueryInterface(disp, &IID_IHTMLElementCollection, (void**)&col);
1018     IDispatch_Release(disp);
1019     ok(hres == S_OK, "Could not get IHTMLElementCollection: %08x\n", hres);
1020     test_elem_collection(col, all_types+1, sizeof(all_types)/sizeof(all_types[0])-1);
1021     IHTMLElementCollection_Release(col);
1022
1023     get_elem_by_id(doc, xxxW, FALSE);
1024     elem = get_elem_by_id(doc, sW, TRUE);
1025     if(elem) {
1026         IHTMLSelectElement *select;
1027
1028         hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLSelectElement, (void**)&select);
1029         ok(hres == S_OK, "Could not get IHTMLSelectElement interface: %08x\n", hres);
1030
1031         test_select_elem(select);
1032
1033         IHTMLSelectElement_Release(select);
1034         IHTMLElement_Release(elem);
1035     }
1036
1037     test_create_option_elem(doc);
1038 }
1039
1040 static IHTMLDocument2 *notif_doc;
1041 static BOOL doc_complete;
1042
1043 static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
1044         REFIID riid, void**ppv)
1045 {
1046     if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
1047         *ppv = iface;
1048         return S_OK;
1049     }
1050
1051     ok(0, "unexpected call\n");
1052     return E_NOINTERFACE;
1053 }
1054
1055 static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface)
1056 {
1057     return 2;
1058 }
1059
1060 static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface)
1061 {
1062     return 1;
1063 }
1064
1065 static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
1066 {
1067     if(dispID == DISPID_READYSTATE){
1068         BSTR state;
1069         HRESULT hres;
1070
1071         static const WCHAR completeW[] = {'c','o','m','p','l','e','t','e',0};
1072
1073         hres = IHTMLDocument2_get_readyState(notif_doc, &state);
1074         ok(hres == S_OK, "get_readyState failed: %08x\n", hres);
1075
1076         if(!lstrcmpW(state, completeW))
1077             doc_complete = TRUE;
1078
1079         SysFreeString(state);        
1080     }
1081
1082     return S_OK;
1083 }
1084
1085 static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
1086 {
1087     ok(0, "unexpected call\n");
1088     return E_NOTIMPL;
1089 }
1090
1091 static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
1092     PropertyNotifySink_QueryInterface,
1093     PropertyNotifySink_AddRef,
1094     PropertyNotifySink_Release,
1095     PropertyNotifySink_OnChanged,
1096     PropertyNotifySink_OnRequestEdit
1097 };
1098
1099 static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl };
1100
1101 static IHTMLDocument2 *create_doc_with_string(const char *str)
1102 {
1103     IPersistStreamInit *init;
1104     IStream *stream;
1105     IHTMLDocument2 *doc;
1106     HGLOBAL mem;
1107     SIZE_T len;
1108
1109     notif_doc = doc = create_document();
1110     if(!doc)
1111         return NULL;
1112
1113     doc_complete = FALSE;
1114     len = strlen(str);
1115     mem = GlobalAlloc(0, len);
1116     memcpy(mem, str, len);
1117     CreateStreamOnHGlobal(mem, TRUE, &stream);
1118
1119     IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init);
1120
1121     IPersistStreamInit_Load(init, stream);
1122     IPersistStreamInit_Release(init);
1123     IStream_Release(stream);
1124
1125     return doc;
1126 }
1127
1128 static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise)
1129 {
1130     IConnectionPointContainer *container;
1131     IConnectionPoint *cp;
1132     DWORD cookie;
1133     HRESULT hres;
1134
1135     hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
1136     ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
1137
1138     hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp);
1139     IConnectionPointContainer_Release(container);
1140     ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
1141
1142     hres = IConnectionPoint_Advise(cp, unk_advise, &cookie);
1143     IConnectionPoint_Release(cp);
1144     ok(hres == S_OK, "Advise failed: %08x\n", hres);
1145 }
1146
1147 typedef void (*domtest_t)(IHTMLDocument2*);
1148
1149 static void run_domtest(const char *str, domtest_t test)
1150 {
1151     IHTMLDocument2 *doc;
1152     IHTMLElement *body = NULL;
1153     ULONG ref;
1154     MSG msg;
1155     HRESULT hres;
1156
1157     doc = create_doc_with_string(str);
1158     do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
1159
1160     while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) {
1161         TranslateMessage(&msg);
1162         DispatchMessage(&msg);
1163     }
1164
1165     hres = IHTMLDocument2_get_body(doc, &body);
1166     ok(hres == S_OK, "get_body failed: %08x\n", hres);
1167
1168     if(body) {
1169         IHTMLElement_Release(body);
1170         test(doc);
1171     }else {
1172         skip("Could not get document body. Assuming no Gecko installed.\n");
1173     }
1174
1175     ref = IHTMLDocument2_Release(doc);
1176     ok(!ref, "ref = %d\n", ref);
1177 }
1178
1179 static void gecko_installer_workaround(BOOL disable)
1180 {
1181     HKEY hkey;
1182     DWORD res;
1183
1184     static BOOL has_url = FALSE;
1185     static char url[2048];
1186
1187     if(!disable && !has_url)
1188         return;
1189
1190     res = RegOpenKey(HKEY_CURRENT_USER, "Software\\Wine\\MSHTML", &hkey);
1191     if(res != ERROR_SUCCESS)
1192         return;
1193
1194     if(disable) {
1195         DWORD type, size = sizeof(url);
1196
1197         res = RegQueryValueEx(hkey, "GeckoUrl", NULL, &type, (PVOID)url, &size);
1198         if(res == ERROR_SUCCESS && type == REG_SZ)
1199             has_url = TRUE;
1200
1201         RegDeleteValue(hkey, "GeckoUrl");
1202     }else {
1203         RegSetValueEx(hkey, "GeckoUrl", 0, REG_SZ, (PVOID)url, lstrlenA(url)+1);
1204     }
1205
1206     RegCloseKey(hkey);
1207 }
1208
1209 START_TEST(dom)
1210 {
1211     gecko_installer_workaround(TRUE);
1212     CoInitialize(NULL);
1213
1214     run_domtest(doc_str1, test_doc_elem);
1215     run_domtest(doc_str2, test_txtrange);
1216     run_domtest(doc_str3, test_elems);
1217     run_domtest(doc_blank, test_defaults);
1218
1219     CoUninitialize();
1220     gecko_installer_workaround(FALSE);
1221 }