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