mshtml: Improved error handling in get_node calls.
[wine] / dlls / mshtml / htmldoc3.c
1 /*
2  * Copyright 2005 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 "ole2.h"
30
31 #include "wine/debug.h"
32
33 #include "mshtml_private.h"
34 #include "htmlevent.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 #define HTMLDOC3_THIS(iface) DEFINE_THIS(HTMLDocument, HTMLDocument3, iface)
39
40 static HRESULT WINAPI HTMLDocument3_QueryInterface(IHTMLDocument3 *iface,
41                                                   REFIID riid, void **ppv)
42 {
43     HTMLDocument *This = HTMLDOC3_THIS(iface);
44     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
45 }
46
47 static ULONG WINAPI HTMLDocument3_AddRef(IHTMLDocument3 *iface)
48 {
49     HTMLDocument *This = HTMLDOC3_THIS(iface);
50     return IHTMLDocument2_AddRef(HTMLDOC(This));
51 }
52
53 static ULONG WINAPI HTMLDocument3_Release(IHTMLDocument3 *iface)
54 {
55     HTMLDocument *This = HTMLDOC3_THIS(iface);
56     return IHTMLDocument2_Release(HTMLDOC(This));
57 }
58
59 static HRESULT WINAPI HTMLDocument3_GetTypeInfoCount(IHTMLDocument3 *iface, UINT *pctinfo)
60 {
61     HTMLDocument *This = HTMLDOC3_THIS(iface);
62     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(This), pctinfo);
63 }
64
65 static HRESULT WINAPI HTMLDocument3_GetTypeInfo(IHTMLDocument3 *iface, UINT iTInfo,
66                                                 LCID lcid, ITypeInfo **ppTInfo)
67 {
68     HTMLDocument *This = HTMLDOC3_THIS(iface);
69     return IDispatchEx_GetTypeInfo(DISPATCHEX(This), iTInfo, lcid, ppTInfo);
70 }
71
72 static HRESULT WINAPI HTMLDocument3_GetIDsOfNames(IHTMLDocument3 *iface, REFIID riid,
73                                                 LPOLESTR *rgszNames, UINT cNames,
74                                                 LCID lcid, DISPID *rgDispId)
75 {
76     HTMLDocument *This = HTMLDOC3_THIS(iface);
77     return IDispatchEx_GetIDsOfNames(DISPATCHEX(This), riid, rgszNames, cNames, lcid, rgDispId);
78 }
79
80 static HRESULT WINAPI HTMLDocument3_Invoke(IHTMLDocument3 *iface, DISPID dispIdMember,
81                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
82                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
83 {
84     HTMLDocument *This = HTMLDOC3_THIS(iface);
85     return IDispatchEx_Invoke(DISPATCHEX(This), dispIdMember, riid, lcid, wFlags, pDispParams,
86             pVarResult, pExcepInfo, puArgErr);
87 }
88
89 static HRESULT WINAPI HTMLDocument3_releaseCapture(IHTMLDocument3 *iface)
90 {
91     HTMLDocument *This = HTMLDOC3_THIS(iface);
92     FIXME("(%p)\n", This);
93     return E_NOTIMPL;
94 }
95
96 static HRESULT WINAPI HTMLDocument3_recalc(IHTMLDocument3 *iface, VARIANT_BOOL fForce)
97 {
98     HTMLDocument *This = HTMLDOC3_THIS(iface);
99     FIXME("(%p)->(%x)\n", This, fForce);
100     return E_NOTIMPL;
101 }
102
103 static HRESULT WINAPI HTMLDocument3_createTextNode(IHTMLDocument3 *iface, BSTR text,
104                                                    IHTMLDOMNode **newTextNode)
105 {
106     HTMLDocument *This = HTMLDOC3_THIS(iface);
107     nsIDOMText *nstext;
108     HTMLDOMNode *node;
109     nsAString text_str;
110     nsresult nsres;
111
112     TRACE("(%p)->(%s %p)\n", This, debugstr_w(text), newTextNode);
113
114     if(!This->doc_node->nsdoc) {
115         WARN("NULL nsdoc\n");
116         return E_UNEXPECTED;
117     }
118
119     nsAString_InitDepend(&text_str, text);
120     nsres = nsIDOMHTMLDocument_CreateTextNode(This->doc_node->nsdoc, &text_str, &nstext);
121     nsAString_Finish(&text_str);
122     if(NS_FAILED(nsres)) {
123         ERR("CreateTextNode failed: %08x\n", nsres);
124         return E_FAIL;
125     }
126
127     node = HTMLDOMTextNode_Create(This->doc_node, (nsIDOMNode*)nstext);
128     nsIDOMElement_Release(nstext);
129
130     *newTextNode = HTMLDOMNODE(node);
131     IHTMLDOMNode_AddRef(HTMLDOMNODE(node));
132     return S_OK;
133 }
134
135 static HRESULT WINAPI HTMLDocument3_get_documentElement(IHTMLDocument3 *iface, IHTMLElement **p)
136 {
137     HTMLDocument *This = HTMLDOC3_THIS(iface);
138     nsIDOMElement *nselem = NULL;
139     HTMLDOMNode *node;
140     nsresult nsres;
141     HRESULT hres;
142
143     TRACE("(%p)->(%p)\n", This, p);
144
145     if(This->window->readystate == READYSTATE_UNINITIALIZED) {
146         *p = NULL;
147         return S_OK;
148     }
149
150     if(!This->doc_node->nsdoc) {
151         WARN("NULL nsdoc\n");
152         return E_UNEXPECTED;
153     }
154
155     nsres = nsIDOMHTMLDocument_GetDocumentElement(This->doc_node->nsdoc, &nselem);
156     if(NS_FAILED(nsres)) {
157         ERR("GetDocumentElement failed: %08x\n", nsres);
158         return E_FAIL;
159     }
160
161     if(!nselem) {
162         *p = NULL;
163         return S_OK;
164     }
165
166     hres = get_node(This->doc_node, (nsIDOMNode *)nselem, TRUE, &node);
167     nsIDOMElement_Release(nselem);
168     if(FAILED(hres))
169         return hres;
170
171     return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(node), &IID_IHTMLElement, (void**)p);
172 }
173
174 static HRESULT WINAPI HTMLDocument3_uniqueID(IHTMLDocument3 *iface, BSTR *p)
175 {
176     HTMLDocument *This = HTMLDOC3_THIS(iface);
177     FIXME("(%p)->(%p)\n", This, p);
178     return E_NOTIMPL;
179 }
180
181 static HRESULT WINAPI HTMLDocument3_attachEvent(IHTMLDocument3 *iface, BSTR event,
182                                                 IDispatch* pDisp, VARIANT_BOOL *pfResult)
183 {
184     HTMLDocument *This = HTMLDOC3_THIS(iface);
185
186     TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(event), pDisp, pfResult);
187
188     return attach_event(&This->doc_node->node.event_target, This->doc_node->node.nsnode, This, event, pDisp, pfResult);
189 }
190
191 static HRESULT WINAPI HTMLDocument3_detachEvent(IHTMLDocument3 *iface, BSTR event,
192                                                 IDispatch *pDisp)
193 {
194     HTMLDocument *This = HTMLDOC3_THIS(iface);
195
196     TRACE("(%p)->(%s %p)\n", This, debugstr_w(event), pDisp);
197
198     return detach_event(This->doc_node->node.event_target, This, event, pDisp);
199 }
200
201 static HRESULT WINAPI HTMLDocument3_put_onrowsdelete(IHTMLDocument3 *iface, VARIANT v)
202 {
203     HTMLDocument *This = HTMLDOC3_THIS(iface);
204     FIXME("(%p)->()\n", This);
205     return E_NOTIMPL;
206 }
207
208 static HRESULT WINAPI HTMLDocument3_get_onrowsdelete(IHTMLDocument3 *iface, VARIANT *p)
209 {
210     HTMLDocument *This = HTMLDOC3_THIS(iface);
211     FIXME("(%p)->(%p)\n", This, p);
212     return E_NOTIMPL;
213 }
214
215 static HRESULT WINAPI HTMLDocument3_put_onrowsinserted(IHTMLDocument3 *iface, VARIANT v)
216 {
217     HTMLDocument *This = HTMLDOC3_THIS(iface);
218     FIXME("(%p)->()\n", This);
219     return E_NOTIMPL;
220 }
221
222 static HRESULT WINAPI HTMLDocument3_get_onrowsinserted(IHTMLDocument3 *iface, VARIANT *p)
223 {
224     HTMLDocument *This = HTMLDOC3_THIS(iface);
225     FIXME("(%p)->(%p)\n", This, p);
226     return E_NOTIMPL;
227 }
228
229 static HRESULT WINAPI HTMLDocument3_put_oncellchange(IHTMLDocument3 *iface, VARIANT v)
230 {
231     HTMLDocument *This = HTMLDOC3_THIS(iface);
232     FIXME("(%p)->()\n", This);
233     return E_NOTIMPL;
234 }
235
236 static HRESULT WINAPI HTMLDocument3_get_oncellchange(IHTMLDocument3 *iface, VARIANT *p)
237 {
238     HTMLDocument *This = HTMLDOC3_THIS(iface);
239     FIXME("(%p)->(%p)\n", This, p);
240     return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI HTMLDocument3_put_ondatasetchanged(IHTMLDocument3 *iface, VARIANT v)
244 {
245     HTMLDocument *This = HTMLDOC3_THIS(iface);
246     FIXME("(%p)->()\n", This);
247     return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI HTMLDocument3_get_ondatasetchanged(IHTMLDocument3 *iface, VARIANT *p)
251 {
252     HTMLDocument *This = HTMLDOC3_THIS(iface);
253     FIXME("(%p)->(%p)\n", This, p);
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI HTMLDocument3_put_ondataavailable(IHTMLDocument3 *iface, VARIANT v)
258 {
259     HTMLDocument *This = HTMLDOC3_THIS(iface);
260     FIXME("(%p)->()\n", This);
261     return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI HTMLDocument3_get_ondataavailable(IHTMLDocument3 *iface, VARIANT *p)
265 {
266     HTMLDocument *This = HTMLDOC3_THIS(iface);
267     FIXME("(%p)->(%p)\n", This, p);
268     return E_NOTIMPL;
269 }
270
271 static HRESULT WINAPI HTMLDocument3_put_ondatasetcomplete(IHTMLDocument3 *iface, VARIANT v)
272 {
273     HTMLDocument *This = HTMLDOC3_THIS(iface);
274     FIXME("(%p)->()\n", This);
275     return E_NOTIMPL;
276 }
277
278 static HRESULT WINAPI HTMLDocument3_get_ondatasetcomplete(IHTMLDocument3 *iface, VARIANT *p)
279 {
280     HTMLDocument *This = HTMLDOC3_THIS(iface);
281     FIXME("(%p)->(%p)\n", This, p);
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI HTMLDocument3_put_onpropertychange(IHTMLDocument3 *iface, VARIANT v)
286 {
287     HTMLDocument *This = HTMLDOC3_THIS(iface);
288     FIXME("(%p)->()\n", This);
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI HTMLDocument3_get_onpropertychange(IHTMLDocument3 *iface, VARIANT *p)
293 {
294     HTMLDocument *This = HTMLDOC3_THIS(iface);
295     FIXME("(%p)->(%p)\n", This, p);
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI HTMLDocument3_put_dir(IHTMLDocument3 *iface, BSTR v)
300 {
301     HTMLDocument *This = HTMLDOC3_THIS(iface);
302     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
303     return E_NOTIMPL;
304 }
305
306 static HRESULT WINAPI HTMLDocument3_get_dir(IHTMLDocument3 *iface, BSTR *p)
307 {
308     HTMLDocument *This = HTMLDOC3_THIS(iface);
309     FIXME("(%p)->(%p)\n", This, p);
310     return E_NOTIMPL;
311 }
312
313 static HRESULT WINAPI HTMLDocument3_put_oncontextmenu(IHTMLDocument3 *iface, VARIANT v)
314 {
315     HTMLDocument *This = HTMLDOC3_THIS(iface);
316
317     TRACE("(%p)->()\n", This);
318
319     return set_doc_event(This, EVENTID_CONTEXTMENU, &v);
320 }
321
322 static HRESULT WINAPI HTMLDocument3_get_oncontextmenu(IHTMLDocument3 *iface, VARIANT *p)
323 {
324     HTMLDocument *This = HTMLDOC3_THIS(iface);
325
326     TRACE("(%p)->(%p)\n", This, p);
327
328     return get_doc_event(This, EVENTID_CONTEXTMENU, p);
329 }
330
331 static HRESULT WINAPI HTMLDocument3_put_onstop(IHTMLDocument3 *iface, VARIANT v)
332 {
333     HTMLDocument *This = HTMLDOC3_THIS(iface);
334     FIXME("(%p)->()\n", This);
335     return E_NOTIMPL;
336 }
337
338 static HRESULT WINAPI HTMLDocument3_get_onstop(IHTMLDocument3 *iface, VARIANT *p)
339 {
340     HTMLDocument *This = HTMLDOC3_THIS(iface);
341     FIXME("(%p)->(%p)\n", This, p);
342     return E_NOTIMPL;
343 }
344
345 static HRESULT WINAPI HTMLDocument3_createDocumentFragment(IHTMLDocument3 *iface,
346                                                            IHTMLDocument2 **ppNewDoc)
347 {
348     HTMLDocument *This = HTMLDOC3_THIS(iface);
349     nsIDOMDocumentFragment *doc_frag;
350     HTMLDocumentNode *docnode;
351     nsresult nsres;
352     HRESULT hres;
353
354     TRACE("(%p)->(%p)\n", This, ppNewDoc);
355
356     if(!This->doc_node->nsdoc) {
357         FIXME("NULL nsdoc\n");
358         return E_NOTIMPL;
359     }
360
361     nsres = nsIDOMHTMLDocument_CreateDocumentFragment(This->doc_node->nsdoc, &doc_frag);
362     if(NS_FAILED(nsres)) {
363         ERR("CreateDocumentFragment failed: %08x\n", nsres);
364         return E_FAIL;
365     }
366
367     hres = create_document_fragment((nsIDOMNode*)doc_frag, This->doc_node, &docnode);
368     nsIDOMDocumentFragment_Release(doc_frag);
369     if(FAILED(hres))
370         return hres;
371
372     *ppNewDoc = HTMLDOC(&docnode->basedoc);
373     return S_OK;
374 }
375
376 static HRESULT WINAPI HTMLDocument3_get_parentDocument(IHTMLDocument3 *iface,
377                                                        IHTMLDocument2 **p)
378 {
379     HTMLDocument *This = HTMLDOC3_THIS(iface);
380     FIXME("(%p)->(%p)\n", This, p);
381     return E_NOTIMPL;
382 }
383
384 static HRESULT WINAPI HTMLDocument3_put_enableDownload(IHTMLDocument3 *iface,
385                                                        VARIANT_BOOL v)
386 {
387     HTMLDocument *This = HTMLDOC3_THIS(iface);
388     FIXME("(%p)->(%x)\n", This, v);
389     return E_NOTIMPL;
390 }
391
392 static HRESULT WINAPI HTMLDocument3_get_enableDownload(IHTMLDocument3 *iface,
393                                                        VARIANT_BOOL *p)
394 {
395     HTMLDocument *This = HTMLDOC3_THIS(iface);
396     FIXME("(%p)->(%p)\n", This, p);
397     return E_NOTIMPL;
398 }
399
400 static HRESULT WINAPI HTMLDocument3_put_baseUrl(IHTMLDocument3 *iface, BSTR v)
401 {
402     HTMLDocument *This = HTMLDOC3_THIS(iface);
403     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
404     return E_NOTIMPL;
405 }
406
407 static HRESULT WINAPI HTMLDocument3_get_baseUrl(IHTMLDocument3 *iface, BSTR *p)
408 {
409     HTMLDocument *This = HTMLDOC3_THIS(iface);
410     FIXME("(%p)->(%p)\n", This, p);
411     return E_NOTIMPL;
412 }
413
414 static HRESULT WINAPI HTMLDocument3_get_childNodes(IHTMLDocument3 *iface, IDispatch **p)
415 {
416     HTMLDocument *This = HTMLDOC3_THIS(iface);
417     FIXME("(%p)->(%p)\n", This, p);
418     return E_NOTIMPL;
419 }
420
421 static HRESULT WINAPI HTMLDocument3_put_inheritStyleSheets(IHTMLDocument3 *iface,
422                                                            VARIANT_BOOL v)
423 {
424     HTMLDocument *This = HTMLDOC3_THIS(iface);
425     FIXME("(%p)->()\n", This);
426     return E_NOTIMPL;
427 }
428
429 static HRESULT WINAPI HTMLDocument3_get_inheritStyleSheets(IHTMLDocument3 *iface,
430                                                            VARIANT_BOOL *p)
431 {
432     HTMLDocument *This = HTMLDOC3_THIS(iface);
433     FIXME("(%p)->(%p)\n", This, p);
434     return E_NOTIMPL;
435 }
436
437 static HRESULT WINAPI HTMLDocument3_put_onbeforeeditfocus(IHTMLDocument3 *iface, VARIANT v)
438 {
439     HTMLDocument *This = HTMLDOC3_THIS(iface);
440     FIXME("(%p)->()\n", This);
441     return E_NOTIMPL;
442 }
443
444 static HRESULT WINAPI HTMLDocument3_get_onbeforeeditfocus(IHTMLDocument3 *iface, VARIANT *p)
445 {
446     HTMLDocument *This = HTMLDOC3_THIS(iface);
447     FIXME("(%p)->(%p)\n", This, p);
448     return E_NOTIMPL;
449 }
450
451 static HRESULT WINAPI HTMLDocument3_getElementsByName(IHTMLDocument3 *iface, BSTR v,
452                                                       IHTMLElementCollection **ppelColl)
453 {
454     HTMLDocument *This = HTMLDOC3_THIS(iface);
455     FIXME("(%p)->(%s %p)\n", This, debugstr_w(v), ppelColl);
456     return E_NOTIMPL;
457 }
458
459
460 static HRESULT WINAPI HTMLDocument3_getElementById(IHTMLDocument3 *iface, BSTR v,
461                                                    IHTMLElement **pel)
462 {
463     HTMLDocument *This = HTMLDOC3_THIS(iface);
464     nsIDOMElement *nselem;
465     HTMLDOMNode *node;
466     nsIDOMNode *nsnode, *nsnode_by_id, *nsnode_by_name;
467     nsIDOMNodeList *nsnode_list;
468     nsAString id_str;
469     nsresult nsres;
470     HRESULT hres;
471
472     TRACE("(%p)->(%s %p)\n", This, debugstr_w(v), pel);
473
474     if(!This->doc_node->nsdoc) {
475         WARN("NULL nsdoc\n");
476         return E_UNEXPECTED;
477     }
478
479     nsAString_InitDepend(&id_str, v);
480     /* get element by id attribute */
481     nsres = nsIDOMHTMLDocument_GetElementById(This->doc_node->nsdoc, &id_str, &nselem);
482     if(FAILED(nsres)) {
483         ERR("GetElementById failed: %08x\n", nsres);
484         nsAString_Finish(&id_str);
485         return E_FAIL;
486     }
487     nsnode_by_id = (nsIDOMNode*)nselem;
488
489     /* get first element by name attribute */
490     nsres = nsIDOMHTMLDocument_GetElementsByName(This->doc_node->nsdoc, &id_str, &nsnode_list);
491     nsAString_Finish(&id_str);
492     if(FAILED(nsres)) {
493         ERR("getElementsByName failed: %08x\n", nsres);
494         if(nsnode_by_id)
495             nsIDOMNode_Release(nsnode_by_id);
496         return E_FAIL;
497     }
498     nsIDOMNodeList_Item(nsnode_list, 0, &nsnode_by_name);
499     nsIDOMNodeList_Release(nsnode_list);
500
501
502     if(nsnode_by_name && nsnode_by_id) {
503         nsIDOM3Node *node3;
504         PRUint16 pos;
505
506         nsres = nsIDOMNode_QueryInterface(nsnode_by_name, &IID_nsIDOM3Node, (void**)&node3);
507         if(NS_FAILED(nsres)) {
508             FIXME("failed to get nsIDOM3Node interface: 0x%08x\n", nsres);
509             nsIDOMNode_Release(nsnode_by_name);
510             nsIDOMNode_Release(nsnode_by_id);
511             return E_FAIL;
512         }
513
514         nsres = nsIDOM3Node_CompareDocumentPosition(node3, nsnode_by_id, &pos);
515         nsIDOM3Node_Release(node3);
516         if(NS_FAILED(nsres)) {
517             FIXME("nsIDOM3Node_CompareDocumentPosition failed: 0x%08x\n", nsres);
518             nsIDOMNode_Release(nsnode_by_name);
519             nsIDOMNode_Release(nsnode_by_id);
520             return E_FAIL;
521         }
522
523         TRACE("CompareDocumentPosition gave: 0x%x\n", pos);
524         if(pos & PRECEDING || pos & CONTAINS) {
525             nsnode = nsnode_by_id;
526             nsIDOMNode_Release(nsnode_by_name);
527         }else {
528             nsnode = nsnode_by_name;
529             nsIDOMNode_Release(nsnode_by_id);
530         }
531     }else
532         nsnode = nsnode_by_name ? nsnode_by_name : nsnode_by_id;
533
534     if(nsnode) {
535         hres = get_node(This->doc_node, nsnode, TRUE, &node);
536         nsIDOMNode_Release(nsnode);
537
538         if(SUCCEEDED(hres))
539             hres = IHTMLDOMNode_QueryInterface(HTMLDOMNODE(node), &IID_IHTMLElement, (void**)pel);
540     }else {
541         *pel = NULL;
542         hres = S_OK;
543     }
544
545     return hres;
546 }
547
548
549 static HRESULT WINAPI HTMLDocument3_getElementsByTagName(IHTMLDocument3 *iface, BSTR v,
550                                                          IHTMLElementCollection **pelColl)
551 {
552     HTMLDocument *This = HTMLDOC3_THIS(iface);
553     nsIDOMNodeList *nslist;
554     nsAString id_str, ns_str;
555     nsresult nsres;
556     static const WCHAR str[] = {'*',0};
557
558     TRACE("(%p)->(%s %p)\n", This, debugstr_w(v), pelColl);
559
560     if(!This->doc_node->nsdoc) {
561         WARN("NULL nsdoc\n");
562         return E_UNEXPECTED;
563     }
564
565     nsAString_InitDepend(&id_str, v);
566     nsAString_InitDepend(&ns_str, str);
567     nsres = nsIDOMHTMLDocument_GetElementsByTagNameNS(This->doc_node->nsdoc, &ns_str, &id_str, &nslist);
568     nsAString_Finish(&id_str);
569     nsAString_Finish(&ns_str);
570     if(FAILED(nsres)) {
571         ERR("GetElementByName failed: %08x\n", nsres);
572         return E_FAIL;
573     }
574
575     *pelColl = (IHTMLElementCollection*)create_collection_from_nodelist(This->doc_node, (IUnknown*)HTMLDOC3(This), nslist);
576     nsIDOMNodeList_Release(nslist);
577
578     return S_OK;
579 }
580
581 #undef HTMLDOC3_THIS
582
583 static const IHTMLDocument3Vtbl HTMLDocument3Vtbl = {
584     HTMLDocument3_QueryInterface,
585     HTMLDocument3_AddRef,
586     HTMLDocument3_Release,
587     HTMLDocument3_GetTypeInfoCount,
588     HTMLDocument3_GetTypeInfo,
589     HTMLDocument3_GetIDsOfNames,
590     HTMLDocument3_Invoke,
591     HTMLDocument3_releaseCapture,
592     HTMLDocument3_recalc,
593     HTMLDocument3_createTextNode,
594     HTMLDocument3_get_documentElement,
595     HTMLDocument3_uniqueID,
596     HTMLDocument3_attachEvent,
597     HTMLDocument3_detachEvent,
598     HTMLDocument3_put_onrowsdelete,
599     HTMLDocument3_get_onrowsdelete,
600     HTMLDocument3_put_onrowsinserted,
601     HTMLDocument3_get_onrowsinserted,
602     HTMLDocument3_put_oncellchange,
603     HTMLDocument3_get_oncellchange,
604     HTMLDocument3_put_ondatasetchanged,
605     HTMLDocument3_get_ondatasetchanged,
606     HTMLDocument3_put_ondataavailable,
607     HTMLDocument3_get_ondataavailable,
608     HTMLDocument3_put_ondatasetcomplete,
609     HTMLDocument3_get_ondatasetcomplete,
610     HTMLDocument3_put_onpropertychange,
611     HTMLDocument3_get_onpropertychange,
612     HTMLDocument3_put_dir,
613     HTMLDocument3_get_dir,
614     HTMLDocument3_put_oncontextmenu,
615     HTMLDocument3_get_oncontextmenu,
616     HTMLDocument3_put_onstop,
617     HTMLDocument3_get_onstop,
618     HTMLDocument3_createDocumentFragment,
619     HTMLDocument3_get_parentDocument,
620     HTMLDocument3_put_enableDownload,
621     HTMLDocument3_get_enableDownload,
622     HTMLDocument3_put_baseUrl,
623     HTMLDocument3_get_baseUrl,
624     HTMLDocument3_get_childNodes,
625     HTMLDocument3_put_inheritStyleSheets,
626     HTMLDocument3_get_inheritStyleSheets,
627     HTMLDocument3_put_onbeforeeditfocus,
628     HTMLDocument3_get_onbeforeeditfocus,
629     HTMLDocument3_getElementsByName,
630     HTMLDocument3_getElementById,
631     HTMLDocument3_getElementsByTagName
632 };
633
634 #define HTMLDOC4_THIS(iface) DEFINE_THIS(HTMLDocument, HTMLDocument4, iface)
635
636 static HRESULT WINAPI HTMLDocument4_QueryInterface(IHTMLDocument4 *iface,
637                                                    REFIID riid, void **ppv)
638 {
639     HTMLDocument *This = HTMLDOC4_THIS(iface);
640     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
641 }
642
643 static ULONG WINAPI HTMLDocument4_AddRef(IHTMLDocument4 *iface)
644 {
645     HTMLDocument *This = HTMLDOC4_THIS(iface);
646     return IHTMLDocument2_AddRef(HTMLDOC(This));
647 }
648
649 static ULONG WINAPI HTMLDocument4_Release(IHTMLDocument4 *iface)
650 {
651     HTMLDocument *This = HTMLDOC4_THIS(iface);
652     return IHTMLDocument2_Release(HTMLDOC(This));
653 }
654
655 static HRESULT WINAPI HTMLDocument4_GetTypeInfoCount(IHTMLDocument4 *iface, UINT *pctinfo)
656 {
657     HTMLDocument *This = HTMLDOC4_THIS(iface);
658     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(This), pctinfo);
659 }
660
661 static HRESULT WINAPI HTMLDocument4_GetTypeInfo(IHTMLDocument4 *iface, UINT iTInfo,
662                                                 LCID lcid, ITypeInfo **ppTInfo)
663 {
664     HTMLDocument *This = HTMLDOC4_THIS(iface);
665     return IDispatchEx_GetTypeInfo(DISPATCHEX(This), iTInfo, lcid, ppTInfo);
666 }
667
668 static HRESULT WINAPI HTMLDocument4_GetIDsOfNames(IHTMLDocument4 *iface, REFIID riid,
669                                                 LPOLESTR *rgszNames, UINT cNames,
670                                                 LCID lcid, DISPID *rgDispId)
671 {
672     HTMLDocument *This = HTMLDOC4_THIS(iface);
673     return IDispatchEx_GetIDsOfNames(DISPATCHEX(This), riid, rgszNames, cNames, lcid, rgDispId);
674 }
675
676 static HRESULT WINAPI HTMLDocument4_Invoke(IHTMLDocument4 *iface, DISPID dispIdMember,
677                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
678                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
679 {
680     HTMLDocument *This = HTMLDOC4_THIS(iface);
681     return IDispatchEx_Invoke(DISPATCHEX(This), dispIdMember, riid, lcid, wFlags, pDispParams,
682             pVarResult, pExcepInfo, puArgErr);
683 }
684
685 static HRESULT WINAPI HTMLDocument4_focus(IHTMLDocument4 *iface)
686 {
687     HTMLDocument *This = HTMLDOC4_THIS(iface);
688     nsIDOMNSHTMLElement *nselem;
689     nsIDOMHTMLElement *nsbody;
690     nsresult nsres;
691
692     TRACE("(%p)->()\n", This);
693
694     nsres = nsIDOMHTMLDocument_GetBody(This->doc_node->nsdoc, &nsbody);
695     if(NS_FAILED(nsres) || !nsbody) {
696         ERR("GetBody failed: %08x\n", nsres);
697         return E_FAIL;
698     }
699
700     nsres = nsIDOMHTMLElement_QueryInterface(nsbody, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
701     nsIDOMHTMLElement_Release(nsbody);
702     if(NS_FAILED(nsres)) {
703         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
704         return E_FAIL;
705     }
706
707     nsres = nsIDOMNSHTMLElement_Focus(nselem);
708     nsIDOMNSHTMLElement_Release(nselem);
709     if(NS_FAILED(nsres)) {
710         ERR("Focus failed: %08x\n", nsres);
711         return E_FAIL;
712     }
713
714     return S_OK;
715 }
716
717 static HRESULT WINAPI HTMLDocument4_hasFocus(IHTMLDocument4 *iface, VARIANT_BOOL *pfFocus)
718 {
719     HTMLDocument *This = HTMLDOC4_THIS(iface);
720     FIXME("(%p)->(%p)\n", This, pfFocus);
721     return E_NOTIMPL;
722 }
723
724 static HRESULT WINAPI HTMLDocument4_put_onselectionchange(IHTMLDocument4 *iface, VARIANT v)
725 {
726     HTMLDocument *This = HTMLDOC4_THIS(iface);
727     FIXME("(%p)->(v)\n", This);
728     return E_NOTIMPL;
729 }
730
731 static HRESULT WINAPI HTMLDocument4_get_onselectionchange(IHTMLDocument4 *iface, VARIANT *p)
732 {
733     HTMLDocument *This = HTMLDOC4_THIS(iface);
734     FIXME("(%p)->(%p)\n", This, p);
735     return E_NOTIMPL;
736 }
737
738 static HRESULT WINAPI HTMLDocument4_get_namespace(IHTMLDocument4 *iface, IDispatch **p)
739 {
740     HTMLDocument *This = HTMLDOC4_THIS(iface);
741     FIXME("(%p)->(%p)\n", This, p);
742     return E_NOTIMPL;
743 }
744
745 static HRESULT WINAPI HTMLDocument4_createDocumentFromUrl(IHTMLDocument4 *iface, BSTR bstrUrl,
746         BSTR bstrOptions, IHTMLDocument2 **newDoc)
747 {
748     HTMLDocument *This = HTMLDOC4_THIS(iface);
749     FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(bstrUrl), debugstr_w(bstrOptions), newDoc);
750     return E_NOTIMPL;
751 }
752
753 static HRESULT WINAPI HTMLDocument4_put_media(IHTMLDocument4 *iface, BSTR v)
754 {
755     HTMLDocument *This = HTMLDOC4_THIS(iface);
756     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
757     return E_NOTIMPL;
758 }
759
760 static HRESULT WINAPI HTMLDocument4_get_media(IHTMLDocument4 *iface, BSTR *p)
761 {
762     HTMLDocument *This = HTMLDOC4_THIS(iface);
763     FIXME("(%p)->(%p)\n", This, p);
764     return E_NOTIMPL;
765 }
766
767 static HRESULT WINAPI HTMLDocument4_createEventObject(IHTMLDocument4 *iface,
768         VARIANT *pvarEventObject, IHTMLEventObj **ppEventObj)
769 {
770     HTMLDocument *This = HTMLDOC4_THIS(iface);
771     FIXME("(%p)->(%p %p)\n", This, pvarEventObject, ppEventObj);
772     return E_NOTIMPL;
773 }
774
775 static HRESULT WINAPI HTMLDocument4_fireEvent(IHTMLDocument4 *iface, BSTR bstrEventName,
776         VARIANT *pvarEventObject, VARIANT_BOOL *pfCanceled)
777 {
778     HTMLDocument *This = HTMLDOC4_THIS(iface);
779     FIXME("(%p)->(%s %p %p)\n", This, debugstr_w(bstrEventName), pvarEventObject, pfCanceled);
780     return E_NOTIMPL;
781 }
782
783 static HRESULT WINAPI HTMLDocument4_createRenderStyle(IHTMLDocument4 *iface, BSTR v,
784         IHTMLRenderStyle **ppIHTMLRenderStyle)
785 {
786     HTMLDocument *This = HTMLDOC4_THIS(iface);
787     FIXME("(%p)->(%s %p)\n", This, debugstr_w(v), ppIHTMLRenderStyle);
788     return E_NOTIMPL;
789 }
790
791 static HRESULT WINAPI HTMLDocument4_put_oncontrolselect(IHTMLDocument4 *iface, VARIANT v)
792 {
793     HTMLDocument *This = HTMLDOC4_THIS(iface);
794     FIXME("(%p)->(v)\n", This);
795     return E_NOTIMPL;
796 }
797
798 static HRESULT WINAPI HTMLDocument4_get_oncontrolselect(IHTMLDocument4 *iface, VARIANT *p)
799 {
800     HTMLDocument *This = HTMLDOC4_THIS(iface);
801     FIXME("(%p)->(%p)\n", This, p);
802     return E_NOTIMPL;
803 }
804
805 static HRESULT WINAPI HTMLDocument4_get_URLEncoded(IHTMLDocument4 *iface, BSTR *p)
806 {
807     HTMLDocument *This = HTMLDOC4_THIS(iface);
808     FIXME("(%p)->(%p)\n", This, p);
809     return E_NOTIMPL;
810 }
811
812 #undef HTMLDOC4_THIS
813
814 static const IHTMLDocument4Vtbl HTMLDocument4Vtbl = {
815     HTMLDocument4_QueryInterface,
816     HTMLDocument4_AddRef,
817     HTMLDocument4_Release,
818     HTMLDocument4_GetTypeInfoCount,
819     HTMLDocument4_GetTypeInfo,
820     HTMLDocument4_GetIDsOfNames,
821     HTMLDocument4_Invoke,
822     HTMLDocument4_focus,
823     HTMLDocument4_hasFocus,
824     HTMLDocument4_put_onselectionchange,
825     HTMLDocument4_get_onselectionchange,
826     HTMLDocument4_get_namespace,
827     HTMLDocument4_createDocumentFromUrl,
828     HTMLDocument4_put_media,
829     HTMLDocument4_get_media,
830     HTMLDocument4_createEventObject,
831     HTMLDocument4_fireEvent,
832     HTMLDocument4_createRenderStyle,
833     HTMLDocument4_put_oncontrolselect,
834     HTMLDocument4_get_oncontrolselect,
835     HTMLDocument4_get_URLEncoded
836 };
837
838 void HTMLDocument_HTMLDocument3_Init(HTMLDocument *This)
839 {
840     This->lpHTMLDocument3Vtbl = &HTMLDocument3Vtbl;
841     This->lpHTMLDocument4Vtbl = &HTMLDocument4Vtbl;
842 }