mshtml: Added IHTMLDocument2::put_URL implementation.
[wine] / dlls / mshtml / htmldoc.c
1 /*
2  * Copyright 2005-2009 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 #include "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "wininet.h"
30 #include "ole2.h"
31 #include "perhist.h"
32 #include "mshtmdid.h"
33
34 #include "wine/debug.h"
35
36 #include "mshtml_private.h"
37 #include "htmlevent.h"
38 #include "pluginhost.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
41
42 static inline HTMLDocument *impl_from_IHTMLDocument2(IHTMLDocument2 *iface)
43 {
44     return CONTAINING_RECORD(iface, HTMLDocument, IHTMLDocument2_iface);
45 }
46
47 static HRESULT WINAPI HTMLDocument_QueryInterface(IHTMLDocument2 *iface, REFIID riid, void **ppv)
48 {
49     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
50
51     return htmldoc_query_interface(This, riid, ppv);
52 }
53
54 static ULONG WINAPI HTMLDocument_AddRef(IHTMLDocument2 *iface)
55 {
56     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
57
58     return htmldoc_addref(This);
59 }
60
61 static ULONG WINAPI HTMLDocument_Release(IHTMLDocument2 *iface)
62 {
63     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
64
65     return htmldoc_release(This);
66 }
67
68 static HRESULT WINAPI HTMLDocument_GetTypeInfoCount(IHTMLDocument2 *iface, UINT *pctinfo)
69 {
70     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
71
72     return IDispatchEx_GetTypeInfoCount(&This->IDispatchEx_iface, pctinfo);
73 }
74
75 static HRESULT WINAPI HTMLDocument_GetTypeInfo(IHTMLDocument2 *iface, UINT iTInfo,
76                                                 LCID lcid, ITypeInfo **ppTInfo)
77 {
78     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
79
80     return IDispatchEx_GetTypeInfo(&This->IDispatchEx_iface, iTInfo, lcid, ppTInfo);
81 }
82
83 static HRESULT WINAPI HTMLDocument_GetIDsOfNames(IHTMLDocument2 *iface, REFIID riid,
84                                                 LPOLESTR *rgszNames, UINT cNames,
85                                                 LCID lcid, DISPID *rgDispId)
86 {
87     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
88
89     return IDispatchEx_GetIDsOfNames(&This->IDispatchEx_iface, riid, rgszNames, cNames, lcid,
90             rgDispId);
91 }
92
93 static HRESULT WINAPI HTMLDocument_Invoke(IHTMLDocument2 *iface, DISPID dispIdMember,
94                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
95                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
96 {
97     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
98
99     return IDispatchEx_Invoke(&This->IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
100             pDispParams, pVarResult, pExcepInfo, puArgErr);
101 }
102
103 static HRESULT WINAPI HTMLDocument_get_Script(IHTMLDocument2 *iface, IDispatch **p)
104 {
105     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
106
107     TRACE("(%p)->(%p)\n", This, p);
108
109     *p = (IDispatch*)&This->window->IHTMLWindow2_iface;
110     IDispatch_AddRef(*p);
111     return S_OK;
112 }
113
114 static HRESULT WINAPI HTMLDocument_get_all(IHTMLDocument2 *iface, IHTMLElementCollection **p)
115 {
116     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
117     nsIDOMElement *nselem = NULL;
118     HTMLDOMNode *node;
119     nsresult nsres;
120     HRESULT hres;
121
122     TRACE("(%p)->(%p)\n", This, p);
123
124     if(!This->doc_node->nsdoc) {
125         WARN("NULL nsdoc\n");
126         return E_UNEXPECTED;
127     }
128
129     nsres = nsIDOMHTMLDocument_GetDocumentElement(This->doc_node->nsdoc, &nselem);
130     if(NS_FAILED(nsres)) {
131         ERR("GetDocumentElement failed: %08x\n", nsres);
132         return E_FAIL;
133     }
134
135     if(!nselem) {
136         *p = NULL;
137         return S_OK;
138     }
139
140     hres = get_node(This->doc_node, (nsIDOMNode*)nselem, TRUE, &node);
141     if(SUCCEEDED(hres))
142         *p = create_all_collection(node, TRUE);
143     nsIDOMElement_Release(nselem);
144     return hres;
145 }
146
147 static HRESULT WINAPI HTMLDocument_get_body(IHTMLDocument2 *iface, IHTMLElement **p)
148 {
149     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
150     nsIDOMHTMLElement *nsbody = NULL;
151     HTMLDOMNode *node;
152     HRESULT hres;
153
154     TRACE("(%p)->(%p)\n", This, p);
155
156     if(This->doc_node->nsdoc) {
157         nsresult nsres;
158
159         nsres = nsIDOMHTMLDocument_GetBody(This->doc_node->nsdoc, &nsbody);
160         if(NS_FAILED(nsres)) {
161             TRACE("Could not get body: %08x\n", nsres);
162             return E_UNEXPECTED;
163         }
164     }
165
166     if(!nsbody) {
167         *p = NULL;
168         return S_OK;
169     }
170
171     hres = get_node(This->doc_node, (nsIDOMNode*)nsbody, TRUE, &node);
172     nsIDOMHTMLElement_Release(nsbody);
173     if(FAILED(hres))
174         return hres;
175
176     return IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_IHTMLElement, (void**)p);
177 }
178
179 static HRESULT WINAPI HTMLDocument_get_activeElement(IHTMLDocument2 *iface, IHTMLElement **p)
180 {
181     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
182     FIXME("(%p)->(%p)\n", This, p);
183     return E_NOTIMPL;
184 }
185
186 static HRESULT WINAPI HTMLDocument_get_images(IHTMLDocument2 *iface, IHTMLElementCollection **p)
187 {
188     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
189     nsIDOMHTMLCollection *nscoll = NULL;
190     nsresult nsres;
191
192     TRACE("(%p)->(%p)\n", This, p);
193
194     if(!p)
195         return E_INVALIDARG;
196
197     *p = NULL;
198
199     if(!This->doc_node->nsdoc) {
200         WARN("NULL nsdoc\n");
201         return E_UNEXPECTED;
202     }
203
204     nsres = nsIDOMHTMLDocument_GetImages(This->doc_node->nsdoc, &nscoll);
205     if(NS_FAILED(nsres)) {
206         ERR("GetImages failed: %08x\n", nsres);
207         return E_FAIL;
208     }
209
210     if(nscoll) {
211         *p = create_collection_from_htmlcol(This->doc_node, (IUnknown*)&This->IHTMLDocument2_iface, nscoll);
212         nsIDOMElement_Release(nscoll);
213     }
214
215     return S_OK;
216 }
217
218 static HRESULT WINAPI HTMLDocument_get_applets(IHTMLDocument2 *iface, IHTMLElementCollection **p)
219 {
220     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
221     nsIDOMHTMLCollection *nscoll = NULL;
222     nsresult nsres;
223
224     TRACE("(%p)->(%p)\n", This, p);
225
226     if(!p)
227         return E_INVALIDARG;
228
229     *p = NULL;
230
231     if(!This->doc_node->nsdoc) {
232         WARN("NULL nsdoc\n");
233         return E_UNEXPECTED;
234     }
235
236     nsres = nsIDOMHTMLDocument_GetApplets(This->doc_node->nsdoc, &nscoll);
237     if(NS_FAILED(nsres)) {
238         ERR("GetApplets failed: %08x\n", nsres);
239         return E_FAIL;
240     }
241
242     if(nscoll) {
243         *p = create_collection_from_htmlcol(This->doc_node, (IUnknown*)&This->IHTMLDocument2_iface, nscoll);
244         nsIDOMElement_Release(nscoll);
245     }
246
247     return S_OK;
248 }
249
250 static HRESULT WINAPI HTMLDocument_get_links(IHTMLDocument2 *iface, IHTMLElementCollection **p)
251 {
252     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
253     nsIDOMHTMLCollection *nscoll = NULL;
254     nsresult nsres;
255
256     TRACE("(%p)->(%p)\n", This, p);
257
258     if(!p)
259         return E_INVALIDARG;
260
261     *p = NULL;
262
263     if(!This->doc_node->nsdoc) {
264         WARN("NULL nsdoc\n");
265         return E_UNEXPECTED;
266     }
267
268     nsres = nsIDOMHTMLDocument_GetLinks(This->doc_node->nsdoc, &nscoll);
269     if(NS_FAILED(nsres)) {
270         ERR("GetLinks failed: %08x\n", nsres);
271         return E_FAIL;
272     }
273
274     if(nscoll) {
275         *p = create_collection_from_htmlcol(This->doc_node, (IUnknown*)&This->IHTMLDocument2_iface, nscoll);
276         nsIDOMElement_Release(nscoll);
277     }
278
279     return S_OK;
280 }
281
282 static HRESULT WINAPI HTMLDocument_get_forms(IHTMLDocument2 *iface, IHTMLElementCollection **p)
283 {
284     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
285     nsIDOMHTMLCollection *nscoll = NULL;
286     nsresult nsres;
287
288     TRACE("(%p)->(%p)\n", This, p);
289
290     if(!p)
291         return E_INVALIDARG;
292
293     *p = NULL;
294
295     if(!This->doc_node->nsdoc) {
296         WARN("NULL nsdoc\n");
297         return E_UNEXPECTED;
298     }
299
300     nsres = nsIDOMHTMLDocument_GetForms(This->doc_node->nsdoc, &nscoll);
301     if(NS_FAILED(nsres)) {
302         ERR("GetForms failed: %08x\n", nsres);
303         return E_FAIL;
304     }
305
306     if(nscoll) {
307         *p = create_collection_from_htmlcol(This->doc_node, (IUnknown*)&This->IHTMLDocument2_iface, nscoll);
308         nsIDOMElement_Release(nscoll);
309     }
310
311     return S_OK;
312 }
313
314 static HRESULT WINAPI HTMLDocument_get_anchors(IHTMLDocument2 *iface, IHTMLElementCollection **p)
315 {
316     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
317     nsIDOMHTMLCollection *nscoll = NULL;
318     nsresult nsres;
319
320     TRACE("(%p)->(%p)\n", This, p);
321
322     if(!p)
323         return E_INVALIDARG;
324
325     *p = NULL;
326
327     if(!This->doc_node->nsdoc) {
328         WARN("NULL nsdoc\n");
329         return E_UNEXPECTED;
330     }
331
332     nsres = nsIDOMHTMLDocument_GetAnchors(This->doc_node->nsdoc, &nscoll);
333     if(NS_FAILED(nsres)) {
334         ERR("GetAnchors failed: %08x\n", nsres);
335         return E_FAIL;
336     }
337
338     if(nscoll) {
339         *p = create_collection_from_htmlcol(This->doc_node, (IUnknown*)&This->IHTMLDocument2_iface, nscoll);
340         nsIDOMElement_Release(nscoll);
341     }
342
343     return S_OK;
344 }
345
346 static HRESULT WINAPI HTMLDocument_put_title(IHTMLDocument2 *iface, BSTR v)
347 {
348     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
349     nsAString nsstr;
350     nsresult nsres;
351
352     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
353
354     if(!This->doc_node->nsdoc) {
355         WARN("NULL nsdoc\n");
356         return E_UNEXPECTED;
357     }
358
359     nsAString_InitDepend(&nsstr, v);
360     nsres = nsIDOMHTMLDocument_SetTitle(This->doc_node->nsdoc, &nsstr);
361     nsAString_Finish(&nsstr);
362     if(NS_FAILED(nsres))
363         ERR("SetTitle failed: %08x\n", nsres);
364
365     return S_OK;
366 }
367
368 static HRESULT WINAPI HTMLDocument_get_title(IHTMLDocument2 *iface, BSTR *p)
369 {
370     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
371     const PRUnichar *ret;
372     nsAString nsstr;
373     nsresult nsres;
374
375     TRACE("(%p)->(%p)\n", This, p);
376
377     if(!This->doc_node->nsdoc) {
378         WARN("NULL nsdoc\n");
379         return E_UNEXPECTED;
380     }
381
382
383     nsAString_Init(&nsstr, NULL);
384     nsres = nsIDOMHTMLDocument_GetTitle(This->doc_node->nsdoc, &nsstr);
385     if (NS_SUCCEEDED(nsres)) {
386         nsAString_GetData(&nsstr, &ret);
387         *p = SysAllocString(ret);
388     }
389     nsAString_Finish(&nsstr);
390
391     if(NS_FAILED(nsres)) {
392         ERR("GetTitle failed: %08x\n", nsres);
393         return E_FAIL;
394     }
395
396     return S_OK;
397 }
398
399 static HRESULT WINAPI HTMLDocument_get_scripts(IHTMLDocument2 *iface, IHTMLElementCollection **p)
400 {
401     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
402     FIXME("(%p)->(%p)\n", This, p);
403     return E_NOTIMPL;
404 }
405
406 static HRESULT WINAPI HTMLDocument_put_designMode(IHTMLDocument2 *iface, BSTR v)
407 {
408     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
409     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
410     return E_NOTIMPL;
411 }
412
413 static HRESULT WINAPI HTMLDocument_get_designMode(IHTMLDocument2 *iface, BSTR *p)
414 {
415     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
416     static WCHAR szOff[] = {'O','f','f',0};
417     FIXME("(%p)->(%p) always returning Off\n", This, p);
418
419     if(!p)
420         return E_INVALIDARG;
421
422     *p = SysAllocString(szOff);
423
424     return S_OK;
425 }
426
427 static HRESULT WINAPI HTMLDocument_get_selection(IHTMLDocument2 *iface, IHTMLSelectionObject **p)
428 {
429     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
430     nsISelection *nsselection;
431     nsresult nsres;
432
433     TRACE("(%p)->(%p)\n", This, p);
434
435     nsres = nsIDOMWindow_GetSelection(This->window->nswindow, &nsselection);
436     if(NS_FAILED(nsres)) {
437         ERR("GetSelection failed: %08x\n", nsres);
438         return E_FAIL;
439     }
440
441     return HTMLSelectionObject_Create(This->doc_node, nsselection, p);
442 }
443
444 static HRESULT WINAPI HTMLDocument_get_readyState(IHTMLDocument2 *iface, BSTR *p)
445 {
446     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
447
448     static const WCHAR wszUninitialized[] = {'u','n','i','n','i','t','i','a','l','i','z','e','d',0};
449     static const WCHAR wszLoading[] = {'l','o','a','d','i','n','g',0};
450     static const WCHAR wszLoaded[] = {'l','o','a','d','e','d',0};
451     static const WCHAR wszInteractive[] = {'i','n','t','e','r','a','c','t','i','v','e',0};
452     static const WCHAR wszComplete[] = {'c','o','m','p','l','e','t','e',0};
453
454     static const LPCWSTR readystate_str[] = {
455         wszUninitialized,
456         wszLoading,
457         wszLoaded,
458         wszInteractive,
459         wszComplete
460     };
461
462     TRACE("(%p)->(%p)\n", iface, p);
463
464     if(!p)
465         return E_POINTER;
466
467     *p = SysAllocString(readystate_str[This->window->readystate]);
468     return S_OK;
469 }
470
471 static HRESULT WINAPI HTMLDocument_get_frames(IHTMLDocument2 *iface, IHTMLFramesCollection2 **p)
472 {
473     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
474
475     TRACE("(%p)->(%p)\n", This, p);
476
477     return IHTMLWindow2_get_frames(&This->window->IHTMLWindow2_iface, p);
478 }
479
480 static HRESULT WINAPI HTMLDocument_get_embeds(IHTMLDocument2 *iface, IHTMLElementCollection **p)
481 {
482     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
483     FIXME("(%p)->(%p)\n", This, p);
484     return E_NOTIMPL;
485 }
486
487 static HRESULT WINAPI HTMLDocument_get_plugins(IHTMLDocument2 *iface, IHTMLElementCollection **p)
488 {
489     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
490     FIXME("(%p)->(%p)\n", This, p);
491     return E_NOTIMPL;
492 }
493
494 static HRESULT WINAPI HTMLDocument_put_alinkColor(IHTMLDocument2 *iface, VARIANT v)
495 {
496     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
497     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
498     return E_NOTIMPL;
499 }
500
501 static HRESULT WINAPI HTMLDocument_get_alinkColor(IHTMLDocument2 *iface, VARIANT *p)
502 {
503     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
504     FIXME("(%p)->(%p)\n", This, p);
505     return E_NOTIMPL;
506 }
507
508 static HRESULT WINAPI HTMLDocument_put_bgColor(IHTMLDocument2 *iface, VARIANT v)
509 {
510     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
511     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
512     return E_NOTIMPL;
513 }
514
515 static HRESULT WINAPI HTMLDocument_get_bgColor(IHTMLDocument2 *iface, VARIANT *p)
516 {
517     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
518     FIXME("(%p)->(%p)\n", This, p);
519     return E_NOTIMPL;
520 }
521
522 static HRESULT WINAPI HTMLDocument_put_fgColor(IHTMLDocument2 *iface, VARIANT v)
523 {
524     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
525     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
526     return E_NOTIMPL;
527 }
528
529 static HRESULT WINAPI HTMLDocument_get_fgColor(IHTMLDocument2 *iface, VARIANT *p)
530 {
531     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
532     FIXME("(%p)->(%p)\n", This, p);
533     return E_NOTIMPL;
534 }
535
536 static HRESULT WINAPI HTMLDocument_put_linkColor(IHTMLDocument2 *iface, VARIANT v)
537 {
538     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
539     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
540     return E_NOTIMPL;
541 }
542
543 static HRESULT WINAPI HTMLDocument_get_linkColor(IHTMLDocument2 *iface, VARIANT *p)
544 {
545     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
546     FIXME("(%p)->(%p)\n", This, p);
547     return E_NOTIMPL;
548 }
549
550 static HRESULT WINAPI HTMLDocument_put_vlinkColor(IHTMLDocument2 *iface, VARIANT v)
551 {
552     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
553     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
554     return E_NOTIMPL;
555 }
556
557 static HRESULT WINAPI HTMLDocument_get_vlinkColor(IHTMLDocument2 *iface, VARIANT *p)
558 {
559     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
560     FIXME("(%p)->(%p)\n", This, p);
561     return E_NOTIMPL;
562 }
563
564 static HRESULT WINAPI HTMLDocument_get_referrer(IHTMLDocument2 *iface, BSTR *p)
565 {
566     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
567
568     FIXME("(%p)->(%p)\n", This, p);
569
570     *p = NULL;
571     return S_OK;
572  }
573
574 static HRESULT WINAPI HTMLDocument_get_location(IHTMLDocument2 *iface, IHTMLLocation **p)
575 {
576     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
577
578     TRACE("(%p)->(%p)\n", This, p);
579
580     if(!This->doc_node->nsdoc) {
581         WARN("NULL nsdoc\n");
582         return E_UNEXPECTED;
583     }
584
585     return IHTMLWindow2_get_location(&This->window->IHTMLWindow2_iface, p);
586 }
587
588 static HRESULT WINAPI HTMLDocument_get_lastModified(IHTMLDocument2 *iface, BSTR *p)
589 {
590     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
591     FIXME("(%p)->(%p)\n", This, p);
592     return E_NOTIMPL;
593 }
594
595 static HRESULT WINAPI HTMLDocument_put_URL(IHTMLDocument2 *iface, BSTR v)
596 {
597     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
598
599     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
600
601     if(!This->window) {
602         FIXME("No window available\n");
603         return E_FAIL;
604     }
605
606     return navigate_url(This->window, v, This->window->url);
607 }
608
609 static HRESULT WINAPI HTMLDocument_get_URL(IHTMLDocument2 *iface, BSTR *p)
610 {
611     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
612
613     static const WCHAR about_blank_url[] =
614         {'a','b','o','u','t',':','b','l','a','n','k',0};
615
616     TRACE("(%p)->(%p)\n", iface, p);
617
618     *p = SysAllocString(This->window->url ? This->window->url : about_blank_url);
619     return *p ? S_OK : E_OUTOFMEMORY;
620 }
621
622 static HRESULT WINAPI HTMLDocument_put_domain(IHTMLDocument2 *iface, BSTR v)
623 {
624     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
625     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
626     return E_NOTIMPL;
627 }
628
629 static HRESULT WINAPI HTMLDocument_get_domain(IHTMLDocument2 *iface, BSTR *p)
630 {
631     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
632     HRESULT hres;
633
634     TRACE("(%p)->(%p)\n", This, p);
635
636     if(!This->window || !This->window->uri) {
637         FIXME("No current URI\n");
638         return E_FAIL;
639     }
640
641     hres = IUri_GetHost(This->window->uri, p);
642     return FAILED(hres) ? hres : S_OK;
643 }
644
645 static HRESULT WINAPI HTMLDocument_put_cookie(IHTMLDocument2 *iface, BSTR v)
646 {
647     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
648     BOOL bret;
649
650     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
651
652     bret = InternetSetCookieExW(This->window->url, NULL, v, 0, 0);
653     if(!bret) {
654         FIXME("InternetSetCookieExW failed: %u\n", GetLastError());
655         return HRESULT_FROM_WIN32(GetLastError());
656     }
657
658     return S_OK;
659 }
660
661 static HRESULT WINAPI HTMLDocument_get_cookie(IHTMLDocument2 *iface, BSTR *p)
662 {
663     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
664     DWORD size;
665     BOOL bret;
666
667     TRACE("(%p)->(%p)\n", This, p);
668
669     size = 0;
670     bret = InternetGetCookieExW(This->window->url, NULL, NULL, &size, 0, NULL);
671     if(!bret) {
672         switch(GetLastError()) {
673         case ERROR_INSUFFICIENT_BUFFER:
674             break;
675         case ERROR_NO_MORE_ITEMS:
676             *p = NULL;
677             return S_OK;
678         default:
679             FIXME("InternetGetCookieExW failed: %u\n", GetLastError());
680             return HRESULT_FROM_WIN32(GetLastError());
681         }
682     }
683
684     if(!size) {
685         *p = NULL;
686         return S_OK;
687     }
688
689     *p = SysAllocStringLen(NULL, size-1);
690     if(!*p)
691         return E_OUTOFMEMORY;
692
693     bret = InternetGetCookieExW(This->window->url, NULL, *p, &size, 0, NULL);
694     if(!bret) {
695         ERR("InternetGetCookieExW failed: %u\n", GetLastError());
696         return E_FAIL;
697     }
698
699     return S_OK;
700 }
701
702 static HRESULT WINAPI HTMLDocument_put_expando(IHTMLDocument2 *iface, VARIANT_BOOL v)
703 {
704     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
705     FIXME("(%p)->(%x)\n", This, v);
706     return E_NOTIMPL;
707 }
708
709 static HRESULT WINAPI HTMLDocument_get_expando(IHTMLDocument2 *iface, VARIANT_BOOL *p)
710 {
711     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
712     FIXME("(%p)->(%p)\n", This, p);
713     return E_NOTIMPL;
714 }
715
716 static HRESULT WINAPI HTMLDocument_put_charset(IHTMLDocument2 *iface, BSTR v)
717 {
718     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
719     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
720     return E_NOTIMPL;
721 }
722
723 static HRESULT WINAPI HTMLDocument_get_charset(IHTMLDocument2 *iface, BSTR *p)
724 {
725     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
726     FIXME("(%p)->(%p)\n", This, p);
727     return E_NOTIMPL;
728 }
729
730 static HRESULT WINAPI HTMLDocument_put_defaultCharset(IHTMLDocument2 *iface, BSTR v)
731 {
732     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
733     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
734     return E_NOTIMPL;
735 }
736
737 static HRESULT WINAPI HTMLDocument_get_defaultCharset(IHTMLDocument2 *iface, BSTR *p)
738 {
739     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
740     FIXME("(%p)->(%p)\n", This, p);
741     return E_NOTIMPL;
742 }
743
744 static HRESULT WINAPI HTMLDocument_get_mimeType(IHTMLDocument2 *iface, BSTR *p)
745 {
746     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
747     FIXME("(%p)->(%p)\n", This, p);
748     return E_NOTIMPL;
749 }
750
751 static HRESULT WINAPI HTMLDocument_get_fileSize(IHTMLDocument2 *iface, BSTR *p)
752 {
753     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
754     FIXME("(%p)->(%p)\n", This, p);
755     return E_NOTIMPL;
756 }
757
758 static HRESULT WINAPI HTMLDocument_get_fileCreatedDate(IHTMLDocument2 *iface, BSTR *p)
759 {
760     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
761     FIXME("(%p)->(%p)\n", This, p);
762     return E_NOTIMPL;
763 }
764
765 static HRESULT WINAPI HTMLDocument_get_fileModifiedDate(IHTMLDocument2 *iface, BSTR *p)
766 {
767     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
768     FIXME("(%p)->(%p)\n", This, p);
769     return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI HTMLDocument_get_fileUpdatedDate(IHTMLDocument2 *iface, BSTR *p)
773 {
774     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
775     FIXME("(%p)->(%p)\n", This, p);
776     return E_NOTIMPL;
777 }
778
779 static HRESULT WINAPI HTMLDocument_get_security(IHTMLDocument2 *iface, BSTR *p)
780 {
781     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
782     FIXME("(%p)->(%p)\n", This, p);
783     return E_NOTIMPL;
784 }
785
786 static HRESULT WINAPI HTMLDocument_get_protocol(IHTMLDocument2 *iface, BSTR *p)
787 {
788     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
789     FIXME("(%p)->(%p)\n", This, p);
790     return E_NOTIMPL;
791 }
792
793 static HRESULT WINAPI HTMLDocument_get_nameProp(IHTMLDocument2 *iface, BSTR *p)
794 {
795     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
796     FIXME("(%p)->(%p)\n", This, p);
797     return E_NOTIMPL;
798 }
799
800 static HRESULT document_write(HTMLDocument *This, SAFEARRAY *psarray, BOOL ln)
801 {
802     nsAString nsstr;
803     VARIANT *var;
804     ULONG i, argc;
805     nsresult nsres;
806     HRESULT hres;
807
808     if(!This->doc_node->nsdoc) {
809         WARN("NULL nsdoc\n");
810         return E_UNEXPECTED;
811     }
812
813     if (!psarray)
814         return S_OK;
815
816     if(psarray->cDims != 1) {
817         FIXME("cDims=%d\n", psarray->cDims);
818         return E_INVALIDARG;
819     }
820
821     hres = SafeArrayAccessData(psarray, (void**)&var);
822     if(FAILED(hres)) {
823         WARN("SafeArrayAccessData failed: %08x\n", hres);
824         return hres;
825     }
826
827     nsAString_Init(&nsstr, NULL);
828
829     argc = psarray->rgsabound[0].cElements;
830     for(i=0; i < argc; i++) {
831         if(V_VT(var+i) == VT_BSTR) {
832             nsAString_SetData(&nsstr, V_BSTR(var+i));
833             if(!ln || i != argc-1)
834                 nsres = nsIDOMHTMLDocument_Write(This->doc_node->nsdoc, &nsstr, NULL /* FIXME! */);
835             else
836                 nsres = nsIDOMHTMLDocument_Writeln(This->doc_node->nsdoc, &nsstr, NULL /* FIXME! */);
837             if(NS_FAILED(nsres))
838                 ERR("Write failed: %08x\n", nsres);
839         }else {
840             FIXME("unsupported arg[%d] = %s\n", i, debugstr_variant(var+i));
841         }
842     }
843
844     nsAString_Finish(&nsstr);
845     SafeArrayUnaccessData(psarray);
846
847     return S_OK;
848 }
849
850 static HRESULT WINAPI HTMLDocument_write(IHTMLDocument2 *iface, SAFEARRAY *psarray)
851 {
852     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
853
854     TRACE("(%p)->(%p)\n", iface, psarray);
855
856     return document_write(This, psarray, FALSE);
857 }
858
859 static HRESULT WINAPI HTMLDocument_writeln(IHTMLDocument2 *iface, SAFEARRAY *psarray)
860 {
861     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
862
863     TRACE("(%p)->(%p)\n", This, psarray);
864
865     return document_write(This, psarray, TRUE);
866 }
867
868 static HRESULT WINAPI HTMLDocument_open(IHTMLDocument2 *iface, BSTR url, VARIANT name,
869                         VARIANT features, VARIANT replace, IDispatch **pomWindowResult)
870 {
871     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
872     nsISupports *tmp;
873     nsresult nsres;
874
875     static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
876
877     TRACE("(%p)->(%s %s %s %s %p)\n", This, debugstr_w(url), debugstr_variant(&name),
878           debugstr_variant(&features), debugstr_variant(&replace), pomWindowResult);
879
880     if(!This->doc_node->nsdoc) {
881         ERR("!nsdoc\n");
882         return E_NOTIMPL;
883     }
884
885     if(!url || strcmpW(url, text_htmlW) || V_VT(&name) != VT_ERROR
886        || V_VT(&features) != VT_ERROR || V_VT(&replace) != VT_ERROR)
887         FIXME("unsupported args\n");
888
889     nsres = nsIDOMHTMLDocument_Open(This->doc_node->nsdoc, NULL, NULL, NULL, NULL, 0, &tmp);
890     if(NS_FAILED(nsres)) {
891         ERR("Open failed: %08x\n", nsres);
892         return E_FAIL;
893     }
894
895     if(tmp)
896         nsISupports_Release(tmp);
897
898     *pomWindowResult = (IDispatch*)&This->window->IHTMLWindow2_iface;
899     IHTMLWindow2_AddRef(&This->window->IHTMLWindow2_iface);
900     return S_OK;
901 }
902
903 static HRESULT WINAPI HTMLDocument_close(IHTMLDocument2 *iface)
904 {
905     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
906     nsresult nsres;
907
908     TRACE("(%p)\n", This);
909
910     if(!This->doc_node->nsdoc) {
911         ERR("!nsdoc\n");
912         return E_NOTIMPL;
913     }
914
915     nsres = nsIDOMHTMLDocument_Close(This->doc_node->nsdoc);
916     if(NS_FAILED(nsres)) {
917         ERR("Close failed: %08x\n", nsres);
918         return E_FAIL;
919     }
920
921     return S_OK;
922 }
923
924 static HRESULT WINAPI HTMLDocument_clear(IHTMLDocument2 *iface)
925 {
926     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
927     nsresult nsres;
928
929     TRACE("(%p)\n", This);
930
931     nsres = nsIDOMHTMLDocument_Clear(This->doc_node->nsdoc);
932     if(NS_FAILED(nsres)) {
933         ERR("Clear failed: %08x\n", nsres);
934         return E_FAIL;
935     }
936
937     return S_OK;
938 }
939
940 static HRESULT WINAPI HTMLDocument_queryCommandSupported(IHTMLDocument2 *iface, BSTR cmdID,
941                                                         VARIANT_BOOL *pfRet)
942 {
943     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
944     FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
945     return E_NOTIMPL;
946 }
947
948 static HRESULT WINAPI HTMLDocument_queryCommandEnabled(IHTMLDocument2 *iface, BSTR cmdID,
949                                                         VARIANT_BOOL *pfRet)
950 {
951     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
952     FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
953     return E_NOTIMPL;
954 }
955
956 static HRESULT WINAPI HTMLDocument_queryCommandState(IHTMLDocument2 *iface, BSTR cmdID,
957                                                         VARIANT_BOOL *pfRet)
958 {
959     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
960     FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
961     return E_NOTIMPL;
962 }
963
964 static HRESULT WINAPI HTMLDocument_queryCommandIndeterm(IHTMLDocument2 *iface, BSTR cmdID,
965                                                         VARIANT_BOOL *pfRet)
966 {
967     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
968     FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
969     return E_NOTIMPL;
970 }
971
972 static HRESULT WINAPI HTMLDocument_queryCommandText(IHTMLDocument2 *iface, BSTR cmdID,
973                                                         BSTR *pfRet)
974 {
975     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
976     FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
977     return E_NOTIMPL;
978 }
979
980 static HRESULT WINAPI HTMLDocument_queryCommandValue(IHTMLDocument2 *iface, BSTR cmdID,
981                                                         VARIANT *pfRet)
982 {
983     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
984     FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
985     return E_NOTIMPL;
986 }
987
988 static HRESULT WINAPI HTMLDocument_execCommand(IHTMLDocument2 *iface, BSTR cmdID,
989                                 VARIANT_BOOL showUI, VARIANT value, VARIANT_BOOL *pfRet)
990 {
991     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
992     FIXME("(%p)->(%s %x %s %p)\n", This, debugstr_w(cmdID), showUI, debugstr_variant(&value), pfRet);
993     return E_NOTIMPL;
994 }
995
996 static HRESULT WINAPI HTMLDocument_execCommandShowHelp(IHTMLDocument2 *iface, BSTR cmdID,
997                                                         VARIANT_BOOL *pfRet)
998 {
999     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1000     FIXME("(%p)->(%s %p)\n", This, debugstr_w(cmdID), pfRet);
1001     return E_NOTIMPL;
1002 }
1003
1004 static HRESULT WINAPI HTMLDocument_createElement(IHTMLDocument2 *iface, BSTR eTag,
1005                                                  IHTMLElement **newElem)
1006 {
1007     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1008     nsIDOMHTMLElement *nselem;
1009     HTMLElement *elem;
1010     HRESULT hres;
1011
1012     TRACE("(%p)->(%s %p)\n", This, debugstr_w(eTag), newElem);
1013
1014     hres = create_nselem(This->doc_node, eTag, &nselem);
1015     if(FAILED(hres))
1016         return hres;
1017
1018     hres = HTMLElement_Create(This->doc_node, (nsIDOMNode*)nselem, TRUE, &elem);
1019     nsIDOMHTMLElement_Release(nselem);
1020     if(FAILED(hres))
1021         return hres;
1022
1023     *newElem = &elem->IHTMLElement_iface;
1024     IHTMLElement_AddRef(&elem->IHTMLElement_iface);
1025     return S_OK;
1026 }
1027
1028 static HRESULT WINAPI HTMLDocument_put_onhelp(IHTMLDocument2 *iface, VARIANT v)
1029 {
1030     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1031     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1032     return E_NOTIMPL;
1033 }
1034
1035 static HRESULT WINAPI HTMLDocument_get_onhelp(IHTMLDocument2 *iface, VARIANT *p)
1036 {
1037     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1038     FIXME("(%p)->(%p)\n", This, p);
1039     return E_NOTIMPL;
1040 }
1041
1042 static HRESULT WINAPI HTMLDocument_put_onclick(IHTMLDocument2 *iface, VARIANT v)
1043 {
1044     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1045
1046     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1047
1048     return set_doc_event(This, EVENTID_CLICK, &v);
1049 }
1050
1051 static HRESULT WINAPI HTMLDocument_get_onclick(IHTMLDocument2 *iface, VARIANT *p)
1052 {
1053     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1054
1055     TRACE("(%p)->(%p)\n", This, p);
1056
1057     return get_doc_event(This, EVENTID_CLICK, p);
1058 }
1059
1060 static HRESULT WINAPI HTMLDocument_put_ondblclick(IHTMLDocument2 *iface, VARIANT v)
1061 {
1062     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1063     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1064     return E_NOTIMPL;
1065 }
1066
1067 static HRESULT WINAPI HTMLDocument_get_ondblclick(IHTMLDocument2 *iface, VARIANT *p)
1068 {
1069     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1070     FIXME("(%p)->(%p)\n", This, p);
1071     return E_NOTIMPL;
1072 }
1073
1074 static HRESULT WINAPI HTMLDocument_put_onkeyup(IHTMLDocument2 *iface, VARIANT v)
1075 {
1076     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1077
1078     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1079
1080     return set_doc_event(This, EVENTID_KEYUP, &v);
1081 }
1082
1083 static HRESULT WINAPI HTMLDocument_get_onkeyup(IHTMLDocument2 *iface, VARIANT *p)
1084 {
1085     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1086
1087     TRACE("(%p)->(%p)\n", This, p);
1088
1089     return get_doc_event(This, EVENTID_KEYUP, p);
1090 }
1091
1092 static HRESULT WINAPI HTMLDocument_put_onkeydown(IHTMLDocument2 *iface, VARIANT v)
1093 {
1094     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1095
1096     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1097
1098     return set_doc_event(This, EVENTID_KEYDOWN, &v);
1099 }
1100
1101 static HRESULT WINAPI HTMLDocument_get_onkeydown(IHTMLDocument2 *iface, VARIANT *p)
1102 {
1103     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1104
1105     TRACE("(%p)->(%p)\n", This, p);
1106
1107     return get_doc_event(This, EVENTID_KEYDOWN, p);
1108 }
1109
1110 static HRESULT WINAPI HTMLDocument_put_onkeypress(IHTMLDocument2 *iface, VARIANT v)
1111 {
1112     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1113
1114     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1115
1116     return set_doc_event(This, EVENTID_KEYPRESS, &v);
1117 }
1118
1119 static HRESULT WINAPI HTMLDocument_get_onkeypress(IHTMLDocument2 *iface, VARIANT *p)
1120 {
1121     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1122
1123     TRACE("(%p)->(%p)\n", This, p);
1124
1125     return get_doc_event(This, EVENTID_KEYPRESS, p);
1126 }
1127
1128 static HRESULT WINAPI HTMLDocument_put_onmouseup(IHTMLDocument2 *iface, VARIANT v)
1129 {
1130     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1131
1132     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1133
1134     return set_doc_event(This, EVENTID_MOUSEUP, &v);
1135 }
1136
1137 static HRESULT WINAPI HTMLDocument_get_onmouseup(IHTMLDocument2 *iface, VARIANT *p)
1138 {
1139     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1140
1141     TRACE("(%p)->(%p)\n", This, p);
1142
1143     return get_doc_event(This, EVENTID_MOUSEUP, p);
1144 }
1145
1146 static HRESULT WINAPI HTMLDocument_put_onmousedown(IHTMLDocument2 *iface, VARIANT v)
1147 {
1148     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1149
1150     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1151
1152     return set_doc_event(This, EVENTID_MOUSEDOWN, &v);
1153 }
1154
1155 static HRESULT WINAPI HTMLDocument_get_onmousedown(IHTMLDocument2 *iface, VARIANT *p)
1156 {
1157     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1158
1159     TRACE("(%p)->(%p)\n", This, p);
1160
1161     return get_doc_event(This, EVENTID_MOUSEDOWN, p);
1162 }
1163
1164 static HRESULT WINAPI HTMLDocument_put_onmousemove(IHTMLDocument2 *iface, VARIANT v)
1165 {
1166     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1167
1168     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1169
1170     return set_doc_event(This, EVENTID_MOUSEMOVE, &v);
1171 }
1172
1173 static HRESULT WINAPI HTMLDocument_get_onmousemove(IHTMLDocument2 *iface, VARIANT *p)
1174 {
1175     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1176
1177     TRACE("(%p)->(%p)\n", This, p);
1178
1179     return get_doc_event(This, EVENTID_MOUSEMOVE, p);
1180 }
1181
1182 static HRESULT WINAPI HTMLDocument_put_onmouseout(IHTMLDocument2 *iface, VARIANT v)
1183 {
1184     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1185
1186     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1187
1188     return set_doc_event(This, EVENTID_MOUSEOUT, &v);
1189 }
1190
1191 static HRESULT WINAPI HTMLDocument_get_onmouseout(IHTMLDocument2 *iface, VARIANT *p)
1192 {
1193     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1194
1195     TRACE("(%p)->(%p)\n", This, p);
1196
1197     return get_doc_event(This, EVENTID_MOUSEOUT, p);
1198 }
1199
1200 static HRESULT WINAPI HTMLDocument_put_onmouseover(IHTMLDocument2 *iface, VARIANT v)
1201 {
1202     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1203
1204     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1205
1206     return set_doc_event(This, EVENTID_MOUSEOVER, &v);
1207 }
1208
1209 static HRESULT WINAPI HTMLDocument_get_onmouseover(IHTMLDocument2 *iface, VARIANT *p)
1210 {
1211     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1212
1213     TRACE("(%p)->(%p)\n", This, p);
1214
1215     return get_doc_event(This, EVENTID_MOUSEOVER, p);
1216 }
1217
1218 static HRESULT WINAPI HTMLDocument_put_onreadystatechange(IHTMLDocument2 *iface, VARIANT v)
1219 {
1220     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1221
1222     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1223
1224     return set_doc_event(This, EVENTID_READYSTATECHANGE, &v);
1225 }
1226
1227 static HRESULT WINAPI HTMLDocument_get_onreadystatechange(IHTMLDocument2 *iface, VARIANT *p)
1228 {
1229     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1230
1231     TRACE("(%p)->(%p)\n", This, p);
1232
1233     return get_doc_event(This, EVENTID_READYSTATECHANGE, p);
1234 }
1235
1236 static HRESULT WINAPI HTMLDocument_put_onafterupdate(IHTMLDocument2 *iface, VARIANT v)
1237 {
1238     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1239     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1240     return E_NOTIMPL;
1241 }
1242
1243 static HRESULT WINAPI HTMLDocument_get_onafterupdate(IHTMLDocument2 *iface, VARIANT *p)
1244 {
1245     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1246     FIXME("(%p)->(%p)\n", This, p);
1247     return E_NOTIMPL;
1248 }
1249
1250 static HRESULT WINAPI HTMLDocument_put_onrowexit(IHTMLDocument2 *iface, VARIANT v)
1251 {
1252     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1253     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1254     return E_NOTIMPL;
1255 }
1256
1257 static HRESULT WINAPI HTMLDocument_get_onrowexit(IHTMLDocument2 *iface, VARIANT *p)
1258 {
1259     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1260     FIXME("(%p)->(%p)\n", This, p);
1261     return E_NOTIMPL;
1262 }
1263
1264 static HRESULT WINAPI HTMLDocument_put_onrowenter(IHTMLDocument2 *iface, VARIANT v)
1265 {
1266     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1267     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1268     return E_NOTIMPL;
1269 }
1270
1271 static HRESULT WINAPI HTMLDocument_get_onrowenter(IHTMLDocument2 *iface, VARIANT *p)
1272 {
1273     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1274     FIXME("(%p)->(%p)\n", This, p);
1275     return E_NOTIMPL;
1276 }
1277
1278 static HRESULT WINAPI HTMLDocument_put_ondragstart(IHTMLDocument2 *iface, VARIANT v)
1279 {
1280     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1281
1282     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1283
1284     return set_doc_event(This, EVENTID_DRAGSTART, &v);
1285 }
1286
1287 static HRESULT WINAPI HTMLDocument_get_ondragstart(IHTMLDocument2 *iface, VARIANT *p)
1288 {
1289     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1290
1291     TRACE("(%p)->(%p)\n", This, p);
1292
1293     return get_doc_event(This, EVENTID_DRAGSTART, p);
1294 }
1295
1296 static HRESULT WINAPI HTMLDocument_put_onselectstart(IHTMLDocument2 *iface, VARIANT v)
1297 {
1298     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1299
1300     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1301
1302     return set_doc_event(This, EVENTID_SELECTSTART, &v);
1303 }
1304
1305 static HRESULT WINAPI HTMLDocument_get_onselectstart(IHTMLDocument2 *iface, VARIANT *p)
1306 {
1307     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1308
1309     TRACE("(%p)->(%p)\n", This, p);
1310
1311     return get_doc_event(This, EVENTID_SELECTSTART, p);
1312 }
1313
1314 static HRESULT WINAPI HTMLDocument_elementFromPoint(IHTMLDocument2 *iface, LONG x, LONG y,
1315                                                         IHTMLElement **elementHit)
1316 {
1317     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1318     nsIDOMElement *nselem;
1319     HTMLDOMNode *node;
1320     nsresult nsres;
1321     HRESULT hres;
1322
1323     TRACE("(%p)->(%d %d %p)\n", This, x, y, elementHit);
1324
1325     nsres = nsIDOMHTMLDocument_ElementFromPoint(This->doc_node->nsdoc, x, y, &nselem);
1326     if(NS_FAILED(nsres)) {
1327         ERR("ElementFromPoint failed: %08x\n", nsres);
1328         return E_FAIL;
1329     }
1330
1331     if(!nselem) {
1332         *elementHit = NULL;
1333         return S_OK;
1334     }
1335
1336     hres = get_node(This->doc_node, (nsIDOMNode*)nselem, TRUE, &node);
1337     nsIDOMElement_Release(nselem);
1338     if(FAILED(hres))
1339         return hres;
1340
1341     return IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_IHTMLElement, (void**)elementHit);
1342 }
1343
1344 static HRESULT WINAPI HTMLDocument_get_parentWindow(IHTMLDocument2 *iface, IHTMLWindow2 **p)
1345 {
1346     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1347
1348     TRACE("(%p)->(%p)\n", This, p);
1349
1350     *p = &This->window->IHTMLWindow2_iface;
1351     IHTMLWindow2_AddRef(*p);
1352     return S_OK;
1353 }
1354
1355 static HRESULT WINAPI HTMLDocument_get_styleSheets(IHTMLDocument2 *iface,
1356                                                    IHTMLStyleSheetsCollection **p)
1357 {
1358     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1359     nsIDOMStyleSheetList *nsstylelist;
1360     nsresult nsres;
1361
1362     TRACE("(%p)->(%p)\n", This, p);
1363
1364     *p = NULL;
1365
1366     if(!This->doc_node->nsdoc) {
1367         WARN("NULL nsdoc\n");
1368         return E_UNEXPECTED;
1369     }
1370
1371     nsres = nsIDOMHTMLDocument_GetStyleSheets(This->doc_node->nsdoc, &nsstylelist);
1372     if(NS_FAILED(nsres)) {
1373         ERR("GetStyleSheets failed: %08x\n", nsres);
1374         return E_FAIL;
1375     }
1376
1377     *p = HTMLStyleSheetsCollection_Create(nsstylelist);
1378     nsIDOMStyleSheetList_Release(nsstylelist);
1379
1380     return S_OK;
1381 }
1382
1383 static HRESULT WINAPI HTMLDocument_put_onbeforeupdate(IHTMLDocument2 *iface, VARIANT v)
1384 {
1385     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1386     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1387     return E_NOTIMPL;
1388 }
1389
1390 static HRESULT WINAPI HTMLDocument_get_onbeforeupdate(IHTMLDocument2 *iface, VARIANT *p)
1391 {
1392     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1393     FIXME("(%p)->(%p)\n", This, p);
1394     return E_NOTIMPL;
1395 }
1396
1397 static HRESULT WINAPI HTMLDocument_put_onerrorupdate(IHTMLDocument2 *iface, VARIANT v)
1398 {
1399     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1400     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1401     return E_NOTIMPL;
1402 }
1403
1404 static HRESULT WINAPI HTMLDocument_get_onerrorupdate(IHTMLDocument2 *iface, VARIANT *p)
1405 {
1406     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1407     FIXME("(%p)->(%p)\n", This, p);
1408     return E_NOTIMPL;
1409 }
1410
1411 static HRESULT WINAPI HTMLDocument_toString(IHTMLDocument2 *iface, BSTR *String)
1412 {
1413     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1414     FIXME("(%p)->(%p)\n", This, String);
1415     return E_NOTIMPL;
1416 }
1417
1418 static HRESULT WINAPI HTMLDocument_createStyleSheet(IHTMLDocument2 *iface, BSTR bstrHref,
1419                                             LONG lIndex, IHTMLStyleSheet **ppnewStyleSheet)
1420 {
1421     HTMLDocument *This = impl_from_IHTMLDocument2(iface);
1422
1423     FIXME("(%p)->(%s %d %p) semi-stub\n", This, debugstr_w(bstrHref), lIndex, ppnewStyleSheet);
1424
1425     *ppnewStyleSheet = HTMLStyleSheet_Create(NULL);
1426     return S_OK;
1427 }
1428
1429 static const IHTMLDocument2Vtbl HTMLDocumentVtbl = {
1430     HTMLDocument_QueryInterface,
1431     HTMLDocument_AddRef,
1432     HTMLDocument_Release,
1433     HTMLDocument_GetTypeInfoCount,
1434     HTMLDocument_GetTypeInfo,
1435     HTMLDocument_GetIDsOfNames,
1436     HTMLDocument_Invoke,
1437     HTMLDocument_get_Script,
1438     HTMLDocument_get_all,
1439     HTMLDocument_get_body,
1440     HTMLDocument_get_activeElement,
1441     HTMLDocument_get_images,
1442     HTMLDocument_get_applets,
1443     HTMLDocument_get_links,
1444     HTMLDocument_get_forms,
1445     HTMLDocument_get_anchors,
1446     HTMLDocument_put_title,
1447     HTMLDocument_get_title,
1448     HTMLDocument_get_scripts,
1449     HTMLDocument_put_designMode,
1450     HTMLDocument_get_designMode,
1451     HTMLDocument_get_selection,
1452     HTMLDocument_get_readyState,
1453     HTMLDocument_get_frames,
1454     HTMLDocument_get_embeds,
1455     HTMLDocument_get_plugins,
1456     HTMLDocument_put_alinkColor,
1457     HTMLDocument_get_alinkColor,
1458     HTMLDocument_put_bgColor,
1459     HTMLDocument_get_bgColor,
1460     HTMLDocument_put_fgColor,
1461     HTMLDocument_get_fgColor,
1462     HTMLDocument_put_linkColor,
1463     HTMLDocument_get_linkColor,
1464     HTMLDocument_put_vlinkColor,
1465     HTMLDocument_get_vlinkColor,
1466     HTMLDocument_get_referrer,
1467     HTMLDocument_get_location,
1468     HTMLDocument_get_lastModified,
1469     HTMLDocument_put_URL,
1470     HTMLDocument_get_URL,
1471     HTMLDocument_put_domain,
1472     HTMLDocument_get_domain,
1473     HTMLDocument_put_cookie,
1474     HTMLDocument_get_cookie,
1475     HTMLDocument_put_expando,
1476     HTMLDocument_get_expando,
1477     HTMLDocument_put_charset,
1478     HTMLDocument_get_charset,
1479     HTMLDocument_put_defaultCharset,
1480     HTMLDocument_get_defaultCharset,
1481     HTMLDocument_get_mimeType,
1482     HTMLDocument_get_fileSize,
1483     HTMLDocument_get_fileCreatedDate,
1484     HTMLDocument_get_fileModifiedDate,
1485     HTMLDocument_get_fileUpdatedDate,
1486     HTMLDocument_get_security,
1487     HTMLDocument_get_protocol,
1488     HTMLDocument_get_nameProp,
1489     HTMLDocument_write,
1490     HTMLDocument_writeln,
1491     HTMLDocument_open,
1492     HTMLDocument_close,
1493     HTMLDocument_clear,
1494     HTMLDocument_queryCommandSupported,
1495     HTMLDocument_queryCommandEnabled,
1496     HTMLDocument_queryCommandState,
1497     HTMLDocument_queryCommandIndeterm,
1498     HTMLDocument_queryCommandText,
1499     HTMLDocument_queryCommandValue,
1500     HTMLDocument_execCommand,
1501     HTMLDocument_execCommandShowHelp,
1502     HTMLDocument_createElement,
1503     HTMLDocument_put_onhelp,
1504     HTMLDocument_get_onhelp,
1505     HTMLDocument_put_onclick,
1506     HTMLDocument_get_onclick,
1507     HTMLDocument_put_ondblclick,
1508     HTMLDocument_get_ondblclick,
1509     HTMLDocument_put_onkeyup,
1510     HTMLDocument_get_onkeyup,
1511     HTMLDocument_put_onkeydown,
1512     HTMLDocument_get_onkeydown,
1513     HTMLDocument_put_onkeypress,
1514     HTMLDocument_get_onkeypress,
1515     HTMLDocument_put_onmouseup,
1516     HTMLDocument_get_onmouseup,
1517     HTMLDocument_put_onmousedown,
1518     HTMLDocument_get_onmousedown,
1519     HTMLDocument_put_onmousemove,
1520     HTMLDocument_get_onmousemove,
1521     HTMLDocument_put_onmouseout,
1522     HTMLDocument_get_onmouseout,
1523     HTMLDocument_put_onmouseover,
1524     HTMLDocument_get_onmouseover,
1525     HTMLDocument_put_onreadystatechange,
1526     HTMLDocument_get_onreadystatechange,
1527     HTMLDocument_put_onafterupdate,
1528     HTMLDocument_get_onafterupdate,
1529     HTMLDocument_put_onrowexit,
1530     HTMLDocument_get_onrowexit,
1531     HTMLDocument_put_onrowenter,
1532     HTMLDocument_get_onrowenter,
1533     HTMLDocument_put_ondragstart,
1534     HTMLDocument_get_ondragstart,
1535     HTMLDocument_put_onselectstart,
1536     HTMLDocument_get_onselectstart,
1537     HTMLDocument_elementFromPoint,
1538     HTMLDocument_get_parentWindow,
1539     HTMLDocument_get_styleSheets,
1540     HTMLDocument_put_onbeforeupdate,
1541     HTMLDocument_get_onbeforeupdate,
1542     HTMLDocument_put_onerrorupdate,
1543     HTMLDocument_get_onerrorupdate,
1544     HTMLDocument_toString,
1545     HTMLDocument_createStyleSheet
1546 };
1547
1548 static void HTMLDocument_on_advise(IUnknown *iface, cp_static_data_t *cp)
1549 {
1550     HTMLDocument *This = impl_from_IHTMLDocument2((IHTMLDocument2*)iface);
1551
1552     if(This->window)
1553         update_cp_events(This->window, &This->doc_node->node.event_target, cp, This->doc_node->node.nsnode);
1554 }
1555
1556 static inline HTMLDocument *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
1557 {
1558     return CONTAINING_RECORD(iface, HTMLDocument, ISupportErrorInfo_iface);
1559 }
1560
1561 static HRESULT WINAPI SupportErrorInfo_QueryInterface(ISupportErrorInfo *iface, REFIID riid, void **ppv)
1562 {
1563     HTMLDocument *This = impl_from_ISupportErrorInfo(iface);
1564     return htmldoc_query_interface(This, riid, ppv);
1565 }
1566
1567 static ULONG WINAPI SupportErrorInfo_AddRef(ISupportErrorInfo *iface)
1568 {
1569     HTMLDocument *This = impl_from_ISupportErrorInfo(iface);
1570     return htmldoc_addref(This);
1571 }
1572
1573 static ULONG WINAPI SupportErrorInfo_Release(ISupportErrorInfo *iface)
1574 {
1575     HTMLDocument *This = impl_from_ISupportErrorInfo(iface);
1576     return htmldoc_release(This);
1577 }
1578
1579 static HRESULT WINAPI SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo *iface, REFIID riid)
1580 {
1581     FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
1582     return S_FALSE;
1583 }
1584
1585 static const ISupportErrorInfoVtbl SupportErrorInfoVtbl = {
1586     SupportErrorInfo_QueryInterface,
1587     SupportErrorInfo_AddRef,
1588     SupportErrorInfo_Release,
1589     SupportErrorInfo_InterfaceSupportsErrorInfo
1590 };
1591
1592 static inline HTMLDocument *impl_from_IDispatchEx(IDispatchEx *iface)
1593 {
1594     return CONTAINING_RECORD(iface, HTMLDocument, IDispatchEx_iface);
1595 }
1596
1597 static HRESULT dispid_from_elem_name(HTMLDocumentNode *This, BSTR name, DISPID *dispid)
1598 {
1599     nsIDOMNodeList *node_list;
1600     nsAString name_str;
1601     PRUint32 len;
1602     unsigned i;
1603     nsresult nsres;
1604
1605     if(!This->nsdoc)
1606         return DISP_E_UNKNOWNNAME;
1607
1608     nsAString_InitDepend(&name_str, name);
1609     nsres = nsIDOMHTMLDocument_GetElementsByName(This->nsdoc, &name_str, &node_list);
1610     nsAString_Finish(&name_str);
1611     if(NS_FAILED(nsres))
1612         return E_FAIL;
1613
1614     nsres = nsIDOMNodeList_GetLength(node_list, &len);
1615     nsIDOMNodeList_Release(node_list);
1616     if(NS_FAILED(nsres))
1617         return E_FAIL;
1618
1619     if(!len)
1620         return DISP_E_UNKNOWNNAME;
1621
1622     for(i=0; i < This->elem_vars_cnt; i++) {
1623         if(!strcmpW(name, This->elem_vars[i])) {
1624             *dispid = MSHTML_DISPID_CUSTOM_MIN+i;
1625             return S_OK;
1626         }
1627     }
1628
1629     if(This->elem_vars_cnt == This->elem_vars_size) {
1630         WCHAR **new_vars;
1631
1632         if(This->elem_vars_size) {
1633             new_vars = heap_realloc(This->elem_vars, This->elem_vars_size*2*sizeof(WCHAR*));
1634             if(!new_vars)
1635                 return E_OUTOFMEMORY;
1636             This->elem_vars_size *= 2;
1637         }else {
1638             new_vars = heap_alloc(16*sizeof(WCHAR*));
1639             if(!new_vars)
1640                 return E_OUTOFMEMORY;
1641             This->elem_vars_size = 16;
1642         }
1643
1644         This->elem_vars = new_vars;
1645     }
1646
1647     This->elem_vars[This->elem_vars_cnt] = heap_strdupW(name);
1648     if(!This->elem_vars[This->elem_vars_cnt])
1649         return E_OUTOFMEMORY;
1650
1651     *dispid = MSHTML_DISPID_CUSTOM_MIN+This->elem_vars_cnt++;
1652     return S_OK;
1653 }
1654
1655 static HRESULT WINAPI DocDispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
1656 {
1657     HTMLDocument *This = impl_from_IDispatchEx(iface);
1658
1659     return htmldoc_query_interface(This, riid, ppv);
1660 }
1661
1662 static ULONG WINAPI DocDispatchEx_AddRef(IDispatchEx *iface)
1663 {
1664     HTMLDocument *This = impl_from_IDispatchEx(iface);
1665
1666     return htmldoc_addref(This);
1667 }
1668
1669 static ULONG WINAPI DocDispatchEx_Release(IDispatchEx *iface)
1670 {
1671     HTMLDocument *This = impl_from_IDispatchEx(iface);
1672
1673     return htmldoc_release(This);
1674 }
1675
1676 static HRESULT WINAPI DocDispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
1677 {
1678     HTMLDocument *This = impl_from_IDispatchEx(iface);
1679
1680     return IDispatchEx_GetTypeInfoCount(This->dispex, pctinfo);
1681 }
1682
1683 static HRESULT WINAPI DocDispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
1684                                                LCID lcid, ITypeInfo **ppTInfo)
1685 {
1686     HTMLDocument *This = impl_from_IDispatchEx(iface);
1687
1688     return IDispatchEx_GetTypeInfo(This->dispex, iTInfo, lcid, ppTInfo);
1689 }
1690
1691 static HRESULT WINAPI DocDispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
1692                                                  LPOLESTR *rgszNames, UINT cNames,
1693                                                  LCID lcid, DISPID *rgDispId)
1694 {
1695     HTMLDocument *This = impl_from_IDispatchEx(iface);
1696
1697     return IDispatchEx_GetIDsOfNames(This->dispex, riid, rgszNames, cNames, lcid, rgDispId);
1698 }
1699
1700 static HRESULT WINAPI DocDispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
1701                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1702                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1703 {
1704     HTMLDocument *This = impl_from_IDispatchEx(iface);
1705
1706     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1707           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1708
1709     switch(dispIdMember) {
1710     case DISPID_READYSTATE:
1711         TRACE("DISPID_READYSTATE\n");
1712
1713         if(!(wFlags & DISPATCH_PROPERTYGET))
1714             return E_INVALIDARG;
1715
1716         V_VT(pVarResult) = VT_I4;
1717         V_I4(pVarResult) = This->window->readystate;
1718         return S_OK;
1719     }
1720
1721     return IDispatchEx_Invoke(This->dispex, dispIdMember, riid, lcid, wFlags, pDispParams,
1722                               pVarResult, pExcepInfo, puArgErr);
1723 }
1724
1725 static HRESULT WINAPI DocDispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
1726 {
1727     HTMLDocument *This = impl_from_IDispatchEx(iface);
1728     HRESULT hres;
1729
1730     hres = IDispatchEx_GetDispID(This->dispex, bstrName, grfdex, pid);
1731     if(hres != DISP_E_UNKNOWNNAME)
1732         return hres;
1733
1734     return  dispid_from_elem_name(This->doc_node, bstrName, pid);
1735 }
1736
1737 static HRESULT WINAPI DocDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1738         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1739 {
1740     HTMLDocument *This = impl_from_IDispatchEx(iface);
1741
1742     if(This->window && id == DISPID_IHTMLDOCUMENT2_LOCATION && (wFlags & DISPATCH_PROPERTYPUT))
1743         return IDispatchEx_InvokeEx(&This->window->IDispatchEx_iface, DISPID_IHTMLWINDOW2_LOCATION,
1744                 lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1745
1746
1747     return IDispatchEx_InvokeEx(This->dispex, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1748 }
1749
1750 static HRESULT WINAPI DocDispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
1751 {
1752     HTMLDocument *This = impl_from_IDispatchEx(iface);
1753
1754     return IDispatchEx_DeleteMemberByName(This->dispex, bstrName, grfdex);
1755 }
1756
1757 static HRESULT WINAPI DocDispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
1758 {
1759     HTMLDocument *This = impl_from_IDispatchEx(iface);
1760
1761     return IDispatchEx_DeleteMemberByDispID(This->dispex, id);
1762 }
1763
1764 static HRESULT WINAPI DocDispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
1765 {
1766     HTMLDocument *This = impl_from_IDispatchEx(iface);
1767
1768     return IDispatchEx_GetMemberProperties(This->dispex, id, grfdexFetch, pgrfdex);
1769 }
1770
1771 static HRESULT WINAPI DocDispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
1772 {
1773     HTMLDocument *This = impl_from_IDispatchEx(iface);
1774
1775     return IDispatchEx_GetMemberName(This->dispex, id, pbstrName);
1776 }
1777
1778 static HRESULT WINAPI DocDispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
1779 {
1780     HTMLDocument *This = impl_from_IDispatchEx(iface);
1781
1782     return IDispatchEx_GetNextDispID(This->dispex, grfdex, id, pid);
1783 }
1784
1785 static HRESULT WINAPI DocDispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
1786 {
1787     HTMLDocument *This = impl_from_IDispatchEx(iface);
1788
1789     return IDispatchEx_GetNameSpaceParent(This->dispex, ppunk);
1790 }
1791
1792 static const IDispatchExVtbl DocDispatchExVtbl = {
1793     DocDispatchEx_QueryInterface,
1794     DocDispatchEx_AddRef,
1795     DocDispatchEx_Release,
1796     DocDispatchEx_GetTypeInfoCount,
1797     DocDispatchEx_GetTypeInfo,
1798     DocDispatchEx_GetIDsOfNames,
1799     DocDispatchEx_Invoke,
1800     DocDispatchEx_GetDispID,
1801     DocDispatchEx_InvokeEx,
1802     DocDispatchEx_DeleteMemberByName,
1803     DocDispatchEx_DeleteMemberByDispID,
1804     DocDispatchEx_GetMemberProperties,
1805     DocDispatchEx_GetMemberName,
1806     DocDispatchEx_GetNextDispID,
1807     DocDispatchEx_GetNameSpaceParent
1808 };
1809
1810 static inline HTMLDocument *impl_from_IProvideClassInfo(IProvideClassInfo *iface)
1811 {
1812     return CONTAINING_RECORD(iface, HTMLDocument, IProvideClassInfo_iface);
1813 }
1814
1815 static HRESULT WINAPI ProvideClassInfo_QueryInterface(IProvideClassInfo *iface,
1816         REFIID riid, void **ppv)
1817 {
1818     HTMLDocument *This = impl_from_IProvideClassInfo(iface);
1819     return htmldoc_query_interface(This, riid, ppv);
1820 }
1821
1822 static ULONG WINAPI ProvideClassInfo_AddRef(IProvideClassInfo *iface)
1823 {
1824     HTMLDocument *This = impl_from_IProvideClassInfo(iface);
1825     return htmldoc_addref(This);
1826 }
1827
1828 static ULONG WINAPI ProvideClassInfo_Release(IProvideClassInfo *iface)
1829 {
1830     HTMLDocument *This = impl_from_IProvideClassInfo(iface);
1831     return htmldoc_release(This);
1832 }
1833
1834 static HRESULT WINAPI ProvideClassInfo_GetClassInfo(IProvideClassInfo* iface,
1835         ITypeInfo **ppTI)
1836 {
1837     HTMLDocument *This = impl_from_IProvideClassInfo(iface);
1838     TRACE("(%p)->(%p)\n", This, ppTI);
1839     return get_htmldoc_classinfo(ppTI);
1840 }
1841
1842 static const IProvideClassInfoVtbl ProvideClassInfoVtbl = {
1843     ProvideClassInfo_QueryInterface,
1844     ProvideClassInfo_AddRef,
1845     ProvideClassInfo_Release,
1846     ProvideClassInfo_GetClassInfo
1847 };
1848
1849 static BOOL htmldoc_qi(HTMLDocument *This, REFIID riid, void **ppv)
1850 {
1851     *ppv = NULL;
1852
1853     if(IsEqualGUID(&IID_IUnknown, riid)) {
1854         TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
1855         *ppv = &This->IHTMLDocument2_iface;
1856     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1857         TRACE("(%p)->(IID_IDispatch, %p)\n", This, ppv);
1858         *ppv = &This->IDispatchEx_iface;
1859     }else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
1860         TRACE("(%p)->(IID_IDispatchEx, %p)\n", This, ppv);
1861         *ppv = &This->IDispatchEx_iface;
1862     }else if(IsEqualGUID(&IID_IHTMLDocument, riid)) {
1863         TRACE("(%p)->(IID_IHTMLDocument, %p)\n", This, ppv);
1864         *ppv = &This->IHTMLDocument2_iface;
1865     }else if(IsEqualGUID(&IID_IHTMLDocument2, riid)) {
1866         TRACE("(%p)->(IID_IHTMLDocument2, %p)\n", This, ppv);
1867         *ppv = &This->IHTMLDocument2_iface;
1868     }else if(IsEqualGUID(&IID_IHTMLDocument3, riid)) {
1869         TRACE("(%p)->(IID_IHTMLDocument3, %p)\n", This, ppv);
1870         *ppv = &This->IHTMLDocument3_iface;
1871     }else if(IsEqualGUID(&IID_IHTMLDocument4, riid)) {
1872         TRACE("(%p)->(IID_IHTMLDocument4, %p)\n", This, ppv);
1873         *ppv = &This->IHTMLDocument4_iface;
1874     }else if(IsEqualGUID(&IID_IHTMLDocument5, riid)) {
1875         TRACE("(%p)->(IID_IHTMLDocument5, %p)\n", This, ppv);
1876         *ppv = &This->IHTMLDocument5_iface;
1877     }else if(IsEqualGUID(&IID_IHTMLDocument6, riid)) {
1878         TRACE("(%p)->(IID_IHTMLDocument6, %p)\n", This, ppv);
1879         *ppv = &This->IHTMLDocument6_iface;
1880     }else if(IsEqualGUID(&IID_IPersist, riid)) {
1881         TRACE("(%p)->(IID_IPersist, %p)\n", This, ppv);
1882         *ppv = &This->IPersistFile_iface;
1883     }else if(IsEqualGUID(&IID_IPersistMoniker, riid)) {
1884         TRACE("(%p)->(IID_IPersistMoniker, %p)\n", This, ppv);
1885         *ppv = &This->IPersistMoniker_iface;
1886     }else if(IsEqualGUID(&IID_IPersistFile, riid)) {
1887         TRACE("(%p)->(IID_IPersistFile, %p)\n", This, ppv);
1888         *ppv = &This->IPersistFile_iface;
1889     }else if(IsEqualGUID(&IID_IMonikerProp, riid)) {
1890         TRACE("(%p)->(IID_IMonikerProp, %p)\n", This, ppv);
1891         *ppv = &This->IMonikerProp_iface;
1892     }else if(IsEqualGUID(&IID_IOleObject, riid)) {
1893         TRACE("(%p)->(IID_IOleObject, %p)\n", This, ppv);
1894         *ppv = &This->IOleObject_iface;
1895     }else if(IsEqualGUID(&IID_IOleDocument, riid)) {
1896         TRACE("(%p)->(IID_IOleDocument, %p)\n", This, ppv);
1897         *ppv = &This->IOleDocument_iface;
1898     }else if(IsEqualGUID(&IID_IOleDocumentView, riid)) {
1899         TRACE("(%p)->(IID_IOleDocumentView, %p)\n", This, ppv);
1900         *ppv = &This->IOleDocumentView_iface;
1901     }else if(IsEqualGUID(&IID_IOleInPlaceActiveObject, riid)) {
1902         TRACE("(%p)->(IID_IOleInPlaceActiveObject, %p)\n", This, ppv);
1903         *ppv = &This->IOleInPlaceActiveObject_iface;
1904     }else if(IsEqualGUID(&IID_IViewObject, riid)) {
1905         TRACE("(%p)->(IID_IViewObject, %p)\n", This, ppv);
1906         *ppv = &This->IViewObjectEx_iface;
1907     }else if(IsEqualGUID(&IID_IViewObject2, riid)) {
1908         TRACE("(%p)->(IID_IViewObject2, %p)\n", This, ppv);
1909         *ppv = &This->IViewObjectEx_iface;
1910     }else if(IsEqualGUID(&IID_IViewObjectEx, riid)) {
1911         TRACE("(%p)->(IID_IViewObjectEx, %p)\n", This, ppv);
1912         *ppv = &This->IViewObjectEx_iface;
1913     }else if(IsEqualGUID(&IID_IOleWindow, riid)) {
1914         TRACE("(%p)->(IID_IOleWindow, %p)\n", This, ppv);
1915         *ppv = &This->IOleInPlaceActiveObject_iface;
1916     }else if(IsEqualGUID(&IID_IOleInPlaceObject, riid)) {
1917         TRACE("(%p)->(IID_IOleInPlaceObject, %p)\n", This, ppv);
1918         *ppv = &This->IOleInPlaceObjectWindowless_iface;
1919     }else if(IsEqualGUID(&IID_IOleInPlaceObjectWindowless, riid)) {
1920         TRACE("(%p)->(IID_IOleInPlaceObjectWindowless, %p)\n", This, ppv);
1921         *ppv = &This->IOleInPlaceObjectWindowless_iface;
1922     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
1923         TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
1924         *ppv = &This->IServiceProvider_iface;
1925     }else if(IsEqualGUID(&IID_IOleCommandTarget, riid)) {
1926         TRACE("(%p)->(IID_IOleCommandTarget, %p)\n", This, ppv);
1927         *ppv = &This->IOleCommandTarget_iface;
1928     }else if(IsEqualGUID(&IID_IOleControl, riid)) {
1929         TRACE("(%p)->(IID_IOleControl, %p)\n", This, ppv);
1930         *ppv = &This->IOleControl_iface;
1931     }else if(IsEqualGUID(&IID_IHlinkTarget, riid)) {
1932         TRACE("(%p)->(IID_IHlinkTarget, %p)\n", This, ppv);
1933         *ppv = &This->IHlinkTarget_iface;
1934     }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) {
1935         TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv);
1936         *ppv = &This->cp_container.IConnectionPointContainer_iface;
1937     }else if(IsEqualGUID(&IID_IPersistStreamInit, riid)) {
1938         TRACE("(%p)->(IID_IPersistStreamInit %p)\n", This, ppv);
1939         *ppv = &This->IPersistStreamInit_iface;
1940     }else if(IsEqualGUID(&DIID_DispHTMLDocument, riid)) {
1941         TRACE("(%p)->(DIID_DispHTMLDocument %p)\n", This, ppv);
1942         *ppv = &This->IHTMLDocument2_iface;
1943     }else if(IsEqualGUID(&IID_ISupportErrorInfo, riid)) {
1944         TRACE("(%p)->(IID_ISupportErrorInfo %p)\n", This, ppv);
1945         *ppv = &This->ISupportErrorInfo_iface;
1946     }else if(IsEqualGUID(&IID_IPersistHistory, riid)) {
1947         TRACE("(%p)->(IID_IPersistHistory %p)\n", This, ppv);
1948         *ppv = &This->IPersistHistory_iface;
1949     }else if(IsEqualGUID(&CLSID_CMarkup, riid)) {
1950         FIXME("(%p)->(CLSID_CMarkup %p)\n", This, ppv);
1951         *ppv = NULL;
1952     }else if(IsEqualGUID(&IID_IRunnableObject, riid)) {
1953         TRACE("(%p)->(IID_IRunnableObject %p) returning NULL\n", This, ppv);
1954         *ppv = NULL;
1955     }else if(IsEqualGUID(&IID_IPersistPropertyBag, riid)) {
1956         TRACE("(%p)->(IID_IPersistPropertyBag %p) returning NULL\n", This, ppv);
1957         *ppv = NULL;
1958     }else if(IsEqualGUID(&IID_IMarshal, riid)) {
1959         TRACE("(%p)->(IID_IMarshal %p) returning NULL\n", This, ppv);
1960         *ppv = NULL;
1961     }else if(IsEqualGUID(&IID_IExternalConnection, riid)) {
1962         TRACE("(%p)->(IID_IExternalConnection %p) returning NULL\n", This, ppv);
1963         *ppv = NULL;
1964     }else if(IsEqualGUID(&IID_IStdMarshalInfo, riid)) {
1965         TRACE("(%p)->(IID_IStdMarshalInfo %p) returning NULL\n", This, ppv);
1966         *ppv = NULL;
1967     }else if(IsEqualGUID(&IID_IObjectWithSite, riid)) {
1968         TRACE("(%p)->(IID_IObjectWithSite %p)\n", This, ppv);
1969         *ppv = &This->IObjectWithSite_iface;
1970     }else if(IsEqualGUID(&IID_IOleContainer, riid)) {
1971         TRACE("(%p)->(IID_IOleContainer %p)\n", This, ppv);
1972         *ppv = &This->IOleContainer_iface;
1973     }else if(IsEqualGUID(&IID_IObjectSafety, riid)) {
1974         TRACE("(%p)->(IID_IObjectSafety %p)\n", This, ppv);
1975         *ppv = &This->IObjectSafety_iface;
1976     }else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) {
1977         TRACE("(%p)->(IID_IProvideClassInfo, %p)\n", This, ppv);
1978         *ppv = &This->IProvideClassInfo_iface;
1979     }else {
1980         return FALSE;
1981     }
1982
1983     if(*ppv)
1984         IUnknown_AddRef((IUnknown*)*ppv);
1985     return TRUE;
1986 }
1987
1988 static cp_static_data_t HTMLDocumentEvents_data = { HTMLDocumentEvents_tid, HTMLDocument_on_advise };
1989
1990 static void init_doc(HTMLDocument *doc, IUnknown *unk_impl, IDispatchEx *dispex)
1991 {
1992     doc->IHTMLDocument2_iface.lpVtbl = &HTMLDocumentVtbl;
1993     doc->IDispatchEx_iface.lpVtbl = &DocDispatchExVtbl;
1994     doc->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl;
1995     doc->IProvideClassInfo_iface.lpVtbl = &ProvideClassInfoVtbl;
1996
1997     doc->unk_impl = unk_impl;
1998     doc->dispex = dispex;
1999     doc->task_magic = get_task_target_magic();
2000
2001     HTMLDocument_HTMLDocument3_Init(doc);
2002     HTMLDocument_HTMLDocument5_Init(doc);
2003     HTMLDocument_Persist_Init(doc);
2004     HTMLDocument_OleCmd_Init(doc);
2005     HTMLDocument_OleObj_Init(doc);
2006     HTMLDocument_View_Init(doc);
2007     HTMLDocument_Window_Init(doc);
2008     HTMLDocument_Service_Init(doc);
2009     HTMLDocument_Hlink_Init(doc);
2010
2011     ConnectionPointContainer_Init(&doc->cp_container, (IUnknown*)&doc->IHTMLDocument2_iface);
2012     ConnectionPoint_Init(&doc->cp_dispatch, &doc->cp_container, &IID_IDispatch, &HTMLDocumentEvents_data);
2013     ConnectionPoint_Init(&doc->cp_propnotif, &doc->cp_container, &IID_IPropertyNotifySink, NULL);
2014     ConnectionPoint_Init(&doc->cp_htmldocevents, &doc->cp_container, &DIID_HTMLDocumentEvents, &HTMLDocumentEvents_data);
2015     ConnectionPoint_Init(&doc->cp_htmldocevents2, &doc->cp_container, &DIID_HTMLDocumentEvents2, NULL);
2016 }
2017
2018 static void destroy_htmldoc(HTMLDocument *This)
2019 {
2020     remove_target_tasks(This->task_magic);
2021
2022     ConnectionPointContainer_Destroy(&This->cp_container);
2023 }
2024
2025 static inline HTMLDocumentNode *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
2026 {
2027     return CONTAINING_RECORD(iface, HTMLDocumentNode, node);
2028 }
2029
2030 static HRESULT HTMLDocumentNode_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
2031 {
2032     HTMLDocumentNode *This = impl_from_HTMLDOMNode(iface);
2033
2034     if(htmldoc_qi(&This->basedoc, riid, ppv))
2035         return *ppv ? S_OK : E_NOINTERFACE;
2036
2037     if(IsEqualGUID(&IID_IInternetHostSecurityManager, riid)) {
2038         TRACE("(%p)->(IID_IInternetHostSecurityManager %p)\n", This, ppv);
2039         *ppv = &This->IInternetHostSecurityManager_iface;
2040     }else {
2041         return HTMLDOMNode_QI(&This->node, riid, ppv);
2042     }
2043
2044     IUnknown_AddRef((IUnknown*)*ppv);
2045     return S_OK;
2046 }
2047
2048 static void HTMLDocumentNode_destructor(HTMLDOMNode *iface)
2049 {
2050     HTMLDocumentNode *This = impl_from_HTMLDOMNode(iface);
2051     unsigned i;
2052
2053     for(i=0; i < This->elem_vars_cnt; i++)
2054         heap_free(This->elem_vars[i]);
2055     heap_free(This->elem_vars);
2056
2057     detach_events(This);
2058     if(This->body_event_target)
2059         release_event_target(This->body_event_target);
2060     if(This->catmgr)
2061         ICatInformation_Release(This->catmgr);
2062
2063     detach_selection(This);
2064     detach_ranges(This);
2065     release_nodes(This);
2066
2067     while(!list_empty(&This->plugin_hosts))
2068         detach_plugin_host(LIST_ENTRY(list_head(&This->plugin_hosts), PluginHost, entry));
2069
2070     if(This->nsdoc) {
2071         release_document_mutation(This);
2072         nsIDOMHTMLDocument_Release(This->nsdoc);
2073     }
2074
2075     heap_free(This->event_vector);
2076     destroy_htmldoc(&This->basedoc);
2077 }
2078
2079 static HRESULT HTMLDocumentNode_clone(HTMLDOMNode *iface, nsIDOMNode *nsnode, HTMLDOMNode **ret)
2080 {
2081     HTMLDocumentNode *This = impl_from_HTMLDOMNode(iface);
2082     FIXME("%p\n", This);
2083     return E_NOTIMPL;
2084 }
2085
2086 static const NodeImplVtbl HTMLDocumentNodeImplVtbl = {
2087     HTMLDocumentNode_QI,
2088     HTMLDocumentNode_destructor,
2089     HTMLDocumentNode_clone
2090 };
2091
2092 static HRESULT HTMLDocumentFragment_clone(HTMLDOMNode *iface, nsIDOMNode *nsnode, HTMLDOMNode **ret)
2093 {
2094     HTMLDocumentNode *This = impl_from_HTMLDOMNode(iface);
2095     HTMLDocumentNode *new_node;
2096     HRESULT hres;
2097
2098     hres = create_document_fragment(nsnode, This->node.doc, &new_node);
2099     if(FAILED(hres))
2100         return hres;
2101
2102     *ret = &new_node->node;
2103     return S_OK;
2104 }
2105
2106 static inline HTMLDocumentNode *impl_from_DispatchEx(DispatchEx *iface)
2107 {
2108     return CONTAINING_RECORD(iface, HTMLDocumentNode, node.dispex);
2109 }
2110
2111 static HRESULT HTMLDocumentNode_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
2112         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
2113 {
2114     HTMLDocumentNode *This = impl_from_DispatchEx(dispex);
2115     nsIDOMNodeList *node_list;
2116     nsAString name_str;
2117     nsIDOMNode *nsnode;
2118     HTMLDOMNode *node;
2119     unsigned i;
2120     nsresult nsres;
2121     HRESULT hres;
2122
2123     if(flags != DISPATCH_PROPERTYGET) {
2124         FIXME("unsupported flags %x\n", flags);
2125         return E_NOTIMPL;
2126     }
2127
2128     i = id - MSHTML_DISPID_CUSTOM_MIN;
2129
2130     if(!This->nsdoc || i >= This->elem_vars_cnt)
2131         return DISP_E_UNKNOWNNAME;
2132
2133     nsAString_InitDepend(&name_str, This->elem_vars[i]);
2134     nsres = nsIDOMHTMLDocument_GetElementsByName(This->nsdoc, &name_str, &node_list);
2135     nsAString_Finish(&name_str);
2136     if(NS_FAILED(nsres))
2137         return E_FAIL;
2138
2139     nsres = nsIDOMNodeList_Item(node_list, 0, &nsnode);
2140     nsIDOMNodeList_Release(node_list);
2141     if(NS_FAILED(nsres) || !nsnode)
2142         return DISP_E_UNKNOWNNAME;
2143
2144     hres = get_node(This, nsnode, TRUE, &node);
2145     if(FAILED(hres))
2146         return hres;
2147
2148     IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface);
2149     V_VT(res) = VT_DISPATCH;
2150     V_DISPATCH(res) = (IDispatch*)&node->IHTMLDOMNode_iface;
2151     return S_OK;
2152 }
2153
2154
2155 static const dispex_static_data_vtbl_t HTMLDocumentNode_dispex_vtbl = {
2156     NULL,
2157     NULL,
2158     HTMLDocumentNode_invoke,
2159     NULL
2160 };
2161
2162 static const NodeImplVtbl HTMLDocumentFragmentImplVtbl = {
2163     HTMLDocumentNode_QI,
2164     HTMLDocumentNode_destructor,
2165     HTMLDocumentFragment_clone
2166 };
2167
2168 static const tid_t HTMLDocumentNode_iface_tids[] = {
2169     IHTMLDOMNode_tid,
2170     IHTMLDOMNode2_tid,
2171     IHTMLDocument2_tid,
2172     IHTMLDocument3_tid,
2173     IHTMLDocument4_tid,
2174     IHTMLDocument5_tid,
2175     0
2176 };
2177
2178 static dispex_static_data_t HTMLDocumentNode_dispex = {
2179     &HTMLDocumentNode_dispex_vtbl,
2180     DispHTMLDocument_tid,
2181     NULL,
2182     HTMLDocumentNode_iface_tids
2183 };
2184
2185 static HTMLDocumentNode *alloc_doc_node(HTMLDocumentObj *doc_obj, HTMLWindow *window)
2186 {
2187     HTMLDocumentNode *doc;
2188
2189     doc = heap_alloc_zero(sizeof(HTMLDocumentNode));
2190     if(!doc)
2191         return NULL;
2192
2193     doc->ref = 1;
2194     doc->basedoc.doc_node = doc;
2195     doc->basedoc.doc_obj = doc_obj;
2196     doc->basedoc.window = window;
2197
2198     init_dispex(&doc->node.dispex, (IUnknown*)&doc->node.IHTMLDOMNode_iface,
2199             &HTMLDocumentNode_dispex);
2200     init_doc(&doc->basedoc, (IUnknown*)&doc->node.IHTMLDOMNode_iface,
2201             &doc->node.dispex.IDispatchEx_iface);
2202     HTMLDocumentNode_SecMgr_Init(doc);
2203
2204     list_init(&doc->bindings);
2205     list_init(&doc->selection_list);
2206     list_init(&doc->range_list);
2207     list_init(&doc->plugin_hosts);
2208
2209     return doc;
2210 }
2211
2212 HRESULT create_doc_from_nsdoc(nsIDOMHTMLDocument *nsdoc, HTMLDocumentObj *doc_obj, HTMLWindow *window, HTMLDocumentNode **ret)
2213 {
2214     HTMLDocumentNode *doc;
2215
2216     doc = alloc_doc_node(doc_obj, window);
2217     if(!doc)
2218         return E_OUTOFMEMORY;
2219
2220     if(!doc_obj->basedoc.window || window == doc_obj->basedoc.window)
2221         doc->basedoc.cp_container.forward_container = &doc_obj->basedoc.cp_container;
2222
2223     nsIDOMHTMLDocument_AddRef(nsdoc);
2224     doc->nsdoc = nsdoc;
2225     init_document_mutation(doc);
2226     doc_init_events(doc);
2227
2228     HTMLDOMNode_Init(doc, &doc->node, (nsIDOMNode*)nsdoc);
2229     doc->node.vtbl = &HTMLDocumentNodeImplVtbl;
2230     doc->node.cp_container = &doc->basedoc.cp_container;
2231
2232     *ret = doc;
2233     return S_OK;
2234 }
2235
2236 HRESULT create_document_fragment(nsIDOMNode *nsnode, HTMLDocumentNode *doc_node, HTMLDocumentNode **ret)
2237 {
2238     HTMLDocumentNode *doc_frag;
2239
2240     doc_frag = alloc_doc_node(doc_node->basedoc.doc_obj, doc_node->basedoc.window);
2241     if(!doc_frag)
2242         return E_OUTOFMEMORY;
2243
2244     HTMLDOMNode_Init(doc_node, &doc_frag->node, nsnode);
2245     doc_frag->node.vtbl = &HTMLDocumentFragmentImplVtbl;
2246     doc_frag->node.cp_container = &doc_frag->basedoc.cp_container;
2247
2248     htmldoc_addref(&doc_frag->basedoc);
2249     *ret = doc_frag;
2250     return S_OK;
2251 }
2252
2253 /**********************************************************
2254  * ICustomDoc implementation
2255  */
2256
2257 static inline HTMLDocumentObj *impl_from_ICustomDoc(ICustomDoc *iface)
2258 {
2259     return CONTAINING_RECORD(iface, HTMLDocumentObj, ICustomDoc_iface);
2260 }
2261
2262 static HRESULT WINAPI CustomDoc_QueryInterface(ICustomDoc *iface, REFIID riid, void **ppv)
2263 {
2264     HTMLDocumentObj *This = impl_from_ICustomDoc(iface);
2265
2266     if(htmldoc_qi(&This->basedoc, riid, ppv))
2267         return *ppv ? S_OK : E_NOINTERFACE;
2268
2269     if(IsEqualGUID(&IID_ICustomDoc, riid)) {
2270         TRACE("(%p)->(IID_ICustomDoc %p)\n", This, ppv);
2271         *ppv = &This->ICustomDoc_iface;
2272     }else if(IsEqualGUID(&IID_ITargetContainer, riid)) {
2273         TRACE("(%p)->(IID_ITargetContainer %p)\n", This, ppv);
2274         *ppv = &This->ITargetContainer_iface;
2275     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
2276         return *ppv ? S_OK : E_NOINTERFACE;
2277     }else {
2278         FIXME("Unimplemented interface %s\n", debugstr_guid(riid));
2279         *ppv = NULL;
2280         return E_NOINTERFACE;
2281     }
2282
2283     IUnknown_AddRef((IUnknown*)*ppv);
2284     return S_OK;
2285 }
2286
2287 static ULONG WINAPI CustomDoc_AddRef(ICustomDoc *iface)
2288 {
2289     HTMLDocumentObj *This = impl_from_ICustomDoc(iface);
2290     ULONG ref = InterlockedIncrement(&This->ref);
2291
2292     TRACE("(%p) ref = %u\n", This, ref);
2293
2294     return ref;
2295 }
2296
2297 static ULONG WINAPI CustomDoc_Release(ICustomDoc *iface)
2298 {
2299     HTMLDocumentObj *This = impl_from_ICustomDoc(iface);
2300     ULONG ref = InterlockedDecrement(&This->ref);
2301
2302     TRACE("(%p) ref = %u\n", This, ref);
2303
2304     if(!ref) {
2305         if(This->basedoc.doc_node) {
2306             This->basedoc.doc_node->basedoc.doc_obj = NULL;
2307             htmldoc_release(&This->basedoc.doc_node->basedoc);
2308         }
2309         if(This->basedoc.window) {
2310             This->basedoc.window->doc_obj = NULL;
2311             IHTMLWindow2_Release(&This->basedoc.window->IHTMLWindow2_iface);
2312         }
2313         if(This->basedoc.advise_holder)
2314             IOleAdviseHolder_Release(This->basedoc.advise_holder);
2315
2316         if(This->view_sink)
2317             IAdviseSink_Release(This->view_sink);
2318         if(This->client)
2319             IOleObject_SetClientSite(&This->basedoc.IOleObject_iface, NULL);
2320         if(This->hostui)
2321             ICustomDoc_SetUIHandler(&This->ICustomDoc_iface, NULL);
2322         if(This->in_place_active)
2323             IOleInPlaceObjectWindowless_InPlaceDeactivate(&This->basedoc.IOleInPlaceObjectWindowless_iface);
2324         if(This->ipsite)
2325             IOleDocumentView_SetInPlaceSite(&This->basedoc.IOleDocumentView_iface, NULL);
2326         if(This->undomgr)
2327             IOleUndoManager_Release(This->undomgr);
2328         if(This->tooltips_hwnd)
2329             DestroyWindow(This->tooltips_hwnd);
2330
2331         if(This->hwnd)
2332             DestroyWindow(This->hwnd);
2333         heap_free(This->mime);
2334
2335         destroy_htmldoc(&This->basedoc);
2336         release_dispex(&This->dispex);
2337
2338         if(This->nscontainer)
2339             NSContainer_Release(This->nscontainer);
2340         heap_free(This);
2341     }
2342
2343     return ref;
2344 }
2345
2346 static HRESULT WINAPI CustomDoc_SetUIHandler(ICustomDoc *iface, IDocHostUIHandler *pUIHandler)
2347 {
2348     HTMLDocumentObj *This = impl_from_ICustomDoc(iface);
2349     IOleCommandTarget *cmdtrg;
2350     HRESULT hres;
2351
2352     TRACE("(%p)->(%p)\n", This, pUIHandler);
2353
2354     if(This->custom_hostui && This->hostui == pUIHandler)
2355         return S_OK;
2356
2357     This->custom_hostui = TRUE;
2358
2359     if(This->hostui)
2360         IDocHostUIHandler_Release(This->hostui);
2361     if(pUIHandler)
2362         IDocHostUIHandler_AddRef(pUIHandler);
2363     This->hostui = pUIHandler;
2364     if(!pUIHandler)
2365         return S_OK;
2366
2367     hres = IDocHostUIHandler_QueryInterface(pUIHandler, &IID_IOleCommandTarget, (void**)&cmdtrg);
2368     if(SUCCEEDED(hres)) {
2369         FIXME("custom UI handler supports IOleCommandTarget\n");
2370         IOleCommandTarget_Release(cmdtrg);
2371     }
2372
2373     return S_OK;
2374 }
2375
2376 static const ICustomDocVtbl CustomDocVtbl = {
2377     CustomDoc_QueryInterface,
2378     CustomDoc_AddRef,
2379     CustomDoc_Release,
2380     CustomDoc_SetUIHandler
2381 };
2382
2383 static const tid_t HTMLDocumentObj_iface_tids[] = {
2384     IHTMLDocument2_tid,
2385     IHTMLDocument3_tid,
2386     IHTMLDocument4_tid,
2387     IHTMLDocument5_tid,
2388     0
2389 };
2390 static dispex_static_data_t HTMLDocumentObj_dispex = {
2391     NULL,
2392     DispHTMLDocument_tid,
2393     NULL,
2394     HTMLDocumentObj_iface_tids
2395 };
2396
2397 HRESULT HTMLDocument_Create(IUnknown *pUnkOuter, REFIID riid, void** ppvObject)
2398 {
2399     HTMLDocumentObj *doc;
2400     nsIDOMWindow *nswindow = NULL;
2401     nsresult nsres;
2402     HRESULT hres;
2403
2404     TRACE("(%p %s %p)\n", pUnkOuter, debugstr_guid(riid), ppvObject);
2405
2406     doc = heap_alloc_zero(sizeof(HTMLDocumentObj));
2407     if(!doc)
2408         return E_OUTOFMEMORY;
2409
2410     init_dispex(&doc->dispex, (IUnknown*)&doc->ICustomDoc_iface, &HTMLDocumentObj_dispex);
2411     init_doc(&doc->basedoc, (IUnknown*)&doc->ICustomDoc_iface, &doc->dispex.IDispatchEx_iface);
2412     TargetContainer_Init(doc);
2413
2414     doc->ICustomDoc_iface.lpVtbl = &CustomDocVtbl;
2415     doc->ref = 1;
2416     doc->basedoc.doc_obj = doc;
2417
2418     doc->usermode = UNKNOWN_USERMODE;
2419
2420     hres = create_nscontainer(doc, NULL, &doc->nscontainer);
2421     if(FAILED(hres)) {
2422         ERR("Failed to init Gecko, returning CLASS_E_CLASSNOTAVAILABLE\n");
2423         htmldoc_release(&doc->basedoc);
2424         return hres;
2425     }
2426
2427     hres = htmldoc_query_interface(&doc->basedoc, riid, ppvObject);
2428     htmldoc_release(&doc->basedoc);
2429     if(FAILED(hres))
2430         return hres;
2431
2432
2433     nsres = nsIWebBrowser_GetContentDOMWindow(doc->nscontainer->webbrowser, &nswindow);
2434     if(NS_FAILED(nsres))
2435         ERR("GetContentDOMWindow failed: %08x\n", nsres);
2436
2437     hres = HTMLWindow_Create(doc, nswindow, NULL /* FIXME */, &doc->basedoc.window);
2438     if(nswindow)
2439         nsIDOMWindow_Release(nswindow);
2440     if(FAILED(hres)) {
2441         htmldoc_release(&doc->basedoc);
2442         return hres;
2443     }
2444
2445     if(!doc->basedoc.doc_node && doc->basedoc.window->doc) {
2446         doc->basedoc.doc_node = doc->basedoc.window->doc;
2447         htmldoc_addref(&doc->basedoc.doc_node->basedoc);
2448     }
2449
2450     get_thread_hwnd();
2451
2452     return S_OK;
2453 }