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