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