mshtml: Implement IHTMLWindow4::get_frameElement.
[wine] / dlls / mshtml / htmlwindow.c
1 /*
2  * Copyright 2006 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 <stdarg.h>
20
21 #define COBJMACROS
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
27
28 #include "wine/debug.h"
29 #include "wine/unicode.h"
30
31 #include "mshtml_private.h"
32 #include "htmlevent.h"
33 #include "resource.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
36
37 static struct list window_list = LIST_INIT(window_list);
38
39 static void window_set_docnode(HTMLWindow *window, HTMLDocumentNode *doc_node)
40 {
41     if(window->doc) {
42         abort_document_bindings(window->doc);
43         window->doc->basedoc.window = NULL;
44         htmldoc_release(&window->doc->basedoc);
45     }
46     window->doc = doc_node;
47     if(doc_node)
48         htmldoc_addref(&doc_node->basedoc);
49
50     if(window->doc_obj && window->doc_obj->basedoc.window == window) {
51         if(window->doc_obj->basedoc.doc_node)
52             htmldoc_release(&window->doc_obj->basedoc.doc_node->basedoc);
53         window->doc_obj->basedoc.doc_node = doc_node;
54         if(doc_node)
55             htmldoc_addref(&doc_node->basedoc);
56     }
57 }
58
59 nsIDOMWindow *get_nsdoc_window(nsIDOMDocument *nsdoc)
60 {
61     nsIDOMDocumentView *nsdocview;
62     nsIDOMAbstractView *nsview;
63     nsIDOMWindow *nswindow;
64     nsresult nsres;
65
66     nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMDocumentView, (void**)&nsdocview);
67     nsIDOMDocument_Release(nsdoc);
68     if(NS_FAILED(nsres)) {
69         ERR("Could not get nsIDOMDocumentView iface: %08x\n", nsres);
70         return NULL;
71     }
72
73     nsres = nsIDOMDocumentView_GetDefaultView(nsdocview, &nsview);
74     nsIDOMDocumentView_Release(nsview);
75     if(NS_FAILED(nsres)) {
76         ERR("GetDefaultView failed: %08x\n", nsres);
77         return NULL;
78     }
79
80     nsres = nsIDOMAbstractView_QueryInterface(nsview, &IID_nsIDOMWindow, (void**)&nswindow);
81     nsIDOMAbstractView_Release(nsview);
82     if(NS_FAILED(nsres)) {
83         ERR("Coult not get nsIDOMWindow iface: %08x\n", nsres);
84         return NULL;
85     }
86
87     return nswindow;
88 }
89
90 static void release_children(HTMLWindow *This)
91 {
92     HTMLWindow *child;
93
94     while(!list_empty(&This->children)) {
95         child = LIST_ENTRY(list_tail(&This->children), HTMLWindow, sibling_entry);
96
97         list_remove(&child->sibling_entry);
98         child->parent = NULL;
99         IHTMLWindow2_Release(HTMLWINDOW2(child));
100     }
101 }
102
103 #define HTMLWINDOW2_THIS(iface) DEFINE_THIS(HTMLWindow, HTMLWindow2, iface)
104
105 static HRESULT WINAPI HTMLWindow2_QueryInterface(IHTMLWindow2 *iface, REFIID riid, void **ppv)
106 {
107     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
108
109     *ppv = NULL;
110
111     if(IsEqualGUID(&IID_IUnknown, riid)) {
112         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
113         *ppv = HTMLWINDOW2(This);
114     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
115         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
116         *ppv = HTMLWINDOW2(This);
117     }else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
118         TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
119         *ppv = DISPATCHEX(This);
120     }else if(IsEqualGUID(&IID_IHTMLFramesCollection2, riid)) {
121         TRACE("(%p)->(IID_IHTMLFramesCollection2 %p)\n", This, ppv);
122         *ppv = HTMLWINDOW2(This);
123     }else if(IsEqualGUID(&IID_IHTMLWindow2, riid)) {
124         TRACE("(%p)->(IID_IHTMLWindow2 %p)\n", This, ppv);
125         *ppv = HTMLWINDOW2(This);
126     }else if(IsEqualGUID(&IID_IHTMLWindow3, riid)) {
127         TRACE("(%p)->(IID_IHTMLWindow3 %p)\n", This, ppv);
128         *ppv = HTMLWINDOW3(This);
129     }else if(IsEqualGUID(&IID_IHTMLWindow4, riid)) {
130         TRACE("(%p)->(IID_IHTMLWindow4 %p)\n", This, ppv);
131         *ppv = HTMLWINDOW4(This);
132     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
133         return *ppv ? S_OK : E_NOINTERFACE;
134     }
135
136     if(*ppv) {
137         IUnknown_AddRef((IUnknown*)*ppv);
138         return S_OK;
139     }
140
141     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
142     return E_NOINTERFACE;
143 }
144
145 static ULONG WINAPI HTMLWindow2_AddRef(IHTMLWindow2 *iface)
146 {
147     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
148     LONG ref = InterlockedIncrement(&This->ref);
149
150     TRACE("(%p) ref=%d\n", This, ref);
151
152     return ref;
153 }
154
155 static ULONG WINAPI HTMLWindow2_Release(IHTMLWindow2 *iface)
156 {
157     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
158     LONG ref = InterlockedDecrement(&This->ref);
159
160     TRACE("(%p) ref=%d\n", This, ref);
161
162     if(!ref) {
163         DWORD i;
164
165         remove_target_tasks(This->task_magic);
166         set_window_bscallback(This, NULL);
167         set_current_mon(This, NULL);
168         window_set_docnode(This, NULL);
169         release_children(This);
170
171         if(This->option_factory) {
172             This->option_factory->window = NULL;
173             IHTMLOptionElementFactory_Release(HTMLOPTFACTORY(This->option_factory));
174         }
175
176         if(This->image_factory) {
177             This->image_factory->window = NULL;
178             IHTMLImageElementFactory_Release(HTMLIMGFACTORY(This->image_factory));
179         }
180
181         if(This->location) {
182             This->location->window = NULL;
183             IHTMLLocation_Release(HTMLLOCATION(This->location));
184         }
185
186         if(This->event_target)
187             release_event_target(This->event_target);
188         for(i=0; i < This->global_prop_cnt; i++)
189             heap_free(This->global_props[i].name);
190
191         This->window_ref->window = NULL;
192         windowref_release(This->window_ref);
193
194         heap_free(This->global_props);
195         release_script_hosts(This);
196         list_remove(&This->entry);
197         release_dispex(&This->dispex);
198         heap_free(This);
199     }
200
201     return ref;
202 }
203
204 static HRESULT WINAPI HTMLWindow2_GetTypeInfoCount(IHTMLWindow2 *iface, UINT *pctinfo)
205 {
206     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
207
208     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(This), pctinfo);
209 }
210
211 static HRESULT WINAPI HTMLWindow2_GetTypeInfo(IHTMLWindow2 *iface, UINT iTInfo,
212                                               LCID lcid, ITypeInfo **ppTInfo)
213 {
214     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
215
216     return IDispatchEx_GetTypeInfo(DISPATCHEX(This), iTInfo, lcid, ppTInfo);
217 }
218
219 static HRESULT WINAPI HTMLWindow2_GetIDsOfNames(IHTMLWindow2 *iface, REFIID riid,
220                                                 LPOLESTR *rgszNames, UINT cNames,
221                                                 LCID lcid, DISPID *rgDispId)
222 {
223     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
224
225     return IDispatchEx_GetIDsOfNames(DISPATCHEX(This), riid, rgszNames, cNames, lcid, rgDispId);
226 }
227
228 static HRESULT WINAPI HTMLWindow2_Invoke(IHTMLWindow2 *iface, DISPID dispIdMember,
229                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
230                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
231 {
232     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
233
234     return IDispatchEx_Invoke(DISPATCHEX(This), dispIdMember, riid, lcid, wFlags, pDispParams,
235             pVarResult, pExcepInfo, puArgErr);
236 }
237
238 static HRESULT WINAPI HTMLWindow2_item(IHTMLWindow2 *iface, VARIANT *pvarIndex, VARIANT *pvarResult)
239 {
240     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
241     FIXME("(%p)->(%p %p)\n", This, pvarIndex, pvarResult);
242     return E_NOTIMPL;
243 }
244
245 static HRESULT WINAPI HTMLWindow2_get_length(IHTMLWindow2 *iface, LONG *p)
246 {
247     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
248     nsIDOMWindowCollection *nscollection;
249     PRUint32 length;
250     nsresult nsres;
251
252     TRACE("(%p)->(%p)\n", This, p);
253
254     nsres = nsIDOMWindow_GetFrames(This->nswindow, &nscollection);
255     if(NS_FAILED(nsres)) {
256         ERR("GetFrames failed: %08x\n", nsres);
257         return E_FAIL;
258     }
259
260     nsres = nsIDOMWindowCollection_GetLength(nscollection, &length);
261     nsIDOMWindowCollection_Release(nscollection);
262     if(NS_FAILED(nsres)) {
263         ERR("GetLength failed: %08x\n", nsres);
264         return E_FAIL;
265     }
266
267     *p = length;
268     return S_OK;
269 }
270
271 static HRESULT WINAPI HTMLWindow2_get_frames(IHTMLWindow2 *iface, IHTMLFramesCollection2 **p)
272 {
273     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
274     FIXME("(%p)->(%p)\n", This, p);
275     return E_NOTIMPL;
276 }
277
278 static HRESULT WINAPI HTMLWindow2_put_defaultStatus(IHTMLWindow2 *iface, BSTR v)
279 {
280     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
281     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI HTMLWindow2_get_defaultStatus(IHTMLWindow2 *iface, BSTR *p)
286 {
287     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
288     FIXME("(%p)->(%p)\n", This, p);
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI HTMLWindow2_put_status(IHTMLWindow2 *iface, BSTR v)
293 {
294     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
295     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI HTMLWindow2_get_status(IHTMLWindow2 *iface, BSTR *p)
300 {
301     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
302     FIXME("(%p)->(%p)\n", This, p);
303     return E_NOTIMPL;
304 }
305
306 static HRESULT WINAPI HTMLWindow2_setTimeout(IHTMLWindow2 *iface, BSTR expression,
307         LONG msec, VARIANT *language, LONG *timerID)
308 {
309     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
310     VARIANT expr_var;
311
312     TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(expression), msec, language, timerID);
313
314     V_VT(&expr_var) = VT_BSTR;
315     V_BSTR(&expr_var) = expression;
316
317     return IHTMLWindow3_setTimeout(HTMLWINDOW3(This), &expr_var, msec, language, timerID);
318 }
319
320 static HRESULT WINAPI HTMLWindow2_clearTimeout(IHTMLWindow2 *iface, LONG timerID)
321 {
322     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
323
324     TRACE("(%p)->(%d)\n", This, timerID);
325
326     return clear_task_timer(&This->doc->basedoc, FALSE, timerID);
327 }
328
329 static HRESULT WINAPI HTMLWindow2_alert(IHTMLWindow2 *iface, BSTR message)
330 {
331     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
332     WCHAR wszTitle[100];
333
334     TRACE("(%p)->(%s)\n", This, debugstr_w(message));
335
336     if(!LoadStringW(get_shdoclc(), IDS_MESSAGE_BOX_TITLE, wszTitle,
337                     sizeof(wszTitle)/sizeof(WCHAR))) {
338         WARN("Could not load message box title: %d\n", GetLastError());
339         return S_OK;
340     }
341
342     MessageBoxW(This->doc_obj->hwnd, message, wszTitle, MB_ICONWARNING);
343     return S_OK;
344 }
345
346 static HRESULT WINAPI HTMLWindow2_confirm(IHTMLWindow2 *iface, BSTR message,
347         VARIANT_BOOL *confirmed)
348 {
349     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
350     WCHAR wszTitle[100];
351
352     TRACE("(%p)->(%s %p)\n", This, debugstr_w(message), confirmed);
353
354     if(!confirmed) return E_INVALIDARG;
355
356     if(!LoadStringW(get_shdoclc(), IDS_MESSAGE_BOX_TITLE, wszTitle,
357                 sizeof(wszTitle)/sizeof(WCHAR))) {
358         WARN("Could not load message box title: %d\n", GetLastError());
359         *confirmed = VARIANT_TRUE;
360         return S_OK;
361     }
362
363     if(MessageBoxW(This->doc_obj->hwnd, message, wszTitle,
364                 MB_OKCANCEL|MB_ICONQUESTION)==IDOK)
365         *confirmed = VARIANT_TRUE;
366     else *confirmed = VARIANT_FALSE;
367
368     return S_OK;
369 }
370
371 typedef struct
372 {
373     BSTR message;
374     BSTR dststr;
375     VARIANT *textdata;
376 }prompt_arg;
377
378 static INT_PTR CALLBACK prompt_dlgproc(HWND hwnd, UINT msg,
379         WPARAM wparam, LPARAM lparam)
380 {
381     switch(msg)
382     {
383         case WM_INITDIALOG:
384         {
385             prompt_arg *arg = (prompt_arg*)lparam;
386             WCHAR wszTitle[100];
387
388             if(!LoadStringW(get_shdoclc(), IDS_MESSAGE_BOX_TITLE, wszTitle,
389                         sizeof(wszTitle)/sizeof(WCHAR))) {
390                 WARN("Could not load message box title: %d\n", GetLastError());
391                 EndDialog(hwnd, wparam);
392                 return FALSE;
393             }
394
395             SetWindowLongPtrW(hwnd, DWLP_USER, lparam);
396             SetWindowTextW(hwnd, wszTitle);
397             SetWindowTextW(GetDlgItem(hwnd, ID_PROMPT_PROMPT), arg->message);
398             SetWindowTextW(GetDlgItem(hwnd, ID_PROMPT_EDIT), arg->dststr);
399             return FALSE;
400         }
401         case WM_COMMAND:
402             switch(wparam)
403             {
404                 case MAKEWPARAM(IDCANCEL, BN_CLICKED):
405                     EndDialog(hwnd, wparam);
406                     return TRUE;
407                 case MAKEWPARAM(IDOK, BN_CLICKED):
408                 {
409                     prompt_arg *arg =
410                         (prompt_arg*)GetWindowLongPtrW(hwnd, DWLP_USER);
411                     HWND hwndPrompt = GetDlgItem(hwnd, ID_PROMPT_EDIT);
412                     INT len = GetWindowTextLengthW(hwndPrompt);
413
414                     if(!arg->textdata)
415                     {
416                         EndDialog(hwnd, wparam);
417                         return TRUE;
418                     }
419
420                     V_VT(arg->textdata) = VT_BSTR;
421                     if(!len && !arg->dststr)
422                         V_BSTR(arg->textdata) = NULL;
423                     else
424                     {
425                         V_BSTR(arg->textdata) = SysAllocStringLen(NULL, len);
426                         GetWindowTextW(hwndPrompt, V_BSTR(arg->textdata), len+1);
427                     }
428                     EndDialog(hwnd, wparam);
429                     return TRUE;
430                 }
431             }
432             return FALSE;
433         case WM_CLOSE:
434             EndDialog(hwnd, IDCANCEL);
435             return TRUE;
436         default:
437             return FALSE;
438     }
439 }
440
441 static HRESULT WINAPI HTMLWindow2_prompt(IHTMLWindow2 *iface, BSTR message,
442         BSTR dststr, VARIANT *textdata)
443 {
444     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
445     prompt_arg arg;
446
447     TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(message), debugstr_w(dststr), textdata);
448
449     if(textdata) V_VT(textdata) = VT_NULL;
450
451     arg.message = message;
452     arg.dststr = dststr;
453     arg.textdata = textdata;
454
455     DialogBoxParamW(hInst, MAKEINTRESOURCEW(ID_PROMPT_DIALOG),
456             This->doc_obj->hwnd, prompt_dlgproc, (LPARAM)&arg);
457     return S_OK;
458 }
459
460 static HRESULT WINAPI HTMLWindow2_get_Image(IHTMLWindow2 *iface, IHTMLImageElementFactory **p)
461 {
462     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
463
464     TRACE("(%p)->(%p)\n", This, p);
465
466     if(!This->image_factory)
467         This->image_factory = HTMLImageElementFactory_Create(This);
468
469     *p = HTMLIMGFACTORY(This->image_factory);
470     IHTMLImageElementFactory_AddRef(*p);
471
472     return S_OK;
473 }
474
475 static HRESULT WINAPI HTMLWindow2_get_location(IHTMLWindow2 *iface, IHTMLLocation **p)
476 {
477     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
478
479     TRACE("(%p)->(%p)\n", This, p);
480
481     if(This->location) {
482         IHTMLLocation_AddRef(HTMLLOCATION(This->location));
483     }else {
484         HRESULT hres;
485
486         hres = HTMLLocation_Create(This, &This->location);
487         if(FAILED(hres))
488             return hres;
489     }
490
491     *p = HTMLLOCATION(This->location);
492     return S_OK;
493 }
494
495 static HRESULT WINAPI HTMLWindow2_get_history(IHTMLWindow2 *iface, IOmHistory **p)
496 {
497     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
498     FIXME("(%p)->(%p)\n", This, p);
499     return E_NOTIMPL;
500 }
501
502 static HRESULT WINAPI HTMLWindow2_close(IHTMLWindow2 *iface)
503 {
504     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
505     FIXME("(%p)->()\n", This);
506     return E_NOTIMPL;
507 }
508
509 static HRESULT WINAPI HTMLWindow2_put_opener(IHTMLWindow2 *iface, VARIANT v)
510 {
511     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
512     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
513     return E_NOTIMPL;
514 }
515
516 static HRESULT WINAPI HTMLWindow2_get_opener(IHTMLWindow2 *iface, VARIANT *p)
517 {
518     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
519     FIXME("(%p)->(%p)\n", This, p);
520     return E_NOTIMPL;
521 }
522
523 static HRESULT WINAPI HTMLWindow2_get_navigator(IHTMLWindow2 *iface, IOmNavigator **p)
524 {
525     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
526
527     TRACE("(%p)->(%p)\n", This, p);
528
529     *p = OmNavigator_Create();
530     return S_OK;
531 }
532
533 static HRESULT WINAPI HTMLWindow2_put_name(IHTMLWindow2 *iface, BSTR v)
534 {
535     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
536     nsAString name_str;
537     nsresult nsres;
538
539     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
540
541     nsAString_Init(&name_str, v);
542     nsres = nsIDOMWindow_SetName(This->nswindow, &name_str);
543     nsAString_Finish(&name_str);
544     if(NS_FAILED(nsres))
545         ERR("SetName failed: %08x\n", nsres);
546
547     return S_OK;
548 }
549
550 static HRESULT WINAPI HTMLWindow2_get_name(IHTMLWindow2 *iface, BSTR *p)
551 {
552     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
553     nsAString name_str;
554     nsresult nsres;
555     HRESULT hres;
556
557     TRACE("(%p)->(%p)\n", This, p);
558
559     nsAString_Init(&name_str, NULL);
560     nsres = nsIDOMWindow_GetName(This->nswindow, &name_str);
561     if(NS_SUCCEEDED(nsres)) {
562         const PRUnichar *name;
563
564         nsAString_GetData(&name_str, &name);
565         if(*name) {
566             *p = SysAllocString(name);
567             hres = *p ? S_OK : E_OUTOFMEMORY;
568         }else {
569             *p = NULL;
570             hres = S_OK;
571         }
572     }else {
573         ERR("GetName failed: %08x\n", nsres);
574         hres = E_FAIL;
575     }
576     nsAString_Finish(&name_str);
577
578     return hres;
579 }
580
581 static HRESULT WINAPI HTMLWindow2_get_parent(IHTMLWindow2 *iface, IHTMLWindow2 **p)
582 {
583     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
584     FIXME("(%p)->(%p)\n", This, p);
585     return E_NOTIMPL;
586 }
587
588 static HRESULT WINAPI HTMLWindow2_open(IHTMLWindow2 *iface, BSTR url, BSTR name,
589          BSTR features, VARIANT_BOOL replace, IHTMLWindow2 **pomWindowResult)
590 {
591     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
592     FIXME("(%p)->(%s %s %s %x %p)\n", This, debugstr_w(url), debugstr_w(name),
593           debugstr_w(features), replace, pomWindowResult);
594     return E_NOTIMPL;
595 }
596
597 static HRESULT WINAPI HTMLWindow2_get_self(IHTMLWindow2 *iface, IHTMLWindow2 **p)
598 {
599     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
600
601     TRACE("(%p)->(%p)\n", This, p);
602
603     /* FIXME: We should return kind of proxy window here. */
604     IHTMLWindow2_AddRef(HTMLWINDOW2(This));
605     *p = HTMLWINDOW2(This);
606     return S_OK;
607 }
608
609 static HRESULT WINAPI HTMLWindow2_get_top(IHTMLWindow2 *iface, IHTMLWindow2 **p)
610 {
611     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
612     FIXME("(%p)->(%p)\n", This, p);
613     return E_NOTIMPL;
614 }
615
616 static HRESULT WINAPI HTMLWindow2_get_window(IHTMLWindow2 *iface, IHTMLWindow2 **p)
617 {
618     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
619
620     TRACE("(%p)->(%p)\n", This, p);
621
622     /* FIXME: We should return kind of proxy window here. */
623     IHTMLWindow2_AddRef(HTMLWINDOW2(This));
624     *p = HTMLWINDOW2(This);
625     return S_OK;
626 }
627
628 static HRESULT WINAPI HTMLWindow2_navigate(IHTMLWindow2 *iface, BSTR url)
629 {
630     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
631     FIXME("(%p)->(%s)\n", This, debugstr_w(url));
632     return E_NOTIMPL;
633 }
634
635 static HRESULT WINAPI HTMLWindow2_put_onfocus(IHTMLWindow2 *iface, VARIANT v)
636 {
637     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
638     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
639     return E_NOTIMPL;
640 }
641
642 static HRESULT WINAPI HTMLWindow2_get_onfocus(IHTMLWindow2 *iface, VARIANT *p)
643 {
644     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
645     FIXME("(%p)->(%p)\n", This, p);
646     return E_NOTIMPL;
647 }
648
649 static HRESULT WINAPI HTMLWindow2_put_onblur(IHTMLWindow2 *iface, VARIANT v)
650 {
651     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
652     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
653     return E_NOTIMPL;
654 }
655
656 static HRESULT WINAPI HTMLWindow2_get_onblur(IHTMLWindow2 *iface, VARIANT *p)
657 {
658     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
659     FIXME("(%p)->(%p)\n", This, p);
660     return E_NOTIMPL;
661 }
662
663 static HRESULT WINAPI HTMLWindow2_put_onload(IHTMLWindow2 *iface, VARIANT v)
664 {
665     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
666
667     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
668
669     return set_window_event(This, EVENTID_LOAD, &v);
670 }
671
672 static HRESULT WINAPI HTMLWindow2_get_onload(IHTMLWindow2 *iface, VARIANT *p)
673 {
674     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
675
676     TRACE("(%p)->(%p)\n", This, p);
677
678     return get_window_event(This, EVENTID_LOAD, p);
679 }
680
681 static HRESULT WINAPI HTMLWindow2_put_onbeforeunload(IHTMLWindow2 *iface, VARIANT v)
682 {
683     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
684
685     TRACE("(%p)->(v(%d))\n", This, V_VT(&v));
686
687     return set_window_event(This, EVENTID_BEFOREUNLOAD, &v);
688 }
689
690 static HRESULT WINAPI HTMLWindow2_get_onbeforeunload(IHTMLWindow2 *iface, VARIANT *p)
691 {
692     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
693
694     TRACE("(%p)->(%p)\n", This, p);
695
696     return get_window_event(This, EVENTID_BEFOREUNLOAD, p);
697 }
698
699 static HRESULT WINAPI HTMLWindow2_put_onunload(IHTMLWindow2 *iface, VARIANT v)
700 {
701     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
702     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
703     return E_NOTIMPL;
704 }
705
706 static HRESULT WINAPI HTMLWindow2_get_onunload(IHTMLWindow2 *iface, VARIANT *p)
707 {
708     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
709     FIXME("(%p)->(%p)\n", This, p);
710     return E_NOTIMPL;
711 }
712
713 static HRESULT WINAPI HTMLWindow2_put_onhelp(IHTMLWindow2 *iface, VARIANT v)
714 {
715     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
716     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
717     return E_NOTIMPL;
718 }
719
720 static HRESULT WINAPI HTMLWindow2_get_onhelp(IHTMLWindow2 *iface, VARIANT *p)
721 {
722     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
723     FIXME("(%p)->(%p)\n", This, p);
724     return E_NOTIMPL;
725 }
726
727 static HRESULT WINAPI HTMLWindow2_put_onerror(IHTMLWindow2 *iface, VARIANT v)
728 {
729     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
730     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
731     return E_NOTIMPL;
732 }
733
734 static HRESULT WINAPI HTMLWindow2_get_onerror(IHTMLWindow2 *iface, VARIANT *p)
735 {
736     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
737     FIXME("(%p)->(%p)\n", This, p);
738     return E_NOTIMPL;
739 }
740
741 static HRESULT WINAPI HTMLWindow2_put_onresize(IHTMLWindow2 *iface, VARIANT v)
742 {
743     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
744     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
745     return E_NOTIMPL;
746 }
747
748 static HRESULT WINAPI HTMLWindow2_get_onresize(IHTMLWindow2 *iface, VARIANT *p)
749 {
750     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
751     FIXME("(%p)->(%p)\n", This, p);
752     return E_NOTIMPL;
753 }
754
755 static HRESULT WINAPI HTMLWindow2_put_onscroll(IHTMLWindow2 *iface, VARIANT v)
756 {
757     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
758     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
759     return E_NOTIMPL;
760 }
761
762 static HRESULT WINAPI HTMLWindow2_get_onscroll(IHTMLWindow2 *iface, VARIANT *p)
763 {
764     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
765     FIXME("(%p)->(%p)\n", This, p);
766     return E_NOTIMPL;
767 }
768
769 static HRESULT WINAPI HTMLWindow2_get_document(IHTMLWindow2 *iface, IHTMLDocument2 **p)
770 {
771     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
772
773     TRACE("(%p)->(%p)\n", This, p);
774
775     if(This->doc) {
776         /* FIXME: We should return a wrapper object here */
777         *p = HTMLDOC(&This->doc->basedoc);
778         IHTMLDocument2_AddRef(*p);
779     }else {
780         *p = NULL;
781     }
782
783     return S_OK;
784 }
785
786 static HRESULT WINAPI HTMLWindow2_get_event(IHTMLWindow2 *iface, IHTMLEventObj **p)
787 {
788     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
789
790     TRACE("(%p)->(%p)\n", This, p);
791
792     if(This->event)
793         IHTMLEventObj_AddRef(This->event);
794     *p = This->event;
795     return S_OK;
796 }
797
798 static HRESULT WINAPI HTMLWindow2_get__newEnum(IHTMLWindow2 *iface, IUnknown **p)
799 {
800     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
801     FIXME("(%p)->(%p)\n", This, p);
802     return E_NOTIMPL;
803 }
804
805 static HRESULT WINAPI HTMLWindow2_showModalDialog(IHTMLWindow2 *iface, BSTR dialog,
806         VARIANT *varArgIn, VARIANT *varOptions, VARIANT *varArgOut)
807 {
808     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
809     FIXME("(%p)->(%s %p %p %p)\n", This, debugstr_w(dialog), varArgIn, varOptions, varArgOut);
810     return E_NOTIMPL;
811 }
812
813 static HRESULT WINAPI HTMLWindow2_showHelp(IHTMLWindow2 *iface, BSTR helpURL, VARIANT helpArg,
814         BSTR features)
815 {
816     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
817     FIXME("(%p)->(%s v(%d) %s)\n", This, debugstr_w(helpURL), V_VT(&helpArg), debugstr_w(features));
818     return E_NOTIMPL;
819 }
820
821 static HRESULT WINAPI HTMLWindow2_get_screen(IHTMLWindow2 *iface, IHTMLScreen **p)
822 {
823     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
824     FIXME("(%p)->(%p)\n", This, p);
825     return E_NOTIMPL;
826 }
827
828 static HRESULT WINAPI HTMLWindow2_get_Option(IHTMLWindow2 *iface, IHTMLOptionElementFactory **p)
829 {
830     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
831
832     TRACE("(%p)->(%p)\n", This, p);
833
834     if(!This->option_factory)
835         This->option_factory = HTMLOptionElementFactory_Create(This);
836
837     *p = HTMLOPTFACTORY(This->option_factory);
838     IHTMLOptionElementFactory_AddRef(*p);
839
840     return S_OK;
841 }
842
843 static HRESULT WINAPI HTMLWindow2_focus(IHTMLWindow2 *iface)
844 {
845     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
846     FIXME("(%p)->()\n", This);
847     return E_NOTIMPL;
848 }
849
850 static HRESULT WINAPI HTMLWindow2_get_closed(IHTMLWindow2 *iface, VARIANT_BOOL *p)
851 {
852     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
853     FIXME("(%p)->(%p)\n", This, p);
854     return E_NOTIMPL;
855 }
856
857 static HRESULT WINAPI HTMLWindow2_blur(IHTMLWindow2 *iface)
858 {
859     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
860     FIXME("(%p)->()\n", This);
861     return E_NOTIMPL;
862 }
863
864 static HRESULT WINAPI HTMLWindow2_scroll(IHTMLWindow2 *iface, LONG x, LONG y)
865 {
866     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
867     FIXME("(%p)->(%d %d)\n", This, x, y);
868     return E_NOTIMPL;
869 }
870
871 static HRESULT WINAPI HTMLWindow2_get_clientInformation(IHTMLWindow2 *iface, IOmNavigator **p)
872 {
873     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
874     FIXME("(%p)->(%p)\n", This, p);
875     return E_NOTIMPL;
876 }
877
878 static HRESULT WINAPI HTMLWindow2_setInterval(IHTMLWindow2 *iface, BSTR expression,
879         LONG msec, VARIANT *language, LONG *timerID)
880 {
881     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
882     VARIANT expr;
883
884     TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(expression), msec, language, timerID);
885
886     V_VT(&expr) = VT_BSTR;
887     V_BSTR(&expr) = expression;
888     return IHTMLWindow3_setInterval(HTMLWINDOW3(This), &expr, msec, language, timerID);
889 }
890
891 static HRESULT WINAPI HTMLWindow2_clearInterval(IHTMLWindow2 *iface, LONG timerID)
892 {
893     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
894
895     TRACE("(%p)->(%d)\n", This, timerID);
896
897     return clear_task_timer(&This->doc->basedoc, TRUE, timerID);
898 }
899
900 static HRESULT WINAPI HTMLWindow2_put_offscreenBuffering(IHTMLWindow2 *iface, VARIANT v)
901 {
902     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
903     FIXME("(%p)->(v(%d))\n", This, V_VT(&v));
904     return E_NOTIMPL;
905 }
906
907 static HRESULT WINAPI HTMLWindow2_get_offscreenBuffering(IHTMLWindow2 *iface, VARIANT *p)
908 {
909     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
910     FIXME("(%p)->(%p)\n", This, p);
911     return E_NOTIMPL;
912 }
913
914 static HRESULT WINAPI HTMLWindow2_execScript(IHTMLWindow2 *iface, BSTR scode, BSTR language,
915         VARIANT *pvarRet)
916 {
917     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
918     FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(scode), debugstr_w(language), pvarRet);
919     return E_NOTIMPL;
920 }
921
922 static HRESULT WINAPI HTMLWindow2_toString(IHTMLWindow2 *iface, BSTR *String)
923 {
924     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
925
926     static const WCHAR objectW[] = {'[','o','b','j','e','c','t',']',0};
927
928     TRACE("(%p)->(%p)\n", This, String);
929
930     if(!String)
931         return E_INVALIDARG;
932
933     *String = SysAllocString(objectW);
934     return *String ? S_OK : E_OUTOFMEMORY;
935 }
936
937 static HRESULT WINAPI HTMLWindow2_scrollBy(IHTMLWindow2 *iface, LONG x, LONG y)
938 {
939     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
940     nsresult nsres;
941
942     TRACE("(%p)->(%d %d)\n", This, x, y);
943
944     nsres = nsIDOMWindow_ScrollBy(This->nswindow, x, y);
945     if(NS_FAILED(nsres))
946         ERR("ScrollBy failed: %08x\n", nsres);
947
948     return S_OK;
949 }
950
951 static HRESULT WINAPI HTMLWindow2_scrollTo(IHTMLWindow2 *iface, LONG x, LONG y)
952 {
953     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
954     nsresult nsres;
955
956     TRACE("(%p)->(%d %d)\n", This, x, y);
957
958     nsres = nsIDOMWindow_ScrollTo(This->nswindow, x, y);
959     if(NS_FAILED(nsres))
960         ERR("ScrollTo failed: %08x\n", nsres);
961
962     return S_OK;
963 }
964
965 static HRESULT WINAPI HTMLWindow2_moveTo(IHTMLWindow2 *iface, LONG x, LONG y)
966 {
967     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
968     FIXME("(%p)->(%d %d)\n", This, x, y);
969     return E_NOTIMPL;
970 }
971
972 static HRESULT WINAPI HTMLWindow2_moveBy(IHTMLWindow2 *iface, LONG x, LONG y)
973 {
974     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
975     FIXME("(%p)->(%d %d)\n", This, x, y);
976     return E_NOTIMPL;
977 }
978
979 static HRESULT WINAPI HTMLWindow2_resizeTo(IHTMLWindow2 *iface, LONG x, LONG y)
980 {
981     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
982     FIXME("(%p)->(%d %d)\n", This, x, y);
983     return E_NOTIMPL;
984 }
985
986 static HRESULT WINAPI HTMLWindow2_resizeBy(IHTMLWindow2 *iface, LONG x, LONG y)
987 {
988     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
989     FIXME("(%p)->(%d %d)\n", This, x, y);
990     return E_NOTIMPL;
991 }
992
993 static HRESULT WINAPI HTMLWindow2_get_external(IHTMLWindow2 *iface, IDispatch **p)
994 {
995     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
996
997     TRACE("(%p)->(%p)\n", This, p);
998
999     *p = NULL;
1000
1001     if(!This->doc_obj->hostui)
1002         return S_OK;
1003
1004     return IDocHostUIHandler_GetExternal(This->doc_obj->hostui, p);
1005 }
1006
1007 static HRESULT HTMLWindow_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
1008         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
1009 {
1010     HTMLWindow *This = HTMLWINDOW2_THIS(iface);
1011     global_prop_t *prop;
1012     DWORD idx;
1013     HRESULT hres;
1014
1015     idx = id - MSHTML_DISPID_CUSTOM_MIN;
1016     if(idx >= This->global_prop_cnt)
1017         return DISP_E_MEMBERNOTFOUND;
1018
1019     prop = This->global_props+idx;
1020
1021     switch(prop->type) {
1022     case GLOBAL_SCRIPTVAR: {
1023         IDispatchEx *dispex;
1024         IDispatch *disp;
1025
1026         disp = get_script_disp(prop->script_host);
1027         if(!disp)
1028             return E_UNEXPECTED;
1029
1030         hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
1031         if(SUCCEEDED(hres)) {
1032             TRACE("%s >>>\n", debugstr_w(prop->name));
1033             hres = IDispatchEx_InvokeEx(dispex, prop->id, lcid, flags, params, res, ei, caller);
1034             if(hres == S_OK)
1035                 TRACE("%s <<<\n", debugstr_w(prop->name));
1036             else
1037                 WARN("%s <<< %08x\n", debugstr_w(prop->name), hres);
1038             IDispatchEx_Release(dispex);
1039         }else {
1040             FIXME("No IDispatchEx\n");
1041         }
1042         IDispatch_Release(disp);
1043         break;
1044     }
1045     case GLOBAL_ELEMENTVAR: {
1046         IHTMLElement *elem;
1047
1048         hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), prop->name, &elem);
1049         if(FAILED(hres))
1050             return hres;
1051
1052         if(!elem)
1053             return DISP_E_MEMBERNOTFOUND;
1054
1055         V_VT(res) = VT_DISPATCH;
1056         V_DISPATCH(res) = (IDispatch*)elem;
1057         break;
1058     }
1059     default:
1060         ERR("invalid type %d\n", prop->type);
1061         hres = DISP_E_MEMBERNOTFOUND;
1062     }
1063
1064     return hres;
1065 }
1066
1067 #undef HTMLWINDOW2_THIS
1068
1069 static const IHTMLWindow2Vtbl HTMLWindow2Vtbl = {
1070     HTMLWindow2_QueryInterface,
1071     HTMLWindow2_AddRef,
1072     HTMLWindow2_Release,
1073     HTMLWindow2_GetTypeInfoCount,
1074     HTMLWindow2_GetTypeInfo,
1075     HTMLWindow2_GetIDsOfNames,
1076     HTMLWindow2_Invoke,
1077     HTMLWindow2_item,
1078     HTMLWindow2_get_length,
1079     HTMLWindow2_get_frames,
1080     HTMLWindow2_put_defaultStatus,
1081     HTMLWindow2_get_defaultStatus,
1082     HTMLWindow2_put_status,
1083     HTMLWindow2_get_status,
1084     HTMLWindow2_setTimeout,
1085     HTMLWindow2_clearTimeout,
1086     HTMLWindow2_alert,
1087     HTMLWindow2_confirm,
1088     HTMLWindow2_prompt,
1089     HTMLWindow2_get_Image,
1090     HTMLWindow2_get_location,
1091     HTMLWindow2_get_history,
1092     HTMLWindow2_close,
1093     HTMLWindow2_put_opener,
1094     HTMLWindow2_get_opener,
1095     HTMLWindow2_get_navigator,
1096     HTMLWindow2_put_name,
1097     HTMLWindow2_get_name,
1098     HTMLWindow2_get_parent,
1099     HTMLWindow2_open,
1100     HTMLWindow2_get_self,
1101     HTMLWindow2_get_top,
1102     HTMLWindow2_get_window,
1103     HTMLWindow2_navigate,
1104     HTMLWindow2_put_onfocus,
1105     HTMLWindow2_get_onfocus,
1106     HTMLWindow2_put_onblur,
1107     HTMLWindow2_get_onblur,
1108     HTMLWindow2_put_onload,
1109     HTMLWindow2_get_onload,
1110     HTMLWindow2_put_onbeforeunload,
1111     HTMLWindow2_get_onbeforeunload,
1112     HTMLWindow2_put_onunload,
1113     HTMLWindow2_get_onunload,
1114     HTMLWindow2_put_onhelp,
1115     HTMLWindow2_get_onhelp,
1116     HTMLWindow2_put_onerror,
1117     HTMLWindow2_get_onerror,
1118     HTMLWindow2_put_onresize,
1119     HTMLWindow2_get_onresize,
1120     HTMLWindow2_put_onscroll,
1121     HTMLWindow2_get_onscroll,
1122     HTMLWindow2_get_document,
1123     HTMLWindow2_get_event,
1124     HTMLWindow2_get__newEnum,
1125     HTMLWindow2_showModalDialog,
1126     HTMLWindow2_showHelp,
1127     HTMLWindow2_get_screen,
1128     HTMLWindow2_get_Option,
1129     HTMLWindow2_focus,
1130     HTMLWindow2_get_closed,
1131     HTMLWindow2_blur,
1132     HTMLWindow2_scroll,
1133     HTMLWindow2_get_clientInformation,
1134     HTMLWindow2_setInterval,
1135     HTMLWindow2_clearInterval,
1136     HTMLWindow2_put_offscreenBuffering,
1137     HTMLWindow2_get_offscreenBuffering,
1138     HTMLWindow2_execScript,
1139     HTMLWindow2_toString,
1140     HTMLWindow2_scrollBy,
1141     HTMLWindow2_scrollTo,
1142     HTMLWindow2_moveTo,
1143     HTMLWindow2_moveBy,
1144     HTMLWindow2_resizeTo,
1145     HTMLWindow2_resizeBy,
1146     HTMLWindow2_get_external
1147 };
1148
1149 #define HTMLWINDOW3_THIS(iface) DEFINE_THIS(HTMLWindow, HTMLWindow3, iface)
1150
1151 static HRESULT WINAPI HTMLWindow3_QueryInterface(IHTMLWindow3 *iface, REFIID riid, void **ppv)
1152 {
1153     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1154
1155     return IHTMLWindow2_QueryInterface(HTMLWINDOW2(This), riid, ppv);
1156 }
1157
1158 static ULONG WINAPI HTMLWindow3_AddRef(IHTMLWindow3 *iface)
1159 {
1160     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1161
1162     return IHTMLWindow2_AddRef(HTMLWINDOW2(This));
1163 }
1164
1165 static ULONG WINAPI HTMLWindow3_Release(IHTMLWindow3 *iface)
1166 {
1167     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1168
1169     return IHTMLWindow2_Release(HTMLWINDOW2(This));
1170 }
1171
1172 static HRESULT WINAPI HTMLWindow3_GetTypeInfoCount(IHTMLWindow3 *iface, UINT *pctinfo)
1173 {
1174     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1175
1176     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(This), pctinfo);
1177 }
1178
1179 static HRESULT WINAPI HTMLWindow3_GetTypeInfo(IHTMLWindow3 *iface, UINT iTInfo,
1180                                               LCID lcid, ITypeInfo **ppTInfo)
1181 {
1182     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1183
1184     return IDispatchEx_GetTypeInfo(DISPATCHEX(This), iTInfo, lcid, ppTInfo);
1185 }
1186
1187 static HRESULT WINAPI HTMLWindow3_GetIDsOfNames(IHTMLWindow3 *iface, REFIID riid,
1188                                                 LPOLESTR *rgszNames, UINT cNames,
1189                                                 LCID lcid, DISPID *rgDispId)
1190 {
1191     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1192
1193     return IDispatchEx_GetIDsOfNames(DISPATCHEX(This), riid, rgszNames, cNames, lcid, rgDispId);
1194 }
1195
1196 static HRESULT WINAPI HTMLWindow3_Invoke(IHTMLWindow3 *iface, DISPID dispIdMember,
1197                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1198                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1199 {
1200     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1201
1202     return IDispatchEx_Invoke(DISPATCHEX(This), dispIdMember, riid, lcid, wFlags, pDispParams,
1203             pVarResult, pExcepInfo, puArgErr);
1204 }
1205
1206 static HRESULT WINAPI HTMLWindow3_get_screenLeft(IHTMLWindow3 *iface, LONG *p)
1207 {
1208     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1209     FIXME("(%p)->(%p)\n", This, p);
1210     return E_NOTIMPL;
1211 }
1212
1213 static HRESULT WINAPI HTMLWindow3_get_screenTop(IHTMLWindow3 *iface, LONG *p)
1214 {
1215     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1216     FIXME("(%p)->(%p)\n", This, p);
1217     return E_NOTIMPL;
1218 }
1219
1220 static HRESULT WINAPI HTMLWindow3_attachEvent(IHTMLWindow3 *iface, BSTR event, IDispatch *pDisp, VARIANT_BOOL *pfResult)
1221 {
1222     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1223
1224     TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(event), pDisp, pfResult);
1225
1226     return attach_event(&This->event_target, &This->doc_obj->basedoc, event, pDisp, pfResult);
1227 }
1228
1229 static HRESULT WINAPI HTMLWindow3_detachEvent(IHTMLWindow3 *iface, BSTR event, IDispatch *pDisp)
1230 {
1231     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1232     FIXME("(%p)->()\n", This);
1233     return E_NOTIMPL;
1234 }
1235
1236 static HRESULT window_set_timer(HTMLWindow *This, VARIANT *expr, LONG msec, VARIANT *language,
1237         BOOL interval, LONG *timer_id)
1238 {
1239     IDispatch *disp = NULL;
1240
1241     switch(V_VT(expr)) {
1242     case VT_DISPATCH:
1243         disp = V_DISPATCH(expr);
1244         IDispatch_AddRef(disp);
1245         break;
1246
1247     case VT_BSTR:
1248         disp = script_parse_event(This, V_BSTR(expr));
1249         break;
1250
1251     default:
1252         FIXME("unimplemented vt=%d\n", V_VT(expr));
1253         return E_NOTIMPL;
1254     }
1255
1256     if(!disp)
1257         return E_FAIL;
1258
1259     *timer_id = set_task_timer(&This->doc->basedoc, msec, interval, disp);
1260     IDispatch_Release(disp);
1261
1262     return S_OK;
1263 }
1264
1265 static HRESULT WINAPI HTMLWindow3_setTimeout(IHTMLWindow3 *iface, VARIANT *expression, LONG msec,
1266         VARIANT *language, LONG *timerID)
1267 {
1268     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1269
1270     TRACE("(%p)->(%p(%d) %d %p %p)\n", This, expression, V_VT(expression), msec, language, timerID);
1271
1272     return window_set_timer(This, expression, msec, language, FALSE, timerID);
1273 }
1274
1275 static HRESULT WINAPI HTMLWindow3_setInterval(IHTMLWindow3 *iface, VARIANT *expression, LONG msec,
1276         VARIANT *language, LONG *timerID)
1277 {
1278     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1279
1280     TRACE("(%p)->(%p %d %p %p)\n", This, expression, msec, language, timerID);
1281
1282     return window_set_timer(This, expression, msec, language, TRUE, timerID);
1283 }
1284
1285 static HRESULT WINAPI HTMLWindow3_print(IHTMLWindow3 *iface)
1286 {
1287     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1288     FIXME("(%p)\n", This);
1289     return E_NOTIMPL;
1290 }
1291
1292 static HRESULT WINAPI HTMLWindow3_put_onbeforeprint(IHTMLWindow3 *iface, VARIANT v)
1293 {
1294     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1295     FIXME("(%p)->()\n", This);
1296     return E_NOTIMPL;
1297 }
1298
1299 static HRESULT WINAPI HTMLWindow3_get_onbeforeprint(IHTMLWindow3 *iface, VARIANT *p)
1300 {
1301     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1302     FIXME("(%p)->(%p)\n", This, p);
1303     return E_NOTIMPL;
1304 }
1305
1306 static HRESULT WINAPI HTMLWindow3_put_onafterprint(IHTMLWindow3 *iface, VARIANT v)
1307 {
1308     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1309     FIXME("(%p)->()\n", This);
1310     return E_NOTIMPL;
1311 }
1312
1313 static HRESULT WINAPI HTMLWindow3_get_onafterprint(IHTMLWindow3 *iface, VARIANT *p)
1314 {
1315     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1316     FIXME("(%p)->(%p)\n", This, p);
1317     return E_NOTIMPL;
1318 }
1319
1320 static HRESULT WINAPI HTMLWindow3_get_clipboardData(IHTMLWindow3 *iface, IHTMLDataTransfer **p)
1321 {
1322     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1323     FIXME("(%p)->(%p)\n", This, p);
1324     return E_NOTIMPL;
1325 }
1326
1327 static HRESULT WINAPI HTMLWindow3_showModelessDialog(IHTMLWindow3 *iface, BSTR url,
1328         VARIANT *varArgIn, VARIANT *options, IHTMLWindow2 **pDialog)
1329 {
1330     HTMLWindow *This = HTMLWINDOW3_THIS(iface);
1331     FIXME("(%p)->(%s %p %p %p)\n", This, debugstr_w(url), varArgIn, options, pDialog);
1332     return E_NOTIMPL;
1333 }
1334
1335 #undef HTMLWINDOW3_THIS
1336
1337 static const IHTMLWindow3Vtbl HTMLWindow3Vtbl = {
1338     HTMLWindow3_QueryInterface,
1339     HTMLWindow3_AddRef,
1340     HTMLWindow3_Release,
1341     HTMLWindow3_GetTypeInfoCount,
1342     HTMLWindow3_GetTypeInfo,
1343     HTMLWindow3_GetIDsOfNames,
1344     HTMLWindow3_Invoke,
1345     HTMLWindow3_get_screenLeft,
1346     HTMLWindow3_get_screenTop,
1347     HTMLWindow3_attachEvent,
1348     HTMLWindow3_detachEvent,
1349     HTMLWindow3_setTimeout,
1350     HTMLWindow3_setInterval,
1351     HTMLWindow3_print,
1352     HTMLWindow3_put_onbeforeprint,
1353     HTMLWindow3_get_onbeforeprint,
1354     HTMLWindow3_put_onafterprint,
1355     HTMLWindow3_get_onafterprint,
1356     HTMLWindow3_get_clipboardData,
1357     HTMLWindow3_showModelessDialog
1358 };
1359
1360 #define HTMLWINDOW4_THIS(iface) DEFINE_THIS(HTMLWindow, HTMLWindow4, iface)
1361
1362 static HRESULT WINAPI HTMLWindow4_QueryInterface(IHTMLWindow4 *iface, REFIID riid, void **ppv)
1363 {
1364     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1365
1366     return IHTMLWindow2_QueryInterface(HTMLWINDOW2(This), riid, ppv);
1367 }
1368
1369 static ULONG WINAPI HTMLWindow4_AddRef(IHTMLWindow4 *iface)
1370 {
1371     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1372
1373     return IHTMLWindow2_AddRef(HTMLWINDOW2(This));
1374 }
1375
1376 static ULONG WINAPI HTMLWindow4_Release(IHTMLWindow4 *iface)
1377 {
1378     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1379
1380     return IHTMLWindow2_Release(HTMLWINDOW2(This));
1381 }
1382
1383 static HRESULT WINAPI HTMLWindow4_GetTypeInfoCount(IHTMLWindow4 *iface, UINT *pctinfo)
1384 {
1385     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1386
1387     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(This), pctinfo);
1388 }
1389
1390 static HRESULT WINAPI HTMLWindow4_GetTypeInfo(IHTMLWindow4 *iface, UINT iTInfo,
1391                                               LCID lcid, ITypeInfo **ppTInfo)
1392 {
1393     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1394
1395     return IDispatchEx_GetTypeInfo(DISPATCHEX(This), iTInfo, lcid, ppTInfo);
1396 }
1397
1398 static HRESULT WINAPI HTMLWindow4_GetIDsOfNames(IHTMLWindow4 *iface, REFIID riid,
1399                                                 LPOLESTR *rgszNames, UINT cNames,
1400                                                 LCID lcid, DISPID *rgDispId)
1401 {
1402     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1403
1404     return IDispatchEx_GetIDsOfNames(DISPATCHEX(This), riid, rgszNames, cNames, lcid, rgDispId);
1405 }
1406
1407 static HRESULT WINAPI HTMLWindow4_Invoke(IHTMLWindow4 *iface, DISPID dispIdMember,
1408                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1409                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1410 {
1411     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1412
1413     return IDispatchEx_Invoke(DISPATCHEX(This), dispIdMember, riid, lcid, wFlags, pDispParams,
1414             pVarResult, pExcepInfo, puArgErr);
1415 }
1416
1417 static HRESULT WINAPI HTMLWindow4_createPopup(IHTMLWindow4 *iface, VARIANT *varArgIn,
1418                             IDispatch **ppPopup)
1419 {
1420     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1421     FIXME("(%p)->(%p %p)\n", This, varArgIn, ppPopup);
1422     return E_NOTIMPL;
1423 }
1424
1425 static HRESULT WINAPI HTMLWindow4_get_frameElement(IHTMLWindow4 *iface, IHTMLFrameBase **p)
1426 {
1427     HTMLWindow *This = HTMLWINDOW4_THIS(iface);
1428     TRACE("(%p)->(%p)\n", This, p);
1429
1430     if(This->frame_element) {
1431         *p = HTMLFRAMEBASE(This->frame_element);
1432         IHTMLFrameBase_AddRef(*p);
1433     }else
1434         *p = NULL;
1435
1436     return S_OK;
1437 }
1438
1439 #undef HTMLWINDOW4_THIS
1440
1441 static const IHTMLWindow4Vtbl HTMLWindow4Vtbl = {
1442     HTMLWindow4_QueryInterface,
1443     HTMLWindow4_AddRef,
1444     HTMLWindow4_Release,
1445     HTMLWindow4_GetTypeInfoCount,
1446     HTMLWindow4_GetTypeInfo,
1447     HTMLWindow4_GetIDsOfNames,
1448     HTMLWindow4_Invoke,
1449     HTMLWindow4_createPopup,
1450     HTMLWindow4_get_frameElement
1451 };
1452
1453 #define DISPEX_THIS(iface) DEFINE_THIS(HTMLWindow, IDispatchEx, iface)
1454
1455 static HRESULT WINAPI WindowDispEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
1456 {
1457     HTMLWindow *This = DISPEX_THIS(iface);
1458
1459     return IHTMLWindow2_QueryInterface(HTMLWINDOW2(This), riid, ppv);
1460 }
1461
1462 static ULONG WINAPI WindowDispEx_AddRef(IDispatchEx *iface)
1463 {
1464     HTMLWindow *This = DISPEX_THIS(iface);
1465
1466     return IHTMLWindow2_AddRef(HTMLWINDOW2(This));
1467 }
1468
1469 static ULONG WINAPI WindowDispEx_Release(IDispatchEx *iface)
1470 {
1471     HTMLWindow *This = DISPEX_THIS(iface);
1472
1473     return IHTMLWindow2_Release(HTMLWINDOW2(This));
1474 }
1475
1476 static HRESULT WINAPI WindowDispEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
1477 {
1478     HTMLWindow *This = DISPEX_THIS(iface);
1479
1480     TRACE("(%p)->(%p)\n", This, pctinfo);
1481
1482     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo);
1483 }
1484
1485 static HRESULT WINAPI WindowDispEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
1486                                                LCID lcid, ITypeInfo **ppTInfo)
1487 {
1488     HTMLWindow *This = DISPEX_THIS(iface);
1489
1490     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1491
1492     return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo);
1493 }
1494
1495 static HRESULT WINAPI WindowDispEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
1496                                                  LPOLESTR *rgszNames, UINT cNames,
1497                                                  LCID lcid, DISPID *rgDispId)
1498 {
1499     HTMLWindow *This = DISPEX_THIS(iface);
1500
1501     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1502           lcid, rgDispId);
1503
1504     /* FIXME: Use script dispatch */
1505
1506     return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId);
1507 }
1508
1509 static HRESULT WINAPI WindowDispEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
1510                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1511                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1512 {
1513     HTMLWindow *This = DISPEX_THIS(iface);
1514
1515     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1516           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1517
1518     /* FIXME: Use script dispatch */
1519
1520     return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid, wFlags, pDispParams,
1521                               pVarResult, pExcepInfo, puArgErr);
1522 }
1523
1524 static global_prop_t *alloc_global_prop(HTMLWindow *This, global_prop_type_t type, BSTR name)
1525 {
1526     if(This->global_prop_cnt == This->global_prop_size) {
1527         global_prop_t *new_props;
1528         DWORD new_size;
1529
1530         if(This->global_props) {
1531             new_size = This->global_prop_size*2;
1532             new_props = heap_realloc(This->global_props, new_size*sizeof(global_prop_t));
1533         }else {
1534             new_size = 16;
1535             new_props = heap_alloc(new_size*sizeof(global_prop_t));
1536         }
1537         if(!new_props)
1538             return NULL;
1539         This->global_props = new_props;
1540         This->global_prop_size = new_size;
1541     }
1542
1543     This->global_props[This->global_prop_cnt].name = heap_strdupW(name);
1544     if(!This->global_props[This->global_prop_cnt].name)
1545         return NULL;
1546
1547     This->global_props[This->global_prop_cnt].type = type;
1548     return This->global_props + This->global_prop_cnt++;
1549 }
1550
1551 static inline DWORD prop_to_dispid(HTMLWindow *This, global_prop_t *prop)
1552 {
1553     return MSHTML_DISPID_CUSTOM_MIN + (prop-This->global_props);
1554 }
1555
1556 static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
1557 {
1558     HTMLWindow *This = DISPEX_THIS(iface);
1559     ScriptHost *script_host;
1560     DISPID id;
1561     DWORD i;
1562     HRESULT hres;
1563
1564     TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
1565
1566     for(i=0; i < This->global_prop_cnt; i++) {
1567         /* FIXME: case sensitivity */
1568         if(!strcmpW(This->global_props[i].name, bstrName)) {
1569             *pid = MSHTML_DISPID_CUSTOM_MIN+i;
1570             return S_OK;
1571         }
1572     }
1573
1574     if(find_global_prop(This, bstrName, grfdex, &script_host, &id)) {
1575         global_prop_t *prop;
1576
1577         prop = alloc_global_prop(This, GLOBAL_SCRIPTVAR, bstrName);
1578         if(!prop)
1579             return E_OUTOFMEMORY;
1580
1581         prop->script_host = script_host;
1582         prop->id = id;
1583
1584         *pid = prop_to_dispid(This, prop);
1585         return S_OK;
1586     }
1587
1588     hres = IDispatchEx_GetDispID(DISPATCHEX(&This->dispex), bstrName, grfdex, pid);
1589     if(hres != DISP_E_UNKNOWNNAME)
1590         return hres;
1591
1592     if(This->doc) {
1593         global_prop_t *prop;
1594         IHTMLElement *elem;
1595
1596         hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), bstrName, &elem);
1597         if(SUCCEEDED(hres) && elem) {
1598             IHTMLElement_Release(elem);
1599
1600             prop = alloc_global_prop(This, GLOBAL_ELEMENTVAR, bstrName);
1601             if(!prop)
1602                 return E_OUTOFMEMORY;
1603
1604             *pid = prop_to_dispid(This, prop);
1605             return S_OK;
1606         }
1607     }
1608
1609     return DISP_E_UNKNOWNNAME;
1610 }
1611
1612 static HRESULT WINAPI WindowDispEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1613         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1614 {
1615     HTMLWindow *This = DISPEX_THIS(iface);
1616
1617     TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1618
1619     return IDispatchEx_InvokeEx(DISPATCHEX(&This->dispex), id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
1620 }
1621
1622 static HRESULT WINAPI WindowDispEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
1623 {
1624     HTMLWindow *This = DISPEX_THIS(iface);
1625
1626     TRACE("(%p)->(%s %x)\n", This, debugstr_w(bstrName), grfdex);
1627
1628     return IDispatchEx_DeleteMemberByName(DISPATCHEX(&This->dispex), bstrName, grfdex);
1629 }
1630
1631 static HRESULT WINAPI WindowDispEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
1632 {
1633     HTMLWindow *This = DISPEX_THIS(iface);
1634
1635     TRACE("(%p)->(%x)\n", This, id);
1636
1637     return IDispatchEx_DeleteMemberByDispID(DISPATCHEX(&This->dispex), id);
1638 }
1639
1640 static HRESULT WINAPI WindowDispEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
1641 {
1642     HTMLWindow *This = DISPEX_THIS(iface);
1643
1644     TRACE("(%p)->(%x %x %p)\n", This, id, grfdexFetch, pgrfdex);
1645
1646     return IDispatchEx_GetMemberProperties(DISPATCHEX(&This->dispex), id, grfdexFetch, pgrfdex);
1647 }
1648
1649 static HRESULT WINAPI WindowDispEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
1650 {
1651     HTMLWindow *This = DISPEX_THIS(iface);
1652
1653     TRACE("(%p)->(%x %p)\n", This, id, pbstrName);
1654
1655     return IDispatchEx_GetMemberName(DISPATCHEX(&This->dispex), id, pbstrName);
1656 }
1657
1658 static HRESULT WINAPI WindowDispEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
1659 {
1660     HTMLWindow *This = DISPEX_THIS(iface);
1661
1662     TRACE("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
1663
1664     return IDispatchEx_GetNextDispID(DISPATCHEX(&This->dispex), grfdex, id, pid);
1665 }
1666
1667 static HRESULT WINAPI WindowDispEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
1668 {
1669     HTMLWindow *This = DISPEX_THIS(iface);
1670
1671     TRACE("(%p)->(%p)\n", This, ppunk);
1672
1673     *ppunk = NULL;
1674     return S_OK;
1675 }
1676
1677 #undef DISPEX_THIS
1678
1679 static const IDispatchExVtbl WindowDispExVtbl = {
1680     WindowDispEx_QueryInterface,
1681     WindowDispEx_AddRef,
1682     WindowDispEx_Release,
1683     WindowDispEx_GetTypeInfoCount,
1684     WindowDispEx_GetTypeInfo,
1685     WindowDispEx_GetIDsOfNames,
1686     WindowDispEx_Invoke,
1687     WindowDispEx_GetDispID,
1688     WindowDispEx_InvokeEx,
1689     WindowDispEx_DeleteMemberByName,
1690     WindowDispEx_DeleteMemberByDispID,
1691     WindowDispEx_GetMemberProperties,
1692     WindowDispEx_GetMemberName,
1693     WindowDispEx_GetNextDispID,
1694     WindowDispEx_GetNameSpaceParent
1695 };
1696
1697 static const tid_t HTMLWindow_iface_tids[] = {
1698     IHTMLWindow2_tid,
1699     IHTMLWindow3_tid,
1700     IHTMLWindow4_tid,
1701     0
1702 };
1703
1704 static const dispex_static_data_vtbl_t HTMLWindow_dispex_vtbl = {
1705     NULL,
1706     NULL,
1707     HTMLWindow_invoke
1708 };
1709
1710 static dispex_static_data_t HTMLWindow_dispex = {
1711     &HTMLWindow_dispex_vtbl,
1712     DispHTMLWindow2_tid,
1713     NULL,
1714     HTMLWindow_iface_tids
1715 };
1716
1717 HRESULT HTMLWindow_Create(HTMLDocumentObj *doc_obj, nsIDOMWindow *nswindow, HTMLWindow *parent, HTMLWindow **ret)
1718 {
1719     HTMLWindow *window;
1720
1721     window = heap_alloc_zero(sizeof(HTMLWindow));
1722     if(!window)
1723         return E_OUTOFMEMORY;
1724
1725     window->window_ref = heap_alloc(sizeof(windowref_t));
1726     if(!window->window_ref) {
1727         heap_free(window);
1728         return E_OUTOFMEMORY;
1729     }
1730
1731     window->lpHTMLWindow2Vtbl = &HTMLWindow2Vtbl;
1732     window->lpHTMLWindow3Vtbl = &HTMLWindow3Vtbl;
1733     window->lpHTMLWindow4Vtbl = &HTMLWindow4Vtbl;
1734     window->lpIDispatchExVtbl = &WindowDispExVtbl;
1735     window->ref = 1;
1736     window->doc_obj = doc_obj;
1737
1738     window->window_ref->window = window;
1739     window->window_ref->ref = 1;
1740
1741     init_dispex(&window->dispex, (IUnknown*)HTMLWINDOW2(window), &HTMLWindow_dispex);
1742
1743     if(nswindow) {
1744         nsIDOMWindow_AddRef(nswindow);
1745         window->nswindow = nswindow;
1746     }
1747
1748     window->scriptmode = parent ? parent->scriptmode : SCRIPTMODE_GECKO;
1749     window->readystate = READYSTATE_UNINITIALIZED;
1750     list_init(&window->script_hosts);
1751
1752     window->task_magic = get_task_target_magic();
1753     update_window_doc(window);
1754
1755     list_init(&window->children);
1756     list_add_head(&window_list, &window->entry);
1757
1758     if(parent) {
1759         IHTMLWindow2_AddRef(HTMLWINDOW2(window));
1760
1761         window->parent = parent;
1762         list_add_tail(&parent->children, &window->sibling_entry);
1763     }
1764
1765     *ret = window;
1766     return S_OK;
1767 }
1768
1769 void update_window_doc(HTMLWindow *window)
1770 {
1771     nsIDOMHTMLDocument *nshtmldoc;
1772     nsIDOMDocument *nsdoc;
1773     nsresult nsres;
1774
1775     nsres = nsIDOMWindow_GetDocument(window->nswindow, &nsdoc);
1776     if(NS_FAILED(nsres) || !nsdoc) {
1777         ERR("GetDocument failed: %08x\n", nsres);
1778         return;
1779     }
1780
1781     nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMHTMLDocument, (void**)&nshtmldoc);
1782     nsIDOMDocument_Release(nsdoc);
1783     if(NS_FAILED(nsres)) {
1784         ERR("Could not get nsIDOMHTMLDocument iface: %08x\n", nsres);
1785         return;
1786     }
1787
1788     if(!window->doc || window->doc->nsdoc != nshtmldoc) {
1789         HTMLDocumentNode *doc;
1790         HRESULT hres;
1791
1792         hres = create_doc_from_nsdoc(nshtmldoc, window->doc_obj, window, &doc);
1793         if(SUCCEEDED(hres)) {
1794             window_set_docnode(window, doc);
1795             htmldoc_release(&doc->basedoc);
1796         }else {
1797             ERR("create_doc_from_nsdoc failed: %08x\n", hres);
1798         }
1799     }
1800
1801     nsIDOMHTMLDocument_Release(nshtmldoc);
1802 }
1803
1804 HTMLWindow *nswindow_to_window(const nsIDOMWindow *nswindow)
1805 {
1806     HTMLWindow *iter;
1807
1808     LIST_FOR_EACH_ENTRY(iter, &window_list, HTMLWindow, entry) {
1809         if(iter->nswindow == nswindow)
1810             return iter;
1811     }
1812
1813     return NULL;
1814 }