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