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