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